- Fix KiDispatchException to unmask KI_EXCEPTION_INTERNAL when setting the exception...
[reactos.git] / reactos / ntoskrnl / io / iomgr / iomgr.c
index 6d47c12..c90778a 100644 (file)
 #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}};
@@ -39,41 +57,46 @@ extern LIST_ENTRY ShutdownListHead;
 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;
@@ -217,20 +240,15 @@ IopInitLookasideLists(VOID)
         }
         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));
@@ -243,19 +261,28 @@ IoInit (VOID)
 
     /* 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");
@@ -263,7 +290,10 @@ IoInit (VOID)
     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");
@@ -272,7 +302,10 @@ IoInit (VOID)
     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");
@@ -287,223 +320,251 @@ IoInit (VOID)
     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 */