[NTOSKRNL]
[reactos.git] / reactos / ntoskrnl / io / iomgr / device.c
index 3e2f679..88e5ba4 100644 (file)
 
 #include <ntoskrnl.h>
 #define NDEBUG
-#include <internal/debug.h>
+#include <debug.h>
 
 /* 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)
+{
+    PDEVICE_OBJECT DeviceObject = ObjectBody;
+    PAGED_CODE();
+    /* TODO: Delete Device Node */
+
+    /* Dereference the driver object, referenced in IoCreateDevice */
+    if (DeviceObject->DriverObject)
+        ObDereferenceObject(DeviceObject->DriverObject);
+}
+
+
 PDEVICE_OBJECT
 NTAPI
 IopAttachDeviceToDeviceStackSafe(IN PDEVICE_OBJECT SourceDevice,
@@ -80,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;
@@ -89,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);
+            }
+
+            /* 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,
+                                                    &ShutdownListLock);
+         }
+    }
+    else if (Phase == 1)
+    {
+        /* Shutdown disk file systems */
+        IopShutdownBaseFileSystems(&IopDiskFsListHead);
 
-        /* Free the shutdown entry and reset the event */
-        ExFreePool(ShutdownEntry);
-        KeClearEvent(&Event);
+        /* Shutdown cdrom file systems */
+        IopShutdownBaseFileSystems(&IopCdRomFsListHead);
 
-        /* Go to the next entry */
-        ListEntry = ExInterlockedRemoveHeadList(&ShutdownListHead,
+        /* 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
@@ -317,7 +422,7 @@ IopUnloadDevice(IN PDEVICE_OBJECT DeviceObject)
         if (DeviceObject->SecurityDescriptor)
         {
             /* Free it */
-            ExFreePool(DeviceObject->SecurityDescriptor);
+            ExFreePoolWithTag(DeviceObject->SecurityDescriptor, TAG_SD);
         }
 
         /* Remove the device from the list */
@@ -356,6 +461,13 @@ IopUnloadDevice(IN PDEVICE_OBJECT DeviceObject)
 
     /* Unload it */
     if (DriverObject->DriverUnload) DriverObject->DriverUnload(DriverObject);
+
+    /* Make object temporary so it can be deleted */
+    ObMakeTemporaryObject(DriverObject);
+
+    /* Dereference once more, referenced at driver object creation */
+    ObDereferenceObject(DriverObject);
+
 }
 
 VOID
@@ -552,6 +664,48 @@ IopStartNextPacketByKeyEx(IN PDEVICE_OBJECT DeviceObject,
     }
 }
 
+NTSTATUS
+NTAPI
+IopGetRelatedTargetDevice(IN PFILE_OBJECT FileObject,
+                          OUT PDEVICE_NODE *DeviceNode)
+{
+    NTSTATUS Status;
+    IO_STACK_LOCATION Stack = {0};
+    PDEVICE_RELATIONS DeviceRelations;
+    PDEVICE_OBJECT DeviceObject = NULL;
+
+    ASSERT(FileObject);
+
+    /* Get DeviceObject related to given FileObject */
+    DeviceObject = IoGetRelatedDeviceObject(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 = IopSynchronousCall(DeviceObject,
+                                &Stack,
+                                (PVOID)&DeviceRelations);
+    if (!NT_SUCCESS(Status)) return Status;
+
+    /* Make sure it's not NULL and contains only one object */
+    ASSERT(DeviceRelations);
+    ASSERT(DeviceRelations->Count == 1);
+
+    /* Finally get the device node */
+    *DeviceNode = IopGetDeviceNode(DeviceRelations->Objects[0]);
+    if (!*DeviceNode) Status = STATUS_NO_SUCH_DEVICE;
+
+    /* Free the DEVICE_RELATIONS structure, it's not needed anymore */
+    ExFreePool(DeviceRelations);
+
+    return Status;
+}
+
 /* PUBLIC FUNCTIONS ***********************************************************/
 
 /*
@@ -776,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;
@@ -865,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);
@@ -1133,16 +1293,20 @@ IoGetLowerDeviceObject(IN PDEVICE_OBJECT DeviceObject)
 
     /* Make sure it's not getting deleted */
     DeviceExtension = IoGetDevObjExtension(DeviceObject);
-    if (DeviceExtension->ExtensionFlags & (DOE_UNLOAD_PENDING |
+    if (!(DeviceExtension->ExtensionFlags & (DOE_UNLOAD_PENDING |
                                            DOE_DELETE_PENDING |
                                            DOE_REMOVE_PENDING |
-                                           DOE_REMOVE_PROCESSED))
+                                           DOE_REMOVE_PROCESSED)))
     {
         /* Get the Lower Device Object */
         LowerDeviceObject = DeviceExtension->AttachedTo;
 
-        /* Reference it */
-        ObReferenceObject(LowerDeviceObject);
+        /* Check that we got a valid device object */
+        if (LowerDeviceObject)
+        {
+            /* We did so let's reference it */
+            ObReferenceObject(LowerDeviceObject);
+        }
     }
 
     /* Return it */
@@ -1195,7 +1359,7 @@ IoGetRelatedDeviceObject(IN PFILE_OBJECT FileObject)
             {
                 /* FIXME: Unhandled yet */
                 DPRINT1("FOEs not supported\n");
-                KEBUGCHECK(0);
+                ASSERT(FALSE);
             }
         }
 
@@ -1207,6 +1371,26 @@ IoGetRelatedDeviceObject(IN PFILE_OBJECT FileObject)
     return DeviceObject;
 }
 
+/*
+ * @implemented
+ */
+NTSTATUS
+NTAPI
+IoGetRelatedTargetDevice(IN PFILE_OBJECT FileObject,
+                         OUT PDEVICE_OBJECT *DeviceObject)
+{
+    NTSTATUS Status;
+    PDEVICE_NODE DeviceNode = NULL;
+
+    /* Call the internal helper function */
+    Status = IopGetRelatedTargetDevice(FileObject, &DeviceNode);
+    if (NT_SUCCESS(Status) && DeviceNode)
+    {
+        *DeviceObject = DeviceNode->PhysicalDeviceObject;
+    }
+    return Status;
+}
+
 /*
  * @implemented
  */
@@ -1260,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,
@@ -1288,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,
@@ -1328,7 +1518,10 @@ IoUnregisterShutdownNotification(PDEVICE_OBJECT DeviceObject)
             NextEntry = NextEntry->Blink;
 
             /* Free the entry */
-            ExFreePool(ShutdownEntry);
+            ExFreePoolWithTag(ShutdownEntry, TAG_SHUTDOWN_ENTRY);
+            
+            /* Get rid of our reference to it */
+            ObDereferenceObject(DeviceObject);
         }
 
         /* Go to the next entry */
@@ -1352,13 +1545,19 @@ IoUnregisterShutdownNotification(PDEVICE_OBJECT DeviceObject)
             NextEntry = NextEntry->Blink;
 
             /* Free the entry */
-            ExFreePool(ShutdownEntry);
+            ExFreePoolWithTag(ShutdownEntry, TAG_SHUTDOWN_ENTRY);
+            
+            /* Get rid of our reference to it */
+            ObDereferenceObject(DeviceObject);
         }
 
         /* Go to the next entry */
         NextEntry = NextEntry->Flink;
     }
 
+    /* Release the shutdown lock */
+    KeReleaseSpinLock(&ShutdownListLock, OldIrql);
+
     /* Now remove the flag */
     DeviceObject->Flags &= ~DO_SHUTDOWN_REGISTERED;
 }
@@ -1498,7 +1697,7 @@ IoStartPacket(IN PDEVICE_OBJECT DeviceObject,
             }
 
             /* Release the cancel lock */
-            IoReleaseCancelSpinLock(OldIrql);
+            IoReleaseCancelSpinLock(CancelIrql);
         }
 
         /* Call the Start I/O function */