3 * smapiexec.c - SM_API_EXECUTE_PROGRAM
5 * Reactos Session Manager
7 * --------------------------------------------------------------------
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.
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.
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,
24 * --------------------------------------------------------------------
31 static const WCHAR szSystemDirectory
[] = L
"\\System32";
33 /**********************************************************************
34 * SmCreateUserProcess/5
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).
52 SmCreateUserProcess (LPWSTR ImagePath
,
55 PLARGE_INTEGER Timeout OPTIONAL
,
56 PRTL_USER_PROCESS_INFORMATION UserProcessInfo OPTIONAL
)
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
;
66 DPRINT("SM: %s called\n", __FUNCTION__
);
68 if (NULL
!= UserProcessInfo
)
70 pProcessInfo
= UserProcessInfo
;
73 RtlInitUnicodeString (& ImagePathString
, ImagePath
);
74 RtlInitUnicodeString (& CommandLineString
, CommandLine
);
76 SystemDirectory
.MaximumLength
= (wcslen(SharedUserData
->NtSystemRoot
) * sizeof(WCHAR
)) + sizeof(szSystemDirectory
);
77 SystemDirectory
.Buffer
= RtlAllocateHeap(RtlGetProcessHeap(),
79 SystemDirectory
.MaximumLength
);
80 if (SystemDirectory
.Buffer
== NULL
)
82 Status
= STATUS_NO_MEMORY
;
83 DPRINT1("SM: %s: Allocating system directory string failed (Status=0x%08lx)\n",
84 __FUNCTION__
, Status
);
88 Status
= RtlAppendUnicodeToString(& SystemDirectory
,
89 SharedUserData
->NtSystemRoot
);
90 if (!NT_SUCCESS(Status
))
95 Status
= RtlAppendUnicodeToString(& SystemDirectory
,
97 if (!NT_SUCCESS(Status
))
103 Status
= RtlCreateProcessParameters(& ProcessParameters
,
114 RtlFreeHeap(RtlGetProcessHeap(),
116 SystemDirectory
.Buffer
);
118 if (!NT_SUCCESS(Status
))
121 DPRINT1("SM: %s: Creating process parameters failed (Status=0x%08lx)\n",
122 __FUNCTION__
, Status
);
126 Status
= RtlCreateUserProcess (& ImagePathString
,
127 OBJ_CASE_INSENSITIVE
,
137 RtlDestroyProcessParameters (ProcessParameters
);
139 if (!NT_SUCCESS(Status
))
141 DPRINT1("SM: %s: Running \"%S\" failed (Status=0x%08lx)\n",
142 __FUNCTION__
, ImagePathString
.Buffer
, Status
);
146 * It the caller is *not* interested in the child info,
147 * resume it immediately.
149 if (NULL
== UserProcessInfo
)
151 Status
= NtResumeThread (ProcessInfo
.ThreadHandle
, NULL
);
152 if(!NT_SUCCESS(Status
))
154 DPRINT1("SM: %s: NtResumeThread failed (Status=0x%08lx)\n",
155 __FUNCTION__
, Status
);
159 /* Wait for process termination */
162 Status
= NtWaitForSingleObject (pProcessInfo
->ProcessHandle
,
165 if (!NT_SUCCESS(Status
))
167 DPRINT1("SM: %s: NtWaitForSingleObject failed with Status=0x%08lx\n",
168 __FUNCTION__
, Status
);
172 if (NULL
== UserProcessInfo
)
174 NtClose(pProcessInfo
->ProcessHandle
);
175 NtClose(pProcessInfo
->ThreadHandle
);
181 /**********************************************************************
186 PSM_PORT_MESSAGE_EXECPGM ExecPgm
= NULL
;
187 WCHAR Name
[SM_EXEXPGM_MAX_LENGTH
+ 1];
188 NTSTATUS Status
= STATUS_SUCCESS
;
190 DPRINT("SM: %s called\n",__FUNCTION__
);
194 DPRINT1("SM: %s: Request == NULL!\n", __FUNCTION__
);
195 return STATUS_INVALID_PARAMETER
;
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 */)
206 WCHAR Data
[MAX_PATH
+ 1] = {0};
207 ULONG DataLength
= sizeof Data
;
208 ULONG DataType
= REG_EXPAND_SZ
;
211 RtlZeroMemory (Name
, sizeof 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
,
221 SmSystemEnvironment
/* expand */);
222 if(NT_SUCCESS(Status
))
224 /* Is the subsystem definition non-empty? */
225 if (DataLength
> sizeof Data
[0])
227 WCHAR ImagePath
[MAX_PATH
+ 1] = {0};
228 PWCHAR CommandLine
= ImagePath
;
229 RTL_USER_PROCESS_INFORMATION ProcessInfo
= {0};
231 wcscpy (ImagePath
, L
"\\??\\");
232 wcscat (ImagePath
, Data
);
234 * Look for the beginning of the command line.
236 for (; (*CommandLine
!= L
'\0') && (*CommandLine
!= L
' ');
238 for (; *CommandLine
== L
' '; CommandLine
++)
240 *CommandLine
= L
'\0';
243 * Create a native process (suspended).
245 ProcessInfo
.Size
= sizeof ProcessInfo
;
246 Request
->SmHeader
.Status
=
247 SmCreateUserProcess(ImagePath
,
252 if (NT_SUCCESS(Request
->SmHeader
.Status
))
254 Status
= SmCreateClient (& ProcessInfo
, Name
);
255 if (NT_SUCCESS(Status
))
257 Status
= NtResumeThread (ProcessInfo
.ThreadHandle
, NULL
);
258 if (!NT_SUCCESS(Status
))
260 DPRINT1("SM: %s: NtResumeThread failed (Status=0x%08lx)\n",
261 __FUNCTION__
, Status
);
262 //Status = SmDestroyClient TODO
265 DPRINT1("SM: %s: SmCreateClient failed (Status=0x%08lx)\n",
266 __FUNCTION__
, Status
);
273 * OK, the definition is empty, but check
274 * if it is the name of an embedded subsystem.
276 if(0 == _wcsicmp(L
"DEBUG", Name
))
279 * Initialize the embedded DBGSS.
281 Request
->SmHeader
.Status
= SmInitializeDbgSs();
286 * Badly defined subsystem. Check the registry!
288 Request
->SmHeader
.Status
= STATUS_NOT_FOUND
;
292 /* It couldn't lookup the Name! */
293 Request
->SmHeader
.Status
= Status
;