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 /**********************************************************************
32 * SmCreateUserProcess/5
37 * ImagePath: bsolute path of the image to run;
38 * CommandLine: arguments and options for ImagePath;
39 * WaitForIt: TRUE for boot time processes and FALSE for
40 * subsystems bootstrapping;
41 * Timeout: optional: used if WaitForIt==TRUE;
42 * ProcessHandle: optional: a duplicated handle for
43 the child process (storage provided by the caller).
50 SmCreateUserProcess (LPWSTR ImagePath
,
53 PLARGE_INTEGER Timeout OPTIONAL
,
54 PRTL_USER_PROCESS_INFORMATION UserProcessInfo OPTIONAL
)
56 UNICODE_STRING ImagePathString
= {0};
57 UNICODE_STRING CommandLineString
= {0};
58 PRTL_USER_PROCESS_PARAMETERS ProcessParameters
= NULL
;
59 RTL_USER_PROCESS_INFORMATION ProcessInfo
= {0};
60 PRTL_USER_PROCESS_INFORMATION pProcessInfo
= & ProcessInfo
;
61 NTSTATUS Status
= STATUS_SUCCESS
;
63 DPRINT("SM: %s called\n", __FUNCTION__
);
65 if (NULL
!= UserProcessInfo
)
67 pProcessInfo
= UserProcessInfo
;
70 RtlInitUnicodeString (& ImagePathString
, ImagePath
);
71 RtlInitUnicodeString (& CommandLineString
, CommandLine
);
73 RtlCreateProcessParameters(& ProcessParameters
,
84 Status
= RtlCreateUserProcess (& ImagePathString
,
95 RtlDestroyProcessParameters (ProcessParameters
);
97 if (!NT_SUCCESS(Status
))
99 DPRINT1("SM: %s: Running \"%S\" failed (Status=0x%08lx)\n",
100 __FUNCTION__
, ImagePathString
.Buffer
, Status
);
104 * It the caller is *not* interested in the child info,
105 * resume it immediately.
107 if (NULL
== UserProcessInfo
)
109 Status
= NtResumeThread (ProcessInfo
.ThreadHandle
, NULL
);
110 if(!NT_SUCCESS(Status
))
112 DPRINT1("SM: %s: NtResumeThread failed (Status=0x%08lx)\n",
113 __FUNCTION__
, Status
);
117 /* Wait for process termination */
120 Status
= NtWaitForSingleObject (pProcessInfo
->ProcessHandle
,
123 if (!NT_SUCCESS(Status
))
125 DPRINT1("SM: %s: NtWaitForSingleObject failed with Status=0x%08lx\n",
126 __FUNCTION__
, Status
);
130 if (NULL
== UserProcessInfo
)
132 NtClose(pProcessInfo
->ProcessHandle
);
133 NtClose(pProcessInfo
->ThreadHandle
);
139 /**********************************************************************
144 PSM_PORT_MESSAGE_EXECPGM ExecPgm
= NULL
;
145 WCHAR Name
[SM_EXEXPGM_MAX_LENGTH
+ 1];
146 NTSTATUS Status
= STATUS_SUCCESS
;
148 DPRINT("SM: %s called\n",__FUNCTION__
);
152 DPRINT1("SM: %s: Request == NULL!\n", __FUNCTION__
);
153 return STATUS_INVALID_PARAMETER
;
155 DPRINT("SM: %s called from CID(%lx|%lx)\n",
156 __FUNCTION__
, Request
->Header
.ClientId
.UniqueProcess
,
157 Request
->Header
.ClientId
.UniqueThread
);
158 ExecPgm
= & Request
->Request
.ExecPgm
;
159 /* Check if the name lenght is valid */
160 if((ExecPgm
->NameLength
> 0) &&
161 (ExecPgm
->NameLength
<= SM_EXEXPGM_MAX_LENGTH
) &&
162 TRUE
/* TODO: check LPC payload size */)
164 WCHAR Data
[MAX_PATH
+ 1] = {0};
165 ULONG DataLength
= sizeof Data
;
166 ULONG DataType
= REG_EXPAND_SZ
;
169 RtlZeroMemory (Name
, sizeof Name
);
172 (sizeof ExecPgm
->Name
[0] * ExecPgm
->NameLength
));
173 DPRINT("SM: %s: Name='%S'\n", __FUNCTION__
, Name
);
174 /* Lookup Name in the registry */
175 Status
= SmLookupSubsystem (Name
,
179 SmSystemEnvironment
/* expand */);
180 if(NT_SUCCESS(Status
))
182 /* Is the subsystem definition non-empty? */
183 if (DataLength
> sizeof Data
[0])
185 WCHAR ImagePath
[MAX_PATH
+ 1] = {0};
186 PWCHAR CommandLine
= ImagePath
;
187 RTL_USER_PROCESS_INFORMATION ProcessInfo
= {0};
189 wcscpy (ImagePath
, L
"\\??\\");
190 wcscat (ImagePath
, Data
);
192 * Look for the beginning of the command line.
194 for (; (*CommandLine
!= L
'\0') && (*CommandLine
!= L
' ');
196 for (; *CommandLine
== L
' '; CommandLine
++)
198 *CommandLine
= L
'\0';
201 * Create a native process (suspended).
203 ProcessInfo
.Size
= sizeof ProcessInfo
;
204 Request
->SmHeader
.Status
=
205 SmCreateUserProcess(ImagePath
,
210 if (NT_SUCCESS(Request
->SmHeader
.Status
))
212 Status
= SmCreateClient (& ProcessInfo
, Name
);
213 if (NT_SUCCESS(Status
))
215 Status
= NtResumeThread (ProcessInfo
.ThreadHandle
, NULL
);
216 if (!NT_SUCCESS(Status
))
218 //Status = SmDestroyClient TODO
221 DPRINT1("SM: %s: SmCreateClient failed (Status=0x%08lx)\n",
222 __FUNCTION__
, Status
);
229 * OK, the definition is empty, but check
230 * if it is the name of an embedded subsystem.
232 if(0 == _wcsicmp(L
"DEBUG", Name
))
235 * Initialize the embedded DBGSS.
237 Request
->SmHeader
.Status
= SmInitializeDbgSs();
242 * Badly defined subsystem. Check the registry!
244 Request
->SmHeader
.Status
= STATUS_NOT_FOUND
;
248 /* It couldn't lookup the Name! */
249 Request
->SmHeader
.Status
= Status
;