Delete all Trailing spaces in code.
[reactos.git] / reactos / base / system / smss / smapiexec.c
1 /* $Id$
2 *
3 * smapiexec.c - SM_API_EXECUTE_PROGRAM
4 *
5 * Reactos Session Manager
6 *
7 * --------------------------------------------------------------------
8 *
9 * This software is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU General Public License as
11 * published by the Free Software Foundation; either version 2 of the
12 * License, or (at your option) any later version.
13 *
14 * This software is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 * General Public License for more details.
18 *
19 * You should have received a copy of the GNU General Public License
20 * along with this software; see the file COPYING.LIB. If not, write
21 * to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge,
22 * MA 02139, USA.
23 *
24 * --------------------------------------------------------------------
25 */
26 #include "smss.h"
27
28 #define NDEBUG
29 #include <debug.h>
30
31 static const WCHAR szSystemDirectory[] = L"\\System32";
32
33 /**********************************************************************
34 * SmCreateUserProcess/5
35 *
36 * DESCRIPTION
37 *
38 * ARGUMENTS
39 * ImagePath: absolute path of the image to run;
40 * CommandLine: arguments and options for ImagePath;
41 * WaitForIt: TRUE for boot time processes and FALSE for
42 * subsystems bootstrapping;
43 * Timeout: optional: used if WaitForIt==TRUE;
44 * ProcessHandle: optional: a duplicated handle for
45 the child process (storage provided by the caller).
46 *
47 * RETURN VALUE
48 * NTSTATUS:
49 *
50 */
51 NTSTATUS STDCALL
52 SmCreateUserProcess (LPWSTR ImagePath,
53 LPWSTR CommandLine,
54 BOOLEAN WaitForIt,
55 PLARGE_INTEGER Timeout OPTIONAL,
56 PRTL_USER_PROCESS_INFORMATION UserProcessInfo OPTIONAL)
57 {
58 UNICODE_STRING ImagePathString = {0};
59 UNICODE_STRING CommandLineString = {0};
60 UNICODE_STRING SystemDirectory = {0};
61 PRTL_USER_PROCESS_PARAMETERS ProcessParameters = NULL;
62 RTL_USER_PROCESS_INFORMATION ProcessInfo = {0};
63 PRTL_USER_PROCESS_INFORMATION pProcessInfo = & ProcessInfo;
64 NTSTATUS Status = STATUS_SUCCESS;
65
66 DPRINT("SM: %s called\n", __FUNCTION__);
67
68 if (NULL != UserProcessInfo)
69 {
70 pProcessInfo = UserProcessInfo;
71 }
72
73 RtlInitUnicodeString (& ImagePathString, ImagePath);
74 RtlInitUnicodeString (& CommandLineString, CommandLine);
75
76 SystemDirectory.MaximumLength = (wcslen(SharedUserData->NtSystemRoot) * sizeof(WCHAR)) + sizeof(szSystemDirectory);
77 SystemDirectory.Buffer = RtlAllocateHeap(RtlGetProcessHeap(),
78 0,
79 SystemDirectory.MaximumLength);
80 if (SystemDirectory.Buffer == NULL)
81 {
82 Status = STATUS_NO_MEMORY;
83 DPRINT1("SM: %s: Allocating system directory string failed (Status=0x%08lx)\n",
84 __FUNCTION__, Status);
85 return Status;
86 }
87
88 Status = RtlAppendUnicodeToString(& SystemDirectory,
89 SharedUserData->NtSystemRoot);
90 if (!NT_SUCCESS(Status))
91 {
92 goto FailProcParams;
93 }
94
95 Status = RtlAppendUnicodeToString(& SystemDirectory,
96 szSystemDirectory);
97 if (!NT_SUCCESS(Status))
98 {
99 goto FailProcParams;
100 }
101
102
103 Status = RtlCreateProcessParameters(& ProcessParameters,
104 & ImagePathString,
105 NULL,
106 & SystemDirectory,
107 & CommandLineString,
108 SmSystemEnvironment,
109 NULL,
110 NULL,
111 NULL,
112 NULL);
113
114 RtlFreeHeap(RtlGetProcessHeap(),
115 0,
116 SystemDirectory.Buffer);
117
118 if (!NT_SUCCESS(Status))
119 {
120 FailProcParams:
121 DPRINT1("SM: %s: Creating process parameters failed (Status=0x%08lx)\n",
122 __FUNCTION__, Status);
123 return Status;
124 }
125
126 Status = RtlCreateUserProcess (& ImagePathString,
127 OBJ_CASE_INSENSITIVE,
128 ProcessParameters,
129 NULL,
130 NULL,
131 NULL,
132 FALSE,
133 NULL,
134 NULL,
135 pProcessInfo);
136
137 RtlDestroyProcessParameters (ProcessParameters);
138
139 if (!NT_SUCCESS(Status))
140 {
141 DPRINT1("SM: %s: Running \"%S\" failed (Status=0x%08lx)\n",
142 __FUNCTION__, ImagePathString.Buffer, Status);
143 return Status;
144 }
145 /*
146 * It the caller is *not* interested in the child info,
147 * resume it immediately.
148 */
149 if (NULL == UserProcessInfo)
150 {
151 Status = NtResumeThread (ProcessInfo.ThreadHandle, NULL);
152 if(!NT_SUCCESS(Status))
153 {
154 DPRINT1("SM: %s: NtResumeThread failed (Status=0x%08lx)\n",
155 __FUNCTION__, Status);
156 }
157 }
158
159 /* Wait for process termination */
160 if (WaitForIt)
161 {
162 Status = NtWaitForSingleObject (pProcessInfo->ProcessHandle,
163 FALSE,
164 Timeout);
165 if (!NT_SUCCESS(Status))
166 {
167 DPRINT1("SM: %s: NtWaitForSingleObject failed with Status=0x%08lx\n",
168 __FUNCTION__, Status);
169 }
170
171 }
172 if (NULL == UserProcessInfo)
173 {
174 NtClose(pProcessInfo->ProcessHandle);
175 NtClose(pProcessInfo->ThreadHandle);
176 }
177 return Status;
178 }
179
180
181 /**********************************************************************
182 * SmExecPgm/1 API
183 */
184 SMAPI(SmExecPgm)
185 {
186 PSM_PORT_MESSAGE_EXECPGM ExecPgm = NULL;
187 WCHAR Name [SM_EXEXPGM_MAX_LENGTH + 1];
188 NTSTATUS Status = STATUS_SUCCESS;
189
190 DPRINT("SM: %s called\n",__FUNCTION__);
191
192 if(NULL == Request)
193 {
194 DPRINT1("SM: %s: Request == NULL!\n", __FUNCTION__);
195 return STATUS_INVALID_PARAMETER;
196 }
197 DPRINT("SM: %s called from CID(%lx|%lx)\n",
198 __FUNCTION__, Request->Header.ClientId.UniqueProcess,
199 Request->Header.ClientId.UniqueThread);
200 ExecPgm = & Request->Request.ExecPgm;
201 /* Check if the name lenght is valid */
202 if((ExecPgm->NameLength > 0) &&
203 (ExecPgm->NameLength <= SM_EXEXPGM_MAX_LENGTH) &&
204 TRUE /* TODO: check LPC payload size */)
205 {
206 WCHAR Data [MAX_PATH + 1] = {0};
207 ULONG DataLength = sizeof Data;
208 ULONG DataType = REG_EXPAND_SZ;
209
210
211 RtlZeroMemory (Name, sizeof Name);
212 RtlCopyMemory (Name,
213 ExecPgm->Name,
214 (sizeof ExecPgm->Name[0] * ExecPgm->NameLength));
215 DPRINT("SM: %s: Name='%S'\n", __FUNCTION__, Name);
216 /* Lookup Name in the registry */
217 Status = SmLookupSubsystem (Name,
218 Data,
219 & DataLength,
220 & DataType,
221 SmSystemEnvironment /* expand */);
222 if(NT_SUCCESS(Status))
223 {
224 /* Is the subsystem definition non-empty? */
225 if (DataLength > sizeof Data[0])
226 {
227 WCHAR ImagePath [MAX_PATH + 1] = {0};
228 PWCHAR CommandLine = ImagePath;
229 RTL_USER_PROCESS_INFORMATION ProcessInfo = {0};
230
231 wcscpy (ImagePath, L"\\??\\");
232 wcscat (ImagePath, Data);
233 /*
234 * Look for the beginning of the command line.
235 */
236 for (; (*CommandLine != L'\0') && (*CommandLine != L' ');
237 CommandLine ++);
238 for (; *CommandLine == L' '; CommandLine ++)
239 {
240 *CommandLine = L'\0';
241 }
242 /*
243 * Create a native process (suspended).
244 */
245 ProcessInfo.Size = sizeof ProcessInfo;
246 Request->SmHeader.Status =
247 SmCreateUserProcess(ImagePath,
248 CommandLine,
249 FALSE, /* wait */
250 NULL, /* timeout */
251 & ProcessInfo);
252 if (NT_SUCCESS(Request->SmHeader.Status))
253 {
254 Status = SmCreateClient (& ProcessInfo, Name);
255 if (NT_SUCCESS(Status))
256 {
257 Status = NtResumeThread (ProcessInfo.ThreadHandle, NULL);
258 if (!NT_SUCCESS(Status))
259 {
260 DPRINT1("SM: %s: NtResumeThread failed (Status=0x%08lx)\n",
261 __FUNCTION__, Status);
262 //Status = SmDestroyClient TODO
263 }
264 } else {
265 DPRINT1("SM: %s: SmCreateClient failed (Status=0x%08lx)\n",
266 __FUNCTION__, Status);
267 }
268 }
269 }
270 else
271 {
272 /*
273 * OK, the definition is empty, but check
274 * if it is the name of an embedded subsystem.
275 */
276 if(0 == _wcsicmp(L"DEBUG", Name))
277 {
278 /*
279 * Initialize the embedded DBGSS.
280 */
281 Request->SmHeader.Status = SmInitializeDbgSs();
282 }
283 else
284 {
285 /*
286 * Badly defined subsystem. Check the registry!
287 */
288 Request->SmHeader.Status = STATUS_NOT_FOUND;
289 }
290 }
291 } else {
292 /* It couldn't lookup the Name! */
293 Request->SmHeader.Status = Status;
294 }
295 }
296 return Status;
297 }
298
299 /* EOF */