2 * HID Plug and Play test driver
4 * Copyright 2021 Zebediah Figura
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
25 #define WIN32_NO_STATUS
32 #include "ddk/hidpi.h"
33 #include "ddk/hidport.h"
35 #include "wine/list.h"
38 #include "driver_hid.h"
40 static UNICODE_STRING control_symlink
;
42 static unsigned int got_start_device
;
43 static HID_DEVICE_ATTRIBUTES attributes
;
44 static char report_descriptor_buf
[4096];
45 static DWORD report_descriptor_len
;
46 static HIDP_CAPS caps
;
47 static DWORD report_id
;
50 #define EXPECT_QUEUE_BUFFER_SIZE (64 * sizeof(struct hid_expect))
55 struct hid_expect
*pos
;
56 struct hid_expect
*end
;
57 struct hid_expect spurious
;
58 struct hid_expect
*buffer
;
63 static void expect_queue_init( struct expect_queue
*queue
)
65 KeInitializeSpinLock( &queue
->lock
);
66 queue
->buffer
= ExAllocatePool( PagedPool
, EXPECT_QUEUE_BUFFER_SIZE
);
67 RtlSecureZeroMemory( queue
->buffer
, EXPECT_QUEUE_BUFFER_SIZE
);
68 queue
->pos
= queue
->buffer
;
69 queue
->end
= queue
->buffer
;
72 static void expect_queue_cleanup( struct expect_queue
*queue
)
77 KeAcquireSpinLock( &queue
->lock
, &irql
);
78 if ((irp
= queue
->pending_wait
))
80 queue
->pending_wait
= NULL
;
81 if (!IoSetCancelRoutine( irp
, NULL
)) irp
= NULL
;
83 KeReleaseSpinLock( &queue
->lock
, irql
);
87 irp
->IoStatus
.Information
= 0;
88 irp
->IoStatus
.Status
= STATUS_DELETE_PENDING
;
89 IoCompleteRequest( irp
, IO_NO_INCREMENT
);
92 ExFreePool( queue
->buffer
);
95 static void expect_queue_reset( struct expect_queue
*queue
, void *buffer
, unsigned int size
)
97 struct hid_expect
*missing
, *missing_end
, *tmp
;
101 missing
= ExAllocatePool( PagedPool
, EXPECT_QUEUE_BUFFER_SIZE
);
102 RtlSecureZeroMemory( missing
, EXPECT_QUEUE_BUFFER_SIZE
);
103 missing_end
= missing
;
105 KeAcquireSpinLock( &queue
->lock
, &irql
);
107 while (tmp
< queue
->end
) *missing_end
++ = *tmp
++;
109 queue
->pos
= queue
->buffer
;
110 queue
->end
= queue
->buffer
;
112 if (size
) memcpy( queue
->end
, buffer
, size
);
113 queue
->end
= queue
->end
+ size
/ sizeof(struct hid_expect
);
114 memcpy( context
, queue
->context
, sizeof(context
) );
115 KeReleaseSpinLock( &queue
->lock
, irql
);
118 while (tmp
!= missing_end
)
120 winetest_push_context( "%s expect[%Id]", context
, tmp
- missing
);
123 todo_wine_if( tmp
->todo
)
124 win_skip( "broken (code %#lx id %u len %u)\n", tmp
->code
, tmp
->report_id
, tmp
->report_len
);
128 todo_wine_if( tmp
->todo
)
129 ok( tmp
->wine_only
, "missing (code %#lx id %u len %u)\n", tmp
->code
, tmp
->report_id
, tmp
->report_len
);
131 winetest_pop_context();
135 ExFreePool( missing
);
138 static void WINAPI
wait_cancel_routine( DEVICE_OBJECT
*device
, IRP
*irp
)
140 struct expect_queue
*queue
= irp
->Tail
.Overlay
.DriverContext
[0];
143 IoReleaseCancelSpinLock( irp
->CancelIrql
);
145 KeAcquireSpinLock( &queue
->lock
, &irql
);
146 queue
->pending_wait
= NULL
;
147 KeReleaseSpinLock( &queue
->lock
, irql
);
149 irp
->IoStatus
.Information
= 0;
150 irp
->IoStatus
.Status
= STATUS_CANCELLED
;
151 IoCompleteRequest( irp
, IO_NO_INCREMENT
);
154 static NTSTATUS
expect_queue_wait( struct expect_queue
*queue
, IRP
*irp
)
159 KeAcquireSpinLock( &queue
->lock
, &irql
);
160 if (queue
->pos
== queue
->end
)
161 status
= STATUS_SUCCESS
;
164 IoSetCancelRoutine( irp
, wait_cancel_routine
);
165 if (irp
->Cancel
&& !IoSetCancelRoutine( irp
, NULL
))
166 status
= STATUS_CANCELLED
;
169 irp
->Tail
.Overlay
.DriverContext
[0] = queue
;
170 IoMarkIrpPending( irp
);
171 queue
->pending_wait
= irp
;
172 status
= STATUS_PENDING
;
175 KeReleaseSpinLock( &queue
->lock
, irql
);
177 if (status
== STATUS_SUCCESS
)
179 irp
->IoStatus
.Status
= STATUS_SUCCESS
;
180 IoCompleteRequest( irp
, IO_NO_INCREMENT
);
186 static void expect_queue_next( struct expect_queue
*queue
, ULONG code
, HID_XFER_PACKET
*packet
,
187 LONG
*index
, struct hid_expect
*expect
, BOOL compare_buf
,
188 char *context
, ULONG context_size
)
190 struct hid_expect
*missing
, *missing_end
, *tmp
;
191 ULONG len
= packet
->reportBufferLen
;
192 BYTE
*buf
= packet
->reportBuffer
;
193 BYTE id
= packet
->reportId
;
197 missing
= ExAllocatePool( PagedPool
, EXPECT_QUEUE_BUFFER_SIZE
);
198 RtlSecureZeroMemory( missing
, EXPECT_QUEUE_BUFFER_SIZE
);
199 missing_end
= missing
;
201 KeAcquireSpinLock( &queue
->lock
, &irql
);
203 while (tmp
< queue
->end
)
205 if (running_under_wine
&& !tmp
->todo
) break;
206 if (!running_under_wine
&& !tmp
->broken
&& !tmp
->wine_only
) break;
207 if (tmp
->code
== code
&& tmp
->report_id
== id
&& tmp
->report_len
== len
&&
208 (!compare_buf
|| RtlCompareMemory( tmp
->report_buf
, buf
, len
) == len
))
210 *missing_end
++ = *tmp
++;
212 *index
= tmp
- queue
->buffer
;
213 if (tmp
< queue
->end
) queue
->pos
= tmp
+ 1;
214 else tmp
= &queue
->spurious
;
217 while (queue
->pos
< queue
->end
)
219 if (running_under_wine
|| !queue
->pos
->wine_only
) break;
222 if (queue
->pos
== queue
->end
&& (irp
= queue
->pending_wait
))
224 queue
->pending_wait
= NULL
;
225 if (!IoSetCancelRoutine( irp
, NULL
)) irp
= NULL
;
227 memcpy( context
, queue
->context
, context_size
);
228 KeReleaseSpinLock( &queue
->lock
, irql
);
232 irp
->IoStatus
.Information
= 0;
233 irp
->IoStatus
.Status
= STATUS_SUCCESS
;
234 IoCompleteRequest( irp
, IO_NO_INCREMENT
);
237 ok( tmp
!= &queue
->spurious
, "%s got spurious packet\n", context
);
239 winetest_push_context( "%s expect[%Id]", context
, tmp
- queue
->buffer
);
240 todo_wine_if( tmp
->todo
)
241 ok( !tmp
->wine_only
, "found code %#lx id %u len %u\n", tmp
->code
, tmp
->report_id
, tmp
->report_len
);
242 winetest_pop_context();
245 while (tmp
!= missing_end
)
247 winetest_push_context( "%s expect[%Id]", context
, tmp
- missing
);
250 todo_wine_if( tmp
->todo
)
251 win_skip( "broken (code %#lx id %u len %u)\n", tmp
->code
, tmp
->report_id
, tmp
->report_len
);
255 todo_wine_if( tmp
->todo
)
256 ok( tmp
->wine_only
, "missing (code %#lx id %u len %u)\n", tmp
->code
, tmp
->report_id
, tmp
->report_len
);
258 winetest_pop_context();
262 ExFreePool( missing
);
265 static struct expect_queue expect_queue
;
273 static IRP
*irp_queue_pop( struct irp_queue
*queue
)
278 KeAcquireSpinLock( &queue
->lock
, &irql
);
279 if (IsListEmpty( &queue
->list
)) irp
= NULL
;
280 else irp
= CONTAINING_RECORD( RemoveHeadList( &queue
->list
), IRP
, Tail
.Overlay
.ListEntry
);
281 KeReleaseSpinLock( &queue
->lock
, irql
);
286 static void irp_queue_push( struct irp_queue
*queue
, IRP
*irp
)
290 KeAcquireSpinLock( &queue
->lock
, &irql
);
291 InsertTailList( &queue
->list
, &irp
->Tail
.Overlay
.ListEntry
);
292 KeReleaseSpinLock( &queue
->lock
, irql
);
295 static void irp_queue_clear( struct irp_queue
*queue
)
299 while ((irp
= irp_queue_pop( queue
)))
301 irp
->IoStatus
.Status
= STATUS_DELETE_PENDING
;
302 IoCompleteRequest( irp
, IO_NO_INCREMENT
);
306 static void irp_queue_init( struct irp_queue
*queue
)
308 KeInitializeSpinLock( &queue
->lock
);
309 InitializeListHead( &queue
->list
);
315 struct hid_expect
*pos
;
316 struct hid_expect
*end
;
317 struct hid_expect
*buffer
;
318 struct irp_queue pending
;
321 static void input_queue_init( struct input_queue
*queue
)
323 KeInitializeSpinLock( &queue
->lock
);
324 queue
->buffer
= ExAllocatePool( PagedPool
, EXPECT_QUEUE_BUFFER_SIZE
);
325 RtlSecureZeroMemory( queue
->buffer
, EXPECT_QUEUE_BUFFER_SIZE
);
326 queue
->pos
= queue
->buffer
;
327 queue
->end
= queue
->buffer
;
328 irp_queue_init( &queue
->pending
);
331 static void input_queue_cleanup( struct input_queue
*queue
)
333 ExFreePool( queue
->buffer
);
336 static BOOL
input_queue_read_locked( struct input_queue
*queue
, IRP
*irp
)
338 IO_STACK_LOCATION
*stack
= IoGetCurrentIrpStackLocation( irp
);
339 ULONG out_size
= stack
->Parameters
.DeviceIoControl
.OutputBufferLength
;
340 struct hid_expect
*tmp
= queue
->pos
;
342 if (tmp
>= queue
->end
) return FALSE
;
343 if (tmp
->ret_length
) out_size
= tmp
->ret_length
;
345 memcpy( irp
->UserBuffer
, tmp
->report_buf
, out_size
);
346 irp
->IoStatus
.Information
= out_size
;
347 irp
->IoStatus
.Status
= tmp
->ret_status
;
348 if (tmp
< queue
->end
) queue
->pos
= tmp
+ 1;
350 /* loop on the queue data in polled mode */
351 if (polled
&& queue
->pos
== queue
->end
) queue
->pos
= queue
->buffer
;
355 static NTSTATUS
input_queue_read( struct input_queue
*queue
, IRP
*irp
)
360 KeAcquireSpinLock( &queue
->lock
, &irql
);
361 if (input_queue_read_locked( queue
, irp
)) status
= STATUS_SUCCESS
;
364 IoMarkIrpPending( irp
);
365 irp_queue_push( &queue
->pending
, irp
);
366 status
= STATUS_PENDING
;
368 KeReleaseSpinLock( &queue
->lock
, irql
);
373 static void input_queue_reset( struct input_queue
*queue
, void *in_buf
, ULONG in_size
)
375 struct irp_queue completed
;
380 irp_queue_init( &completed
);
382 KeAcquireSpinLock( &queue
->lock
, &irql
);
383 remaining
= queue
->end
- queue
->pos
;
384 queue
->pos
= queue
->buffer
;
385 queue
->end
= queue
->buffer
;
386 memcpy( queue
->end
, in_buf
, in_size
);
387 queue
->end
+= in_size
/ sizeof(struct hid_expect
);
389 while (!polled
&& queue
->pos
< queue
->end
&& (irp
= irp_queue_pop( &queue
->pending
)))
391 input_queue_read_locked( queue
, irp
);
392 irp_queue_push( &completed
, irp
);
394 KeReleaseSpinLock( &queue
->lock
, irql
);
396 if (!polled
) ok( !remaining
, "unread input\n" );
398 while ((irp
= irp_queue_pop( &completed
))) IoCompleteRequest( irp
, IO_NO_INCREMENT
);
401 static struct input_queue input_queue
;
409 static DRIVER_OBJECT
*expect_driver
;
410 static DEVICE_OBJECT
*expect_bus_pdo
;
411 static DEVICE_OBJECT
*expect_hid_fdo
;
412 static DEVICE_OBJECT
*expect_hid_pdo
;
413 static struct hid_device
*expect_hid_ext
;
415 static void check_device( DEVICE_OBJECT
*device
)
417 static int checked_fdo
, checked_pdo
;
418 HID_DEVICE_EXTENSION
*ext
= device
->DeviceExtension
;
420 ok( device
== expect_hid_pdo
|| device
== expect_hid_fdo
, "got device %p\n", device
);
421 ok( device
->DriverObject
== expect_driver
, "got DriverObject %p\n", device
->DriverObject
);
422 if (!device
->NextDevice
) ok( device
== expect_hid_fdo
, "got device %p\n", device
);
423 else ok( device
->NextDevice
== expect_hid_fdo
, "got NextDevice %p\n", device
->NextDevice
);
424 ok( !device
->AttachedDevice
, "got AttachedDevice %p\n", device
->AttachedDevice
);
426 if (device
== expect_hid_pdo
&& checked_pdo
++) return;
427 if (device
== expect_hid_fdo
&& checked_fdo
++) return;
429 todo_wine_if( device
!= expect_hid_fdo
)
430 ok( ext
->MiniDeviceExtension
== expect_hid_ext
, "got MiniDeviceExtension %p\n", ext
->MiniDeviceExtension
);
431 if (ext
->MiniDeviceExtension
!= expect_hid_ext
) return;
432 ok( ext
->PhysicalDeviceObject
== expect_bus_pdo
, "got PhysicalDeviceObject %p\n", ext
->PhysicalDeviceObject
);
433 ok( ext
->NextDeviceObject
== expect_bus_pdo
, "got NextDeviceObject %p\n", ext
->NextDeviceObject
);
436 static NTSTATUS WINAPI
driver_pnp( DEVICE_OBJECT
*device
, IRP
*irp
)
438 IO_STACK_LOCATION
*stack
= IoGetCurrentIrpStackLocation( irp
);
439 HID_DEVICE_EXTENSION
*ext
= device
->DeviceExtension
;
440 struct hid_device
*impl
= ext
->MiniDeviceExtension
;
441 ULONG code
= stack
->MinorFunction
;
444 if (winetest_debug
> 1) trace( "%s: device %p, code %#lx %s\n", __func__
, device
, code
, debugstr_pnp(code
) );
448 case IRP_MN_START_DEVICE
:
450 impl
->removed
= FALSE
;
451 KeInitializeSpinLock( &impl
->lock
);
452 IoSetDeviceInterfaceState( &control_symlink
, TRUE
);
453 irp
->IoStatus
.Status
= STATUS_SUCCESS
;
456 case IRP_MN_SURPRISE_REMOVAL
:
457 case IRP_MN_QUERY_REMOVE_DEVICE
:
458 KeAcquireSpinLock( &impl
->lock
, &irql
);
459 impl
->removed
= TRUE
;
460 KeReleaseSpinLock( &impl
->lock
, irql
);
461 irp_queue_clear( &input_queue
.pending
);
462 irp
->IoStatus
.Status
= STATUS_SUCCESS
;
465 case IRP_MN_CANCEL_REMOVE_DEVICE
:
466 KeAcquireSpinLock( &impl
->lock
, &irql
);
467 impl
->removed
= FALSE
;
468 KeReleaseSpinLock( &impl
->lock
, irql
);
469 irp
->IoStatus
.Status
= STATUS_SUCCESS
;
472 case IRP_MN_STOP_DEVICE
:
473 irp
->IoStatus
.Status
= STATUS_SUCCESS
;
476 case IRP_MN_REMOVE_DEVICE
:
477 irp_queue_clear( &input_queue
.pending
);
478 IoSetDeviceInterfaceState( &control_symlink
, FALSE
);
479 irp
->IoStatus
.Status
= STATUS_SUCCESS
;
483 IoSkipCurrentIrpStackLocation( irp
);
484 return IoCallDriver( ext
->NextDeviceObject
, irp
);
487 #define check_buffer( a, b ) check_buffer_( __LINE__, a, b )
488 static void check_buffer_( int line
, HID_XFER_PACKET
*packet
, struct hid_expect
*expect
)
492 match_len
= RtlCompareMemory( packet
->reportBuffer
, expect
->report_buf
, expect
->report_len
);
493 ok( match_len
== expect
->report_len
, "unexpected data:\n" );
494 if (match_len
== expect
->report_len
) return;
496 for (i
= 0; i
< packet
->reportBufferLen
;)
498 char buffer
[256], *buf
= buffer
;
499 buf
+= sprintf( buf
, "%08lx ", i
);
500 do buf
+= sprintf( buf
, " %02x", packet
->reportBuffer
[i
] );
501 while (++i
% 16 && i
< packet
->reportBufferLen
);
502 ok( 0, " %s\n", buffer
);
506 static NTSTATUS WINAPI
driver_internal_ioctl( DEVICE_OBJECT
*device
, IRP
*irp
)
508 IO_STACK_LOCATION
*stack
= IoGetCurrentIrpStackLocation( irp
);
509 HID_DEVICE_EXTENSION
*ext
= device
->DeviceExtension
;
510 struct hid_device
*impl
= ext
->MiniDeviceExtension
;
511 const ULONG in_size
= stack
->Parameters
.DeviceIoControl
.InputBufferLength
;
512 ULONG out_size
= stack
->Parameters
.DeviceIoControl
.OutputBufferLength
;
513 const ULONG code
= stack
->Parameters
.DeviceIoControl
.IoControlCode
;
514 struct hid_expect expect
= {0};
521 if (winetest_debug
> 1) trace( "%s: device %p, code %#lx %s\n", __func__
, device
, code
, debugstr_ioctl(code
) );
523 ok( expect_hid_fdo
== device
, "got device %p\n", device
);
524 check_device( device
);
526 ok( got_start_device
, "expected IRP_MN_START_DEVICE before any ioctls\n" );
528 irp
->IoStatus
.Information
= 0;
530 KeAcquireSpinLock( &impl
->lock
, &irql
);
531 removed
= impl
->removed
;
532 KeReleaseSpinLock( &impl
->lock
, irql
);
536 irp
->IoStatus
.Status
= STATUS_DELETE_PENDING
;
537 IoCompleteRequest( irp
, IO_NO_INCREMENT
);
538 return STATUS_DELETE_PENDING
;
541 winetest_push_context( "id %ld%s", report_id
, polled
? " poll" : "" );
545 case IOCTL_HID_GET_DEVICE_DESCRIPTOR
:
547 HID_DESCRIPTOR
*desc
= irp
->UserBuffer
;
549 ok( !in_size
, "got input size %lu\n", in_size
);
550 ok( out_size
== sizeof(*desc
), "got output size %lu\n", out_size
);
552 if (out_size
== sizeof(*desc
))
554 ok( !desc
->bLength
, "got size %u\n", desc
->bLength
);
556 desc
->bLength
= sizeof(*desc
);
557 desc
->bDescriptorType
= HID_HID_DESCRIPTOR_TYPE
;
558 desc
->bcdHID
= HID_REVISION
;
560 desc
->bNumDescriptors
= 1;
561 desc
->DescriptorList
[0].bReportType
= HID_REPORT_DESCRIPTOR_TYPE
;
562 desc
->DescriptorList
[0].wReportLength
= report_descriptor_len
;
563 irp
->IoStatus
.Information
= sizeof(*desc
);
565 ret
= STATUS_SUCCESS
;
569 case IOCTL_HID_GET_REPORT_DESCRIPTOR
:
570 ok( !in_size
, "got input size %lu\n", in_size
);
571 ok( out_size
== report_descriptor_len
, "got output size %lu\n", out_size
);
573 if (out_size
== report_descriptor_len
)
575 memcpy( irp
->UserBuffer
, report_descriptor_buf
, report_descriptor_len
);
576 irp
->IoStatus
.Information
= report_descriptor_len
;
578 ret
= STATUS_SUCCESS
;
581 case IOCTL_HID_GET_DEVICE_ATTRIBUTES
:
582 ok( !in_size
, "got input size %lu\n", in_size
);
583 ok( out_size
== sizeof(attributes
), "got output size %lu\n", out_size
);
585 if (out_size
== sizeof(attributes
))
587 memcpy( irp
->UserBuffer
, &attributes
, sizeof(attributes
) );
588 irp
->IoStatus
.Information
= sizeof(attributes
);
590 ret
= STATUS_SUCCESS
;
593 case IOCTL_HID_READ_REPORT
:
595 ULONG expected_size
= caps
.InputReportByteLength
- (report_id
? 0 : 1);
596 ok( !in_size
, "got input size %lu\n", in_size
);
597 ok( out_size
== expected_size
, "got output size %lu\n", out_size
);
598 ret
= input_queue_read( &input_queue
, irp
);
602 case IOCTL_HID_WRITE_REPORT
:
604 HID_XFER_PACKET
*packet
= irp
->UserBuffer
;
605 ULONG expected_size
= caps
.OutputReportByteLength
- (report_id
? 0 : 1);
607 ok( in_size
== sizeof(*packet
), "got input size %lu\n", in_size
);
608 ok( !out_size
, "got output size %lu\n", out_size
);
609 ok( packet
->reportBufferLen
>= expected_size
, "got report size %lu\n", packet
->reportBufferLen
);
611 expect_queue_next( &expect_queue
, code
, packet
, &index
, &expect
, TRUE
, context
, sizeof(context
) );
612 winetest_push_context( "%s expect[%ld]", context
, index
);
613 ok( code
== expect
.code
, "got %#lx, expected %#lx\n", code
, expect
.code
);
614 ok( packet
->reportId
== expect
.report_id
, "got id %u\n", packet
->reportId
);
615 ok( packet
->reportBufferLen
== expect
.report_len
, "got len %lu\n", packet
->reportBufferLen
);
616 check_buffer( packet
, &expect
);
617 winetest_pop_context();
619 irp
->IoStatus
.Information
= expect
.ret_length
? expect
.ret_length
: expect
.report_len
;
620 ret
= expect
.ret_status
;
624 case IOCTL_HID_GET_INPUT_REPORT
:
626 HID_XFER_PACKET
*packet
= irp
->UserBuffer
;
627 ULONG expected_size
= caps
.InputReportByteLength
- (report_id
? 0 : 1);
628 ok( !in_size
, "got input size %lu\n", in_size
);
629 ok( out_size
== sizeof(*packet
), "got output size %lu\n", out_size
);
631 ok( packet
->reportBufferLen
>= expected_size
, "got len %lu\n", packet
->reportBufferLen
);
632 ok( !!packet
->reportBuffer
, "got buffer %p\n", packet
->reportBuffer
);
634 expect_queue_next( &expect_queue
, code
, packet
, &index
, &expect
, FALSE
, context
, sizeof(context
) );
635 winetest_push_context( "%s expect[%ld]", context
, index
);
636 ok( code
== expect
.code
, "got %#lx, expected %#lx\n", code
, expect
.code
);
637 ok( packet
->reportId
== expect
.report_id
, "got id %u\n", packet
->reportId
);
638 ok( packet
->reportBufferLen
== expect
.report_len
, "got len %lu\n", packet
->reportBufferLen
);
639 winetest_pop_context();
641 irp
->IoStatus
.Information
= expect
.ret_length
? expect
.ret_length
: expect
.report_len
;
642 memcpy( packet
->reportBuffer
, expect
.report_buf
, irp
->IoStatus
.Information
);
643 ret
= expect
.ret_status
;
647 case IOCTL_HID_SET_OUTPUT_REPORT
:
649 HID_XFER_PACKET
*packet
= irp
->UserBuffer
;
650 ULONG expected_size
= caps
.OutputReportByteLength
- (report_id
? 0 : 1);
651 ok( in_size
== sizeof(*packet
), "got input size %lu\n", in_size
);
652 ok( !out_size
, "got output size %lu\n", out_size
);
654 ok( packet
->reportBufferLen
>= expected_size
, "got len %lu\n", packet
->reportBufferLen
);
655 ok( !!packet
->reportBuffer
, "got buffer %p\n", packet
->reportBuffer
);
657 expect_queue_next( &expect_queue
, code
, packet
, &index
, &expect
, TRUE
, context
, sizeof(context
) );
658 winetest_push_context( "%s expect[%ld]", context
, index
);
659 ok( code
== expect
.code
, "got %#lx, expected %#lx\n", code
, expect
.code
);
660 ok( packet
->reportId
== expect
.report_id
, "got id %u\n", packet
->reportId
);
661 ok( packet
->reportBufferLen
== expect
.report_len
, "got len %lu\n", packet
->reportBufferLen
);
662 check_buffer( packet
, &expect
);
663 winetest_pop_context();
665 irp
->IoStatus
.Information
= expect
.ret_length
? expect
.ret_length
: expect
.report_len
;
666 ret
= expect
.ret_status
;
670 case IOCTL_HID_GET_FEATURE
:
672 HID_XFER_PACKET
*packet
= irp
->UserBuffer
;
673 ULONG expected_size
= caps
.FeatureReportByteLength
- (report_id
? 0 : 1);
674 ok( !in_size
, "got input size %lu\n", in_size
);
675 ok( out_size
== sizeof(*packet
), "got output size %lu\n", out_size
);
677 ok( packet
->reportBufferLen
>= expected_size
, "got len %lu\n", packet
->reportBufferLen
);
678 ok( !!packet
->reportBuffer
, "got buffer %p\n", packet
->reportBuffer
);
680 expect_queue_next( &expect_queue
, code
, packet
, &index
, &expect
, FALSE
, context
, sizeof(context
) );
681 winetest_push_context( "%s expect[%ld]", context
, index
);
682 ok( code
== expect
.code
, "got %#lx, expected %#lx\n", code
, expect
.code
);
683 ok( packet
->reportId
== expect
.report_id
, "got id %u\n", packet
->reportId
);
684 ok( packet
->reportBufferLen
== expect
.report_len
, "got len %lu\n", packet
->reportBufferLen
);
685 winetest_pop_context();
687 irp
->IoStatus
.Information
= expect
.ret_length
? expect
.ret_length
: expect
.report_len
;
688 memcpy( packet
->reportBuffer
, expect
.report_buf
, irp
->IoStatus
.Information
);
689 ret
= expect
.ret_status
;
693 case IOCTL_HID_SET_FEATURE
:
695 HID_XFER_PACKET
*packet
= irp
->UserBuffer
;
696 ULONG expected_size
= caps
.FeatureReportByteLength
- (report_id
? 0 : 1);
697 ok( in_size
== sizeof(*packet
), "got input size %lu\n", in_size
);
698 ok( !out_size
, "got output size %lu\n", out_size
);
700 ok( packet
->reportBufferLen
>= expected_size
, "got len %lu\n", packet
->reportBufferLen
);
701 ok( !!packet
->reportBuffer
, "got buffer %p\n", packet
->reportBuffer
);
703 expect_queue_next( &expect_queue
, code
, packet
, &index
, &expect
, TRUE
, context
, sizeof(context
) );
704 winetest_push_context( "%s expect[%ld]", context
, index
);
705 ok( code
== expect
.code
, "got %#lx, expected %#lx\n", code
, expect
.code
);
706 ok( packet
->reportId
== expect
.report_id
, "got id %u\n", packet
->reportId
);
707 ok( packet
->reportBufferLen
== expect
.report_len
, "got len %lu\n", packet
->reportBufferLen
);
708 check_buffer( packet
, &expect
);
709 winetest_pop_context();
711 irp
->IoStatus
.Information
= expect
.ret_length
? expect
.ret_length
: expect
.report_len
;
712 ret
= expect
.ret_status
;
716 case IOCTL_HID_GET_STRING
:
718 memcpy( irp
->UserBuffer
, L
"Wine Test", sizeof(L
"Wine Test") );
719 irp
->IoStatus
.Information
= sizeof(L
"Wine Test");
720 ret
= STATUS_SUCCESS
;
725 ok( 0, "unexpected ioctl %#lx\n", code
);
726 ret
= STATUS_NOT_IMPLEMENTED
;
729 winetest_pop_context();
731 if (ret
!= STATUS_PENDING
)
733 irp
->IoStatus
.Status
= ret
;
734 IoCompleteRequest( irp
, IO_NO_INCREMENT
);
739 static NTSTATUS (WINAPI
*hidclass_driver_ioctl
)( DEVICE_OBJECT
*device
, IRP
*irp
);
740 static NTSTATUS WINAPI
driver_ioctl( DEVICE_OBJECT
*device
, IRP
*irp
)
742 IO_STACK_LOCATION
*stack
= IoGetCurrentIrpStackLocation( irp
);
743 ULONG in_size
= stack
->Parameters
.DeviceIoControl
.InputBufferLength
;
744 ULONG code
= stack
->Parameters
.DeviceIoControl
.IoControlCode
;
747 if (winetest_debug
> 1) trace( "%s: device %p, code %#lx %s\n", __func__
, device
, code
, debugstr_ioctl(code
) );
749 if (!expect_hid_pdo
) expect_hid_pdo
= device
;
750 else ok( expect_hid_pdo
== device
, "got device %p\n", device
);
751 check_device( device
);
755 case IOCTL_WINETEST_HID_SET_EXPECT
:
756 expect_queue_reset( &expect_queue
, irp
->AssociatedIrp
.SystemBuffer
, in_size
);
757 irp
->IoStatus
.Status
= STATUS_SUCCESS
;
758 IoCompleteRequest( irp
, IO_NO_INCREMENT
);
759 return STATUS_SUCCESS
;
760 case IOCTL_WINETEST_HID_WAIT_EXPECT
:
761 return expect_queue_wait( &expect_queue
, irp
);
762 case IOCTL_WINETEST_HID_SEND_INPUT
:
763 input_queue_reset( &input_queue
, irp
->AssociatedIrp
.SystemBuffer
, in_size
);
764 irp
->IoStatus
.Status
= STATUS_SUCCESS
;
765 IoCompleteRequest( irp
, IO_NO_INCREMENT
);
766 return STATUS_SUCCESS
;
767 case IOCTL_WINETEST_HID_SET_CONTEXT
:
768 KeAcquireSpinLock( &expect_queue
.lock
, &irql
);
769 memcpy( expect_queue
.context
, irp
->AssociatedIrp
.SystemBuffer
, in_size
);
770 KeReleaseSpinLock( &expect_queue
.lock
, irql
);
772 irp
->IoStatus
.Status
= STATUS_SUCCESS
;
773 IoCompleteRequest( irp
, IO_NO_INCREMENT
);
774 return STATUS_SUCCESS
;
776 case IOCTL_WINETEST_REMOVE_DEVICE
:
777 case IOCTL_WINETEST_CREATE_DEVICE
:
778 ok( 0, "unexpected call\n" );
779 irp
->IoStatus
.Status
= STATUS_NOT_SUPPORTED
;
780 IoCompleteRequest( irp
, IO_NO_INCREMENT
);
781 return STATUS_NOT_SUPPORTED
;
784 return hidclass_driver_ioctl( device
, irp
);
787 static NTSTATUS WINAPI
driver_add_device( DRIVER_OBJECT
*driver
, DEVICE_OBJECT
*device
)
789 HID_DEVICE_EXTENSION
*ext
= device
->DeviceExtension
;
792 if (winetest_debug
> 1) trace( "%s: driver %p, device %p\n", __func__
, driver
, device
);
794 expect_hid_fdo
= device
;
795 expect_bus_pdo
= ext
->PhysicalDeviceObject
;
796 expect_hid_ext
= ext
->MiniDeviceExtension
;
799 ok( expect_bus_pdo
->AttachedDevice
== device
, "got AttachedDevice %p\n", expect_bus_pdo
->AttachedDevice
);
800 ok( driver
== expect_driver
, "got driver %p\n", driver
);
801 check_device( device
);
803 ret
= IoRegisterDeviceInterface( ext
->PhysicalDeviceObject
, &control_class
, NULL
, &control_symlink
);
804 ok( !ret
, "got %#lx\n", ret
);
806 if (winetest_debug
> 1) trace( "Created HID FDO %p for Bus PDO %p\n", device
, ext
->PhysicalDeviceObject
);
808 device
->Flags
&= ~DO_DEVICE_INITIALIZING
;
809 return STATUS_SUCCESS
;
812 static NTSTATUS WINAPI
driver_create( DEVICE_OBJECT
*device
, IRP
*irp
)
814 if (winetest_debug
> 1) trace( "%s: device %p\n", __func__
, device
);
815 ok( 0, "unexpected call\n" );
816 irp
->IoStatus
.Status
= STATUS_SUCCESS
;
817 IoCompleteRequest( irp
, IO_NO_INCREMENT
);
818 return STATUS_SUCCESS
;
821 static NTSTATUS WINAPI
driver_close( DEVICE_OBJECT
*device
, IRP
*irp
)
823 if (winetest_debug
> 1) trace( "%s: device %p\n", __func__
, device
);
824 ok( 0, "unexpected call\n" );
825 irp
->IoStatus
.Status
= STATUS_SUCCESS
;
826 IoCompleteRequest( irp
, IO_NO_INCREMENT
);
827 return STATUS_SUCCESS
;
830 static void WINAPI
driver_unload( DRIVER_OBJECT
*driver
)
832 if (winetest_debug
> 1) trace( "%s: driver %p\n", __func__
, driver
);
833 input_queue_cleanup( &input_queue
);
834 expect_queue_cleanup( &expect_queue
);
838 NTSTATUS WINAPI
DriverEntry( DRIVER_OBJECT
*driver
, UNICODE_STRING
*registry
)
840 static const int info_size
= offsetof( KEY_VALUE_PARTIAL_INFORMATION
, Data
);
841 HID_MINIDRIVER_REGISTRATION params
=
843 .Revision
= HID_REVISION
,
844 .DriverObject
= driver
,
845 .DeviceExtensionSize
= sizeof(struct hid_device
),
846 .RegistryPath
= registry
,
848 UNICODE_STRING name_str
;
849 OBJECT_ATTRIBUTES attr
;
855 expect_driver
= driver
;
857 if ((ret
= winetest_init())) return ret
;
858 if (winetest_debug
> 1) trace( "%s: driver %p\n", __func__
, driver
);
860 InitializeObjectAttributes( &attr
, registry
, 0, NULL
, NULL
);
861 ret
= ZwOpenKey( &hkey
, KEY_ALL_ACCESS
, &attr
);
862 ok( !ret
, "ZwOpenKey returned %#lx\n", ret
);
864 buffer
= ExAllocatePool( PagedPool
, info_size
+ EXPECT_QUEUE_BUFFER_SIZE
);
865 ok( buffer
!= NULL
, "ExAllocatePool failed\n" );
866 if (!buffer
) return STATUS_NO_MEMORY
;
868 RtlInitUnicodeString( &name_str
, L
"ReportID" );
869 size
= info_size
+ sizeof(report_id
);
870 ret
= ZwQueryValueKey( hkey
, &name_str
, KeyValuePartialInformation
, buffer
, size
, &size
);
871 ok( !ret
, "ZwQueryValueKey returned %#lx\n", ret
);
872 memcpy( &report_id
, buffer
+ info_size
, size
- info_size
);
874 RtlInitUnicodeString( &name_str
, L
"PolledMode" );
875 size
= info_size
+ sizeof(polled
);
876 ret
= ZwQueryValueKey( hkey
, &name_str
, KeyValuePartialInformation
, buffer
, size
, &size
);
877 ok( !ret
, "ZwQueryValueKey returned %#lx\n", ret
);
878 memcpy( &polled
, buffer
+ info_size
, size
- info_size
);
879 params
.DevicesArePolled
= polled
;
880 /* polled mode calls this in a state where printing anything locks the system up */
881 if (polled
) winetest_debug
= 0;
883 RtlInitUnicodeString( &name_str
, L
"Descriptor" );
884 size
= info_size
+ sizeof(report_descriptor_buf
);
885 ret
= ZwQueryValueKey( hkey
, &name_str
, KeyValuePartialInformation
, buffer
, size
, &size
);
886 ok( !ret
, "ZwQueryValueKey returned %#lx\n", ret
);
887 memcpy( report_descriptor_buf
, buffer
+ info_size
, size
- info_size
);
888 report_descriptor_len
= size
- info_size
;
890 RtlInitUnicodeString( &name_str
, L
"Attributes" );
891 size
= info_size
+ sizeof(attributes
);
892 ret
= ZwQueryValueKey( hkey
, &name_str
, KeyValuePartialInformation
, buffer
, size
, &size
);
893 ok( !ret
, "ZwQueryValueKey returned %#lx\n", ret
);
894 memcpy( &attributes
, buffer
+ info_size
, size
- info_size
);
896 RtlInitUnicodeString( &name_str
, L
"Caps" );
897 size
= info_size
+ sizeof(caps
);
898 ret
= ZwQueryValueKey( hkey
, &name_str
, KeyValuePartialInformation
, buffer
, size
, &size
);
899 ok( !ret
, "ZwQueryValueKey returned %#lx\n", ret
);
900 memcpy( &caps
, buffer
+ info_size
, size
- info_size
);
902 expect_queue_init( &expect_queue
);
903 RtlInitUnicodeString( &name_str
, L
"Expect" );
904 size
= info_size
+ EXPECT_QUEUE_BUFFER_SIZE
;
905 ret
= ZwQueryValueKey( hkey
, &name_str
, KeyValuePartialInformation
, buffer
, size
, &size
);
906 ok( !ret
, "ZwQueryValueKey returned %#lx\n", ret
);
907 expect_queue_reset( &expect_queue
, buffer
+ info_size
, size
- info_size
);
909 input_queue_init( &input_queue
);
910 RtlInitUnicodeString( &name_str
, L
"Input" );
911 size
= info_size
+ EXPECT_QUEUE_BUFFER_SIZE
;
912 ret
= ZwQueryValueKey( hkey
, &name_str
, KeyValuePartialInformation
, buffer
, size
, &size
);
913 ok( !ret
, "ZwQueryValueKey returned %#lx\n", ret
);
914 input_queue_reset( &input_queue
, buffer
+ info_size
, size
- info_size
);
916 RtlInitUnicodeString( &name_str
, L
"Context" );
917 size
= info_size
+ sizeof(expect_queue
.context
);
918 ret
= ZwQueryValueKey( hkey
, &name_str
, KeyValuePartialInformation
, buffer
, size
, &size
);
919 ok( !ret
, "ZwQueryValueKey returned %#lx\n", ret
);
920 memcpy( expect_queue
.context
, buffer
+ info_size
, size
- info_size
);
922 driver
->DriverExtension
->AddDevice
= driver_add_device
;
923 driver
->DriverUnload
= driver_unload
;
924 driver
->MajorFunction
[IRP_MJ_PNP
] = driver_pnp
;
925 driver
->MajorFunction
[IRP_MJ_DEVICE_CONTROL
] = driver_ioctl
;
926 driver
->MajorFunction
[IRP_MJ_INTERNAL_DEVICE_CONTROL
] = driver_internal_ioctl
;
927 driver
->MajorFunction
[IRP_MJ_CREATE
] = driver_create
;
928 driver
->MajorFunction
[IRP_MJ_CLOSE
] = driver_close
;
930 ExFreePool( buffer
);
932 ret
= HidRegisterMinidriver( ¶ms
);
933 ok( !ret
, "got %#lx\n", ret
);
935 hidclass_driver_ioctl
= driver
->MajorFunction
[IRP_MJ_DEVICE_CONTROL
];
936 driver
->MajorFunction
[IRP_MJ_DEVICE_CONTROL
] = driver_ioctl
;
938 return STATUS_SUCCESS
;