[NTOS:IO] Improve the device action worker

- Improve the device action worker to support more than just a single action
- Move the action queue code from IoInvalidateDeviceRelations to a new function IopQueueDeviceAction.
This commit is contained in:
Eric Kohl 2020-03-01 23:29:23 +01:00
parent 74eda39118
commit 9a07cde37f
2 changed files with 85 additions and 35 deletions

View file

@ -538,6 +538,29 @@ typedef enum _SECURITY_DESCRIPTOR_TYPE
SystemDefault,
} SECURITY_DESCRIPTOR_TYPE, *PSECURITY_DESCRIPTOR_TYPE;
//
// Action types and data for IopQueueDeviceAction()
//
typedef enum _DEVICE_ACTION
{
DeviceActionInvalidateDeviceRelations,
MaxDeviceAction
} DEVICE_ACTION;
typedef struct _DEVICE_ACTION_DATA
{
LIST_ENTRY RequestListEntry;
PDEVICE_OBJECT DeviceObject;
DEVICE_ACTION Action;
union
{
struct
{
DEVICE_RELATION_TYPE Type;
} InvalidateDeviceRelations;
};
} DEVICE_ACTION_DATA, *PDEVICE_ACTION_DATA;
//
// Resource code
//
@ -1398,6 +1421,14 @@ IopStoreSystemPartitionInformation(IN PUNICODE_STRING NtSystemPartitionDeviceNam
IN PUNICODE_STRING OsLoaderPathName
);
//
// Device action
//
VOID
IopQueueDeviceAction(
_In_ PDEVICE_ACTION_DATA ActionData
);
//
// Global I/O Data
//

View file

@ -38,14 +38,8 @@ WORK_QUEUE_ITEM IopDeviceActionWorkItem;
BOOLEAN IopDeviceActionInProgress;
KSPIN_LOCK IopDeviceActionLock;
typedef struct _DEVICE_ACTION_DATA
{
LIST_ENTRY RequestListEntry;
PDEVICE_OBJECT DeviceObject;
DEVICE_RELATION_TYPE Type;
} DEVICE_ACTION_DATA, *PDEVICE_ACTION_DATA;
/* FUNCTIONS *****************************************************************/
NTSTATUS
NTAPI
IopCreateDeviceKeyPath(IN PCUNICODE_STRING RegistryPath,
@ -1073,8 +1067,17 @@ IopDeviceActionWorker(
DEVICE_ACTION_DATA,
RequestListEntry);
IoSynchronousInvalidateDeviceRelations(Data->DeviceObject,
Data->Type);
switch (Data->Action)
{
case DeviceActionInvalidateDeviceRelations:
IoSynchronousInvalidateDeviceRelations(Data->DeviceObject,
Data->InvalidateDeviceRelations.Type);
break;
default:
DPRINT1("Unimplemented device action %u\n", Data->Action);
break;
}
ObDereferenceObject(Data->DeviceObject);
ExFreePoolWithTag(Data, TAG_IO);
@ -1084,6 +1087,43 @@ IopDeviceActionWorker(
KeReleaseSpinLock(&IopDeviceActionLock, OldIrql);
}
VOID
IopQueueDeviceAction(
_In_ PDEVICE_ACTION_DATA ActionData)
{
PDEVICE_ACTION_DATA Data;
KIRQL OldIrql;
DPRINT("IopQueueDeviceAction(%p)\n", ActionData);
Data = ExAllocatePoolWithTag(NonPagedPool,
sizeof(DEVICE_ACTION_DATA),
TAG_IO);
if (!Data)
return;
ObReferenceObject(ActionData->DeviceObject);
RtlCopyMemory(Data, ActionData, sizeof(DEVICE_ACTION_DATA));
DPRINT("Action %u\n", Data->Action);
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);
}
NTSTATUS
IopGetSystemPowerDeviceObject(PDEVICE_OBJECT *DeviceObject)
{
@ -5112,34 +5152,13 @@ IoInvalidateDeviceRelations(
IN PDEVICE_OBJECT DeviceObject,
IN DEVICE_RELATION_TYPE Type)
{
PDEVICE_ACTION_DATA Data;
KIRQL OldIrql;
DEVICE_ACTION_DATA ActionData;
Data = ExAllocatePoolWithTag(NonPagedPool,
sizeof(DEVICE_ACTION_DATA),
TAG_IO);
if (!Data)
return;
ActionData.DeviceObject = DeviceObject;
ActionData.Action = DeviceActionInvalidateDeviceRelations;
ActionData.InvalidateDeviceRelations.Type = Type;
ObReferenceObject(DeviceObject);
Data->DeviceObject = DeviceObject;
Data->Type = Type;
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);
IopQueueDeviceAction(&ActionData);
}
/*