KGUARDED_MUTEX PpDeviceReferenceTableLock;
RTL_AVL_TABLE PpDeviceReferenceTable;
+extern ERESOURCE IopDriverLoadResource;
extern ULONG ExpInitializationPhase;
-extern BOOLEAN ExpInTextModeSetup;
extern BOOLEAN PnpSystemInit;
+#define MAX_DEVICE_ID_LEN 200
+#define MAX_SEPARATORS_INSTANCEID 0
+#define MAX_SEPARATORS_DEVICEID 1
+
/* DATA **********************************************************************/
PDRIVER_OBJECT IopRootDriverObject;
PIO_BUS_TYPE_GUID_LIST PnpBusTypeGuidList = NULL;
+LIST_ENTRY IopDeviceActionRequestList;
+WORK_QUEUE_ITEM IopDeviceActionWorkItem;
+BOOLEAN IopDeviceActionInProgress;
+KSPIN_LOCK IopDeviceActionLock;
-typedef struct _INVALIDATE_DEVICE_RELATION_DATA
+typedef struct _DEVICE_ACTION_DATA
{
+ LIST_ENTRY RequestListEntry;
PDEVICE_OBJECT DeviceObject;
DEVICE_RELATION_TYPE Type;
- PIO_WORKITEM WorkItem;
-} INVALIDATE_DEVICE_RELATION_DATA, *PINVALIDATE_DEVICE_RELATION_DATA;
+} DEVICE_ACTION_DATA, *PDEVICE_ACTION_DATA;
/* FUNCTIONS *****************************************************************/
NTSTATUS
PKEY_VALUE_PARTIAL_INFORMATION PartialInfo;
ULONG HidLength = 0, CidLength = 0, BufferLength;
PWCHAR IdBuffer, OriginalIdBuffer;
-
+
/* Open the device instance key */
- Status = IopCreateDeviceKeyPath(&DeviceNode->InstancePath, 0, &InstanceKey);
+ Status = IopCreateDeviceKeyPath(&DeviceNode->InstancePath, REG_OPTION_NON_VOLATILE, &InstanceKey);
if (Status != STATUS_SUCCESS)
return;
ZwClose(InstanceKey);
return;
}
-
+
/* Copy CID next */
CidLength = PartialInfo->DataLength;
RtlCopyMemory(((PUCHAR)IdBuffer) + HidLength, PartialInfo->Data, CidLength);
/* Free our temp buffer */
ExFreePool(PartialInfo);
-
+
InitializeObjectAttributes(&ObjectAttributes,
&CriticalDeviceKeyU,
OBJ_KERNEL_HANDLE | OBJ_CASE_INSENSITIVE,
while (*IdBuffer)
{
USHORT StringLength = (USHORT)wcslen(IdBuffer) + 1, Index;
-
+
IopFixupDeviceId(IdBuffer);
-
+
/* Look through all subkeys for a match */
for (Index = 0; TRUE; Index++)
{
ULONG NeededLength;
PKEY_BASIC_INFORMATION BasicInfo;
-
+
Status = ZwEnumerateKey(CriticalDeviceKey,
Index,
KeyBasicInformation,
continue;
}
- DPRINT1("Installed service '%S' for critical device '%wZ'\n", PartialInfo->Data, &ChildIdNameU);
+ DPRINT("Installed service '%S' for critical device '%wZ'\n", PartialInfo->Data, &ChildIdNameU);
}
else
{
/* Advance to the next ID */
IdBuffer += StringLength;
}
-
+
ExFreePool(OriginalIdBuffer);
ZwClose(InstanceKey);
ZwClose(CriticalDeviceKey);
IopInitializeDevice(PDEVICE_NODE DeviceNode,
PDRIVER_OBJECT DriverObject)
{
- PDEVICE_OBJECT Fdo;
- NTSTATUS Status;
-
- if (!DriverObject)
- {
- /* Special case for bus driven devices */
- DeviceNode->Flags |= DNF_ADDED;
- return STATUS_SUCCESS;
- }
+ PDEVICE_OBJECT Fdo;
+ NTSTATUS Status;
- if (!DriverObject->DriverExtension->AddDevice)
- {
- DeviceNode->Flags |= DNF_LEGACY_DRIVER;
- }
+ if (!DriverObject)
+ {
+ /* Special case for bus driven devices */
+ DeviceNode->Flags |= DNF_ADDED;
+ return STATUS_SUCCESS;
+ }
- if (DeviceNode->Flags & DNF_LEGACY_DRIVER)
- {
- DeviceNode->Flags |= DNF_ADDED + DNF_STARTED;
- return STATUS_SUCCESS;
- }
+ if (!DriverObject->DriverExtension->AddDevice)
+ {
+ DeviceNode->Flags |= DNF_LEGACY_DRIVER;
+ }
+
+ if (DeviceNode->Flags & DNF_LEGACY_DRIVER)
+ {
+ DeviceNode->Flags |= (DNF_ADDED | DNF_STARTED);
+ return STATUS_SUCCESS;
+ }
- /* This is a Plug and Play driver */
- DPRINT("Plug and Play driver found\n");
- ASSERT(DeviceNode->PhysicalDeviceObject);
+ /* This is a Plug and Play driver */
+ DPRINT("Plug and Play driver found\n");
+ ASSERT(DeviceNode->PhysicalDeviceObject);
- DPRINT("Calling %wZ->AddDevice(%wZ)\n",
- &DriverObject->DriverName,
- &DeviceNode->InstancePath);
- Status = DriverObject->DriverExtension->AddDevice(
- DriverObject, DeviceNode->PhysicalDeviceObject);
- if (!NT_SUCCESS(Status))
- {
- DPRINT1("%wZ->AddDevice(%wZ) failed with status 0x%x\n",
- &DriverObject->DriverName,
- &DeviceNode->InstancePath,
- Status);
- IopDeviceNodeSetFlag(DeviceNode, DNF_DISABLED);
- DeviceNode->Problem = CM_PROB_FAILED_ADD;
- return Status;
- }
+ DPRINT("Calling %wZ->AddDevice(%wZ)\n",
+ &DriverObject->DriverName,
+ &DeviceNode->InstancePath);
+ Status = DriverObject->DriverExtension->AddDevice(DriverObject,
+ DeviceNode->PhysicalDeviceObject);
+ if (!NT_SUCCESS(Status))
+ {
+ DPRINT1("%wZ->AddDevice(%wZ) failed with status 0x%x\n",
+ &DriverObject->DriverName,
+ &DeviceNode->InstancePath,
+ Status);
+ IopDeviceNodeSetFlag(DeviceNode, DNF_DISABLED);
+ DeviceNode->Problem = CM_PROB_FAILED_ADD;
+ return Status;
+ }
- Fdo = IoGetAttachedDeviceReference(DeviceNode->PhysicalDeviceObject);
+ Fdo = IoGetAttachedDeviceReference(DeviceNode->PhysicalDeviceObject);
- /* Check if we have a ACPI device (needed for power management) */
- if (Fdo->DeviceType == FILE_DEVICE_ACPI)
- {
- static BOOLEAN SystemPowerDeviceNodeCreated = FALSE;
+ /* Check if we have a ACPI device (needed for power management) */
+ if (Fdo->DeviceType == FILE_DEVICE_ACPI)
+ {
+ static BOOLEAN SystemPowerDeviceNodeCreated = FALSE;
- /* There can be only one system power device */
- if (!SystemPowerDeviceNodeCreated)
- {
- PopSystemPowerDeviceNode = DeviceNode;
- ObReferenceObject(PopSystemPowerDeviceNode->PhysicalDeviceObject);
- SystemPowerDeviceNodeCreated = TRUE;
- }
- }
+ /* There can be only one system power device */
+ if (!SystemPowerDeviceNodeCreated)
+ {
+ PopSystemPowerDeviceNode = DeviceNode;
+ ObReferenceObject(PopSystemPowerDeviceNode->PhysicalDeviceObject);
+ SystemPowerDeviceNodeCreated = TRUE;
+ }
+ }
- ObDereferenceObject(Fdo);
+ ObDereferenceObject(Fdo);
- IopDeviceNodeSetFlag(DeviceNode, DNF_ADDED);
+ IopDeviceNodeSetFlag(DeviceNode, DNF_ADDED);
- return STATUS_SUCCESS;
+ return STATUS_SUCCESS;
}
static
{
IO_STACK_LOCATION Stack;
PVOID Dummy;
-
+
RtlZeroMemory(&Stack, sizeof(IO_STACK_LOCATION));
Stack.MajorFunction = IRP_MJ_PNP;
Stack.MinorFunction = IRP_MN_EJECT;
-
+
return IopSynchronousCall(DeviceObject, &Stack, &Dummy);
}
{
IO_STACK_LOCATION Stack;
PVOID Dummy;
-
+
RtlZeroMemory(&Stack, sizeof(IO_STACK_LOCATION));
Stack.MajorFunction = IRP_MJ_PNP;
Stack.MinorFunction = IRP_MN_SURPRISE_REMOVAL;
-
+
/* Drivers should never fail a IRP_MN_SURPRISE_REMOVAL request */
IopSynchronousCall(DeviceObject, &Stack, &Dummy);
}
IO_STACK_LOCATION Stack;
PVOID Dummy;
NTSTATUS Status;
-
+
ASSERT(DeviceNode);
-
+
IopQueueTargetDeviceEvent(&GUID_DEVICE_REMOVE_PENDING,
&DeviceNode->InstancePath);
-
+
RtlZeroMemory(&Stack, sizeof(IO_STACK_LOCATION));
Stack.MajorFunction = IRP_MJ_PNP;
Stack.MinorFunction = IRP_MN_QUERY_REMOVE_DEVICE;
&GUID_TARGET_DEVICE_QUERY_REMOVE,
NULL,
NULL);
-
+
if (!NT_SUCCESS(Status))
{
DPRINT1("Removal vetoed by %wZ\n", &DeviceNode->InstancePath);
{
IO_STACK_LOCATION Stack;
PVOID Dummy;
-
+
RtlZeroMemory(&Stack, sizeof(IO_STACK_LOCATION));
Stack.MajorFunction = IRP_MJ_PNP;
Stack.MinorFunction = IRP_MN_QUERY_STOP_DEVICE;
-
+
return IopSynchronousCall(DeviceObject, &Stack, &Dummy);
}
{
IO_STACK_LOCATION Stack;
PVOID Dummy;
+ PDEVICE_NODE DeviceNode = IopGetDeviceNode(DeviceObject);
+
+ /* Drop all our state for this device in case it isn't really going away */
+ DeviceNode->Flags &= DNF_ENUMERATED | DNF_PROCESSED;
RtlZeroMemory(&Stack, sizeof(IO_STACK_LOCATION));
Stack.MajorFunction = IRP_MJ_PNP;
&GUID_TARGET_DEVICE_REMOVE_COMPLETE,
NULL,
NULL);
+ ObDereferenceObject(DeviceObject);
}
static
{
IO_STACK_LOCATION Stack;
PVOID Dummy;
-
+
RtlZeroMemory(&Stack, sizeof(IO_STACK_LOCATION));
Stack.MajorFunction = IRP_MJ_PNP;
Stack.MinorFunction = IRP_MN_CANCEL_REMOVE_DEVICE;
-
+
/* Drivers should never fail a IRP_MN_CANCEL_REMOVE_DEVICE request */
IopSynchronousCall(DeviceObject, &Stack, &Dummy);
-
+
IopNotifyPlugPlayNotification(DeviceObject,
EventCategoryTargetDeviceChange,
&GUID_TARGET_DEVICE_REMOVE_CANCELLED,
{
IO_STACK_LOCATION Stack;
PVOID Dummy;
-
+
RtlZeroMemory(&Stack, sizeof(IO_STACK_LOCATION));
Stack.MajorFunction = IRP_MJ_PNP;
Stack.MinorFunction = IRP_MN_STOP_DEVICE;
-
+
/* Drivers should never fail a IRP_MN_STOP_DEVICE request */
IopSynchronousCall(DeviceObject, &Stack, &Dummy);
}
+static
+NTSTATUS
+IopSetServiceEnumData(PDEVICE_NODE DeviceNode)
+{
+ UNICODE_STRING ServicesKeyPath = RTL_CONSTANT_STRING(L"\\Registry\\Machine\\System\\CurrentControlSet\\Services\\");
+ UNICODE_STRING ServiceKeyName;
+ UNICODE_STRING EnumKeyName;
+ UNICODE_STRING ValueName;
+ PKEY_VALUE_FULL_INFORMATION KeyValueInformation;
+ HANDLE ServiceKey = NULL, ServiceEnumKey;
+ ULONG Disposition;
+ ULONG Count = 0, NextInstance = 0;
+ WCHAR ValueBuffer[6];
+ NTSTATUS Status = STATUS_SUCCESS;
+
+ DPRINT("IopSetServiceEnumData(%p)\n", DeviceNode);
+ DPRINT("Instance: %wZ\n", &DeviceNode->InstancePath);
+ DPRINT("Service: %wZ\n", &DeviceNode->ServiceName);
+
+ if (DeviceNode->ServiceName.Buffer == NULL)
+ {
+ DPRINT1("No service!\n");
+ return STATUS_SUCCESS;
+ }
+
+ ServiceKeyName.MaximumLength = ServicesKeyPath.Length + DeviceNode->ServiceName.Length + sizeof(UNICODE_NULL);
+ ServiceKeyName.Length = 0;
+ ServiceKeyName.Buffer = ExAllocatePool(PagedPool, ServiceKeyName.MaximumLength);
+ if (ServiceKeyName.Buffer == NULL)
+ {
+ DPRINT1("No ServiceKeyName.Buffer!\n");
+ return STATUS_INSUFFICIENT_RESOURCES;
+ }
+
+ RtlAppendUnicodeStringToString(&ServiceKeyName, &ServicesKeyPath);
+ RtlAppendUnicodeStringToString(&ServiceKeyName, &DeviceNode->ServiceName);
+
+ DPRINT("ServiceKeyName: %wZ\n", &ServiceKeyName);
+
+ Status = IopOpenRegistryKeyEx(&ServiceKey, NULL, &ServiceKeyName, KEY_CREATE_SUB_KEY);
+ if (!NT_SUCCESS(Status))
+ {
+ goto done;
+ }
+
+ RtlInitUnicodeString(&EnumKeyName, L"Enum");
+ Status = IopCreateRegistryKeyEx(&ServiceEnumKey,
+ ServiceKey,
+ &EnumKeyName,
+ KEY_SET_VALUE,
+ REG_OPTION_VOLATILE,
+ &Disposition);
+ if (NT_SUCCESS(Status))
+ {
+ if (Disposition == REG_OPENED_EXISTING_KEY)
+ {
+ /* Read the NextInstance value */
+ Status = IopGetRegistryValue(ServiceEnumKey,
+ L"Count",
+ &KeyValueInformation);
+ if (!NT_SUCCESS(Status))
+ goto done;
+
+ if ((KeyValueInformation->Type == REG_DWORD) &&
+ (KeyValueInformation->DataLength))
+ {
+ /* Read it */
+ Count = *(PULONG)((ULONG_PTR)KeyValueInformation +
+ KeyValueInformation->DataOffset);
+ }
+
+ ExFreePool(KeyValueInformation);
+ KeyValueInformation = NULL;
+
+ /* Read the NextInstance value */
+ Status = IopGetRegistryValue(ServiceEnumKey,
+ L"NextInstance",
+ &KeyValueInformation);
+ if (!NT_SUCCESS(Status))
+ goto done;
+
+ if ((KeyValueInformation->Type == REG_DWORD) &&
+ (KeyValueInformation->DataLength))
+ {
+ NextInstance = *(PULONG)((ULONG_PTR)KeyValueInformation +
+ KeyValueInformation->DataOffset);
+ }
+
+ ExFreePool(KeyValueInformation);
+ KeyValueInformation = NULL;
+ }
+
+ /* Set the instance path */
+ swprintf(ValueBuffer, L"%lu", NextInstance);
+ RtlInitUnicodeString(&ValueName, ValueBuffer);
+ Status = ZwSetValueKey(ServiceEnumKey,
+ &ValueName,
+ 0,
+ REG_SZ,
+ DeviceNode->InstancePath.Buffer,
+ DeviceNode->InstancePath.MaximumLength);
+ if (!NT_SUCCESS(Status))
+ goto done;
+
+ /* Increment Count and NextInstance */
+ Count++;
+ NextInstance++;
+
+ /* Set the new Count value */
+ RtlInitUnicodeString(&ValueName, L"Count");
+ Status = ZwSetValueKey(ServiceEnumKey,
+ &ValueName,
+ 0,
+ REG_DWORD,
+ &Count,
+ sizeof(Count));
+ if (!NT_SUCCESS(Status))
+ goto done;
+
+ /* Set the new NextInstance value */
+ RtlInitUnicodeString(&ValueName, L"NextInstance");
+ Status = ZwSetValueKey(ServiceEnumKey,
+ &ValueName,
+ 0,
+ REG_DWORD,
+ &NextInstance,
+ sizeof(NextInstance));
+ }
+
+done:
+ if (ServiceEnumKey != NULL)
+ ZwClose(ServiceEnumKey);
+
+ if (ServiceKey != NULL)
+ ZwClose(ServiceKey);
+
+ ExFreePool(ServiceKeyName.Buffer);
+
+ return Status;
+}
+
VOID
NTAPI
IopStartDevice2(IN PDEVICE_OBJECT DeviceObject)
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 */
+ /* Build the I/O stack location */
RtlZeroMemory(&Stack, sizeof(IO_STACK_LOCATION));
Stack.MajorFunction = IRP_MJ_PNP;
Stack.MinorFunction = IRP_MN_START_DEVICE;
-
+
Stack.Parameters.StartDevice.AllocatedResources =
DeviceNode->ResourceList;
Stack.Parameters.StartDevice.AllocatedResourcesTranslated =
DPRINT1("Warning: PnP Start failed (%wZ) [Status: 0x%x]\n", &DeviceNode->InstancePath, Status);
return;
}
-
+
DPRINT("Sending IRP_MN_QUERY_CAPABILITIES to device stack (after start)\n");
Status = IopQueryDeviceCapabilities(DeviceNode, &DeviceCapabilities);
if (!NT_SUCCESS(Status))
{
- DPRINT1("IopInitiatePnpIrp() failed (Status 0x%08lx)\n", 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;
PDEVICE_OBJECT DeviceObject;
NTSTATUS Status;
PAGED_CODE();
-
+
/* Sanity check */
ASSERT((DeviceNode->Flags & DNF_ADDED));
ASSERT((DeviceNode->Flags & (DNF_RESOURCE_ASSIGNED |
DNF_RESOURCE_REPORTED |
DNF_NO_RESOURCE_REQUIRED)));
-
+
/* Get the device object */
DeviceObject = DeviceNode->PhysicalDeviceObject;
-
+
/* Check if we're not started yet */
if (!(DeviceNode->Flags & DNF_STARTED))
{
/* Start us */
IopStartDevice2(DeviceObject);
}
-
+
/* Do we need to query IDs? This happens in the case of manual reporting */
#if 0
if (DeviceNode->Flags & DNF_NEED_QUERY_IDS)
ASSERT(FALSE);
}
#endif
-
+
+ IopSetServiceEnumData(DeviceNode);
+
/* Make sure we're started, and check if we need enumeration */
if ((DeviceNode->Flags & DNF_STARTED) &&
(DeviceNode->Flags & DNF_NEED_ENUMERATION_ONLY))
/* Nothing to do */
Status = STATUS_SUCCESS;
}
-
+
/* Return */
return Status;
}
IopStopDevice(
PDEVICE_NODE DeviceNode)
{
- NTSTATUS Status;
+ NTSTATUS Status;
- DPRINT("Stopping device: %wZ\n", &DeviceNode->InstancePath);
+ DPRINT("Stopping device: %wZ\n", &DeviceNode->InstancePath);
- Status = IopQueryStopDevice(DeviceNode->PhysicalDeviceObject);
- if (NT_SUCCESS(Status))
- {
- IopSendStopDevice(DeviceNode->PhysicalDeviceObject);
+ Status = IopQueryStopDevice(DeviceNode->PhysicalDeviceObject);
+ if (NT_SUCCESS(Status))
+ {
+ IopSendStopDevice(DeviceNode->PhysicalDeviceObject);
- DeviceNode->Flags &= ~(DNF_STARTED | DNF_START_REQUEST_PENDING);
- DeviceNode->Flags |= DNF_STOPPED;
+ DeviceNode->Flags &= ~(DNF_STARTED | DNF_START_REQUEST_PENDING);
+ DeviceNode->Flags |= DNF_STOPPED;
- return STATUS_SUCCESS;
- }
+ return STATUS_SUCCESS;
+ }
- return Status;
+ return Status;
}
NTSTATUS
IopStartDevice(
PDEVICE_NODE DeviceNode)
{
- NTSTATUS Status;
- HANDLE InstanceHandle = INVALID_HANDLE_VALUE, ControlHandle = INVALID_HANDLE_VALUE;
- UNICODE_STRING KeyName;
- OBJECT_ATTRIBUTES ObjectAttributes;
+ NTSTATUS Status;
+ HANDLE InstanceHandle = NULL, ControlHandle = NULL;
+ UNICODE_STRING KeyName, ValueString;
+ OBJECT_ATTRIBUTES ObjectAttributes;
- if (DeviceNode->Flags & DNF_DISABLED)
- return STATUS_SUCCESS;
+ if (DeviceNode->Flags & DNF_DISABLED)
+ return STATUS_SUCCESS;
- Status = IopAssignDeviceResources(DeviceNode);
- if (!NT_SUCCESS(Status))
- goto ByeBye;
+ Status = IopAssignDeviceResources(DeviceNode);
+ if (!NT_SUCCESS(Status))
+ goto ByeBye;
- /* New PnP ABI */
- IopStartAndEnumerateDevice(DeviceNode);
+ /* New PnP ABI */
+ IopStartAndEnumerateDevice(DeviceNode);
- /* FIX: Should be done in new device instance code */
- Status = IopCreateDeviceKeyPath(&DeviceNode->InstancePath, 0, &InstanceHandle);
- if (!NT_SUCCESS(Status))
- goto ByeBye;
+ /* FIX: Should be done in new device instance code */
+ Status = IopCreateDeviceKeyPath(&DeviceNode->InstancePath, REG_OPTION_NON_VOLATILE, &InstanceHandle);
+ if (!NT_SUCCESS(Status))
+ goto ByeBye;
- /* FIX: Should be done in IoXxxPrepareDriverLoading */
- // {
- RtlInitUnicodeString(&KeyName, L"Control");
- InitializeObjectAttributes(&ObjectAttributes,
- &KeyName,
- OBJ_CASE_INSENSITIVE,
- InstanceHandle,
- NULL);
- Status = ZwCreateKey(&ControlHandle, KEY_SET_VALUE, &ObjectAttributes, 0, NULL, REG_OPTION_VOLATILE, NULL);
- if (!NT_SUCCESS(Status))
- goto ByeBye;
+ /* FIX: Should be done in IoXxxPrepareDriverLoading */
+ // {
+ RtlInitUnicodeString(&KeyName, L"Control");
+ InitializeObjectAttributes(&ObjectAttributes,
+ &KeyName,
+ OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE,
+ InstanceHandle,
+ NULL);
+ Status = ZwCreateKey(&ControlHandle,
+ KEY_SET_VALUE,
+ &ObjectAttributes,
+ 0,
+ NULL,
+ REG_OPTION_VOLATILE,
+ NULL);
+ if (!NT_SUCCESS(Status))
+ goto ByeBye;
RtlInitUnicodeString(&KeyName, L"ActiveService");
- Status = ZwSetValueKey(ControlHandle, &KeyName, 0, REG_SZ, DeviceNode->ServiceName.Buffer, DeviceNode->ServiceName.Length);
+ ValueString = DeviceNode->ServiceName;
+ if (!ValueString.Buffer)
+ RtlInitUnicodeString(&ValueString, L"");
+ Status = ZwSetValueKey(ControlHandle, &KeyName, 0, REG_SZ, ValueString.Buffer, ValueString.Length + sizeof(UNICODE_NULL));
// }
ByeBye:
- if (ControlHandle != INVALID_HANDLE_VALUE)
- ZwClose(ControlHandle);
+ if (ControlHandle != NULL)
+ ZwClose(ControlHandle);
- if (InstanceHandle != INVALID_HANDLE_VALUE)
- ZwClose(InstanceHandle);
+ if (InstanceHandle != NULL)
+ ZwClose(InstanceHandle);
- return Status;
+ return Status;
}
NTSTATUS
IopQueryDeviceCapabilities(PDEVICE_NODE DeviceNode,
PDEVICE_CAPABILITIES DeviceCaps)
{
- IO_STATUS_BLOCK StatusBlock;
- IO_STACK_LOCATION Stack;
- NTSTATUS Status;
- HANDLE InstanceKey;
- UNICODE_STRING ValueName;
-
- /* 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.Parameters.DeviceCapabilities.Capabilities = DeviceCaps;
-
- /* Send the IRP */
- 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;
- }
+ IO_STATUS_BLOCK StatusBlock;
+ IO_STACK_LOCATION Stack;
+ NTSTATUS Status;
+ HANDLE InstanceKey;
+ UNICODE_STRING ValueName;
- DeviceNode->CapabilityFlags = *(PULONG)((ULONG_PTR)&DeviceCaps->Version + sizeof(DeviceCaps->Version));
+ /* Set up the Header */
+ RtlZeroMemory(DeviceCaps, sizeof(DEVICE_CAPABILITIES));
+ DeviceCaps->Size = sizeof(DEVICE_CAPABILITIES);
+ DeviceCaps->Version = 1;
+ DeviceCaps->Address = -1;
+ DeviceCaps->UINumber = -1;
- if (DeviceCaps->NoDisplayInUI)
- DeviceNode->UserFlags |= DNUF_DONT_SHOW_IN_UI;
- else
- DeviceNode->UserFlags &= ~DNUF_DONT_SHOW_IN_UI;
+ /* Set up the Stack */
+ RtlZeroMemory(&Stack, sizeof(IO_STACK_LOCATION));
+ Stack.Parameters.DeviceCapabilities.Capabilities = DeviceCaps;
- 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));
+ /* Send the IRP */
+ Status = IopInitiatePnpIrp(DeviceNode->PhysicalDeviceObject,
+ &StatusBlock,
+ IRP_MN_QUERY_CAPABILITIES,
+ &Stack);
+ if (!NT_SUCCESS(Status))
+ {
+ if (Status != STATUS_NOT_SUPPORTED)
+ {
+ DPRINT1("IRP_MN_QUERY_CAPABILITIES failed with status 0x%lx\n", Status);
+ }
+ return Status;
+ }
- /* Set 'UINumber' value */
- if (DeviceCaps->UINumber != MAXULONG)
- {
- RtlInitUnicodeString(&ValueName, L"UINumber");
- Status = ZwSetValueKey(InstanceKey,
- &ValueName,
- 0,
- REG_DWORD,
- &DeviceCaps->UINumber,
- sizeof(ULONG));
- }
- }
+ DeviceNode->CapabilityFlags = *(PULONG)((ULONG_PTR)&DeviceCaps->Version + sizeof(DeviceCaps->Version));
- return Status;
+ if (DeviceCaps->NoDisplayInUI)
+ DeviceNode->UserFlags |= DNUF_DONT_SHOW_IN_UI;
+ else
+ DeviceNode->UserFlags &= ~DNUF_DONT_SHOW_IN_UI;
+
+ Status = IopCreateDeviceKeyPath(&DeviceNode->InstancePath, REG_OPTION_NON_VOLATILE, &InstanceKey);
+ if (NT_SUCCESS(Status))
+ {
+ /* Set 'Capabilities' value */
+ RtlInitUnicodeString(&ValueName, L"Capabilities");
+ Status = ZwSetValueKey(InstanceKey,
+ &ValueName,
+ 0,
+ REG_DWORD,
+ &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));
+ }
+
+ ZwClose(InstanceKey);
+ }
+
+ return Status;
}
-static VOID NTAPI
-IopAsynchronousInvalidateDeviceRelations(
- IN PDEVICE_OBJECT DeviceObject,
- IN PVOID InvalidateContext)
+static
+VOID
+NTAPI
+IopDeviceActionWorker(
+ _In_ PVOID Context)
{
- PINVALIDATE_DEVICE_RELATION_DATA Data = InvalidateContext;
-
- IoSynchronousInvalidateDeviceRelations(
- Data->DeviceObject,
- Data->Type);
+ PLIST_ENTRY ListEntry;
+ PDEVICE_ACTION_DATA Data;
+ KIRQL OldIrql;
- ObDereferenceObject(Data->DeviceObject);
- IoFreeWorkItem(Data->WorkItem);
- ExFreePool(Data);
+ KeAcquireSpinLock(&IopDeviceActionLock, &OldIrql);
+ while (!IsListEmpty(&IopDeviceActionRequestList))
+ {
+ ListEntry = RemoveHeadList(&IopDeviceActionRequestList);
+ KeReleaseSpinLock(&IopDeviceActionLock, OldIrql);
+ Data = CONTAINING_RECORD(ListEntry,
+ DEVICE_ACTION_DATA,
+ RequestListEntry);
+
+ IoSynchronousInvalidateDeviceRelations(Data->DeviceObject,
+ Data->Type);
+
+ ObDereferenceObject(Data->DeviceObject);
+ ExFreePoolWithTag(Data, TAG_IO);
+ KeAcquireSpinLock(&IopDeviceActionLock, &OldIrql);
+ }
+ IopDeviceActionInProgress = FALSE;
+ KeReleaseSpinLock(&IopDeviceActionLock, OldIrql);
}
NTSTATUS
IopGetSystemPowerDeviceObject(PDEVICE_OBJECT *DeviceObject)
{
- KIRQL OldIrql;
+ KIRQL OldIrql;
- if (PopSystemPowerDeviceNode)
- {
- KeAcquireSpinLock(&IopDeviceTreeLock, &OldIrql);
- *DeviceObject = PopSystemPowerDeviceNode->PhysicalDeviceObject;
- KeReleaseSpinLock(&IopDeviceTreeLock, OldIrql);
+ if (PopSystemPowerDeviceNode)
+ {
+ KeAcquireSpinLock(&IopDeviceTreeLock, &OldIrql);
+ *DeviceObject = PopSystemPowerDeviceNode->PhysicalDeviceObject;
+ KeReleaseSpinLock(&IopDeviceTreeLock, OldIrql);
- return STATUS_SUCCESS;
- }
+ return STATUS_SUCCESS;
+ }
- return STATUS_UNSUCCESSFUL;
+ return STATUS_UNSUCCESSFUL;
}
USHORT
NTAPI
IopGetBusTypeGuidIndex(LPGUID BusTypeGuid)
{
- USHORT i = 0, FoundIndex = 0xFFFF;
- ULONG NewSize;
- PVOID NewList;
+ USHORT i = 0, FoundIndex = 0xFFFF;
+ ULONG NewSize;
+ PVOID NewList;
- /* Acquire the lock */
- ExAcquireFastMutex(&PnpBusTypeGuidList->Lock);
+ /* Acquire the lock */
+ ExAcquireFastMutex(&PnpBusTypeGuidList->Lock);
- /* Loop all entries */
- while (i < PnpBusTypeGuidList->GuidCount)
- {
- /* Try to find a match */
- if (RtlCompareMemory(BusTypeGuid,
- &PnpBusTypeGuidList->Guids[i],
- sizeof(GUID)) == sizeof(GUID))
- {
- /* Found it */
- FoundIndex = i;
- goto Quickie;
- }
- i++;
- }
+ /* Loop all entries */
+ while (i < PnpBusTypeGuidList->GuidCount)
+ {
+ /* Try to find a match */
+ if (RtlCompareMemory(BusTypeGuid,
+ &PnpBusTypeGuidList->Guids[i],
+ sizeof(GUID)) == sizeof(GUID))
+ {
+ /* Found it */
+ FoundIndex = i;
+ goto Quickie;
+ }
+ i++;
+ }
- /* Check if we have to grow the list */
- if (PnpBusTypeGuidList->GuidCount)
- {
- /* Calculate the new size */
- NewSize = sizeof(IO_BUS_TYPE_GUID_LIST) +
- (sizeof(GUID) * PnpBusTypeGuidList->GuidCount);
+ /* Check if we have to grow the list */
+ if (PnpBusTypeGuidList->GuidCount)
+ {
+ /* Calculate the new size */
+ NewSize = sizeof(IO_BUS_TYPE_GUID_LIST) +
+ (sizeof(GUID) * PnpBusTypeGuidList->GuidCount);
- /* Allocate the new copy */
- NewList = ExAllocatePool(PagedPool, NewSize);
+ /* Allocate the new copy */
+ NewList = ExAllocatePool(PagedPool, NewSize);
- if (!NewList) {
- /* Fail */
- ExFreePool(PnpBusTypeGuidList);
- goto Quickie;
- }
+ if (!NewList)
+ {
+ /* Fail */
+ ExFreePool(PnpBusTypeGuidList);
+ goto Quickie;
+ }
- /* Now copy them, decrease the size too */
- NewSize -= sizeof(GUID);
- RtlCopyMemory(NewList, PnpBusTypeGuidList, NewSize);
+ /* Now copy them, decrease the size too */
+ NewSize -= sizeof(GUID);
+ RtlCopyMemory(NewList, PnpBusTypeGuidList, NewSize);
- /* Free the old list */
- ExFreePool(PnpBusTypeGuidList);
+ /* Free the old list */
+ ExFreePool(PnpBusTypeGuidList);
- /* Use the new buffer */
- PnpBusTypeGuidList = NewList;
- }
+ /* Use the new buffer */
+ PnpBusTypeGuidList = NewList;
+ }
- /* Copy the new GUID */
- RtlCopyMemory(&PnpBusTypeGuidList->Guids[PnpBusTypeGuidList->GuidCount],
- BusTypeGuid,
- sizeof(GUID));
+ /* Copy the new GUID */
+ RtlCopyMemory(&PnpBusTypeGuidList->Guids[PnpBusTypeGuidList->GuidCount],
+ BusTypeGuid,
+ sizeof(GUID));
- /* The new entry is the index */
- FoundIndex = (USHORT)PnpBusTypeGuidList->GuidCount;
- PnpBusTypeGuidList->GuidCount++;
+ /* The new entry is the index */
+ FoundIndex = (USHORT)PnpBusTypeGuidList->GuidCount;
+ PnpBusTypeGuidList->GuidCount++;
Quickie:
- ExReleaseFastMutex(&PnpBusTypeGuidList->Lock);
- return FoundIndex;
+ ExReleaseFastMutex(&PnpBusTypeGuidList->Lock);
+ return FoundIndex;
}
/*
PUNICODE_STRING ServiceName,
PDEVICE_NODE *DeviceNode)
{
- PDEVICE_NODE Node;
- NTSTATUS Status;
- KIRQL OldIrql;
- UNICODE_STRING FullServiceName;
- UNICODE_STRING LegacyPrefix = RTL_CONSTANT_STRING(L"LEGACY_");
- UNICODE_STRING UnknownDeviceName = RTL_CONSTANT_STRING(L"UNKNOWN");
- UNICODE_STRING KeyName, ClassName;
- PUNICODE_STRING ServiceName1;
- ULONG LegacyValue;
- UNICODE_STRING ClassGUID;
- HANDLE InstanceHandle;
+ PDEVICE_NODE Node;
+ NTSTATUS Status;
+ KIRQL OldIrql;
+ UNICODE_STRING FullServiceName;
+ UNICODE_STRING LegacyPrefix = RTL_CONSTANT_STRING(L"LEGACY_");
+ UNICODE_STRING UnknownDeviceName = RTL_CONSTANT_STRING(L"UNKNOWN");
+ UNICODE_STRING KeyName, ClassName;
+ PUNICODE_STRING ServiceName1;
+ ULONG LegacyValue;
+ UNICODE_STRING ClassGUID;
+ HANDLE InstanceHandle;
+
+ DPRINT("ParentNode 0x%p PhysicalDeviceObject 0x%p ServiceName %wZ\n",
+ ParentNode, PhysicalDeviceObject, ServiceName);
+
+ Node = ExAllocatePoolWithTag(NonPagedPool, sizeof(DEVICE_NODE), TAG_IO_DEVNODE);
+ if (!Node)
+ {
+ return STATUS_INSUFFICIENT_RESOURCES;
+ }
- DPRINT("ParentNode 0x%p PhysicalDeviceObject 0x%p ServiceName %wZ\n",
- ParentNode, PhysicalDeviceObject, ServiceName);
+ RtlZeroMemory(Node, sizeof(DEVICE_NODE));
- Node = (PDEVICE_NODE)ExAllocatePool(NonPagedPool, sizeof(DEVICE_NODE));
- if (!Node)
- {
- return STATUS_INSUFFICIENT_RESOURCES;
- }
+ if (!ServiceName)
+ ServiceName1 = &UnknownDeviceName;
+ else
+ ServiceName1 = ServiceName;
- RtlZeroMemory(Node, sizeof(DEVICE_NODE));
+ if (!PhysicalDeviceObject)
+ {
+ FullServiceName.MaximumLength = LegacyPrefix.Length + ServiceName1->Length + sizeof(UNICODE_NULL);
+ FullServiceName.Length = 0;
+ FullServiceName.Buffer = ExAllocatePool(PagedPool, FullServiceName.MaximumLength);
+ if (!FullServiceName.Buffer)
+ {
+ ExFreePoolWithTag(Node, TAG_IO_DEVNODE);
+ return STATUS_INSUFFICIENT_RESOURCES;
+ }
- if (!ServiceName)
- ServiceName1 = &UnknownDeviceName;
- else
- ServiceName1 = ServiceName;
+ RtlAppendUnicodeStringToString(&FullServiceName, &LegacyPrefix);
+ RtlAppendUnicodeStringToString(&FullServiceName, ServiceName1);
+ RtlUpcaseUnicodeString(&FullServiceName, &FullServiceName, FALSE);
- if (!PhysicalDeviceObject)
- {
- FullServiceName.MaximumLength = LegacyPrefix.Length + ServiceName1->Length;
- FullServiceName.Length = 0;
- FullServiceName.Buffer = ExAllocatePool(PagedPool, FullServiceName.MaximumLength);
- if (!FullServiceName.Buffer)
- {
- ExFreePool(Node);
- return STATUS_INSUFFICIENT_RESOURCES;
- }
+ Status = PnpRootCreateDevice(&FullServiceName, NULL, &PhysicalDeviceObject, &Node->InstancePath);
+ if (!NT_SUCCESS(Status))
+ {
+ DPRINT1("PnpRootCreateDevice() failed with status 0x%08X\n", Status);
+ ExFreePool(FullServiceName.Buffer);
+ ExFreePoolWithTag(Node, TAG_IO_DEVNODE);
+ return Status;
+ }
- RtlAppendUnicodeStringToString(&FullServiceName, &LegacyPrefix);
- RtlAppendUnicodeStringToString(&FullServiceName, ServiceName1);
+ /* Create the device key for legacy drivers */
+ Status = IopCreateDeviceKeyPath(&Node->InstancePath, REG_OPTION_VOLATILE, &InstanceHandle);
+ if (!NT_SUCCESS(Status))
+ {
+ ExFreePool(FullServiceName.Buffer);
+ ExFreePoolWithTag(Node, TAG_IO_DEVNODE);
+ return Status;
+ }
- Status = PnpRootCreateDevice(&FullServiceName, NULL, &PhysicalDeviceObject, &Node->InstancePath);
- if (!NT_SUCCESS(Status))
- {
- DPRINT1("PnpRootCreateDevice() failed with status 0x%08X\n", Status);
- ExFreePool(Node);
- return Status;
- }
-
- /* Create the device key for legacy drivers */
- Status = IopCreateDeviceKeyPath(&Node->InstancePath, REG_OPTION_VOLATILE, &InstanceHandle);
- if (!NT_SUCCESS(Status))
- {
- ZwClose(InstanceHandle);
- ExFreePool(Node);
- ExFreePool(FullServiceName.Buffer);
- return Status;
- }
-
- Node->ServiceName.Buffer = ExAllocatePool(PagedPool, ServiceName1->Length);
- if (!Node->ServiceName.Buffer)
- {
- ZwClose(InstanceHandle);
- ExFreePool(Node);
- ExFreePool(FullServiceName.Buffer);
- return Status;
- }
+ Node->ServiceName.MaximumLength = ServiceName1->Length + sizeof(UNICODE_NULL);
+ Node->ServiceName.Length = 0;
+ Node->ServiceName.Buffer = ExAllocatePool(PagedPool, Node->ServiceName.MaximumLength);
+ if (!Node->ServiceName.Buffer)
+ {
+ ZwClose(InstanceHandle);
+ ExFreePool(FullServiceName.Buffer);
+ ExFreePoolWithTag(Node, TAG_IO_DEVNODE);
+ return Status;
+ }
- Node->ServiceName.MaximumLength = ServiceName1->Length;
- Node->ServiceName.Length = 0;
+ RtlCopyUnicodeString(&Node->ServiceName, ServiceName1);
- RtlAppendUnicodeStringToString(&Node->ServiceName, ServiceName1);
+ if (ServiceName)
+ {
+ RtlInitUnicodeString(&KeyName, L"Service");
+ Status = ZwSetValueKey(InstanceHandle, &KeyName, 0, REG_SZ, ServiceName->Buffer, ServiceName->Length + sizeof(UNICODE_NULL));
+ }
- if (ServiceName)
- {
- RtlInitUnicodeString(&KeyName, L"Service");
- Status = ZwSetValueKey(InstanceHandle, &KeyName, 0, REG_SZ, ServiceName->Buffer, ServiceName->Length);
- }
+ if (NT_SUCCESS(Status))
+ {
+ RtlInitUnicodeString(&KeyName, L"Legacy");
+ LegacyValue = 1;
+ Status = ZwSetValueKey(InstanceHandle, &KeyName, 0, REG_DWORD, &LegacyValue, sizeof(LegacyValue));
- if (NT_SUCCESS(Status))
- {
- RtlInitUnicodeString(&KeyName, L"Legacy");
+ RtlInitUnicodeString(&KeyName, L"ConfigFlags");
+ LegacyValue = 0;
+ ZwSetValueKey(InstanceHandle, &KeyName, 0, REG_DWORD, &LegacyValue, sizeof(LegacyValue));
- LegacyValue = 1;
- Status = ZwSetValueKey(InstanceHandle, &KeyName, 0, REG_DWORD, &LegacyValue, sizeof(LegacyValue));
- if (NT_SUCCESS(Status))
- {
- RtlInitUnicodeString(&KeyName, L"Class");
-
- 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}\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));
- }
- }
- }
- }
+ if (NT_SUCCESS(Status))
+ {
+ RtlInitUnicodeString(&KeyName, L"Class");
+ RtlInitUnicodeString(&ClassName, L"LegacyDriver");
+ 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 + sizeof(UNICODE_NULL));
+ if (NT_SUCCESS(Status))
+ {
+ // FIXME: Retrieve the real "description" by looking at the "DisplayName" string
+ // of the corresponding CurrentControlSet\Services\xxx entry for this driver.
+ RtlInitUnicodeString(&KeyName, L"DeviceDesc");
+ Status = ZwSetValueKey(InstanceHandle, &KeyName, 0, REG_SZ, ServiceName1->Buffer, ServiceName1->Length + sizeof(UNICODE_NULL));
+ }
+ }
+ }
+ }
- ZwClose(InstanceHandle);
- ExFreePool(FullServiceName.Buffer);
+ ZwClose(InstanceHandle);
+ ExFreePool(FullServiceName.Buffer);
- if (!NT_SUCCESS(Status))
- {
- ExFreePool(Node);
- return Status;
- }
+ if (!NT_SUCCESS(Status))
+ {
+ ExFreePool(Node->ServiceName.Buffer);
+ ExFreePoolWithTag(Node, TAG_IO_DEVNODE);
+ return Status;
+ }
- IopDeviceNodeSetFlag(Node, DNF_LEGACY_DRIVER);
- IopDeviceNodeSetFlag(Node, DNF_PROCESSED);
- IopDeviceNodeSetFlag(Node, DNF_ADDED);
- IopDeviceNodeSetFlag(Node, DNF_STARTED);
- }
+ IopDeviceNodeSetFlag(Node, DNF_LEGACY_DRIVER);
+ IopDeviceNodeSetFlag(Node, DNF_PROCESSED);
+ IopDeviceNodeSetFlag(Node, DNF_ADDED);
+ IopDeviceNodeSetFlag(Node, DNF_STARTED);
+ }
- Node->PhysicalDeviceObject = PhysicalDeviceObject;
+ Node->PhysicalDeviceObject = PhysicalDeviceObject;
- ((PEXTENDED_DEVOBJ_EXTENSION)PhysicalDeviceObject->DeviceObjectExtension)->DeviceNode = Node;
+ ((PEXTENDED_DEVOBJ_EXTENSION)PhysicalDeviceObject->DeviceObjectExtension)->DeviceNode = Node;
if (ParentNode)
{
PhysicalDeviceObject->Flags &= ~DO_DEVICE_INITIALIZING;
- *DeviceNode = Node;
+ *DeviceNode = Node;
- return STATUS_SUCCESS;
+ return STATUS_SUCCESS;
}
NTSTATUS
IopFreeDeviceNode(PDEVICE_NODE DeviceNode)
{
- KIRQL OldIrql;
- PDEVICE_NODE PrevSibling = NULL;
+ KIRQL OldIrql;
+ PDEVICE_NODE PrevSibling = NULL;
- /* All children must be deleted before a parent is deleted */
- ASSERT(!DeviceNode->Child);
- ASSERT(DeviceNode->PhysicalDeviceObject);
+ /* All children must be deleted before a parent is deleted */
+ ASSERT(!DeviceNode->Child);
+ ASSERT(DeviceNode->PhysicalDeviceObject);
- KeAcquireSpinLock(&IopDeviceTreeLock, &OldIrql);
+ KeAcquireSpinLock(&IopDeviceTreeLock, &OldIrql);
/* Get previous sibling */
if (DeviceNode->Parent && DeviceNode->Parent->Child != DeviceNode)
if (PrevSibling)
PrevSibling->Sibling = DeviceNode->Sibling;
- KeReleaseSpinLock(&IopDeviceTreeLock, OldIrql);
+ KeReleaseSpinLock(&IopDeviceTreeLock, OldIrql);
- RtlFreeUnicodeString(&DeviceNode->InstancePath);
+ RtlFreeUnicodeString(&DeviceNode->InstancePath);
- RtlFreeUnicodeString(&DeviceNode->ServiceName);
+ RtlFreeUnicodeString(&DeviceNode->ServiceName);
- if (DeviceNode->ResourceList)
- {
- ExFreePool(DeviceNode->ResourceList);
- }
+ if (DeviceNode->ResourceList)
+ {
+ ExFreePool(DeviceNode->ResourceList);
+ }
- if (DeviceNode->ResourceListTranslated)
- {
- ExFreePool(DeviceNode->ResourceListTranslated);
- }
+ if (DeviceNode->ResourceListTranslated)
+ {
+ ExFreePool(DeviceNode->ResourceListTranslated);
+ }
- if (DeviceNode->ResourceRequirements)
- {
- ExFreePool(DeviceNode->ResourceRequirements);
- }
+ if (DeviceNode->ResourceRequirements)
+ {
+ ExFreePool(DeviceNode->ResourceRequirements);
+ }
- if (DeviceNode->BootResources)
- {
- ExFreePool(DeviceNode->BootResources);
- }
+ if (DeviceNode->BootResources)
+ {
+ ExFreePool(DeviceNode->BootResources);
+ }
- ExFreePool(DeviceNode);
+ ((PEXTENDED_DEVOBJ_EXTENSION)DeviceNode->PhysicalDeviceObject->DeviceObjectExtension)->DeviceNode = NULL;
+ ExFreePoolWithTag(DeviceNode, TAG_IO_DEVNODE);
- return STATUS_SUCCESS;
+ return STATUS_SUCCESS;
}
NTSTATUS
NTSTATUS Status;
PDEVICE_OBJECT TopDeviceObject;
PAGED_CODE();
-
+
/* Call the top of the device stack */
TopDeviceObject = IoGetAttachedDeviceReference(DeviceObject);
-
+
/* Allocate an IRP */
Irp = IoAllocateIrp(TopDeviceObject->StackSize, FALSE);
if (!Irp) return STATUS_INSUFFICIENT_RESOURCES;
-
+
/* Initialize to failure */
Irp->IoStatus.Status = IoStatusBlock.Status = STATUS_NOT_SUPPORTED;
Irp->IoStatus.Information = IoStatusBlock.Information = 0;
-
+
/* Special case for IRP_MN_FILTER_RESOURCE_REQUIREMENTS */
if (IoStackLocation->MinorFunction == IRP_MN_FILTER_RESOURCE_REQUIREMENTS)
{
Irp->IoStatus.Information =
IoStatusBlock.Information = (ULONG_PTR)IoStackLocation->Parameters.FilterResourceRequirements.IoResourceRequirementList;
}
-
+
/* Initialize the event */
KeInitializeEvent(&Event, SynchronizationEvent, FALSE);
-
+
/* Set them up */
Irp->UserIosb = &IoStatusBlock;
Irp->UserEvent = &Event;
-
+
/* Queue the IRP */
Irp->Tail.Overlay.Thread = PsGetCurrentThread();
IoQueueThreadIrp(Irp);
-
+
/* Copy-in the stack */
IrpStack = IoGetNextIrpStackLocation(Irp);
*IrpStack = *IoStackLocation;
-
+
/* Call the driver */
Status = IoCallDriver(TopDeviceObject, Irp);
if (Status == STATUS_PENDING)
IN PIO_STACK_LOCATION Stack OPTIONAL)
{
IO_STACK_LOCATION IoStackLocation;
-
+
/* Fill out the stack information */
RtlZeroMemory(&IoStackLocation, sizeof(IO_STACK_LOCATION));
IoStackLocation.MajorFunction = IRP_MJ_PNP;
&Stack->Parameters,
sizeof(Stack->Parameters));
}
-
+
/* Do the PnP call */
IoStatusBlock->Status = IopSynchronousCall(DeviceObject,
&IoStackLocation,
NTSTATUS
IopTraverseDeviceTreeNode(PDEVICETREE_TRAVERSE_CONTEXT Context)
{
- PDEVICE_NODE ParentDeviceNode;
- PDEVICE_NODE ChildDeviceNode;
- NTSTATUS Status;
+ PDEVICE_NODE ParentDeviceNode;
+ PDEVICE_NODE ChildDeviceNode;
+ NTSTATUS Status;
- /* Copy context data so we don't overwrite it in subsequent calls to this function */
- ParentDeviceNode = Context->DeviceNode;
+ /* Copy context data so we don't overwrite it in subsequent calls to this function */
+ ParentDeviceNode = Context->DeviceNode;
- /* Call the action routine */
- Status = (Context->Action)(ParentDeviceNode, Context->Context);
- if (!NT_SUCCESS(Status))
- {
- return Status;
- }
+ /* Call the action routine */
+ Status = (Context->Action)(ParentDeviceNode, Context->Context);
+ if (!NT_SUCCESS(Status))
+ {
+ return Status;
+ }
- /* Traversal of all children nodes */
- for (ChildDeviceNode = ParentDeviceNode->Child;
- ChildDeviceNode != NULL;
- ChildDeviceNode = ChildDeviceNode->Sibling)
- {
- /* Pass the current device node to the action routine */
- Context->DeviceNode = ChildDeviceNode;
+ /* Traversal of all children nodes */
+ for (ChildDeviceNode = ParentDeviceNode->Child;
+ ChildDeviceNode != NULL;
+ ChildDeviceNode = ChildDeviceNode->Sibling)
+ {
+ /* Pass the current device node to the action routine */
+ Context->DeviceNode = ChildDeviceNode;
- Status = IopTraverseDeviceTreeNode(Context);
- if (!NT_SUCCESS(Status))
- {
- return Status;
- }
- }
+ Status = IopTraverseDeviceTreeNode(Context);
+ if (!NT_SUCCESS(Status))
+ {
+ return Status;
+ }
+ }
- return Status;
+ return Status;
}
NTSTATUS
IopTraverseDeviceTree(PDEVICETREE_TRAVERSE_CONTEXT Context)
{
- NTSTATUS Status;
+ NTSTATUS Status;
- DPRINT("Context 0x%p\n", Context);
+ DPRINT("Context 0x%p\n", Context);
- DPRINT("IopTraverseDeviceTree(DeviceNode 0x%p FirstDeviceNode 0x%p Action %p Context 0x%p)\n",
- Context->DeviceNode, Context->FirstDeviceNode, Context->Action, Context->Context);
+ 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 */
- Context->DeviceNode = Context->FirstDeviceNode;
+ /* Start from the specified device node */
+ Context->DeviceNode = Context->FirstDeviceNode;
- /* Recursively traverse the device tree */
- Status = IopTraverseDeviceTreeNode(Context);
- if (Status == STATUS_UNSUCCESSFUL)
- {
- /* The action routine just wanted to terminate the traversal with status
- code STATUS_SUCCESS */
- Status = STATUS_SUCCESS;
- }
+ /* Recursively traverse the device tree */
+ Status = IopTraverseDeviceTreeNode(Context);
+ if (Status == STATUS_UNSUCCESSFUL)
+ {
+ /* The action routine just wanted to terminate the traversal with status
+ code STATUS_SUCCESS */
+ Status = STATUS_SUCCESS;
+ }
- return Status;
+ return Status;
}
HANDLE hParent = NULL, hKey;
OBJECT_ATTRIBUTES ObjectAttributes;
UNICODE_STRING KeyName;
- LPCWSTR Current, Last;
+ PCWSTR Current, Last;
USHORT Length;
NTSTATUS Status;
/* Assume failure */
*Handle = NULL;
- /* Create a volatile device tree in 1st stage so we have a clean slate
- * for enumeration using the correct HAL (chosen in 1st stage setup) */
- if (ExpInTextModeSetup) CreateOptions |= REG_OPTION_VOLATILE;
-
/* Open root key for device instances */
Status = IopOpenRegistryKeyEx(&hParent, NULL, &EnumU, KEY_CREATE_SUB_KEY);
if (!NT_SUCCESS(Status))
/* Go up to the end of the string */
while (Current <= Last)
{
- if (Current != Last && *Current != '\\')
+ if (Current != Last && *Current != L'\\')
{
/* Not the end of the string and not a separator */
Current++;
/* Open key */
InitializeObjectAttributes(&ObjectAttributes,
&KeyName,
- OBJ_CASE_INSENSITIVE,
+ OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE,
hParent,
NULL);
Status = ZwCreateKey(&hKey,
/* Start with this new parent key */
hParent = hKey;
Current++;
- KeyName.Buffer = (LPWSTR)Current;
+ KeyName.Buffer = (PWSTR)Current;
}
return STATUS_UNSUCCESSFUL;
IopSetDeviceInstanceData(HANDLE InstanceKey,
PDEVICE_NODE DeviceNode)
{
- OBJECT_ATTRIBUTES ObjectAttributes;
- UNICODE_STRING KeyName;
- HANDLE LogConfKey;
- ULONG ResCount;
- ULONG ResultLength;
- NTSTATUS Status;
- HANDLE ControlHandle;
+ OBJECT_ATTRIBUTES ObjectAttributes;
+ UNICODE_STRING KeyName;
+ HANDLE LogConfKey, ControlKey, DeviceParamsKey;
+ ULONG ResCount;
+ ULONG ResultLength;
+ NTSTATUS Status;
- DPRINT("IopSetDeviceInstanceData() called\n");
+ DPRINT("IopSetDeviceInstanceData() called\n");
- /* Create the 'LogConf' key */
- RtlInitUnicodeString(&KeyName, L"LogConf");
- InitializeObjectAttributes(&ObjectAttributes,
- &KeyName,
- OBJ_CASE_INSENSITIVE,
- InstanceKey,
- NULL);
- Status = ZwCreateKey(&LogConfKey,
- KEY_ALL_ACCESS,
- &ObjectAttributes,
- 0,
- NULL,
- REG_OPTION_VOLATILE,
- NULL);
- if (NT_SUCCESS(Status))
- {
- /* Set 'BootConfig' value */
- if (DeviceNode->BootResources != NULL)
- {
- ResCount = DeviceNode->BootResources->Count;
- if (ResCount != 0)
- {
- RtlInitUnicodeString(&KeyName, L"BootConfig");
+ /* Create the 'LogConf' key */
+ RtlInitUnicodeString(&KeyName, L"LogConf");
+ InitializeObjectAttributes(&ObjectAttributes,
+ &KeyName,
+ OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE,
+ InstanceKey,
+ NULL);
+ Status = ZwCreateKey(&LogConfKey,
+ KEY_ALL_ACCESS,
+ &ObjectAttributes,
+ 0,
+ NULL,
+ // FIXME? In r53694 it was silently turned from non-volatile into this,
+ // without any extra warning. Is this still needed??
+ REG_OPTION_VOLATILE,
+ NULL);
+ if (NT_SUCCESS(Status))
+ {
+ /* Set 'BootConfig' value */
+ if (DeviceNode->BootResources != NULL)
+ {
+ ResCount = DeviceNode->BootResources->Count;
+ if (ResCount != 0)
+ {
+ RtlInitUnicodeString(&KeyName, L"BootConfig");
+ Status = ZwSetValueKey(LogConfKey,
+ &KeyName,
+ 0,
+ REG_RESOURCE_LIST,
+ DeviceNode->BootResources,
+ PnpDetermineResourceListSize(DeviceNode->BootResources));
+ }
+ }
+
+ /* Set 'BasicConfigVector' value */
+ if (DeviceNode->ResourceRequirements != NULL &&
+ DeviceNode->ResourceRequirements->ListSize != 0)
+ {
+ RtlInitUnicodeString(&KeyName, L"BasicConfigVector");
Status = ZwSetValueKey(LogConfKey,
&KeyName,
0,
- REG_RESOURCE_LIST,
- DeviceNode->BootResources,
- PnpDetermineResourceListSize(DeviceNode->BootResources));
- }
- }
+ REG_RESOURCE_REQUIREMENTS_LIST,
+ DeviceNode->ResourceRequirements,
+ DeviceNode->ResourceRequirements->ListSize);
+ }
- /* Set 'BasicConfigVector' value */
- if (DeviceNode->ResourceRequirements != NULL &&
- DeviceNode->ResourceRequirements->ListSize != 0)
- {
- RtlInitUnicodeString(&KeyName, L"BasicConfigVector");
- Status = ZwSetValueKey(LogConfKey,
- &KeyName,
- 0,
- REG_RESOURCE_REQUIREMENTS_LIST,
- DeviceNode->ResourceRequirements,
- DeviceNode->ResourceRequirements->ListSize);
- }
+ ZwClose(LogConfKey);
+ }
- ZwClose(LogConfKey);
- }
+ /* Set the 'ConfigFlags' value */
+ RtlInitUnicodeString(&KeyName, L"ConfigFlags");
+ Status = ZwQueryValueKey(InstanceKey,
+ &KeyName,
+ KeyValueBasicInformation,
+ NULL,
+ 0,
+ &ResultLength);
+ if (Status == STATUS_OBJECT_NAME_NOT_FOUND)
+ {
+ /* Write the default value */
+ ULONG DefaultConfigFlags = 0;
+ Status = ZwSetValueKey(InstanceKey,
+ &KeyName,
+ 0,
+ REG_DWORD,
+ &DefaultConfigFlags,
+ sizeof(DefaultConfigFlags));
+ }
- /* Set the 'ConfigFlags' value */
- RtlInitUnicodeString(&KeyName, L"ConfigFlags");
- Status = ZwQueryValueKey(InstanceKey,
- &KeyName,
- KeyValueBasicInformation,
- NULL,
- 0,
- &ResultLength);
- if (Status == STATUS_OBJECT_NAME_NOT_FOUND)
- {
- /* Write the default value */
- ULONG DefaultConfigFlags = 0;
- Status = ZwSetValueKey(InstanceKey,
- &KeyName,
- 0,
- REG_DWORD,
- &DefaultConfigFlags,
- sizeof(DefaultConfigFlags));
- }
+ /* Create the 'Control' key */
+ RtlInitUnicodeString(&KeyName, L"Control");
+ InitializeObjectAttributes(&ObjectAttributes,
+ &KeyName,
+ OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE,
+ InstanceKey,
+ NULL);
+ Status = ZwCreateKey(&ControlKey,
+ 0,
+ &ObjectAttributes,
+ 0,
+ NULL,
+ REG_OPTION_VOLATILE,
+ NULL);
+ if (NT_SUCCESS(Status))
+ ZwClose(ControlKey);
- /* Create the 'Control' key */
- RtlInitUnicodeString(&KeyName, L"Control");
- InitializeObjectAttributes(&ObjectAttributes,
- &KeyName,
- OBJ_CASE_INSENSITIVE,
- InstanceKey,
- NULL);
- Status = ZwCreateKey(&ControlHandle, 0, &ObjectAttributes, 0, NULL, REG_OPTION_VOLATILE, NULL);
+ /* Create the 'Device Parameters' key and set the 'FirmwareIdentified' value for all ACPI-enumerated devices */
+ if (_wcsnicmp(DeviceNode->InstancePath.Buffer, L"ACPI\\", 5) == 0)
+ {
+ RtlInitUnicodeString(&KeyName, L"Device Parameters");
+ InitializeObjectAttributes(&ObjectAttributes,
+ &KeyName,
+ OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE,
+ InstanceKey,
+ NULL);
+ Status = ZwCreateKey(&DeviceParamsKey,
+ 0,
+ &ObjectAttributes,
+ 0,
+ NULL,
+ REG_OPTION_NON_VOLATILE,
+ NULL);
+ if (NT_SUCCESS(Status))
+ {
+ ULONG FirmwareIdentified = 1;
+ RtlInitUnicodeString(&KeyName, L"FirmwareIdentified");
+ Status = ZwSetValueKey(DeviceParamsKey,
+ &KeyName,
+ 0,
+ REG_DWORD,
+ &FirmwareIdentified,
+ sizeof(FirmwareIdentified));
- if (NT_SUCCESS(Status))
- ZwClose(ControlHandle);
+ ZwClose(DeviceParamsKey);
+ }
+ }
- DPRINT("IopSetDeviceInstanceData() done\n");
+ DPRINT("IopSetDeviceInstanceData() done\n");
- return Status;
+ return Status;
}
/*
IopGetParentIdPrefix(PDEVICE_NODE DeviceNode,
PUNICODE_STRING ParentIdPrefix)
{
- ULONG KeyNameBufferLength;
- PKEY_VALUE_PARTIAL_INFORMATION ParentIdPrefixInformation = NULL;
- UNICODE_STRING KeyName = {0, 0, NULL};
- UNICODE_STRING KeyValue;
- UNICODE_STRING ValueName;
- HANDLE hKey = NULL;
- ULONG crc32;
- NTSTATUS Status;
-
- /* HACK: As long as some devices have a NULL device
- * instance path, the following test is required :(
- */
- if (DeviceNode->Parent->InstancePath.Length == 0)
- {
- DPRINT1("Parent of %wZ has NULL Instance path, please report!\n",
- &DeviceNode->InstancePath);
- return STATUS_UNSUCCESSFUL;
- }
-
- /* 1. Try to retrieve ParentIdPrefix from registry */
- KeyNameBufferLength = FIELD_OFFSET(KEY_VALUE_PARTIAL_INFORMATION, Data[0]) + MAX_PATH * sizeof(WCHAR);
- ParentIdPrefixInformation = ExAllocatePool(PagedPool, KeyNameBufferLength + sizeof(WCHAR));
- if (!ParentIdPrefixInformation)
- {
- return STATUS_INSUFFICIENT_RESOURCES;
- }
+ const UNICODE_STRING EnumKeyPath = RTL_CONSTANT_STRING(L"\\Registry\\Machine\\System\\CurrentControlSet\\Enum\\");
+ ULONG KeyNameBufferLength;
+ PKEY_VALUE_PARTIAL_INFORMATION ParentIdPrefixInformation = NULL;
+ UNICODE_STRING KeyName = {0, 0, NULL};
+ UNICODE_STRING KeyValue;
+ UNICODE_STRING ValueName;
+ HANDLE hKey = NULL;
+ ULONG crc32;
+ NTSTATUS Status;
- KeyName.Buffer = ExAllocatePool(PagedPool, (49 * sizeof(WCHAR)) + DeviceNode->Parent->InstancePath.Length);
- if (!KeyName.Buffer)
- {
- Status = STATUS_INSUFFICIENT_RESOURCES;
- goto cleanup;
- }
- KeyName.Length = 0;
- KeyName.MaximumLength = (49 * sizeof(WCHAR)) + DeviceNode->Parent->InstancePath.Length;
+ /* HACK: As long as some devices have a NULL device
+ * instance path, the following test is required :(
+ */
+ if (DeviceNode->Parent->InstancePath.Length == 0)
+ {
+ DPRINT1("Parent of %wZ has NULL Instance path, please report!\n",
+ &DeviceNode->InstancePath);
+ return STATUS_UNSUCCESSFUL;
+ }
- RtlAppendUnicodeToString(&KeyName, L"\\Registry\\Machine\\System\\CurrentControlSet\\Enum\\");
- RtlAppendUnicodeStringToString(&KeyName, &DeviceNode->Parent->InstancePath);
+ /* 1. Try to retrieve ParentIdPrefix from registry */
+ KeyNameBufferLength = FIELD_OFFSET(KEY_VALUE_PARTIAL_INFORMATION, Data[0]) + MAX_PATH * sizeof(WCHAR);
+ ParentIdPrefixInformation = ExAllocatePoolWithTag(PagedPool,
+ KeyNameBufferLength + sizeof(UNICODE_NULL),
+ TAG_IO);
+ if (!ParentIdPrefixInformation)
+ {
+ return STATUS_INSUFFICIENT_RESOURCES;
+ }
- Status = IopOpenRegistryKeyEx(&hKey, NULL, &KeyName, KEY_QUERY_VALUE | KEY_SET_VALUE);
- if (!NT_SUCCESS(Status))
- goto cleanup;
- RtlInitUnicodeString(&ValueName, L"ParentIdPrefix");
- Status = ZwQueryValueKey(
- hKey, &ValueName,
- KeyValuePartialInformation, ParentIdPrefixInformation,
- KeyNameBufferLength, &KeyNameBufferLength);
- if (NT_SUCCESS(Status))
- {
- if (ParentIdPrefixInformation->Type != REG_SZ)
- Status = STATUS_UNSUCCESSFUL;
- else
- {
- KeyValue.Length = KeyValue.MaximumLength = (USHORT)ParentIdPrefixInformation->DataLength;
- KeyValue.Buffer = (PWSTR)ParentIdPrefixInformation->Data;
- }
- goto cleanup;
- }
- if (Status != STATUS_OBJECT_NAME_NOT_FOUND)
- {
- KeyValue.Length = KeyValue.MaximumLength = (USHORT)ParentIdPrefixInformation->DataLength;
- KeyValue.Buffer = (PWSTR)ParentIdPrefixInformation->Data;
- goto cleanup;
- }
+ KeyName.Length = 0;
+ KeyName.MaximumLength = EnumKeyPath.Length +
+ DeviceNode->Parent->InstancePath.Length +
+ sizeof(UNICODE_NULL);
+ KeyName.Buffer = ExAllocatePoolWithTag(PagedPool,
+ KeyName.MaximumLength,
+ TAG_IO);
+ if (!KeyName.Buffer)
+ {
+ Status = STATUS_INSUFFICIENT_RESOURCES;
+ goto cleanup;
+ }
- /* 2. Create the ParentIdPrefix value */
- crc32 = RtlComputeCrc32(0,
- (PUCHAR)DeviceNode->Parent->InstancePath.Buffer,
- DeviceNode->Parent->InstancePath.Length);
+ RtlCopyUnicodeString(&KeyName, &EnumKeyPath);
+ RtlAppendUnicodeStringToString(&KeyName, &DeviceNode->Parent->InstancePath);
- swprintf((PWSTR)ParentIdPrefixInformation->Data, L"%lx&%lx", DeviceNode->Parent->Level, crc32);
- RtlInitUnicodeString(&KeyValue, (PWSTR)ParentIdPrefixInformation->Data);
+ Status = IopOpenRegistryKeyEx(&hKey, NULL, &KeyName, KEY_QUERY_VALUE | KEY_SET_VALUE);
+ if (!NT_SUCCESS(Status))
+ {
+ goto cleanup;
+ }
+ RtlInitUnicodeString(&ValueName, L"ParentIdPrefix");
+ Status = ZwQueryValueKey(hKey,
+ &ValueName,
+ KeyValuePartialInformation,
+ ParentIdPrefixInformation,
+ KeyNameBufferLength,
+ &KeyNameBufferLength);
+ if (NT_SUCCESS(Status))
+ {
+ if (ParentIdPrefixInformation->Type != REG_SZ)
+ {
+ Status = STATUS_UNSUCCESSFUL;
+ }
+ else
+ {
+ KeyValue.MaximumLength = (USHORT)ParentIdPrefixInformation->DataLength;
+ KeyValue.Length = KeyValue.MaximumLength - sizeof(UNICODE_NULL);
+ KeyValue.Buffer = (PWSTR)ParentIdPrefixInformation->Data;
+ ASSERT(KeyValue.Buffer[KeyValue.Length / sizeof(WCHAR)] == UNICODE_NULL);
+ }
+ goto cleanup;
+ }
+ if (Status != STATUS_OBJECT_NAME_NOT_FOUND)
+ {
+ /* FIXME how do we get here and why is ParentIdPrefixInformation valid? */
+ KeyValue.MaximumLength = (USHORT)ParentIdPrefixInformation->DataLength;
+ KeyValue.Length = KeyValue.MaximumLength - sizeof(UNICODE_NULL);
+ KeyValue.Buffer = (PWSTR)ParentIdPrefixInformation->Data;
+ ASSERT(KeyValue.Buffer[KeyValue.Length / sizeof(WCHAR)] == UNICODE_NULL);
+ goto cleanup;
+ }
- /* 3. Try to write the ParentIdPrefix to registry */
- Status = ZwSetValueKey(hKey,
- &ValueName,
- 0,
- REG_SZ,
- (PVOID)KeyValue.Buffer,
- ((ULONG)wcslen(KeyValue.Buffer) + 1) * sizeof(WCHAR));
+ /* 2. Create the ParentIdPrefix value */
+ crc32 = RtlComputeCrc32(0,
+ (PUCHAR)DeviceNode->Parent->InstancePath.Buffer,
+ DeviceNode->Parent->InstancePath.Length);
+
+ RtlStringCbPrintfW((PWSTR)ParentIdPrefixInformation,
+ KeyNameBufferLength,
+ L"%lx&%lx",
+ DeviceNode->Parent->Level,
+ crc32);
+ RtlInitUnicodeString(&KeyValue, (PWSTR)ParentIdPrefixInformation);
+
+ /* 3. Try to write the ParentIdPrefix to registry */
+ Status = ZwSetValueKey(hKey,
+ &ValueName,
+ 0,
+ REG_SZ,
+ KeyValue.Buffer,
+ ((ULONG)wcslen(KeyValue.Buffer) + 1) * sizeof(WCHAR));
cleanup:
- if (NT_SUCCESS(Status))
- {
- /* Duplicate the string to return it */
- Status = RtlDuplicateUnicodeString(RTL_DUPLICATE_UNICODE_STRING_NULL_TERMINATE, &KeyValue, ParentIdPrefix);
- }
- ExFreePool(ParentIdPrefixInformation);
- RtlFreeUnicodeString(&KeyName);
- if (hKey != NULL)
- ZwClose(hKey);
- return Status;
+ if (NT_SUCCESS(Status))
+ {
+ /* Duplicate the string to return it */
+ Status = RtlDuplicateUnicodeString(RTL_DUPLICATE_UNICODE_STRING_NULL_TERMINATE,
+ &KeyValue,
+ ParentIdPrefix);
+ }
+ ExFreePoolWithTag(ParentIdPrefixInformation, TAG_IO);
+ RtlFreeUnicodeString(&KeyName);
+ if (hKey != NULL)
+ {
+ ZwClose(hKey);
+ }
+ return Status;
}
-NTSTATUS
-IopQueryHardwareIds(PDEVICE_NODE DeviceNode,
- HANDLE InstanceKey)
+static
+BOOLEAN
+IopValidateID(
+ _In_ PWCHAR Id,
+ _In_ BUS_QUERY_ID_TYPE QueryType)
{
- IO_STACK_LOCATION Stack;
- IO_STATUS_BLOCK IoStatusBlock;
- PWSTR Ptr;
- UNICODE_STRING ValueName;
- NTSTATUS Status;
- ULONG Length, TotalLength;
+ PWCHAR PtrChar;
+ PWCHAR StringEnd;
+ WCHAR Char;
+ ULONG SeparatorsCount = 0;
+ PWCHAR PtrPrevChar = NULL;
+ ULONG MaxSeparators;
+ BOOLEAN IsMultiSz;
- DPRINT("Sending IRP_MN_QUERY_ID.BusQueryHardwareIDs to device stack\n");
+ PAGED_CODE();
- RtlZeroMemory(&Stack, sizeof(Stack));
- Stack.Parameters.QueryId.IdType = BusQueryHardwareIDs;
- Status = IopInitiatePnpIrp(DeviceNode->PhysicalDeviceObject,
- &IoStatusBlock,
- IRP_MN_QUERY_ID,
- &Stack);
- if (NT_SUCCESS(Status))
- {
- /*
- * FIXME: Check for valid characters, if there is invalid characters
- * then bugcheck.
- */
- TotalLength = 0;
- Ptr = (PWSTR)IoStatusBlock.Information;
- DPRINT("Hardware IDs:\n");
- while (*Ptr)
- {
- DPRINT(" %S\n", Ptr);
- Length = (ULONG)wcslen(Ptr) + 1;
+ switch (QueryType)
+ {
+ case BusQueryDeviceID:
+ MaxSeparators = MAX_SEPARATORS_DEVICEID;
+ IsMultiSz = FALSE;
+ break;
+ case BusQueryInstanceID:
+ MaxSeparators = MAX_SEPARATORS_INSTANCEID;
+ IsMultiSz = FALSE;
+ break;
- Ptr += Length;
- TotalLength += Length;
- }
- DPRINT("TotalLength: %hu\n", TotalLength);
- DPRINT("\n");
-
- RtlInitUnicodeString(&ValueName, L"HardwareID");
- Status = ZwSetValueKey(InstanceKey,
- &ValueName,
- 0,
- REG_MULTI_SZ,
- (PVOID)IoStatusBlock.Information,
- (TotalLength + 1) * sizeof(WCHAR));
- if (!NT_SUCCESS(Status))
- {
- DPRINT1("ZwSetValueKey() failed (Status %lx)\n", Status);
- }
- }
- else
- {
- DPRINT("IopInitiatePnpIrp() failed (Status %x)\n", Status);
- }
+ case BusQueryHardwareIDs:
+ case BusQueryCompatibleIDs:
+ MaxSeparators = MAX_SEPARATORS_DEVICEID;
+ IsMultiSz = TRUE;
+ break;
- return Status;
+ default:
+ DPRINT1("IopValidateID: Not handled QueryType - %x\n", QueryType);
+ return FALSE;
+ }
+
+ StringEnd = Id + MAX_DEVICE_ID_LEN;
+
+ for (PtrChar = Id; PtrChar < StringEnd; PtrChar++)
+ {
+ Char = *PtrChar;
+
+ if (Char == UNICODE_NULL)
+ {
+ if (!IsMultiSz || (PtrPrevChar && PtrChar == PtrPrevChar + 1))
+ {
+ if (MaxSeparators == SeparatorsCount || IsMultiSz)
+ {
+ return TRUE;
+ }
+
+ DPRINT1("IopValidateID: SeparatorsCount - %lu, MaxSeparators - %lu\n",
+ SeparatorsCount, MaxSeparators);
+ goto ErrorExit;
+ }
+
+ StringEnd = PtrChar + MAX_DEVICE_ID_LEN + 1;
+ PtrPrevChar = PtrChar;
+ SeparatorsCount = 0;
+ }
+ else if (Char < ' ' || Char > 0x7F || Char == ',')
+ {
+ DPRINT1("IopValidateID: Invalid character - %04X\n", Char);
+ goto ErrorExit;
+ }
+ else if (Char == ' ')
+ {
+ *PtrChar = '_';
+ }
+ else if (Char == '\\')
+ {
+ SeparatorsCount++;
+
+ if (SeparatorsCount > MaxSeparators)
+ {
+ DPRINT1("IopValidateID: SeparatorsCount - %lu, MaxSeparators - %lu\n",
+ SeparatorsCount, MaxSeparators);
+ goto ErrorExit;
+ }
+ }
+ }
+
+ DPRINT1("IopValidateID: Not terminated ID\n");
+
+ErrorExit:
+ // FIXME logging
+ return FALSE;
+}
+
+NTSTATUS
+IopQueryHardwareIds(PDEVICE_NODE DeviceNode,
+ HANDLE InstanceKey)
+{
+ IO_STACK_LOCATION Stack;
+ IO_STATUS_BLOCK IoStatusBlock;
+ PWSTR Ptr;
+ UNICODE_STRING ValueName;
+ NTSTATUS Status;
+ ULONG Length, TotalLength;
+ BOOLEAN IsValidID;
+
+ DPRINT("Sending IRP_MN_QUERY_ID.BusQueryHardwareIDs to device stack\n");
+
+ RtlZeroMemory(&Stack, sizeof(Stack));
+ Stack.Parameters.QueryId.IdType = BusQueryHardwareIDs;
+ Status = IopInitiatePnpIrp(DeviceNode->PhysicalDeviceObject,
+ &IoStatusBlock,
+ IRP_MN_QUERY_ID,
+ &Stack);
+ if (NT_SUCCESS(Status))
+ {
+ IsValidID = IopValidateID((PWCHAR)IoStatusBlock.Information, BusQueryHardwareIDs);
+
+ if (!IsValidID)
+ {
+ DPRINT1("Invalid HardwareIDs. DeviceNode - %p\n", DeviceNode);
+ }
+
+ TotalLength = 0;
+
+ Ptr = (PWSTR)IoStatusBlock.Information;
+ DPRINT("Hardware IDs:\n");
+ while (*Ptr)
+ {
+ DPRINT(" %S\n", Ptr);
+ Length = (ULONG)wcslen(Ptr) + 1;
+
+ Ptr += Length;
+ TotalLength += Length;
+ }
+ DPRINT("TotalLength: %hu\n", TotalLength);
+ DPRINT("\n");
+
+ RtlInitUnicodeString(&ValueName, L"HardwareID");
+ Status = ZwSetValueKey(InstanceKey,
+ &ValueName,
+ 0,
+ REG_MULTI_SZ,
+ (PVOID)IoStatusBlock.Information,
+ (TotalLength + 1) * sizeof(WCHAR));
+ if (!NT_SUCCESS(Status))
+ {
+ DPRINT1("ZwSetValueKey() failed (Status %lx)\n", Status);
+ }
+ }
+ else
+ {
+ DPRINT("IopInitiatePnpIrp() failed (Status %x)\n", Status);
+ }
+
+ return Status;
}
NTSTATUS
IopQueryCompatibleIds(PDEVICE_NODE DeviceNode,
HANDLE InstanceKey)
{
- IO_STACK_LOCATION Stack;
- IO_STATUS_BLOCK IoStatusBlock;
- PWSTR Ptr;
- UNICODE_STRING ValueName;
- NTSTATUS Status;
- ULONG Length, TotalLength;
-
- DPRINT("Sending IRP_MN_QUERY_ID.BusQueryCompatibleIDs to device stack\n");
-
- RtlZeroMemory(&Stack, sizeof(Stack));
- Stack.Parameters.QueryId.IdType = BusQueryCompatibleIDs;
- Status = IopInitiatePnpIrp(
- DeviceNode->PhysicalDeviceObject,
- &IoStatusBlock,
- IRP_MN_QUERY_ID,
- &Stack);
- if (NT_SUCCESS(Status) && IoStatusBlock.Information)
- {
- /*
- * FIXME: Check for valid characters, if there is invalid characters
- * then bugcheck.
- */
- TotalLength = 0;
- Ptr = (PWSTR)IoStatusBlock.Information;
- DPRINT("Compatible IDs:\n");
- while (*Ptr)
- {
- DPRINT(" %S\n", Ptr);
- Length = (ULONG)wcslen(Ptr) + 1;
+ IO_STACK_LOCATION Stack;
+ IO_STATUS_BLOCK IoStatusBlock;
+ PWSTR Ptr;
+ UNICODE_STRING ValueName;
+ NTSTATUS Status;
+ ULONG Length, TotalLength;
+ BOOLEAN IsValidID;
- Ptr += Length;
- TotalLength += Length;
- }
- DPRINT("TotalLength: %hu\n", TotalLength);
- DPRINT("\n");
+ DPRINT("Sending IRP_MN_QUERY_ID.BusQueryCompatibleIDs to device stack\n");
- RtlInitUnicodeString(&ValueName, L"CompatibleIDs");
- Status = ZwSetValueKey(InstanceKey,
- &ValueName,
- 0,
- REG_MULTI_SZ,
- (PVOID)IoStatusBlock.Information,
- (TotalLength + 1) * sizeof(WCHAR));
- if (!NT_SUCCESS(Status))
- {
- DPRINT1("ZwSetValueKey() failed (Status %lx) or no Compatible ID returned\n", Status);
- }
- }
- else
- {
- DPRINT("IopInitiatePnpIrp() failed (Status %x)\n", Status);
- }
+ RtlZeroMemory(&Stack, sizeof(Stack));
+ Stack.Parameters.QueryId.IdType = BusQueryCompatibleIDs;
+ Status = IopInitiatePnpIrp(DeviceNode->PhysicalDeviceObject,
+ &IoStatusBlock,
+ IRP_MN_QUERY_ID,
+ &Stack);
+ if (NT_SUCCESS(Status) && IoStatusBlock.Information)
+ {
+ IsValidID = IopValidateID((PWCHAR)IoStatusBlock.Information, BusQueryCompatibleIDs);
- return Status;
+ if (!IsValidID)
+ {
+ DPRINT1("Invalid CompatibleIDs. DeviceNode - %p\n", DeviceNode);
+ }
+
+ TotalLength = 0;
+
+ Ptr = (PWSTR)IoStatusBlock.Information;
+ DPRINT("Compatible IDs:\n");
+ while (*Ptr)
+ {
+ DPRINT(" %S\n", Ptr);
+ Length = (ULONG)wcslen(Ptr) + 1;
+
+ Ptr += Length;
+ TotalLength += Length;
+ }
+ DPRINT("TotalLength: %hu\n", TotalLength);
+ DPRINT("\n");
+
+ RtlInitUnicodeString(&ValueName, L"CompatibleIDs");
+ Status = ZwSetValueKey(InstanceKey,
+ &ValueName,
+ 0,
+ REG_MULTI_SZ,
+ (PVOID)IoStatusBlock.Information,
+ (TotalLength + 1) * sizeof(WCHAR));
+ if (!NT_SUCCESS(Status))
+ {
+ DPRINT1("ZwSetValueKey() failed (Status %lx) or no Compatible ID returned\n", Status);
+ }
+ }
+ else
+ {
+ DPRINT("IopInitiatePnpIrp() failed (Status %x)\n", Status);
+ }
+
+ return Status;
}
+NTSTATUS
+IopCreateDeviceInstancePath(
+ _In_ PDEVICE_NODE DeviceNode,
+ _Out_ PUNICODE_STRING InstancePath)
+{
+ IO_STATUS_BLOCK IoStatusBlock;
+ UNICODE_STRING DeviceId;
+ UNICODE_STRING InstanceId;
+ IO_STACK_LOCATION Stack;
+ NTSTATUS Status;
+ UNICODE_STRING ParentIdPrefix = { 0, 0, NULL };
+ DEVICE_CAPABILITIES DeviceCapabilities;
+ BOOLEAN IsValidID;
+
+ DPRINT("Sending IRP_MN_QUERY_ID.BusQueryDeviceID to device stack\n");
+
+ Stack.Parameters.QueryId.IdType = BusQueryDeviceID;
+ Status = IopInitiatePnpIrp(DeviceNode->PhysicalDeviceObject,
+ &IoStatusBlock,
+ IRP_MN_QUERY_ID,
+ &Stack);
+ if (!NT_SUCCESS(Status))
+ {
+ DPRINT1("IopInitiatePnpIrp(BusQueryDeviceID) failed (Status %x)\n", Status);
+ return Status;
+ }
+
+ IsValidID = IopValidateID((PWCHAR)IoStatusBlock.Information, BusQueryDeviceID);
+
+ if (!IsValidID)
+ {
+ DPRINT1("Invalid DeviceID. DeviceNode - %p\n", DeviceNode);
+ }
+
+ /* Save the device id string */
+ RtlInitUnicodeString(&DeviceId, (PWSTR)IoStatusBlock.Information);
+
+ DPRINT("Sending IRP_MN_QUERY_CAPABILITIES to device stack (after enumeration)\n");
+
+ Status = IopQueryDeviceCapabilities(DeviceNode, &DeviceCapabilities);
+ if (!NT_SUCCESS(Status))
+ {
+ DPRINT1("IopQueryDeviceCapabilities() failed (Status 0x%08lx)\n", Status);
+ RtlFreeUnicodeString(&DeviceId);
+ return Status;
+ }
+
+ /* This bit is only check after enumeration */
+ if (DeviceCapabilities.HardwareDisabled)
+ {
+ /* FIXME: Cleanup device */
+ DeviceNode->Flags |= DNF_DISABLED;
+ RtlFreeUnicodeString(&DeviceId);
+ return STATUS_PLUGPLAY_NO_DEVICE;
+ }
+ else
+ {
+ DeviceNode->Flags &= ~DNF_DISABLED;
+ }
+
+ if (!DeviceCapabilities.UniqueID)
+ {
+ /* Device has not a unique ID. We need to prepend parent bus unique identifier */
+ DPRINT("Instance ID is not unique\n");
+ Status = IopGetParentIdPrefix(DeviceNode, &ParentIdPrefix);
+ if (!NT_SUCCESS(Status))
+ {
+ DPRINT1("IopGetParentIdPrefix() failed (Status 0x%08lx)\n", Status);
+ RtlFreeUnicodeString(&DeviceId);
+ return Status;
+ }
+ }
+
+ DPRINT("Sending IRP_MN_QUERY_ID.BusQueryInstanceID to device stack\n");
+
+ Stack.Parameters.QueryId.IdType = BusQueryInstanceID;
+ Status = IopInitiatePnpIrp(DeviceNode->PhysicalDeviceObject,
+ &IoStatusBlock,
+ IRP_MN_QUERY_ID,
+ &Stack);
+ if (!NT_SUCCESS(Status))
+ {
+ DPRINT("IopInitiatePnpIrp(BusQueryInstanceID) failed (Status %lx)\n", Status);
+ ASSERT(IoStatusBlock.Information == 0);
+ }
+
+ if (IoStatusBlock.Information)
+ {
+ IsValidID = IopValidateID((PWCHAR)IoStatusBlock.Information, BusQueryInstanceID);
+
+ if (!IsValidID)
+ {
+ DPRINT1("Invalid InstanceID. DeviceNode - %p\n", DeviceNode);
+ }
+ }
+
+ RtlInitUnicodeString(&InstanceId,
+ (PWSTR)IoStatusBlock.Information);
+
+ InstancePath->Length = 0;
+ InstancePath->MaximumLength = DeviceId.Length + sizeof(WCHAR) +
+ ParentIdPrefix.Length +
+ InstanceId.Length +
+ sizeof(UNICODE_NULL);
+ if (ParentIdPrefix.Length && InstanceId.Length)
+ {
+ InstancePath->MaximumLength += sizeof(WCHAR);
+ }
+
+ InstancePath->Buffer = ExAllocatePoolWithTag(PagedPool,
+ InstancePath->MaximumLength,
+ TAG_IO);
+ if (!InstancePath->Buffer)
+ {
+ RtlFreeUnicodeString(&InstanceId);
+ RtlFreeUnicodeString(&ParentIdPrefix);
+ RtlFreeUnicodeString(&DeviceId);
+ return STATUS_INSUFFICIENT_RESOURCES;
+ }
+
+ /* Start with the device id */
+ RtlCopyUnicodeString(InstancePath, &DeviceId);
+ RtlAppendUnicodeToString(InstancePath, L"\\");
+
+ /* Add information from parent bus device to InstancePath */
+ RtlAppendUnicodeStringToString(InstancePath, &ParentIdPrefix);
+ if (ParentIdPrefix.Length && InstanceId.Length)
+ {
+ RtlAppendUnicodeToString(InstancePath, L"&");
+ }
+
+ /* Finally, add the id returned by the driver stack */
+ RtlAppendUnicodeStringToString(InstancePath, &InstanceId);
+
+ /*
+ * FIXME: Check for valid characters, if there is invalid characters
+ * then bugcheck
+ */
+
+ RtlFreeUnicodeString(&InstanceId);
+ RtlFreeUnicodeString(&DeviceId);
+ RtlFreeUnicodeString(&ParentIdPrefix);
+
+ return STATUS_SUCCESS;
+}
/*
* IopActionInterrogateDeviceStack
IopActionInterrogateDeviceStack(PDEVICE_NODE DeviceNode,
PVOID Context)
{
- IO_STATUS_BLOCK IoStatusBlock;
- PDEVICE_NODE ParentDeviceNode;
- WCHAR InstancePath[MAX_PATH];
- IO_STACK_LOCATION Stack;
- NTSTATUS Status;
- ULONG RequiredLength;
- LCID LocaleId;
- 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);
-
- ParentDeviceNode = (PDEVICE_NODE)Context;
-
- /*
- * We are called for the parent too, but we don't need to do special
- * handling for this node
- */
-
- if (DeviceNode == ParentDeviceNode)
- {
- DPRINT("Success\n");
- return STATUS_SUCCESS;
- }
-
- /*
- * Make sure this device node is a direct child of the parent device node
- * that is given as an argument
- */
-
- if (DeviceNode->Parent != ParentDeviceNode)
- {
- DPRINT("Skipping 2+ level child\n");
- return STATUS_SUCCESS;
- }
-
- /* Skip processing if it was already completed before */
- if (DeviceNode->Flags & DNF_PROCESSED)
- {
- /* Nothing to do */
- return STATUS_SUCCESS;
- }
-
- /* Get Locale ID */
- Status = ZwQueryDefaultLocale(FALSE, &LocaleId);
- if (!NT_SUCCESS(Status))
- {
- DPRINT1("ZwQueryDefaultLocale() failed with status 0x%lx\n", Status);
- return Status;
- }
-
- /*
- * FIXME: For critical errors, cleanup and disable device, but always
- * return STATUS_SUCCESS.
- */
-
- DPRINT("Sending IRP_MN_QUERY_ID.BusQueryDeviceID to device stack\n");
-
- Stack.Parameters.QueryId.IdType = BusQueryDeviceID;
- Status = IopInitiatePnpIrp(DeviceNode->PhysicalDeviceObject,
- &IoStatusBlock,
- IRP_MN_QUERY_ID,
- &Stack);
- if (NT_SUCCESS(Status))
- {
- /* Copy the device id string */
- wcscpy(InstancePath, (PWSTR)IoStatusBlock.Information);
-
- /*
- * FIXME: Check for valid characters, if there is invalid characters
- * then bugcheck.
- */
- }
- else
- {
- DPRINT1("IopInitiatePnpIrp() failed (Status %x)\n", Status);
-
- /* We have to return success otherwise we abort the traverse operation */
- return STATUS_SUCCESS;
- }
+ IO_STATUS_BLOCK IoStatusBlock;
+ PWSTR DeviceDescription;
+ PWSTR LocationInformation;
+ PDEVICE_NODE ParentDeviceNode;
+ IO_STACK_LOCATION Stack;
+ NTSTATUS Status;
+ ULONG RequiredLength;
+ LCID LocaleId;
+ HANDLE InstanceKey = NULL;
+ UNICODE_STRING ValueName;
+ UNICODE_STRING InstancePathU;
+ PDEVICE_OBJECT OldDeviceObject;
- DPRINT("Sending IRP_MN_QUERY_CAPABILITIES to device stack (after enumeration)\n");
+ DPRINT("IopActionInterrogateDeviceStack(%p, %p)\n", DeviceNode, Context);
+ DPRINT("PDO 0x%p\n", DeviceNode->PhysicalDeviceObject);
- Status = IopQueryDeviceCapabilities(DeviceNode, &DeviceCapabilities);
- if (!NT_SUCCESS(Status))
- {
- DPRINT1("IopInitiatePnpIrp() failed (Status 0x%08lx)\n", Status);
+ ParentDeviceNode = (PDEVICE_NODE)Context;
- /* We have to return success otherwise we abort the traverse operation */
- return STATUS_SUCCESS;
- }
-
- /* 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;
+ /*
+ * We are called for the parent too, but we don't need to do special
+ * handling for this node
+ */
+ if (DeviceNode == ParentDeviceNode)
+ {
+ DPRINT("Success\n");
+ return STATUS_SUCCESS;
+ }
- if (!DeviceCapabilities.UniqueID)
- {
- /* Device has not a unique ID. We need to prepend parent bus unique identifier */
- DPRINT("Instance ID is not unique\n");
- Status = IopGetParentIdPrefix(DeviceNode, &ParentIdPrefix);
- if (!NT_SUCCESS(Status))
- {
- DPRINT1("IopGetParentIdPrefix() failed (Status 0x%08lx)\n", Status);
+ /*
+ * Make sure this device node is a direct child of the parent device node
+ * that is given as an argument
+ */
+ if (DeviceNode->Parent != ParentDeviceNode)
+ {
+ DPRINT("Skipping 2+ level child\n");
+ return STATUS_SUCCESS;
+ }
- /* We have to return success otherwise we abort the traverse operation */
- return STATUS_SUCCESS;
- }
- }
+ /* Skip processing if it was already completed before */
+ if (DeviceNode->Flags & DNF_PROCESSED)
+ {
+ /* Nothing to do */
+ return STATUS_SUCCESS;
+ }
- DPRINT("Sending IRP_MN_QUERY_ID.BusQueryInstanceID to device stack\n");
+ /* Get Locale ID */
+ Status = ZwQueryDefaultLocale(FALSE, &LocaleId);
+ if (!NT_SUCCESS(Status))
+ {
+ DPRINT1("ZwQueryDefaultLocale() failed with status 0x%lx\n", Status);
+ return Status;
+ }
- Stack.Parameters.QueryId.IdType = BusQueryInstanceID;
- Status = IopInitiatePnpIrp(DeviceNode->PhysicalDeviceObject,
- &IoStatusBlock,
- IRP_MN_QUERY_ID,
- &Stack);
- if (NT_SUCCESS(Status))
- {
- /* Append the instance id string */
- wcscat(InstancePath, L"\\");
- if (ParentIdPrefix.Length > 0)
- {
- /* Add information from parent bus device to InstancePath */
- wcscat(InstancePath, ParentIdPrefix.Buffer);
- if (IoStatusBlock.Information && *(PWSTR)IoStatusBlock.Information)
- wcscat(InstancePath, L"&");
- }
- if (IoStatusBlock.Information)
- wcscat(InstancePath, (PWSTR)IoStatusBlock.Information);
+ /*
+ * FIXME: For critical errors, cleanup and disable device, but always
+ * return STATUS_SUCCESS.
+ */
- /*
- * FIXME: Check for valid characters, if there is invalid characters
- * then bugcheck
- */
- }
- else
- {
- DPRINT("IopInitiatePnpIrp() failed (Status %x)\n", Status);
- }
- RtlFreeUnicodeString(&ParentIdPrefix);
+ Status = IopCreateDeviceInstancePath(DeviceNode, &InstancePathU);
+ if (!NT_SUCCESS(Status))
+ {
+ if (Status != STATUS_PLUGPLAY_NO_DEVICE)
+ {
+ DPRINT1("IopCreateDeviceInstancePath() failed with status 0x%lx\n", Status);
+ }
- if (!RtlCreateUnicodeString(&InstancePathU, InstancePath))
- {
- DPRINT("No resources\n");
- /* FIXME: Cleanup and disable device */
- }
+ /* We have to return success otherwise we abort the traverse operation */
+ return STATUS_SUCCESS;
+ }
- /* Verify that this is not a duplicate */
- OldDeviceObject = IopGetDeviceObjectFromDeviceInstance(&InstancePathU);
- if (OldDeviceObject != NULL)
- {
- PDEVICE_NODE OldDeviceNode = IopGetDeviceNode(OldDeviceObject);
+ /* 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);
+ 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);
- }
+ KeBugCheckEx(PNP_DETECTED_FATAL_ERROR,
+ 0x01,
+ (ULONG_PTR)DeviceNode->PhysicalDeviceObject,
+ (ULONG_PTR)OldDeviceObject,
+ 0);
+ }
- DeviceNode->InstancePath = InstancePathU;
+ DeviceNode->InstancePath = InstancePathU;
- DPRINT("InstancePath is %S\n", DeviceNode->InstancePath.Buffer);
+ DPRINT("InstancePath is %S\n", DeviceNode->InstancePath.Buffer);
- /*
- * Create registry key for the instance id, if it doesn't exist yet
- */
- Status = IopCreateDeviceKeyPath(&DeviceNode->InstancePath, 0, &InstanceKey);
- if (!NT_SUCCESS(Status))
- {
- DPRINT1("Failed to create the instance key! (Status %lx)\n", Status);
+ /*
+ * Create registry key for the instance id, if it doesn't exist yet
+ */
+ Status = IopCreateDeviceKeyPath(&DeviceNode->InstancePath, REG_OPTION_NON_VOLATILE, &InstanceKey);
+ if (!NT_SUCCESS(Status))
+ {
+ DPRINT1("Failed to create the instance key! (Status %lx)\n", Status);
- /* We have to return success otherwise we abort the traverse operation */
- return STATUS_SUCCESS;
- }
+ /* We have to return success otherwise we abort the traverse operation */
+ return STATUS_SUCCESS;
+ }
- IopQueryHardwareIds(DeviceNode, InstanceKey);
+ IopQueryHardwareIds(DeviceNode, InstanceKey);
- IopQueryCompatibleIds(DeviceNode, InstanceKey);
+ IopQueryCompatibleIds(DeviceNode, InstanceKey);
- DPRINT("Sending IRP_MN_QUERY_DEVICE_TEXT.DeviceTextDescription to device stack\n");
+ DPRINT("Sending IRP_MN_QUERY_DEVICE_TEXT.DeviceTextDescription to device stack\n");
- Stack.Parameters.QueryDeviceText.DeviceTextType = DeviceTextDescription;
- Stack.Parameters.QueryDeviceText.LocaleId = LocaleId;
- Status = IopInitiatePnpIrp(
- DeviceNode->PhysicalDeviceObject,
- &IoStatusBlock,
- IRP_MN_QUERY_DEVICE_TEXT,
- &Stack);
- /* This key is mandatory, so even if the Irp fails, we still write it */
- RtlInitUnicodeString(&ValueName, L"DeviceDesc");
- if (ZwQueryValueKey(InstanceKey, &ValueName, KeyValueBasicInformation, NULL, 0, &RequiredLength) == STATUS_OBJECT_NAME_NOT_FOUND)
- {
- if (NT_SUCCESS(Status) &&
- IoStatusBlock.Information &&
- (*(PWSTR)IoStatusBlock.Information != 0))
- {
- /* This key is overriden when a driver is installed. Don't write the
- * new description if another one already exists */
- Status = ZwSetValueKey(InstanceKey,
- &ValueName,
- 0,
- REG_SZ,
- (PVOID)IoStatusBlock.Information,
- ((ULONG)wcslen((PWSTR)IoStatusBlock.Information) + 1) * sizeof(WCHAR));
- }
- else
- {
- UNICODE_STRING DeviceDesc = RTL_CONSTANT_STRING(L"Unknown device");
- DPRINT("Driver didn't return DeviceDesc (Status 0x%08lx), so place unknown device there\n", Status);
+ Stack.Parameters.QueryDeviceText.DeviceTextType = DeviceTextDescription;
+ Stack.Parameters.QueryDeviceText.LocaleId = LocaleId;
+ Status = IopInitiatePnpIrp(DeviceNode->PhysicalDeviceObject,
+ &IoStatusBlock,
+ IRP_MN_QUERY_DEVICE_TEXT,
+ &Stack);
+ DeviceDescription = NT_SUCCESS(Status) ? (PWSTR)IoStatusBlock.Information
+ : NULL;
+ /* This key is mandatory, so even if the Irp fails, we still write it */
+ RtlInitUnicodeString(&ValueName, L"DeviceDesc");
+ if (ZwQueryValueKey(InstanceKey, &ValueName, KeyValueBasicInformation, NULL, 0, &RequiredLength) == STATUS_OBJECT_NAME_NOT_FOUND)
+ {
+ if (DeviceDescription &&
+ *DeviceDescription != UNICODE_NULL)
+ {
+ /* This key is overriden when a driver is installed. Don't write the
+ * new description if another one already exists */
+ Status = ZwSetValueKey(InstanceKey,
+ &ValueName,
+ 0,
+ REG_SZ,
+ DeviceDescription,
+ ((ULONG)wcslen(DeviceDescription) + 1) * sizeof(WCHAR));
+ }
+ else
+ {
+ UNICODE_STRING DeviceDesc = RTL_CONSTANT_STRING(L"Unknown device");
+ DPRINT("Driver didn't return DeviceDesc (Status 0x%08lx), so place unknown device there\n", Status);
- Status = ZwSetValueKey(InstanceKey,
- &ValueName,
- 0,
- REG_SZ,
- DeviceDesc.Buffer,
- DeviceDesc.MaximumLength);
+ Status = ZwSetValueKey(InstanceKey,
+ &ValueName,
+ 0,
+ REG_SZ,
+ DeviceDesc.Buffer,
+ DeviceDesc.MaximumLength);
+ if (!NT_SUCCESS(Status))
+ {
+ DPRINT1("ZwSetValueKey() failed (Status 0x%lx)\n", Status);
+ }
- if (!NT_SUCCESS(Status))
- {
- DPRINT1("ZwSetValueKey() failed (Status 0x%lx)\n", Status);
- }
+ }
+ }
- }
- }
+ if (DeviceDescription)
+ {
+ ExFreePoolWithTag(DeviceDescription, 0);
+ }
- DPRINT("Sending IRP_MN_QUERY_DEVICE_TEXT.DeviceTextLocation to device stack\n");
+ DPRINT("Sending IRP_MN_QUERY_DEVICE_TEXT.DeviceTextLocation to device stack\n");
- Stack.Parameters.QueryDeviceText.DeviceTextType = DeviceTextLocationInformation;
- Stack.Parameters.QueryDeviceText.LocaleId = LocaleId;
- Status = IopInitiatePnpIrp(
- DeviceNode->PhysicalDeviceObject,
- &IoStatusBlock,
- IRP_MN_QUERY_DEVICE_TEXT,
- &Stack);
- if (NT_SUCCESS(Status) && IoStatusBlock.Information)
- {
- DPRINT("LocationInformation: %S\n", (PWSTR)IoStatusBlock.Information);
- RtlInitUnicodeString(&ValueName, L"LocationInformation");
- Status = ZwSetValueKey(InstanceKey,
- &ValueName,
- 0,
- REG_SZ,
- (PVOID)IoStatusBlock.Information,
- ((ULONG)wcslen((PWSTR)IoStatusBlock.Information) + 1) * sizeof(WCHAR));
- if (!NT_SUCCESS(Status))
- {
- DPRINT1("ZwSetValueKey() failed (Status %lx)\n", Status);
- }
- }
- else
- {
- DPRINT("IopInitiatePnpIrp() failed (Status %x) or IoStatusBlock.Information=NULL\n", Status);
- }
+ Stack.Parameters.QueryDeviceText.DeviceTextType = DeviceTextLocationInformation;
+ Stack.Parameters.QueryDeviceText.LocaleId = LocaleId;
+ Status = IopInitiatePnpIrp(DeviceNode->PhysicalDeviceObject,
+ &IoStatusBlock,
+ IRP_MN_QUERY_DEVICE_TEXT,
+ &Stack);
+ if (NT_SUCCESS(Status) && IoStatusBlock.Information)
+ {
+ LocationInformation = (PWSTR)IoStatusBlock.Information;
+ DPRINT("LocationInformation: %S\n", LocationInformation);
+ RtlInitUnicodeString(&ValueName, L"LocationInformation");
+ Status = ZwSetValueKey(InstanceKey,
+ &ValueName,
+ 0,
+ REG_SZ,
+ LocationInformation,
+ ((ULONG)wcslen(LocationInformation) + 1) * sizeof(WCHAR));
+ if (!NT_SUCCESS(Status))
+ {
+ DPRINT1("ZwSetValueKey() failed (Status %lx)\n", Status);
+ }
- DPRINT("Sending IRP_MN_QUERY_BUS_INFORMATION to device stack\n");
+ ExFreePoolWithTag(LocationInformation, 0);
+ }
+ else
+ {
+ DPRINT("IopInitiatePnpIrp() failed (Status %x) or IoStatusBlock.Information=NULL\n", Status);
+ }
- Status = IopInitiatePnpIrp(
- DeviceNode->PhysicalDeviceObject,
- &IoStatusBlock,
- IRP_MN_QUERY_BUS_INFORMATION,
- NULL);
- if (NT_SUCCESS(Status) && IoStatusBlock.Information)
- {
- PPNP_BUS_INFORMATION BusInformation =
- (PPNP_BUS_INFORMATION)IoStatusBlock.Information;
+ DPRINT("Sending IRP_MN_QUERY_BUS_INFORMATION to device stack\n");
- DeviceNode->ChildBusNumber = BusInformation->BusNumber;
- DeviceNode->ChildInterfaceType = BusInformation->LegacyBusType;
- DeviceNode->ChildBusTypeIndex = IopGetBusTypeGuidIndex(&BusInformation->BusTypeGuid);
- ExFreePool(BusInformation);
- }
- else
- {
- DPRINT("IopInitiatePnpIrp() failed (Status %x) or IoStatusBlock.Information=NULL\n", Status);
+ Status = IopInitiatePnpIrp(DeviceNode->PhysicalDeviceObject,
+ &IoStatusBlock,
+ IRP_MN_QUERY_BUS_INFORMATION,
+ NULL);
+ if (NT_SUCCESS(Status) && IoStatusBlock.Information)
+ {
+ PPNP_BUS_INFORMATION BusInformation = (PPNP_BUS_INFORMATION)IoStatusBlock.Information;
- DeviceNode->ChildBusNumber = 0xFFFFFFF0;
- DeviceNode->ChildInterfaceType = InterfaceTypeUndefined;
- DeviceNode->ChildBusTypeIndex = -1;
- }
+ DeviceNode->ChildBusNumber = BusInformation->BusNumber;
+ DeviceNode->ChildInterfaceType = BusInformation->LegacyBusType;
+ DeviceNode->ChildBusTypeIndex = IopGetBusTypeGuidIndex(&BusInformation->BusTypeGuid);
+ ExFreePoolWithTag(BusInformation, 0);
+ }
+ else
+ {
+ DPRINT("IopInitiatePnpIrp() failed (Status %x) or IoStatusBlock.Information=NULL\n", Status);
- DPRINT("Sending IRP_MN_QUERY_RESOURCES to device stack\n");
+ DeviceNode->ChildBusNumber = 0xFFFFFFF0;
+ DeviceNode->ChildInterfaceType = InterfaceTypeUndefined;
+ DeviceNode->ChildBusTypeIndex = -1;
+ }
- Status = IopInitiatePnpIrp(
- DeviceNode->PhysicalDeviceObject,
- &IoStatusBlock,
- IRP_MN_QUERY_RESOURCES,
- NULL);
- if (NT_SUCCESS(Status) && IoStatusBlock.Information)
- {
- DeviceNode->BootResources =
- (PCM_RESOURCE_LIST)IoStatusBlock.Information;
- IopDeviceNodeSetFlag(DeviceNode, DNF_HAS_BOOT_CONFIG);
- }
- else
- {
- DPRINT("IopInitiatePnpIrp() failed (Status %x) or IoStatusBlock.Information=NULL\n", Status);
- DeviceNode->BootResources = NULL;
- }
+ DPRINT("Sending IRP_MN_QUERY_RESOURCES to device stack\n");
- DPRINT("Sending IRP_MN_QUERY_RESOURCE_REQUIREMENTS to device stack\n");
+ Status = IopInitiatePnpIrp(DeviceNode->PhysicalDeviceObject,
+ &IoStatusBlock,
+ IRP_MN_QUERY_RESOURCES,
+ NULL);
+ if (NT_SUCCESS(Status) && IoStatusBlock.Information)
+ {
+ DeviceNode->BootResources = (PCM_RESOURCE_LIST)IoStatusBlock.Information;
+ IopDeviceNodeSetFlag(DeviceNode, DNF_HAS_BOOT_CONFIG);
+ }
+ else
+ {
+ DPRINT("IopInitiatePnpIrp() failed (Status %x) or IoStatusBlock.Information=NULL\n", Status);
+ DeviceNode->BootResources = NULL;
+ }
- Status = IopInitiatePnpIrp(
- DeviceNode->PhysicalDeviceObject,
- &IoStatusBlock,
- IRP_MN_QUERY_RESOURCE_REQUIREMENTS,
- NULL);
- if (NT_SUCCESS(Status))
- {
- DeviceNode->ResourceRequirements =
- (PIO_RESOURCE_REQUIREMENTS_LIST)IoStatusBlock.Information;
- }
- else
- {
- DPRINT("IopInitiatePnpIrp() failed (Status %08lx)\n", Status);
- DeviceNode->ResourceRequirements = NULL;
- }
+ DPRINT("Sending IRP_MN_QUERY_RESOURCE_REQUIREMENTS to device stack\n");
- if (InstanceKey != NULL)
- {
- IopSetDeviceInstanceData(InstanceKey, DeviceNode);
- }
+ Status = IopInitiatePnpIrp(DeviceNode->PhysicalDeviceObject,
+ &IoStatusBlock,
+ IRP_MN_QUERY_RESOURCE_REQUIREMENTS,
+ NULL);
+ if (NT_SUCCESS(Status))
+ {
+ DeviceNode->ResourceRequirements = (PIO_RESOURCE_REQUIREMENTS_LIST)IoStatusBlock.Information;
+ }
+ else
+ {
+ DPRINT("IopInitiatePnpIrp() failed (Status %08lx)\n", Status);
+ DeviceNode->ResourceRequirements = NULL;
+ }
- ZwClose(InstanceKey);
+ if (InstanceKey != NULL)
+ {
+ IopSetDeviceInstanceData(InstanceKey, DeviceNode);
+ }
- IopDeviceNodeSetFlag(DeviceNode, DNF_PROCESSED);
+ ZwClose(InstanceKey);
- if (!IopDeviceNodeHasFlag(DeviceNode, DNF_LEGACY_DRIVER))
- {
- /* Report the device to the user-mode pnp manager */
- IopQueueTargetDeviceEvent(&GUID_DEVICE_ENUMERATED,
- &DeviceNode->InstancePath);
- }
+ IopDeviceNodeSetFlag(DeviceNode, DNF_PROCESSED);
- return STATUS_SUCCESS;
+ if (!IopDeviceNodeHasFlag(DeviceNode, DNF_LEGACY_DRIVER))
+ {
+ /* Report the device to the user-mode pnp manager */
+ IopQueueTargetDeviceEvent(&GUID_DEVICE_ENUMERATED,
+ &DeviceNode->InstancePath);
+ }
+
+ return STATUS_SUCCESS;
}
static
DeviceCaps.RawDeviceOK)
{
DPRINT("%wZ is using parent bus driver (%wZ)\n", &DeviceNode->InstancePath, &ParentDeviceNode->ServiceName);
-
- DeviceNode->ServiceName.Length = 0;
- DeviceNode->ServiceName.MaximumLength = 0;
- DeviceNode->ServiceName.Buffer = NULL;
+ RtlInitEmptyUnicodeString(&DeviceNode->ServiceName, NULL, 0);
}
else if (ClassGUID.Length != 0)
{
DPRINT("IopActionInitChildServices(%p, %p)\n", DeviceNode, Context);
- ParentDeviceNode = (PDEVICE_NODE)Context;
+ ParentDeviceNode = Context;
/*
* We are called for the parent too, but we don't need to do special
PLDR_DATA_TABLE_ENTRY ModuleObject;
PDRIVER_OBJECT DriverObject;
+ KeEnterCriticalRegion();
+ ExAcquireResourceExclusiveLite(&IopDriverLoadResource, TRUE);
/* Get existing DriverObject pointer (in case the driver has
already been loaded and initialized) */
Status = IopGetDriverObject(
if (!BootDrivers) DeviceNode->Problem = CM_PROB_DRIVER_FAILED_LOAD;
}
}
+ ExReleaseResourceLite(&IopDriverLoadResource);
+ KeLeaveCriticalRegion();
/* Driver is loaded and initialized at this point */
if (NT_SUCCESS(Status))
&ObjectAttributes,
0,
NULL,
- ExpInTextModeSetup ? REG_OPTION_VOLATILE : 0,
+ REG_OPTION_NON_VOLATILE,
NULL);
if (!NT_SUCCESS(Status))
{
&ObjectAttributes,
0,
NULL,
- ExpInTextModeSetup ? REG_OPTION_VOLATILE : 0,
+ REG_OPTION_NON_VOLATILE,
NULL);
ZwClose(hLevel1Key);
if (!NT_SUCCESS(Status))
DPRINT1("ZwOpenKey(%wZ) failed with status 0x%08lx\n", &KeyPathU, Status);
}
- DPRINT1("Firmware mapper is %s\n", KeyValue != 0 ? "disabled" : "enabled");
+ DPRINT("Firmware mapper is %s\n", KeyValue != 0 ? "disabled" : "enabled");
return (KeyValue != 0) ? TRUE : FALSE;
}
NTSTATUS Status;
InitializeObjectAttributes(&ObjectAttributes, &EnumU, OBJ_KERNEL_HANDLE | OBJ_CASE_INSENSITIVE, NULL, NULL);
- Status = ZwCreateKey(&hEnum, KEY_CREATE_SUB_KEY, &ObjectAttributes, 0, NULL, 0, NULL);
+ Status = ZwCreateKey(&hEnum, KEY_CREATE_SUB_KEY, &ObjectAttributes, 0, NULL, REG_OPTION_NON_VOLATILE, NULL);
if (!NT_SUCCESS(Status))
{
DPRINT1("ZwCreateKey() failed with status 0x%08lx\n", Status);
}
InitializeObjectAttributes(&ObjectAttributes, &RootPathU, OBJ_KERNEL_HANDLE | OBJ_CASE_INSENSITIVE, hEnum, NULL);
- Status = ZwCreateKey(&hRoot, KEY_CREATE_SUB_KEY, &ObjectAttributes, 0, NULL, 0, NULL);
+ Status = ZwCreateKey(&hRoot, KEY_CREATE_SUB_KEY, &ObjectAttributes, 0, NULL, REG_OPTION_NON_VOLATILE, NULL);
ZwClose(hEnum);
if (!NT_SUCCESS(Status))
{
UNICODE_STRING KeyString;
NTSTATUS Status = STATUS_SUCCESS;
PAGED_CODE();
-
+
/* P1 is start, pp is end */
p1 = KeyName->Buffer;
pp = (PVOID)((ULONG_PTR)p1 + KeyName->Length);
-
+
/* Create the target key */
InitializeObjectAttributes(&ObjectAttributes,
KeyName,
/* Target key failed, so we'll need to create its parent. Setup array */
HandleArray[0] = NULL;
HandleArray[1] = RootHandle;
-
+
/* Keep recursing for each missing parent */
while (Recursing)
{
/* And if we're deep enough, close the last handle */
if (NestedCloseLevel > 1) ZwClose(HandleArray[RootHandleIndex]);
-
+
/* We're setup to ping-pong between the two handle array entries */
RootHandleIndex = i;
i = (i + 1) & 1;
-
+
/* Clear the one we're attempting to open now */
HandleArray[i] = NULL;
-
+
/* Process the parent key name */
for (p = p1; ((p < pp) && (*p != OBJ_NAME_PATH_SEPARATOR)); p++);
Length = (USHORT)(p - p1) * sizeof(WCHAR);
-
+
/* Is there a parent name? */
if (Length)
{
/* Build the unicode string for it */
KeyString.Buffer = p1;
KeyString.Length = KeyString.MaximumLength = Length;
-
+
/* Now try opening the parent */
InitializeObjectAttributes(&ObjectAttributes,
&KeyString,
Recursing = FALSE;
continue;
}
-
+
/* Now see if there's more parents to create */
p1 = p + 1;
if ((p == pp) || (p1 == pp))
Recursing = FALSE;
}
}
-
+
/* Outer loop check for handle nesting that requires closing the top handle */
if (NestedCloseLevel > 1) ZwClose(HandleArray[RootHandleIndex]);
}
-
+
/* Check if we broke out of the loop due to success */
if (NT_SUCCESS(Status))
{
*Handle = HandleArray[i];
if (Disposition) *Disposition = KeyDisposition;
}
-
+
/* Return the success state */
return Status;
}
{
PDEVICE_NODE DeviceNode;
PAGED_CODE();
-
+
/* Allocate it */
- DeviceNode = ExAllocatePoolWithTag(NonPagedPool, sizeof(DEVICE_NODE), 'donD');
+ DeviceNode = ExAllocatePoolWithTag(NonPagedPool, sizeof(DEVICE_NODE), TAG_IO_DEVNODE);
if (!DeviceNode) return DeviceNode;
-
+
/* Statistics */
InterlockedIncrement(&IopNumberDeviceNodes);
-
+
/* Set it up */
RtlZeroMemory(DeviceNode, sizeof(DEVICE_NODE));
DeviceNode->InterfaceType = InterfaceTypeUndefined;
InitializeListHead(&DeviceNode->TargetDeviceNotify);
InitializeListHead(&DeviceNode->DockInfo.ListEntry);
InitializeListHead(&DeviceNode->PendedSetInterfaceState);
-
+
/* Check if there is a PDO */
if (PhysicalDeviceObject)
{
((PEXTENDED_DEVOBJ_EXTENSION)PhysicalDeviceObject->DeviceObjectExtension)->DeviceNode = DeviceNode;
PhysicalDeviceObject->Flags &= ~DO_DEVICE_INITIALIZING;
}
-
+
/* Return the node */
return DeviceNode;
}
/* Acquire the lock */
ExAcquireFastMutex(&PnpBusTypeGuidList->Lock);
-
+
/* Validate size */
if (Index < PnpBusTypeGuidList->GuidCount)
{
/* Failure path */
Status = STATUS_OBJECT_NAME_NOT_FOUND;
}
-
+
/* Release lock and return status */
ExReleaseFastMutex(&PnpBusTypeGuidList->Lock);
return Status;
PDEVICE_NODE DeviceNode;
UNICODE_STRING KeyName = RTL_CONSTANT_STRING(L"\\REGISTRY\\MACHINE\\SYSTEM\\CURRENTCONTROLSET\\ENUM");
PAGED_CODE();
-
+
/* Open the enum key */
Status = IopOpenRegistryKeyEx(&KeyHandle,
NULL,
&KeyName,
KEY_READ);
if (!NT_SUCCESS(Status)) return Status;
-
+
/* Make sure we have an instance path */
DeviceNode = IopGetDeviceNode(DeviceObject);
if ((DeviceNode) && (DeviceNode->InstancePath.Length))
/* Fail */
Status = STATUS_INVALID_DEVICE_REQUEST;
}
-
+
/* Close the handle and return status */
ZwClose(KeyHandle);
return Status;
ULONG FinalSize, PartialSize, EntrySize, i, j;
PCM_FULL_RESOURCE_DESCRIPTOR FullDescriptor;
PCM_PARTIAL_RESOURCE_DESCRIPTOR PartialDescriptor;
-
+
/* If we don't have one, that's easy */
if (!ResourceList) return 0;
-
+
/* Start with the minimum size possible */
FinalSize = FIELD_OFFSET(CM_RESOURCE_LIST, List);
-
+
/* Loop each full descriptor */
FullDescriptor = ResourceList->List;
for (i = 0; i < ResourceList->Count; i++)
/* Start with the minimum size possible */
PartialSize = FIELD_OFFSET(CM_FULL_RESOURCE_DESCRIPTOR, PartialResourceList) +
FIELD_OFFSET(CM_PARTIAL_RESOURCE_LIST, PartialDescriptors);
-
+
/* Loop each partial descriptor */
PartialDescriptor = FullDescriptor->PartialResourceList.PartialDescriptors;
for (j = 0; j < FullDescriptor->PartialResourceList.Count; j++)
{
/* Start with the minimum size possible */
EntrySize = sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR);
-
+
/* Check if there is extra data */
if (PartialDescriptor->Type == CmResourceTypeDeviceSpecific)
{
/* Add that data */
EntrySize += PartialDescriptor->u.DeviceSpecificData.DataSize;
}
-
+
/* The size of partial descriptors is bigger */
PartialSize += EntrySize;
-
+
/* Go to the next partial descriptor */
PartialDescriptor = (PVOID)((ULONG_PTR)PartialDescriptor + EntrySize);
}
-
+
/* The size of full descriptors is bigger */
FinalSize += PartialSize;
-
+
/* Go to the next full descriptor */
FullDescriptor = (PVOID)((ULONG_PTR)FullDescriptor + PartialSize);
}
-
+
/* Return the final size */
return FinalSize;
}
/* This is the format of the returned data */
PIP_RETURN_DATA(sizeof(GUID), &BusTypeGuid);
-
+
case DevicePropertyLegacyBusType:
-
+
/* Validate correct interface type */
if (DeviceNode->ChildInterfaceType == InterfaceTypeUndefined)
return STATUS_OBJECT_NAME_NOT_FOUND;
/* This is the format of the returned data */
PIP_RETURN_DATA(sizeof(INTERFACE_TYPE), &DeviceNode->ChildInterfaceType);
-
+
case DevicePropertyBusNumber:
-
+
/* Validate correct bus number */
if ((DeviceNode->ChildBusNumber & 0x80000000) == 0x80000000)
return STATUS_OBJECT_NAME_NOT_FOUND;
-
+
/* This is the format of the returned data */
PIP_RETURN_DATA(sizeof(ULONG), &DeviceNode->ChildBusNumber);
-
+
case DevicePropertyEnumeratorName:
/* Get the instance path */
DeviceInstanceName = DeviceNode->InstancePath.Buffer;
-
+
/* Sanity checks */
ASSERT((BufferLength & 1) == 0);
ASSERT(DeviceInstanceName != NULL);
-
+
/* Get the name from the path */
EnumeratorNameEnd = wcschr(DeviceInstanceName, OBJ_NAME_PATH_SEPARATOR);
ASSERT(EnumeratorNameEnd);
/* This is the format of the returned data */
PIP_RETURN_DATA((ULONG)(EnumeratorNameEnd - DeviceInstanceName) * sizeof(WCHAR),
DeviceInstanceName);
-
+
case DevicePropertyAddress:
/* Query the device caps */
/* This is the format of the returned data */
PIP_RETURN_DATA(sizeof(ULONG), &DeviceCaps.Address);
-
+
case DevicePropertyBootConfigurationTranslated:
-
+
/* Validate we have resources */
if (!DeviceNode->BootResources)
// if (!DeviceNode->BootResourcesTranslated) // FIXFIX: Need this field
*ResultLength = 0;
return STATUS_SUCCESS;
}
-
+
/* This is the format of the returned data */
PIP_RETURN_DATA(PnpDetermineResourceListSize(DeviceNode->BootResources), // FIXFIX: Should use BootResourcesTranslated
DeviceNode->BootResources); // FIXFIX: Should use BootResourcesTranslated
case DevicePropertyPhysicalDeviceObjectName:
-
+
/* Sanity check for Unicode-sized string */
ASSERT((BufferLength & 1) == 0);
-
+
/* Allocate name buffer */
Length = BufferLength + sizeof(OBJECT_NAME_INFORMATION);
ObjectNameInfo = ExAllocatePool(PagedPool, Length);
if (!ObjectNameInfo) return STATUS_INSUFFICIENT_RESOURCES;
-
+
/* Query the PDO name */
Status = ObQueryNameString(DeviceObject,
ObjectNameInfo,
/* Let the caller know how big the name is */
*ResultLength -= sizeof(OBJECT_NAME_INFORMATION);
break;
-
+
+ case DevicePropertyRemovalPolicy:
+ PIP_RETURN_DATA(sizeof(UCHAR), &DeviceNode->RemovalPolicy);
+
/* Handle the registry-based properties */
case DevicePropertyUINumber:
PIP_REGISTRY_DATA(REGSTR_VAL_UI_NUMBER, REG_DWORD);
case DevicePropertyContainerID:
//PIP_REGISTRY_DATA(REGSTR_VAL_CONTAINERID, REG_SZ); // Win7
PIP_UNIMPLEMENTED();
- case DevicePropertyRemovalPolicy:
- PIP_UNIMPLEMENTED();
+ break;
case DevicePropertyInstallState:
- PIP_UNIMPLEMENTED();
+ PIP_REGISTRY_DATA(REGSTR_VAL_CONFIGFLAGS, REG_DWORD);
+ break;
case DevicePropertyResourceRequirements:
PIP_UNIMPLEMENTED();
case DevicePropertyAllocatedResources:
default:
return STATUS_INVALID_PARAMETER_2;
}
-
+
/* Having a registry value name implies registry data */
if (ValueName)
{
/* We know up-front how much data to expect */
*ResultLength = BufferLength;
-
+
/* Go get the data, use the LogConf subkey if necessary */
Status = PiGetDeviceRegistryProperty(DeviceObject,
ValueType,
/* Terminate the string */
((PWCHAR)PropertyBuffer)[ReturnLength / sizeof(WCHAR)] = UNICODE_NULL;
}
-
+
/* This is the success path */
Status = STATUS_SUCCESS;
}
Status = STATUS_BUFFER_TOO_SMALL;
}
}
-
+
/* Free any allocation we may have made, and return the status code */
if (ObjectNameInfo) ExFreePool(ObjectNameInfo);
return Status;
ULONG PnPFlags;
NTSTATUS Status;
IO_STATUS_BLOCK IoStatusBlock;
-
+
RtlZeroMemory(&Stack, sizeof(IO_STACK_LOCATION));
Stack.MajorFunction = IRP_MJ_PNP;
Stack.MinorFunction = IRP_MN_QUERY_PNP_DEVICE_STATE;
-
+
Status = IopSynchronousCall(PhysicalDeviceObject, &Stack, (PVOID*)&PnPFlags);
if (!NT_SUCCESS(Status))
{
- DPRINT1("IRP_MN_QUERY_PNP_DEVICE_STATE failed with status 0x%x\n", Status);
+ if (Status != STATUS_NOT_SUPPORTED)
+ {
+ DPRINT1("IRP_MN_QUERY_PNP_DEVICE_STATE failed with status 0x%lx\n", Status);
+ }
return;
}
/* Send surprise removal */
IopSendSurpriseRemoval(PhysicalDeviceObject);
-
+
/* Tell the user-mode PnP manager that a device was removed */
IopQueueTargetDeviceEvent(&GUID_DEVICE_SURPRISE_REMOVAL,
&DeviceNode->InstancePath);
-
+
IopSendRemoveDevice(PhysicalDeviceObject);
}
else if ((PnPFlags & PNP_DEVICE_FAILED) && (PnPFlags & PNP_DEVICE_RESOURCE_REQUIREMENTS_CHANGED))
PnPFlags &= ~PNP_DEVICE_RESOURCE_REQUIREMENTS_CHANGED;
}
}
-
+
/* Resource rebalance */
if (PnPFlags & PNP_DEVICE_RESOURCE_REQUIREMENTS_CHANGED)
{
DPRINT("Sending IRP_MN_QUERY_RESOURCES to device stack\n");
-
+
Status = IopInitiatePnpIrp(PhysicalDeviceObject,
&IoStatusBlock,
IRP_MN_QUERY_RESOURCES,
DPRINT("IopInitiatePnpIrp() failed (Status %x) or IoStatusBlock.Information=NULL\n", Status);
DeviceNode->BootResources = NULL;
}
-
+
DPRINT("Sending IRP_MN_QUERY_RESOURCE_REQUIREMENTS to device stack\n");
-
+
Status = IopInitiatePnpIrp(PhysicalDeviceObject,
&IoStatusBlock,
IRP_MN_QUERY_RESOURCE_REQUIREMENTS,
DPRINT("IopInitiatePnpIrp() failed (Status %08lx)\n", Status);
DeviceNode->ResourceRequirements = NULL;
}
-
+
/* IRP_MN_FILTER_RESOURCE_REQUIREMENTS is called indirectly by IopStartDevice */
if (IopStartDevice(DeviceNode) != STATUS_SUCCESS)
{
static WCHAR EnumKeyName[] = L"Enum\\";
static WCHAR DeviceParametersKeyName[] = L"Device Parameters";
ULONG KeyNameLength;
- LPWSTR KeyNameBuffer;
+ PWSTR KeyNameBuffer;
UNICODE_STRING KeyName;
ULONG DriverKeyLength;
OBJECT_ATTRIBUTES ObjectAttributes;
*/
RtlInitUnicodeString(&KeyName, DeviceParametersKeyName);
- InitializeObjectAttributes(&ObjectAttributes, &KeyName,
- OBJ_CASE_INSENSITIVE, *DevInstRegKey, NULL);
- Status = ZwCreateKey(DevInstRegKey, DesiredAccess, &ObjectAttributes,
- 0, NULL, ExpInTextModeSetup ? REG_OPTION_VOLATILE : 0, NULL);
+ InitializeObjectAttributes(&ObjectAttributes,
+ &KeyName,
+ OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE,
+ *DevInstRegKey,
+ NULL);
+ Status = ZwCreateKey(DevInstRegKey,
+ DesiredAccess,
+ &ObjectAttributes,
+ 0,
+ NULL,
+ REG_OPTION_NON_VOLATILE,
+ NULL);
ZwClose(ObjectAttributes.RootDirectory);
return Status;
PDEVICE_NODE ChildDeviceNode, NextDeviceNode, FailedRemoveDevice;
NTSTATUS Status;
KIRQL OldIrql;
-
+
KeAcquireSpinLock(&IopDeviceTreeLock, &OldIrql);
ChildDeviceNode = ParentDeviceNode->Child;
while (ChildDeviceNode != NULL)
{
NextDeviceNode = ChildDeviceNode->Sibling;
KeReleaseSpinLock(&IopDeviceTreeLock, OldIrql);
-
+
Status = IopPrepareDeviceForRemoval(ChildDeviceNode->PhysicalDeviceObject, Force);
if (!NT_SUCCESS(Status))
{
FailedRemoveDevice = ChildDeviceNode;
goto cleanup;
}
-
+
KeAcquireSpinLock(&IopDeviceTreeLock, &OldIrql);
ChildDeviceNode = NextDeviceNode;
}
KeReleaseSpinLock(&IopDeviceTreeLock, OldIrql);
-
+
return STATUS_SUCCESS;
-
+
cleanup:
KeAcquireSpinLock(&IopDeviceTreeLock, &OldIrql);
ChildDeviceNode = ParentDeviceNode->Child;
{
NextDeviceNode = ChildDeviceNode->Sibling;
KeReleaseSpinLock(&IopDeviceTreeLock, OldIrql);
-
+
IopCancelPrepareDeviceForRemoval(ChildDeviceNode->PhysicalDeviceObject);
-
+
/* IRP_MN_CANCEL_REMOVE_DEVICE is also sent to the device
* that failed the IRP_MN_QUERY_REMOVE_DEVICE request */
if (ChildDeviceNode == FailedRemoveDevice)
return Status;
-
+
ChildDeviceNode = NextDeviceNode;
-
+
KeAcquireSpinLock(&IopDeviceTreeLock, &OldIrql);
}
KeReleaseSpinLock(&IopDeviceTreeLock, OldIrql);
-
+
return Status;
}
{
PDEVICE_NODE ChildDeviceNode, NextDeviceNode;
KIRQL OldIrql;
-
+
KeAcquireSpinLock(&IopDeviceTreeLock, &OldIrql);
ChildDeviceNode = ParentDeviceNode->Child;
while (ChildDeviceNode != NULL)
{
NextDeviceNode = ChildDeviceNode->Sibling;
KeReleaseSpinLock(&IopDeviceTreeLock, OldIrql);
-
+
IopSendRemoveDevice(ChildDeviceNode->PhysicalDeviceObject);
-
+
ChildDeviceNode = NextDeviceNode;
-
+
KeAcquireSpinLock(&IopDeviceTreeLock, &OldIrql);
}
KeReleaseSpinLock(&IopDeviceTreeLock, OldIrql);
{
PDEVICE_NODE ChildDeviceNode, NextDeviceNode;
KIRQL OldIrql;
-
+
KeAcquireSpinLock(&IopDeviceTreeLock, &OldIrql);
ChildDeviceNode = ParentDeviceNode->Child;
while (ChildDeviceNode != NULL)
{
NextDeviceNode = ChildDeviceNode->Sibling;
KeReleaseSpinLock(&IopDeviceTreeLock, OldIrql);
-
+
IopCancelPrepareDeviceForRemoval(ChildDeviceNode->PhysicalDeviceObject);
-
+
ChildDeviceNode = NextDeviceNode;
-
+
KeAcquireSpinLock(&IopDeviceTreeLock, &OldIrql);
}
KeReleaseSpinLock(&IopDeviceTreeLock, OldIrql);
{
/* This function DOES NOT dereference the device objects on SUCCESS
* but it DOES dereference device objects on FAILURE */
-
+
ULONG i, j;
NTSTATUS Status;
-
+
for (i = 0; i < DeviceRelations->Count; i++)
{
Status = IopPrepareDeviceForRemoval(DeviceRelations->Objects[i], Force);
goto cleanup;
}
}
-
+
return STATUS_SUCCESS;
-
+
cleanup:
/* IRP_MN_CANCEL_REMOVE_DEVICE is also sent to the device
* that failed the IRP_MN_QUERY_REMOVE_DEVICE request */
DeviceRelations->Objects[i] = NULL;
}
ExFreePool(DeviceRelations);
-
+
return Status;
}
IopSendRemoveDeviceRelations(PDEVICE_RELATIONS DeviceRelations)
{
/* This function DOES dereference the device objects in all cases */
-
+
ULONG i;
-
+
for (i = 0; i < DeviceRelations->Count; i++)
{
IopSendRemoveDevice(DeviceRelations->Objects[i]);
- ObDereferenceObject(DeviceRelations->Objects[i]);
DeviceRelations->Objects[i] = NULL;
}
-
+
ExFreePool(DeviceRelations);
}
IopCancelRemoveDeviceRelations(PDEVICE_RELATIONS DeviceRelations)
{
/* This function DOES dereference the device objects in all cases */
-
+
ULONG i;
-
+
for (i = 0; i < DeviceRelations->Count; i++)
{
IopCancelPrepareDeviceForRemoval(DeviceRelations->Objects[i]);
ObDereferenceObject(DeviceRelations->Objects[i]);
DeviceRelations->Objects[i] = NULL;
}
-
+
ExFreePool(DeviceRelations);
}
IO_STATUS_BLOCK IoStatusBlock;
PDEVICE_RELATIONS DeviceRelations;
NTSTATUS Status;
-
+
IopCancelRemoveDevice(DeviceObject);
-
+
Stack.Parameters.QueryDeviceRelations.Type = RemovalRelations;
-
+
Status = IopInitiatePnpIrp(DeviceObject,
&IoStatusBlock,
IRP_MN_QUERY_DEVICE_RELATIONS,
{
DeviceRelations = (PDEVICE_RELATIONS)IoStatusBlock.Information;
}
-
+
if (DeviceRelations)
IopCancelRemoveDeviceRelations(DeviceRelations);
}
DPRINT1("Removal not allowed for %wZ\n", &DeviceNode->InstancePath);
return STATUS_UNSUCCESSFUL;
}
-
+
if (!Force && IopQueryRemoveDevice(DeviceObject) != STATUS_SUCCESS)
{
DPRINT1("Removal vetoed by failing the query remove request\n");
-
+
IopCancelRemoveDevice(DeviceObject);
-
+
return STATUS_UNSUCCESSFUL;
}
-
+
Stack.Parameters.QueryDeviceRelations.Type = RemovalRelations;
Status = IopInitiatePnpIrp(DeviceObject,
return Status;
}
- DeviceNode->Flags |= DNF_WILL_BE_REMOVED;
- DeviceNode->Problem = CM_PROB_WILL_BE_REMOVED;
if (DeviceRelations)
IopSendRemoveDeviceRelations(DeviceRelations);
IopSendRemoveChildDevices(DeviceNode);
-
+
return STATUS_SUCCESS;
}
IO_STACK_LOCATION Stack;
DEVICE_CAPABILITIES Capabilities;
NTSTATUS Status;
-
+
IopQueueTargetDeviceEvent(&GUID_DEVICE_KERNEL_INITIATED_EJECT,
&DeviceNode->InstancePath);
-
+
if (IopQueryDeviceCapabilities(DeviceNode, &Capabilities) != STATUS_SUCCESS)
{
goto cleanup;
}
-
+
Stack.Parameters.QueryDeviceRelations.Type = EjectionRelations;
-
+
Status = IopInitiatePnpIrp(PhysicalDeviceObject,
&IoStatusBlock,
IRP_MN_QUERY_DEVICE_RELATIONS,
{
DeviceRelations = (PDEVICE_RELATIONS)IoStatusBlock.Information;
}
-
+
if (DeviceRelations)
{
Status = IopQueryRemoveDeviceRelations(DeviceRelations, FALSE);
if (!NT_SUCCESS(Status))
goto cleanup;
}
-
+
Status = IopQueryRemoveChildDevices(DeviceNode, FALSE);
if (!NT_SUCCESS(Status))
{
IopCancelRemoveDeviceRelations(DeviceRelations);
goto cleanup;
}
-
+
if (IopPrepareDeviceForRemoval(PhysicalDeviceObject, FALSE) != STATUS_SUCCESS)
{
if (DeviceRelations)
IopCancelRemoveChildDevices(DeviceNode);
goto cleanup;
}
-
+
if (DeviceRelations)
IopSendRemoveDeviceRelations(DeviceRelations);
IopSendRemoveChildDevices(DeviceNode);
{
DeviceNode->Flags |= DNF_DISABLED;
}
-
+
IopQueueTargetDeviceEvent(&GUID_DEVICE_EJECT,
&DeviceNode->InstancePath);
-
+
return;
-
+
cleanup:
IopQueueTargetDeviceEvent(&GUID_DEVICE_EJECT_VETOED,
&DeviceNode->InstancePath);
IN PDEVICE_OBJECT DeviceObject,
IN DEVICE_RELATION_TYPE Type)
{
- PIO_WORKITEM WorkItem;
- PINVALIDATE_DEVICE_RELATION_DATA Data;
+ PDEVICE_ACTION_DATA Data;
+ KIRQL OldIrql;
- Data = ExAllocatePool(NonPagedPool, sizeof(INVALIDATE_DEVICE_RELATION_DATA));
+ Data = ExAllocatePoolWithTag(NonPagedPool,
+ sizeof(DEVICE_ACTION_DATA),
+ TAG_IO);
if (!Data)
return;
- WorkItem = IoAllocateWorkItem(DeviceObject);
- if (!WorkItem)
- {
- ExFreePool(Data);
- return;
- }
ObReferenceObject(DeviceObject);
Data->DeviceObject = DeviceObject;
Data->Type = Type;
- Data->WorkItem = WorkItem;
- IoQueueWorkItem(
- WorkItem,
- IopAsynchronousInvalidateDeviceRelations,
- DelayedWorkQueue,
- Data);
+ KeAcquireSpinLock(&IopDeviceActionLock, &OldIrql);
+ InsertTailList(&IopDeviceActionRequestList, &Data->RequestListEntry);
+ if (IopDeviceActionInProgress)
+ {
+ KeReleaseSpinLock(&IopDeviceActionLock, OldIrql);
+ return;
+ }
+ IopDeviceActionInProgress = TRUE;
+ KeReleaseSpinLock(&IopDeviceActionLock, OldIrql);
+
+ ExInitializeWorkItem(&IopDeviceActionWorkItem,
+ IopDeviceActionWorker,
+ NULL);
+ ExQueueWorkItem(&IopDeviceActionWorkItem,
+ DelayedWorkQueue);
}
/*
IN DEVICE_RELATION_TYPE Type)
{
PAGED_CODE();
-
+
switch (Type)
{
case BusRelations: