mirror of
https://github.com/reactos/reactos.git
synced 2024-09-06 19:02:32 +00:00
![Hermès Bélusca-Maïto](/assets/img/avatar_default.png)
CORE-17470 + KdpDebugLogInit: Add resources cleanup in failure code paths. Fix, in an NT-compatible manner, how (and when) the KD/KDBG BootPhase >=2 initialization steps are performed. These are necessary for any functionality KDBG needs, that would depend on the NT I/O Manager and the storage and filesystem stacks to be running. This includes, creating the debug log file, and for KDBG, loading its KDBinit initialization file. As a result, file debug logging is fixed. The old ReactOS-specific (NT-incompatible) callback we did in the middle of IoInitSystem() is removed, in favor of a runtime mechanism that should work on Windows as well. The idea for this new mechanism is loosely inspired by the TDL4 rootkit, see http://blog.w4kfu.com/public/tdl4_article/draft_tdl4article.html but contrary to it, a specific hook is used instead, as well as the technique of driver reinitialization: https://web.archive.org/web/20211021050515/https://driverentry.com.br/en/blog/?p=261 Its rationale is as follows: We want to be able to perform I/O-related initialization (starting a logger thread for file log debugging, loading KDBinit file for KDBG, etc.). A good place for this would be as early as possible, once the I/O Manager has started the storage and the boot filesystem drivers. Here is an overview of the initialization steps of the NT Kernel and Executive: ---- KiSystemStartup(KeLoaderBlock) if (Cpu == 0) KdInitSystem(0, KeLoaderBlock); KiSwitchToBootStack() -> KiSystemStartupBootStack() -> KiInitializeKernel() -> ExpInitializeExecutive(Cpu, KeLoaderBlock) (NOTE: Any unexpected debugger break will call KdInitSystem(0, NULL); ) KdInitSystem(0, LoaderBlock) -> KdDebuggerInitialize0(LoaderBlock); ExpInitializeExecutive(Cpu == 0): ExpInitializationPhase = 0; HalInitSystem(0, KeLoaderBlock); <-- Sets HalInitPnpDriver callback. ... PsInitSystem(LoaderBlock) PsCreateSystemThread(Phase1Initialization) Phase1Initialization(Discard): ExpInitializationPhase = 1; HalInitSystem(1, KeLoaderBlock); ... Early initialization of Ob, Ex, Ke. KdInitSystem(1, KeLoaderBlock); ... KdDebuggerInitialize1(LoaderBlock); ... IoInitSystem(LoaderBlock); ... ---- As we can see, KdDebuggerInitialize1() is the last KD initialization routine the kernel calls, and is called *before* the I/O Manager starts. Thus, direct Nt/ZwCreateFile ... calls done there would fail. Also, we want to do the I/O initialization as soon as possible. There does not seem to be any exported way to be notified about the I/O manager initialization steps... that is, unless we somehow become a driver and insert ourselves in the flow! Since we are not a regular driver, we need to invoke IoCreateDriver() to create one. However, remember that we are currently running *before* IoInitSystem(), the I/O subsystem is not initialized yet. Due to this, calling IoCreateDriver(), much like any other IO functions, would lead to a crash, because it calls ObCreateObject(..., IoDriverObjectType, ...), and IoDriverObjectType is non-initialized yet (it's NULL). The chosen solution is to hook a "known" exported callback: namely, the HalInitPnpDriver() callback (it initializes the "HAL Root Bus Driver"). It is set very early on by the HAL via the HalInitSystem(0, ...) call, and is called early on by IoInitSystem() before any driver is loaded, but after the I/O Manager has been minimally set up so that new drivers can be created. When the hook: KdpInitDriver() is called, we create our driver with IoCreateDriver(), specifying its entrypoint KdpDriverEntry(), then restore and call the original HalInitPnpDriver() callback. Another possible unexplored alternative, could be to insert ourselves in the KeLoaderBlock->LoadOrderListHead boot modules list, or in the KeLoaderBlock->BootDriverListHead boot-driver list. (Note that while we may be able to do this, because boot-drivers are resident in memory, much like we are, we cannot insert ourselves in the system-driver list however, since those drivers are expected to come from PE image files.) Once the KdpDriverEntry() driver entrypoint is called, we register KdpDriverReinit() for re-initialization with the I/O Manager, in order to provide more initialization points. KdpDriverReinit() calls the KD providers at BootPhase >= 2, and schedules further reinitializations (at most 3 more) if any of the providers request so.
656 lines
22 KiB
C
656 lines
22 KiB
C
/*
|
|
* COPYRIGHT: See COPYING in the top level directory
|
|
* PROJECT: ReactOS Kernel
|
|
* FILE: ntoskrnl/io/iomgr/iomgr.c
|
|
* PURPOSE: I/O Manager Initialization and Misc Utility Functions
|
|
*
|
|
* PROGRAMMERS: David Welch (welch@mcmail.com)
|
|
*/
|
|
|
|
/* INCLUDES ****************************************************************/
|
|
|
|
#include <ntoskrnl.h>
|
|
#define NDEBUG
|
|
#include <debug.h>
|
|
|
|
ULONG IopTraceLevel = 0;
|
|
BOOLEAN PnpSystemInit = FALSE;
|
|
|
|
VOID
|
|
NTAPI
|
|
IopTimerDispatch(
|
|
IN PKDPC Dpc,
|
|
IN PVOID DeferredContext,
|
|
IN PVOID SystemArgument1,
|
|
IN PVOID SystemArgument2
|
|
);
|
|
|
|
BOOLEAN
|
|
NTAPI
|
|
WmiInitialize(
|
|
VOID);
|
|
|
|
/* DATA ********************************************************************/
|
|
|
|
POBJECT_TYPE IoDeviceObjectType = NULL;
|
|
POBJECT_TYPE IoFileObjectType = NULL;
|
|
extern POBJECT_TYPE IoControllerObjectType;
|
|
BOOLEAN IoCountOperations = TRUE;
|
|
ULONG IoReadOperationCount = 0;
|
|
LARGE_INTEGER IoReadTransferCount = {{0, 0}};
|
|
ULONG IoWriteOperationCount = 0;
|
|
LARGE_INTEGER IoWriteTransferCount = {{0, 0}};
|
|
ULONG IoOtherOperationCount = 0;
|
|
LARGE_INTEGER IoOtherTransferCount = {{0, 0}};
|
|
KSPIN_LOCK IoStatisticsLock = 0;
|
|
ULONG IopNumTriageDumpDataBlocks;
|
|
PVOID IopTriageDumpDataBlocks[64];
|
|
|
|
GENERIC_MAPPING IopFileMapping = {
|
|
FILE_GENERIC_READ,
|
|
FILE_GENERIC_WRITE,
|
|
FILE_GENERIC_EXECUTE,
|
|
FILE_ALL_ACCESS};
|
|
|
|
extern LIST_ENTRY ShutdownListHead;
|
|
extern LIST_ENTRY LastChanceShutdownListHead;
|
|
extern KSPIN_LOCK ShutdownListLock;
|
|
extern POBJECT_TYPE IoAdapterObjectType;
|
|
extern ERESOURCE IopDatabaseResource;
|
|
ERESOURCE IopSecurityResource;
|
|
extern ERESOURCE IopDriverLoadResource;
|
|
extern LIST_ENTRY IopDiskFileSystemQueueHead;
|
|
extern LIST_ENTRY IopCdRomFileSystemQueueHead;
|
|
extern LIST_ENTRY IopTapeFileSystemQueueHead;
|
|
extern LIST_ENTRY IopNetworkFileSystemQueueHead;
|
|
extern LIST_ENTRY DriverBootReinitListHead;
|
|
extern LIST_ENTRY DriverReinitListHead;
|
|
extern LIST_ENTRY IopFsNotifyChangeQueueHead;
|
|
extern LIST_ENTRY IopErrorLogListHead;
|
|
extern LIST_ENTRY IopTimerQueueHead;
|
|
extern KDPC IopTimerDpc;
|
|
extern KTIMER IopTimer;
|
|
extern KSPIN_LOCK IoStatisticsLock;
|
|
extern KSPIN_LOCK DriverReinitListLock;
|
|
extern KSPIN_LOCK DriverBootReinitListLock;
|
|
extern KSPIN_LOCK IopLogListLock;
|
|
extern KSPIN_LOCK IopTimerLock;
|
|
|
|
extern PDEVICE_OBJECT IopErrorLogObject;
|
|
extern BOOLEAN PnPBootDriversInitialized;
|
|
|
|
GENERAL_LOOKASIDE IoLargeIrpLookaside;
|
|
GENERAL_LOOKASIDE IoSmallIrpLookaside;
|
|
GENERAL_LOOKASIDE IopMdlLookasideList;
|
|
extern GENERAL_LOOKASIDE IoCompletionPacketLookaside;
|
|
|
|
PLOADER_PARAMETER_BLOCK IopLoaderBlock;
|
|
|
|
/* INIT FUNCTIONS ************************************************************/
|
|
|
|
CODE_SEG("INIT")
|
|
VOID
|
|
NTAPI
|
|
IopInitLookasideLists(VOID)
|
|
{
|
|
ULONG LargeIrpSize, SmallIrpSize, MdlSize;
|
|
LONG i;
|
|
PKPRCB Prcb;
|
|
PGENERAL_LOOKASIDE CurrentList = NULL;
|
|
|
|
/* Calculate the sizes */
|
|
LargeIrpSize = sizeof(IRP) + (8 * sizeof(IO_STACK_LOCATION));
|
|
SmallIrpSize = sizeof(IRP) + sizeof(IO_STACK_LOCATION);
|
|
MdlSize = sizeof(MDL) + (23 * sizeof(PFN_NUMBER));
|
|
|
|
/* Initialize the Lookaside List for I\O Completion */
|
|
ExInitializeSystemLookasideList(&IoCompletionPacketLookaside,
|
|
NonPagedPool,
|
|
sizeof(IOP_MINI_COMPLETION_PACKET),
|
|
IOC_TAG1,
|
|
32,
|
|
&ExSystemLookasideListHead);
|
|
|
|
/* Initialize the Lookaside List for Large IRPs */
|
|
ExInitializeSystemLookasideList(&IoLargeIrpLookaside,
|
|
NonPagedPool,
|
|
LargeIrpSize,
|
|
IO_LARGEIRP,
|
|
64,
|
|
&ExSystemLookasideListHead);
|
|
|
|
|
|
/* Initialize the Lookaside List for Small IRPs */
|
|
ExInitializeSystemLookasideList(&IoSmallIrpLookaside,
|
|
NonPagedPool,
|
|
SmallIrpSize,
|
|
IO_SMALLIRP,
|
|
32,
|
|
&ExSystemLookasideListHead);
|
|
|
|
/* Initialize the Lookaside List for MDLs */
|
|
ExInitializeSystemLookasideList(&IopMdlLookasideList,
|
|
NonPagedPool,
|
|
MdlSize,
|
|
TAG_MDL,
|
|
128,
|
|
&ExSystemLookasideListHead);
|
|
|
|
/* Allocate the global lookaside list buffer */
|
|
CurrentList = ExAllocatePoolWithTag(NonPagedPool,
|
|
4 * KeNumberProcessors *
|
|
sizeof(GENERAL_LOOKASIDE),
|
|
TAG_IO);
|
|
|
|
/* Loop all processors */
|
|
for (i = 0; i < KeNumberProcessors; i++)
|
|
{
|
|
/* Get the PRCB for this CPU */
|
|
Prcb = KiProcessorBlock[i];
|
|
DPRINT("Setting up lookaside for CPU: %x, PRCB: %p\n", i, Prcb);
|
|
|
|
/* Write IRP credit limit */
|
|
Prcb->LookasideIrpFloat = 512 / KeNumberProcessors;
|
|
|
|
/* Set the I/O Completion List */
|
|
Prcb->PPLookasideList[LookasideCompletionList].L = &IoCompletionPacketLookaside;
|
|
if (CurrentList)
|
|
{
|
|
/* Initialize the Lookaside List for mini-packets */
|
|
ExInitializeSystemLookasideList(CurrentList,
|
|
NonPagedPool,
|
|
sizeof(IOP_MINI_COMPLETION_PACKET),
|
|
IO_SMALLIRP_CPU,
|
|
32,
|
|
&ExSystemLookasideListHead);
|
|
Prcb->PPLookasideList[LookasideCompletionList].P = CurrentList;
|
|
CurrentList++;
|
|
|
|
}
|
|
else
|
|
{
|
|
Prcb->PPLookasideList[LookasideCompletionList].P = &IoCompletionPacketLookaside;
|
|
}
|
|
|
|
/* Set the Large IRP List */
|
|
Prcb->PPLookasideList[LookasideLargeIrpList].L = &IoLargeIrpLookaside;
|
|
if (CurrentList)
|
|
{
|
|
/* Initialize the Lookaside List for Large IRPs */
|
|
ExInitializeSystemLookasideList(CurrentList,
|
|
NonPagedPool,
|
|
LargeIrpSize,
|
|
IO_LARGEIRP_CPU,
|
|
64,
|
|
&ExSystemLookasideListHead);
|
|
Prcb->PPLookasideList[LookasideLargeIrpList].P = CurrentList;
|
|
CurrentList++;
|
|
|
|
}
|
|
else
|
|
{
|
|
Prcb->PPLookasideList[LookasideLargeIrpList].P = &IoLargeIrpLookaside;
|
|
}
|
|
|
|
/* Set the Small IRP List */
|
|
Prcb->PPLookasideList[LookasideSmallIrpList].L = &IoSmallIrpLookaside;
|
|
if (CurrentList)
|
|
{
|
|
/* Initialize the Lookaside List for Small IRPs */
|
|
ExInitializeSystemLookasideList(CurrentList,
|
|
NonPagedPool,
|
|
SmallIrpSize,
|
|
IO_SMALLIRP_CPU,
|
|
32,
|
|
&ExSystemLookasideListHead);
|
|
Prcb->PPLookasideList[LookasideSmallIrpList].P = CurrentList;
|
|
CurrentList++;
|
|
|
|
}
|
|
else
|
|
{
|
|
Prcb->PPLookasideList[LookasideSmallIrpList].P = &IoSmallIrpLookaside;
|
|
}
|
|
|
|
/* Set the MDL Completion List */
|
|
Prcb->PPLookasideList[LookasideMdlList].L = &IopMdlLookasideList;
|
|
if (CurrentList)
|
|
{
|
|
/* Initialize the Lookaside List for MDLs */
|
|
ExInitializeSystemLookasideList(CurrentList,
|
|
NonPagedPool,
|
|
SmallIrpSize,
|
|
TAG_MDL,
|
|
128,
|
|
&ExSystemLookasideListHead);
|
|
|
|
Prcb->PPLookasideList[LookasideMdlList].P = CurrentList;
|
|
CurrentList++;
|
|
|
|
}
|
|
else
|
|
{
|
|
Prcb->PPLookasideList[LookasideMdlList].P = &IopMdlLookasideList;
|
|
}
|
|
}
|
|
}
|
|
|
|
CODE_SEG("INIT")
|
|
BOOLEAN
|
|
NTAPI
|
|
IopCreateObjectTypes(VOID)
|
|
{
|
|
OBJECT_TYPE_INITIALIZER ObjectTypeInitializer;
|
|
UNICODE_STRING Name;
|
|
|
|
/* Initialize default settings */
|
|
RtlZeroMemory(&ObjectTypeInitializer, sizeof(ObjectTypeInitializer));
|
|
ObjectTypeInitializer.Length = sizeof(ObjectTypeInitializer);
|
|
ObjectTypeInitializer.PoolType = NonPagedPool;
|
|
ObjectTypeInitializer.InvalidAttributes = OBJ_OPENLINK;
|
|
ObjectTypeInitializer.ValidAccessMask = FILE_ALL_ACCESS;
|
|
ObjectTypeInitializer.UseDefaultObject = TRUE;
|
|
ObjectTypeInitializer.GenericMapping = IopFileMapping;
|
|
|
|
/* Do the Adapter Type */
|
|
RtlInitUnicodeString(&Name, L"Adapter");
|
|
if (!NT_SUCCESS(ObCreateObjectType(&Name,
|
|
&ObjectTypeInitializer,
|
|
NULL,
|
|
&IoAdapterObjectType))) return FALSE;
|
|
|
|
/* Do the Controller Type */
|
|
RtlInitUnicodeString(&Name, L"Controller");
|
|
ObjectTypeInitializer.DefaultNonPagedPoolCharge = sizeof(CONTROLLER_OBJECT);
|
|
if (!NT_SUCCESS(ObCreateObjectType(&Name,
|
|
&ObjectTypeInitializer,
|
|
NULL,
|
|
&IoControllerObjectType))) return FALSE;
|
|
|
|
/* Do the Device Type */
|
|
RtlInitUnicodeString(&Name, L"Device");
|
|
ObjectTypeInitializer.DefaultNonPagedPoolCharge = sizeof(DEVICE_OBJECT);
|
|
ObjectTypeInitializer.DeleteProcedure = IopDeleteDevice;
|
|
ObjectTypeInitializer.ParseProcedure = IopParseDevice;
|
|
ObjectTypeInitializer.SecurityProcedure = IopGetSetSecurityObject;
|
|
ObjectTypeInitializer.CaseInsensitive = TRUE;
|
|
if (!NT_SUCCESS(ObCreateObjectType(&Name,
|
|
&ObjectTypeInitializer,
|
|
NULL,
|
|
&IoDeviceObjectType))) return FALSE;
|
|
|
|
/* Initialize the Driver object type */
|
|
RtlInitUnicodeString(&Name, L"Driver");
|
|
ObjectTypeInitializer.DefaultNonPagedPoolCharge = sizeof(DRIVER_OBJECT);
|
|
ObjectTypeInitializer.DeleteProcedure = IopDeleteDriver;
|
|
ObjectTypeInitializer.ParseProcedure = NULL;
|
|
ObjectTypeInitializer.SecurityProcedure = NULL;
|
|
if (!NT_SUCCESS(ObCreateObjectType(&Name,
|
|
&ObjectTypeInitializer,
|
|
NULL,
|
|
&IoDriverObjectType))) return FALSE;
|
|
|
|
/* Initialize the I/O Completion object type */
|
|
RtlInitUnicodeString(&Name, L"IoCompletion");
|
|
ObjectTypeInitializer.DefaultNonPagedPoolCharge = sizeof(KQUEUE);
|
|
ObjectTypeInitializer.ValidAccessMask = IO_COMPLETION_ALL_ACCESS;
|
|
ObjectTypeInitializer.InvalidAttributes |= OBJ_PERMANENT;
|
|
ObjectTypeInitializer.GenericMapping = IopCompletionMapping;
|
|
ObjectTypeInitializer.DeleteProcedure = IopDeleteIoCompletion;
|
|
if (!NT_SUCCESS(ObCreateObjectType(&Name,
|
|
&ObjectTypeInitializer,
|
|
NULL,
|
|
&IoCompletionType))) return FALSE;
|
|
|
|
/* Initialize the File object type */
|
|
RtlInitUnicodeString(&Name, L"File");
|
|
ObjectTypeInitializer.DefaultNonPagedPoolCharge = sizeof(FILE_OBJECT);
|
|
ObjectTypeInitializer.InvalidAttributes |= OBJ_EXCLUSIVE;
|
|
ObjectTypeInitializer.MaintainHandleCount = TRUE;
|
|
ObjectTypeInitializer.ValidAccessMask = FILE_ALL_ACCESS;
|
|
ObjectTypeInitializer.GenericMapping = IopFileMapping;
|
|
ObjectTypeInitializer.CloseProcedure = IopCloseFile;
|
|
ObjectTypeInitializer.DeleteProcedure = IopDeleteFile;
|
|
ObjectTypeInitializer.SecurityProcedure = IopGetSetSecurityObject;
|
|
ObjectTypeInitializer.QueryNameProcedure = IopQueryName;
|
|
ObjectTypeInitializer.ParseProcedure = IopParseFile;
|
|
ObjectTypeInitializer.UseDefaultObject = FALSE;
|
|
if (!NT_SUCCESS(ObCreateObjectType(&Name,
|
|
&ObjectTypeInitializer,
|
|
NULL,
|
|
&IoFileObjectType))) return FALSE;
|
|
|
|
/* Success */
|
|
return TRUE;
|
|
}
|
|
|
|
CODE_SEG("INIT")
|
|
BOOLEAN
|
|
NTAPI
|
|
IopCreateRootDirectories(VOID)
|
|
{
|
|
OBJECT_ATTRIBUTES ObjectAttributes;
|
|
UNICODE_STRING DirName;
|
|
HANDLE Handle;
|
|
NTSTATUS Status;
|
|
|
|
/* Create the '\Driver' object directory */
|
|
RtlInitUnicodeString(&DirName, L"\\Driver");
|
|
InitializeObjectAttributes(&ObjectAttributes,
|
|
&DirName,
|
|
OBJ_PERMANENT,
|
|
NULL,
|
|
NULL);
|
|
Status = NtCreateDirectoryObject(&Handle,
|
|
DIRECTORY_ALL_ACCESS,
|
|
&ObjectAttributes);
|
|
if (!NT_SUCCESS(Status))
|
|
{
|
|
DPRINT1("Failed to create \\Driver directory: 0x%lx\n", Status);
|
|
return FALSE;
|
|
}
|
|
NtClose(Handle);
|
|
|
|
/* Create the '\FileSystem' object directory */
|
|
RtlInitUnicodeString(&DirName, L"\\FileSystem");
|
|
InitializeObjectAttributes(&ObjectAttributes,
|
|
&DirName,
|
|
OBJ_PERMANENT,
|
|
NULL,
|
|
NULL);
|
|
Status = NtCreateDirectoryObject(&Handle,
|
|
DIRECTORY_ALL_ACCESS,
|
|
&ObjectAttributes);
|
|
if (!NT_SUCCESS(Status))
|
|
{
|
|
DPRINT1("Failed to create \\FileSystem directory: 0x%lx\n", Status);
|
|
return FALSE;
|
|
}
|
|
NtClose(Handle);
|
|
|
|
/* Create the '\FileSystem' object directory */
|
|
RtlInitUnicodeString(&DirName, L"\\FileSystem\\Filters");
|
|
InitializeObjectAttributes(&ObjectAttributes,
|
|
&DirName,
|
|
OBJ_PERMANENT,
|
|
NULL,
|
|
NULL);
|
|
Status = NtCreateDirectoryObject(&Handle,
|
|
DIRECTORY_ALL_ACCESS,
|
|
&ObjectAttributes);
|
|
if (!NT_SUCCESS(Status))
|
|
{
|
|
DPRINT1("Failed to create \\FileSystem\\Filters directory: 0x%lx\n", Status);
|
|
return FALSE;
|
|
}
|
|
NtClose(Handle);
|
|
|
|
/* Return success */
|
|
return TRUE;
|
|
}
|
|
|
|
CODE_SEG("INIT")
|
|
BOOLEAN
|
|
NTAPI
|
|
IopMarkBootPartition(IN PLOADER_PARAMETER_BLOCK LoaderBlock)
|
|
{
|
|
OBJECT_ATTRIBUTES ObjectAttributes;
|
|
STRING DeviceString;
|
|
CHAR Buffer[256];
|
|
UNICODE_STRING DeviceName;
|
|
NTSTATUS Status;
|
|
HANDLE FileHandle;
|
|
IO_STATUS_BLOCK IoStatusBlock;
|
|
PFILE_OBJECT FileObject;
|
|
|
|
/* Build the ARC device name */
|
|
sprintf(Buffer, "\\ArcName\\%s", LoaderBlock->ArcBootDeviceName);
|
|
RtlInitAnsiString(&DeviceString, Buffer);
|
|
Status = RtlAnsiStringToUnicodeString(&DeviceName, &DeviceString, TRUE);
|
|
if (!NT_SUCCESS(Status)) return FALSE;
|
|
|
|
/* Open it */
|
|
InitializeObjectAttributes(&ObjectAttributes,
|
|
&DeviceName,
|
|
OBJ_CASE_INSENSITIVE,
|
|
NULL,
|
|
NULL);
|
|
Status = ZwOpenFile(&FileHandle,
|
|
FILE_READ_ATTRIBUTES,
|
|
&ObjectAttributes,
|
|
&IoStatusBlock,
|
|
0,
|
|
FILE_NON_DIRECTORY_FILE);
|
|
if (!NT_SUCCESS(Status))
|
|
{
|
|
/* Fail */
|
|
KeBugCheckEx(INACCESSIBLE_BOOT_DEVICE,
|
|
(ULONG_PTR)&DeviceName,
|
|
Status,
|
|
0,
|
|
0);
|
|
}
|
|
|
|
/* Get the DO */
|
|
Status = ObReferenceObjectByHandle(FileHandle,
|
|
0,
|
|
IoFileObjectType,
|
|
KernelMode,
|
|
(PVOID *)&FileObject,
|
|
NULL);
|
|
if (!NT_SUCCESS(Status))
|
|
{
|
|
/* Fail */
|
|
RtlFreeUnicodeString(&DeviceName);
|
|
return FALSE;
|
|
}
|
|
|
|
/* Mark it as the boot partition */
|
|
FileObject->DeviceObject->Flags |= DO_SYSTEM_BOOT_PARTITION;
|
|
|
|
/* Save a copy of the DO for the I/O Error Logger */
|
|
ObReferenceObject(FileObject->DeviceObject);
|
|
IopErrorLogObject = FileObject->DeviceObject;
|
|
|
|
/* Cleanup and return success */
|
|
RtlFreeUnicodeString(&DeviceName);
|
|
NtClose(FileHandle);
|
|
ObDereferenceObject(FileObject);
|
|
return TRUE;
|
|
}
|
|
|
|
CODE_SEG("INIT")
|
|
BOOLEAN
|
|
NTAPI
|
|
IoInitSystem(IN PLOADER_PARAMETER_BLOCK LoaderBlock)
|
|
{
|
|
LARGE_INTEGER ExpireTime;
|
|
NTSTATUS Status;
|
|
CHAR Buffer[256];
|
|
ANSI_STRING NtBootPath, RootString;
|
|
|
|
/* Initialize empty NT Boot Path */
|
|
RtlInitEmptyAnsiString(&NtBootPath, Buffer, sizeof(Buffer));
|
|
|
|
/* Initialize the lookaside lists */
|
|
IopInitLookasideLists();
|
|
|
|
/* Initialize all locks and lists */
|
|
ExInitializeResourceLite(&IopDatabaseResource);
|
|
ExInitializeResourceLite(&IopSecurityResource);
|
|
ExInitializeResourceLite(&IopDriverLoadResource);
|
|
InitializeListHead(&IopDiskFileSystemQueueHead);
|
|
InitializeListHead(&IopCdRomFileSystemQueueHead);
|
|
InitializeListHead(&IopTapeFileSystemQueueHead);
|
|
InitializeListHead(&IopNetworkFileSystemQueueHead);
|
|
InitializeListHead(&DriverBootReinitListHead);
|
|
InitializeListHead(&DriverReinitListHead);
|
|
InitializeListHead(&ShutdownListHead);
|
|
InitializeListHead(&LastChanceShutdownListHead);
|
|
InitializeListHead(&IopFsNotifyChangeQueueHead);
|
|
InitializeListHead(&IopErrorLogListHead);
|
|
KeInitializeSpinLock(&IoStatisticsLock);
|
|
KeInitializeSpinLock(&DriverReinitListLock);
|
|
KeInitializeSpinLock(&DriverBootReinitListLock);
|
|
KeInitializeSpinLock(&ShutdownListLock);
|
|
KeInitializeSpinLock(&IopLogListLock);
|
|
|
|
/* Initialize PnP notifications */
|
|
PiInitializeNotifications();
|
|
|
|
/* Initialize the reserve IRP */
|
|
if (!IopInitializeReserveIrp(&IopReserveIrpAllocator))
|
|
{
|
|
DPRINT1("IopInitializeReserveIrp failed!\n");
|
|
return FALSE;
|
|
}
|
|
|
|
/* Initialize Timer List Lock */
|
|
KeInitializeSpinLock(&IopTimerLock);
|
|
|
|
/* Initialize Timer List */
|
|
InitializeListHead(&IopTimerQueueHead);
|
|
|
|
/* Initialize the DPC/Timer which will call the other Timer Routines */
|
|
ExpireTime.QuadPart = -10000000;
|
|
KeInitializeDpc(&IopTimerDpc, IopTimerDispatch, NULL);
|
|
KeInitializeTimerEx(&IopTimer, SynchronizationTimer);
|
|
KeSetTimerEx(&IopTimer, ExpireTime, 1000, &IopTimerDpc);
|
|
|
|
/* Create Object Types */
|
|
if (!IopCreateObjectTypes())
|
|
{
|
|
DPRINT1("IopCreateObjectTypes failed!\n");
|
|
return FALSE;
|
|
}
|
|
|
|
/* Create Object Directories */
|
|
if (!IopCreateRootDirectories())
|
|
{
|
|
DPRINT1("IopCreateRootDirectories failed!\n");
|
|
return FALSE;
|
|
}
|
|
|
|
/* Initialize PnP manager */
|
|
IopInitializePlugPlayServices();
|
|
|
|
/* Initialize SHIM engine */
|
|
ApphelpCacheInitialize();
|
|
|
|
/* Initialize WMI */
|
|
WmiInitialize();
|
|
|
|
/* Initialize HAL Root Bus Driver */
|
|
HalInitPnpDriver();
|
|
|
|
/* Reenumerate what HAL has added (synchronously)
|
|
* This function call should eventually become a 2nd stage of the PnP initialization */
|
|
PiQueueDeviceAction(IopRootDeviceNode->PhysicalDeviceObject,
|
|
PiActionEnumRootDevices,
|
|
NULL,
|
|
NULL);
|
|
|
|
/* Make loader block available for the whole kernel */
|
|
IopLoaderBlock = LoaderBlock;
|
|
|
|
/* Load boot start drivers */
|
|
IopInitializeBootDrivers();
|
|
|
|
/* Call back drivers that asked for */
|
|
IopReinitializeBootDrivers();
|
|
|
|
/* Check if this was a ramdisk boot */
|
|
if (!_strnicmp(LoaderBlock->ArcBootDeviceName, "ramdisk(0)", 10))
|
|
{
|
|
/* Initialize the ramdisk driver */
|
|
IopStartRamdisk(LoaderBlock);
|
|
}
|
|
|
|
/* No one should need loader block any longer */
|
|
IopLoaderBlock = NULL;
|
|
|
|
/* Create ARC names for boot devices */
|
|
Status = IopCreateArcNames(LoaderBlock);
|
|
if (!NT_SUCCESS(Status))
|
|
{
|
|
DPRINT1("IopCreateArcNames failed: %lx\n", Status);
|
|
return FALSE;
|
|
}
|
|
|
|
/* Mark the system boot partition */
|
|
if (!IopMarkBootPartition(LoaderBlock))
|
|
{
|
|
DPRINT1("IopMarkBootPartition failed!\n");
|
|
return FALSE;
|
|
}
|
|
|
|
/* The disk subsystem is initialized here and the SystemRoot is set too.
|
|
* We can finally load other drivers from the boot volume. */
|
|
PnPBootDriversInitialized = TRUE;
|
|
|
|
/* Load system start drivers */
|
|
IopInitializeSystemDrivers();
|
|
PnpSystemInit = TRUE;
|
|
|
|
/* Reinitialize drivers that requested it */
|
|
IopReinitializeDrivers();
|
|
|
|
/* Convert SystemRoot from ARC to NT path */
|
|
Status = IopReassignSystemRoot(LoaderBlock, &NtBootPath);
|
|
if (!NT_SUCCESS(Status))
|
|
{
|
|
DPRINT1("IopReassignSystemRoot failed: %lx\n", Status);
|
|
return FALSE;
|
|
}
|
|
|
|
/* Set the ANSI_STRING for the root path */
|
|
RootString.MaximumLength = NtSystemRoot.MaximumLength / sizeof(WCHAR);
|
|
RootString.Length = 0;
|
|
RootString.Buffer = ExAllocatePoolWithTag(PagedPool,
|
|
RootString.MaximumLength,
|
|
TAG_IO);
|
|
|
|
/* Convert the path into the ANSI_STRING */
|
|
Status = RtlUnicodeStringToAnsiString(&RootString, &NtSystemRoot, FALSE);
|
|
if (!NT_SUCCESS(Status))
|
|
{
|
|
DPRINT1("RtlUnicodeStringToAnsiString failed: %lx\n", Status);
|
|
return FALSE;
|
|
}
|
|
|
|
/* Assign drive letters */
|
|
IoAssignDriveLetters(LoaderBlock,
|
|
&NtBootPath,
|
|
(PUCHAR)RootString.Buffer,
|
|
&RootString);
|
|
|
|
/* Update system root */
|
|
Status = RtlAnsiStringToUnicodeString(&NtSystemRoot, &RootString, FALSE);
|
|
if (!NT_SUCCESS(Status))
|
|
{
|
|
DPRINT1("RtlAnsiStringToUnicodeString failed: %lx\n", Status);
|
|
return FALSE;
|
|
}
|
|
|
|
/* Load the System DLL and its entrypoints */
|
|
Status = PsLocateSystemDll();
|
|
if (!NT_SUCCESS(Status))
|
|
{
|
|
DPRINT1("PsLocateSystemDll failed: %lx\n", Status);
|
|
return FALSE;
|
|
}
|
|
|
|
/* Return success */
|
|
return TRUE;
|
|
}
|
|
|
|
BOOLEAN
|
|
NTAPI
|
|
IoInitializeCrashDump(IN HANDLE PageFileHandle)
|
|
{
|
|
UNIMPLEMENTED;
|
|
return FALSE;
|
|
}
|
|
|
|
/* EOF */
|