ntoskrnl.exe: Implement Ke(Initialize|Insert|Remove)DeviceQueue.
Signed-off-by: Rémi Bernon <rbernon@codeweavers.com> Signed-off-by: Zebediah Figura <zfigura@codeweavers.com> Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
parent
0f48202335
commit
2862ff6ba7
|
@ -567,7 +567,7 @@
|
||||||
@ stub KeI386SetGdtSelector
|
@ stub KeI386SetGdtSelector
|
||||||
@ stub KeIcacheFlushCount
|
@ stub KeIcacheFlushCount
|
||||||
@ stdcall KeInitializeApc(ptr ptr long ptr ptr ptr long ptr)
|
@ stdcall KeInitializeApc(ptr ptr long ptr ptr ptr long ptr)
|
||||||
@ stub KeInitializeDeviceQueue
|
@ stdcall KeInitializeDeviceQueue(ptr)
|
||||||
@ stdcall KeInitializeDpc(ptr ptr ptr)
|
@ stdcall KeInitializeDpc(ptr ptr ptr)
|
||||||
@ stdcall KeInitializeEvent(ptr long long)
|
@ stdcall KeInitializeEvent(ptr long long)
|
||||||
@ stub KeInitializeInterrupt
|
@ stub KeInitializeInterrupt
|
||||||
|
@ -579,7 +579,7 @@
|
||||||
@ stdcall KeInitializeTimer(ptr)
|
@ stdcall KeInitializeTimer(ptr)
|
||||||
@ stdcall KeInitializeTimerEx(ptr long)
|
@ stdcall KeInitializeTimerEx(ptr long)
|
||||||
@ stub KeInsertByKeyDeviceQueue
|
@ stub KeInsertByKeyDeviceQueue
|
||||||
@ stub KeInsertDeviceQueue
|
@ stdcall KeInsertDeviceQueue(ptr ptr)
|
||||||
@ stub KeInsertHeadQueue
|
@ stub KeInsertHeadQueue
|
||||||
@ stdcall KeInsertQueue(ptr ptr)
|
@ stdcall KeInsertQueue(ptr ptr)
|
||||||
@ stub KeInsertQueueApc
|
@ stub KeInsertQueueApc
|
||||||
|
@ -617,7 +617,7 @@
|
||||||
@ stdcall KeReleaseSpinLockFromDpcLevel(ptr)
|
@ stdcall KeReleaseSpinLockFromDpcLevel(ptr)
|
||||||
@ stub KeRemoveByKeyDeviceQueue
|
@ stub KeRemoveByKeyDeviceQueue
|
||||||
@ stub KeRemoveByKeyDeviceQueueIfBusy
|
@ stub KeRemoveByKeyDeviceQueueIfBusy
|
||||||
@ stub KeRemoveDeviceQueue
|
@ stdcall KeRemoveDeviceQueue(ptr)
|
||||||
@ stub KeRemoveEntryDeviceQueue
|
@ stub KeRemoveEntryDeviceQueue
|
||||||
@ stub KeRemoveQueue
|
@ stub KeRemoveQueue
|
||||||
@ stub KeRemoveQueueDpc
|
@ stub KeRemoveQueueDpc
|
||||||
|
|
|
@ -1362,3 +1362,50 @@ BOOLEAN WINAPI KeSetTimer(KTIMER *timer, LARGE_INTEGER duetime, KDPC *dpc)
|
||||||
|
|
||||||
return KeSetTimerEx(timer, duetime, 0, dpc);
|
return KeSetTimerEx(timer, duetime, 0, dpc);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void WINAPI KeInitializeDeviceQueue( KDEVICE_QUEUE *queue )
|
||||||
|
{
|
||||||
|
TRACE( "queue %p.\n", queue );
|
||||||
|
|
||||||
|
KeInitializeSpinLock( &queue->Lock );
|
||||||
|
InitializeListHead( &queue->DeviceListHead );
|
||||||
|
queue->Busy = FALSE;
|
||||||
|
queue->Type = IO_TYPE_DEVICE_QUEUE;
|
||||||
|
queue->Size = sizeof(*queue);
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOLEAN WINAPI KeInsertDeviceQueue( KDEVICE_QUEUE *queue, KDEVICE_QUEUE_ENTRY *entry )
|
||||||
|
{
|
||||||
|
BOOL insert;
|
||||||
|
KIRQL irql;
|
||||||
|
|
||||||
|
TRACE( "queue %p, entry %p.\n", queue, entry );
|
||||||
|
|
||||||
|
KeAcquireSpinLock( &queue->Lock, &irql );
|
||||||
|
insert = entry->Inserted = queue->Busy;
|
||||||
|
if (insert) InsertTailList( &queue->DeviceListHead, &entry->DeviceListEntry );
|
||||||
|
queue->Busy = TRUE;
|
||||||
|
KeReleaseSpinLock( &queue->Lock, irql );
|
||||||
|
|
||||||
|
return insert;
|
||||||
|
}
|
||||||
|
|
||||||
|
KDEVICE_QUEUE_ENTRY *WINAPI KeRemoveDeviceQueue( KDEVICE_QUEUE *queue )
|
||||||
|
{
|
||||||
|
KDEVICE_QUEUE_ENTRY *entry = NULL;
|
||||||
|
KIRQL irql;
|
||||||
|
|
||||||
|
TRACE( "queue %p.\n", queue );
|
||||||
|
|
||||||
|
KeAcquireSpinLock( &queue->Lock, &irql );
|
||||||
|
if (IsListEmpty( &queue->DeviceListHead )) queue->Busy = FALSE;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
entry = CONTAINING_RECORD( RemoveHeadList( &queue->DeviceListHead ),
|
||||||
|
KDEVICE_QUEUE_ENTRY, DeviceListEntry );
|
||||||
|
entry->Inserted = FALSE;
|
||||||
|
}
|
||||||
|
KeReleaseSpinLock( &queue->Lock, irql );
|
||||||
|
|
||||||
|
return entry;
|
||||||
|
}
|
||||||
|
|
|
@ -141,6 +141,133 @@ static void test_irp_struct(IRP *irp, DEVICE_OBJECT *device)
|
||||||
IoFreeIrp(irp);
|
IoFreeIrp(irp);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int cancel_queue_cnt;
|
||||||
|
|
||||||
|
static void WINAPI cancel_queued_irp(DEVICE_OBJECT *device, IRP *irp)
|
||||||
|
{
|
||||||
|
IoReleaseCancelSpinLock(irp->CancelIrql);
|
||||||
|
ok(irp->Cancel == TRUE, "Cancel = %x\n", irp->Cancel);
|
||||||
|
ok(!irp->CancelRoutine, "CancelRoutine = %p\n", irp->CancelRoutine);
|
||||||
|
irp->IoStatus.Status = STATUS_CANCELLED;
|
||||||
|
irp->IoStatus.Information = 0;
|
||||||
|
cancel_queue_cnt++;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void test_queue(void)
|
||||||
|
{
|
||||||
|
KDEVICE_QUEUE_ENTRY *entry;
|
||||||
|
KDEVICE_QUEUE queue;
|
||||||
|
BOOLEAN ret;
|
||||||
|
KIRQL irql;
|
||||||
|
IRP *irp;
|
||||||
|
|
||||||
|
irp = IoAllocateIrp(1, FALSE);
|
||||||
|
|
||||||
|
memset(&queue, 0xcd, sizeof(queue));
|
||||||
|
KeInitializeDeviceQueue(&queue);
|
||||||
|
ok(!queue.Busy, "unexpected Busy state\n");
|
||||||
|
ok(queue.Size == sizeof(queue), "unexpected Size %x\n", queue.Size);
|
||||||
|
ok(queue.Type == IO_TYPE_DEVICE_QUEUE, "unexpected Type %x\n", queue.Type);
|
||||||
|
ok(IsListEmpty(&queue.DeviceListHead), "expected empty queue list\n");
|
||||||
|
|
||||||
|
ret = KeInsertDeviceQueue(&queue, &irp->Tail.Overlay.DeviceQueueEntry);
|
||||||
|
ok(!ret, "expected KeInsertDeviceQueue to not insert IRP\n");
|
||||||
|
ok(queue.Busy, "expected Busy state\n");
|
||||||
|
ok(IsListEmpty(&queue.DeviceListHead), "expected empty queue list\n");
|
||||||
|
ok(!irp->Tail.Overlay.DeviceQueueEntry.Inserted, "expected not inserted\n");
|
||||||
|
|
||||||
|
entry = KeRemoveDeviceQueue(&queue);
|
||||||
|
ok(!entry, "expected KeRemoveDeviceQueue to return NULL\n");
|
||||||
|
ok(!queue.Busy, "unexpected Busy state\n");
|
||||||
|
ok(IsListEmpty(&queue.DeviceListHead), "expected empty queue list\n");
|
||||||
|
ok(!irp->Tail.Overlay.DeviceQueueEntry.Inserted, "expected not inserted\n");
|
||||||
|
|
||||||
|
ret = KeInsertDeviceQueue(&queue, &irp->Tail.Overlay.DeviceQueueEntry);
|
||||||
|
ok(!ret, "expected KeInsertDeviceQueue to not insert IRP\n");
|
||||||
|
ok(queue.Busy, "expected Busy state\n");
|
||||||
|
ok(IsListEmpty(&queue.DeviceListHead), "expected empty queue list\n");
|
||||||
|
ok(!irp->Tail.Overlay.DeviceQueueEntry.Inserted, "expected not inserted\n");
|
||||||
|
|
||||||
|
ret = KeInsertDeviceQueue(&queue, &irp->Tail.Overlay.DeviceQueueEntry);
|
||||||
|
ok(ret, "expected KeInsertDeviceQueue to insert IRP\n");
|
||||||
|
ok(queue.Busy, "expected Busy state\n");
|
||||||
|
ok(!IsListEmpty(&queue.DeviceListHead), "unexpected empty queue list\n");
|
||||||
|
ok(irp->Tail.Overlay.DeviceQueueEntry.Inserted, "expected inserted\n");
|
||||||
|
ok(queue.DeviceListHead.Flink == &irp->Tail.Overlay.DeviceQueueEntry.DeviceListEntry,
|
||||||
|
"unexpected queue list head\n");
|
||||||
|
|
||||||
|
entry = KeRemoveDeviceQueue(&queue);
|
||||||
|
ok(entry != NULL, "expected KeRemoveDeviceQueue to return non-NULL\n");
|
||||||
|
ok(CONTAINING_RECORD(entry, IRP, Tail.Overlay.DeviceQueueEntry) == irp,
|
||||||
|
"unexpected IRP returned\n");
|
||||||
|
ok(queue.Busy, "expected Busy state\n");
|
||||||
|
ok(IsListEmpty(&queue.DeviceListHead), "expected empty queue list\n");
|
||||||
|
ok(!irp->Tail.Overlay.DeviceQueueEntry.Inserted, "expected not inserted\n");
|
||||||
|
|
||||||
|
entry = KeRemoveDeviceQueue(&queue);
|
||||||
|
ok(entry == NULL, "expected KeRemoveDeviceQueue to return NULL\n");
|
||||||
|
ok(!queue.Busy, "unexpected Busy state\n");
|
||||||
|
ok(IsListEmpty(&queue.DeviceListHead), "expected empty queue list\n");
|
||||||
|
ok(!irp->Tail.Overlay.DeviceQueueEntry.Inserted, "expected not inserted\n");
|
||||||
|
|
||||||
|
IoCancelIrp(irp);
|
||||||
|
ok(irp->Cancel, "unexpected non-cancelled state\n");
|
||||||
|
|
||||||
|
ret = KeInsertDeviceQueue(&queue, &irp->Tail.Overlay.DeviceQueueEntry);
|
||||||
|
ok(!ret, "expected KeInsertDeviceQueue to not insert IRP\n");
|
||||||
|
ok(queue.Busy, "expected Busy state\n");
|
||||||
|
ok(IsListEmpty(&queue.DeviceListHead), "expected empty queue list\n");
|
||||||
|
ok(!irp->Tail.Overlay.DeviceQueueEntry.Inserted, "expected inserted\n");
|
||||||
|
ret = KeInsertDeviceQueue(&queue, &irp->Tail.Overlay.DeviceQueueEntry);
|
||||||
|
ok(ret, "expected KeInsertDeviceQueue to insert IRP\n");
|
||||||
|
ok(queue.Busy, "expected Busy state\n");
|
||||||
|
ok(!IsListEmpty(&queue.DeviceListHead), "unexpected empty queue list\n");
|
||||||
|
ok(irp->Tail.Overlay.DeviceQueueEntry.Inserted, "expected inserted\n");
|
||||||
|
ok(queue.DeviceListHead.Flink == &irp->Tail.Overlay.DeviceQueueEntry.DeviceListEntry,
|
||||||
|
"unexpected queue list head\n");
|
||||||
|
|
||||||
|
entry = KeRemoveDeviceQueue(&queue);
|
||||||
|
ok(entry != NULL, "expected KeRemoveDeviceQueue to return non-NULL\n");
|
||||||
|
ok(CONTAINING_RECORD(entry, IRP, Tail.Overlay.DeviceQueueEntry) == irp,
|
||||||
|
"unexpected IRP returned\n");
|
||||||
|
ok(queue.Busy, "expected Busy state\n");
|
||||||
|
ok(IsListEmpty(&queue.DeviceListHead), "expected empty queue list\n");
|
||||||
|
ok(!irp->Tail.Overlay.DeviceQueueEntry.Inserted, "expected inserted\n");
|
||||||
|
ok(irp->Cancel, "unexpected non-cancelled state\n");
|
||||||
|
|
||||||
|
IoFreeIrp(irp);
|
||||||
|
|
||||||
|
irp = IoAllocateIrp(1, FALSE);
|
||||||
|
|
||||||
|
IoAcquireCancelSpinLock(&irql);
|
||||||
|
IoSetCancelRoutine(irp, cancel_queued_irp);
|
||||||
|
IoReleaseCancelSpinLock(irql);
|
||||||
|
|
||||||
|
ret = KeInsertDeviceQueue(&queue, &irp->Tail.Overlay.DeviceQueueEntry);
|
||||||
|
ok(ret, "expected KeInsertDeviceQueue to insert IRP\n");
|
||||||
|
ok(queue.Busy, "expected Busy state\n");
|
||||||
|
ok(!IsListEmpty(&queue.DeviceListHead), "expected empty queue list\n");
|
||||||
|
ok(irp->Tail.Overlay.DeviceQueueEntry.Inserted, "expected inserted\n");
|
||||||
|
ok(queue.DeviceListHead.Flink == &irp->Tail.Overlay.DeviceQueueEntry.DeviceListEntry,
|
||||||
|
"unexpected queue list head\n");
|
||||||
|
|
||||||
|
IoCancelIrp(irp);
|
||||||
|
ok(irp->Cancel, "unexpected non-cancelled state\n");
|
||||||
|
ok(cancel_queue_cnt, "expected cancel routine to be called\n");
|
||||||
|
|
||||||
|
entry = KeRemoveDeviceQueue(&queue);
|
||||||
|
ok(entry != NULL, "expected KeRemoveDeviceQueue to return non-NULL\n");
|
||||||
|
ok(CONTAINING_RECORD(entry, IRP, Tail.Overlay.DeviceQueueEntry) == irp,
|
||||||
|
"unexpected IRP returned\n");
|
||||||
|
ok(irp->Cancel, "unexpected non-cancelled state\n");
|
||||||
|
ok(cancel_queue_cnt, "expected cancel routine to be called\n");
|
||||||
|
ok(queue.Busy, "expected Busy state\n");
|
||||||
|
ok(IsListEmpty(&queue.DeviceListHead), "expected empty queue list\n");
|
||||||
|
ok(!irp->Tail.Overlay.DeviceQueueEntry.Inserted, "expected inserted\n");
|
||||||
|
|
||||||
|
IoFreeIrp(irp);
|
||||||
|
}
|
||||||
|
|
||||||
static void test_mdl_map(void)
|
static void test_mdl_map(void)
|
||||||
{
|
{
|
||||||
char buffer[20] = "test buffer";
|
char buffer[20] = "test buffer";
|
||||||
|
@ -2128,6 +2255,7 @@ static NTSTATUS main_test(DEVICE_OBJECT *device, IRP *irp, IO_STACK_LOCATION *st
|
||||||
test_init_funcs();
|
test_init_funcs();
|
||||||
test_load_driver();
|
test_load_driver();
|
||||||
test_sync();
|
test_sync();
|
||||||
|
test_queue();
|
||||||
test_version();
|
test_version();
|
||||||
test_stack_callout();
|
test_stack_callout();
|
||||||
test_lookaside_list();
|
test_lookaside_list();
|
||||||
|
|
|
@ -397,6 +397,7 @@ typedef struct _WAIT_CONTEXT_BLOCK {
|
||||||
#define IO_TYPE_ERROR_LOG 0x0b
|
#define IO_TYPE_ERROR_LOG 0x0b
|
||||||
#define IO_TYPE_ERROR_MESSAGE 0x0c
|
#define IO_TYPE_ERROR_MESSAGE 0x0c
|
||||||
#define IO_TYPE_DEVICE_OBJECT_EXTENSION 0x0d
|
#define IO_TYPE_DEVICE_OBJECT_EXTENSION 0x0d
|
||||||
|
#define IO_TYPE_DEVICE_QUEUE 0x14
|
||||||
|
|
||||||
typedef struct _DEVICE_OBJECT {
|
typedef struct _DEVICE_OBJECT {
|
||||||
CSHORT Type;
|
CSHORT Type;
|
||||||
|
@ -1750,6 +1751,7 @@ void WINAPI KeEnterCriticalRegion(void);
|
||||||
void WINAPI KeGenericCallDpc(PKDEFERRED_ROUTINE,PVOID);
|
void WINAPI KeGenericCallDpc(PKDEFERRED_ROUTINE,PVOID);
|
||||||
ULONG WINAPI KeGetCurrentProcessorNumber(void);
|
ULONG WINAPI KeGetCurrentProcessorNumber(void);
|
||||||
PKTHREAD WINAPI KeGetCurrentThread(void);
|
PKTHREAD WINAPI KeGetCurrentThread(void);
|
||||||
|
void WINAPI KeInitializeDeviceQueue(KDEVICE_QUEUE*);
|
||||||
void WINAPI KeInitializeDpc(KDPC*,PKDEFERRED_ROUTINE,void*);
|
void WINAPI KeInitializeDpc(KDPC*,PKDEFERRED_ROUTINE,void*);
|
||||||
void WINAPI KeInitializeEvent(PRKEVENT,EVENT_TYPE,BOOLEAN);
|
void WINAPI KeInitializeEvent(PRKEVENT,EVENT_TYPE,BOOLEAN);
|
||||||
void WINAPI KeInitializeMutex(PRKMUTEX,ULONG);
|
void WINAPI KeInitializeMutex(PRKMUTEX,ULONG);
|
||||||
|
@ -1760,6 +1762,7 @@ static FORCEINLINE void WINAPI KeInitializeSpinLock( KSPIN_LOCK *lock )
|
||||||
}
|
}
|
||||||
void WINAPI KeInitializeTimerEx(PKTIMER,TIMER_TYPE);
|
void WINAPI KeInitializeTimerEx(PKTIMER,TIMER_TYPE);
|
||||||
void WINAPI KeInitializeTimer(KTIMER*);
|
void WINAPI KeInitializeTimer(KTIMER*);
|
||||||
|
BOOLEAN WINAPI KeInsertDeviceQueue(KDEVICE_QUEUE*,KDEVICE_QUEUE_ENTRY*);
|
||||||
void WINAPI KeLeaveCriticalRegion(void);
|
void WINAPI KeLeaveCriticalRegion(void);
|
||||||
ULONG WINAPI KeQueryActiveProcessorCountEx(USHORT);
|
ULONG WINAPI KeQueryActiveProcessorCountEx(USHORT);
|
||||||
KAFFINITY WINAPI KeQueryActiveProcessors(void);
|
KAFFINITY WINAPI KeQueryActiveProcessors(void);
|
||||||
|
@ -1772,6 +1775,7 @@ LONG WINAPI KeReleaseMutex(PRKMUTEX,BOOLEAN);
|
||||||
LONG WINAPI KeReleaseSemaphore(PRKSEMAPHORE,KPRIORITY,LONG,BOOLEAN);
|
LONG WINAPI KeReleaseSemaphore(PRKSEMAPHORE,KPRIORITY,LONG,BOOLEAN);
|
||||||
void WINAPI KeReleaseSpinLock(KSPIN_LOCK*,KIRQL);
|
void WINAPI KeReleaseSpinLock(KSPIN_LOCK*,KIRQL);
|
||||||
void WINAPI KeReleaseSpinLockFromDpcLevel(KSPIN_LOCK*);
|
void WINAPI KeReleaseSpinLockFromDpcLevel(KSPIN_LOCK*);
|
||||||
|
KDEVICE_QUEUE_ENTRY * WINAPI KeRemoveDeviceQueue(KDEVICE_QUEUE*);
|
||||||
LONG WINAPI KeResetEvent(PRKEVENT);
|
LONG WINAPI KeResetEvent(PRKEVENT);
|
||||||
void WINAPI KeRevertToUserAffinityThread(void);
|
void WINAPI KeRevertToUserAffinityThread(void);
|
||||||
void WINAPI KeRevertToUserAffinityThreadEx(KAFFINITY affinity);
|
void WINAPI KeRevertToUserAffinityThreadEx(KAFFINITY affinity);
|
||||||
|
|
Loading…
Reference in New Issue