diff --git a/reactos/drivers/bus/acpi/acpienum.c b/reactos/drivers/bus/acpi/acpienum.c index ab1047fe7fd..b5aea37f619 100644 --- a/reactos/drivers/bus/acpi/acpienum.c +++ b/reactos/drivers/bus/acpi/acpienum.c @@ -45,10 +45,38 @@ Bus_PlugInDevice ( for (entry = FdoData->ListOfPDOs.Flink; entry != &FdoData->ListOfPDOs; entry = entry->Flink) { - pdoData = CONTAINING_RECORD (entry, PDO_DEVICE_DATA, Link); - //dont duplicate devices - if(pdoData->AcpiHandle == Device->handle) + struct acpi_device *CurrentDevice; + + pdoData = CONTAINING_RECORD (entry, PDO_DEVICE_DATA, Link); + + //dont duplicate devices + if (pdoData->AcpiHandle == Device->handle) + return STATUS_SUCCESS; + + //check everything but fixed feature devices + if (pdoData->AcpiHandle) + acpi_bus_get_device(pdoData->AcpiHandle, &CurrentDevice); + else + continue; + + //check if the HID matches + if (strstr(Device->pnp.hardware_id, CurrentDevice->pnp.hardware_id)) + { + //check if UID exists for both and matches + if (Device->flags.unique_id && CurrentDevice->flags.unique_id && + strstr(Device->pnp.unique_id, CurrentDevice->pnp.unique_id)) + { + /* We have a UID on both but they're the same so we have to ignore it */ + DPRINT1("Detected duplicate device: %hs %hs\n", Device->pnp.hardware_id, Device->pnp.unique_id); return STATUS_SUCCESS; + } + else if (!Device->flags.unique_id && !CurrentDevice->flags.unique_id) + { + /* No UID so we can only legally have 1 of these devices */ + DPRINT1("Detected duplicate device: %hs\n", Device->pnp.hardware_id); + return STATUS_SUCCESS; + } + } } DPRINT("Exposing PDO\n" diff --git a/reactos/ntoskrnl/io/pnpmgr/plugplay.c b/reactos/ntoskrnl/io/pnpmgr/plugplay.c index 745f7572b28..68cdbc54e3c 100644 --- a/reactos/ntoskrnl/io/pnpmgr/plugplay.c +++ b/reactos/ntoskrnl/io/pnpmgr/plugplay.c @@ -141,7 +141,7 @@ IopTraverseDeviceNode(PDEVICE_NODE Node, PUNICODE_STRING DeviceInstance) } -static PDEVICE_OBJECT +PDEVICE_OBJECT IopGetDeviceObjectFromDeviceInstance(PUNICODE_STRING DeviceInstance) { if (IopRootDeviceNode == NULL) diff --git a/reactos/ntoskrnl/io/pnpmgr/pnpmgr.c b/reactos/ntoskrnl/io/pnpmgr/pnpmgr.c index 710fef0a2bc..0823e46a1c9 100644 --- a/reactos/ntoskrnl/io/pnpmgr/pnpmgr.c +++ b/reactos/ntoskrnl/io/pnpmgr/pnpmgr.c @@ -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) @@ -1850,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); @@ -1991,12 +1996,26 @@ 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) + { + DPRINT1("Duplicate device instance '%wZ'\n", &InstancePathU); + 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); /*