Merge 25584, 25588.
[reactos.git] / reactos / ntoskrnl / ex / init.c
index 45beb62..6673931 100644 (file)
@@ -1,14 +1,14 @@
 /*
- * 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>
@@ -49,6 +49,113 @@ PVOID ExpNlsSectionPointer;
 
 /* FUNCTIONS ****************************************************************/
 
+NTSTATUS
+NTAPI
+ExpCreateSystemRootLink(IN PLOADER_PARAMETER_BLOCK LoaderBlock)
+{
+    UNICODE_STRING LinkName;
+    OBJECT_ATTRIBUTES ObjectAttributes;
+    HANDLE LinkHandle;
+    NTSTATUS Status;
+    ANSI_STRING AnsiName;
+    CHAR Buffer[256];
+    ANSI_STRING TargetString;
+    UNICODE_STRING TargetName;
+
+    /* Initialize the ArcName tree */
+    RtlInitUnicodeString(&LinkName, L"\\ArcName");
+    InitializeObjectAttributes(&ObjectAttributes,
+                               &LinkName,
+                               OBJ_CASE_INSENSITIVE | OBJ_PERMANENT,
+                               NULL,
+                               SePublicDefaultSd);
+
+    /* Create it */
+    Status = NtCreateDirectoryObject(&LinkHandle,
+                                     DIRECTORY_ALL_ACCESS,
+                                     &ObjectAttributes);
+    if (!NT_SUCCESS(Status))
+    {
+        KeBugCheckEx(SYMBOLIC_INITIALIZATION_FAILED, Status, 1, 0, 0);
+    }
+
+    /* Close the LinkHandle */
+    NtClose(LinkHandle);
+
+    /* Initialize the Device tree */
+    RtlInitUnicodeString(&LinkName, L"\\Device");
+    InitializeObjectAttributes(&ObjectAttributes,
+                               &LinkName,
+                               OBJ_CASE_INSENSITIVE | OBJ_PERMANENT,
+                               NULL,
+                               SePublicDefaultSd);
+
+    /* Create it */
+    Status = NtCreateDirectoryObject(&LinkHandle,
+                                     DIRECTORY_ALL_ACCESS,
+                                     &ObjectAttributes);
+    if (!NT_SUCCESS(Status))
+    {
+        KeBugCheckEx(SYMBOLIC_INITIALIZATION_FAILED, Status, 2, 0, 0);
+    }
+
+    /* Close the LinkHandle */
+    ObCloseHandle(LinkHandle, KernelMode);
+
+    /* 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);
+    }
+
+    /* Initialize the attributes for the link */
+    InitializeObjectAttributes(&ObjectAttributes,
+                               &LinkName,
+                               OBJ_CASE_INSENSITIVE | OBJ_PERMANENT,
+                               NULL,
+                               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);
+    }
+
+    /* Create it */
+    Status = NtCreateSymbolicLinkObject(&LinkHandle,
+                                        SYMBOLIC_LINK_ALL_ACCESS,
+                                        &ObjectAttributes,
+                                        &TargetName);
+
+    /* Free the strings */
+    RtlFreeUnicodeString(&LinkName);
+    RtlFreeUnicodeString(&TargetName);
+
+    /* Check if creating the link failed */
+    if (!NT_SUCCESS(Status))
+    {
+        KeBugCheckEx(SYMBOLIC_INITIALIZATION_FAILED, Status, 5, 0, 0);
+    }
+
+    /* Close the handle and return success */
+    ObCloseHandle(LinkHandle, KernelMode);
+    return STATUS_SUCCESS;
+}
+
 VOID
 NTAPI
 ExpInitNls(IN PLOADER_PARAMETER_BLOCK LoaderBlock)
@@ -99,7 +206,7 @@ ExpInitNls(IN PLOADER_PARAMETER_BLOCK LoaderBlock)
         if (!ExpNlsTableBase) KeBugCheck(PHASE0_INITIALIZATION_FAILED);
 
         /* Copy the codepage data in its new location. */
-        RtlMoveMemory(ExpNlsTableBase,
+        RtlCopyMemory(ExpNlsTableBase,
                       LoaderBlock->NlsData->AnsiCodePageData,
                       ExpNlsTableSize);
 
@@ -157,7 +264,7 @@ ExpInitNls(IN PLOADER_PARAMETER_BLOCK LoaderBlock)
     }
 
     /* Copy the codepage data in its new location. */
-    RtlMoveMemory(SectionBase, ExpNlsTableBase, ExpNlsTableSize);
+    RtlCopyMemory(SectionBase, ExpNlsTableBase, ExpNlsTableSize);
 
     /* Free the previously allocated buffer and set the new location */
     ExFreePool(ExpNlsTableBase);
@@ -194,161 +301,10 @@ ExpInitNls(IN PLOADER_PARAMETER_BLOCK LoaderBlock)
     }
 
     /* Copy the table into the system process and set this as the base */
-    RtlMoveMemory(SectionBase, ExpNlsTableBase, ExpNlsTableSize);
+    RtlCopyMemory(SectionBase, ExpNlsTableBase, ExpNlsTableSize);
     ExpNlsTableBase = SectionBase;
 }
 
-static
-VOID
-INIT_FUNCTION
-InitSystemSharedUserPage (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;
-    OBJECT_ATTRIBUTES ObjectAttributes;
-    HANDLE Handle;
-    ULONG i;
-    BOOLEAN BootDriveFound = FALSE;
-
-    /* Set the Product Type */
-    SharedUserData->NtProductType = NtProductWinNt;
-    SharedUserData->ProductTypeIsValid = TRUE;
-
-    /*
-     * 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...]"
-     */
-
-    RtlCreateUnicodeStringFromAsciiz(&BootPath, LoaderBlock->NtBootPathName);
-
-    /* Remove the trailing backslash */
-    BootPath.Length -= sizeof(WCHAR);
-    BootPath.MaximumLength -= sizeof(WCHAR);
-
-    /* Only ARC Name left - Build full ARC Name */
-    ArcNameBuffer = ExAllocatePool (PagedPool, 256 * sizeof(WCHAR));
-    swprintf (ArcNameBuffer, L"\\ArcName\\%S", LoaderBlock->ArcBootDeviceName);
-    RtlInitUnicodeString (&ArcName, ArcNameBuffer);
-
-    /* Allocate ARC Device Name string */
-    ArcDeviceName.Length = 0;
-    ArcDeviceName.MaximumLength = 256 * sizeof(WCHAR);
-    ArcDeviceName.Buffer = ExAllocatePool (PagedPool, 256 * sizeof(WCHAR));
-
-    /* Open the Symbolic Link */
-    InitializeObjectAttributes(&ObjectAttributes,
-                               &ArcName,
-                               OBJ_OPENLINK,
-                               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);
-    }
-
-    /* Query the Link */
-    Status = NtQuerySymbolicLinkObject(Handle,
-                                       &ArcDeviceName,
-                                       &Length);
-    NtClose (Handle);
-
-    /* Check for Success */
-    if (!NT_SUCCESS(Status)) {
-
-        /* Free the Strings */
-        RtlFreeUnicodeString(&BootPath);
-        ExFreePool(ArcDeviceName.Buffer);
-        CPRINT("NtQuerySymbolicLinkObject() failed (Status %x)\n", Status);
-        KEBUGCHECK(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;
-        }
-
-        /* Query it */
-        Status = NtQuerySymbolicLinkObject(Handle,
-                                           &DriveDeviceName,
-                                           &Length);
-
-        /* If it failed, skip to the next drive */
-        if (!NT_SUCCESS(Status)) {
-            DPRINT("Failed to query link %wZ\n", &DriveName);
-            continue;
-        }
-        DPRINT("Opened link: %wZ ==> %wZ\n", &DriveName, &DriveDeviceName);
-
-        /* See if we've found the boot drive */
-        if (!RtlCompareUnicodeString (&ArcDeviceName, &DriveDeviceName, FALSE)) {
-
-            DPRINT("DOS Boot path: %c:%wZ\n", 'A' + i, &BootPath);
-            swprintf(SharedUserData->NtSystemRoot, L"%C:%wZ", 'A' + i, &BootPath);
-            BootDriveFound = TRUE;
-        }
-
-        /* Close this Link */
-        NtClose (Handle);
-    }
-
-    /* Free all the Strings we have in memory */
-    RtlFreeUnicodeString (&BootPath);
-    ExFreePool(DriveDeviceName.Buffer);
-    ExFreePool(ArcDeviceName.Buffer);
-
-    /* Make sure we found the Boot Drive */
-    if (BootDriveFound == FALSE) {
-
-        DbgPrint("No system drive found!\n");
-        KEBUGCHECK (NO_BOOT_DEVICE);
-    }
-}
-
 VOID
 INIT_FUNCTION
 ExpDisplayNotice(VOID)
@@ -469,7 +425,7 @@ ExpLoadInitialProcess(IN PHANDLE ProcessHandle,
     /* Create the environment string */
     RtlInitEmptyUnicodeString(&Environment,
                               ProcessParameters->Environment,
-                              Size);
+                              (USHORT)Size);
 
     /* Append the DLL path to it */
     RtlAppendUnicodeToString(&Environment, L"Path=" );
@@ -663,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;
 }
 
@@ -698,7 +654,7 @@ ExpInitializeExecutive(IN ULONG Cpu,
         if (!HalInitSystem(ExpInitializationPhase, LoaderBlock))
         {
             /* Initialization failed */
-            KEBUGCHECK(HAL_INITIALIZATION_FAILED);
+            KeBugCheck(HAL_INITIALIZATION_FAILED);
         }
 
         /* We're done */
@@ -772,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;
@@ -830,9 +786,15 @@ ExpInitializeExecutive(IN ULONG Cpu,
     /* Set up Region Maps, Sections and the Paging File */
     MmInit2();
 
+    /* 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;
@@ -876,8 +838,11 @@ ExPhase2Init(PVOID Context)
     /* Check if GUI Boot is enabled */
     if (strstr(KeLoaderBlock->LoadOptions, "NOGUIBOOT")) NoGuiBoot = TRUE;
 
+    /* Display the boot screen image if not disabled */
+    if (!ExpInTextModeSetup) InbvDisplayInitialize2(NoGuiBoot);
+    if (!NoGuiBoot) InbvDisplayBootLogo();
+
     /* Clear the screen to blue and display the boot notice and debug status */
-    HalInitSystem(2, KeLoaderBlock);
     if (NoGuiBoot) ExpDisplayNotice();
     KdInitSystem(2, KeLoaderBlock);
 
@@ -934,6 +899,11 @@ ExPhase2Init(PVOID Context)
     }
 
     /* Create SystemRoot Link */
+    Status = ExpCreateSystemRootLink(KeLoaderBlock);
+    if (!NT_SUCCESS(Status))
+    {
+        KeBugCheckEx(SYMBOLIC_INITIALIZATION_FAILED, Status, 0, 0, 0);
+    }
 
     /* Create NLS section */
     ExpInitNls(KeLoaderBlock);
@@ -941,8 +911,8 @@ ExPhase2Init(PVOID Context)
     /* Initialize Cache Views */
     CcInitializeCacheManager();
 
-    /* Initialize the Registry (Hives are NOT yet loaded!) */
-    CmInitSystem1();
+    /* Initialize the Registry */
+    if (!CmInitSystem1()) KeBugCheck(CONFIG_INITIALIZATION_FAILED);
 
     /* Update timezone information */
     ExRefreshTimeZoneInformation(&SystemBootTime);
@@ -956,32 +926,18 @@ ExPhase2Init(PVOID Context)
     /* Initialize LPC */
     LpcpInitSystem();
 
-    /* Initialize I/O Objects, Filesystems, Error Logging and Shutdown */
-    IoInit();
-
-    /* Unmap Low memory, and initialize the MPW and Balancer Thread */
-    MmInit3();
-
-    /* Import and Load Registry Hives */
-    CmInitHives(ExpInTextModeSetup);
-
     /* Enter the kernel debugger before starting up the boot drivers */
     if (KdDebuggerEnabled && KdpEarlyBreak) DbgBreakPoint();
 
-    /* Setup Drivers and Root Device Node */
-    IoInit2(FALSE);
-
-    /* Display the boot screen image if not disabled */
-    if (!NoGuiBoot) InbvEnableBootDriver(TRUE);
-
-    /* Create ARC Names, SystemRoot SymLink, Load Drivers and Assign Letters */
-    IoInit3();
-
-    /* Load the System DLL and its Entrypoints */
-    PsLocateSystemDll();
+    /* Initialize the I/O Subsystem */
+    if (!IoInitSystem(KeLoaderBlock)) KeBugCheck(IO1_INITIALIZATION_FAILED);
 
-    /* Initialize shared user page. Set dos system path, dos device map, etc. */
-    InitSystemSharedUserPage(KeLoaderBlock);
+    /* Unmap Low memory, and initialize the MPW and Balancer Thread */
+    MmInit3();
+#if DBG
+    extern ULONG Guard;
+#endif
+    ASSERT(Guard == 0xCACA1234);
 
     /* Initialize VDM support */
     KeI386VdmInitialize();
@@ -998,6 +954,7 @@ ExPhase2Init(PVOID Context)
     /* 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 */
@@ -1009,12 +966,6 @@ ExPhase2Init(PVOID Context)
         ZwClose(ThreadHandle);
         ZwClose(ProcessHandle);
 
-        /*
-        * FIXME: FILIP!
-        * Disable the Boot Logo
-        */
-        if (!NoGuiBoot) InbvEnableBootDriver(FALSE);
-
         /* FIXME: We should free the initial process' memory!*/
 
         /* Increase init phase */