Commit 00550496 authored by Rémi Bernon's avatar Rémi Bernon Committed by Alexandre Julliard

ntoskrnl.exe/tests: Return STATUS_PENDING from IOCTL_HID_READ_REPORT.

Marking input report read requests as pending and queueing them instead of returning STATUS_NOT_IMPLEMENTED. Windows also calls IRP_MN_(QUERY|CANCEL)_REMOVE_DEVICE on device initialization and we have to implement them for the test to not timeout. Signed-off-by: 's avatarRémi Bernon <rbernon@codeweavers.com> Signed-off-by: 's avatarZebediah Figura <zfigura@codeweavers.com> Signed-off-by: 's avatarAlexandre Julliard <julliard@winehq.org>
parent b065daa6
...@@ -42,10 +42,64 @@ static UNICODE_STRING control_symlink; ...@@ -42,10 +42,64 @@ static UNICODE_STRING control_symlink;
static unsigned int got_start_device; static unsigned int got_start_device;
static DWORD report_id; static DWORD report_id;
struct irp_queue
{
KSPIN_LOCK lock;
LIST_ENTRY list;
};
static IRP *irp_queue_pop(struct irp_queue *queue)
{
KIRQL irql;
IRP *irp;
KeAcquireSpinLock(&queue->lock, &irql);
if (IsListEmpty(&queue->list)) irp = NULL;
else irp = CONTAINING_RECORD(RemoveHeadList(&queue->list), IRP, Tail.Overlay.ListEntry);
KeReleaseSpinLock(&queue->lock, irql);
return irp;
}
static void irp_queue_push(struct irp_queue *queue, IRP *irp)
{
KIRQL irql;
KeAcquireSpinLock(&queue->lock, &irql);
InsertTailList(&queue->list, &irp->Tail.Overlay.ListEntry);
KeReleaseSpinLock(&queue->lock, irql);
}
static void irp_queue_clear(struct irp_queue *queue)
{
IRP *irp;
while ((irp = irp_queue_pop(queue)))
{
irp->IoStatus.Status = STATUS_DELETE_PENDING;
IoCompleteRequest(irp, IO_NO_INCREMENT);
}
}
static void irp_queue_init(struct irp_queue *queue)
{
KeInitializeSpinLock(&queue->lock);
InitializeListHead(&queue->list);
}
struct hid_device
{
BOOL removed;
KSPIN_LOCK lock;
struct irp_queue irp_queue;
};
static NTSTATUS WINAPI driver_pnp(DEVICE_OBJECT *device, IRP *irp) static NTSTATUS WINAPI driver_pnp(DEVICE_OBJECT *device, IRP *irp)
{ {
IO_STACK_LOCATION *stack = IoGetCurrentIrpStackLocation(irp); IO_STACK_LOCATION *stack = IoGetCurrentIrpStackLocation(irp);
HID_DEVICE_EXTENSION *ext = device->DeviceExtension; HID_DEVICE_EXTENSION *ext = device->DeviceExtension;
struct hid_device *impl = ext->MiniDeviceExtension;
KIRQL irql;
if (winetest_debug > 1) trace("pnp %#x\n", stack->MinorFunction); if (winetest_debug > 1) trace("pnp %#x\n", stack->MinorFunction);
...@@ -53,17 +107,35 @@ static NTSTATUS WINAPI driver_pnp(DEVICE_OBJECT *device, IRP *irp) ...@@ -53,17 +107,35 @@ static NTSTATUS WINAPI driver_pnp(DEVICE_OBJECT *device, IRP *irp)
{ {
case IRP_MN_START_DEVICE: case IRP_MN_START_DEVICE:
++got_start_device; ++got_start_device;
impl->removed = FALSE;
KeInitializeSpinLock(&impl->lock);
irp_queue_init(&impl->irp_queue);
IoSetDeviceInterfaceState(&control_symlink, TRUE); IoSetDeviceInterfaceState(&control_symlink, TRUE);
irp->IoStatus.Status = STATUS_SUCCESS; irp->IoStatus.Status = STATUS_SUCCESS;
break; break;
case IRP_MN_SURPRISE_REMOVAL: case IRP_MN_SURPRISE_REMOVAL:
case IRP_MN_QUERY_REMOVE_DEVICE: case IRP_MN_QUERY_REMOVE_DEVICE:
KeAcquireSpinLock(&impl->lock, &irql);
impl->removed = TRUE;
KeReleaseSpinLock(&impl->lock, irql);
irp_queue_clear(&impl->irp_queue);
irp->IoStatus.Status = STATUS_SUCCESS;
break;
case IRP_MN_CANCEL_REMOVE_DEVICE:
KeAcquireSpinLock(&impl->lock, &irql);
impl->removed = FALSE;
KeReleaseSpinLock(&impl->lock, irql);
irp->IoStatus.Status = STATUS_SUCCESS;
break;
case IRP_MN_STOP_DEVICE: case IRP_MN_STOP_DEVICE:
irp->IoStatus.Status = STATUS_SUCCESS; irp->IoStatus.Status = STATUS_SUCCESS;
break; break;
case IRP_MN_REMOVE_DEVICE: case IRP_MN_REMOVE_DEVICE:
irp_queue_clear(&impl->irp_queue);
IoSetDeviceInterfaceState(&control_symlink, FALSE); IoSetDeviceInterfaceState(&control_symlink, FALSE);
irp->IoStatus.Status = STATUS_SUCCESS; irp->IoStatus.Status = STATUS_SUCCESS;
break; break;
...@@ -317,10 +389,14 @@ static NTSTATUS WINAPI driver_internal_ioctl(DEVICE_OBJECT *device, IRP *irp) ...@@ -317,10 +389,14 @@ static NTSTATUS WINAPI driver_internal_ioctl(DEVICE_OBJECT *device, IRP *irp)
static BOOL test_failed; static BOOL test_failed;
IO_STACK_LOCATION *stack = IoGetCurrentIrpStackLocation(irp); IO_STACK_LOCATION *stack = IoGetCurrentIrpStackLocation(irp);
HID_DEVICE_EXTENSION *ext = device->DeviceExtension;
struct hid_device *impl = ext->MiniDeviceExtension;
const ULONG in_size = stack->Parameters.DeviceIoControl.InputBufferLength; const ULONG in_size = stack->Parameters.DeviceIoControl.InputBufferLength;
const ULONG out_size = stack->Parameters.DeviceIoControl.OutputBufferLength; const ULONG out_size = stack->Parameters.DeviceIoControl.OutputBufferLength;
const ULONG code = stack->Parameters.DeviceIoControl.IoControlCode; const ULONG code = stack->Parameters.DeviceIoControl.IoControlCode;
NTSTATUS ret; NTSTATUS ret;
BOOL removed;
KIRQL irql;
if (winetest_debug > 1) trace("ioctl %#x\n", code); if (winetest_debug > 1) trace("ioctl %#x\n", code);
...@@ -328,6 +404,17 @@ static NTSTATUS WINAPI driver_internal_ioctl(DEVICE_OBJECT *device, IRP *irp) ...@@ -328,6 +404,17 @@ static NTSTATUS WINAPI driver_internal_ioctl(DEVICE_OBJECT *device, IRP *irp)
irp->IoStatus.Information = 0; irp->IoStatus.Information = 0;
KeAcquireSpinLock(&impl->lock, &irql);
removed = impl->removed;
KeReleaseSpinLock(&impl->lock, irql);
if (removed)
{
irp->IoStatus.Status = STATUS_DELETE_PENDING;
IoCompleteRequest(irp, IO_NO_INCREMENT);
return STATUS_DELETE_PENDING;
}
switch (code) switch (code)
{ {
case IOCTL_HID_GET_DEVICE_DESCRIPTOR: case IOCTL_HID_GET_DEVICE_DESCRIPTOR:
...@@ -398,7 +485,9 @@ static NTSTATUS WINAPI driver_internal_ioctl(DEVICE_OBJECT *device, IRP *irp) ...@@ -398,7 +485,9 @@ static NTSTATUS WINAPI driver_internal_ioctl(DEVICE_OBJECT *device, IRP *irp)
} }
if (out_size != expected_size) test_failed = TRUE; if (out_size != expected_size) test_failed = TRUE;
ret = STATUS_NOT_IMPLEMENTED; IoMarkIrpPending(irp);
irp_queue_push(&impl->irp_queue, irp);
ret = STATUS_PENDING;
break; break;
} }
...@@ -494,8 +583,11 @@ static NTSTATUS WINAPI driver_internal_ioctl(DEVICE_OBJECT *device, IRP *irp) ...@@ -494,8 +583,11 @@ static NTSTATUS WINAPI driver_internal_ioctl(DEVICE_OBJECT *device, IRP *irp)
ret = STATUS_NOT_IMPLEMENTED; ret = STATUS_NOT_IMPLEMENTED;
} }
if (ret != STATUS_PENDING)
{
irp->IoStatus.Status = ret; irp->IoStatus.Status = ret;
IoCompleteRequest(irp, IO_NO_INCREMENT); IoCompleteRequest(irp, IO_NO_INCREMENT);
}
return ret; return ret;
} }
...@@ -555,6 +647,7 @@ NTSTATUS WINAPI DriverEntry(DRIVER_OBJECT *driver, UNICODE_STRING *registry) ...@@ -555,6 +647,7 @@ NTSTATUS WINAPI DriverEntry(DRIVER_OBJECT *driver, UNICODE_STRING *registry)
{ {
.Revision = HID_REVISION, .Revision = HID_REVISION,
.DriverObject = driver, .DriverObject = driver,
.DeviceExtensionSize = sizeof(struct hid_device),
.RegistryPath = registry, .RegistryPath = registry,
}; };
UNICODE_STRING name_str; UNICODE_STRING name_str;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment