[TRANSLATION][CLIPBRD] Italian translation implemented (#344)
[reactos.git] / base / system / smss / smss.c
index e6a5c21..28bd66f 100644 (file)
 /*
- * PROJECT:         ReactOS Session Manager
- * LICENSE:         GPL v2 or later - See COPYING in the top level directory
+ * PROJECT:         ReactOS Windows-Compatible Session Manager
+ * LICENSE:         BSD 2-Clause License
  * FILE:            base/system/smss/smss.c
- * PURPOSE:         Initialization routine.
- * PROGRAMMERS:     ReactOS Development Team
+ * PURPOSE:         Main SMSS Code
+ * PROGRAMMERS:     Alex Ionescu
  */
 
-/* INCLUDES ******************************************************************/
+/* INCLUDES *******************************************************************/
+
 #include "smss.h"
-#include <reactos/buildno.h>
+
+#include <pseh/pseh2.h>
 
 #define NDEBUG
 #include <debug.h>
 
-ULONG SmSsProcessId = 0;
+/* GLOBALS ********************************************************************/
+
+UNICODE_STRING SmpSystemRoot;
+ULONG AttachedSessionId = -1;
+BOOLEAN SmpDebug, SmpEnableDots;
+HANDLE SmApiPort;
+HANDLE SmpInitialCommandProcessId;
+
+/* FUNCTIONS ******************************************************************/
+
+/* GCC's incompetence strikes again */
+VOID
+sprintf_nt(IN PCHAR Buffer,
+           IN PCHAR Format,
+           IN ...)
+{
+    va_list ap;
+    va_start(ap, Format);
+    sprintf(Buffer, Format, ap);
+    va_end(ap);
+}
+
+NTSTATUS
+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)
+{
+    PRTL_USER_PROCESS_INFORMATION ProcessInfo;
+    NTSTATUS Status;
+    RTL_USER_PROCESS_INFORMATION LocalProcessInfo;
+    PRTL_USER_PROCESS_PARAMETERS ProcessParameters;
+
+    /* Use the input process information if we have it, otherwise use local */
+    ProcessInfo = ProcessInformation;
+    if (!ProcessInfo) ProcessInfo = &LocalProcessInfo;
+
+    /* Create parameters for the target process */
+    Status = RtlCreateProcessParameters(&ProcessParameters,
+                                        FileName,
+                                        SmpDefaultLibPath.Length ?
+                                        &SmpDefaultLibPath : NULL,
+                                        Directory,
+                                        CommandLine,
+                                        SmpDefaultEnvironment,
+                                        NULL,
+                                        NULL,
+                                        NULL,
+                                        0);
+    if (!NT_SUCCESS(Status))
+    {
+        /* This is a pretty bad failure. ASSERT on checked builds and exit */
+        ASSERTMSG("RtlCreateProcessParameters", NT_SUCCESS(Status));
+        DPRINT1("SMSS: RtlCreateProcessParameters failed for %wZ - Status == %lx\n",
+                FileName, Status);
+        return Status;
+    }
+
+    /* Set the size field as required */
+    ProcessInfo->Size = sizeof(RTL_USER_PROCESS_INFORMATION);
+
+    /* Check if the debug flag was requested */
+    if (Flags & SMP_DEBUG_FLAG)
+    {
+        /* Write it in the process parameters */
+        ProcessParameters->DebugFlags = 1;
+    }
+    else
+    {
+        /* Otherwise inherit the flag that was passed to SMSS itself */
+        ProcessParameters->DebugFlags = SmpDebug;
+    }
+
+    /* Subsystems get the first 1MB of memory reserved for DOS/IVT purposes */
+    if (Flags & SMP_SUBSYSTEM_FLAG)
+    {
+        ProcessParameters->Flags |= RTL_USER_PROCESS_PARAMETERS_RESERVE_1MB;
+    }
+
+    /* And always force NX for anything that SMSS launches */
+    ProcessParameters->Flags |= RTL_USER_PROCESS_PARAMETERS_NX;
+
+    /* Now create the process */
+    Status = RtlCreateUserProcess(FileName,
+                                  OBJ_CASE_INSENSITIVE,
+                                  ProcessParameters,
+                                  NULL,
+                                  NULL,
+                                  NULL,
+                                  FALSE,
+                                  NULL,
+                                  NULL,
+                                  ProcessInfo);
+    RtlDestroyProcessParameters(ProcessParameters);
+    if (!NT_SUCCESS(Status))
+    {
+        /* If we couldn't create it, fail back to the caller */
+        DPRINT1("SMSS: Failed load of %wZ - Status  == %lx\n",
+                FileName, Status);
+        return Status;
+    }
+
+    /* Associate a session with this process */
+    Status = SmpSetProcessMuSessionId(ProcessInfo->ProcessHandle, MuSessionId);
+
+    /* If the application is deferred (suspended), there's nothing to do */
+    if (Flags & SMP_DEFERRED_FLAG) return Status;
+
+    /* Otherwise, get ready to start it, but make sure it's a native app */
+    if (ProcessInfo->ImageInformation.SubSystemType == IMAGE_SUBSYSTEM_NATIVE)
+    {
+        /* Resume it */
+        NtResumeThread(ProcessInfo->ThreadHandle, NULL);
+        if (!(Flags & SMP_ASYNC_FLAG))
+        {
+            /* Block on it unless Async was requested */
+            NtWaitForSingleObject(ProcessInfo->ThreadHandle, FALSE, NULL);
+        }
+
+        /* It's up and running now, close our handles */
+        NtClose(ProcessInfo->ThreadHandle);
+        NtClose(ProcessInfo->ProcessHandle);
+    }
+    else
+    {
+        /* This image is invalid, so kill it, close our handles, and fail */
+        Status = STATUS_INVALID_IMAGE_FORMAT;
+        NtTerminateProcess(ProcessInfo->ProcessHandle, Status);
+        NtWaitForSingleObject(ProcessInfo->ThreadHandle, 0, 0);
+        NtClose(ProcessInfo->ThreadHandle);
+        NtClose(ProcessInfo->ProcessHandle);
+        DPRINT1("SMSS: Not an NT image - %wZ\n", FileName);
+    }
+
+    /* Return the outcome of the process create */
+    return Status;
+}
+
+NTSTATUS
+NTAPI
+SmpInvokeAutoChk(IN PUNICODE_STRING FileName,
+                 IN PUNICODE_STRING Directory,
+                 IN PUNICODE_STRING Arguments,
+                 IN ULONG Flags)
+{
+    ANSI_STRING MessageString;
+    CHAR MessageBuffer[256];
+    UNICODE_STRING Destination;
+    WCHAR Buffer[1024];
+    BOOLEAN BootState, BootOkay, ShutdownOkay;
+
+    /* Check if autochk should show dots (if the user booted with /SOS) */
+    if (SmpQueryRegistrySosOption()) SmpEnableDots = FALSE;
+
+    /* Make sure autochk was actually found */
+    if (Flags & SMP_INVALID_PATH)
+    {
+        /* It wasn't, so create an error message to print on the screen */
+        sprintf_nt(MessageBuffer,
+                   "%wZ program not found - skipping AUTOCHECK\r\n",
+                   FileName);
+        RtlInitAnsiString(&MessageString, MessageBuffer);
+        if (NT_SUCCESS(RtlAnsiStringToUnicodeString(&Destination,
+                                                    &MessageString,
+                                                    TRUE)))
+        {
+            /* And show it */
+            NtDisplayString(&Destination);
+            RtlFreeUnicodeString(&Destination);
+        }
+    }
+    else
+    {
+        /* Autochk is there, so record the BSD state */
+        BootState = SmpSaveAndClearBootStatusData(&BootOkay, &ShutdownOkay);
+
+        /* Build the path to autochk and place its arguments */
+        RtlInitEmptyUnicodeString(&Destination, Buffer, sizeof(Buffer));
+        RtlAppendUnicodeStringToString(&Destination, FileName);
+        RtlAppendUnicodeToString(&Destination, L" ");
+        RtlAppendUnicodeStringToString(&Destination, Arguments);
+
+        /* Execute it */
+        SmpExecuteImage(FileName,
+                        Directory,
+                        &Destination,
+                        0,
+                        Flags & ~SMP_AUTOCHK_FLAG,
+                        NULL);
+
+        /* Restore the BSD state */
+        if (BootState) SmpRestoreBootStatusData(BootOkay, ShutdownOkay);
+    }
+
+    /* We're all done! */
+    return STATUS_SUCCESS;
+}
+
+NTSTATUS
+NTAPI
+SmpExecuteCommand(IN PUNICODE_STRING CommandLine,
+                  IN ULONG MuSessionId,
+                  OUT PHANDLE ProcessId,
+                  IN ULONG Flags)
+{
+    NTSTATUS Status;
+    UNICODE_STRING Arguments, Directory, FileName;
+
+    /* There's no longer a debugging subsystem */
+    if (Flags & SMP_DEBUG_FLAG) return STATUS_SUCCESS;
+
+    /* Parse the command line to see what execution flags are requested */
+    Status = SmpParseCommandLine(CommandLine,
+                                 &Flags,
+                                 &FileName,
+                                 &Directory,
+                                 &Arguments);
+    if (!NT_SUCCESS(Status))
+    {
+        /* Fail if we couldn't do that */
+        DPRINT1("SMSS: SmpParseCommandLine( %wZ ) failed - Status == %lx\n",
+                CommandLine, Status);
+        return Status;
+    }
+
+    /* Check if autochk is requested */
+    if (Flags & SMP_AUTOCHK_FLAG)
+    {
+        /* Run it */
+        Status = SmpInvokeAutoChk(&FileName, &Directory, &Arguments, Flags);
+    }
+    else if (Flags & SMP_SUBSYSTEM_FLAG)
+    {
+        Status = SmpLoadSubSystem(&FileName,
+                                  &Directory,
+                                  CommandLine,
+                                  MuSessionId,
+                                  ProcessId,
+                                  Flags);
+    }
+    else if (Flags & SMP_INVALID_PATH)
+    {
+        /* An invalid image was specified, fail */
+        DPRINT1("SMSS: Image file (%wZ) not found\n", &FileName);
+        Status = STATUS_OBJECT_NAME_NOT_FOUND;
+    }
+    else
+    {
+        /* An actual image name was present -- execute it */
+        Status = SmpExecuteImage(&FileName,
+                                 &Directory,
+                                 CommandLine,
+                                 MuSessionId,
+                                 Flags,
+                                 NULL);
+    }
+
+    /* Free all the token parameters */
+    if (FileName.Buffer) RtlFreeHeap(RtlGetProcessHeap(), 0, FileName.Buffer);
+    if (Directory.Buffer) RtlFreeHeap(RtlGetProcessHeap(), 0, Directory.Buffer);
+    if (Arguments.Buffer) RtlFreeHeap(RtlGetProcessHeap(), 0, Arguments.Buffer);
 
-/* Native image's entry point */
+    /* Return to the caller */
+    if (!NT_SUCCESS(Status))
+    {
+        DPRINT1("SMSS: Command '%wZ' failed - Status == %x\n",
+                CommandLine, Status);
+    }
+    return Status;
+}
 
-NTSTATUS __cdecl _main(int argc,
-                       char *argv[],
-                       char *envp[],
-                       ULONG DebugFlag)
+NTSTATUS
+NTAPI
+SmpExecuteInitialCommand(IN ULONG MuSessionId,
+                         IN PUNICODE_STRING InitialCommand,
+                         IN HANDLE InitialCommandProcess,
+                         OUT PHANDLE ReturnPid)
 {
-  NTSTATUS Status = STATUS_SUCCESS;
-  PROCESS_BASIC_INFORMATION PBI = {0};
-
-  /* Lookup yourself */
-  Status = NtQueryInformationProcess (NtCurrentProcess(),
-                                     ProcessBasicInformation,
-                                     & PBI,
-                                     sizeof PBI,
-                                     NULL);
-  if(NT_SUCCESS(Status))
-  {
-         SmSsProcessId = (ULONG) PBI.UniqueProcessId;
-  }
-  /* Initialize the system */
-  Status = InitSessionManager();
-  /* Watch required subsystems TODO */
-#if 0
-  if (!NT_SUCCESS(Status))
-    {
-      int i;
-      for (i=0; i < (sizeof Children / sizeof Children[0]); i++)
-      {
-        if (Children[i])
+    NTSTATUS Status;
+    RTL_USER_PROCESS_INFORMATION ProcessInfo;
+    UNICODE_STRING Arguments, ImageFileDirectory, ImageFileName;
+    ULONG Flags = 0;
+
+    /* Check if we haven't yet connected to ourselves */
+    if (!SmApiPort)
+    {
+        /* Connect to ourselves, as a client */
+        Status = SmConnectToSm(0, 0, 0, &SmApiPort);
+        if (!NT_SUCCESS(Status))
         {
-          NtTerminateProcess(Children[i],0);
+            DPRINT1("SMSS: Unable to connect to SM - Status == %lx\n", Status);
+            return Status;
         }
-      }
-      DPRINT1("SM: Initialization failed!\n");
-      goto ByeBye;
     }
 
-  Status = NtWaitForMultipleObjects(((LONG) sizeof(Children) / sizeof(HANDLE)),
-                                   Children,
-                                   WaitAny,
-                                   TRUE,       /* alertable */
-                                   NULL);      /* NULL for infinite */
-  if (!NT_SUCCESS(Status))
+    /* Parse the initial command line */
+    Status = SmpParseCommandLine(InitialCommand,
+                                 &Flags,
+                                 &ImageFileName,
+                                 &ImageFileDirectory,
+                                 &Arguments);
+    if (Flags & SMP_INVALID_PATH)
+    {
+        /* Fail if it doesn't exist */
+        DPRINT1("SMSS: Initial command image (%wZ) not found\n", &ImageFileName);
+        if (ImageFileName.Buffer) RtlFreeHeap(RtlGetProcessHeap(), 0, ImageFileName.Buffer);
+        return STATUS_OBJECT_NAME_NOT_FOUND;
+    }
+
+    /* And fail if any other reason is also true */
+    if (!NT_SUCCESS(Status))
+    {
+        DPRINT1("SMSS: SmpParseCommandLine( %wZ ) failed - Status == %lx\n",
+                InitialCommand, Status);
+        return Status;
+    }
+
+    /* Execute the initial command -- but defer its full execution */
+    Status = SmpExecuteImage(&ImageFileName,
+                             &ImageFileDirectory,
+                             InitialCommand,
+                             MuSessionId,
+                             SMP_DEFERRED_FLAG,
+                             &ProcessInfo);
+
+    /* Free any buffers we had lying around */
+    if (ImageFileName.Buffer)
+    {
+        RtlFreeHeap(RtlGetProcessHeap(), 0, ImageFileName.Buffer);
+    }
+    if (ImageFileDirectory.Buffer)
+    {
+        RtlFreeHeap(RtlGetProcessHeap(), 0, ImageFileDirectory.Buffer);
+    }
+    if (Arguments.Buffer) RtlFreeHeap(RtlGetProcessHeap(), 0, Arguments.Buffer);
+
+    /* Bail out if we couldn't execute the initial command */
+    if (!NT_SUCCESS(Status)) return Status;
+
+    /* Now duplicate the handle to this process */
+    Status = NtDuplicateObject(NtCurrentProcess(),
+                               ProcessInfo.ProcessHandle,
+                               NtCurrentProcess(),
+                               InitialCommandProcess,
+                               PROCESS_ALL_ACCESS,
+                               0,
+                               0);
+    if (!NT_SUCCESS(Status))
     {
-      DPRINT1("SM: NtWaitForMultipleObjects failed! (Status=0x%08lx)\n", Status);
+        /* Kill it utterly if duplication failed */
+        DPRINT1("SMSS: DupObject Failed. Status == %lx\n", Status);
+        NtTerminateProcess(ProcessInfo.ProcessHandle, Status);
+        NtResumeThread(ProcessInfo.ThreadHandle, NULL);
+        NtClose(ProcessInfo.ThreadHandle);
+        NtClose(ProcessInfo.ProcessHandle);
+        return Status;
     }
-  else
+
+    /* Return PID to the caller, and set this as the initial command PID */
+    if (ReturnPid) *ReturnPid = ProcessInfo.ClientId.UniqueProcess;
+    if (!MuSessionId) SmpInitialCommandProcessId = ProcessInfo.ClientId.UniqueProcess;
+
+    /* Now call our server execution function to wrap up its initialization */
+    Status = SmExecPgm(SmApiPort, &ProcessInfo, FALSE);
+    if (!NT_SUCCESS(Status)) DPRINT1("SMSS: SmExecPgm Failed. Status == %lx\n", Status);
+    return Status;
+}
+
+NTSTATUS
+NTAPI
+SmpTerminate(IN PULONG_PTR Parameters,
+             IN ULONG ParameterMask,
+             IN ULONG ParameterCount)
+{
+    NTSTATUS Status;
+    BOOLEAN Old;
+    ULONG Response;
+
+    /* Give the shutdown privilege to the thread */
+    if (RtlAdjustPrivilege(SE_SHUTDOWN_PRIVILEGE, TRUE, TRUE, &Old) ==
+        STATUS_NO_TOKEN)
     {
-      DPRINT1("SM: Process terminated!\n");
+        /* Thread doesn't have a token, give it to the entire process */
+        RtlAdjustPrivilege(SE_SHUTDOWN_PRIVILEGE, TRUE, FALSE, &Old);
     }
 
-ByeBye:
-  /* Raise a hard error (crash the system/BSOD) */
-  NtRaiseHardError(STATUS_SYSTEM_PROCESS_TERMINATED,
-                  0,0,0,0,0);
+    /* Take down the process/machine with a hard error */
+    Status = NtRaiseHardError(STATUS_SYSTEM_PROCESS_TERMINATED,
+                              ParameterCount,
+                              ParameterMask,
+                              Parameters,
+                              OptionShutdownSystem,
+                              &Response);
+
+    /* Terminate the process if the hard error didn't already */
+    return NtTerminateProcess(NtCurrentProcess(), Status);
+}
+
+LONG
+SmpUnhandledExceptionFilter(IN PEXCEPTION_POINTERS ExceptionInfo)
+{
+    ULONG_PTR Parameters[4];
+    UNICODE_STRING DestinationString;
+
+    /* Print and breakpoint into the debugger */
+    DbgPrint("SMSS: Unhandled exception - Status == %x  IP == %p\n",
+             ExceptionInfo->ExceptionRecord->ExceptionCode,
+             ExceptionInfo->ExceptionRecord->ExceptionAddress);
+    DbgPrint("      Memory Address: %x  Read/Write: %x\n",
+             ExceptionInfo->ExceptionRecord->ExceptionInformation[0],
+             ExceptionInfo->ExceptionRecord->ExceptionInformation[1]);
+    DbgBreakPoint();
+
+    /* Build the hard error and terminate */
+    RtlInitUnicodeString(&DestinationString, L"Unhandled Exception in Session Manager");
+    Parameters[0] = (ULONG_PTR)&DestinationString;
+    Parameters[1] = ExceptionInfo->ExceptionRecord->ExceptionCode;
+    Parameters[2] = (ULONG_PTR)ExceptionInfo->ExceptionRecord->ExceptionAddress;
+    Parameters[3] = (ULONG_PTR)ExceptionInfo->ContextRecord;
+    SmpTerminate(Parameters, 1, RTL_NUMBER_OF(Parameters));
+
+    /* We should never get here */
+    ASSERT(FALSE);
+    return EXCEPTION_EXECUTE_HANDLER;
+}
+
+NTSTATUS
+__cdecl
+_main(IN INT argc,
+      IN PCHAR argv[],
+      IN PCHAR envp[],
+      IN ULONG DebugFlag)
+{
+    NTSTATUS Status;
+    KPRIORITY SetBasePriority;
+    ULONG_PTR Parameters[4];
+    HANDLE Handles[2];
+    PVOID State;
+    ULONG Flags;
+    PROCESS_BASIC_INFORMATION ProcessInfo;
+    UNICODE_STRING DbgString, InitialCommand;
+
+    /* Make us critical */
+    RtlSetProcessIsCritical(TRUE, NULL, FALSE);
+    RtlSetThreadIsCritical(TRUE, NULL, FALSE);
+
+    /* Raise our priority */
+    SetBasePriority = 11;
+    Status = NtSetInformationProcess(NtCurrentProcess(),
+                                     ProcessBasePriority,
+                                     (PVOID)&SetBasePriority,
+                                     sizeof(SetBasePriority));
+    ASSERT(NT_SUCCESS(Status));
+
+    /* Save the debug flag if it was passed */
+    if (DebugFlag) SmpDebug = DebugFlag != 0;
+
+    /* Build the hard error parameters */
+    Parameters[0] = (ULONG_PTR)&DbgString;
+    Parameters[1] = Parameters[2] = Parameters[3] = 0;
+
+    /* Enter SEH so we can terminate correctly if anything goes wrong */
+    _SEH2_TRY
+    {
+        /* Initialize SMSS */
+        Status = SmpInit(&InitialCommand, Handles);
+        if (!NT_SUCCESS(Status))
+        {
+            DPRINT1("SMSS: SmpInit return failure - Status == %x\n", Status);
+            RtlInitUnicodeString(&DbgString, L"Session Manager Initialization");
+            Parameters[1] = Status;
+            _SEH2_LEAVE;
+        }
+
+        /* Get the global flags */
+        Status = NtQuerySystemInformation(SystemFlagsInformation,
+                                          &Flags,
+                                          sizeof(Flags),
+                                          NULL);
+        ASSERT(NT_SUCCESS(Status));
+
+        /* Before executing the initial command check if the debug flag is on */
+        if (Flags & (FLG_DEBUG_INITIAL_COMMAND | FLG_DEBUG_INITIAL_COMMAND_EX))
+        {
+            /* SMSS should launch ntsd with a few parameters at this point */
+            DPRINT1("Global Flags Set to SMSS Debugging: Not yet supported\n");
+        }
+
+        /* Execute the initial command (Winlogon.exe) */
+        Status = SmpExecuteInitialCommand(0, &InitialCommand, &Handles[1], NULL);
+        if (!NT_SUCCESS(Status))
+        {
+            /* Fail and raise a hard error */
+            DPRINT1("SMSS: Execute Initial Command failed\n");
+            RtlInitUnicodeString(&DbgString,
+                                 L"Session Manager ExecuteInitialCommand");
+            Parameters[1] = Status;
+            _SEH2_LEAVE;
+        }
+
+        /*  Check if we're already attached to a session */
+        Status = SmpAcquirePrivilege(SE_LOAD_DRIVER_PRIVILEGE, &State);
+        if (AttachedSessionId != -1)
+        {
+            /* Detach from it, we should be in no session right now */
+            Status = NtSetSystemInformation(SystemSessionDetach,
+                                            &AttachedSessionId,
+                                            sizeof(AttachedSessionId));
+            ASSERT(NT_SUCCESS(Status));
+            AttachedSessionId = -1;
+        }
+        SmpReleasePrivilege(State);
+
+        /* Wait on either CSRSS or Winlogon to die */
+        Status = NtWaitForMultipleObjects(RTL_NUMBER_OF(Handles),
+                                          Handles,
+                                          WaitAny,
+                                          FALSE,
+                                          NULL);
+        if (Status == STATUS_WAIT_0)
+        {
+            /* CSRSS is dead, get exit code and prepare for the hard error */
+            RtlInitUnicodeString(&DbgString, L"Windows SubSystem");
+            Status = NtQueryInformationProcess(Handles[0],
+                                               ProcessBasicInformation,
+                                               &ProcessInfo,
+                                               sizeof(ProcessInfo),
+                                               NULL);
+            DPRINT1("SMSS: Windows subsystem terminated when it wasn't supposed to.\n");
+        }
+        else
+        {
+            /* The initial command is dead or we have another failure */
+            RtlInitUnicodeString(&DbgString, L"Windows Logon Process");
+            if (Status == STATUS_WAIT_1)
+            {
+                /* Winlogon.exe got terminated, get its exit code */
+                Status = NtQueryInformationProcess(Handles[1],
+                                                   ProcessBasicInformation,
+                                                   &ProcessInfo,
+                                                   sizeof(ProcessInfo),
+                                                   NULL);
+            }
+            else
+            {
+                /* Something else satisfied our wait, so set the wait status */
+                ProcessInfo.ExitStatus = Status;
+                Status = STATUS_SUCCESS;
+            }
+            DPRINT1("SMSS: Initial command '%wZ' terminated when it wasn't supposed to.\n",
+                    &InitialCommand);
+        }
+
+        /* Check if NtQueryInformationProcess was successful */
+        if (NT_SUCCESS(Status))
+        {
+            /* Then we must have a valid exit status in the structure, use it */
+            Parameters[1] = ProcessInfo.ExitStatus;
+        }
+        else
+        {
+            /* We really don't know what happened, so set a generic error */
+            Parameters[1] = STATUS_UNSUCCESSFUL;
+        }
+    }
+    _SEH2_EXCEPT(SmpUnhandledExceptionFilter(_SEH2_GetExceptionInformation()))
+    {
+        /* The filter should never return here */
+        ASSERT(FALSE);
+    }
+    _SEH2_END;
 
-//   NtTerminateProcess(NtCurrentProcess(), 0);
-#endif
-       return NtTerminateThread(NtCurrentThread(), Status);
+    /* Something in the init loop failed, terminate SMSS */
+    return SmpTerminate(Parameters, 1, RTL_NUMBER_OF(Parameters));
 }
 
 /* EOF */