Git conversion: Make reactos the root directory, move rosapps, rostests, wallpapers...
[reactos.git] / reactos / base / system / smss / smss.c
diff --git a/reactos/base/system/smss/smss.c b/reactos/base/system/smss/smss.c
deleted file mode 100644 (file)
index 28bd66f..0000000
+++ /dev/null
@@ -1,597 +0,0 @@
-/*
- * PROJECT:         ReactOS Windows-Compatible Session Manager
- * LICENSE:         BSD 2-Clause License
- * FILE:            base/system/smss/smss.c
- * PURPOSE:         Main SMSS Code
- * PROGRAMMERS:     Alex Ionescu
- */
-
-/* INCLUDES *******************************************************************/
-
-#include "smss.h"
-
-#include <pseh/pseh2.h>
-
-#define NDEBUG
-#include <debug.h>
-
-/* 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);
-
-    /* Return to the caller */
-    if (!NT_SUCCESS(Status))
-    {
-        DPRINT1("SMSS: Command '%wZ' failed - Status == %x\n",
-                CommandLine, Status);
-    }
-    return Status;
-}
-
-NTSTATUS
-NTAPI
-SmpExecuteInitialCommand(IN ULONG MuSessionId,
-                         IN PUNICODE_STRING InitialCommand,
-                         IN HANDLE InitialCommandProcess,
-                         OUT PHANDLE ReturnPid)
-{
-    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))
-        {
-            DPRINT1("SMSS: Unable to connect to SM - Status == %lx\n", Status);
-            return 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))
-    {
-        /* 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;
-    }
-
-    /* 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)
-    {
-        /* Thread doesn't have a token, give it to the entire process */
-        RtlAdjustPrivilege(SE_SHUTDOWN_PRIVILEGE, TRUE, FALSE, &Old);
-    }
-
-    /* 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;
-
-    /* Something in the init loop failed, terminate SMSS */
-    return SmpTerminate(Parameters, 1, RTL_NUMBER_OF(Parameters));
-}
-
-/* EOF */