- Initialize the registry in one shot, and allow it to fail and do the associated CONFIG_INIT_FAILED bugcheck.

- Initialize Io in one shot, with IoInitSystem.
- Locate the system DLL a bit later, since on the boot CD this creates a small incompatibility due to the wrong path being in use.

svn path=/trunk/; revision=24463
This commit is contained in:
Alex Ionescu 2006-10-09 01:16:28 +00:00
parent b772538a22
commit 3012ee8072
5 changed files with 324 additions and 336 deletions

View file

@ -29,7 +29,6 @@
// - FIXES:
// * Sanitize some context fields during conversions.
// * Figure out why the DPC stack doesn't really work.
// * Try to make MmInit1 NTLDR compatible.
// * Add DR macro/save and VM macro/save.
// - FEATURES:
// * New optimized table-based tick-hashed timer implementation.

View file

@ -28,6 +28,8 @@
/* GLOBALS ******************************************************************/
extern BOOLEAN ExpInTextModeSetup;
POBJECT_TYPE CmiKeyType = NULL;
PEREGISTRY_HIVE CmiVolatileHive = NULL;
@ -129,219 +131,6 @@ CmiWorkerThread(PVOID Param)
}
}
VOID
INIT_FUNCTION
STDCALL
CmInitHives(BOOLEAN SetupBoot)
{
PCHAR BaseAddress;
PLIST_ENTRY ListHead, NextEntry;
PMEMORY_ALLOCATION_DESCRIPTOR MdBlock = NULL;
/* Load Registry Hives. This one can be missing. */
BaseAddress = KeLoaderBlock->RegistryBase;
if (BaseAddress)
{
CmImportSystemHive(BaseAddress,
KeLoaderBlock->RegistryLength);
}
/* Loop the memory descriptors */
ListHead = &KeLoaderBlock->MemoryDescriptorListHead;
NextEntry = ListHead->Flink;
while (NextEntry != ListHead)
{
/* Get the current block */
MdBlock = CONTAINING_RECORD(NextEntry,
MEMORY_ALLOCATION_DESCRIPTOR,
ListEntry);
/* Check if this is an registry block */
if (MdBlock->MemoryType == LoaderRegistryData)
{
/* Check if it's not the SYSTEM hive that we already initialized */
if ((MdBlock->BasePage) != ((ULONG_PTR)BaseAddress >> PAGE_SHIFT))
{
/* Hardware hive break out */
break;
}
}
/* Go to the next block */
NextEntry = MdBlock->ListEntry.Flink;
}
/* We need a hardware hive */
ASSERT(MdBlock);
BaseAddress = (PCHAR)(MdBlock->BasePage << PAGE_SHIFT);
CmImportHardwareHive(BaseAddress,
MdBlock->PageCount << PAGE_SHIFT);
/* Create dummy keys if no hardware hive was found */
CmImportHardwareHive (NULL, 0);
/* Initialize volatile registry settings */
if (SetupBoot == FALSE) CmInit2(KeLoaderBlock->LoadOptions);
}
VOID
INIT_FUNCTION
NTAPI
CmInitSystem1(VOID)
{
OBJECT_ATTRIBUTES ObjectAttributes;
UNICODE_STRING KeyName;
PKEY_OBJECT RootKey;
#if 0
PCM_KEY_SECURITY RootSecurityCell;
#endif
HANDLE RootKeyHandle;
HANDLE KeyHandle;
NTSTATUS Status;
LARGE_INTEGER DueTime;
HANDLE ThreadHandle;
CLIENT_ID ThreadId;
OBJECT_TYPE_INITIALIZER ObjectTypeInitializer;
UNICODE_STRING Name;
DPRINT("Creating Registry Object Type\n");
/* Initialize the Key object type */
RtlZeroMemory(&ObjectTypeInitializer, sizeof(ObjectTypeInitializer));
RtlInitUnicodeString(&Name, L"Key");
ObjectTypeInitializer.Length = sizeof(ObjectTypeInitializer);
ObjectTypeInitializer.DefaultPagedPoolCharge = sizeof(KEY_OBJECT);
ObjectTypeInitializer.GenericMapping = CmiKeyMapping;
ObjectTypeInitializer.PoolType = PagedPool;
ObjectTypeInitializer.ValidAccessMask = KEY_ALL_ACCESS;
ObjectTypeInitializer.UseDefaultObject = TRUE;
ObjectTypeInitializer.DeleteProcedure = CmiObjectDelete;
ObjectTypeInitializer.ParseProcedure = CmiObjectParse;
ObjectTypeInitializer.SecurityProcedure = CmiObjectSecurity;
ObjectTypeInitializer.QueryNameProcedure = CmiObjectQueryName;
ObCreateObjectType(&Name, &ObjectTypeInitializer, NULL, &CmiKeyType);
/* Initialize the hive list */
InitializeListHead(&CmiHiveListHead);
/* Initialize registry lock */
ExInitializeResourceLite(&CmiRegistryLock);
/* Initialize the key object list */
InitializeListHead(&CmiKeyObjectListHead);
InitializeListHead(&CmiConnectedHiveList);
/* Initialize the worker timer */
KeInitializeTimerEx(&CmiWorkerTimer, SynchronizationTimer);
/* Initialize the worker thread */
Status = PsCreateSystemThread(&ThreadHandle,
THREAD_ALL_ACCESS,
NULL,
NULL,
&ThreadId,
CmiWorkerThread,
NULL);
if (!NT_SUCCESS(Status))
{
KEBUGCHECK(0);
}
/* Start the timer */
DueTime.QuadPart = -1;
KeSetTimerEx(&CmiWorkerTimer, DueTime, 5000, NULL); /* 5sec */
/* Build volatile registry store */
Status = CmiCreateVolatileHive (&CmiVolatileHive);
ASSERT(NT_SUCCESS(Status));
InitializeListHead(&CmiCallbackHead);
ExInitializeFastMutex(&CmiCallbackLock);
/* Create '\Registry' key. */
RtlInitUnicodeString(&KeyName, REG_ROOT_KEY_NAME);
InitializeObjectAttributes(&ObjectAttributes, &KeyName, 0, NULL, NULL);
Status = ObCreateObject(KernelMode,
CmiKeyType,
&ObjectAttributes,
KernelMode,
NULL,
sizeof(KEY_OBJECT),
0,
0,
(PVOID *) &RootKey);
ASSERT(NT_SUCCESS(Status));
Status = ObInsertObject(RootKey,
NULL,
KEY_ALL_ACCESS,
0,
NULL,
&RootKeyHandle);
ASSERT(NT_SUCCESS(Status));
RootKey->RegistryHive = CmiVolatileHive;
RootKey->KeyCellOffset = CmiVolatileHive->Hive.HiveHeader->RootCell;
RootKey->KeyCell = HvGetCell (&CmiVolatileHive->Hive, RootKey->KeyCellOffset);
RootKey->ParentKey = RootKey;
RootKey->Flags = 0;
RootKey->SubKeyCounts = 0;
RootKey->SubKeys = NULL;
RootKey->SizeOfSubKeys = 0;
InsertTailList(&CmiKeyObjectListHead, &RootKey->ListEntry);
Status = RtlpCreateUnicodeString(&RootKey->Name, L"Registry", NonPagedPool);
ASSERT(NT_SUCCESS(Status));
#if 0
Status = CmiAllocateCell(CmiVolatileHive,
0x10, //LONG CellSize,
(PVOID *)&RootSecurityCell,
&RootKey->KeyCell->SecurityKeyOffset);
ASSERT(NT_SUCCESS(Status));
/* Copy the security descriptor */
CmiVolatileHive->RootSecurityCell = RootSecurityCell;
#endif
/* Create '\Registry\Machine' key. */
RtlInitUnicodeString(&KeyName,
L"Machine");
InitializeObjectAttributes(&ObjectAttributes,
&KeyName,
0,
RootKeyHandle,
NULL);
Status = ZwCreateKey(&KeyHandle,
KEY_ALL_ACCESS,
&ObjectAttributes,
0,
NULL,
REG_OPTION_VOLATILE,
NULL);
ASSERT(NT_SUCCESS(Status));
/* Create '\Registry\User' key. */
RtlInitUnicodeString(&KeyName,
L"User");
InitializeObjectAttributes(&ObjectAttributes,
&KeyName,
0,
RootKeyHandle,
NULL);
Status = ZwCreateKey(&KeyHandle,
KEY_ALL_ACCESS,
&ObjectAttributes,
0,
NULL,
REG_OPTION_VOLATILE,
NULL);
ASSERT(NT_SUCCESS(Status));
}
VOID INIT_FUNCTION
CmInit2(PCHAR CommandLine)
{
@ -452,6 +241,220 @@ CmInit2(PCHAR CommandLine)
}
VOID
INIT_FUNCTION
STDCALL
CmInitHives(BOOLEAN SetupBoot)
{
PCHAR BaseAddress;
PLIST_ENTRY ListHead, NextEntry;
PMEMORY_ALLOCATION_DESCRIPTOR MdBlock = NULL;
/* Load Registry Hives. This one can be missing. */
BaseAddress = KeLoaderBlock->RegistryBase;
if (BaseAddress)
{
CmImportSystemHive(BaseAddress,
KeLoaderBlock->RegistryLength);
}
/* Loop the memory descriptors */
ListHead = &KeLoaderBlock->MemoryDescriptorListHead;
NextEntry = ListHead->Flink;
while (NextEntry != ListHead)
{
/* Get the current block */
MdBlock = CONTAINING_RECORD(NextEntry,
MEMORY_ALLOCATION_DESCRIPTOR,
ListEntry);
/* Check if this is an registry block */
if (MdBlock->MemoryType == LoaderRegistryData)
{
/* Check if it's not the SYSTEM hive that we already initialized */
if ((MdBlock->BasePage) != ((ULONG_PTR)BaseAddress >> PAGE_SHIFT))
{
/* Hardware hive break out */
break;
}
}
/* Go to the next block */
NextEntry = MdBlock->ListEntry.Flink;
}
/* We need a hardware hive */
ASSERT(MdBlock);
BaseAddress = (PCHAR)(MdBlock->BasePage << PAGE_SHIFT);
CmImportHardwareHive(BaseAddress,
MdBlock->PageCount << PAGE_SHIFT);
/* Create dummy keys if no hardware hive was found */
CmImportHardwareHive (NULL, 0);
/* Initialize volatile registry settings */
if (SetupBoot == FALSE) CmInit2(KeLoaderBlock->LoadOptions);
}
BOOLEAN
INIT_FUNCTION
NTAPI
CmInitSystem1(VOID)
{
OBJECT_ATTRIBUTES ObjectAttributes;
UNICODE_STRING KeyName;
PKEY_OBJECT RootKey;
#if 0
PCM_KEY_SECURITY RootSecurityCell;
#endif
HANDLE RootKeyHandle;
HANDLE KeyHandle;
NTSTATUS Status;
LARGE_INTEGER DueTime;
HANDLE ThreadHandle;
CLIENT_ID ThreadId;
OBJECT_TYPE_INITIALIZER ObjectTypeInitializer;
UNICODE_STRING Name;
DPRINT("Creating Registry Object Type\n");
/* Initialize the Key object type */
RtlZeroMemory(&ObjectTypeInitializer, sizeof(ObjectTypeInitializer));
RtlInitUnicodeString(&Name, L"Key");
ObjectTypeInitializer.Length = sizeof(ObjectTypeInitializer);
ObjectTypeInitializer.DefaultPagedPoolCharge = sizeof(KEY_OBJECT);
ObjectTypeInitializer.GenericMapping = CmiKeyMapping;
ObjectTypeInitializer.PoolType = PagedPool;
ObjectTypeInitializer.ValidAccessMask = KEY_ALL_ACCESS;
ObjectTypeInitializer.UseDefaultObject = TRUE;
ObjectTypeInitializer.DeleteProcedure = CmiObjectDelete;
ObjectTypeInitializer.ParseProcedure = CmiObjectParse;
ObjectTypeInitializer.SecurityProcedure = CmiObjectSecurity;
ObjectTypeInitializer.QueryNameProcedure = CmiObjectQueryName;
ObCreateObjectType(&Name, &ObjectTypeInitializer, NULL, &CmiKeyType);
/* Initialize the hive list */
InitializeListHead(&CmiHiveListHead);
/* Initialize registry lock */
ExInitializeResourceLite(&CmiRegistryLock);
/* Initialize the key object list */
InitializeListHead(&CmiKeyObjectListHead);
InitializeListHead(&CmiConnectedHiveList);
/* Initialize the worker timer */
KeInitializeTimerEx(&CmiWorkerTimer, SynchronizationTimer);
/* Initialize the worker thread */
Status = PsCreateSystemThread(&ThreadHandle,
THREAD_ALL_ACCESS,
NULL,
NULL,
&ThreadId,
CmiWorkerThread,
NULL);
if (!NT_SUCCESS(Status)) return FALSE;
/* Start the timer */
DueTime.QuadPart = -1;
KeSetTimerEx(&CmiWorkerTimer, DueTime, 5000, NULL); /* 5sec */
/* Build volatile registry store */
Status = CmiCreateVolatileHive (&CmiVolatileHive);
ASSERT(NT_SUCCESS(Status));
InitializeListHead(&CmiCallbackHead);
ExInitializeFastMutex(&CmiCallbackLock);
/* Create '\Registry' key. */
RtlInitUnicodeString(&KeyName, REG_ROOT_KEY_NAME);
InitializeObjectAttributes(&ObjectAttributes, &KeyName, 0, NULL, NULL);
Status = ObCreateObject(KernelMode,
CmiKeyType,
&ObjectAttributes,
KernelMode,
NULL,
sizeof(KEY_OBJECT),
0,
0,
(PVOID *) &RootKey);
ASSERT(NT_SUCCESS(Status));
Status = ObInsertObject(RootKey,
NULL,
KEY_ALL_ACCESS,
0,
NULL,
&RootKeyHandle);
ASSERT(NT_SUCCESS(Status));
RootKey->RegistryHive = CmiVolatileHive;
RootKey->KeyCellOffset = CmiVolatileHive->Hive.HiveHeader->RootCell;
RootKey->KeyCell = HvGetCell (&CmiVolatileHive->Hive, RootKey->KeyCellOffset);
RootKey->ParentKey = RootKey;
RootKey->Flags = 0;
RootKey->SubKeyCounts = 0;
RootKey->SubKeys = NULL;
RootKey->SizeOfSubKeys = 0;
InsertTailList(&CmiKeyObjectListHead, &RootKey->ListEntry);
Status = RtlpCreateUnicodeString(&RootKey->Name, L"Registry", NonPagedPool);
ASSERT(NT_SUCCESS(Status));
#if 0
Status = CmiAllocateCell(CmiVolatileHive,
0x10, //LONG CellSize,
(PVOID *)&RootSecurityCell,
&RootKey->KeyCell->SecurityKeyOffset);
ASSERT(NT_SUCCESS(Status));
/* Copy the security descriptor */
CmiVolatileHive->RootSecurityCell = RootSecurityCell;
#endif
/* Create '\Registry\Machine' key. */
RtlInitUnicodeString(&KeyName,
L"Machine");
InitializeObjectAttributes(&ObjectAttributes,
&KeyName,
0,
RootKeyHandle,
NULL);
Status = ZwCreateKey(&KeyHandle,
KEY_ALL_ACCESS,
&ObjectAttributes,
0,
NULL,
REG_OPTION_VOLATILE,
NULL);
ASSERT(NT_SUCCESS(Status));
/* Create '\Registry\User' key. */
RtlInitUnicodeString(&KeyName,
L"User");
InitializeObjectAttributes(&ObjectAttributes,
&KeyName,
0,
RootKeyHandle,
NULL);
Status = ZwCreateKey(&KeyHandle,
KEY_ALL_ACCESS,
&ObjectAttributes,
0,
NULL,
REG_OPTION_VOLATILE,
NULL);
ASSERT(NT_SUCCESS(Status));
/* Import and Load Registry Hives */
CmInitHives(ExpInTextModeSetup);
return TRUE;
}
static NTSTATUS
CmiCreateCurrentControlSetLink(VOID)
{

View file

@ -654,7 +654,7 @@ ExpInitializeExecutive(IN ULONG Cpu,
if (!HalInitSystem(ExpInitializationPhase, LoaderBlock))
{
/* Initialization failed */
KEBUGCHECK(HAL_INITIALIZATION_FAILED);
KeBugCheck(HAL_INITIALIZATION_FAILED);
}
/* We're done */
@ -728,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;
@ -902,8 +902,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);
@ -917,15 +917,6 @@ 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();
@ -935,6 +926,9 @@ ExPhase2Init(PVOID Context)
/* Display the boot screen image if not disabled */
if (!NoGuiBoot) InbvEnableBootDriver(TRUE);
/* Unmap Low memory, and initialize the MPW and Balancer Thread */
MmInit3();
/* Initialize VDM support */
KeI386VdmInitialize();

View file

@ -60,11 +60,8 @@ typedef struct __DESCRIPTOR
* Initalization functions (called once by main())
*/
VOID MmInitSystem(ULONG Phase, PLOADER_PARAMETER_BLOCK LoaderBlock, ULONG LastKernelAddress);
VOID IoInit(VOID);
BOOLEAN NTAPI ObInit(VOID);
VOID NTAPI CmInitSystem1(VOID);
VOID NTAPI CmInitHives(BOOLEAN SetupBoot);
VOID CmInit2(PCHAR CommandLine);
BOOLEAN NTAPI CmInitSystem1(VOID);
VOID CmShutdownRegistry(VOID);
BOOLEAN CmImportSystemHive(PCHAR ChunkBase, ULONG ChunkSize);
BOOLEAN CmImportHardwareHive(PCHAR ChunkBase, ULONG ChunkSize);

View file

@ -229,10 +229,18 @@ IopInitLookasideLists(VOID)
DPRINT("Done allocation\n");
}
VOID
BOOLEAN
INIT_FUNCTION
IoInit (VOID)
NTAPI
IoInitSystem(IN PLOADER_PARAMETER_BLOCK LoaderBlock)
{
PDEVICE_NODE DeviceNode;
PDRIVER_OBJECT DriverObject;
LDR_DATA_TABLE_ENTRY ModuleObject;
NTSTATUS Status;
CHAR Buffer[256];
ANSI_STRING NtBootPath, RootString;
OBJECT_TYPE_INITIALIZER ObjectTypeInitializer;
UNICODE_STRING Name;
OBJECT_ATTRIBUTES ObjectAttributes;
@ -297,113 +305,100 @@ IoInit (VOID)
ObjectTypeInitializer.UseDefaultObject = FALSE;
ObCreateObjectType(&Name, &ObjectTypeInitializer, NULL, &IoFileObjectType);
/*
* Create the '\Driver' object directory
*/
RtlInitUnicodeString(&DirName, L"\\Driver");
InitializeObjectAttributes(&ObjectAttributes,
&DirName,
0,
NULL,
NULL);
ZwCreateDirectoryObject(&Handle,
0,
&ObjectAttributes);
/*
* Create the '\Driver' object directory
*/
RtlInitUnicodeString(&DirName, L"\\Driver");
InitializeObjectAttributes(&ObjectAttributes,
&DirName,
0,
NULL,
NULL);
ZwCreateDirectoryObject(&Handle,
0,
&ObjectAttributes);
/*
* Create the '\FileSystem' object directory
*/
RtlInitUnicodeString(&DirName,
L"\\FileSystem");
InitializeObjectAttributes(&ObjectAttributes,
&DirName,
0,
NULL,
NULL);
ZwCreateDirectoryObject(&Handle,
0,
&ObjectAttributes);
/*
* Create the '\FileSystem' object directory
*/
RtlInitUnicodeString(&DirName,
L"\\FileSystem");
InitializeObjectAttributes(&ObjectAttributes,
&DirName,
0,
NULL,
NULL);
ZwCreateDirectoryObject(&Handle,
0,
&ObjectAttributes);
/*
* Create the '\Device' directory
*/
RtlInitUnicodeString(&DirName,
L"\\Device");
InitializeObjectAttributes(&ObjectAttributes,
&DirName,
0,
NULL,
NULL);
ZwCreateDirectoryObject(&Handle,
0,
&ObjectAttributes);
/*
* Create the '\Device' directory
*/
RtlInitUnicodeString(&DirName,
L"\\Device");
InitializeObjectAttributes(&ObjectAttributes,
&DirName,
0,
NULL,
NULL);
ZwCreateDirectoryObject(&Handle,
0,
&ObjectAttributes);
/*
* Create the '\??' directory
*/
RtlInitUnicodeString(&DirName,
L"\\??");
InitializeObjectAttributes(&ObjectAttributes,
&DirName,
0,
NULL,
NULL);
ZwCreateDirectoryObject(&Handle,
0,
&ObjectAttributes);
/*
* Create the '\??' directory
*/
RtlInitUnicodeString(&DirName,
L"\\??");
InitializeObjectAttributes(&ObjectAttributes,
&DirName,
0,
NULL,
NULL);
ZwCreateDirectoryObject(&Handle,
0,
&ObjectAttributes);
/*
* Create the '\ArcName' directory
*/
RtlInitUnicodeString(&DirName,
L"\\ArcName");
InitializeObjectAttributes(&ObjectAttributes,
&DirName,
0,
NULL,
NULL);
ZwCreateDirectoryObject(&Handle,
0,
&ObjectAttributes);
/*
* Create the '\ArcName' directory
*/
RtlInitUnicodeString(&DirName,
L"\\ArcName");
InitializeObjectAttributes(&ObjectAttributes,
&DirName,
0,
NULL,
NULL);
ZwCreateDirectoryObject(&Handle,
0,
&ObjectAttributes);
/*
* Initialize remaining subsubsystem
*/
IopInitDriverImplementation();
IoInitCancelHandling();
IoInitFileSystemImplementation();
IoInitVpbImplementation();
IoInitShutdownNotification();
IopInitPnpNotificationImplementation();
IopInitErrorLog();
IopInitTimerImplementation();
IopInitLookasideLists();
/*
* Initialize remaining subsubsystem
*/
IopInitDriverImplementation();
IoInitCancelHandling();
IoInitFileSystemImplementation();
IoInitVpbImplementation();
IoInitShutdownNotification();
IopInitPnpNotificationImplementation();
IopInitErrorLog();
IopInitTimerImplementation();
IopInitLookasideLists();
/*
* Create link from '\DosDevices' to '\??' directory
*/
RtlInitUnicodeString(&DirName,
L"\\??");
IoCreateSymbolicLink(&LinkName,
&DirName);
/*
* Create link from '\DosDevices' to '\??' directory
*/
RtlInitUnicodeString(&DirName,
L"\\??");
IoCreateSymbolicLink(&LinkName,
&DirName);
/*
* Initialize PnP manager
*/
PnpInit();
}
BOOLEAN
INIT_FUNCTION
NTAPI
IoInitSystem(IN PLOADER_PARAMETER_BLOCK LoaderBlock)
{
PDEVICE_NODE DeviceNode;
PDRIVER_OBJECT DriverObject;
LDR_DATA_TABLE_ENTRY ModuleObject;
NTSTATUS Status;
CHAR Buffer[256];
ANSI_STRING NtBootPath, RootString;
/*
* Initialize PnP manager
*/
PnpInit();
RtlInitEmptyAnsiString(&NtBootPath, Buffer, sizeof(Buffer));
@ -480,9 +475,6 @@ IoInitSystem(IN PLOADER_PARAMETER_BLOCK LoaderBlock)
/* Load services for devices found by PnP manager */
IopInitializePnpServices(IopRootDeviceNode, FALSE);
/* Load the System DLL and its Entrypoints */
if (!NT_SUCCESS(PsLocateSystemDll())) return FALSE;
/* Load system start drivers */
IopInitializeSystemDrivers();
@ -517,6 +509,9 @@ IoInitSystem(IN PLOADER_PARAMETER_BLOCK LoaderBlock)
Status = RtlAnsiStringToUnicodeString(&NtSystemRoot, &RootString, FALSE);
if (!NT_SUCCESS(Status)) return FALSE;
/* Load the System DLL and its Entrypoints */
if (!NT_SUCCESS(PsLocateSystemDll())) return FALSE;
/* Return success */
return TRUE;
}