- Added support for NTLDR style freeloader GUI. To enable, edit freeldr.ini and add:
[reactos.git] / reactos / ntoskrnl / ex / init.c
index 6737db0..2847aaf 100644 (file)
@@ -3,15 +3,13 @@
  * PROJECT:         ReactOS kernel
  * 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)
  */
 
 #include <ntoskrnl.h>
-#include <ntos/bootvid.h>
-#include "../dbg/kdb.h"
 #define NDEBUG
 #include <internal/debug.h>
 
@@ -27,18 +25,30 @@ extern ULONG_PTR LastKrnlPhysAddr;
 extern ULONG_PTR LastKernelAddress;
 extern LOADER_MODULE KeLoaderModules[64];
 extern PRTL_MESSAGE_RESOURCE_DATA KiBugCodeMessages;
-#if 0
 extern LIST_ENTRY KiProfileListHead;
 extern LIST_ENTRY KiProfileSourceListHead;
 extern KSPIN_LOCK KiProfileLock;
-#endif
+BOOLEAN SetupMode = TRUE;
+BOOLEAN NoGuiBoot = FALSE;
 
 VOID PspPostInitSystemProcess(VOID);
 
+static VOID INIT_FUNCTION InitSystemSharedUserPage (PCSZ ParameterLine);
+VOID INIT_FUNCTION ExpDisplayNotice(VOID);
+INIT_FUNCTION NTSTATUS ExpLoadInitialProcess(PHANDLE ProcessHandle, PHANDLE ThreadHandle);
+
+#if defined (ALLOC_PRAGMA)
+#pragma alloc_text(INIT, InitSystemSharedUserPage)
+#pragma alloc_text(INIT, ExpDisplayNotice)
+#pragma alloc_text(INIT, ExpLoadInitialProcess)
+#pragma alloc_text(INIT, ExpInitializeExecutive)
+#pragma alloc_text(INIT, ExInit2)
+#endif
+
 /* FUNCTIONS ****************************************************************/
 
-static 
-VOID 
+static
+VOID
 INIT_FUNCTION
 InitSystemSharedUserPage (PCSZ ParameterLine)
 {
@@ -64,13 +74,13 @@ InitSystemSharedUserPage (PCSZ ParameterLine)
     *   There is NO need to do this again.
     */
     Ki386SetProcessorFeatures();
-    
+
     /* Set the Version Data */
     SharedUserData->NtProductType = NtProductWinNt;
     SharedUserData->ProductTypeIsValid = TRUE;
     SharedUserData->NtMajorVersion = 5;
     SharedUserData->NtMinorVersion = 0;
-   
+
     /*
      * Retrieve the current dos system path
      * (e.g.: C:\reactos) from the given arc path
@@ -80,7 +90,7 @@ InitSystemSharedUserPage (PCSZ ParameterLine)
 
     /* Create local parameter line copy */
     ParamBuffer = ExAllocatePool(PagedPool, 256);
-    strcpy (ParamBuffer, (char *)ParameterLine);
+    strcpy (ParamBuffer, (const char *)ParameterLine);
     DPRINT("%s\n", ParamBuffer);
 
     /* Cut options off */
@@ -91,18 +101,18 @@ InitSystemSharedUserPage (PCSZ ParameterLine)
     /* Extract path */
     p = strchr (ParamBuffer, '\\');
     if (p) {
-        
+
         DPRINT("Boot path: %s\n", p);
         RtlCreateUnicodeStringFromAsciiz (&BootPath, p);
         *p = 0;
-    
+
     } else {
-        
+
         DPRINT("Boot path: %s\n", "\\");
         RtlCreateUnicodeStringFromAsciiz (&BootPath, "\\");
     }
     DPRINT("Arc name: %s\n", ParamBuffer);
-   
+
     /* Only ARC Name left - Build full ARC Name */
     ArcNameBuffer = ExAllocatePool (PagedPool, 256 * sizeof(WCHAR));
     swprintf (ArcNameBuffer, L"\\ArcName\\%S", ParamBuffer);
@@ -126,32 +136,32 @@ InitSystemSharedUserPage (PCSZ ParameterLine)
     Status = NtOpenSymbolicLinkObject(&Handle,
                                       SYMBOLIC_LINK_ALL_ACCESS,
                                       &ObjectAttributes);
-    
+
     /* Free the String */
-    RtlFreeUnicodeString(&ArcName);
-    
+    ExFreePool(ArcName.Buffer);
+
     /* Check for Success */
     if (!NT_SUCCESS(Status)) {
-        
+
         /* Free the Strings */
         RtlFreeUnicodeString(&BootPath);
-        RtlFreeUnicodeString(&ArcDeviceName);
+        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);
-        RtlFreeUnicodeString(&ArcDeviceName);
+        ExFreePool(ArcDeviceName.Buffer);
         CPRINT("NtQuerySymbolicLinkObject() failed (Status %x)\n", Status);
         KEBUGCHECK(0);
     }
@@ -164,12 +174,12 @@ InitSystemSharedUserPage (PCSZ ParameterLine)
 
     /* 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,
@@ -179,18 +189,18 @@ InitSystemSharedUserPage (PCSZ ParameterLine)
         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);
@@ -200,7 +210,7 @@ InitSystemSharedUserPage (PCSZ ParameterLine)
 
         /* 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;
@@ -209,21 +219,21 @@ InitSystemSharedUserPage (PCSZ ParameterLine)
         /* Close this Link */
         NtClose (Handle);
     }
-    
+
     /* Free all the Strings we have in memory */
     RtlFreeUnicodeString (&BootPath);
-    RtlFreeUnicodeString (&DriveDeviceName);
-    RtlFreeUnicodeString (&ArcDeviceName);
+    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);
     }
 }
 
-inline
+__inline
 VOID
 STDCALL
 ExecuteRuntimeAsserts(VOID)
@@ -232,6 +242,7 @@ ExecuteRuntimeAsserts(VOID)
      * Fail at runtime if someone has changed various structures without
      * updating the offsets used for the assembler code.
      */
+    ASSERT(FIELD_OFFSET(KUSER_SHARED_DATA, SystemCall) == 0x300);
     ASSERT(FIELD_OFFSET(KTHREAD, InitialStack) == KTHREAD_INITIAL_STACK);
     ASSERT(FIELD_OFFSET(KTHREAD, Teb) == KTHREAD_TEB);
     ASSERT(FIELD_OFFSET(KTHREAD, KernelStack) == KTHREAD_KERNEL_STACK);
@@ -244,148 +255,251 @@ ExecuteRuntimeAsserts(VOID)
     ASSERT(FIELD_OFFSET(KPROCESS, DirectoryTableBase) == KPROCESS_DIRECTORY_TABLE_BASE);
     ASSERT(FIELD_OFFSET(KPROCESS, IopmOffset) == KPROCESS_IOPM_OFFSET);
     ASSERT(FIELD_OFFSET(KPROCESS, LdtDescriptor) == KPROCESS_LDT_DESCRIPTOR0);
-    ASSERT(FIELD_OFFSET(KTRAP_FRAME, Reserved9) == KTRAP_FRAME_RESERVED9);
     ASSERT(FIELD_OFFSET(KV86M_TRAP_FRAME, SavedExceptionStack) == TF_SAVED_EXCEPTION_STACK);
     ASSERT(FIELD_OFFSET(KV86M_TRAP_FRAME, regs) == TF_REGS);
     ASSERT(FIELD_OFFSET(KV86M_TRAP_FRAME, orig_ebp) == TF_ORIG_EBP);
     ASSERT(FIELD_OFFSET(KPCR, Tib.ExceptionList) == KPCR_EXCEPTION_LIST);
     ASSERT(FIELD_OFFSET(KPCR, Self) == KPCR_SELF);
-    ASSERT(FIELD_OFFSET(KPCR, PrcbData) + FIELD_OFFSET(KPRCB, CurrentThread) == KPCR_CURRENT_THREAD);  
-    ASSERT(FIELD_OFFSET(KPCR, PrcbData) + FIELD_OFFSET(KPRCB, NpxThread) == KPCR_NPX_THREAD);
+    ASSERT(FIELD_OFFSET(KIPCR, PrcbData) + FIELD_OFFSET(KPRCB, CurrentThread) == KPCR_CURRENT_THREAD);
+    ASSERT(FIELD_OFFSET(KIPCR, PrcbData) + FIELD_OFFSET(KPRCB, NpxThread) == KPCR_NPX_THREAD);
     ASSERT(FIELD_OFFSET(KTSS, Esp0) == KTSS_ESP0);
-    ASSERT(FIELD_OFFSET(KTSS, Eflags) == KTSS_EFLAGS);
     ASSERT(FIELD_OFFSET(KTSS, IoMapBase) == KTSS_IOMAPBASE);
     ASSERT(sizeof(FX_SAVE_AREA) == SIZEOF_FX_SAVE_AREA);
 }
 
-inline
+__inline
 VOID
 STDCALL
-ParseAndCacheLoadedModules(PBOOLEAN SetupBoot)
+ParseAndCacheLoadedModules(VOID)
 {
     ULONG i;
     PCHAR Name;
-    
+
     /* Loop the Module List and get the modules we want */
     for (i = 1; i < KeLoaderBlock.ModsCount; i++) {
-       
+
         /* 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];
-            *SetupBoot = FALSE;
-      
+            SetupMode = FALSE;
+
         } else if (!_stricmp(Name, "hardware") || !_stricmp(Name, "hardware.hiv")) {
-      
+
             CachedModules[HardwareRegistry] = &KeLoaderModules[i];
         }
-    }    
+    }
 }
 
-inline
+__inline
 VOID
 STDCALL
-ParseCommandLine(PULONG MaxMem, 
-                 PBOOLEAN NoGuiBoot, 
-                 PBOOLEAN BootLog, 
+ParseCommandLine(PULONG MaxMem,
+                 PBOOLEAN NoGuiBoot,
+                 PBOOLEAN BootLog,
                  PBOOLEAN ForceAcpiDisable)
 {
-    PCHAR p1, p2; 
-    
+    PCHAR p1, p2;
+
     p1 = (PCHAR)KeLoaderBlock.CommandLine;
     while(*p1 && (p2 = strchr(p1, '/'))) {
-        
+
         p2++;
         if (!_strnicmp(p2, "MAXMEM", 6)) {
-            
+
             p2 += 6;
             while (isspace(*p2)) p2++;
-            
+
             if (*p2 == '=') {
-                
+
                 p2++;
-                
+
                 while(isspace(*p2)) p2++;
-                
+
                 if (isdigit(*p2)) {
                     while (isdigit(*p2)) {
                         *MaxMem = *MaxMem * 10 + *p2 - '0';
                         p2++;
-                    }                
+                    }
                     break;
                 }
             }
         } else if (!_strnicmp(p2, "NOGUIBOOT", 9)) {
-            
+
             p2 += 9;
             *NoGuiBoot = TRUE;
-            
+
         } else if (!_strnicmp(p2, "CRASHDUMP", 9)) {
-            
+
             p2 += 9;
             if (*p2 == ':') {
-                
+
                 p2++;
                 if (!_strnicmp(p2, "FULL", 4)) {
-                    
+
                     MmCoreDumpType = MM_CORE_DUMP_TYPE_FULL;
-                    
+
                 } else {
-                    
+
                     MmCoreDumpType = MM_CORE_DUMP_TYPE_NONE;
                 }
             }
         } else if (!_strnicmp(p2, "BOOTLOG", 7)) {
-            
+
             p2 += 7;
             *BootLog = TRUE;
         } else if (!_strnicmp(p2, "NOACPI", 6)) {
-            
+
             p2 += 6;
             *ForceAcpiDisable = TRUE;
         }
-        
+
         p1 = p2;
     }
 }
+   
+VOID
+INIT_FUNCTION
+ExpDisplayNotice(VOID)
+{
+    CHAR str[50];
+   
+    if (SetupMode)
+    {
+        HalDisplayString(
+        "\n\n\n     ReactOS " KERNEL_VERSION_STR " Setup \n");
+        HalDisplayString(
+        "    \xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD");
+        HalDisplayString(
+        "\xCD\xCD\n");
+        return;
+    }
+    
+    HalDisplayString("Starting ReactOS "KERNEL_VERSION_STR" (Build "
+                     KERNEL_VERSION_BUILD_STR")\n");
+    HalDisplayString(RES_STR_LEGAL_COPYRIGHT);
+    HalDisplayString("\n\nReactOS is free software, covered by the GNU General "
+                     "Public License, and you\n");
+    HalDisplayString("are welcome to change it and/or distribute copies of it "
+                     "under certain\n");
+    HalDisplayString("conditions. There is absolutely no warranty for "
+                      "ReactOS.\n\n");
+
+    /* Display number of Processors */
+    sprintf(str,
+            "Found %x system processor(s). [%lu MB Memory]\n",
+            (int)KeNumberProcessors,
+            (KeLoaderBlock.MemHigher + 1088)/ 1024);
+    HalDisplayString(str);
+    
+}
 
-VOID 
+INIT_FUNCTION
+NTSTATUS
+ExpLoadInitialProcess(PHANDLE ProcessHandle,
+                      PHANDLE ThreadHandle)
+{
+    UNICODE_STRING ImagePath = RTL_CONSTANT_STRING(L"\\SystemRoot\\system32\\smss.exe");
+    HANDLE SystemProcessHandle;
+    NTSTATUS Status;
+    PRTL_USER_PROCESS_PARAMETERS Params=NULL;
+    RTL_USER_PROCESS_INFORMATION Info;
+
+    /* Create a handle to the process */
+    Status = ObpCreateHandle(PsInitialSystemProcess,
+                             PROCESS_CREATE_PROCESS | PROCESS_CREATE_THREAD | PROCESS_QUERY_INFORMATION,
+                             OBJ_KERNEL_HANDLE,
+                             &SystemProcessHandle);
+    if(!NT_SUCCESS(Status))
+    {
+        DPRINT1("Failed to create a handle for the system process!\n");
+        return Status;
+    }
+
+    /* Create the Parameters */
+    Status = RtlCreateProcessParameters(&Params,
+                                        &ImagePath,
+                                        NULL,
+                                        NULL,
+                                        NULL,
+                                        NULL,
+                                        NULL,
+                                        NULL,
+                                        NULL,
+                                        NULL);
+    if(!NT_SUCCESS(Status))
+    {
+        DPRINT1("Failed to create ppb!\n");
+        ZwClose(SystemProcessHandle);
+        return Status;
+    }
+
+    DPRINT("Creating process\n");
+    Status = RtlCreateUserProcess(&ImagePath,
+                                  OBJ_CASE_INSENSITIVE,
+                                  Params,
+                                  NULL,
+                                  NULL,
+                                  SystemProcessHandle,
+                                  FALSE,
+                                  NULL,
+                                  NULL,
+                                  &Info);
+    
+    /* Close the handle and free the params */
+    ZwClose(SystemProcessHandle);
+    RtlDestroyProcessParameters(Params);
+
+    if (!NT_SUCCESS(Status))
+    {
+        DPRINT1("NtCreateProcess() failed (Status %lx)\n", Status);
+        return(Status);
+    }
+
+    /* Start it up */
+    ZwResumeThread(Info.ThreadHandle, NULL);
+
+    /* Return Handles */
+    *ProcessHandle = Info.ProcessHandle;
+    *ThreadHandle = Info.ThreadHandle;
+    DPRINT("Process created successfully\n");
+    return STATUS_SUCCESS;
+}
+   
+VOID
 INIT_FUNCTION
 STDCALL
 ExpInitializeExecutive(VOID)
 {
-    CHAR str[50];
     UNICODE_STRING EventName;
     HANDLE InitDoneEventHandle;
     OBJECT_ATTRIBUTES ObjectAttributes;
-    BOOLEAN NoGuiBoot = FALSE;
     BOOLEAN BootLog = FALSE;
     ULONG MaxMem = 0;
-    BOOLEAN SetupBoot = TRUE;
     BOOLEAN ForceAcpiDisable = FALSE;
     LARGE_INTEGER Timeout;
     HANDLE ProcessHandle;
@@ -394,19 +508,19 @@ ExpInitializeExecutive(VOID)
 
     /* Check if the structures match the ASM offset constants */
     ExecuteRuntimeAsserts();
-    
+
     /* Sets up the Text Sections of the Kernel and HAL for debugging */
     LdrInit1();
-    
+
     /* Lower the IRQL to Dispatch Level */
     KeLowerIrql(DISPATCH_LEVEL);
-    
+
     /* Sets up the VDM Data */
     NtEarlyInitVdm();
 
     /* Parse Command Line Settings */
     ParseCommandLine(&MaxMem, &NoGuiBoot, &BootLog, &ForceAcpiDisable);
-    
+
     /* Initialize Kernel Memory Address Space */
     MmInit1(FirstKrnlPhysAddr,
             LastKrnlPhysAddr,
@@ -416,33 +530,28 @@ ExpInitializeExecutive(VOID)
             MaxMem > 8 ? MaxMem : 4096);
 
     /* Parse the Loaded Modules (by FreeLoader) and cache the ones we'll need */
-    ParseAndCacheLoadedModules(&SetupBoot);
-    
-    /* Initialize the kernel debugger */
-    KdInitSystem (1, (PLOADER_PARAMETER_BLOCK)&KeLoaderBlock);
-    
+    ParseAndCacheLoadedModules();
+
     /* Initialize the Dispatcher, Clock and Bug Check Mechanisms. */
     KeInit2();
 
     /* Bring back the IRQL to Passive */
     KeLowerIrql(PASSIVE_LEVEL);
-    
-#if 0
+
     /* Initialize Profiling */
     InitializeListHead(&KiProfileListHead);
     InitializeListHead(&KiProfileSourceListHead);
     KeInitializeSpinLock(&KiProfileLock);
-#endif
-    
+
     /* Load basic Security for other Managers */
     if (!SeInit1()) KEBUGCHECK(SECURITY_INITIALIZATION_FAILED);
 
     /* Create the Basic Object Manager Types to allow new Object Types */
     ObInit();
-    
+
     /* Initialize Lookaside Lists */
-    ExInit2();
-    
+    ExpInitLookasideLists();
+
     /* Set up Region Maps, Sections and the Paging File */
     MmInit2();
 
@@ -454,21 +563,21 @@ ExpInitializeExecutive(VOID)
     
     /* Initalize the Process Manager */
     PiInitProcessManager();
-
+    
     /* Break into the Debugger if requested */
     if (KdPollBreakIn()) DbgBreakPointWithStatus (DBG_STATUS_CONTROL_C);
 
     /* Initialize all processors */
     while (!HalAllProcessorsStarted()) {
-        
+
         PVOID ProcessorStack;
 
         /* Set up the Kernel and Process Manager for this CPU */
         KePrepareForApplicationProcessorInit(KeNumberProcessors);
-        PsPrepareForApplicationProcessorInit(KeNumberProcessors);
+        KeCreateApplicationProcessorIdleThread(KeNumberProcessors);
 
         /* Allocate a stack for use when booting the processor */
-        ProcessorStack = Ki386InitialStackArray[((int)KeNumberProcessors)] + MM_STACK_SIZE;
+        ProcessorStack = RVA(Ki386InitialStackArray[((int)KeNumberProcessors)], MM_STACK_SIZE);
 
         /* Tell HAL a new CPU is being started */
         HalStartNextProcessor(0, (ULONG)ProcessorStack - 2*sizeof(FX_SAVE_AREA));
@@ -477,10 +586,10 @@ ExpInitializeExecutive(VOID)
 
     /* Do Phase 1 HAL Initalization */
     HalInitSystem(1, (PLOADER_PARAMETER_BLOCK)&KeLoaderBlock);
-    
+
     /* Initialize Basic System Objects and Worker Threads */
-    ExInit3();
-    
+    ExInit2();
+
     /* Create the system handle table, assign it to the system process, create
        the client id table and assign a PID for the system process. This needs
        to be done before the worker threads are initialized so the system
@@ -488,88 +597,72 @@ ExpInitializeExecutive(VOID)
     PspPostInitSystemProcess();
 
     /* initialize the worker threads */
-    ExInitializeWorkerThreads();
-    
+    ExpInitializeWorkerThreads();
+
     /* initialize callbacks */
     ExpInitializeCallbacks();
-    
-    /* Initialize the GDB Stub and break */
-    KdInit1();
-  
+
+    /* Call KD Providers at Phase 1 */
+    KdInitSystem(1, (PLOADER_PARAMETER_BLOCK)&KeLoaderBlock);
+
     /* Initialize I/O Objects, Filesystems, Error Logging and Shutdown */
     IoInit();
-    
+
     /* TBD */
     PoInit((PLOADER_PARAMETER_BLOCK)&KeLoaderBlock, ForceAcpiDisable);
-  
+
     /* 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();
-  
-    /* Hook System Interrupt for the Debugger */
-    KdInit2();
-    
+
     /* Initialize File Locking */
     FsRtlpInitFileLockingImplementation();
 
     /* Report all resources used by hal */
-    HalReportResourceUsage();  
+    HalReportResourceUsage();
 
     /* Clear the screen to blue */
     HalInitSystem(2, (PLOADER_PARAMETER_BLOCK)&KeLoaderBlock);
 
     /* Display version number and copyright/warranty message */
-    HalDisplayString("Starting ReactOS "KERNEL_VERSION_STR" (Build "
-                     KERNEL_VERSION_BUILD_STR")\n");
-    HalDisplayString(RES_STR_LEGAL_COPYRIGHT);
-    HalDisplayString("\n\nReactOS is free software, covered by the GNU General "
-                     "Public License, and you\n");
-    HalDisplayString("are welcome to change it and/or distribute copies of it "
-                     "under certain\n"); 
-    HalDisplayString("conditions. There is absolutely no warranty for "
-                      "ReactOS.\n\n");
-
-    /* Display number of Processors */
-    sprintf(str,
-            "Found %d system processor(s). [%lu MB Memory]\n",
-            KeNumberProcessors,
-            (KeLoaderBlock.MemHigher + 1088)/ 1024);
-    HalDisplayString(str);
+    if (NoGuiBoot) ExpDisplayNotice();
 
-    /* Print which Debugger is being used */
-    KdInit3();
+    /* Call KD Providers at Phase 2 */
+    KdInitSystem(2, (PLOADER_PARAMETER_BLOCK)&KeLoaderBlock);
 
     /* Import and create NLS Data and Sections */
     RtlpInitNls();
 
     /* Import and Load Registry Hives */
-    CmInitHives(SetupBoot);
-    
+    CmInitHives(SetupMode);
+
     /* Initialize the time zone information from the registry */
     ExpInitTimeZoneInfo();
-   
-  /* Enter the kernel debugger before starting up the boot drivers */
-#ifdef KDBG
-    KdbEnter();
-#endif /* KDBG */
+
+    /* Enter the kernel debugger before starting up the boot drivers */
+    if (KdDebuggerEnabled && KdpEarlyBreak)
+        DbgBreakPoint();
 
     /* Setup Drivers and Root Device Node */
     IoInit2(BootLog);
 
     /* 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 Default Locale */
     PiInitDefaultLocale();
-    
+
     /* Initialize shared user page. Set dos system path, dos device map, etc. */
     InitSystemSharedUserPage ((PCHAR)KeLoaderBlock.CommandLine);
 
@@ -585,21 +678,21 @@ ExpInitializeExecutive(VOID)
                            &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;
     }
 
     /* Launch initial process */
-    Status = LdrLoadInitialProcess(&ProcessHandle,
+    Status = ExpLoadInitialProcess(&ProcessHandle,
                                    &ThreadHandle);
-    
+
     /* Check for success, Bugcheck if we failed */
     if (!NT_SUCCESS(Status)) {
-        
+
         KEBUGCHECKEX(SESSION4_INITIALIZATION_FAILED, Status, 0, 0, 0);
     }
 
@@ -620,28 +713,31 @@ ExpInitializeExecutive(VOID)
                                           FALSE,
                                           &Timeout);
         if (!NT_SUCCESS(Status)) {
-            
+
             DPRINT1("NtWaitForMultipleObjects failed with status 0x%x!\n", Status);
-        
+
         } else if (Status == STATUS_TIMEOUT) {
-            
+
             DPRINT1("WARNING: System not initialized after 120 seconds.\n");
-        
+
         } else if (Status == STATUS_WAIT_0 + 1) {
-            
+
             /* Crash the system if the initial process was terminated. */
             KEBUGCHECKEX(SESSION5_INITIALIZATION_FAILED, Status, 0, 0, 0);
         }
 
-        /* Disable the Boot Logo */
+        /*
+         * FIXME: FILIP!
+         * Disable the Boot Logo
+         */
         if (!NoGuiBoot) InbvEnableBootDriver(FALSE);
 
         /* Signal the Event and close the handle */
         ZwSetEvent(InitDoneEventHandle, NULL);
         ZwClose(InitDoneEventHandle);
-    
+
     } else {
-        
+
         /* On failure to create 'ReactOSInitDone' event, go to text mode ASAP */
         if (!NoGuiBoot) InbvEnableBootDriver(FALSE);
 
@@ -650,36 +746,32 @@ ExpInitializeExecutive(VOID)
         Status = ZwWaitForSingleObject(ProcessHandle,
                                        FALSE,
                                        &Timeout);
-        
+
         /* Check for timeout, crash if the initial process didn't initalize */
         if (Status != STATUS_TIMEOUT) KEBUGCHECKEX(SESSION5_INITIALIZATION_FAILED, Status, 1, 0, 0);
     }
-    
+
     /* Enable the Clock, close remaining handles */
     KiTimerSystemAuditing = 1;
     ZwClose(ThreadHandle);
     ZwClose(ProcessHandle);
 }
 
-VOID INIT_FUNCTION
+VOID
+STDCALL
+INIT_FUNCTION
 ExInit2(VOID)
 {
-  ExpInitLookasideLists();
-}
-
-VOID INIT_FUNCTION
-ExInit3 (VOID)
-{
-  ExpInitializeEventImplementation();
-  ExpInitializeEventPairImplementation();
-  ExpInitializeMutantImplementation();
-  ExpInitializeSemaphoreImplementation();
-  ExpInitializeTimerImplementation();
-  LpcpInitSystem();
-  ExpInitializeProfileImplementation();
-  ExpWin32kInit();
-  ExpInitUuids();
-  ExpInitializeHandleTables();
+    ExpInitializeEventImplementation();
+    ExpInitializeEventPairImplementation();
+    ExpInitializeMutantImplementation();
+    ExpInitializeSemaphoreImplementation();
+    ExpInitializeTimerImplementation();
+    LpcpInitSystem();
+    ExpInitializeProfileImplementation();
+    ExpWin32kInit();
+    ExpInitUuids();
+    ExpInitializeHandleTables();
 }
 
 /* EOF */