1c2c66affSColin Finck /*
2c2c66affSColin Finck * PROJECT: ReactOS Windows-Compatible Session Manager
3c2c66affSColin Finck * LICENSE: BSD 2-Clause License
4c2c66affSColin Finck * FILE: base/system/smss/smss.c
5c2c66affSColin Finck * PURPOSE: Main SMSS Code
6c2c66affSColin Finck * PROGRAMMERS: Alex Ionescu
7c2c66affSColin Finck */
8c2c66affSColin Finck
9c2c66affSColin Finck /* INCLUDES *******************************************************************/
10c2c66affSColin Finck
11c2c66affSColin Finck #include "smss.h"
12c2c66affSColin Finck
13c2c66affSColin Finck #include <pseh/pseh2.h>
14c2c66affSColin Finck
15c2c66affSColin Finck #define NDEBUG
16c2c66affSColin Finck #include <debug.h>
17c2c66affSColin Finck
18c2c66affSColin Finck /* GLOBALS ********************************************************************/
19c2c66affSColin Finck
20c2c66affSColin Finck UNICODE_STRING SmpSystemRoot;
21c2c66affSColin Finck ULONG AttachedSessionId = -1;
22c2c66affSColin Finck BOOLEAN SmpDebug, SmpEnableDots;
23c2c66affSColin Finck HANDLE SmApiPort;
24c2c66affSColin Finck HANDLE SmpInitialCommandProcessId;
25c2c66affSColin Finck
26c2c66affSColin Finck /* FUNCTIONS ******************************************************************/
27c2c66affSColin Finck
28c2c66affSColin Finck NTSTATUS
29c2c66affSColin Finck NTAPI
SmpExecuteImage(IN PUNICODE_STRING FileName,IN PUNICODE_STRING Directory,IN PUNICODE_STRING CommandLine,IN ULONG MuSessionId,IN ULONG Flags,IN PRTL_USER_PROCESS_INFORMATION ProcessInformation)30c2c66affSColin Finck SmpExecuteImage(IN PUNICODE_STRING FileName,
31c2c66affSColin Finck IN PUNICODE_STRING Directory,
32c2c66affSColin Finck IN PUNICODE_STRING CommandLine,
33c2c66affSColin Finck IN ULONG MuSessionId,
34c2c66affSColin Finck IN ULONG Flags,
35c2c66affSColin Finck IN PRTL_USER_PROCESS_INFORMATION ProcessInformation)
36c2c66affSColin Finck {
37c2c66affSColin Finck PRTL_USER_PROCESS_INFORMATION ProcessInfo;
38c2c66affSColin Finck NTSTATUS Status;
39c2c66affSColin Finck RTL_USER_PROCESS_INFORMATION LocalProcessInfo;
40c2c66affSColin Finck PRTL_USER_PROCESS_PARAMETERS ProcessParameters;
41c2c66affSColin Finck
42c2c66affSColin Finck /* Use the input process information if we have it, otherwise use local */
43c2c66affSColin Finck ProcessInfo = ProcessInformation;
44c2c66affSColin Finck if (!ProcessInfo) ProcessInfo = &LocalProcessInfo;
45c2c66affSColin Finck
46c2c66affSColin Finck /* Create parameters for the target process */
47c2c66affSColin Finck Status = RtlCreateProcessParameters(&ProcessParameters,
48c2c66affSColin Finck FileName,
49c2c66affSColin Finck SmpDefaultLibPath.Length ?
50c2c66affSColin Finck &SmpDefaultLibPath : NULL,
51c2c66affSColin Finck Directory,
52c2c66affSColin Finck CommandLine,
53c2c66affSColin Finck SmpDefaultEnvironment,
54c2c66affSColin Finck NULL,
55c2c66affSColin Finck NULL,
56c2c66affSColin Finck NULL,
57c2c66affSColin Finck 0);
58c2c66affSColin Finck if (!NT_SUCCESS(Status))
59c2c66affSColin Finck {
60c2c66affSColin Finck /* This is a pretty bad failure. ASSERT on checked builds and exit */
617d6bda16SSerge Gautherie ASSERTMSG("RtlCreateProcessParameters failed.\n", NT_SUCCESS(Status));
62c2c66affSColin Finck DPRINT1("SMSS: RtlCreateProcessParameters failed for %wZ - Status == %lx\n",
63c2c66affSColin Finck FileName, Status);
64c2c66affSColin Finck return Status;
65c2c66affSColin Finck }
66c2c66affSColin Finck
67c2c66affSColin Finck /* Set the size field as required */
68*f43ce465SHermès Bélusca-Maïto ProcessInfo->Size = sizeof(*ProcessInfo);
69c2c66affSColin Finck
70c2c66affSColin Finck /* Check if the debug flag was requested */
71c2c66affSColin Finck if (Flags & SMP_DEBUG_FLAG)
72c2c66affSColin Finck {
73c2c66affSColin Finck /* Write it in the process parameters */
74c2c66affSColin Finck ProcessParameters->DebugFlags = 1;
75c2c66affSColin Finck }
76c2c66affSColin Finck else
77c2c66affSColin Finck {
78c2c66affSColin Finck /* Otherwise inherit the flag that was passed to SMSS itself */
79c2c66affSColin Finck ProcessParameters->DebugFlags = SmpDebug;
80c2c66affSColin Finck }
81c2c66affSColin Finck
82c2c66affSColin Finck /* Subsystems get the first 1MB of memory reserved for DOS/IVT purposes */
83c2c66affSColin Finck if (Flags & SMP_SUBSYSTEM_FLAG)
84c2c66affSColin Finck {
85c2c66affSColin Finck ProcessParameters->Flags |= RTL_USER_PROCESS_PARAMETERS_RESERVE_1MB;
86c2c66affSColin Finck }
87c2c66affSColin Finck
88c2c66affSColin Finck /* And always force NX for anything that SMSS launches */
89c2c66affSColin Finck ProcessParameters->Flags |= RTL_USER_PROCESS_PARAMETERS_NX;
90c2c66affSColin Finck
91*f43ce465SHermès Bélusca-Maïto /* Now create the process in suspended state */
92c2c66affSColin Finck Status = RtlCreateUserProcess(FileName,
93c2c66affSColin Finck OBJ_CASE_INSENSITIVE,
94c2c66affSColin Finck ProcessParameters,
95c2c66affSColin Finck NULL,
96c2c66affSColin Finck NULL,
97c2c66affSColin Finck NULL,
98c2c66affSColin Finck FALSE,
99c2c66affSColin Finck NULL,
100c2c66affSColin Finck NULL,
101c2c66affSColin Finck ProcessInfo);
102c2c66affSColin Finck RtlDestroyProcessParameters(ProcessParameters);
103c2c66affSColin Finck if (!NT_SUCCESS(Status))
104c2c66affSColin Finck {
105c2c66affSColin Finck /* If we couldn't create it, fail back to the caller */
106c2c66affSColin Finck DPRINT1("SMSS: Failed load of %wZ - Status == %lx\n",
107c2c66affSColin Finck FileName, Status);
108c2c66affSColin Finck return Status;
109c2c66affSColin Finck }
110c2c66affSColin Finck
111c2c66affSColin Finck /* Associate a session with this process */
112c2c66affSColin Finck Status = SmpSetProcessMuSessionId(ProcessInfo->ProcessHandle, MuSessionId);
113c2c66affSColin Finck
114c2c66affSColin Finck /* If the application is deferred (suspended), there's nothing to do */
115c2c66affSColin Finck if (Flags & SMP_DEFERRED_FLAG) return Status;
116c2c66affSColin Finck
117c2c66affSColin Finck /* Otherwise, get ready to start it, but make sure it's a native app */
118c2c66affSColin Finck if (ProcessInfo->ImageInformation.SubSystemType == IMAGE_SUBSYSTEM_NATIVE)
119c2c66affSColin Finck {
120c2c66affSColin Finck /* Resume it */
121c2c66affSColin Finck NtResumeThread(ProcessInfo->ThreadHandle, NULL);
122c2c66affSColin Finck if (!(Flags & SMP_ASYNC_FLAG))
123c2c66affSColin Finck {
124c2c66affSColin Finck /* Block on it unless Async was requested */
125c2c66affSColin Finck NtWaitForSingleObject(ProcessInfo->ThreadHandle, FALSE, NULL);
126c2c66affSColin Finck }
127c2c66affSColin Finck
128c2c66affSColin Finck /* It's up and running now, close our handles */
129c2c66affSColin Finck NtClose(ProcessInfo->ThreadHandle);
130c2c66affSColin Finck NtClose(ProcessInfo->ProcessHandle);
131c2c66affSColin Finck }
132c2c66affSColin Finck else
133c2c66affSColin Finck {
134c2c66affSColin Finck /* This image is invalid, so kill it, close our handles, and fail */
135c2c66affSColin Finck Status = STATUS_INVALID_IMAGE_FORMAT;
136c2c66affSColin Finck NtTerminateProcess(ProcessInfo->ProcessHandle, Status);
137*f43ce465SHermès Bélusca-Maïto NtWaitForSingleObject(ProcessInfo->ThreadHandle, FALSE, NULL);
138c2c66affSColin Finck NtClose(ProcessInfo->ThreadHandle);
139c2c66affSColin Finck NtClose(ProcessInfo->ProcessHandle);
140c2c66affSColin Finck DPRINT1("SMSS: Not an NT image - %wZ\n", FileName);
141c2c66affSColin Finck }
142c2c66affSColin Finck
143c2c66affSColin Finck /* Return the outcome of the process create */
144c2c66affSColin Finck return Status;
145c2c66affSColin Finck }
146c2c66affSColin Finck
147c2c66affSColin Finck NTSTATUS
148c2c66affSColin Finck NTAPI
SmpInvokeAutoChk(IN PUNICODE_STRING FileName,IN PUNICODE_STRING Directory,IN PUNICODE_STRING Arguments,IN ULONG Flags)149c2c66affSColin Finck SmpInvokeAutoChk(IN PUNICODE_STRING FileName,
150c2c66affSColin Finck IN PUNICODE_STRING Directory,
151c2c66affSColin Finck IN PUNICODE_STRING Arguments,
152c2c66affSColin Finck IN ULONG Flags)
153c2c66affSColin Finck {
154c2c66affSColin Finck ANSI_STRING MessageString;
155c2c66affSColin Finck CHAR MessageBuffer[256];
156c2c66affSColin Finck UNICODE_STRING Destination;
157c2c66affSColin Finck WCHAR Buffer[1024];
158c2c66affSColin Finck BOOLEAN BootState, BootOkay, ShutdownOkay;
159c2c66affSColin Finck
160c2c66affSColin Finck /* Check if autochk should show dots (if the user booted with /SOS) */
161c2c66affSColin Finck if (SmpQueryRegistrySosOption()) SmpEnableDots = FALSE;
162c2c66affSColin Finck
163c2c66affSColin Finck /* Make sure autochk was actually found */
164c2c66affSColin Finck if (Flags & SMP_INVALID_PATH)
165c2c66affSColin Finck {
166c2c66affSColin Finck /* It wasn't, so create an error message to print on the screen */
1670997e902SHermès Bélusca-Maïto RtlStringCbPrintfA(MessageBuffer,
1680997e902SHermès Bélusca-Maïto sizeof(MessageBuffer),
169c2c66affSColin Finck "%wZ program not found - skipping AUTOCHECK\r\n",
170c2c66affSColin Finck FileName);
171c2c66affSColin Finck RtlInitAnsiString(&MessageString, MessageBuffer);
172c2c66affSColin Finck if (NT_SUCCESS(RtlAnsiStringToUnicodeString(&Destination,
173c2c66affSColin Finck &MessageString,
174c2c66affSColin Finck TRUE)))
175c2c66affSColin Finck {
176c2c66affSColin Finck /* And show it */
177c2c66affSColin Finck NtDisplayString(&Destination);
178c2c66affSColin Finck RtlFreeUnicodeString(&Destination);
179c2c66affSColin Finck }
180c2c66affSColin Finck }
181c2c66affSColin Finck else
182c2c66affSColin Finck {
183c2c66affSColin Finck /* Autochk is there, so record the BSD state */
184c2c66affSColin Finck BootState = SmpSaveAndClearBootStatusData(&BootOkay, &ShutdownOkay);
185c2c66affSColin Finck
186c2c66affSColin Finck /* Build the path to autochk and place its arguments */
187c2c66affSColin Finck RtlInitEmptyUnicodeString(&Destination, Buffer, sizeof(Buffer));
188c2c66affSColin Finck RtlAppendUnicodeStringToString(&Destination, FileName);
189c2c66affSColin Finck RtlAppendUnicodeToString(&Destination, L" ");
190c2c66affSColin Finck RtlAppendUnicodeStringToString(&Destination, Arguments);
191c2c66affSColin Finck
192c2c66affSColin Finck /* Execute it */
193c2c66affSColin Finck SmpExecuteImage(FileName,
194c2c66affSColin Finck Directory,
195c2c66affSColin Finck &Destination,
196c2c66affSColin Finck 0,
197c2c66affSColin Finck Flags & ~SMP_AUTOCHK_FLAG,
198c2c66affSColin Finck NULL);
199c2c66affSColin Finck
200c2c66affSColin Finck /* Restore the BSD state */
201c2c66affSColin Finck if (BootState) SmpRestoreBootStatusData(BootOkay, ShutdownOkay);
202c2c66affSColin Finck }
203c2c66affSColin Finck
204c2c66affSColin Finck /* We're all done! */
205c2c66affSColin Finck return STATUS_SUCCESS;
206c2c66affSColin Finck }
207c2c66affSColin Finck
208c2c66affSColin Finck NTSTATUS
209c2c66affSColin Finck NTAPI
SmpExecuteCommand(IN PUNICODE_STRING CommandLine,IN ULONG MuSessionId,OUT PHANDLE ProcessId,IN ULONG Flags)210c2c66affSColin Finck SmpExecuteCommand(IN PUNICODE_STRING CommandLine,
211c2c66affSColin Finck IN ULONG MuSessionId,
212c2c66affSColin Finck OUT PHANDLE ProcessId,
213c2c66affSColin Finck IN ULONG Flags)
214c2c66affSColin Finck {
215c2c66affSColin Finck NTSTATUS Status;
216c2c66affSColin Finck UNICODE_STRING Arguments, Directory, FileName;
217c2c66affSColin Finck
218c2c66affSColin Finck /* There's no longer a debugging subsystem */
219c2c66affSColin Finck if (Flags & SMP_DEBUG_FLAG) return STATUS_SUCCESS;
220c2c66affSColin Finck
221c2c66affSColin Finck /* Parse the command line to see what execution flags are requested */
222c2c66affSColin Finck Status = SmpParseCommandLine(CommandLine,
223c2c66affSColin Finck &Flags,
224c2c66affSColin Finck &FileName,
225c2c66affSColin Finck &Directory,
226c2c66affSColin Finck &Arguments);
227c2c66affSColin Finck if (!NT_SUCCESS(Status))
228c2c66affSColin Finck {
229c2c66affSColin Finck /* Fail if we couldn't do that */
230c2c66affSColin Finck DPRINT1("SMSS: SmpParseCommandLine( %wZ ) failed - Status == %lx\n",
231c2c66affSColin Finck CommandLine, Status);
232c2c66affSColin Finck return Status;
233c2c66affSColin Finck }
234c2c66affSColin Finck
235c2c66affSColin Finck /* Check if autochk is requested */
236c2c66affSColin Finck if (Flags & SMP_AUTOCHK_FLAG)
237c2c66affSColin Finck {
238c2c66affSColin Finck /* Run it */
239c2c66affSColin Finck Status = SmpInvokeAutoChk(&FileName, &Directory, &Arguments, Flags);
240c2c66affSColin Finck }
241c2c66affSColin Finck else if (Flags & SMP_SUBSYSTEM_FLAG)
242c2c66affSColin Finck {
243c2c66affSColin Finck Status = SmpLoadSubSystem(&FileName,
244c2c66affSColin Finck &Directory,
245c2c66affSColin Finck CommandLine,
246c2c66affSColin Finck MuSessionId,
247c2c66affSColin Finck ProcessId,
248c2c66affSColin Finck Flags);
249c2c66affSColin Finck }
250c2c66affSColin Finck else if (Flags & SMP_INVALID_PATH)
251c2c66affSColin Finck {
252c2c66affSColin Finck /* An invalid image was specified, fail */
253c2c66affSColin Finck DPRINT1("SMSS: Image file (%wZ) not found\n", &FileName);
254c2c66affSColin Finck Status = STATUS_OBJECT_NAME_NOT_FOUND;
255c2c66affSColin Finck }
256c2c66affSColin Finck else
257c2c66affSColin Finck {
258*f43ce465SHermès Bélusca-Maïto /* An actual image name was present, execute it */
259c2c66affSColin Finck Status = SmpExecuteImage(&FileName,
260c2c66affSColin Finck &Directory,
261c2c66affSColin Finck CommandLine,
262c2c66affSColin Finck MuSessionId,
263c2c66affSColin Finck Flags,
264c2c66affSColin Finck NULL);
265c2c66affSColin Finck }
266c2c66affSColin Finck
267c2c66affSColin Finck /* Free all the token parameters */
268c2c66affSColin Finck if (FileName.Buffer) RtlFreeHeap(RtlGetProcessHeap(), 0, FileName.Buffer);
269c2c66affSColin Finck if (Directory.Buffer) RtlFreeHeap(RtlGetProcessHeap(), 0, Directory.Buffer);
270c2c66affSColin Finck if (Arguments.Buffer) RtlFreeHeap(RtlGetProcessHeap(), 0, Arguments.Buffer);
271c2c66affSColin Finck
272c2c66affSColin Finck /* Return to the caller */
273c2c66affSColin Finck if (!NT_SUCCESS(Status))
274c2c66affSColin Finck {
275c2c66affSColin Finck DPRINT1("SMSS: Command '%wZ' failed - Status == %x\n",
276c2c66affSColin Finck CommandLine, Status);
277c2c66affSColin Finck }
278c2c66affSColin Finck return Status;
279c2c66affSColin Finck }
280c2c66affSColin Finck
281c2c66affSColin Finck NTSTATUS
282c2c66affSColin Finck NTAPI
SmpExecuteInitialCommand(IN ULONG MuSessionId,IN PUNICODE_STRING InitialCommand,IN HANDLE InitialCommandProcess,OUT PHANDLE ReturnPid)283c2c66affSColin Finck SmpExecuteInitialCommand(IN ULONG MuSessionId,
284c2c66affSColin Finck IN PUNICODE_STRING InitialCommand,
285c2c66affSColin Finck IN HANDLE InitialCommandProcess,
286c2c66affSColin Finck OUT PHANDLE ReturnPid)
287c2c66affSColin Finck {
288c2c66affSColin Finck NTSTATUS Status;
289c2c66affSColin Finck RTL_USER_PROCESS_INFORMATION ProcessInfo;
290*f43ce465SHermès Bélusca-Maïto UNICODE_STRING Arguments, Directory, FileName;
291c2c66affSColin Finck ULONG Flags = 0;
292c2c66affSColin Finck
293c2c66affSColin Finck /* Check if we haven't yet connected to ourselves */
294c2c66affSColin Finck if (!SmApiPort)
295c2c66affSColin Finck {
296c2c66affSColin Finck /* Connect to ourselves, as a client */
297f766ca5eSHermès Bélusca-Maïto Status = SmConnectToSm(NULL, NULL, 0, &SmApiPort);
298c2c66affSColin Finck if (!NT_SUCCESS(Status))
299c2c66affSColin Finck {
300c2c66affSColin Finck DPRINT1("SMSS: Unable to connect to SM - Status == %lx\n", Status);
301c2c66affSColin Finck return Status;
302c2c66affSColin Finck }
303c2c66affSColin Finck }
304c2c66affSColin Finck
305c2c66affSColin Finck /* Parse the initial command line */
306c2c66affSColin Finck Status = SmpParseCommandLine(InitialCommand,
307c2c66affSColin Finck &Flags,
308*f43ce465SHermès Bélusca-Maïto &FileName,
309*f43ce465SHermès Bélusca-Maïto &Directory,
310c2c66affSColin Finck &Arguments);
311c2c66affSColin Finck if (Flags & SMP_INVALID_PATH)
312c2c66affSColin Finck {
313c2c66affSColin Finck /* Fail if it doesn't exist */
314*f43ce465SHermès Bélusca-Maïto DPRINT1("SMSS: Initial command image (%wZ) not found\n", &FileName);
315*f43ce465SHermès Bélusca-Maïto if (FileName.Buffer) RtlFreeHeap(RtlGetProcessHeap(), 0, FileName.Buffer);
316c2c66affSColin Finck return STATUS_OBJECT_NAME_NOT_FOUND;
317c2c66affSColin Finck }
318c2c66affSColin Finck
319c2c66affSColin Finck /* And fail if any other reason is also true */
320c2c66affSColin Finck if (!NT_SUCCESS(Status))
321c2c66affSColin Finck {
322c2c66affSColin Finck DPRINT1("SMSS: SmpParseCommandLine( %wZ ) failed - Status == %lx\n",
323c2c66affSColin Finck InitialCommand, Status);
324c2c66affSColin Finck return Status;
325c2c66affSColin Finck }
326c2c66affSColin Finck
327*f43ce465SHermès Bélusca-Maïto /* Execute the initial command, but defer its full execution */
328*f43ce465SHermès Bélusca-Maïto Status = SmpExecuteImage(&FileName,
329*f43ce465SHermès Bélusca-Maïto &Directory,
330c2c66affSColin Finck InitialCommand,
331c2c66affSColin Finck MuSessionId,
332c2c66affSColin Finck SMP_DEFERRED_FLAG,
333c2c66affSColin Finck &ProcessInfo);
334c2c66affSColin Finck
335*f43ce465SHermès Bélusca-Maïto /* Free all the token parameters */
336*f43ce465SHermès Bélusca-Maïto if (FileName.Buffer) RtlFreeHeap(RtlGetProcessHeap(), 0, FileName.Buffer);
337*f43ce465SHermès Bélusca-Maïto if (Directory.Buffer) RtlFreeHeap(RtlGetProcessHeap(), 0, Directory.Buffer);
338c2c66affSColin Finck if (Arguments.Buffer) RtlFreeHeap(RtlGetProcessHeap(), 0, Arguments.Buffer);
339c2c66affSColin Finck
340c2c66affSColin Finck /* Bail out if we couldn't execute the initial command */
341c2c66affSColin Finck if (!NT_SUCCESS(Status)) return Status;
342c2c66affSColin Finck
343c2c66affSColin Finck /* Now duplicate the handle to this process */
344c2c66affSColin Finck Status = NtDuplicateObject(NtCurrentProcess(),
345c2c66affSColin Finck ProcessInfo.ProcessHandle,
346c2c66affSColin Finck NtCurrentProcess(),
347c2c66affSColin Finck InitialCommandProcess,
348c2c66affSColin Finck PROCESS_ALL_ACCESS,
349c2c66affSColin Finck 0,
350c2c66affSColin Finck 0);
351c2c66affSColin Finck if (!NT_SUCCESS(Status))
352c2c66affSColin Finck {
353c2c66affSColin Finck /* Kill it utterly if duplication failed */
354c2c66affSColin Finck DPRINT1("SMSS: DupObject Failed. Status == %lx\n", Status);
355c2c66affSColin Finck NtTerminateProcess(ProcessInfo.ProcessHandle, Status);
356c2c66affSColin Finck NtResumeThread(ProcessInfo.ThreadHandle, NULL);
357c2c66affSColin Finck NtClose(ProcessInfo.ThreadHandle);
358c2c66affSColin Finck NtClose(ProcessInfo.ProcessHandle);
359c2c66affSColin Finck return Status;
360c2c66affSColin Finck }
361c2c66affSColin Finck
362c2c66affSColin Finck /* Return PID to the caller, and set this as the initial command PID */
363c2c66affSColin Finck if (ReturnPid) *ReturnPid = ProcessInfo.ClientId.UniqueProcess;
364c2c66affSColin Finck if (!MuSessionId) SmpInitialCommandProcessId = ProcessInfo.ClientId.UniqueProcess;
365c2c66affSColin Finck
366c2c66affSColin Finck /* Now call our server execution function to wrap up its initialization */
367c2c66affSColin Finck Status = SmExecPgm(SmApiPort, &ProcessInfo, FALSE);
368c2c66affSColin Finck if (!NT_SUCCESS(Status)) DPRINT1("SMSS: SmExecPgm Failed. Status == %lx\n", Status);
369c2c66affSColin Finck return Status;
370c2c66affSColin Finck }
371c2c66affSColin Finck
372c2c66affSColin Finck NTSTATUS
373c2c66affSColin Finck NTAPI
SmpTerminate(IN PULONG_PTR Parameters,IN ULONG ParameterMask,IN ULONG ParameterCount)374c2c66affSColin Finck SmpTerminate(IN PULONG_PTR Parameters,
375c2c66affSColin Finck IN ULONG ParameterMask,
376c2c66affSColin Finck IN ULONG ParameterCount)
377c2c66affSColin Finck {
378c2c66affSColin Finck NTSTATUS Status;
379c2c66affSColin Finck BOOLEAN Old;
380c2c66affSColin Finck ULONG Response;
381c2c66affSColin Finck
382c2c66affSColin Finck /* Give the shutdown privilege to the thread */
383c2c66affSColin Finck if (RtlAdjustPrivilege(SE_SHUTDOWN_PRIVILEGE, TRUE, TRUE, &Old) ==
384c2c66affSColin Finck STATUS_NO_TOKEN)
385c2c66affSColin Finck {
386c2c66affSColin Finck /* Thread doesn't have a token, give it to the entire process */
387c2c66affSColin Finck RtlAdjustPrivilege(SE_SHUTDOWN_PRIVILEGE, TRUE, FALSE, &Old);
388c2c66affSColin Finck }
389c2c66affSColin Finck
390c2c66affSColin Finck /* Take down the process/machine with a hard error */
391c2c66affSColin Finck Status = NtRaiseHardError(STATUS_SYSTEM_PROCESS_TERMINATED,
392c2c66affSColin Finck ParameterCount,
393c2c66affSColin Finck ParameterMask,
394c2c66affSColin Finck Parameters,
395c2c66affSColin Finck OptionShutdownSystem,
396c2c66affSColin Finck &Response);
397c2c66affSColin Finck
398c2c66affSColin Finck /* Terminate the process if the hard error didn't already */
399c2c66affSColin Finck return NtTerminateProcess(NtCurrentProcess(), Status);
400c2c66affSColin Finck }
401c2c66affSColin Finck
402c2c66affSColin Finck LONG
SmpUnhandledExceptionFilter(IN PEXCEPTION_POINTERS ExceptionInfo)403c2c66affSColin Finck SmpUnhandledExceptionFilter(IN PEXCEPTION_POINTERS ExceptionInfo)
404c2c66affSColin Finck {
405c2c66affSColin Finck ULONG_PTR Parameters[4];
406*f43ce465SHermès Bélusca-Maïto UNICODE_STRING ErrorString;
407c2c66affSColin Finck
408c2c66affSColin Finck /* Print and breakpoint into the debugger */
409c2c66affSColin Finck DbgPrint("SMSS: Unhandled exception - Status == %x IP == %p\n",
410c2c66affSColin Finck ExceptionInfo->ExceptionRecord->ExceptionCode,
411c2c66affSColin Finck ExceptionInfo->ExceptionRecord->ExceptionAddress);
412c2c66affSColin Finck DbgPrint(" Memory Address: %x Read/Write: %x\n",
413c2c66affSColin Finck ExceptionInfo->ExceptionRecord->ExceptionInformation[0],
414c2c66affSColin Finck ExceptionInfo->ExceptionRecord->ExceptionInformation[1]);
415c2c66affSColin Finck DbgBreakPoint();
416c2c66affSColin Finck
417c2c66affSColin Finck /* Build the hard error and terminate */
418*f43ce465SHermès Bélusca-Maïto RtlInitUnicodeString(&ErrorString, L"Unhandled Exception in Session Manager");
419*f43ce465SHermès Bélusca-Maïto Parameters[0] = (ULONG_PTR)&ErrorString;
420c2c66affSColin Finck Parameters[1] = ExceptionInfo->ExceptionRecord->ExceptionCode;
421c2c66affSColin Finck Parameters[2] = (ULONG_PTR)ExceptionInfo->ExceptionRecord->ExceptionAddress;
422c2c66affSColin Finck Parameters[3] = (ULONG_PTR)ExceptionInfo->ContextRecord;
423c2c66affSColin Finck SmpTerminate(Parameters, 1, RTL_NUMBER_OF(Parameters));
424c2c66affSColin Finck
425c2c66affSColin Finck /* We should never get here */
426c2c66affSColin Finck ASSERT(FALSE);
427c2c66affSColin Finck return EXCEPTION_EXECUTE_HANDLER;
428c2c66affSColin Finck }
429c2c66affSColin Finck
430c2c66affSColin Finck NTSTATUS
431c2c66affSColin Finck __cdecl
_main(IN INT argc,IN PCHAR argv[],IN PCHAR envp[],IN ULONG DebugFlag)432c2c66affSColin Finck _main(IN INT argc,
433c2c66affSColin Finck IN PCHAR argv[],
434c2c66affSColin Finck IN PCHAR envp[],
435c2c66affSColin Finck IN ULONG DebugFlag)
436c2c66affSColin Finck {
437c2c66affSColin Finck NTSTATUS Status;
438c2c66affSColin Finck KPRIORITY SetBasePriority;
439c2c66affSColin Finck ULONG_PTR Parameters[4];
440c2c66affSColin Finck HANDLE Handles[2];
441c2c66affSColin Finck PVOID State;
442c2c66affSColin Finck ULONG Flags;
443c2c66affSColin Finck PROCESS_BASIC_INFORMATION ProcessInfo;
444c2c66affSColin Finck UNICODE_STRING DbgString, InitialCommand;
445c2c66affSColin Finck
446c2c66affSColin Finck /* Make us critical */
447c2c66affSColin Finck RtlSetProcessIsCritical(TRUE, NULL, FALSE);
448c2c66affSColin Finck RtlSetThreadIsCritical(TRUE, NULL, FALSE);
449c2c66affSColin Finck
450c2c66affSColin Finck /* Raise our priority */
451c2c66affSColin Finck SetBasePriority = 11;
452c2c66affSColin Finck Status = NtSetInformationProcess(NtCurrentProcess(),
453c2c66affSColin Finck ProcessBasePriority,
454c2c66affSColin Finck (PVOID)&SetBasePriority,
455c2c66affSColin Finck sizeof(SetBasePriority));
456c2c66affSColin Finck ASSERT(NT_SUCCESS(Status));
457c2c66affSColin Finck
458c2c66affSColin Finck /* Save the debug flag if it was passed */
459c2c66affSColin Finck if (DebugFlag) SmpDebug = DebugFlag != 0;
460c2c66affSColin Finck
461c2c66affSColin Finck /* Build the hard error parameters */
462c2c66affSColin Finck Parameters[0] = (ULONG_PTR)&DbgString;
463c2c66affSColin Finck Parameters[1] = Parameters[2] = Parameters[3] = 0;
464c2c66affSColin Finck
465c2c66affSColin Finck /* Enter SEH so we can terminate correctly if anything goes wrong */
466c2c66affSColin Finck _SEH2_TRY
467c2c66affSColin Finck {
468c2c66affSColin Finck /* Initialize SMSS */
469cb8c8693SHermès Bélusca-Maïto Status = SmpInit(&InitialCommand, &Handles[0]);
470c2c66affSColin Finck if (!NT_SUCCESS(Status))
471c2c66affSColin Finck {
472c2c66affSColin Finck DPRINT1("SMSS: SmpInit return failure - Status == %x\n", Status);
473c2c66affSColin Finck RtlInitUnicodeString(&DbgString, L"Session Manager Initialization");
474c2c66affSColin Finck Parameters[1] = Status;
475c2c66affSColin Finck _SEH2_LEAVE;
476c2c66affSColin Finck }
477c2c66affSColin Finck
478c2c66affSColin Finck /* Get the global flags */
479c2c66affSColin Finck Status = NtQuerySystemInformation(SystemFlagsInformation,
480c2c66affSColin Finck &Flags,
481c2c66affSColin Finck sizeof(Flags),
482c2c66affSColin Finck NULL);
483c2c66affSColin Finck ASSERT(NT_SUCCESS(Status));
484c2c66affSColin Finck
485c2c66affSColin Finck /* Before executing the initial command check if the debug flag is on */
486c2c66affSColin Finck if (Flags & (FLG_DEBUG_INITIAL_COMMAND | FLG_DEBUG_INITIAL_COMMAND_EX))
487c2c66affSColin Finck {
488c2c66affSColin Finck /* SMSS should launch ntsd with a few parameters at this point */
489c2c66affSColin Finck DPRINT1("Global Flags Set to SMSS Debugging: Not yet supported\n");
490c2c66affSColin Finck }
491c2c66affSColin Finck
492c2c66affSColin Finck /* Execute the initial command (Winlogon.exe) */
493c2c66affSColin Finck Status = SmpExecuteInitialCommand(0, &InitialCommand, &Handles[1], NULL);
494c2c66affSColin Finck if (!NT_SUCCESS(Status))
495c2c66affSColin Finck {
496c2c66affSColin Finck /* Fail and raise a hard error */
497c2c66affSColin Finck DPRINT1("SMSS: Execute Initial Command failed\n");
498c2c66affSColin Finck RtlInitUnicodeString(&DbgString,
499c2c66affSColin Finck L"Session Manager ExecuteInitialCommand");
500c2c66affSColin Finck Parameters[1] = Status;
501c2c66affSColin Finck _SEH2_LEAVE;
502c2c66affSColin Finck }
503c2c66affSColin Finck
504c2c66affSColin Finck /* Check if we're already attached to a session */
505c2c66affSColin Finck Status = SmpAcquirePrivilege(SE_LOAD_DRIVER_PRIVILEGE, &State);
506c2c66affSColin Finck if (AttachedSessionId != -1)
507c2c66affSColin Finck {
508c2c66affSColin Finck /* Detach from it, we should be in no session right now */
509c2c66affSColin Finck Status = NtSetSystemInformation(SystemSessionDetach,
510c2c66affSColin Finck &AttachedSessionId,
511c2c66affSColin Finck sizeof(AttachedSessionId));
512c2c66affSColin Finck ASSERT(NT_SUCCESS(Status));
513c2c66affSColin Finck AttachedSessionId = -1;
514c2c66affSColin Finck }
515c2c66affSColin Finck SmpReleasePrivilege(State);
516c2c66affSColin Finck
517c2c66affSColin Finck /* Wait on either CSRSS or Winlogon to die */
518c2c66affSColin Finck Status = NtWaitForMultipleObjects(RTL_NUMBER_OF(Handles),
519c2c66affSColin Finck Handles,
520c2c66affSColin Finck WaitAny,
521c2c66affSColin Finck FALSE,
522c2c66affSColin Finck NULL);
523c2c66affSColin Finck if (Status == STATUS_WAIT_0)
524c2c66affSColin Finck {
525c2c66affSColin Finck /* CSRSS is dead, get exit code and prepare for the hard error */
526c2c66affSColin Finck RtlInitUnicodeString(&DbgString, L"Windows SubSystem");
527c2c66affSColin Finck Status = NtQueryInformationProcess(Handles[0],
528c2c66affSColin Finck ProcessBasicInformation,
529c2c66affSColin Finck &ProcessInfo,
530c2c66affSColin Finck sizeof(ProcessInfo),
531c2c66affSColin Finck NULL);
532c2c66affSColin Finck DPRINT1("SMSS: Windows subsystem terminated when it wasn't supposed to.\n");
533c2c66affSColin Finck }
534c2c66affSColin Finck else
535c2c66affSColin Finck {
536c2c66affSColin Finck /* The initial command is dead or we have another failure */
537c2c66affSColin Finck RtlInitUnicodeString(&DbgString, L"Windows Logon Process");
538c2c66affSColin Finck if (Status == STATUS_WAIT_1)
539c2c66affSColin Finck {
540c2c66affSColin Finck /* Winlogon.exe got terminated, get its exit code */
541c2c66affSColin Finck Status = NtQueryInformationProcess(Handles[1],
542c2c66affSColin Finck ProcessBasicInformation,
543c2c66affSColin Finck &ProcessInfo,
544c2c66affSColin Finck sizeof(ProcessInfo),
545c2c66affSColin Finck NULL);
546c2c66affSColin Finck }
547c2c66affSColin Finck else
548c2c66affSColin Finck {
549c2c66affSColin Finck /* Something else satisfied our wait, so set the wait status */
550c2c66affSColin Finck ProcessInfo.ExitStatus = Status;
551c2c66affSColin Finck Status = STATUS_SUCCESS;
552c2c66affSColin Finck }
553c2c66affSColin Finck DPRINT1("SMSS: Initial command '%wZ' terminated when it wasn't supposed to.\n",
554c2c66affSColin Finck &InitialCommand);
555c2c66affSColin Finck }
556c2c66affSColin Finck
557c2c66affSColin Finck /* Check if NtQueryInformationProcess was successful */
558c2c66affSColin Finck if (NT_SUCCESS(Status))
559c2c66affSColin Finck {
560c2c66affSColin Finck /* Then we must have a valid exit status in the structure, use it */
561c2c66affSColin Finck Parameters[1] = ProcessInfo.ExitStatus;
562c2c66affSColin Finck }
563c2c66affSColin Finck else
564c2c66affSColin Finck {
565c2c66affSColin Finck /* We really don't know what happened, so set a generic error */
566c2c66affSColin Finck Parameters[1] = STATUS_UNSUCCESSFUL;
567c2c66affSColin Finck }
568c2c66affSColin Finck }
569c2c66affSColin Finck _SEH2_EXCEPT(SmpUnhandledExceptionFilter(_SEH2_GetExceptionInformation()))
570c2c66affSColin Finck {
571c2c66affSColin Finck /* The filter should never return here */
572c2c66affSColin Finck ASSERT(FALSE);
573c2c66affSColin Finck }
574c2c66affSColin Finck _SEH2_END;
575c2c66affSColin Finck
576c2c66affSColin Finck /* Something in the init loop failed, terminate SMSS */
577c2c66affSColin Finck return SmpTerminate(Parameters, 1, RTL_NUMBER_OF(Parameters));
578c2c66affSColin Finck }
579c2c66affSColin Finck
580c2c66affSColin Finck /* EOF */
581