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
36 SmCreateUserProcess (LPWSTR ImagePath
,
39 PLARGE_INTEGER Timeout OPTIONAL
,
41 PRTL_PROCESS_INFO UserProcessInfo OPTIONAL
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
;
52 DPRINT("SM: %s called\n",__FUNCTION__
);
54 RtlInitUnicodeString (& ImagePathString
, ImagePath
);
55 RtlInitUnicodeString (& CommandLineString
, CommandLine
);
57 RtlCreateProcessParameters(& ProcessParameters
,
68 if(NULL
!= UserProcessInfo
)
70 /* Use caller provided storage */
71 pProcessInfo
= UserProcessInfo
;
74 Status
= RtlCreateUserProcess (& ImagePathString
,
85 RtlDestroyProcessParameters (ProcessParameters
);
87 if (!NT_SUCCESS(Status
))
89 DPRINT1("SM: %s: Running \"%S\" failed (Status=0x%08lx)\n",
90 __FUNCTION__
, ImagePathString
.Buffer
, Status
);
94 ZwResumeThread(pProcessInfo
->ThreadHandle
, NULL
);
97 /* Wait for process termination */
100 NtWaitForSingleObject (pProcessInfo
->ProcessHandle
,
105 /* Terminate process */
108 NtClose(pProcessInfo
->ThreadHandle
);
109 NtClose(pProcessInfo
->ProcessHandle
);
111 return STATUS_SUCCESS
;
114 /**********************************************************************
116 * SmLookupSubsystem/5
119 * Read from the registry key
120 * \Registry\SYSTEM\CurrentControlSet\Control\Session Manager\Subsystems
121 * the value which name is Name.
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.
133 SmLookupSubsystem (IN PWSTR Name
,
135 IN OUT PULONG DataLength
,
136 IN OUT PULONG DataType
,
139 NTSTATUS Status
= STATUS_SUCCESS
;
140 UNICODE_STRING usKeyName
= {0};
141 OBJECT_ATTRIBUTES Oa
= {0};
142 HANDLE hKey
= (HANDLE
) 0;
144 DPRINT("SM: %s(Name='%S') called\n", __FUNCTION__
, Name
);
146 * Prepare the key name to scan and
147 * related object attributes.
149 RtlInitUnicodeString (& usKeyName
,
150 L
"\\Registry\\Machine\\SYSTEM\\CurrentControlSet\\Control\\Session Manager\\SubSystems");
152 InitializeObjectAttributes (& Oa
,
154 OBJ_CASE_INSENSITIVE
,
158 * Open the key. This MUST NOT fail, if the
159 * request is for a legitimate subsystem.
161 Status
= NtOpenKey (& hKey
,
164 if(NT_SUCCESS(Status
))
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
;
173 RtlInitUnicodeString (& usValueName
, Name
);
174 Status
= NtQueryValueKey (hKey
,
176 KeyValuePartialInformation
,
178 sizeof KeyValueInformation
,
180 if(NT_SUCCESS(Status
))
182 DPRINT("nkvpi.TitleIndex = %ld\n", kvpi
->TitleIndex
);
183 DPRINT("kvpi.Type = %ld\n", kvpi
->Type
);
184 DPRINT("kvpi.DataLength = %ld\n", kvpi
->DataLength
);
186 if((NULL
!= Data
) && (NULL
!= DataLength
) && (NULL
!= DataType
))
188 *DataType
= kvpi
->Type
;
189 if((Expand
) && (REG_EXPAND_SZ
== *DataType
))
191 UNICODE_STRING Source
;
192 WCHAR DestinationBuffer
[2048] = {0};
193 UNICODE_STRING Destination
;
196 DPRINT("SM: %s: value will be expanded\n", __FUNCTION__
);
198 Source
.Length
= kvpi
->DataLength
;
199 Source
.MaximumLength
= kvpi
->DataLength
;
200 Source
.Buffer
= (PWCHAR
) & kvpi
->Data
;
202 Destination
.Length
= 0;
203 Destination
.MaximumLength
= sizeof DestinationBuffer
;
204 Destination
.Buffer
= DestinationBuffer
;
206 Status
= RtlExpandEnvironmentStrings_U (SmSystemEnvironment
,
210 if(NT_SUCCESS(Status
))
212 *DataLength
= min(*DataLength
, Destination
.Length
);
213 RtlCopyMemory (Data
, Destination
.Buffer
, *DataLength
);
217 DPRINT("SM: %s: value won't be expanded\n", __FUNCTION__
);
218 *DataLength
= min(*DataLength
, kvpi
->DataLength
);
219 RtlCopyMemory (Data
, & kvpi
->Data
, *DataLength
);
221 *DataType
= kvpi
->Type
;
223 DPRINT1("SM: %s: Data or DataLength or DataType is NULL!\n", __FUNCTION__
);
224 Status
= STATUS_INVALID_PARAMETER
;
227 DPRINT1("%s: NtQueryValueKey failed (Status=0x%08lx)\n", __FUNCTION__
, Status
);
231 DPRINT1("%s: NtOpenKey failed (Status=0x%08lx)\n", __FUNCTION__
, Status
);
237 /**********************************************************************
242 PSM_PORT_MESSAGE_EXECPGM ExecPgm
= NULL
;
243 WCHAR Name
[SM_EXEXPGM_MAX_LENGTH
+ 1];
244 NTSTATUS Status
= STATUS_SUCCESS
;
246 DPRINT("SM: %s called\n",__FUNCTION__
);
250 DPRINT1("SM: %s: Request == NULL!\n", __FUNCTION__
);
251 return STATUS_INVALID_PARAMETER
;
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 */)
263 RtlZeroMemory (Name
, sizeof Name
);
266 (sizeof ExecPgm
->Name
[0] * ExecPgm
->NameLength
));
267 DPRINT("SM: %s: Name='%S'\n", __FUNCTION__
, Name
);
269 * Check if program name is internal
270 * (Is this correct? Debug is in the registry too)
272 if(0 == _wcsicmp(L
"DEBUG", Name
))
276 * NOTE: probably in early prototypes it was an
277 * independent process; now it is embedded in the
278 * SM for performance or security.
280 Request
->Status
= SmInitializeDbgSs();
284 WCHAR Data
[MAX_PATH
+ 1] = {0};
285 ULONG DataLength
= sizeof Data
;
286 ULONG DataType
= REG_EXPAND_SZ
;
288 /* Lookup Name in the registry */
289 Status
= SmLookupSubsystem (Name
,
294 if(NT_SUCCESS(Status
))
296 WCHAR ImagePath
[MAX_PATH
+ 1] = {0};
298 wcscpy (ImagePath
, L
"\\??\\");
299 wcscat (ImagePath
, Data
);
301 /* Create native process */
302 Request
->Status
= SmCreateUserProcess(ImagePath
,
306 FALSE
, /* terminate */
309 Request
->Status
= Status
;
315 Request
->Status
= Status
= STATUS_INVALID_PARAMETER
;