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