[i8042prt]
[reactos.git] / reactos / ntoskrnl / io / pnpmgr / pnpmgr.c
index c52453b..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++)
     {
@@ -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
           }
       }
 
@@ -1158,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)
@@ -1361,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 */
@@ -1849,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);
@@ -1990,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);
 
    /*
@@ -2243,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;
@@ -2493,6 +2516,7 @@ IopActionConfigureChildServices(PDEVICE_NODE DeviceNode,
          }
          else
          {
+            DeviceNode->Problem = CM_PROB_FAILED_INSTALL;
             IopDeviceNodeSetFlag(DeviceNode, DNF_DISABLED);
          }
          return STATUS_SUCCESS;
@@ -2598,11 +2622,18 @@ IopActionInitChildServices(PDEVICE_NODE DeviceNode,
             /* Initialize the driver */
             Status = IopInitializeDriverModule(DeviceNode, ModuleObject,
                   &DeviceNode->ServiceName, FALSE, &DriverObject);
+            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
          {
             DPRINT("IopLoadServiceModule(%wZ) failed with status 0x%08x\n",
                     &DeviceNode->ServiceName, Status);
+            if (!BootDrivers) DeviceNode->Problem = CM_PROB_DRIVER_FAILED_LOAD;
          }
       }
 
@@ -2613,7 +2644,7 @@ IopActionInitChildServices(PDEVICE_NODE DeviceNode,
           Status = PipCallDriverAddDevice(DeviceNode, FALSE, DriverObject);
 
           /* Remove the extra reference */
-          //ObDereferenceObject(DriverObject);
+          ObDereferenceObject(DriverObject);
       }
       else
       {
@@ -2623,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);
          }
       }
    }
@@ -3755,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
@@ -4015,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 */
@@ -4028,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))
         {
@@ -4476,7 +4507,7 @@ IopPrepareDeviceForRemoval(IN PDEVICE_OBJECT DeviceObject, BOOLEAN Force)
     }
     
     Stack.Parameters.QueryDeviceRelations.Type = RemovalRelations;
-    
+
     Status = IopInitiatePnpIrp(DeviceObject,
                                &IoStatusBlock,
                                IRP_MN_QUERY_DEVICE_RELATIONS,
@@ -4490,7 +4521,7 @@ IopPrepareDeviceForRemoval(IN PDEVICE_OBJECT DeviceObject, BOOLEAN Force)
     {
         DeviceRelations = (PDEVICE_RELATIONS)IoStatusBlock.Information;
     }
-    
+
     if (DeviceRelations)
     {
         Status = IopQueryRemoveDeviceRelations(DeviceRelations, Force);
@@ -4507,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);
@@ -4597,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)