From: Rémi Bernon rbernon@codeweavers.com
--- dlls/dinput/tests/driver_bus.c | 36 +++++++++++++++++++++------------- 1 file changed, 22 insertions(+), 14 deletions(-)
diff --git a/dlls/dinput/tests/driver_bus.c b/dlls/dinput/tests/driver_bus.c index c0d181c58a5..7ad8c90adb4 100644 --- a/dlls/dinput/tests/driver_bus.c +++ b/dlls/dinput/tests/driver_bus.c @@ -348,13 +348,13 @@ static void irp_queue_push( struct irp_queue *queue, IRP *irp ) KeReleaseSpinLock( &queue->lock, irql ); }
-static void irp_queue_clear( struct irp_queue *queue ) +static void irp_queue_complete( struct irp_queue *queue, BOOL delete ) { IRP *irp;
while ((irp = irp_queue_pop( queue ))) { - irp->IoStatus.Status = STATUS_DELETE_PENDING; + if (delete) irp->IoStatus.Status = STATUS_DELETE_PENDING; IoCompleteRequest( irp, IO_NO_INCREMENT ); } } @@ -373,6 +373,7 @@ struct input_queue struct hid_expect *end; struct hid_expect *buffer; struct irp_queue pending; + struct irp_queue completed; };
static void input_queue_init( struct input_queue *queue, BOOL is_polled ) @@ -384,6 +385,7 @@ static void input_queue_init( struct input_queue *queue, BOOL is_polled ) queue->pos = queue->buffer; queue->end = queue->buffer; irp_queue_init( &queue->pending ); + irp_queue_init( &queue->completed ); }
static void input_queue_cleanup( struct input_queue *queue ) @@ -416,7 +418,11 @@ static NTSTATUS input_queue_read( struct input_queue *queue, IRP *irp ) KIRQL irql;
KeAcquireSpinLock( &queue->lock, &irql ); - if (input_queue_read_locked( queue, irp )) status = STATUS_SUCCESS; + if (input_queue_read_locked( queue, irp )) + { + irp_queue_push( &queue->completed, irp ); + status = STATUS_SUCCESS; + } else { IoMarkIrpPending( irp ); @@ -428,15 +434,12 @@ static NTSTATUS input_queue_read( struct input_queue *queue, IRP *irp ) return status; }
-static void input_queue_reset( struct input_queue *queue, void *in_buf, ULONG in_size ) +static void input_queue_reset( struct input_queue *queue, void *in_buf, ULONG in_size, const char *context ) { - struct irp_queue completed; ULONG remaining; KIRQL irql; IRP *irp;
- irp_queue_init( &completed ); - KeAcquireSpinLock( &queue->lock, &irql ); remaining = queue->end - queue->pos; queue->pos = queue->buffer; @@ -447,13 +450,13 @@ static void input_queue_reset( struct input_queue *queue, void *in_buf, ULONG in while (!queue->is_polled && queue->pos < queue->end && (irp = irp_queue_pop( &queue->pending ))) { input_queue_read_locked( queue, irp ); - irp_queue_push( &completed, irp ); + irp_queue_push( &queue->completed, irp ); } KeReleaseSpinLock( &queue->lock, irql );
if (!queue->is_polled) ok( !remaining, "unread input\n" );
- while ((irp = irp_queue_pop( &completed ))) IoCompleteRequest( irp, IO_NO_INCREMENT ); + irp_queue_complete( &queue->completed, FALSE ); }
struct device @@ -721,7 +724,8 @@ static NTSTATUS pdo_pnp( DEVICE_OBJECT *device, IRP *irp ) state = (code == IRP_MN_START_DEVICE || code == IRP_MN_CANCEL_REMOVE_DEVICE) ? 0 : PNP_DEVICE_REMOVED; KeAcquireSpinLock( &impl->base.lock, &irql ); impl->base.state = state; - irp_queue_clear( &impl->input_queue.pending ); + irp_queue_complete( &impl->input_queue.pending, TRUE ); + irp_queue_complete( &impl->input_queue.completed, TRUE ); KeReleaseSpinLock( &impl->base.lock, irql ); if (code != IRP_MN_REMOVE_DEVICE) status = STATUS_SUCCESS; else @@ -884,7 +888,7 @@ static NTSTATUS create_child_pdo( DEVICE_OBJECT *device, struct hid_device_desc impl->report_descriptor_len = desc->report_descriptor_len; memcpy( impl->report_descriptor_buf, desc->report_descriptor_buf, desc->report_descriptor_len ); input_queue_init( &impl->input_queue, desc->is_polled ); - input_queue_reset( &impl->input_queue, desc->input, desc->input_size ); + input_queue_reset( &impl->input_queue, desc->input, desc->input_size, impl->expect_queue.context ); expect_queue_init( &impl->expect_queue ); expect_queue_reset( &impl->expect_queue, desc->expect, desc->expect_size ); memcpy( impl->expect_queue.context, desc->context, desc->context_size ); @@ -1087,7 +1091,10 @@ static NTSTATUS pdo_internal_ioctl( DEVICE_OBJECT *device, IRP *irp ) ok( !in_size, "got input size %lu\n", in_size ); ok( out_size == expected_size, "got output size %lu\n", out_size ); status = input_queue_read( &impl->input_queue, irp ); - break; + irp_queue_complete( &impl->input_queue.completed, FALSE ); + + winetest_pop_context(); + return status; }
case IOCTL_HID_WRITE_REPORT: @@ -1266,7 +1273,7 @@ static NTSTATUS pdo_handle_ioctl( struct phys_device *impl, IRP *irp, ULONG code } case IOCTL_WINETEST_HID_SEND_INPUT: if (in_size > EXPECT_QUEUE_BUFFER_SIZE) return STATUS_BUFFER_OVERFLOW; - input_queue_reset( &impl->input_queue, in_buffer, in_size ); + input_queue_reset( &impl->input_queue, in_buffer, in_size, impl->expect_queue.context ); return STATUS_SUCCESS; case IOCTL_WINETEST_HID_SET_CONTEXT: if (in_size > sizeof(impl->expect_queue.context)) return STATUS_BUFFER_OVERFLOW; @@ -1277,7 +1284,8 @@ static NTSTATUS pdo_handle_ioctl( struct phys_device *impl, IRP *irp, ULONG code case IOCTL_WINETEST_REMOVE_DEVICE: KeAcquireSpinLock( &impl->base.lock, &irql ); impl->base.state = PNP_DEVICE_REMOVED; - irp_queue_clear( &impl->input_queue.pending ); + irp_queue_complete( &impl->input_queue.pending, TRUE ); + irp_queue_complete( &impl->input_queue.completed, TRUE ); KeReleaseSpinLock( &impl->base.lock, irql ); impl->pending_remove = irp; IoMarkIrpPending( irp );