[NTOSKRNL]
[reactos.git] / reactos / ntoskrnl / io / iomgr / device.c
index 482f730..88e5ba4 100644 (file)
 /* GLOBALS ********************************************************************/
 
 ULONG IopDeviceObjectNumber = 0;
-
 LIST_ENTRY ShutdownListHead, LastChanceShutdownListHead;
 KSPIN_LOCK ShutdownListLock;
+extern LIST_ENTRY IopDiskFsListHead;
+extern LIST_ENTRY IopCdRomFsListHead;
+extern LIST_ENTRY IopTapeFsListHead;
 
 /* PRIVATE FUNCTIONS **********************************************************/
 
+VOID
+NTAPI
+IopReadyDeviceObjects(IN PDRIVER_OBJECT Driver)
+{
+    PDEVICE_OBJECT DeviceObject;
+    PAGED_CODE();
+
+    /* Set the driver as initialized */
+    Driver->Flags |= DRVO_INITIALIZED;
+    DeviceObject = Driver->DeviceObject;
+    while (DeviceObject)
+    {
+        /* Set every device as initialized too */
+        DeviceObject->Flags &= ~DO_DEVICE_INITIALIZING;
+        DeviceObject = DeviceObject->NextDevice;
+    }
+}
+
 VOID
 NTAPI
 IopDeleteDevice(IN PVOID ObjectBody)
@@ -95,7 +115,15 @@ IopAttachDeviceToDeviceStackSafe(IN PDEVICE_OBJECT SourceDevice,
 
 VOID
 NTAPI
-IoShutdownRegisteredDevices(VOID)
+IoShutdownPnpDevices(VOID)
+{
+    /* This routine is only used by Driver Verifier to validate shutdown */
+    return;
+}
+
+VOID
+NTAPI
+IoShutdownSystem(IN ULONG Phase)
 {
     PLIST_ENTRY ListEntry;
     PDEVICE_OBJECT DeviceObject;
@@ -104,46 +132,108 @@ IoShutdownRegisteredDevices(VOID)
     PIRP Irp;
     KEVENT Event;
     NTSTATUS Status;
-
+        
     /* Initialize an event to wait on */
     KeInitializeEvent(&Event, NotificationEvent, FALSE);
-
-    /* Get the first entry and start looping */
-    ListEntry = ExInterlockedRemoveHeadList(&ShutdownListHead,
-                                            &ShutdownListLock);
-    while (ListEntry)
+    
+    /* What phase? */
+    if (Phase == 0)
     {
-        /* Get the shutdown entry */
-        ShutdownEntry = CONTAINING_RECORD(ListEntry,
-                                          SHUTDOWN_ENTRY,
-                                          ShutdownList);
+        /* Shutdown PnP */
+        IoShutdownPnpDevices();
 
-        /* Get the attached device */
-        DeviceObject = IoGetAttachedDevice(ShutdownEntry->DeviceObject);
-
-        /* Build the shutdown IRP and call the driver */
-        Irp = IoBuildSynchronousFsdRequest(IRP_MJ_SHUTDOWN,
-                                           DeviceObject,
-                                           NULL,
-                                           0,
-                                           NULL,
-                                           &Event,
-                                           &StatusBlock);
-        Status = IoCallDriver(DeviceObject, Irp);
-        if (Status == STATUS_PENDING)
+        /* Loop first-chance shutdown notifications */
+        ListEntry = ExInterlockedRemoveHeadList(&ShutdownListHead,
+                                                &ShutdownListLock);
+        while (ListEntry)
         {
-            /* Wait on the driver */
-            KeWaitForSingleObject(&Event, Executive, KernelMode, FALSE, NULL);
-        }
+            /* Get the shutdown entry */
+            ShutdownEntry = CONTAINING_RECORD(ListEntry,
+                                              SHUTDOWN_ENTRY,
+                                              ShutdownList);
+
+            /* Get the attached device */
+            DeviceObject = IoGetAttachedDevice(ShutdownEntry->DeviceObject);
+
+            /* Build the shutdown IRP and call the driver */
+            Irp = IoBuildSynchronousFsdRequest(IRP_MJ_SHUTDOWN,
+                                               DeviceObject,
+                                               NULL,
+                                               0,
+                                               NULL,
+                                               &Event,
+                                               &StatusBlock);
+            Status = IoCallDriver(DeviceObject, Irp);
+            if (Status == STATUS_PENDING)
+            {
+                /* Wait on the driver */
+                KeWaitForSingleObject(&Event, Executive, KernelMode, FALSE, NULL);
+            }
 
-        /* Free the shutdown entry and reset the event */
-        ExFreePoolWithTag(ShutdownEntry, TAG_SHUTDOWN_ENTRY);
-        KeClearEvent(&Event);
+            /* Get rid of our reference to it */
+            ObDereferenceObject(DeviceObject);
+            
+            /* Free the shutdown entry and reset the event */
+            ExFreePoolWithTag(ShutdownEntry, TAG_SHUTDOWN_ENTRY);
+            KeClearEvent(&Event);
 
-        /* Go to the next entry */
-        ListEntry = ExInterlockedRemoveHeadList(&ShutdownListHead,
+            /* Go to the next entry */
+            ListEntry = ExInterlockedRemoveHeadList(&ShutdownListHead,
+                                                    &ShutdownListLock);
+         }
+    }
+    else if (Phase == 1)
+    {
+        /* Shutdown disk file systems */
+        IopShutdownBaseFileSystems(&IopDiskFsListHead);
+
+        /* Shutdown cdrom file systems */
+        IopShutdownBaseFileSystems(&IopCdRomFsListHead);
+
+        /* Shutdown tape filesystems */
+        IopShutdownBaseFileSystems(&IopTapeFsListHead);
+        
+        /* Loop last-chance shutdown notifications */
+        ListEntry = ExInterlockedRemoveHeadList(&LastChanceShutdownListHead,
                                                 &ShutdownListLock);
-     }
+        while (ListEntry)
+        {
+            /* Get the shutdown entry */
+            ShutdownEntry = CONTAINING_RECORD(ListEntry,
+                                              SHUTDOWN_ENTRY,
+                                              ShutdownList);
+
+            /* Get the attached device */
+            DeviceObject = IoGetAttachedDevice(ShutdownEntry->DeviceObject);
+
+            /* Build the shutdown IRP and call the driver */
+            Irp = IoBuildSynchronousFsdRequest(IRP_MJ_SHUTDOWN,
+                                               DeviceObject,
+                                               NULL,
+                                               0,
+                                               NULL,
+                                               &Event,
+                                               &StatusBlock);
+            Status = IoCallDriver(DeviceObject, Irp);
+            if (Status == STATUS_PENDING)
+            {
+                /* Wait on the driver */
+                KeWaitForSingleObject(&Event, Executive, KernelMode, FALSE, NULL);
+            }
+
+            /* Get rid of our reference to it */
+            ObDereferenceObject(DeviceObject);
+            
+            /* Free the shutdown entry and reset the event */
+            ExFreePoolWithTag(ShutdownEntry, TAG_SHUTDOWN_ENTRY);
+            KeClearEvent(&Event);
+
+            /* Go to the next entry */
+            ListEntry = ExInterlockedRemoveHeadList(&LastChanceShutdownListHead,
+                                                    &ShutdownListLock);
+         }
+
+    }
 }
 
 NTSTATUS
@@ -581,7 +671,6 @@ IopGetRelatedTargetDevice(IN PFILE_OBJECT FileObject,
 {
     NTSTATUS Status;
     IO_STACK_LOCATION Stack = {0};
-    IO_STATUS_BLOCK IoStatusBlock;
     PDEVICE_RELATIONS DeviceRelations;
     PDEVICE_OBJECT DeviceObject = NULL;
 
@@ -592,19 +681,17 @@ IopGetRelatedTargetDevice(IN PFILE_OBJECT FileObject,
     if (!DeviceObject) return STATUS_NO_SUCH_DEVICE;
 
     /* Define input parameters */
+    Stack.MajorFunction = IRP_MJ_PNP;
+    Stack.MinorFunction = IRP_MN_QUERY_DEVICE_RELATIONS;
     Stack.Parameters.QueryDeviceRelations.Type = TargetDeviceRelation;
     Stack.FileObject = FileObject;
 
     /* Call the driver to query all relations (IRP_MJ_PNP) */
-    Status = IopInitiatePnpIrp(DeviceObject,
-                               &IoStatusBlock,
-                               IRP_MN_QUERY_DEVICE_RELATIONS,
-                               &Stack);
+    Status = IopSynchronousCall(DeviceObject,
+                                &Stack,
+                                (PVOID)&DeviceRelations);
     if (!NT_SUCCESS(Status)) return Status;
 
-    /* Get returned pointer to DEVICE_RELATIONS */
-    DeviceRelations = (PDEVICE_RELATIONS)IoStatusBlock.Information;
-
     /* Make sure it's not NULL and contains only one object */
     ASSERT(DeviceRelations);
     ASSERT(DeviceRelations->Count == 1);
@@ -843,6 +930,9 @@ IoCreateDevice(IN PDRIVER_OBJECT DriverObject,
     /* Set the Type and Size. Question: why is Size 0 on Windows? */
     DeviceObjectExtension->Type = IO_TYPE_DEVICE_OBJECT_EXTENSION;
     DeviceObjectExtension->Size = 0;
+    
+    /* Initialize with Power Manager */
+    PoInitializeDeviceObject(DeviceObjectExtension);
 
     /* Link the Object and Extension */
     DeviceObjectExtension->DeviceObject = CreatedDeviceObject;
@@ -932,6 +1022,9 @@ IoCreateDevice(IN PDRIVER_OBJECT DriverObject,
     ASSERT((DriverObject->Flags & DRVO_UNLOAD_INVOKED) == 0);
     CreatedDeviceObject->DriverObject = DriverObject;
     IopEditDeviceList(DriverObject, CreatedDeviceObject, IopAdd);
+    
+    /* Link with the power manager */
+    if (CreatedDeviceObject->Vpb) PoVolumeDevice(CreatedDeviceObject);
 
     /* Close the temporary handle and return to caller */
     ObCloseHandle(TempHandle, KernelMode);
@@ -1351,6 +1444,9 @@ IoRegisterLastChanceShutdownNotification(IN PDEVICE_OBJECT DeviceObject)
 
     /* Set the DO */
     Entry->DeviceObject = DeviceObject;
+    
+    /* Reference it so it doesn't go away */
+    ObReferenceObject(DeviceObject);
 
     /* Insert it into the list */
     ExInterlockedInsertHeadList(&LastChanceShutdownListHead,
@@ -1379,6 +1475,9 @@ IoRegisterShutdownNotification(PDEVICE_OBJECT DeviceObject)
 
     /* Set the DO */
     Entry->DeviceObject = DeviceObject;
+    
+    /* Reference it so it doesn't go away */
+    ObReferenceObject(DeviceObject);
 
     /* Insert it into the list */
     ExInterlockedInsertHeadList(&ShutdownListHead,
@@ -1420,6 +1519,9 @@ IoUnregisterShutdownNotification(PDEVICE_OBJECT DeviceObject)
 
             /* Free the entry */
             ExFreePoolWithTag(ShutdownEntry, TAG_SHUTDOWN_ENTRY);
+            
+            /* Get rid of our reference to it */
+            ObDereferenceObject(DeviceObject);
         }
 
         /* Go to the next entry */
@@ -1444,6 +1546,9 @@ IoUnregisterShutdownNotification(PDEVICE_OBJECT DeviceObject)
 
             /* Free the entry */
             ExFreePoolWithTag(ShutdownEntry, TAG_SHUTDOWN_ENTRY);
+            
+            /* Get rid of our reference to it */
+            ObDereferenceObject(DeviceObject);
         }
 
         /* Go to the next entry */