[USB-BRINGUP-TRUNK]
[reactos.git] / ntoskrnl / io / pnpmgr / pnpmgr.c
index c4311ff..9d20b97 100644 (file)
@@ -48,7 +48,7 @@ VOID
 IopCancelPrepareDeviceForRemoval(PDEVICE_OBJECT DeviceObject);
 
 NTSTATUS
-IopPrepareDeviceForRemoval(PDEVICE_OBJECT DeviceObject);
+IopPrepareDeviceForRemoval(PDEVICE_OBJECT DeviceObject, BOOLEAN Force);
 
 PDEVICE_NODE
 FASTCALL
@@ -102,16 +102,7 @@ IopInitializeDevice(PDEVICE_NODE DeviceNode,
       return Status;
    }
 
-   /* Check if driver added a FDO above the PDO */
    Fdo = IoGetAttachedDeviceReference(DeviceNode->PhysicalDeviceObject);
-   if (Fdo == DeviceNode->PhysicalDeviceObject)
-   {
-      /* FIXME: What do we do? Unload the driver or just disable the device? */
-      DPRINT1("An FDO was not attached\n");
-      ObDereferenceObject(Fdo);
-      IopDeviceNodeSetFlag(DeviceNode, DNF_DISABLED);
-      return STATUS_UNSUCCESSFUL;
-   }
 
    /* Check if we have a ACPI device (needed for power management) */
    if (Fdo->DeviceType == FILE_DEVICE_ACPI)
@@ -597,9 +588,9 @@ IopGetBusTypeGuidIndex(LPGUID BusTypeGuid)
        NewList = ExAllocatePool(PagedPool, NewSize);
 
        if (!NewList) {
-          /* Fail */
-          ExFreePool(PnpBusTypeGuidList);
-          goto Quickie;
+       /* Fail */
+       ExFreePool(PnpBusTypeGuidList);
+       goto Quickie;
        }
 
        /* Now copy them, decrease the size too */
@@ -629,7 +620,7 @@ Quickie:
 
 /*
  * DESCRIPTION
- *     Creates a device node
+ *     Creates a device node
  *
  * ARGUMENTS
  *   ParentNode           = Pointer to parent device node
@@ -639,7 +630,7 @@ Quickie:
  *   DeviceNode           = Pointer to storage for created device node
  *
  * RETURN VALUE
- *     Status
+ *     Status
  */
 NTSTATUS
 IopCreateDeviceNode(PDEVICE_NODE ParentNode,
@@ -1378,11 +1369,11 @@ IopQueryHardwareIds(PDEVICE_NODE DeviceNode,
 
       RtlInitUnicodeString(&ValueName, L"HardwareID");
       Status = ZwSetValueKey(InstanceKey,
-                            &ValueName,
-                            0,
-                            REG_MULTI_SZ,
-                            (PVOID)IoStatusBlock.Information,
-                            (TotalLength + 1) * sizeof(WCHAR));
+                 &ValueName,
+                 0,
+                 REG_MULTI_SZ,
+                 (PVOID)IoStatusBlock.Information,
+                 (TotalLength + 1) * sizeof(WCHAR));
       if (!NT_SUCCESS(Status))
       {
          DPRINT1("ZwSetValueKey() failed (Status %lx)\n", Status);
@@ -1833,14 +1824,19 @@ IopHandleDeviceRemoval(
             }
         }
 
-        if (!Found)
+        if (!Found && !(Child->Flags & DNF_WILL_BE_REMOVED))
         {
+            /* Send removal IRPs to all of its children */
+            IopPrepareDeviceForRemoval(Child->PhysicalDeviceObject, TRUE);
+
+            /* Send the surprise removal IRP */
             IopSendSurpriseRemoval(Child->PhysicalDeviceObject);
 
             /* Tell the user-mode PnP manager that a device was removed */
             IopQueueTargetDeviceEvent(&GUID_DEVICE_SURPRISE_REMOVAL,
                                       &Child->InstancePath);
 
+            /* Send the remove device IRP */
             IopSendRemoveDevice(Child->PhysicalDeviceObject);
         }
 
@@ -3908,7 +3904,7 @@ IoOpenDeviceRegistryKey(IN PDEVICE_OBJECT DeviceObject,
 
 static
 NTSTATUS
-IopQueryRemoveChildDevices(PDEVICE_NODE ParentDeviceNode)
+IopQueryRemoveChildDevices(PDEVICE_NODE ParentDeviceNode, BOOLEAN Force)
 {
     PDEVICE_NODE ChildDeviceNode, NextDeviceNode, FailedRemoveDevice;
     NTSTATUS Status;
@@ -3921,7 +3917,7 @@ IopQueryRemoveChildDevices(PDEVICE_NODE ParentDeviceNode)
         NextDeviceNode = ChildDeviceNode->Sibling;
         KeReleaseSpinLock(&IopDeviceTreeLock, OldIrql);
         
-        Status = IopPrepareDeviceForRemoval(ChildDeviceNode->PhysicalDeviceObject);
+        Status = IopPrepareDeviceForRemoval(ChildDeviceNode->PhysicalDeviceObject, Force);
         if (!NT_SUCCESS(Status))
         {
             FailedRemoveDevice = ChildDeviceNode;
@@ -4007,7 +4003,7 @@ IopCancelRemoveChildDevices(PDEVICE_NODE ParentDeviceNode)
 
 static
 NTSTATUS
-IopQueryRemoveDeviceRelations(PDEVICE_RELATIONS DeviceRelations)
+IopQueryRemoveDeviceRelations(PDEVICE_RELATIONS DeviceRelations, BOOLEAN Force)
 {
     /* This function DOES NOT dereference the device objects on SUCCESS
      * but it DOES dereference device objects on FAILURE */
@@ -4017,7 +4013,7 @@ IopQueryRemoveDeviceRelations(PDEVICE_RELATIONS DeviceRelations)
     
     for (i = 0; i < DeviceRelations->Count; i++)
     {
-        Status = IopPrepareDeviceForRemoval(DeviceRelations->Objects[i]);
+        Status = IopPrepareDeviceForRemoval(DeviceRelations->Objects[i], Force);
         if (!NT_SUCCESS(Status))
         {
             j = i;
@@ -4113,7 +4109,7 @@ IopCancelPrepareDeviceForRemoval(PDEVICE_OBJECT DeviceObject)
 }
 
 NTSTATUS
-IopPrepareDeviceForRemoval(IN PDEVICE_OBJECT DeviceObject)
+IopPrepareDeviceForRemoval(IN PDEVICE_OBJECT DeviceObject, BOOLEAN Force)
 {
     PDEVICE_NODE DeviceNode = IopGetDeviceNode(DeviceObject);
     IO_STACK_LOCATION Stack;
@@ -4121,13 +4117,13 @@ IopPrepareDeviceForRemoval(IN PDEVICE_OBJECT DeviceObject)
     PDEVICE_RELATIONS DeviceRelations;
     NTSTATUS Status;
 
-    if (DeviceNode->UserFlags & DNUF_NOT_DISABLEABLE)
+    if ((DeviceNode->UserFlags & DNUF_NOT_DISABLEABLE) && !Force)
     {
         DPRINT1("Removal not allowed for %wZ\n", &DeviceNode->InstancePath);
         return STATUS_UNSUCCESSFUL;
     }
     
-    if (IopQueryRemoveDevice(DeviceObject) != STATUS_SUCCESS)
+    if (!Force && IopQueryRemoveDevice(DeviceObject) != STATUS_SUCCESS)
     {
         DPRINT1("Removal vetoed by failing the query remove request\n");
         
@@ -4154,19 +4150,20 @@ IopPrepareDeviceForRemoval(IN PDEVICE_OBJECT DeviceObject)
     
     if (DeviceRelations)
     {
-        Status = IopQueryRemoveDeviceRelations(DeviceRelations);
+        Status = IopQueryRemoveDeviceRelations(DeviceRelations, Force);
         if (!NT_SUCCESS(Status))
             return Status;
     }
-    
-    Status = IopQueryRemoveChildDevices(DeviceNode);
+
+    Status = IopQueryRemoveChildDevices(DeviceNode, Force);
     if (!NT_SUCCESS(Status))
     {
         if (DeviceRelations)
             IopCancelRemoveDeviceRelations(DeviceRelations);
         return Status;
     }
-    
+
+    DeviceNode->Flags |= DNF_WILL_BE_REMOVED;
     if (DeviceRelations)
         IopSendRemoveDeviceRelations(DeviceRelations);
     IopSendRemoveChildDevices(DeviceNode);
@@ -4181,13 +4178,12 @@ IopRemoveDevice(PDEVICE_NODE DeviceNode)
 
     DPRINT("Removing device: %wZ\n", &DeviceNode->InstancePath);
 
-    Status = IopPrepareDeviceForRemoval(DeviceNode->PhysicalDeviceObject);
+    Status = IopPrepareDeviceForRemoval(DeviceNode->PhysicalDeviceObject, FALSE);
     if (NT_SUCCESS(Status))
     {
         IopSendRemoveDevice(DeviceNode->PhysicalDeviceObject);
         IopQueueTargetDeviceEvent(&GUID_DEVICE_SAFE_REMOVAL,
                                   &DeviceNode->InstancePath);
-        DeviceNode->Flags |= DNF_WILL_BE_REMOVED;
         return STATUS_SUCCESS;
     }
 
@@ -4234,12 +4230,12 @@ IoRequestDeviceEject(IN PDEVICE_OBJECT PhysicalDeviceObject)
     
     if (DeviceRelations)
     {
-        Status = IopQueryRemoveDeviceRelations(DeviceRelations);
+        Status = IopQueryRemoveDeviceRelations(DeviceRelations, FALSE);
         if (!NT_SUCCESS(Status))
             goto cleanup;
     }
     
-    Status = IopQueryRemoveChildDevices(DeviceNode);
+    Status = IopQueryRemoveChildDevices(DeviceNode, FALSE);
     if (!NT_SUCCESS(Status))
     {
         if (DeviceRelations)
@@ -4247,7 +4243,7 @@ IoRequestDeviceEject(IN PDEVICE_OBJECT PhysicalDeviceObject)
         goto cleanup;
     }
     
-    if (IopPrepareDeviceForRemoval(PhysicalDeviceObject) != STATUS_SUCCESS)
+    if (IopPrepareDeviceForRemoval(PhysicalDeviceObject, FALSE) != STATUS_SUCCESS)
     {
         if (DeviceRelations)
             IopCancelRemoveDeviceRelations(DeviceRelations);