Make IoInvalidateDeviceRelations really asynchronous

Implement IoSynchronousInvalidateDeviceRelations

svn path=/trunk/; revision=24152
This commit is contained in:
Hervé Poussineau 2006-09-16 23:30:57 +00:00
parent 5d0d792e67
commit 68bee00b1d
3 changed files with 206 additions and 226 deletions

View file

@ -558,12 +558,6 @@ IopInitializePnpServices(
IN BOOLEAN BootDrivers) IN BOOLEAN BootDrivers)
; ;
NTSTATUS
IopInvalidateDeviceRelations(
IN PDEVICE_NODE DeviceNode,
IN DEVICE_RELATION_TYPE Type
);
// //
// Initialization Routines // Initialization Routines
// //

View file

@ -448,8 +448,8 @@ IoInit2(BOOLEAN BootLog)
/* /*
* Initialize PnP root releations * Initialize PnP root releations
*/ */
IopInvalidateDeviceRelations( IoInvalidateDeviceRelations(
IopRootDeviceNode, IopRootDeviceNode->PhysicalDeviceObject,
BusRelations); BusRelations);
/* Start boot logging */ /* Start boot logging */

View file

@ -25,11 +25,7 @@ KSPIN_LOCK IopDeviceTreeLock;
PDRIVER_OBJECT IopRootDriverObject; PDRIVER_OBJECT IopRootDriverObject;
PIO_BUS_TYPE_GUID_LIST IopBusTypeGuidList = NULL; PIO_BUS_TYPE_GUID_LIST IopBusTypeGuidList = NULL;
static NTSTATUS INIT_FUNCTION
IopSetRootDeviceInstanceData(PDEVICE_NODE DeviceNode);
#if defined (ALLOC_PRAGMA) #if defined (ALLOC_PRAGMA)
#pragma alloc_text(INIT, IopSetRootDeviceInstanceData)
#pragma alloc_text(INIT, PnpInit) #pragma alloc_text(INIT, PnpInit)
#pragma alloc_text(INIT, PnpInit2) #pragma alloc_text(INIT, PnpInit2)
#pragma alloc_text(INIT, IopUpdateRootKey) #pragma alloc_text(INIT, IopUpdateRootKey)
@ -37,6 +33,18 @@ IopSetRootDeviceInstanceData(PDEVICE_NODE DeviceNode);
#pragma alloc_text(INIT, IopIsAcpiComputer) #pragma alloc_text(INIT, IopIsAcpiComputer)
#endif #endif
typedef struct _INVALIDATE_DEVICE_RELATION_DATA
{
DEVICE_RELATION_TYPE Type;
PIO_WORKITEM WorkItem;
PKEVENT Event;
NTSTATUS Status;
} INVALIDATE_DEVICE_RELATION_DATA, *PINVALIDATE_DEVICE_RELATION_DATA;
static VOID CALLBACK
IopInvalidateDeviceRelations(
IN PDEVICE_OBJECT DeviceObject,
IN PVOID InvalidateContext);
/* FUNCTIONS *****************************************************************/ /* FUNCTIONS *****************************************************************/
@ -66,7 +74,7 @@ IopInitializeDevice(PDEVICE_NODE DeviceNode,
DPRINT("Calling driver AddDevice entrypoint at %08lx\n", DPRINT("Calling driver AddDevice entrypoint at %08lx\n",
DriverObject->DriverExtension->AddDevice); DriverObject->DriverExtension->AddDevice);
IsPnpDriver = (DeviceNode->PhysicalDeviceObject != NULL); IsPnpDriver = !IopDeviceNodeHasFlag(DeviceNode, DNF_LEGACY_DRIVER);
Status = DriverObject->DriverExtension->AddDevice( Status = DriverObject->DriverExtension->AddDevice(
DriverObject, IsPnpDriver ? DeviceNode->PhysicalDeviceObject : NULL); DriverObject, IsPnpDriver ? DeviceNode->PhysicalDeviceObject : NULL);
@ -139,7 +147,7 @@ IopStartDevice(
if (IopDeviceNodeHasFlag(DeviceNode, DNF_NEED_ENUMERATION_ONLY)) if (IopDeviceNodeHasFlag(DeviceNode, DNF_NEED_ENUMERATION_ONLY))
{ {
DPRINT("Device needs enumeration, invalidating bus relations\n"); DPRINT("Device needs enumeration, invalidating bus relations\n");
Status = IopInvalidateDeviceRelations(DeviceNode, BusRelations); IoInvalidateDeviceRelations(DeviceNode->PhysicalDeviceObject, BusRelations);
IopDeviceNodeClearFlag(DeviceNode, DNF_NEED_ENUMERATION_ONLY); IopDeviceNodeClearFlag(DeviceNode, DNF_NEED_ENUMERATION_ONLY);
} }
} }
@ -178,31 +186,13 @@ IopQueryDeviceCapabilities(PDEVICE_NODE DeviceNode,
&Stack); &Stack);
} }
typedef struct _INVALIDATE_DEVICE_RELATION_DATA
{
DEVICE_RELATION_TYPE Type;
PIO_WORKITEM WorkItem;
} INVALIDATE_DEVICE_RELATION_DATA, *PINVALIDATE_DEVICE_RELATION_DATA;
static VOID
NTAPI
IoInvalidateDeviceRelationsWorker(
IN PDEVICE_OBJECT DeviceObject,
IN PVOID Context)
{
PINVALIDATE_DEVICE_RELATION_DATA Data = Context;
IopInvalidateDeviceRelations(IopGetDeviceNode(DeviceObject), Data->Type);
IoFreeWorkItem(Data->WorkItem);
ExFreePool(Data);
}
/* /*
* @implemented * @implemented
*/ */
VOID VOID
STDCALL NTAPI
IoInvalidateDeviceRelations(IN PDEVICE_OBJECT DeviceObject, IoInvalidateDeviceRelations(
IN PDEVICE_OBJECT DeviceObject,
IN DEVICE_RELATION_TYPE Type) IN DEVICE_RELATION_TYPE Type)
{ {
PIO_WORKITEM WorkItem; PIO_WORKITEM WorkItem;
@ -220,23 +210,51 @@ IoInvalidateDeviceRelations(IN PDEVICE_OBJECT DeviceObject,
Data->Type = Type; Data->Type = Type;
Data->WorkItem = WorkItem; Data->WorkItem = WorkItem;
Data->Event = NULL;
IoQueueWorkItem( IoQueueWorkItem(
WorkItem, WorkItem,
IoInvalidateDeviceRelationsWorker, IopInvalidateDeviceRelations,
DelayedWorkQueue, DelayedWorkQueue,
Data); Data);
} }
/* /*
* @unimplemented * @implemented
*/ */
VOID VOID
STDCALL NTAPI
IoSynchronousInvalidateDeviceRelations(IN PDEVICE_OBJECT DeviceObject, IoSynchronousInvalidateDeviceRelations(
IN PDEVICE_OBJECT DeviceObject,
IN DEVICE_RELATION_TYPE Type) IN DEVICE_RELATION_TYPE Type)
{ {
UNIMPLEMENTED; PIO_WORKITEM WorkItem;
PINVALIDATE_DEVICE_RELATION_DATA Data;
KEVENT Event;
Data = ExAllocatePool(PagedPool, sizeof(INVALIDATE_DEVICE_RELATION_DATA));
if (!Data)
return;
WorkItem = IoAllocateWorkItem(DeviceObject);
if (!WorkItem)
{
ExFreePool(Data);
return;
}
KeInitializeEvent(&Event, NotificationEvent, FALSE);
Data->Type = Type;
Data->WorkItem = WorkItem;
Data->Event = &Event;
IoQueueWorkItem(
WorkItem,
IopInvalidateDeviceRelations,
DelayedWorkQueue,
Data);
KeWaitForSingleObject(&Event, Executive, KernelMode, FALSE, NULL);
ExFreePool(Data);
} }
/* /*
@ -2346,11 +2364,18 @@ IopInitializePnpServices(IN PDEVICE_NODE DeviceNode,
return IopTraverseDeviceTree(&Context); return IopTraverseDeviceTree(&Context);
} }
/* Invalidate device list enumerated by a device node.
NTSTATUS * The call can be make synchronous by defining the Event field
IopInvalidateDeviceRelations(IN PDEVICE_NODE DeviceNode, * of the INVALIDATE_DEVICE_RELATION_DATA structure
IN DEVICE_RELATION_TYPE Type) */
static VOID CALLBACK
IopInvalidateDeviceRelations(
IN PDEVICE_OBJECT DeviceObject,
IN PVOID InvalidateContext) /* PINVALIDATE_DEVICE_RELATION_DATA */
{ {
PINVALIDATE_DEVICE_RELATION_DATA Data = InvalidateContext;
PDEVICE_NODE DeviceNode = IopGetDeviceNode(DeviceObject);
PKEVENT Event = Data->Event;
DEVICETREE_TRAVERSE_CONTEXT Context; DEVICETREE_TRAVERSE_CONTEXT Context;
PDEVICE_RELATIONS DeviceRelations; PDEVICE_RELATIONS DeviceRelations;
IO_STATUS_BLOCK IoStatusBlock; IO_STATUS_BLOCK IoStatusBlock;
@ -2358,38 +2383,39 @@ IopInvalidateDeviceRelations(IN PDEVICE_NODE DeviceNode,
IO_STACK_LOCATION Stack; IO_STACK_LOCATION Stack;
BOOLEAN BootDrivers; BOOLEAN BootDrivers;
OBJECT_ATTRIBUTES ObjectAttributes; OBJECT_ATTRIBUTES ObjectAttributes;
UNICODE_STRING LinkName; UNICODE_STRING LinkName = RTL_CONSTANT_STRING(L"\\SystemRoot");
HANDLE Handle; HANDLE Handle;
NTSTATUS Status; NTSTATUS Status;
ULONG i; ULONG i;
DPRINT("DeviceNode 0x%p, Type %d\n", DeviceNode, Type); DPRINT("DeviceObject 0x%p, Type %d\n", DeviceObject, Type);
DPRINT("Sending IRP_MN_QUERY_DEVICE_RELATIONS to device stack\n"); DPRINT("Sending IRP_MN_QUERY_DEVICE_RELATIONS to device stack\n");
Stack.Parameters.QueryDeviceRelations.Type = Type/*BusRelations*/; Stack.Parameters.QueryDeviceRelations.Type = Data->Type;
Status = IopInitiatePnpIrp( Status = IopInitiatePnpIrp(
DeviceNode->PhysicalDeviceObject, DeviceObject,
&IoStatusBlock, &IoStatusBlock,
IRP_MN_QUERY_DEVICE_RELATIONS, IRP_MN_QUERY_DEVICE_RELATIONS,
&Stack); &Stack);
if (!NT_SUCCESS(Status)) if (!NT_SUCCESS(Status))
{ {
DPRINT("IopInitiatePnpIrp() failed\n"); DPRINT("IopInitiatePnpIrp() failed with status 0x%08lx\n", Status);
return Status; goto cleanup;
} }
DeviceRelations = (PDEVICE_RELATIONS)IoStatusBlock.Information; DeviceRelations = (PDEVICE_RELATIONS)IoStatusBlock.Information;
if ((!DeviceRelations) || (DeviceRelations->Count <= 0)) if (!DeviceRelations || DeviceRelations->Count <= 0)
{ {
DPRINT("No PDOs\n"); DPRINT("No PDOs\n");
if (DeviceRelations) if (DeviceRelations)
{ {
ExFreePool(DeviceRelations); ExFreePool(DeviceRelations);
} }
return STATUS_SUCCESS; Status = STATUS_SUCCESS;
goto cleanup;
} }
DPRINT("Got %d PDOs\n", DeviceRelations->Count); DPRINT("Got %d PDOs\n", DeviceRelations->Count);
@ -2397,7 +2423,6 @@ IopInvalidateDeviceRelations(IN PDEVICE_NODE DeviceNode,
/* /*
* Create device nodes for all discovered devices * Create device nodes for all discovered devices
*/ */
for (i = 0; i < DeviceRelations->Count; i++) for (i = 0; i < DeviceRelations->Count; i++)
{ {
Status = IopCreateDeviceNode( Status = IopCreateDeviceNode(
@ -2411,7 +2436,8 @@ IopInvalidateDeviceRelations(IN PDEVICE_NODE DeviceNode,
for (i = 0; i < DeviceRelations->Count; i++) for (i = 0; i < DeviceRelations->Count; i++)
ObDereferenceObject(DeviceRelations->Objects[i]); ObDereferenceObject(DeviceRelations->Objects[i]);
ExFreePool(DeviceRelations); ExFreePool(DeviceRelations);
return STATUS_INSUFFICIENT_RESOURCES; Status = STATUS_NO_MEMORY;
goto cleanup;
} }
} }
ExFreePool(DeviceRelations); ExFreePool(DeviceRelations);
@ -2419,7 +2445,6 @@ IopInvalidateDeviceRelations(IN PDEVICE_NODE DeviceNode,
/* /*
* Retrieve information about all discovered children from the bus driver * Retrieve information about all discovered children from the bus driver
*/ */
IopInitDeviceTreeTraverseContext( IopInitDeviceTreeTraverseContext(
&Context, &Context,
DeviceNode, DeviceNode,
@ -2429,14 +2454,13 @@ IopInvalidateDeviceRelations(IN PDEVICE_NODE DeviceNode,
Status = IopTraverseDeviceTree(&Context); Status = IopTraverseDeviceTree(&Context);
if (!NT_SUCCESS(Status)) if (!NT_SUCCESS(Status))
{ {
DPRINT("IopTraverseDeviceTree() failed with status (%x)\n", Status); DPRINT("IopTraverseDeviceTree() failed with status 0x%08lx\n", Status);
return Status; goto cleanup;
} }
/* /*
* Retrieve configuration from the registry for discovered children * Retrieve configuration from the registry for discovered children
*/ */
IopInitDeviceTreeTraverseContext( IopInitDeviceTreeTraverseContext(
&Context, &Context,
DeviceNode, DeviceNode,
@ -2446,8 +2470,8 @@ IopInvalidateDeviceRelations(IN PDEVICE_NODE DeviceNode,
Status = IopTraverseDeviceTree(&Context); Status = IopTraverseDeviceTree(&Context);
if (!NT_SUCCESS(Status)) if (!NT_SUCCESS(Status))
{ {
DPRINT("IopTraverseDeviceTree() failed with status (%x)\n", Status); DPRINT("IopTraverseDeviceTree() failed with status 0x%08lx\n", Status);
return Status; goto cleanup;
} }
/* /*
@ -2455,16 +2479,12 @@ IopInvalidateDeviceRelations(IN PDEVICE_NODE DeviceNode,
* created yet, we will assume that it's possible to load only boot * created yet, we will assume that it's possible to load only boot
* drivers. * drivers.
*/ */
RtlInitUnicodeString(&LinkName, L"\\SystemRoot");
InitializeObjectAttributes( InitializeObjectAttributes(
&ObjectAttributes, &ObjectAttributes,
&LinkName, &LinkName,
0, 0,
NULL, NULL,
NULL); NULL);
Status = ZwOpenFile( Status = ZwOpenFile(
&Handle, &Handle,
FILE_ALL_ACCESS, FILE_ALL_ACCESS,
@ -2484,53 +2504,27 @@ IopInvalidateDeviceRelations(IN PDEVICE_NODE DeviceNode,
* Initialize services for discovered children. Only boot drivers will * Initialize services for discovered children. Only boot drivers will
* be loaded from boot driver! * be loaded from boot driver!
*/ */
Status = IopInitializePnpServices(DeviceNode, BootDrivers); Status = IopInitializePnpServices(DeviceNode, BootDrivers);
if (!NT_SUCCESS(Status)) if (!NT_SUCCESS(Status))
{ {
DPRINT("IopInitializePnpServices() failed with status (%x)\n", Status); DPRINT("IopInitializePnpServices() failed with status 0x%08lx\n", Status);
return Status; goto cleanup;
} }
DPRINT("IopInvalidateDeviceRelations() finished\n"); DPRINT("IopInvalidateDeviceRelations() finished\n");
return STATUS_SUCCESS; Status = STATUS_SUCCESS;
}
cleanup:
static IoFreeWorkItem(Data->WorkItem);
NTSTATUS if (Event)
INIT_FUNCTION
IopSetRootDeviceInstanceData(PDEVICE_NODE DeviceNode)
{ {
#if 0 Data->Status = Status;
PWSTR KeyBuffer; KeSetEvent(Event, 0, FALSE);
HANDLE InstanceKey = NULL;
NTSTATUS Status;
/* Create registry key for the instance id, if it doesn't exist yet */
KeyBuffer = ExAllocatePool(PagedPool,
(49 * sizeof(WCHAR)) + DeviceNode->InstancePath.Length);
wcscpy(KeyBuffer, L"\\Registry\\Machine\\System\\CurrentControlSet\\Enum\\");
wcscat(KeyBuffer, DeviceNode->InstancePath.Buffer);
Status = IopCreateDeviceKeyPath(KeyBuffer,
&InstanceKey);
ExFreePool(KeyBuffer);
if (!NT_SUCCESS(Status))
{
DPRINT1("Failed to create the instance key! (Status %lx)\n", Status);
return Status;
} }
else
/* FIXME: Set 'ConfigFlags' value */ ExFreePool(Data);
ZwClose(InstanceKey);
return Status;
#endif
return STATUS_SUCCESS;
} }
VOID INIT_FUNCTION VOID INIT_FUNCTION
PnpInit(VOID) PnpInit(VOID)
{ {
@ -2584,7 +2578,7 @@ PnpInit(VOID)
L"HTREE\\ROOT\\0")) L"HTREE\\ROOT\\0"))
{ {
CPRINT("Failed to create the instance path!\n"); CPRINT("Failed to create the instance path!\n");
KEBUGCHECKEX(PHASE1_INITIALIZATION_FAILED, STATUS_UNSUCCESSFUL, 0, 0, 0); KEBUGCHECKEX(PHASE1_INITIALIZATION_FAILED, STATUS_NO_MEMORY, 0, 0, 0);
} }
/* Report the device to the user-mode pnp manager */ /* Report the device to the user-mode pnp manager */
@ -3141,14 +3135,6 @@ PnpInit2(VOID)
CPRINT("IopUpdateRootKey() failed\n"); CPRINT("IopUpdateRootKey() failed\n");
KEBUGCHECKEX(PHASE1_INITIALIZATION_FAILED, Status, 0, 0, 0); KEBUGCHECKEX(PHASE1_INITIALIZATION_FAILED, Status, 0, 0, 0);
} }
/* Set root device instance data */
Status = IopSetRootDeviceInstanceData(IopRootDeviceNode);
if (!NT_SUCCESS(Status))
{
CPRINT("Failed to set instance data\n");
KEBUGCHECKEX(PHASE1_INITIALIZATION_FAILED, Status, 0, 0, 0);
}
} }
/* EOF */ /* EOF */