2 * PROJECT: ReactOS Session Manager
3 * LICENSE: GPL v2 or later - See COPYING in the top level directory
4 * FILE: base/system/smss/smapiexec.c
5 * PURPOSE: SM_API_EXECUTE_PROGRAM.
6 * PROGRAMMERS: ReactOS Development Team
9 /* INCLUDES ******************************************************************/
15 static const WCHAR szSystemDirectory
[] = L
"\\System32";
17 /**********************************************************************
18 * SmCreateUserProcess/5
23 * ImagePath: absolute path of the image to run;
24 * CommandLine: arguments and options for ImagePath;
25 * Flags: Wait flag: Set for boot time processes and unset for
26 * subsystems bootstrapping;
27 * 1Mb reserve flag: Set for subsystems, unset for everything
29 * Timeout: optional: used if WaitForIt==TRUE;
30 * ProcessHandle: optional: a duplicated handle for
31 the child process (storage provided by the caller).
38 SmCreateUserProcess (LPWSTR ImagePath
,
41 PLARGE_INTEGER Timeout OPTIONAL
,
42 PRTL_USER_PROCESS_INFORMATION UserProcessInfo OPTIONAL
)
44 UNICODE_STRING ImagePathString
= { 0, 0, NULL
};
45 UNICODE_STRING CommandLineString
= { 0, 0, NULL
};
46 UNICODE_STRING SystemDirectory
= { 0, 0, NULL
};
47 PRTL_USER_PROCESS_PARAMETERS ProcessParameters
= NULL
;
48 RTL_USER_PROCESS_INFORMATION ProcessInfo
= {0};
49 PRTL_USER_PROCESS_INFORMATION pProcessInfo
= & ProcessInfo
;
50 NTSTATUS Status
= STATUS_SUCCESS
;
52 DPRINT("SM: %s called\n", __FUNCTION__
);
54 if (NULL
!= UserProcessInfo
)
56 pProcessInfo
= UserProcessInfo
;
59 RtlInitUnicodeString (& ImagePathString
, ImagePath
);
60 RtlInitUnicodeString (& CommandLineString
, CommandLine
);
62 SystemDirectory
.MaximumLength
= (wcslen(SharedUserData
->NtSystemRoot
) * sizeof(WCHAR
)) + sizeof(szSystemDirectory
);
63 SystemDirectory
.Buffer
= RtlAllocateHeap(RtlGetProcessHeap(),
65 SystemDirectory
.MaximumLength
);
66 if (SystemDirectory
.Buffer
== NULL
)
68 Status
= STATUS_NO_MEMORY
;
69 DPRINT1("SM: %s: Allocating system directory string failed (Status=0x%08lx)\n",
70 __FUNCTION__
, Status
);
74 Status
= RtlAppendUnicodeToString(& SystemDirectory
,
75 SharedUserData
->NtSystemRoot
);
76 if (!NT_SUCCESS(Status
))
81 Status
= RtlAppendUnicodeToString(& SystemDirectory
,
83 if (!NT_SUCCESS(Status
))
89 Status
= RtlCreateProcessParameters(& ProcessParameters
,
100 RtlFreeHeap(RtlGetProcessHeap(),
102 SystemDirectory
.Buffer
);
104 if (!NT_SUCCESS(Status
))
107 DPRINT1("SM: %s: Creating process parameters failed (Status=0x%08lx)\n",
108 __FUNCTION__
, Status
);
112 /* Reserve lower 1Mb, if requested */
113 if (Flags
& SM_CREATE_FLAG_RESERVE_1MB
)
114 ProcessParameters
->Flags
|= RTL_USER_PROCESS_PARAMETERS_RESERVE_1MB
;
116 /* Create the user process */
117 Status
= RtlCreateUserProcess (& ImagePathString
,
118 OBJ_CASE_INSENSITIVE
,
128 RtlDestroyProcessParameters (ProcessParameters
);
130 if (!NT_SUCCESS(Status
))
132 DPRINT1("SM: %s: Running \"%S\" failed (Status=0x%08lx)\n",
133 __FUNCTION__
, ImagePathString
.Buffer
, Status
);
137 * It the caller is *not* interested in the child info,
138 * resume it immediately.
140 if (NULL
== UserProcessInfo
)
142 Status
= NtResumeThread (ProcessInfo
.ThreadHandle
, NULL
);
143 if(!NT_SUCCESS(Status
))
145 DPRINT1("SM: %s: NtResumeThread failed (Status=0x%08lx)\n",
146 __FUNCTION__
, Status
);
150 /* Wait for process termination */
151 if (Flags
& SM_CREATE_FLAG_WAIT
)
153 Status
= NtWaitForSingleObject (pProcessInfo
->ProcessHandle
,
156 if (!NT_SUCCESS(Status
))
158 DPRINT1("SM: %s: NtWaitForSingleObject failed with Status=0x%08lx\n",
159 __FUNCTION__
, Status
);
163 if (NULL
== UserProcessInfo
)
165 NtClose(pProcessInfo
->ProcessHandle
);
166 NtClose(pProcessInfo
->ThreadHandle
);
172 /**********************************************************************
177 PSM_PORT_MESSAGE_EXECPGM ExecPgm
= NULL
;
178 WCHAR Name
[SM_EXEXPGM_MAX_LENGTH
+ 1];
179 NTSTATUS Status
= STATUS_SUCCESS
;
181 DPRINT("SM: %s called\n",__FUNCTION__
);
185 DPRINT1("SM: %s: Request == NULL!\n", __FUNCTION__
);
186 return STATUS_INVALID_PARAMETER
;
188 DPRINT("SM: %s called from CID(%p|%p)\n",
189 __FUNCTION__
, Request
->Header
.ClientId
.UniqueProcess
,
190 Request
->Header
.ClientId
.UniqueThread
);
191 ExecPgm
= & Request
->Request
.ExecPgm
;
192 /* Check if the name lenght is valid */
193 if((ExecPgm
->NameLength
> 0) &&
194 (ExecPgm
->NameLength
<= SM_EXEXPGM_MAX_LENGTH
) &&
195 TRUE
/* TODO: check LPC payload size */)
197 WCHAR Data
[MAX_PATH
+ 1] = {0};
198 ULONG DataLength
= sizeof Data
;
199 ULONG DataType
= REG_EXPAND_SZ
;
202 RtlZeroMemory (Name
, sizeof Name
);
205 (sizeof ExecPgm
->Name
[0] * ExecPgm
->NameLength
));
206 DPRINT("SM: %s: Name='%S'\n", __FUNCTION__
, Name
);
207 /* Lookup Name in the registry */
208 Status
= SmLookupSubsystem (Name
,
212 SmSystemEnvironment
/* expand */);
213 if(NT_SUCCESS(Status
))
215 /* Is the subsystem definition non-empty? */
216 if (DataLength
> sizeof Data
[0])
218 WCHAR ImagePath
[MAX_PATH
+ 1] = {0};
219 PWCHAR CommandLine
= ImagePath
;
220 RTL_USER_PROCESS_INFORMATION ProcessInfo
= {0};
222 wcscpy (ImagePath
, L
"\\??\\");
223 wcscat (ImagePath
, Data
);
225 * Look for the beginning of the command line.
227 for (; (*CommandLine
!= L
'\0') && (*CommandLine
!= L
' ');
229 for (; *CommandLine
== L
' '; CommandLine
++)
231 *CommandLine
= L
'\0';
234 * Create a native process (suspended).
236 ProcessInfo
.Size
= sizeof ProcessInfo
;
237 Request
->SmHeader
.Status
=
238 SmCreateUserProcess(ImagePath
,
240 SM_CREATE_FLAG_RESERVE_1MB
,
243 if (NT_SUCCESS(Request
->SmHeader
.Status
))
245 Status
= SmCreateClient (& ProcessInfo
, Name
);
246 if (NT_SUCCESS(Status
))
248 Status
= NtResumeThread (ProcessInfo
.ThreadHandle
, NULL
);
249 if (!NT_SUCCESS(Status
))
251 DPRINT1("SM: %s: NtResumeThread failed (Status=0x%08lx)\n",
252 __FUNCTION__
, Status
);
253 //Status = SmDestroyClient TODO
256 DPRINT1("SM: %s: SmCreateClient failed (Status=0x%08lx)\n",
257 __FUNCTION__
, Status
);
259 NtClose(ProcessInfo
.ThreadHandle
);
260 NtClose(ProcessInfo
.ProcessHandle
);
266 * OK, the definition is empty, but check
267 * if it is the name of an embedded subsystem.
269 if(0 == _wcsicmp(L
"DEBUG", Name
))
272 * Initialize the embedded DBGSS.
274 Request
->SmHeader
.Status
= SmInitializeDbgSs();
279 * Badly defined subsystem. Check the registry!
281 Request
->SmHeader
.Status
= STATUS_NOT_FOUND
;
285 /* It couldn't lookup the Name! */
286 Request
->SmHeader
.Status
= Status
;