#define NDEBUG
#include <internal/debug.h>
-ULONG IopTraceLevel = IO_IRP_DEBUG;
+ULONG IopTraceLevel = 0; //IO_API_DEBUG | IO_FILE_DEBUG;
+
+// should go into a proper header
+VOID
+NTAPI
+IoSynchronousInvalidateDeviceRelations(
+ IN PDEVICE_OBJECT DeviceObject,
+ IN DEVICE_RELATION_TYPE Type
+);
+
+VOID
+NTAPI
+IopTimerDispatch(
+ IN PKDPC Dpc,
+ IN PVOID DeferredContext,
+ IN PVOID SystemArgument1,
+ IN PVOID SystemArgument2
+);
/* DATA ********************************************************************/
POBJECT_TYPE IoDeviceObjectType = NULL;
POBJECT_TYPE IoFileObjectType = NULL;
extern POBJECT_TYPE IoControllerObjectType;
+extern UNICODE_STRING NtSystemRoot;
BOOLEAN IoCountOperations;
ULONG IoReadOperationCount = 0;
LARGE_INTEGER IoReadTransferCount = {{0, 0}};
extern KSPIN_LOCK ShutdownListLock;
extern NPAGED_LOOKASIDE_LIST IoCompletionPacketLookaside;
extern POBJECT_TYPE IoAdapterObjectType;
+ERESOURCE IopDatabaseResource;
+extern ERESOURCE FileSystemListLock;
+ERESOURCE IopSecurityResource;
+extern KGUARDED_MUTEX FsChangeNotifyListLock;
+extern KGUARDED_MUTEX PnpNotifyListLock;
+extern LIST_ENTRY IopDiskFsListHead;
+extern LIST_ENTRY IopCdRomFsListHead;
+extern LIST_ENTRY IopTapeFsListHead;
+extern LIST_ENTRY IopNetworkFsListHead;
+extern LIST_ENTRY DriverBootReinitListHead;
+extern LIST_ENTRY DriverReinitListHead;
+extern LIST_ENTRY PnpNotifyListHead;
+extern LIST_ENTRY FsChangeNotifyListHead;
+extern LIST_ENTRY IopErrorLogListHead;
+extern LIST_ENTRY IopTimerQueueHead;
+extern KDPC IopTimerDpc;
+extern KTIMER IopTimer;
+extern KSPIN_LOCK CancelSpinLock;
+extern KSPIN_LOCK IoVpbLock;
+extern KSPIN_LOCK IoStatisticsLock;
+extern KSPIN_LOCK DriverReinitListLock;
+extern KSPIN_LOCK DriverBootReinitListLock;
+extern KSPIN_LOCK IopLogListLock;
+extern KSPIN_LOCK IopTimerLock;
+
+extern PDEVICE_OBJECT IopErrorLogObject;
+
NPAGED_LOOKASIDE_LIST IoLargeIrpLookaside;
NPAGED_LOOKASIDE_LIST IoSmallIrpLookaside;
NPAGED_LOOKASIDE_LIST IopMdlLookasideList;
-VOID INIT_FUNCTION IopInitLookasideLists(VOID);
-
#if defined (ALLOC_PRAGMA)
-#pragma alloc_text(INIT, IoInitCancelHandling)
-#pragma alloc_text(INIT, IoInitShutdownNotification)
-#pragma alloc_text(INIT, IopInitLookasideLists)
-#pragma alloc_text(INIT, IoInit)
-#pragma alloc_text(INIT, IoInit2)
-#pragma alloc_text(INIT, IoInit3)
+#pragma alloc_text(INIT, IoInitSystem)
#endif
/* INIT FUNCTIONS ************************************************************/
VOID
INIT_FUNCTION
-IoInitCancelHandling(VOID)
-{
- extern KSPIN_LOCK CancelSpinLock;
- KeInitializeSpinLock(&CancelSpinLock);
-}
-
-VOID
-INIT_FUNCTION
-IoInitShutdownNotification (VOID)
-{
- InitializeListHead(&ShutdownListHead);
- KeInitializeSpinLock(&ShutdownListLock);
-}
-
-VOID
-INIT_FUNCTION
+NTAPI
IopInitLookasideLists(VOID)
{
ULONG LargeIrpSize, SmallIrpSize, MdlSize;
}
Prcb->PPLookasideList[LookasideMdlList].P = &CurrentList->L;
}
-
- DPRINT("Done allocation\n");
}
-VOID
+BOOLEAN
INIT_FUNCTION
-IoInit (VOID)
+NTAPI
+IopCreateObjectTypes(VOID)
{
OBJECT_TYPE_INITIALIZER ObjectTypeInitializer;
UNICODE_STRING Name;
- OBJECT_ATTRIBUTES ObjectAttributes;
- UNICODE_STRING DirName;
- UNICODE_STRING LinkName = RTL_CONSTANT_STRING(L"\\DosDevices");
- HANDLE Handle;
/* Initialize default settings */
RtlZeroMemory(&ObjectTypeInitializer, sizeof(ObjectTypeInitializer));
/* Do the Adapter Type */
RtlInitUnicodeString(&Name, L"Adapter");
- ObCreateObjectType(&Name, &ObjectTypeInitializer, NULL, &IoAdapterObjectType);
+ if (!NT_SUCCESS(ObCreateObjectType(&Name,
+ &ObjectTypeInitializer,
+ NULL,
+ &IoAdapterObjectType))) return FALSE;
/* Do the Controller Type */
RtlInitUnicodeString(&Name, L"Controller");
ObjectTypeInitializer.DefaultNonPagedPoolCharge = sizeof(CONTROLLER_OBJECT);
- ObCreateObjectType(&Name, &ObjectTypeInitializer, NULL, &IoControllerObjectType);
+ if (!NT_SUCCESS(ObCreateObjectType(&Name,
+ &ObjectTypeInitializer,
+ NULL,
+ &IoControllerObjectType))) return FALSE;
- /* Do the Device Type */
+ /* Do the Device Type. FIXME: Needs Delete Routine! */
RtlInitUnicodeString(&Name, L"Device");
ObjectTypeInitializer.DefaultNonPagedPoolCharge = sizeof(DEVICE_OBJECT);
ObjectTypeInitializer.ParseProcedure = IopParseDevice;
ObjectTypeInitializer.SecurityProcedure = IopSecurityFile;
- ObCreateObjectType(&Name, &ObjectTypeInitializer, NULL, &IoDeviceObjectType);
+ if (!NT_SUCCESS(ObCreateObjectType(&Name,
+ &ObjectTypeInitializer,
+ NULL,
+ &IoDeviceObjectType))) return FALSE;
/* Initialize the Driver object type */
RtlInitUnicodeString(&Name, L"Driver");
ObjectTypeInitializer.DeleteProcedure = IopDeleteDriver;
ObjectTypeInitializer.ParseProcedure = NULL;
ObjectTypeInitializer.SecurityProcedure = NULL;
- ObCreateObjectType(&Name, &ObjectTypeInitializer, NULL, &IoDriverObjectType);
+ if (!NT_SUCCESS(ObCreateObjectType(&Name,
+ &ObjectTypeInitializer,
+ NULL,
+ &IoDriverObjectType))) return FALSE;
/* Initialize the I/O Completion object type */
RtlInitUnicodeString(&Name, L"IoCompletion");
ObjectTypeInitializer.InvalidAttributes |= OBJ_PERMANENT;
ObjectTypeInitializer.GenericMapping = IopCompletionMapping;
ObjectTypeInitializer.DeleteProcedure = IopDeleteIoCompletion;
- ObCreateObjectType(&Name, &ObjectTypeInitializer, NULL, &IoCompletionType);
+ if (!NT_SUCCESS(ObCreateObjectType(&Name,
+ &ObjectTypeInitializer,
+ NULL,
+ &IoCompletionType))) return FALSE;
/* Initialize the File object type */
RtlInitUnicodeString(&Name, L"File");
ObjectTypeInitializer.QueryNameProcedure = IopQueryNameFile;
ObjectTypeInitializer.ParseProcedure = IopParseFile;
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 '\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 '\??' 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);
-
- /*
- * Initialize remaining subsubsystem
- */
- IopInitDriverImplementation();
- IoInitCancelHandling();
- IoInitFileSystemImplementation();
- IoInitVpbImplementation();
- IoInitShutdownNotification();
- IopInitPnpNotificationImplementation();
- IopInitErrorLog();
- IopInitTimerImplementation();
- IopInitLookasideLists();
-
- /*
- * Create link from '\DosDevices' to '\??' directory
- */
- RtlInitUnicodeString(&DirName,
- L"\\??");
- IoCreateSymbolicLink(&LinkName,
- &DirName);
-
- /*
- * Initialize PnP manager
- */
- PnpInit();
+ if (!NT_SUCCESS(ObCreateObjectType(&Name,
+ &ObjectTypeInitializer,
+ NULL,
+ &IoFileObjectType))) return FALSE;
+
+ /* Success */
+ return TRUE;
}
-VOID
+BOOLEAN
INIT_FUNCTION
-IoInit2(BOOLEAN BootLog)
+NTAPI
+IopCreateRootDirectories()
{
- PDEVICE_NODE DeviceNode;
- PDRIVER_OBJECT DriverObject;
- LDR_DATA_TABLE_ENTRY ModuleObject;
- NTSTATUS Status;
-
- PnpInit2();
-
- IoCreateDriverList();
-
- KeInitializeSpinLock (&IoStatisticsLock);
+ OBJECT_ATTRIBUTES ObjectAttributes;
+ UNICODE_STRING DirName;
+ HANDLE Handle;
- /* Initialize raw filesystem driver */
+ /* Create the '\Driver' object directory */
+ RtlInitUnicodeString(&DirName, L"\\Driver");
+ InitializeObjectAttributes(&ObjectAttributes,
+ &DirName,
+ OBJ_PERMANENT,
+ NULL,
+ NULL);
+ if (!NT_SUCCESS(NtCreateDirectoryObject(&Handle,
+ DIRECTORY_ALL_ACCESS,
+ &ObjectAttributes))) return FALSE;
+ NtClose(Handle);
+
+ /* Create the '\FileSystem' object directory */
+ RtlInitUnicodeString(&DirName, L"\\FileSystem");
+ InitializeObjectAttributes(&ObjectAttributes,
+ &DirName,
+ OBJ_PERMANENT,
+ NULL,
+ NULL);
+ if (!NT_SUCCESS(NtCreateDirectoryObject(&Handle,
+ DIRECTORY_ALL_ACCESS,
+ &ObjectAttributes))) return FALSE;
+ NtClose(Handle);
+
+ /* Return success */
+ return TRUE;
+}
- /* Use IopRootDeviceNode for now */
- Status = IopCreateDeviceNode(IopRootDeviceNode,
- NULL,
- &DeviceNode);
- if (!NT_SUCCESS(Status))
+BOOLEAN
+INIT_FUNCTION
+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))
{
- CPRINT("IopCreateDeviceNode() failed with status (%x)\n", Status);
- return;
+ /* Fail */
+ KeBugCheckEx(INACCESSIBLE_BOOT_DEVICE,
+ (ULONG_PTR)&DeviceName,
+ Status,
+ 0,
+ 0);
}
- ModuleObject.DllBase = NULL;
- ModuleObject.SizeOfImage = 0;
- ModuleObject.EntryPoint = RawFsDriverEntry;
-
- Status = IopInitializeDriverModule(
- DeviceNode,
- &ModuleObject,
- &DeviceNode->ServiceName,
- TRUE,
- &DriverObject);
- if (!NT_SUCCESS(Status))
+ /* Get the DO */
+ Status = ObReferenceObjectByHandle(FileHandle,
+ 0,
+ IoFileObjectType,
+ KernelMode,
+ (PVOID *)&FileObject,
+ NULL);
+ if (!NT_SUCCESS(Status))
{
- IopFreeDeviceNode(DeviceNode);
- CPRINT("IopInitializeDriver() failed with status (%x)\n", Status);
- return;
+ /* Fail */
+ RtlFreeUnicodeString(&DeviceName);
+ return FALSE;
}
- Status = IopInitializeDevice(DeviceNode, DriverObject);
- if (!NT_SUCCESS(Status))
- {
- IopFreeDeviceNode(DeviceNode);
- CPRINT("IopInitializeDevice() failed with status (%x)\n", Status);
- return;
- }
+ /* Mark it as the boot partition */
+ FileObject->DeviceObject->Flags |= DO_SYSTEM_BOOT_PARTITION;
- Status = IopStartDevice(DeviceNode);
- if (!NT_SUCCESS(Status))
- {
- IopFreeDeviceNode(DeviceNode);
- CPRINT("IopInitializeDevice() failed with status (%x)\n", Status);
- return;
- }
+ /* 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;
+}
+
+BOOLEAN
+INIT_FUNCTION
+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 */
+ ExInitializeResource(&IopDatabaseResource);
+ ExInitializeResource(&FileSystemListLock);
+ ExInitializeResource(&IopSecurityResource);
+ KeInitializeGuardedMutex(&FsChangeNotifyListLock);
+ KeInitializeGuardedMutex(&PnpNotifyListLock);
+ InitializeListHead(&IopDiskFsListHead);
+ InitializeListHead(&IopCdRomFsListHead);
+ InitializeListHead(&IopTapeFsListHead);
+ InitializeListHead(&IopNetworkFsListHead);
+ InitializeListHead(&DriverBootReinitListHead);
+ InitializeListHead(&DriverReinitListHead);
+ InitializeListHead(&PnpNotifyListHead);
+ InitializeListHead(&ShutdownListHead);
+ InitializeListHead(&FsChangeNotifyListHead);
+ InitializeListHead(&IopErrorLogListHead);
+ KeInitializeSpinLock(&CancelSpinLock);
+ KeInitializeSpinLock(&IoVpbLock);
+ KeInitializeSpinLock(&IoStatisticsLock);
+ KeInitializeSpinLock(&DriverReinitListLock);
+ KeInitializeSpinLock(&DriverBootReinitListLock);
+ KeInitializeSpinLock(&ShutdownListLock);
+ KeInitializeSpinLock(&IopLogListLock);
+
+ /* 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()) return FALSE;
- /*
- * Initialize PnP root releations
- */
- IopInvalidateDeviceRelations(
- IopRootDeviceNode,
- BusRelations);
+ /* Create Object Directories */
+ if (!IopCreateRootDirectories()) return FALSE;
- /* Start boot logging */
- IopInitBootLog(BootLog);
+ /* Initialize PnP manager */
+ PnpInit();
+
+ /* Initialize PnP root relations */
+ IoSynchronousInvalidateDeviceRelations(IopRootDeviceNode->
+ PhysicalDeviceObject,
+ BusRelations);
+
+ /* Create the group driver list */
+ IoCreateDriverList();
/* Load boot start drivers */
IopInitializeBootDrivers();
/* Call back drivers that asked for */
IopReinitializeBootDrivers();
-}
-
-VOID
-STDCALL
-INIT_FUNCTION
-IoInit3(VOID)
-{
- NTSTATUS Status;
/* Create ARC names for boot devices */
- IoCreateArcNames();
-
- /* Create the SystemRoot symbolic link */
- DPRINT("CommandLine: %s\n", (PCHAR)KeLoaderBlock.CommandLine);
- Status = IoCreateSystemRootLink((PCHAR)KeLoaderBlock.CommandLine);
- if (!NT_SUCCESS(Status)) {
- CPRINT("IoCreateSystemRootLink FAILED: (0x%x) - ", Status);
- KEBUGCHECK(INACCESSIBLE_BOOT_DEVICE);
- }
+ IopCreateArcNames(LoaderBlock);
+
+ /* Mark the system boot partition */
+ if (!IopMarkBootPartition(LoaderBlock)) return FALSE;
/* Read KDB Data */
KdbInit();
/* I/O is now setup for disk access, so phase 3 */
- KdInitSystem(3, (PROS_LOADER_PARAMETER_BLOCK)&KeLoaderBlock);
+ KdInitSystem(3, LoaderBlock);
/* Load services for devices found by PnP manager */
IopInitializePnpServices(IopRootDeviceNode, FALSE);
/* Load system start drivers */
IopInitializeSystemDrivers();
+
+ /* Destroy the group driver list */
IoDestroyDriverList();
/* Reinitialize drivers that requested it */
IopReinitializeDrivers();
- /* Stop boot logging */
- IopStopBootLog();
+ /* Convert SystemRoot from ARC to NT path */
+ Status = IopReassignSystemRoot(LoaderBlock, &NtBootPath);
+ if (!NT_SUCCESS(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)) return FALSE;
/* Assign drive letters */
- IoAssignDriveLetters((PLOADER_PARAMETER_BLOCK)&KeLoaderBlock,
- NULL,
- NULL,
- NULL);
+ IoAssignDriveLetters(LoaderBlock,
+ &NtBootPath,
+ (PUCHAR)RootString.Buffer,
+ &RootString);
+
+ /* Update system root */
+ 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;
}
/* EOF */