Copy wininet to branch
[reactos.git] / reactos / subsys / 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 /**********************************************************************
32 * SmCreateUserProcess/5
33 *
34 */
35 NTSTATUS STDCALL
36 SmCreateUserProcess (LPWSTR ImagePath,
37 LPWSTR CommandLine,
38 BOOLEAN WaitForIt,
39 PLARGE_INTEGER Timeout OPTIONAL,
40 BOOLEAN TerminateIt,
41 PRTL_PROCESS_INFO UserProcessInfo OPTIONAL
42 )
43 {
44 UNICODE_STRING ImagePathString = {0};
45 UNICODE_STRING CommandLineString = {0};
46 PRTL_USER_PROCESS_PARAMETERS ProcessParameters = NULL;
47 RTL_PROCESS_INFO ProcessInfo = {0};
48 PRTL_PROCESS_INFO pProcessInfo = & ProcessInfo;
49 NTSTATUS Status = STATUS_SUCCESS;
50
51
52 DPRINT("SM: %s called\n",__FUNCTION__);
53
54 RtlInitUnicodeString (& ImagePathString, ImagePath);
55 RtlInitUnicodeString (& CommandLineString, CommandLine);
56
57 RtlCreateProcessParameters(& ProcessParameters,
58 & ImagePathString,
59 NULL,
60 NULL,
61 & CommandLineString,
62 SmSystemEnvironment,
63 NULL,
64 NULL,
65 NULL,
66 NULL);
67
68 if(NULL != UserProcessInfo)
69 {
70 /* Use caller provided storage */
71 pProcessInfo = UserProcessInfo;
72 }
73
74 Status = RtlCreateUserProcess (& ImagePathString,
75 OBJ_CASE_INSENSITIVE,
76 ProcessParameters,
77 NULL,
78 NULL,
79 NULL,
80 FALSE,
81 NULL,
82 NULL,
83 pProcessInfo);
84
85 RtlDestroyProcessParameters (ProcessParameters);
86
87 if (!NT_SUCCESS(Status))
88 {
89 DPRINT1("SM: %s: Running \"%S\" failed (Status=0x%08lx)\n",
90 __FUNCTION__, ImagePathString.Buffer, Status);
91 return Status;
92 }
93
94 ZwResumeThread(pProcessInfo->ThreadHandle, NULL);
95
96
97 /* Wait for process termination */
98 if(WaitForIt)
99 {
100 NtWaitForSingleObject (pProcessInfo->ProcessHandle,
101 FALSE,
102 Timeout);
103 }
104
105 /* Terminate process */
106 if(TerminateIt)
107 {
108 NtClose(pProcessInfo->ThreadHandle);
109 NtClose(pProcessInfo->ProcessHandle);
110 }
111 return STATUS_SUCCESS;
112 }
113
114 /**********************************************************************
115 * NAME
116 * SmLookupSubsystem/5
117 *
118 * DESCRIPTION
119 * Read from the registry key
120 * \Registry\SYSTEM\CurrentControlSet\Control\Session Manager\Subsystems
121 * the value which name is Name.
122 *
123 * ARGUMENTS
124 * Name: name of the program to run, that is a value's name in
125 * the SM registry key Subsystems;
126 * Data: what the registry gave back for Name;
127 * DataLength: how much Data the registry returns;
128 * DataType: what is Data?
129 * Expand: set it TRUE if you want this function to use the env
130 * to possibly expand Data before giving it back.
131 */
132 NTSTATUS STDCALL
133 SmLookupSubsystem (IN PWSTR Name,
134 IN OUT PWSTR Data,
135 IN OUT PULONG DataLength,
136 IN OUT PULONG DataType,
137 IN BOOLEAN Expand)
138 {
139 NTSTATUS Status = STATUS_SUCCESS;
140 UNICODE_STRING usKeyName = {0};
141 OBJECT_ATTRIBUTES Oa = {0};
142 HANDLE hKey = (HANDLE) 0;
143
144 DPRINT("SM: %s(Name='%S') called\n", __FUNCTION__, Name);
145 /*
146 * Prepare the key name to scan and
147 * related object attributes.
148 */
149 RtlInitUnicodeString (& usKeyName,
150 L"\\Registry\\Machine\\SYSTEM\\CurrentControlSet\\Control\\Session Manager\\SubSystems");
151
152 InitializeObjectAttributes (& Oa,
153 & usKeyName,
154 OBJ_CASE_INSENSITIVE,
155 NULL,
156 NULL);
157 /*
158 * Open the key. This MUST NOT fail, if the
159 * request is for a legitimate subsystem.
160 */
161 Status = NtOpenKey (& hKey,
162 MAXIMUM_ALLOWED,
163 & Oa);
164 if(NT_SUCCESS(Status))
165 {
166 UNICODE_STRING usValueName = {0};
167 WCHAR KeyValueInformation [1024] = {L'\0'};
168 ULONG ResultLength = 0L;
169 PKEY_VALUE_PARTIAL_INFORMATION
170 kvpi = (PKEY_VALUE_PARTIAL_INFORMATION) KeyValueInformation;
171
172
173 RtlInitUnicodeString (& usValueName, Name);
174 Status = NtQueryValueKey (hKey,
175 & usValueName,
176 KeyValuePartialInformation,
177 KeyValueInformation,
178 sizeof KeyValueInformation,
179 & ResultLength);
180 if(NT_SUCCESS(Status))
181 {
182 DPRINT("nkvpi.TitleIndex = %ld\n", kvpi->TitleIndex);
183 DPRINT("kvpi.Type = %ld\n", kvpi->Type);
184 DPRINT("kvpi.DataLength = %ld\n", kvpi->DataLength);
185
186 if((NULL != Data) && (NULL != DataLength) && (NULL != DataType))
187 {
188 *DataType = kvpi->Type;
189 if((Expand) && (REG_EXPAND_SZ == *DataType))
190 {
191 UNICODE_STRING Source;
192 WCHAR DestinationBuffer [2048] = {0};
193 UNICODE_STRING Destination;
194 ULONG Length = 0;
195
196 DPRINT("SM: %s: value will be expanded\n", __FUNCTION__);
197
198 Source.Length = kvpi->DataLength;
199 Source.MaximumLength = kvpi->DataLength;
200 Source.Buffer = (PWCHAR) & kvpi->Data;
201
202 Destination.Length = 0;
203 Destination.MaximumLength = sizeof DestinationBuffer;
204 Destination.Buffer = DestinationBuffer;
205
206 Status = RtlExpandEnvironmentStrings_U (SmSystemEnvironment,
207 & Source,
208 & Destination,
209 & Length);
210 if(NT_SUCCESS(Status))
211 {
212 *DataLength = min(*DataLength, Destination.Length);
213 RtlCopyMemory (Data, Destination.Buffer, *DataLength);
214 }
215
216 }else{
217 DPRINT("SM: %s: value won't be expanded\n", __FUNCTION__);
218 *DataLength = min(*DataLength, kvpi->DataLength);
219 RtlCopyMemory (Data, & kvpi->Data, *DataLength);
220 }
221 *DataType = kvpi->Type;
222 }else{
223 DPRINT1("SM: %s: Data or DataLength or DataType is NULL!\n", __FUNCTION__);
224 Status = STATUS_INVALID_PARAMETER;
225 }
226 }else{
227 DPRINT1("%s: NtQueryValueKey failed (Status=0x%08lx)\n", __FUNCTION__, Status);
228 }
229 NtClose (hKey);
230 }else{
231 DPRINT1("%s: NtOpenKey failed (Status=0x%08lx)\n", __FUNCTION__, Status);
232 }
233 return Status;
234 }
235
236
237 /**********************************************************************
238 * SmExecPgm/1 API
239 */
240 SMAPI(SmExecPgm)
241 {
242 PSM_PORT_MESSAGE_EXECPGM ExecPgm = NULL;
243 WCHAR Name [SM_EXEXPGM_MAX_LENGTH + 1];
244 NTSTATUS Status = STATUS_SUCCESS;
245
246 DPRINT("SM: %s called\n",__FUNCTION__);
247
248 if(NULL == Request)
249 {
250 DPRINT1("SM: %s: Request == NULL!\n", __FUNCTION__);
251 return STATUS_INVALID_PARAMETER;
252 }
253 DPRINT("SM: %s called from CID(%lx|%lx)\n",
254 __FUNCTION__, Request->Header.ClientId.UniqueProcess,
255 Request->Header.ClientId.UniqueThread);
256 ExecPgm = & Request->ExecPgm;
257 /* Check if the name lenght is valid */
258 if((ExecPgm->NameLength > 0) &&
259 (ExecPgm->NameLength <= SM_EXEXPGM_MAX_LENGTH) &&
260 TRUE /* TODO: check LPC payload size */)
261 {
262
263 RtlZeroMemory (Name, sizeof Name);
264 RtlCopyMemory (Name,
265 ExecPgm->Name,
266 (sizeof ExecPgm->Name[0] * ExecPgm->NameLength));
267 DPRINT("SM: %s: Name='%S'\n", __FUNCTION__, Name);
268 /*
269 * Check if program name is internal
270 * (Is this correct? Debug is in the registry too)
271 */
272 if(0 == _wcsicmp(L"DEBUG", Name))
273 {
274 /*
275 * Initialize DBGSS.
276 * NOTE: probably in early prototypes it was an
277 * independent process; now it is embedded in the
278 * SM for performance or security.
279 */
280 Request->Status = SmInitializeDbgSs();
281 }
282 else
283 {
284 WCHAR Data [MAX_PATH + 1] = {0};
285 ULONG DataLength = sizeof Data;
286 ULONG DataType = REG_EXPAND_SZ;
287
288 /* Lookup Name in the registry */
289 Status = SmLookupSubsystem (Name,
290 Data,
291 & DataLength,
292 & DataType,
293 TRUE); /* expand */
294 if(NT_SUCCESS(Status))
295 {
296 WCHAR ImagePath [MAX_PATH + 1] = {0};
297
298 wcscpy (ImagePath, L"\\??\\");
299 wcscat (ImagePath, Data);
300
301 /* Create native process */
302 Request->Status = SmCreateUserProcess(ImagePath,
303 L"", /* FIXME */
304 FALSE, /* wait */
305 NULL,
306 FALSE, /* terminate */
307 NULL);
308 }else{
309 Request->Status = Status;
310 }
311 }
312 }
313 else
314 {
315 Request->Status = Status = STATUS_INVALID_PARAMETER;
316 }
317 return Status;
318 }
319
320 /* EOF */