Merge 25584, 25588.
[reactos.git] / reactos / ntoskrnl / ex / init.c
index 07b4d77..6673931 100644 (file)
@@ -1,20 +1,23 @@
 /*
- * COPYRIGHT:       See COPYING in the top level directory
- * PROJECT:         ReactOS kernel
+ * PROJECT:         ReactOS Kernel
+ * LICENSE:         GPL - See COPYING in the top level directory
  * FILE:            ntoskrnl/ex/init.c
- * PURPOSE:         Executive initalization
- *
- * PROGRAMMERS:     Alex Ionescu (alex@relsoft.net) - Added ExpInitializeExecutive
- *                                                    and optimized/cleaned it.
- *                  Eric Kohl (ekohl@abo.rhein-zeitung.de)
+ * PURPOSE:         Executive Initialization Code
+ * PROGRAMMERS:     Alex Ionescu (alex.ionescu@reactos.org)
+ *                  Eric Kohl (ekohl@rz-online.de)
  */
 
+/* INCLUDES ******************************************************************/
+
 #include <ntoskrnl.h>
 #define NDEBUG
 #include <internal/debug.h>
 
 /* DATA **********************************************************************/
 
+/* HACK */
+extern BOOLEAN KiClockSetupComplete;
+
 #define BUILD_OSCSDVERSION(major, minor) (((major & 0xFF) << 8) | (minor & 0xFF))
 
 /* NT Version Info */
@@ -25,17 +28,14 @@ ULONG NtBuildNumber = KERNEL_VERSION_BUILD;
 ULONG NtGlobalFlag;
 ULONG ExSuiteMask;
 
-extern LOADER_MODULE KeLoaderModules[64];
-extern ULONG KeLoaderModuleCount;
-extern ULONG KiServiceLimit;
-BOOLEAN NoGuiBoot = FALSE;
-
 /* Init flags and settings */
 ULONG ExpInitializationPhase;
 BOOLEAN ExpInTextModeSetup;
 BOOLEAN IoRemoteBootClient;
 ULONG InitSafeBootMode;
 
+BOOLEAN NoGuiBoot = FALSE;
+
 /* NT Boot Path */
 UNICODE_STRING NtSystemRoot;
 
@@ -45,204 +45,264 @@ ULONG ExpAnsiCodePageDataOffset, ExpOemCodePageDataOffset;
 ULONG ExpUnicodeCaseTableDataOffset;
 NLSTABLEINFO ExpNlsTableInfo;
 ULONG ExpNlsTableSize;
+PVOID ExpNlsSectionPointer;
 
 /* FUNCTIONS ****************************************************************/
 
-static
-VOID
-INIT_FUNCTION
-InitSystemSharedUserPage (IN PLOADER_PARAMETER_BLOCK LoaderBlock)
+NTSTATUS
+NTAPI
+ExpCreateSystemRootLink(IN PLOADER_PARAMETER_BLOCK LoaderBlock)
 {
-    UNICODE_STRING ArcDeviceName;
-    UNICODE_STRING ArcName;
-    UNICODE_STRING BootPath;
-    UNICODE_STRING DriveDeviceName;
-    UNICODE_STRING DriveName;
-    WCHAR DriveNameBuffer[20];
-    PWCHAR ArcNameBuffer;
-    NTSTATUS Status;
-    ULONG Length;
+    UNICODE_STRING LinkName;
     OBJECT_ATTRIBUTES ObjectAttributes;
-    HANDLE Handle;
-    ULONG i;
-    BOOLEAN BootDriveFound = FALSE;
+    HANDLE LinkHandle;
+    NTSTATUS Status;
+    ANSI_STRING AnsiName;
+    CHAR Buffer[256];
+    ANSI_STRING TargetString;
+    UNICODE_STRING TargetName;
 
-    /* Set the Product Type */
-    SharedUserData->NtProductType = NtProductWinNt;
-    SharedUserData->ProductTypeIsValid = TRUE;
+    /* Initialize the ArcName tree */
+    RtlInitUnicodeString(&LinkName, L"\\ArcName");
+    InitializeObjectAttributes(&ObjectAttributes,
+                               &LinkName,
+                               OBJ_CASE_INSENSITIVE | OBJ_PERMANENT,
+                               NULL,
+                               SePublicDefaultSd);
 
-    /*
-     * Retrieve the current dos system path
-     * (e.g.: C:\reactos) from the given arc path
-     * (e.g.: multi(0)disk(0)rdisk(0)partititon(1)\reactos)
-     * Format: "<arc_name>\<path> [options...]"
-     */
+    /* Create it */
+    Status = NtCreateDirectoryObject(&LinkHandle,
+                                     DIRECTORY_ALL_ACCESS,
+                                     &ObjectAttributes);
+    if (!NT_SUCCESS(Status))
+    {
+        KeBugCheckEx(SYMBOLIC_INITIALIZATION_FAILED, Status, 1, 0, 0);
+    }
 
-    RtlCreateUnicodeStringFromAsciiz(&BootPath, LoaderBlock->NtBootPathName);
+    /* Close the LinkHandle */
+    NtClose(LinkHandle);
+
+    /* Initialize the Device tree */
+    RtlInitUnicodeString(&LinkName, L"\\Device");
+    InitializeObjectAttributes(&ObjectAttributes,
+                               &LinkName,
+                               OBJ_CASE_INSENSITIVE | OBJ_PERMANENT,
+                               NULL,
+                               SePublicDefaultSd);
 
-    /* Remove the trailing backslash */
-    BootPath.Length -= sizeof(WCHAR);
-    BootPath.MaximumLength -= sizeof(WCHAR);
+    /* Create it */
+    Status = NtCreateDirectoryObject(&LinkHandle,
+                                     DIRECTORY_ALL_ACCESS,
+                                     &ObjectAttributes);
+    if (!NT_SUCCESS(Status))
+    {
+        KeBugCheckEx(SYMBOLIC_INITIALIZATION_FAILED, Status, 2, 0, 0);
+    }
 
-    /* Only ARC Name left - Build full ARC Name */
-    ArcNameBuffer = ExAllocatePool (PagedPool, 256 * sizeof(WCHAR));
-    swprintf (ArcNameBuffer, L"\\ArcName\\%S", LoaderBlock->ArcBootDeviceName);
-    RtlInitUnicodeString (&ArcName, ArcNameBuffer);
+    /* Close the LinkHandle */
+    ObCloseHandle(LinkHandle, KernelMode);
 
-    /* Allocate ARC Device Name string */
-    ArcDeviceName.Length = 0;
-    ArcDeviceName.MaximumLength = 256 * sizeof(WCHAR);
-    ArcDeviceName.Buffer = ExAllocatePool (PagedPool, 256 * sizeof(WCHAR));
+    /* Create the system root symlink name */
+    RtlInitAnsiString(&AnsiName, "\\SystemRoot");
+    Status = RtlAnsiStringToUnicodeString(&LinkName, &AnsiName, TRUE);
+    if (!NT_SUCCESS(Status))
+    {
+        KeBugCheckEx(SYMBOLIC_INITIALIZATION_FAILED, Status, 3, 0, 0);
+    }
 
-    /* Open the Symbolic Link */
+    /* Initialize the attributes for the link */
     InitializeObjectAttributes(&ObjectAttributes,
-                               &ArcName,
-                               OBJ_OPENLINK,
+                               &LinkName,
+                               OBJ_CASE_INSENSITIVE | OBJ_PERMANENT,
                                NULL,
-                               NULL);
-    Status = NtOpenSymbolicLinkObject(&Handle,
-                                      SYMBOLIC_LINK_ALL_ACCESS,
-                                      &ObjectAttributes);
-
-    /* Free the String */
-    ExFreePool(ArcName.Buffer);
-
-    /* Check for Success */
-    if (!NT_SUCCESS(Status)) {
-
-        /* Free the Strings */
-        RtlFreeUnicodeString(&BootPath);
-        ExFreePool(ArcDeviceName.Buffer);
-        CPRINT("NtOpenSymbolicLinkObject() failed (Status %x)\n", Status);
-        KEBUGCHECK(0);
+                               SePublicDefaultSd);
+
+    /* Build the ARC name */
+    sprintf(Buffer,
+            "\\ArcName\\%s%s",
+            LoaderBlock->ArcBootDeviceName,
+            LoaderBlock->NtBootPathName);
+    Buffer[strlen(Buffer) - 1] = ANSI_NULL;
+
+    /* Convert it to Unicode */
+    RtlInitString(&TargetString, Buffer);
+    Status = RtlAnsiStringToUnicodeString(&TargetName,
+                                          &TargetString,
+                                          TRUE);
+    if (!NT_SUCCESS(Status))
+    {
+        /* We failed, bugcheck */
+        KeBugCheckEx(SYMBOLIC_INITIALIZATION_FAILED, Status, 4, 0, 0);
     }
 
-    /* Query the Link */
-    Status = NtQuerySymbolicLinkObject(Handle,
-                                       &ArcDeviceName,
-                                       &Length);
-    NtClose (Handle);
+    /* Create it */
+    Status = NtCreateSymbolicLinkObject(&LinkHandle,
+                                        SYMBOLIC_LINK_ALL_ACCESS,
+                                        &ObjectAttributes,
+                                        &TargetName);
 
-    /* Check for Success */
-    if (!NT_SUCCESS(Status)) {
+    /* Free the strings */
+    RtlFreeUnicodeString(&LinkName);
+    RtlFreeUnicodeString(&TargetName);
 
-        /* Free the Strings */
-        RtlFreeUnicodeString(&BootPath);
-        ExFreePool(ArcDeviceName.Buffer);
-        CPRINT("NtQuerySymbolicLinkObject() failed (Status %x)\n", Status);
-        KEBUGCHECK(0);
+    /* Check if creating the link failed */
+    if (!NT_SUCCESS(Status))
+    {
+        KeBugCheckEx(SYMBOLIC_INITIALIZATION_FAILED, Status, 5, 0, 0);
     }
 
-    /* Allocate Device Name string */
-    DriveDeviceName.Length = 0;
-    DriveDeviceName.MaximumLength = 256 * sizeof(WCHAR);
-    DriveDeviceName.Buffer = ExAllocatePool (PagedPool, 256 * sizeof(WCHAR));
-
-    /* Loop Drives */
-    for (i = 0; i < 26; i++)  {
-
-        /* Setup the String */
-        swprintf (DriveNameBuffer, L"\\??\\%C:", 'A' + i);
-        RtlInitUnicodeString(&DriveName,
-                             DriveNameBuffer);
-
-        /* Open the Symbolic Link */
-        InitializeObjectAttributes(&ObjectAttributes,
-                                   &DriveName,
-                                   OBJ_OPENLINK,
-                                   NULL,
-                                   NULL);
-        Status = NtOpenSymbolicLinkObject(&Handle,
-                                          SYMBOLIC_LINK_ALL_ACCESS,
-                                          &ObjectAttributes);
-
-        /* If it failed, skip to the next drive */
-        if (!NT_SUCCESS(Status)) {
-            DPRINT("Failed to open link %wZ\n", &DriveName);
-            continue;
-        }
+    /* Close the handle and return success */
+    ObCloseHandle(LinkHandle, KernelMode);
+    return STATUS_SUCCESS;
+}
 
-        /* Query it */
-        Status = NtQuerySymbolicLinkObject(Handle,
-                                           &DriveDeviceName,
-                                           &Length);
+VOID
+NTAPI
+ExpInitNls(IN PLOADER_PARAMETER_BLOCK LoaderBlock)
+{
+    LARGE_INTEGER SectionSize;
+    NTSTATUS Status;
+    HANDLE NlsSection;
+    PVOID SectionBase = NULL;
+    ULONG ViewSize = 0;
+    LARGE_INTEGER SectionOffset = {{0}};
+    PLIST_ENTRY ListHead, NextEntry;
+    PMEMORY_ALLOCATION_DESCRIPTOR MdBlock;
 
-        /* If it failed, skip to the next drive */
-        if (!NT_SUCCESS(Status)) {
-            DPRINT("Failed to query link %wZ\n", &DriveName);
-            continue;
+    /* Check if this is boot-time phase 0 initialization */
+    if (!ExpInitializationPhase)
+    {
+        /* Loop the memory descriptors */
+        ListHead = &LoaderBlock->MemoryDescriptorListHead;
+        NextEntry = ListHead->Flink;
+        while (NextEntry != ListHead)
+        {
+            /* Get the current block */
+            MdBlock = CONTAINING_RECORD(NextEntry,
+                                        MEMORY_ALLOCATION_DESCRIPTOR,
+                                        ListEntry);
+
+            /* Check if this is an NLS block */
+            if (MdBlock->MemoryType == LoaderNlsData)
+            {
+                /* Increase the table size */
+                ExpNlsTableSize += MdBlock->PageCount * PAGE_SIZE;
+            }
+
+            /* Go to the next block */
+            NextEntry = MdBlock->ListEntry.Flink;
         }
-        DPRINT("Opened link: %wZ ==> %wZ\n", &DriveName, &DriveDeviceName);
 
-        /* See if we've found the boot drive */
-        if (!RtlCompareUnicodeString (&ArcDeviceName, &DriveDeviceName, FALSE)) {
+        /*
+         * In NT, the memory blocks are contiguous, but in ReactOS they aren't,
+         * so unless someone fixes FreeLdr, we'll have to use this icky hack.
+         */
+        ExpNlsTableSize += 2 * PAGE_SIZE; // BIAS FOR FREELDR. HACK!
+
+        /* Allocate the a new buffer since loader memory will be freed */
+        ExpNlsTableBase = ExAllocatePoolWithTag(NonPagedPool,
+                                                ExpNlsTableSize,
+                                                TAG('R', 't', 'l', 'i'));
+        if (!ExpNlsTableBase) KeBugCheck(PHASE0_INITIALIZATION_FAILED);
+
+        /* Copy the codepage data in its new location. */
+        RtlCopyMemory(ExpNlsTableBase,
+                      LoaderBlock->NlsData->AnsiCodePageData,
+                      ExpNlsTableSize);
+
+        /* Initialize and reset the NLS TAbles */
+        RtlInitNlsTables((PVOID)((ULONG_PTR)ExpNlsTableBase +
+                                 ExpAnsiCodePageDataOffset),
+                         (PVOID)((ULONG_PTR)ExpNlsTableBase +
+                                 ExpOemCodePageDataOffset),
+                         (PVOID)((ULONG_PTR)ExpNlsTableBase +
+                                 ExpUnicodeCaseTableDataOffset),
+                         &ExpNlsTableInfo);
+        RtlResetRtlTranslations(&ExpNlsTableInfo);
+        return;
+    }
 
-            DPRINT("DOS Boot path: %c:%wZ\n", 'A' + i, &BootPath);
-            swprintf(SharedUserData->NtSystemRoot, L"%C:%wZ", 'A' + i, &BootPath);
-            BootDriveFound = TRUE;
-        }
+    /* Set the section size */
+    SectionSize.QuadPart = ExpNlsTableSize;
+
+    /* Create the NLS Section */
+    Status = ZwCreateSection(&NlsSection,
+                             SECTION_ALL_ACCESS,
+                             NULL,
+                             &SectionSize,
+                             PAGE_READWRITE,
+                             SEC_COMMIT,
+                             NULL);
+    if (!NT_SUCCESS(Status))
+    {
+        /* Failed */
+        KeBugCheckEx(PHASE1_INITIALIZATION_FAILED, Status, 1, 0, 0);
+    }
 
-        /* Close this Link */
-        NtClose (Handle);
+    /* Get a pointer to the section */
+    Status = ObReferenceObjectByHandle(NlsSection,
+                                       SECTION_ALL_ACCESS,
+                                       MmSectionObjectType,
+                                       KernelMode,
+                                       &ExpNlsSectionPointer,
+                                       NULL);
+    ZwClose(NlsSection);
+    if (!NT_SUCCESS(Status))
+    {
+        /* Failed */
+        KeBugCheckEx(PHASE1_INITIALIZATION_FAILED, Status, 2, 0, 0);
     }
 
-    /* Free all the Strings we have in memory */
-    RtlFreeUnicodeString (&BootPath);
-    ExFreePool(DriveDeviceName.Buffer);
-    ExFreePool(ArcDeviceName.Buffer);
+    /* Map the NLS Section in system space */
+    Status = MmMapViewInSystemSpace(ExpNlsSectionPointer,
+                                    &SectionBase,
+                                    &ExpNlsTableSize);
+    if (!NT_SUCCESS(Status))
+    {
+        /* Failed */
+        KeBugCheckEx(PHASE1_INITIALIZATION_FAILED, Status, 3, 0, 0);
+    }
 
-    /* Make sure we found the Boot Drive */
-    if (BootDriveFound == FALSE) {
+    /* Copy the codepage data in its new location. */
+    RtlCopyMemory(SectionBase, ExpNlsTableBase, ExpNlsTableSize);
 
-        DbgPrint("No system drive found!\n");
-        KEBUGCHECK (NO_BOOT_DEVICE);
-    }
-}
+    /* Free the previously allocated buffer and set the new location */
+    ExFreePool(ExpNlsTableBase);
+    ExpNlsTableBase = SectionBase;
 
-VOID
-FORCEINLINE
-ParseAndCacheLoadedModules(VOID)
-{
-    ULONG i;
-    PCHAR Name;
+    /* Initialize the NLS Tables */
+    RtlInitNlsTables((PVOID)((ULONG_PTR)ExpNlsTableBase +
+                             ExpAnsiCodePageDataOffset),
+                     (PVOID)((ULONG_PTR)ExpNlsTableBase +
+                             ExpOemCodePageDataOffset),
+                     (PVOID)((ULONG_PTR)ExpNlsTableBase +
+                             ExpUnicodeCaseTableDataOffset),
+                     &ExpNlsTableInfo);
+    RtlResetRtlTranslations(&ExpNlsTableInfo);
 
-    /* Loop the Module List and get the modules we want */
-    for (i = 1; i < KeLoaderModuleCount; i++)
+    /* Reset the base to 0 */
+    SectionBase = NULL;
+
+    /* Map the section in the system process */
+    Status = MmMapViewOfSection(ExpNlsSectionPointer,
+                                PsGetCurrentProcess(),
+                                &SectionBase,
+                                0L,
+                                0L,
+                                &SectionOffset,
+                                &ViewSize,
+                                ViewShare,
+                                0L,
+                                PAGE_READWRITE);
+    if (!NT_SUCCESS(Status))
     {
-        /* Get the Name of this Module */
-        if (!(Name = strrchr((PCHAR)KeLoaderModules[i].String, '\\')))
-        {
-            /* Save the name */
-            Name = (PCHAR)KeLoaderModules[i].String;
-        }
-        else
-        {
-            /* No name, skip */
-            Name++;
-        }
-
-        /* Now check for any of the modules we will need later */
-        if (!_stricmp(Name, "ansi.nls"))
-        {
-            CachedModules[AnsiCodepage] = &KeLoaderModules[i];
-        }
-        else if (!_stricmp(Name, "oem.nls"))
-        {
-            CachedModules[OemCodepage] = &KeLoaderModules[i];
-        }
-        else if (!_stricmp(Name, "casemap.nls"))
-        {
-            CachedModules[UnicodeCasemap] = &KeLoaderModules[i];
-        }
-        else if (!_stricmp(Name, "system") || !_stricmp(Name, "system.hiv"))
-        {
-            CachedModules[SystemRegistry] = &KeLoaderModules[i];
-        }
-        else if (!_stricmp(Name, "hardware") || !_stricmp(Name, "hardware.hiv"))
-        {
-            CachedModules[HardwareRegistry] = &KeLoaderModules[i];
-        }
+        /* Failed */
+        KeBugCheckEx(PHASE1_INITIALIZATION_FAILED, Status, 5, 0, 0);
     }
+
+    /* Copy the table into the system process and set this as the base */
+    RtlCopyMemory(SectionBase, ExpNlsTableBase, ExpNlsTableSize);
+    ExpNlsTableBase = SectionBase;
 }
 
 VOID
@@ -281,83 +341,147 @@ ExpDisplayNotice(VOID)
     
 }
 
-INIT_FUNCTION
 NTSTATUS
-ExpLoadInitialProcess(PHANDLE ProcessHandle,
-                      PHANDLE ThreadHandle)
+NTAPI
+ExpLoadInitialProcess(IN PHANDLE ProcessHandle,
+                      IN PHANDLE ThreadHandle)
 {
-    UNICODE_STRING CurrentDirectory;
-    UNICODE_STRING ImagePath = RTL_CONSTANT_STRING(L"\\SystemRoot\\system32\\smss.exe");
+    PRTL_USER_PROCESS_PARAMETERS ProcessParameters = NULL;
     NTSTATUS Status;
-    PRTL_USER_PROCESS_PARAMETERS Params=NULL;
-    RTL_USER_PROCESS_INFORMATION Info;
-
-    RtlInitUnicodeString(&CurrentDirectory,
-                         SharedUserData->NtSystemRoot);
-
-    /* Create the Parameters */
-    Status = RtlCreateProcessParameters(&Params,
-                                        &ImagePath,
-                                        NULL,
-                                        &CurrentDirectory,
-                                        NULL,
-                                        NULL,
-                                        NULL,
-                                        NULL,
-                                        NULL,
-                                        NULL);
-    if(!NT_SUCCESS(Status))
+    ULONG Size;
+    RTL_USER_PROCESS_INFORMATION ProcessInformation;
+    PWSTR p;
+    UNICODE_STRING NullString = RTL_CONSTANT_STRING(L"");
+    UNICODE_STRING SmssName, Environment, SystemDriveString;
+
+    /* Allocate memory for the process parameters */
+    Size = sizeof(RTL_USER_PROCESS_PARAMETERS) +
+           ((MAX_PATH * 4) * sizeof(WCHAR));
+    Status = ZwAllocateVirtualMemory(NtCurrentProcess(),
+                                     (PVOID)&ProcessParameters,
+                                     0,
+                                     &Size,
+                                     MEM_COMMIT,
+                                     PAGE_READWRITE);
+    if (!NT_SUCCESS(Status))
+    {
+        /* Failed */
+        KeBugCheckEx(SESSION1_INITIALIZATION_FAILED, Status, 0, 0, 0);
+    }
+
+    /* Setup the basic header, and give the process the low 1MB to itself */
+    ProcessParameters->Length = Size;
+    ProcessParameters->MaximumLength = Size;
+    ProcessParameters->Flags = RTL_USER_PROCESS_PARAMETERS_NORMALIZED |
+                               RTL_USER_PROCESS_PARAMETERS_RESERVE_1MB;
+
+    /* Allocate a page for the environment */
+    Size = PAGE_SIZE;
+    Status = ZwAllocateVirtualMemory(NtCurrentProcess(),
+                                     (PVOID)&ProcessParameters->Environment,
+                                     0,
+                                     &Size,
+                                     MEM_COMMIT,
+                                     PAGE_READWRITE);
+    if (!NT_SUCCESS(Status))
     {
-        DPRINT1("Failed to create ppb!\n");
-        return Status;
+        /* Failed */
+        KeBugCheckEx(SESSION2_INITIALIZATION_FAILED, Status, 0, 0, 0);
     }
 
-    DPRINT("Creating process\n");
-    Status = RtlCreateUserProcess(&ImagePath,
+    /* Make a buffer for the DOS path */
+    p = (PWSTR)(ProcessParameters + 1);
+    ProcessParameters->CurrentDirectory.DosPath.Buffer = p;
+    ProcessParameters->
+        CurrentDirectory.DosPath.MaximumLength = MAX_PATH * sizeof(WCHAR);
+
+    /* Copy the DOS path */
+    RtlCopyUnicodeString(&ProcessParameters->CurrentDirectory.DosPath,
+                         &NtSystemRoot);
+
+    /* Make a buffer for the DLL Path */
+    p = (PWSTR)((PCHAR)ProcessParameters->CurrentDirectory.DosPath.Buffer +
+                ProcessParameters->CurrentDirectory.DosPath.MaximumLength);
+    ProcessParameters->DllPath.Buffer = p;
+    ProcessParameters->DllPath.MaximumLength = MAX_PATH * sizeof(WCHAR);
+
+    /* Copy the DLL path and append the system32 directory */
+    RtlCopyUnicodeString(&ProcessParameters->DllPath,
+                         &ProcessParameters->CurrentDirectory.DosPath);
+    RtlAppendUnicodeToString(&ProcessParameters->DllPath, L"\\System32");
+
+    /* Make a buffer for the image name */
+    p = (PWSTR)((PCHAR)ProcessParameters->DllPath.Buffer +
+                ProcessParameters->DllPath.MaximumLength);
+    ProcessParameters->ImagePathName.Buffer = p;
+    ProcessParameters->ImagePathName.MaximumLength = MAX_PATH * sizeof(WCHAR);
+
+    /* Append the system path and session manager name */
+    RtlAppendUnicodeToString(&ProcessParameters->ImagePathName,
+                             L"\\SystemRoot\\System32");
+    RtlAppendUnicodeToString(&ProcessParameters->ImagePathName,
+                             L"\\smss.exe");
+
+    /* Create the environment string */
+    RtlInitEmptyUnicodeString(&Environment,
+                              ProcessParameters->Environment,
+                              (USHORT)Size);
+
+    /* Append the DLL path to it */
+    RtlAppendUnicodeToString(&Environment, L"Path=" );
+    RtlAppendUnicodeStringToString(&Environment, &ProcessParameters->DllPath);
+    RtlAppendUnicodeStringToString(&Environment, &NullString );
+
+    /* Create the system drive string */
+    SystemDriveString = NtSystemRoot;
+    SystemDriveString.Length = 2 * sizeof(WCHAR);
+
+    /* Append it to the environment */
+    RtlAppendUnicodeToString(&Environment, L"SystemDrive=");
+    RtlAppendUnicodeStringToString(&Environment, &SystemDriveString);
+    RtlAppendUnicodeStringToString(&Environment, &NullString);
+
+    /* Append the system root to the environment */
+    RtlAppendUnicodeToString(&Environment, L"SystemRoot=");
+    RtlAppendUnicodeStringToString(&Environment, &NtSystemRoot);
+    RtlAppendUnicodeStringToString(&Environment, &NullString);
+
+    /* Get and set the command line equal to the image path */
+    ProcessParameters->CommandLine = ProcessParameters->ImagePathName;
+    SmssName = ProcessParameters->ImagePathName;
+
+    /* Create SMSS process */
+    Status = RtlCreateUserProcess(&SmssName,
                                   OBJ_CASE_INSENSITIVE,
-                                  Params,
+                                  RtlDeNormalizeProcessParams(
+                                  ProcessParameters),
                                   NULL,
                                   NULL,
                                   NULL,
                                   FALSE,
                                   NULL,
                                   NULL,
-                                  &Info);
-    
-    /* Close the handle and free the params */
-    RtlDestroyProcessParameters(Params);
-
+                                  &ProcessInformation);
     if (!NT_SUCCESS(Status))
     {
-        DPRINT1("NtCreateProcess() failed (Status %lx)\n", Status);
-        return(Status);
+        /* Failed */
+        KeBugCheckEx(SESSION3_INITIALIZATION_FAILED, Status, 0, 0, 0);
     }
 
-    /* Start it up */
-    ZwResumeThread(Info.ThreadHandle, NULL);
+    /* Resume the thread */
+    Status = ZwResumeThread(ProcessInformation.ThreadHandle, NULL);
+    if (!NT_SUCCESS(Status))
+    {
+        /* Failed */
+        KeBugCheckEx(SESSION4_INITIALIZATION_FAILED, Status, 0, 0, 0);
+    }
 
     /* Return Handles */
-    *ProcessHandle = Info.ProcessHandle;
-    *ThreadHandle = Info.ThreadHandle;
-    DPRINT("Process created successfully\n");
+    *ProcessHandle = ProcessInformation.ProcessHandle;
+    *ThreadHandle = ProcessInformation.ThreadHandle;
     return STATUS_SUCCESS;
 }
 
-VOID
-NTAPI
-ExInit3(VOID)
-{
-    ExpInitializeEventImplementation();
-    ExpInitializeEventPairImplementation();
-    ExpInitializeMutantImplementation();
-    ExpInitializeSemaphoreImplementation();
-    ExpInitializeTimerImplementation();
-    LpcpInitSystem();
-    ExpInitializeProfileImplementation();
-    ExpWin32kInit();
-    ExpInitUuids();
-}
-
 ULONG
 NTAPI
 ExComputeTickCountMultiplier(IN ULONG ClockIncrement)
@@ -416,8 +540,37 @@ BOOLEAN
 NTAPI
 ExpInitSystemPhase1(VOID)
 {
-    /* Not yet done */
-    return FALSE;
+    /* Initialize worker threads */
+    ExpInitializeWorkerThreads();
+
+    /* Initialize pushlocks */
+    ExpInitializePushLocks();
+
+    /* Initialize events and event pairs */
+    ExpInitializeEventImplementation();
+    ExpInitializeEventPairImplementation();
+
+    /* Initialize callbacks */
+    ExpInitializeCallbacks();
+
+    /* Initialize mutants */
+    ExpInitializeMutantImplementation();
+
+    /* Initialize semaphores */
+    ExpInitializeSemaphoreImplementation();
+
+    /* Initialize timers */
+    ExpInitializeTimerImplementation();
+
+    /* Initialize profiling */
+    ExpInitializeProfileImplementation();
+
+    /* Initialize UUIDs */
+    ExpInitUuids();
+
+    /* Initialize Win32K */
+    ExpWin32kInit();
+    return TRUE;
 }
 
 BOOLEAN
@@ -466,7 +619,7 @@ ExpIsLoaderValid(IN PLOADER_PARAMETER_BLOCK LoaderBlock)
     /* Fail if this is XP */
     if (Extension->MinorVersion < 2) return FALSE;
 
-    /* This is 2003 or newer, aprove it */
+    /* This is 2003 or newer, approve it */
     return TRUE;
 }
 
@@ -479,11 +632,6 @@ ExpInitializeExecutive(IN ULONG Cpu,
     CHAR Buffer[256];
     ANSI_STRING AnsiPath;
     NTSTATUS Status;
-    PLIST_ENTRY NextEntry, ListHead;
-    PMEMORY_ALLOCATION_DESCRIPTOR MdBlock;
-
-    /* FIXME: Deprecate soon */
-    ParseAndCacheLoadedModules();
 
     /* Validate Loader */
     if (!ExpIsLoaderValid(LoaderBlock))
@@ -506,7 +654,7 @@ ExpInitializeExecutive(IN ULONG Cpu,
         if (!HalInitSystem(ExpInitializationPhase, LoaderBlock))
         {
             /* Initialization failed */
-            KEBUGCHECK(HAL_INITIALIZATION_FAILED);
+            KeBugCheck(HAL_INITIALIZATION_FAILED);
         }
 
         /* We're done */
@@ -580,7 +728,7 @@ ExpInitializeExecutive(IN ULONG Cpu,
 
     /* Convert to ANSI_STRING and null-terminate it */
     RtlInitString(&AnsiPath, Buffer );
-    Buffer[--AnsiPath.Length] = UNICODE_NULL;
+    Buffer[--AnsiPath.Length] = ANSI_NULL;
 
     /* Get the string from KUSER_SHARED_DATA's buffer */
     NtSystemRoot.Buffer = SharedUserData->NtSystemRoot;
@@ -594,9 +742,6 @@ ExpInitializeExecutive(IN ULONG Cpu,
     /* Setup bugcheck messages */
     KiInitializeBugCheck();
 
-    /* Setup system time */
-    KiInitializeSystemClock();
-
     /* Initialize the executive at phase 0 */
     if (!ExInitSystem()) KEBUGCHECK(PHASE0_INITIALIZATION_FAILED);
 
@@ -607,53 +752,8 @@ ExpInitializeExecutive(IN ULONG Cpu,
     SharedUserData->Reserved1 = (ULONG_PTR)MmHighestUserAddress;
     SharedUserData->Reserved3 = (ULONG_PTR)MmSystemRangeStart;
 
-    /* Loop the memory descriptors */
-    ListHead = &LoaderBlock->MemoryDescriptorListHead;
-    NextEntry = ListHead->Flink;
-    while (NextEntry != ListHead)
-    {
-        /* Get the current block */
-        MdBlock = CONTAINING_RECORD(NextEntry,
-                                    MEMORY_ALLOCATION_DESCRIPTOR,
-                                    ListEntry);
-
-        /* Check if this is an NLS block */
-        if (MdBlock->MemoryType == LoaderNlsData)
-        {
-            /* Increase the table size */
-            ExpNlsTableSize += MdBlock->PageCount * PAGE_SIZE;
-        }
-
-        /* Go to the next block */
-        NextEntry = MdBlock->ListEntry.Flink;
-    }
-
-    /*
-     * In NT, the memory blocks are contiguous, but in ReactOS they are not,
-     * so unless someone fixes FreeLdr, we'll have to use this icky hack.
-     */
-    ExpNlsTableSize += 2 * PAGE_SIZE; // BIAS FOR FREELDR. HACK!
-
-    /* Allocate the NLS buffer in the pool since loader memory will be freed */
-    ExpNlsTableBase = ExAllocatePoolWithTag(NonPagedPool,
-                                            ExpNlsTableSize,
-                                            TAG('R', 't', 'l', 'i'));
-    if (!ExpNlsTableBase) KeBugCheck(PHASE0_INITIALIZATION_FAILED);
-
-    /* Copy the codepage data in its new location. */
-    RtlMoveMemory(ExpNlsTableBase,
-                  LoaderBlock->NlsData->AnsiCodePageData,
-                  ExpNlsTableSize);
-
-    /* Initialize and reset the NLS TAbles */
-    RtlInitNlsTables((PVOID)((ULONG_PTR)ExpNlsTableBase +
-                             ExpAnsiCodePageDataOffset),
-                     (PVOID)((ULONG_PTR)ExpNlsTableBase +
-                             ExpOemCodePageDataOffset),
-                     (PVOID)((ULONG_PTR)ExpNlsTableBase +
-                             ExpUnicodeCaseTableDataOffset),
-                     &ExpNlsTableInfo);
-    RtlResetRtlTranslations(&ExpNlsTableInfo);
+    /* Make a copy of the NLS Tables */
+    ExpInitNls(LoaderBlock);
 
     /* Initialize the Handle Table */
     ExpInitializeHandleTables();
@@ -686,12 +786,15 @@ ExpInitializeExecutive(IN ULONG Cpu,
     /* Set up Region Maps, Sections and the Paging File */
     MmInit2();
 
-    /* Call OB initialization again */
-    if (!ObInit()) KEBUGCHECK(OBJECT_INITIALIZATION_FAILED);
+    /* Initialize the boot video. */
+    InbvDisplayInitialize();
 
     /* Initialize the Process Manager */
     if (!PsInitSystem()) KEBUGCHECK(PROCESS_INITIALIZATION_FAILED);
 
+    /* Initialize the User-Mode Debugging Subsystem */
+    DbgkInitialize();
+
     /* Calculate the tick count multiplier */
     ExpTickCountMultiplier = ExComputeTickCountMultiplier(KeMaximumIncrement);
     SharedUserData->TickCountMultiplier = ExpTickCountMultiplier;
@@ -716,209 +819,160 @@ VOID
 NTAPI
 ExPhase2Init(PVOID Context)
 {
-    UNICODE_STRING EventName;
-    HANDLE InitDoneEventHandle;
-    OBJECT_ATTRIBUTES ObjectAttributes;
     LARGE_INTEGER Timeout;
     HANDLE ProcessHandle;
     HANDLE ThreadHandle;
     NTSTATUS Status;
+    TIME_FIELDS TimeFields;
+    LARGE_INTEGER SystemBootTime, UniversalBootTime;
+
+    /* Set to phase 1 */
+    ExpInitializationPhase = 1;
 
     /* Set us at maximum priority */
     KeSetPriorityThread(KeGetCurrentThread(), HIGH_PRIORITY);
 
-    /* Initialize the later stages of the kernel */
-    KeInitSystem();
-
-    /* Initialize all processors */
-    HalAllProcessorsStarted();
-
     /* Do Phase 1 HAL Initialization */
     HalInitSystem(1, KeLoaderBlock);
 
-    /* Initialize Basic System Objects and Worker Threads */
-    ExInit3();
-
-    /* initialize the worker threads */
-    ExpInitializeWorkerThreads();
-
-    /* initialize callbacks */
-    ExpInitializeCallbacks();
-
-    /* Call KD Providers at Phase 1 */
-    KdInitSystem(1, KeLoaderBlock);
-
-    /* Initialize I/O Objects, Filesystems, Error Logging and Shutdown */
-    IoInit();
-
-    /* TBD */
-    PoInit(AcpiTableDetected, KeLoaderBlock);
-
-    /* Initialize the Registry (Hives are NOT yet loaded!) */
-    CmInitializeRegistry();
-
-    /* Unmap Low memory, initialize the Page Zeroing and the Balancer Thread */
-    MmInit3();
-
-    /* Initialize Cache Views */
-    CcInit();
-
-    /* Initialize File Locking */
-    FsRtlpInitFileLockingImplementation();
-
-    /* Report all resources used by hal */
-    HalReportResourceUsage();
-
-    /* Clear the screen to blue */
-    HalInitSystem(2, KeLoaderBlock);
-
     /* Check if GUI Boot is enabled */
     if (strstr(KeLoaderBlock->LoadOptions, "NOGUIBOOT")) NoGuiBoot = TRUE;
 
-    /* Display version number and copyright/warranty message */
-    if (NoGuiBoot) ExpDisplayNotice();
+    /* Display the boot screen image if not disabled */
+    if (!ExpInTextModeSetup) InbvDisplayInitialize2(NoGuiBoot);
+    if (!NoGuiBoot) InbvDisplayBootLogo();
 
-    /* Call KD Providers at Phase 2 */
+    /* Clear the screen to blue and display the boot notice and debug status */
+    if (NoGuiBoot) ExpDisplayNotice();
     KdInitSystem(2, KeLoaderBlock);
 
-    /* Import and create NLS Data and Sections */
-    RtlpInitNls();
-
-    /* Import and Load Registry Hives */
-    CmInitHives(ExpInTextModeSetup);
+    /* Initialize Power Subsystem in Phase 0 */
+    PoInit(0, AcpiTableDetected);
 
-    /* Initialize VDM support */
-    KeI386VdmInitialize();
-
-    /* Initialize the time zone information from the registry */
-    ExpInitTimeZoneInfo();
+    /* Query the clock */
+    if (HalQueryRealTimeClock(&TimeFields))
+    {
+        /* Convert to time fields */
+        RtlTimeFieldsToTime(&TimeFields, &SystemBootTime);
+        UniversalBootTime = SystemBootTime;
+
+#if 0 // FIXME: Won't work until we can read registry data here
+        /* FIXME: This assumes that the RTC is not already in GMT */
+        ExpTimeZoneBias.QuadPart = Int32x32To64(ExpLastTimeZoneBias * 60,
+                                                10000000);
+
+        /* Set the boot time-zone bias */
+        SharedUserData->TimeZoneBias.High2Time = ExpTimeZoneBias.HighPart;
+        SharedUserData->TimeZoneBias.LowPart = ExpTimeZoneBias.LowPart;
+        SharedUserData->TimeZoneBias.High1Time = ExpTimeZoneBias.HighPart;
+
+        /* Convert the boot time to local time, and set it */
+        UniversalBootTime.QuadPart = SystemBootTime.QuadPart +
+                                     ExpTimeZoneBias.QuadPart;
+#endif
+        KiSetSystemTime(&UniversalBootTime);
 
-    /* Enter the kernel debugger before starting up the boot drivers */
-    if (KdDebuggerEnabled && KdpEarlyBreak)
-        DbgBreakPoint();
+        /* Remember this as the boot time */
+        KeBootTime = UniversalBootTime;
+    }
 
-    /* Setup Drivers and Root Device Node */
-    IoInit2(FALSE);
+    /* The clock is ready now (FIXME: HACK FOR OLD HAL) */
+    KiClockSetupComplete = TRUE;
 
-    /* Display the boot screen image if not disabled */
-    if (!NoGuiBoot) InbvEnableBootDriver(TRUE);
+    /* Initialize all processors */
+    HalAllProcessorsStarted();
 
-    /* Create ARC Names, SystemRoot SymLink, Load Drivers and Assign Letters */
-    IoInit3();
+    /* Call OB initialization again */
+    if (!ObInit()) KeBugCheck(OBJECT1_INITIALIZATION_FAILED);
 
-    /* Load the System DLL and its Entrypoints */
-    PsLocateSystemDll();
+    /* Initialize Basic System Objects and Worker Threads */
+    if (!ExInitSystem()) KeBugCheckEx(PHASE1_INITIALIZATION_FAILED, 1, 0, 0, 0);
 
-    /* Initialize shared user page. Set dos system path, dos device map, etc. */
-    InitSystemSharedUserPage(KeLoaderBlock);
+    /* Initialize the later stages of the kernel */
+    if (!KeInitSystem()) KeBugCheckEx(PHASE1_INITIALIZATION_FAILED, 2, 0, 0, 0);
 
-    /* Create 'ReactOSInitDone' event */
-    RtlInitUnicodeString(&EventName, L"\\ReactOSInitDone");
-    InitializeObjectAttributes(&ObjectAttributes,
-                               &EventName,
-                               0,
-                               NULL,
-                               NULL);
-    Status = ZwCreateEvent(&InitDoneEventHandle,
-                           EVENT_ALL_ACCESS,
-                           &ObjectAttributes,
-                           SynchronizationEvent,
-                           FALSE);
-
-    /* Check for Success */
-    if (!NT_SUCCESS(Status)) {
-
-        DPRINT1("Failed to create 'ReactOSInitDone' event (Status 0x%x)\n", Status);
-        InitDoneEventHandle = INVALID_HANDLE_VALUE;
+    /* Call KD Providers at Phase 1 */
+    if (!KdInitSystem(ExpInitializationPhase, KeLoaderBlock))
+    {
+        /* Failed, bugcheck */
+        KeBugCheckEx(PHASE1_INITIALIZATION_FAILED, 3, 0, 0, 0);
     }
 
-    /* Launch initial process */
-    Status = ExpLoadInitialProcess(&ProcessHandle,
-                                   &ThreadHandle);
-
-    /* Check for success, Bugcheck if we failed */
-    if (!NT_SUCCESS(Status)) {
-
-        KEBUGCHECKEX(SESSION4_INITIALIZATION_FAILED, Status, 0, 0, 0);
+    /* Create SystemRoot Link */
+    Status = ExpCreateSystemRootLink(KeLoaderBlock);
+    if (!NT_SUCCESS(Status))
+    {
+        KeBugCheckEx(SYMBOLIC_INITIALIZATION_FAILED, Status, 0, 0, 0);
     }
 
-    /* Wait on the Completion Event */
-    if (InitDoneEventHandle != INVALID_HANDLE_VALUE) {
+    /* Create NLS section */
+    ExpInitNls(KeLoaderBlock);
 
-        HANDLE Handles[2]; /* Init event, Initial process */
+    /* Initialize Cache Views */
+    CcInitializeCacheManager();
 
-        /* Setup the Handles to wait on */
-        Handles[0] = InitDoneEventHandle;
-        Handles[1] = ProcessHandle;
+    /* Initialize the Registry */
+    if (!CmInitSystem1()) KeBugCheck(CONFIG_INITIALIZATION_FAILED);
 
-        /* Wait for the system to be initialized */
-        Timeout.QuadPart = (LONGLONG)-1200000000;  /* 120 second timeout */
-        Status = ZwWaitForMultipleObjects(2,
-                                          Handles,
-                                          WaitAny,
-                                          FALSE,
-                                          &Timeout);
-        if (!NT_SUCCESS(Status)) {
+    /* Update timezone information */
+    ExRefreshTimeZoneInformation(&SystemBootTime);
 
-            DPRINT1("NtWaitForMultipleObjects failed with status 0x%x!\n", Status);
+    /* Initialize the File System Runtime Library */
+    FsRtlInitSystem();
 
-        } else if (Status == STATUS_TIMEOUT) {
+    /* Report all resources used by HAL */
+    HalReportResourceUsage();
 
-            DPRINT1("WARNING: System not initialized after 120 seconds.\n");
+    /* Initialize LPC */
+    LpcpInitSystem();
 
-        } else if (Status == STATUS_WAIT_0 + 1) {
+    /* Enter the kernel debugger before starting up the boot drivers */
+    if (KdDebuggerEnabled && KdpEarlyBreak) DbgBreakPoint();
 
-            /* Crash the system if the initial process was terminated. */
-            KEBUGCHECKEX(SESSION5_INITIALIZATION_FAILED, Status, 0, 0, 0);
-        }
+    /* Initialize the I/O Subsystem */
+    if (!IoInitSystem(KeLoaderBlock)) KeBugCheck(IO1_INITIALIZATION_FAILED);
 
-        /*
-         * FIXME: FILIP!
-         * Disable the Boot Logo
-         */
-        if (!NoGuiBoot) InbvEnableBootDriver(FALSE);
+    /* Unmap Low memory, and initialize the MPW and Balancer Thread */
+    MmInit3();
+#if DBG
+    extern ULONG Guard;
+#endif
+    ASSERT(Guard == 0xCACA1234);
 
-        /* Signal the Event and close the handle */
-        ZwSetEvent(InitDoneEventHandle, NULL);
-        ZwClose(InitDoneEventHandle);
+    /* Initialize VDM support */
+    KeI386VdmInitialize();
 
-    } else {
+    /* Initialize Power Subsystem in Phase 1*/
+    PoInit(1, AcpiTableDetected);
 
-        /* On failure to create 'ReactOSInitDone' event, go to text mode ASAP */
-        if (!NoGuiBoot) InbvEnableBootDriver(FALSE);
+    /* Initialize the Process Manager at Phase 1 */
+    if (!PsInitSystem()) KeBugCheck(PROCESS1_INITIALIZATION_FAILED);
 
-        /* Crash the system if the initial process terminates within 5 seconds. */
-        Timeout.QuadPart = (LONGLONG)-50000000;  /* 5 second timeout */
-        Status = ZwWaitForSingleObject(ProcessHandle,
-                                       FALSE,
-                                       &Timeout);
+    /* Launch initial process */
+    Status = ExpLoadInitialProcess(&ProcessHandle, &ThreadHandle);
 
-        /* Check for timeout, crash if the initial process didn't initalize */
-        if (Status != STATUS_TIMEOUT) KEBUGCHECKEX(SESSION5_INITIALIZATION_FAILED, Status, 1, 0, 0);
+    /* Wait 5 seconds for it to initialize */
+    Timeout.QuadPart = Int32x32To64(5, -10000000);
+    Status = ZwWaitForSingleObject(ProcessHandle, FALSE, &Timeout);
+    if (!NoGuiBoot) InbvFinalizeBootLogo();
+    if (Status == STATUS_SUCCESS)
+    {
+        /* Bugcheck the system if SMSS couldn't initialize */
+        KeBugCheck(SESSION5_INITIALIZATION_FAILED);
     }
-
-    /* Enable the Clock, close remaining handles */
-    ZwClose(ThreadHandle);
-    ZwClose(ProcessHandle);
-
-    DPRINT1("System initialization complete\n");
+    else
     {
-        /* FIXME: We should instead jump to zero-page thread */
-        /* Free initial kernel memory */
-        MiFreeInitMemory();
+        /* Close process handles */
+        ZwClose(ThreadHandle);
+        ZwClose(ProcessHandle);
 
-        /* Set our priority to 0 */
-        KeGetCurrentThread()->BasePriority = 0;
-        KeSetPriorityThread(KeGetCurrentThread(), 0);
+        /* FIXME: We should free the initial process' memory!*/
 
-        /* Wait ad-infinitum */
-        for (;;)
-        {
-            LARGE_INTEGER Timeout;
-            Timeout.QuadPart = 0x7fffffffffffffffLL;
-            KeDelayExecutionThread(KernelMode, FALSE, &Timeout);
-        }
+        /* Increase init phase */
+        ExpInitializationPhase += 1;
+
+        /* Jump into zero page thread */
+        MmZeroPageThreadMain(NULL);
     }
 }
-
 /* EOF */