From 200cdb6daf60b09fb2d3f8a28139685ee5d72449 Mon Sep 17 00:00:00 2001 From: Cameron Gutman Date: Tue, 31 May 2011 18:11:40 +0000 Subject: [PATCH] [NTOSKRNL] - Set the DNF_DISABLED flag if a driver returns with the HardwareDisabled flag set to true (but only BEFORE starting the device) - Don't try to start a device with the DNF_DISABLED flag set - Send IRP_MN_QUERY_CAPABILITIES (again) and IRP_MN_QUERY_PNP_DEVICE_STATE after the device has started - Write the UINumber and Capabilities registry entries in IopQueryDeviceCapabilities so they will be updated after every IRP_MN_QUERY_CAPABILITIES is sent - Set the DNUF_DONT_SHOW_IN_UI flag in response to the NoDisplayInUI flag set in DEVICE_CAPABILITIES or PNP_DEVICE_DONT_DISPLAY_IN_UI set after sending IRP_MN_QUERY_PNP_DEVICE_STATE - Set DNUF_NBOT_DISABLEABLE if PNP_DEVICE_NOT_DISABLEABLE is set after sending IRP_MN_QUERY_PNP_DEVICE_STATE - Remove duplicate code - Fix sending GUID_DEVICE_ARRIVAL (patch by Eric Kohl) - IRPs sent to PnP devices on enumeration and start are now completely compatible with Windows XP/2003/Vista svn path=/trunk/; revision=52026 --- reactos/ntoskrnl/include/internal/io.h | 5 + reactos/ntoskrnl/io/pnpmgr/pnpmgr.c | 172 ++++++++++++++----------- 2 files changed, 103 insertions(+), 74 deletions(-) diff --git a/reactos/ntoskrnl/include/internal/io.h b/reactos/ntoskrnl/include/internal/io.h index 8edb68e75be..052d350ea8a 100644 --- a/reactos/ntoskrnl/include/internal/io.h +++ b/reactos/ntoskrnl/include/internal/io.h @@ -600,6 +600,11 @@ IopFreeDeviceNode( IN PDEVICE_NODE DeviceNode ); +NTSTATUS +NTAPI +IopQueryDeviceCapabilities(PDEVICE_NODE DeviceNode, + PDEVICE_CAPABILITIES DeviceCaps); + NTSTATUS NTAPI IopSynchronousCall( diff --git a/reactos/ntoskrnl/io/pnpmgr/pnpmgr.c b/reactos/ntoskrnl/io/pnpmgr/pnpmgr.c index 57bf88378ba..0636d812cfd 100644 --- a/reactos/ntoskrnl/io/pnpmgr/pnpmgr.c +++ b/reactos/ntoskrnl/io/pnpmgr/pnpmgr.c @@ -235,25 +235,23 @@ IopStartDevice2(IN PDEVICE_OBJECT DeviceObject) PDEVICE_NODE DeviceNode; NTSTATUS Status; PVOID Dummy; + DEVICE_CAPABILITIES DeviceCapabilities; /* Get the device node */ DeviceNode = IopGetDeviceNode(DeviceObject); + ASSERT(!(DeviceNode->Flags & DNF_DISABLED)); + /* Build the I/O stack locaiton */ RtlZeroMemory(&Stack, sizeof(IO_STACK_LOCATION)); Stack.MajorFunction = IRP_MJ_PNP; Stack.MinorFunction = IRP_MN_START_DEVICE; - /* Check if we didn't already report the resources */ - if (!(DeviceNode->Flags & DNF_RESOURCE_REPORTED)) - { - /* Report them */ - Stack.Parameters.StartDevice.AllocatedResources = - DeviceNode->ResourceList; - Stack.Parameters.StartDevice.AllocatedResourcesTranslated = - DeviceNode->ResourceListTranslated; - } - + Stack.Parameters.StartDevice.AllocatedResources = + DeviceNode->ResourceList; + Stack.Parameters.StartDevice.AllocatedResourcesTranslated = + DeviceNode->ResourceListTranslated; + /* Do the call */ Status = IopSynchronousCall(DeviceObject, &Stack, &Dummy); if (!NT_SUCCESS(Status)) @@ -268,6 +266,17 @@ IopStartDevice2(IN PDEVICE_OBJECT DeviceObject) return; } + DPRINT("Sending IRP_MN_QUERY_CAPABILITIES to device stack (after start)\n"); + + Status = IopQueryDeviceCapabilities(DeviceNode, &DeviceCapabilities); + if (!NT_SUCCESS(Status)) + { + DPRINT("IopInitiatePnpIrp() failed (Status 0x%08lx)\n", Status); + } + + /* Invalidate device state so IRP_MN_QUERY_PNP_DEVICE_STATE is sent */ + IoInvalidateDeviceState(DeviceObject); + /* Otherwise, mark us as started */ DeviceNode->Flags |= DNF_STARTED; DeviceNode->Flags &= ~DNF_STOPPED; @@ -316,7 +325,6 @@ IopStartAndEnumerateDevice(IN PDEVICE_NODE DeviceNode) { /* Enumerate us */ IoSynchronousInvalidateDeviceRelations(DeviceObject, BusRelations); - IopDeviceNodeClearFlag(DeviceNode, DNF_NEED_ENUMERATION_ONLY); Status = STATUS_SUCCESS; } else @@ -338,6 +346,9 @@ IopStartDevice( UNICODE_STRING KeyName; OBJECT_ATTRIBUTES ObjectAttributes; + if (DeviceNode->Flags & DNF_DISABLED) + return STATUS_SUCCESS; + Status = IopAssignDeviceResources(DeviceNode); if (!NT_SUCCESS(Status)) goto ByeBye; @@ -383,6 +394,9 @@ IopQueryDeviceCapabilities(PDEVICE_NODE DeviceNode, { IO_STATUS_BLOCK StatusBlock; IO_STACK_LOCATION Stack; + NTSTATUS Status; + HANDLE InstanceKey; + UNICODE_STRING ValueName; /* Set up the Header */ RtlZeroMemory(DeviceCaps, sizeof(DEVICE_CAPABILITIES)); @@ -396,10 +410,49 @@ IopQueryDeviceCapabilities(PDEVICE_NODE DeviceNode, Stack.Parameters.DeviceCapabilities.Capabilities = DeviceCaps; /* Send the IRP */ - return IopInitiatePnpIrp(DeviceNode->PhysicalDeviceObject, - &StatusBlock, - IRP_MN_QUERY_CAPABILITIES, - &Stack); + Status = IopInitiatePnpIrp(DeviceNode->PhysicalDeviceObject, + &StatusBlock, + IRP_MN_QUERY_CAPABILITIES, + &Stack); + if (!NT_SUCCESS(Status)) + { + DPRINT1("IRP_MN_QUERY_CAPABILITIES failed with status 0x%x\n", Status); + return Status; + } + + DeviceNode->CapabilityFlags = *(PULONG)((ULONG_PTR)&DeviceCaps + 4); + + if (DeviceCaps->NoDisplayInUI) + DeviceNode->UserFlags |= DNUF_DONT_SHOW_IN_UI; + else + DeviceNode->UserFlags &= DNUF_DONT_SHOW_IN_UI; + + Status = IopCreateDeviceKeyPath(&DeviceNode->InstancePath, 0, &InstanceKey); + if (NT_SUCCESS(Status)) + { + /* Set 'Capabilities' value */ + RtlInitUnicodeString(&ValueName, L"Capabilities"); + Status = ZwSetValueKey(InstanceKey, + &ValueName, + 0, + REG_DWORD, + (PVOID)&DeviceNode->CapabilityFlags, + sizeof(ULONG)); + + /* Set 'UINumber' value */ + if (DeviceCaps->UINumber != MAXULONG) + { + RtlInitUnicodeString(&ValueName, L"UINumber"); + Status = ZwSetValueKey(InstanceKey, + &ValueName, + 0, + REG_DWORD, + &DeviceCaps->UINumber, + sizeof(ULONG)); + } + } + + return Status; } static VOID NTAPI @@ -1303,7 +1356,7 @@ IopActionInterrogateDeviceStack(PDEVICE_NODE DeviceNode, DPRINT("IopInitiatePnpIrp() failed (Status %x)\n", Status); } - DPRINT("Sending IRP_MN_QUERY_CAPABILITIES to device stack\n"); + DPRINT("Sending IRP_MN_QUERY_CAPABILITIES to device stack (after enumeration)\n"); Status = IopQueryDeviceCapabilities(DeviceNode, &DeviceCapabilities); if (!NT_SUCCESS(Status)) @@ -1311,7 +1364,15 @@ IopActionInterrogateDeviceStack(PDEVICE_NODE DeviceNode, DPRINT("IopInitiatePnpIrp() failed (Status 0x%08lx)\n", Status); } - DeviceNode->CapabilityFlags = *(PULONG)((ULONG_PTR)&DeviceCapabilities + 4); + /* This bit is only check after enumeration */ + if (DeviceCapabilities.HardwareDisabled) + { + /* FIXME: Cleanup device */ + DeviceNode->Flags |= DNF_DISABLED; + return STATUS_SUCCESS; + } + else + DeviceNode->Flags &= ~DNF_DISABLED; if (!DeviceCapabilities.UniqueID) { @@ -1373,29 +1434,6 @@ IopActionInterrogateDeviceStack(PDEVICE_NODE DeviceNode, DPRINT1("Failed to create the instance key! (Status %lx)\n", Status); } - { - /* Set 'Capabilities' value */ - RtlInitUnicodeString(&ValueName, L"Capabilities"); - Status = ZwSetValueKey(InstanceKey, - &ValueName, - 0, - REG_DWORD, - (PVOID)&DeviceNode->CapabilityFlags, - sizeof(ULONG)); - - /* Set 'UINumber' value */ - if (DeviceCapabilities.UINumber != MAXULONG) - { - RtlInitUnicodeString(&ValueName, L"UINumber"); - Status = ZwSetValueKey(InstanceKey, - &ValueName, - 0, - REG_DWORD, - &DeviceCapabilities.UINumber, - sizeof(ULONG)); - } - } - DPRINT("Sending IRP_MN_QUERY_ID.BusQueryHardwareIDs to device stack\n"); Stack.Parameters.QueryId.IdType = BusQueryHardwareIDs; @@ -1697,6 +1735,15 @@ IopEnumerateDevice( DPRINT("DeviceObject 0x%p\n", DeviceObject); + if (DeviceNode->Flags & DNF_NEED_ENUMERATION_ONLY) + { + DeviceNode->Flags &= ~DNF_NEED_ENUMERATION_ONLY; + + DPRINT("Sending GUID_DEVICE_ARRIVAL\n"); + IopQueueTargetDeviceEvent(&GUID_DEVICE_ARRIVAL, + &DeviceNode->InstancePath); + } + DPRINT("Sending IRP_MN_QUERY_DEVICE_RELATIONS to device stack\n"); Stack.Parameters.QueryDeviceRelations.Type = BusRelations; @@ -1746,12 +1793,6 @@ IopEnumerateDevice( &ChildDeviceNode); if (NT_SUCCESS(Status)) { - DPRINT("Sending GUID_DEVICE_ARRIVAL\n"); - - /* Report the device to the user-mode pnp manager */ - IopQueueTargetDeviceEvent(&GUID_DEVICE_ARRIVAL, - &ChildDeviceNode->InstancePath); - /* Mark the node as enumerated */ ChildDeviceNode->Flags |= DNF_ENUMERATED; @@ -3160,33 +3201,6 @@ PnpBusTypeGuidGet(IN USHORT Index, return Status; } -NTSTATUS -NTAPI -PpIrpQueryCapabilities(IN PDEVICE_OBJECT DeviceObject, - OUT PDEVICE_CAPABILITIES DeviceCaps) -{ - PVOID Dummy; - IO_STACK_LOCATION Stack; - - PAGED_CODE(); - - /* Set up the Header */ - RtlZeroMemory(DeviceCaps, sizeof(DEVICE_CAPABILITIES)); - DeviceCaps->Size = sizeof(DEVICE_CAPABILITIES); - DeviceCaps->Version = 1; - DeviceCaps->Address = -1; - DeviceCaps->UINumber = -1; - - /* Set up the Stack */ - RtlZeroMemory(&Stack, sizeof(IO_STACK_LOCATION)); - Stack.MajorFunction = IRP_MJ_PNP; - Stack.MinorFunction = IRP_MN_QUERY_CAPABILITIES; - Stack.Parameters.DeviceCapabilities.Capabilities = DeviceCaps; - - /* Send the IRP */ - return IopSynchronousCall(DeviceObject, &Stack, &Dummy); -} - NTSTATUS NTAPI PnpDeviceObjectToDeviceInstance(IN PDEVICE_OBJECT DeviceObject, @@ -3446,7 +3460,7 @@ IoGetDeviceProperty(IN PDEVICE_OBJECT DeviceObject, case DevicePropertyAddress: /* Query the device caps */ - Status = PpIrpQueryCapabilities(DeviceObject, &DeviceCaps); + Status = IopQueryDeviceCapabilities(DeviceNode, &DeviceCaps); if (!NT_SUCCESS(Status) || (DeviceCaps.Address == MAXULONG)) return STATUS_OBJECT_NAME_NOT_FOUND; @@ -3607,6 +3621,16 @@ IoInvalidateDeviceState(IN PDEVICE_OBJECT PhysicalDeviceObject) return; } + if (PnPFlags & PNP_DEVICE_NOT_DISABLEABLE) + DeviceNode->UserFlags |= DNUF_NOT_DISABLEABLE; + else + DeviceNode->UserFlags &= ~DNUF_NOT_DISABLEABLE; + + if (PnPFlags & PNP_DEVICE_DONT_DISPLAY_IN_UI) + DeviceNode->UserFlags |= DNUF_DONT_SHOW_IN_UI; + else + DeviceNode->UserFlags &= ~DNUF_DONT_SHOW_IN_UI; + if ((PnPFlags & PNP_DEVICE_REMOVED) || ((PnPFlags & PNP_DEVICE_FAILED) && !(PnPFlags & PNP_DEVICE_RESOURCE_REQUIREMENTS_CHANGED))) {