xref: /reactos/sdk/lib/smlib/smclient.c (revision 40462c92)
1 /*
2  * PROJECT:         ReactOS Windows-Compatible Session Manager
3  * LICENSE:         BSD 2-Clause License
4  * FILE:            lib/smlib/smclient.c
5  * PURPOSE:         SMSS Client Library Stubs for calling SM APIs from a client
6  * PROGRAMMERS:     Alex Ionescu
7  */
8 
9 /* INCLUDES *******************************************************************/
10 
11 #include "precomp.h"
12 #include <sm/smmsg.h> // To go in precomp.h after
13 
14 #define NDEBUG
15 #include <debug.h>
16 
17 /* FUNCTIONS ******************************************************************/
18 
19 NTSTATUS
20 NTAPI
21 SmExecPgm(IN HANDLE SmApiPort,
22           IN PRTL_USER_PROCESS_INFORMATION ProcessInformation,
23           IN BOOLEAN DebugFlag)
24 {
25     NTSTATUS Status;
26     SM_API_MSG SmApiMsg;
27 
28 #if 0 //def _WIN64 // You can take care of this Timo
29     /* 64-bit SMSS needs to talk to 32-bit processes so do the LPC conversion */
30     if (SmpIsWow64Process())
31     {
32         return SmpWow64ExecPgm(SmApiPort, ProcessInformation, DebugFlag);
33     }
34 #endif
35 
36     /* Initialize the generic LPC header */
37     SmApiMsg.h.u2.ZeroInit = 0;
38     SmApiMsg.h.u1.s1.DataLength = sizeof(SM_EXEC_PGM_MSG) + 8;
39     SmApiMsg.h.u1.s1.TotalLength = sizeof(SmApiMsg);
40 
41     /* Initialize this specific API's parameters */
42     SmApiMsg.ApiNumber = SmpExecPgmApi;
43     RtlCopyMemory(&SmApiMsg.u.ExecPgm.ProcessInformation,
44                   ProcessInformation,
45                   sizeof(SmApiMsg.u.ExecPgm.ProcessInformation));
46     SmApiMsg.u.ExecPgm.DebugFlag = DebugFlag;
47 
48     /* Send the message to SMSS */
49     Status = NtRequestWaitReplyPort(SmApiPort, &SmApiMsg.h, &SmApiMsg.h);
50     if (!NT_SUCCESS(Status))
51     {
52         DPRINT1("SmExecPgm: NtRequestWaitReply Failed %lx\n", Status);
53     }
54     else
55     {
56         /* Upon success, we use the API's return value */
57         Status = SmApiMsg.ReturnValue;
58     }
59 
60     /* Close the handles that the parent passed in and return status */
61     NtClose(ProcessInformation->ProcessHandle);
62     NtClose(ProcessInformation->ThreadHandle);
63     return Status;
64 }
65 
66 NTSTATUS
67 NTAPI
68 SmConnectToSm(IN PUNICODE_STRING SbApiPortName,
69               IN HANDLE SbApiPort,
70               IN ULONG ImageType,
71               OUT PHANDLE SmApiPort)
72 {
73     NTSTATUS Status;
74     SB_CONNECTION_INFO ConnectInfo;
75     UNICODE_STRING PortName;
76     SECURITY_QUALITY_OF_SERVICE SecurityQos;
77     ULONG ConnectInfoLength = sizeof(ConnectInfo);
78 
79     /* Setup the QoS structure */
80     SecurityQos.ImpersonationLevel = SecurityIdentification;
81     SecurityQos.ContextTrackingMode = SECURITY_DYNAMIC_TRACKING;
82     SecurityQos.EffectiveOnly = TRUE;
83 
84     /* Set the SM API port name */
85     RtlInitUnicodeString(&PortName, L"\\SmApiPort");
86 
87     /* Check if this is a client connecting to SMSS, or SMSS to itself */
88     if (SbApiPortName)
89     {
90         /* A client SB port as well as an image type must be present */
91         if (!(SbApiPort) || !(ImageType)) return STATUS_INVALID_PARAMETER_MIX;
92 
93         /* Copy the client port name, and NULL-terminate it */
94         RtlCopyMemory(ConnectInfo.SbApiPortName,
95                       SbApiPortName->Buffer,
96                       SbApiPortName->Length);
97         ConnectInfo.SbApiPortName[SbApiPortName->Length /
98                                   sizeof(WCHAR)] = UNICODE_NULL;
99 
100         /* Save the subsystem type */
101         ConnectInfo.SubsystemType = ImageType;
102     }
103     else
104     {
105         /* No client port, and the subsystem type is not set */
106         ConnectInfo.SbApiPortName[0] = UNICODE_NULL;
107         ConnectInfo.SubsystemType = IMAGE_SUBSYSTEM_UNKNOWN;
108     }
109 
110     /* Connect to SMSS and exchange connection information */
111     Status = NtConnectPort(SmApiPort,
112                            &PortName,
113                            &SecurityQos,
114                            NULL,
115                            NULL,
116                            NULL,
117                            &ConnectInfo,
118                            &ConnectInfoLength);
119     if (!NT_SUCCESS(Status))
120     {
121         DPRINT1("SmConnectToSm: Connect to Sm failed %lx\n", Status);
122     }
123     else
124     {
125         /* Treat a warning or informational status as success */
126         Status = STATUS_SUCCESS;
127     }
128 
129     /* Return if the connection was successful or not */
130     return Status;
131 }
132 
133 NTSTATUS
134 NTAPI
135 SmSessionComplete(IN HANDLE SmApiPort,
136                   IN ULONG SessionId,
137                   IN NTSTATUS SessionStatus)
138 {
139     NTSTATUS Status;
140     SM_API_MSG ApiMessage;
141     PSM_SESSION_COMPLETE_MSG SessionComplete = &ApiMessage.u.SessionComplete;
142 
143     /* Set the message data */
144     SessionComplete->SessionId = SessionId;
145     SessionComplete->SessionStatus = SessionStatus;
146 
147     /* Set the API Message Port Message header */
148     ApiMessage.ApiNumber = SmpSessionCompleteApi;
149     ApiMessage.h.u1.s1.DataLength = sizeof(SM_SESSION_COMPLETE_MSG) + 8;
150     ApiMessage.h.u1.s1.TotalLength = sizeof(SM_API_MSG);
151     ApiMessage.h.u2.ZeroInit = 0;
152 
153     /* Sent the message and wait for a reply */
154     Status = NtRequestWaitReplyPort(SmApiPort,
155                                     &ApiMessage.h,
156                                     &ApiMessage.h);
157     if (NT_SUCCESS(Status))
158     {
159         /* Return the real status */
160         Status = ApiMessage.ReturnValue;
161     }
162     else
163     {
164         DPRINT1("SmCompleteSession: NtRequestWaitReply failed\n");
165     }
166 
167     /* Return status */
168     return Status;
169 }
170