[i8042prt]
[reactos.git] / reactos / ntoskrnl / io / pnpmgr / pnpmgr.c
index 75188f9..5c18437 100644 (file)
@@ -50,6 +50,9 @@ IopCancelPrepareDeviceForRemoval(PDEVICE_OBJECT DeviceObject);
 NTSTATUS
 IopPrepareDeviceForRemoval(PDEVICE_OBJECT DeviceObject, BOOLEAN Force);
 
+PDEVICE_OBJECT
+IopGetDeviceObjectFromDeviceInstance(PUNICODE_STRING DeviceInstance);
+
 PDEVICE_NODE
 FASTCALL
 IopGetDeviceNode(PDEVICE_OBJECT DeviceObject)
@@ -60,7 +63,7 @@ IopGetDeviceNode(PDEVICE_OBJECT DeviceObject)
 VOID
 IopFixupDeviceId(PWCHAR String)
 {
-    ULONG Length = wcslen(String), i;
+    SIZE_T Length = wcslen(String), i;
 
     for (i = 0; i < Length; i++)
     {
@@ -199,7 +202,7 @@ IopInstallCriticalDevice(PDEVICE_NODE DeviceNode)
 
     while (*IdBuffer)
     {
-        ULONG StringLength = (ULONG)wcslen(IdBuffer) + 1, Index;
+        USHORT StringLength = (USHORT)wcslen(IdBuffer) + 1, Index;
         
         IopFixupDeviceId(IdBuffer);
         
@@ -247,7 +250,7 @@ IopInstallCriticalDevice(PDEVICE_NODE DeviceNode)
                 ChildIdNameU.Buffer = IdBuffer;
                 ChildIdNameU.MaximumLength = ChildIdNameU.Length = (StringLength - 1) * sizeof(WCHAR);
                 RegKeyNameU.Buffer = BasicInfo->Name;
-                RegKeyNameU.MaximumLength = RegKeyNameU.Length = BasicInfo->NameLength;
+                RegKeyNameU.MaximumLength = RegKeyNameU.Length = (USHORT)BasicInfo->NameLength;
 
                 if (RtlEqualUnicodeString(&ChildIdNameU, &RegKeyNameU, TRUE))
                 {
@@ -460,6 +463,7 @@ IopInitializeDevice(PDEVICE_NODE DeviceNode,
               &DeviceNode->InstancePath,
               Status);
       IopDeviceNodeSetFlag(DeviceNode, DNF_DISABLED);
+      DeviceNode->Problem = CM_PROB_FAILED_ADD;
       return Status;
    }
 
@@ -644,7 +648,7 @@ IopStartDevice2(IN PDEVICE_OBJECT DeviceObject)
     
     ASSERT(!(DeviceNode->Flags & DNF_DISABLED));
 
-    /* Build the I/O stack locaiton */
+    /* Build the I/O stack location */
     RtlZeroMemory(&Stack, sizeof(IO_STACK_LOCATION));
     Stack.MajorFunction = IRP_MJ_PNP;
     Stack.MinorFunction = IRP_MN_START_DEVICE;
@@ -663,6 +667,7 @@ IopStartDevice2(IN PDEVICE_OBJECT DeviceObject)
 
         /* Set the appropriate flag */
         DeviceNode->Flags |= DNF_START_FAILED;
+        DeviceNode->Problem = CM_PROB_FAILED_START;
 
         DPRINT1("Warning: PnP Start failed (%wZ) [Status: 0x%x]\n", &DeviceNode->InstancePath, Status);
         return;
@@ -1008,9 +1013,7 @@ IopCreateDeviceNode(PDEVICE_NODE ParentNode,
    UNICODE_STRING KeyName, ClassName;
    PUNICODE_STRING ServiceName1;
    ULONG LegacyValue;
-#if 0
    UNICODE_STRING ClassGUID;
-#endif
    HANDLE InstanceHandle;
 
    DPRINT("ParentNode 0x%p PhysicalDeviceObject 0x%p ServiceName %wZ\n",
@@ -1091,17 +1094,21 @@ IopCreateDeviceNode(PDEVICE_NODE ParentNode,
           {
               RtlInitUnicodeString(&KeyName, L"Class");
 
-              RtlInitUnicodeString(&ClassName, L"LegacyDriver");
-              Status = ZwSetValueKey(InstanceHandle, &KeyName, 0, REG_SZ, ClassName.Buffer, ClassName.Length);
-#if 0
+              RtlInitUnicodeString(&ClassName, L"LegacyDriver\0");
+              Status = ZwSetValueKey(InstanceHandle, &KeyName, 0, REG_SZ, ClassName.Buffer, ClassName.Length + sizeof(UNICODE_NULL));
               if (NT_SUCCESS(Status))
               {
                   RtlInitUnicodeString(&KeyName, L"ClassGUID");
 
-                  RtlInitUnicodeString(&ClassGUID, L"{8ECC055D-047F-11D1-A537-0000F8753ED1}");
-                  Status = ZwSetValueKey(InstanceHandle, &KeyName, 0, REG_SZ, ClassGUID.Buffer, ClassGUID.Length);
+                  RtlInitUnicodeString(&ClassGUID, L"{8ECC055D-047F-11D1-A537-0000F8753ED1}\0");
+                  Status = ZwSetValueKey(InstanceHandle, &KeyName, 0, REG_SZ, ClassGUID.Buffer, ClassGUID.Length + sizeof(UNICODE_NULL));
+                  if (NT_SUCCESS(Status))
+                  {
+                      RtlInitUnicodeString(&KeyName, L"DeviceDesc");
+
+                      Status = ZwSetValueKey(InstanceHandle, &KeyName, 0, REG_SZ, ServiceName1->Buffer, ServiceName1->Length + sizeof(UNICODE_NULL));
+                  }
               }
-#endif
           }
       }
 
@@ -1128,10 +1135,17 @@ IopCreateDeviceNode(PDEVICE_NODE ParentNode,
     {
         KeAcquireSpinLock(&IopDeviceTreeLock, &OldIrql);
         Node->Parent = ParentNode;
-        Node->Sibling = ParentNode->Child;
-        ParentNode->Child = Node;
+        Node->Sibling = NULL;
         if (ParentNode->LastChild == NULL)
+        {
+            ParentNode->Child = Node;
             ParentNode->LastChild = Node;
+        }
+        else
+        {
+            ParentNode->LastChild->Sibling = Node;
+            ParentNode->LastChild = Node;
+        }
         KeReleaseSpinLock(&IopDeviceTreeLock, OldIrql);
         Node->Level = ParentNode->Level + 1;
     }
@@ -1151,12 +1165,9 @@ IopFreeDeviceNode(PDEVICE_NODE DeviceNode)
 
    /* All children must be deleted before a parent is deleted */
    ASSERT(!DeviceNode->Child);
-
-   KeAcquireSpinLock(&IopDeviceTreeLock, &OldIrql);
-
    ASSERT(DeviceNode->PhysicalDeviceObject);
 
-   ObDereferenceObject(DeviceNode->PhysicalDeviceObject);
+   KeAcquireSpinLock(&IopDeviceTreeLock, &OldIrql);
 
     /* Get previous sibling */
     if (DeviceNode->Parent && DeviceNode->Parent->Child != DeviceNode)
@@ -1274,7 +1285,10 @@ IopSynchronousCall(IN PDEVICE_OBJECT DeviceObject,
                               NULL);
         Status = IoStatusBlock.Status;
     }
-    
+
+    /* Remove the reference */
+    ObDereferenceObject(TopDeviceObject);
+
     /* Return the information */
     *Information = (PVOID)IoStatusBlock.Information;
     return Status;
@@ -1351,7 +1365,7 @@ IopTraverseDeviceTree(PDEVICETREE_TRAVERSE_CONTEXT Context)
 
    DPRINT("Context 0x%p\n", Context);
 
-   DPRINT("IopTraverseDeviceTree(DeviceNode 0x%p  FirstDeviceNode 0x%p  Action %x  Context 0x%p)\n",
+   DPRINT("IopTraverseDeviceTree(DeviceNode 0x%p  FirstDeviceNode 0x%p  Action %p  Context 0x%p)\n",
       Context->DeviceNode, Context->FirstDeviceNode, Context->Action, Context->Context);
 
    /* Start from the specified device node */
@@ -1839,7 +1853,9 @@ IopActionInterrogateDeviceStack(PDEVICE_NODE DeviceNode,
    HANDLE InstanceKey = NULL;
    UNICODE_STRING ValueName;
    UNICODE_STRING ParentIdPrefix = { 0, 0, NULL };
+   UNICODE_STRING InstancePathU;
    DEVICE_CAPABILITIES DeviceCapabilities;
+   PDEVICE_OBJECT OldDeviceObject;
 
    DPRINT("IopActionInterrogateDeviceStack(%p, %p)\n", DeviceNode, Context);
    DPRINT("PDO 0x%p\n", DeviceNode->PhysicalDeviceObject);
@@ -1980,12 +1996,31 @@ IopActionInterrogateDeviceStack(PDEVICE_NODE DeviceNode,
    }
    RtlFreeUnicodeString(&ParentIdPrefix);
 
-   if (!RtlCreateUnicodeString(&DeviceNode->InstancePath, InstancePath))
+   if (!RtlCreateUnicodeString(&InstancePathU, InstancePath))
    {
       DPRINT("No resources\n");
       /* FIXME: Cleanup and disable device */
    }
 
+   /* Verify that this is not a duplicate */
+   OldDeviceObject = IopGetDeviceObjectFromDeviceInstance(&InstancePathU);
+   if (OldDeviceObject != NULL)
+   {
+       PDEVICE_NODE OldDeviceNode = IopGetDeviceNode(OldDeviceObject);
+
+       DPRINT1("Duplicate device instance '%wZ'\n", &InstancePathU);
+       DPRINT1("Current instance parent: '%wZ'\n", &DeviceNode->Parent->InstancePath);
+       DPRINT1("Old instance parent: '%wZ'\n", &OldDeviceNode->Parent->InstancePath);
+
+       KeBugCheckEx(PNP_DETECTED_FATAL_ERROR,
+                    0x01,
+                    (ULONG_PTR)DeviceNode->PhysicalDeviceObject,
+                    (ULONG_PTR)OldDeviceObject,
+                    0);
+   }
+
+   DeviceNode->InstancePath = InstancePathU;
+
    DPRINT("InstancePath is %S\n", DeviceNode->InstancePath.Buffer);
 
    /*
@@ -2233,8 +2268,6 @@ IopEnumerateDevice(
                                   &DeviceNode->InstancePath);
     }
 
-    DeviceNode->Flags &= ~DNF_NEED_TO_ENUM;
-
     DPRINT("Sending IRP_MN_QUERY_DEVICE_RELATIONS to device stack\n");
 
     Stack.Parameters.QueryDeviceRelations.Type = BusRelations;
@@ -2467,7 +2500,7 @@ IopActionConfigureChildServices(PDEVICE_NODE DeviceNode,
          if (NT_SUCCESS(IopQueryDeviceCapabilities(DeviceNode, &DeviceCaps)) &&
              DeviceCaps.RawDeviceOK)
          {
-            DPRINT1("%wZ is using parent bus driver (%wZ)\n", &DeviceNode->InstancePath, &ParentDeviceNode->ServiceName);
+            DPRINT("%wZ is using parent bus driver (%wZ)\n", &DeviceNode->InstancePath, &ParentDeviceNode->ServiceName);
 
             DeviceNode->ServiceName.Length = 0;
             DeviceNode->ServiceName.MaximumLength = 0;
@@ -2483,6 +2516,7 @@ IopActionConfigureChildServices(PDEVICE_NODE DeviceNode,
          }
          else
          {
+            DeviceNode->Problem = CM_PROB_FAILED_INSTALL;
             IopDeviceNodeSetFlag(DeviceNode, DNF_DISABLED);
          }
          return STATUS_SUCCESS;
@@ -2585,24 +2619,21 @@ IopActionInitChildServices(PDEVICE_NODE DeviceNode,
 
          if (NT_SUCCESS(Status) || Status == STATUS_IMAGE_ALREADY_LOADED)
          {
-            /* STATUS_IMAGE_ALREADY_LOADED means this driver
-               was loaded by the bootloader */
-            if ((Status != STATUS_IMAGE_ALREADY_LOADED) ||
-                (Status == STATUS_IMAGE_ALREADY_LOADED && !DriverObject))
-            {
-               /* Initialize the driver */
-               Status = IopInitializeDriverModule(DeviceNode, ModuleObject,
+            /* Initialize the driver */
+            Status = IopInitializeDriverModule(DeviceNode, ModuleObject,
                   &DeviceNode->ServiceName, FALSE, &DriverObject);
-            }
-            else
-            {
-               Status = STATUS_SUCCESS;
-            }
+            if (!NT_SUCCESS(Status)) DeviceNode->Problem = CM_PROB_FAILED_DRIVER_ENTRY;
+         }
+         else if (Status == STATUS_DRIVER_UNABLE_TO_LOAD)
+         {
+            DPRINT1("Service '%wZ' is disabled\n", &DeviceNode->ServiceName);
+            DeviceNode->Problem = CM_PROB_DISABLED_SERVICE;
          }
          else
          {
-            DPRINT1("IopLoadServiceModule(%wZ) failed with status 0x%08x\n",
+            DPRINT("IopLoadServiceModule(%wZ) failed with status 0x%08x\n",
                     &DeviceNode->ServiceName, Status);
+            if (!BootDrivers) DeviceNode->Problem = CM_PROB_DRIVER_FAILED_LOAD;
          }
       }
 
@@ -2611,6 +2642,9 @@ IopActionInitChildServices(PDEVICE_NODE DeviceNode,
       {
           /* Initialize the device, including all filters */
           Status = PipCallDriverAddDevice(DeviceNode, FALSE, DriverObject);
+
+          /* Remove the extra reference */
+          ObDereferenceObject(DriverObject);
       }
       else
       {
@@ -2620,10 +2654,6 @@ IopActionInitChildServices(PDEVICE_NODE DeviceNode,
          if (!BootDrivers)
          {
             IopDeviceNodeSetFlag(DeviceNode, DNF_DISABLED);
-            IopDeviceNodeSetFlag(DeviceNode, DNF_START_FAILED);
-            /* FIXME: Log the error (possibly in IopInitializeDeviceNodeService) */
-            DPRINT1("Initialization of service %S failed (Status %x)\n",
-              DeviceNode->ServiceName.Buffer, Status);
          }
       }
    }
@@ -2691,9 +2721,6 @@ IopEnumerateDetectedDevices(
    ULONG BootResourcesLength;
    NTSTATUS Status;
 
-   const UNICODE_STRING IdentifierPci = RTL_CONSTANT_STRING(L"PCI");
-   UNICODE_STRING HardwareIdPci = RTL_CONSTANT_STRING(L"*PNP0A03\0");
-   static ULONG DeviceIndexPci = 0;
    const UNICODE_STRING IdentifierSerial = RTL_CONSTANT_STRING(L"SerialController");
    UNICODE_STRING HardwareIdSerial = RTL_CONSTANT_STRING(L"*PNP0501\0");
    static ULONG DeviceIndexSerial = 0;
@@ -2709,9 +2736,6 @@ IopEnumerateDetectedDevices(
    const UNICODE_STRING IdentifierFloppy = RTL_CONSTANT_STRING(L"FloppyDiskPeripheral");
    UNICODE_STRING HardwareIdFloppy = RTL_CONSTANT_STRING(L"*PNP0700\0");
    static ULONG DeviceIndexFloppy = 0;
-   const UNICODE_STRING IdentifierIsa = RTL_CONSTANT_STRING(L"ISA");
-   UNICODE_STRING HardwareIdIsa = RTL_CONSTANT_STRING(L"*PNP0A00\0");
-   static ULONG DeviceIndexIsa = 0;
    UNICODE_STRING HardwareIdKey;
    PUNICODE_STRING pHardwareId;
    ULONG DeviceIndex = 0;
@@ -2964,25 +2988,6 @@ IopEnumerateDetectedDevices(
          pHardwareId = &HardwareIdFloppy;
          DeviceIndex = DeviceIndexFloppy++;
       }
-      else if (NT_SUCCESS(Status))
-      {
-         /* Try to also match the device identifier */
-         if (RtlCompareUnicodeString(&ValueName, &IdentifierPci, FALSE) == 0)
-         {
-            pHardwareId = &HardwareIdPci;
-            DeviceIndex = DeviceIndexPci++;
-         }
-         else if (RtlCompareUnicodeString(&ValueName, &IdentifierIsa, FALSE) == 0)
-         {
-            pHardwareId = &HardwareIdIsa;
-            DeviceIndex = DeviceIndexIsa++;
-         }
-         else
-         {
-            DPRINT("Unknown device '%wZ'\n", &ValueName);
-            goto nextdevice;
-         }
-      }
       else
       {
          /* Unknown key path */
@@ -3777,7 +3782,7 @@ PiGetDeviceRegistryProperty(IN PDEVICE_OBJECT DeviceObject,
 
 #define PIP_RETURN_DATA(x, y)   {ReturnLength = x; Data = y; Status = STATUS_SUCCESS; break;}
 #define PIP_REGISTRY_DATA(x, y) {ValueName = x; ValueType = y; break;}
-#define PIP_UNIMPLEMENTED()     {UNIMPLEMENTED; while(TRUE); break;}
+#define PIP_UNIMPLEMENTED()     {UNIMPLEMENTED_DBGBREAK(); break;}
 
 /*
  * @implemented
@@ -4037,8 +4042,13 @@ IoInvalidateDeviceState(IN PDEVICE_OBJECT PhysicalDeviceObject)
     if ((PnPFlags & PNP_DEVICE_REMOVED) ||
         ((PnPFlags & PNP_DEVICE_FAILED) && !(PnPFlags & PNP_DEVICE_RESOURCE_REQUIREMENTS_CHANGED)))
     {
-        /* Surprise removal */
-        
+        /* Flag it if it's failed */
+        if (PnPFlags & PNP_DEVICE_FAILED) DeviceNode->Problem = CM_PROB_FAILED_POST_START;
+
+        /* Send removal IRPs to all of its children */
+        IopPrepareDeviceForRemoval(PhysicalDeviceObject, TRUE);
+
+        /* Send surprise removal */
         IopSendSurpriseRemoval(PhysicalDeviceObject);
         
         /* Tell the user-mode PnP manager that a device was removed */
@@ -4050,7 +4060,6 @@ IoInvalidateDeviceState(IN PDEVICE_OBJECT PhysicalDeviceObject)
     else if ((PnPFlags & PNP_DEVICE_FAILED) && (PnPFlags & PNP_DEVICE_RESOURCE_REQUIREMENTS_CHANGED))
     {
         /* Stop for resource rebalance */
-        
         Status = IopStopDevice(DeviceNode);
         if (!NT_SUCCESS(Status))
         {
@@ -4498,7 +4507,7 @@ IopPrepareDeviceForRemoval(IN PDEVICE_OBJECT DeviceObject, BOOLEAN Force)
     }
     
     Stack.Parameters.QueryDeviceRelations.Type = RemovalRelations;
-    
+
     Status = IopInitiatePnpIrp(DeviceObject,
                                &IoStatusBlock,
                                IRP_MN_QUERY_DEVICE_RELATIONS,
@@ -4512,7 +4521,7 @@ IopPrepareDeviceForRemoval(IN PDEVICE_OBJECT DeviceObject, BOOLEAN Force)
     {
         DeviceRelations = (PDEVICE_RELATIONS)IoStatusBlock.Information;
     }
-    
+
     if (DeviceRelations)
     {
         Status = IopQueryRemoveDeviceRelations(DeviceRelations, Force);
@@ -4529,6 +4538,7 @@ IopPrepareDeviceForRemoval(IN PDEVICE_OBJECT DeviceObject, BOOLEAN Force)
     }
 
     DeviceNode->Flags |= DNF_WILL_BE_REMOVED;
+    DeviceNode->Problem = CM_PROB_WILL_BE_REMOVED;
     if (DeviceRelations)
         IopSendRemoveDeviceRelations(DeviceRelations);
     IopSendRemoveChildDevices(DeviceNode);
@@ -4619,7 +4629,8 @@ IoRequestDeviceEject(IN PDEVICE_OBJECT PhysicalDeviceObject)
     if (DeviceRelations)
         IopSendRemoveDeviceRelations(DeviceRelations);
     IopSendRemoveChildDevices(DeviceNode);
-    
+
+    DeviceNode->Problem = CM_PROB_HELD_FOR_EJECT;
     if (Capabilities.EjectSupported)
     {
         if (IopSendEject(PhysicalDeviceObject) != STATUS_SUCCESS)