2 * Plug and Play test driver
4 * Copyright 2022 RĂ©mi Bernon for CodeWeavers
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
22 #pragma makedep testdll
29 #define WIN32_NO_STATUS
35 #include "ddk/hidsdi.h"
36 #include "ddk/hidport.h"
38 #include "wine/list.h"
40 #define WINE_DRIVER_TEST
42 #include "driver_hid.h"
44 typedef ULONG PNP_DEVICE_STATE
;
45 #define PNP_DEVICE_REMOVED 8
47 #define check_buffer( a, b ) check_buffer_( __LINE__, a, b )
48 static void check_buffer_( int line
, HID_XFER_PACKET
*packet
, struct hid_expect
*expect
)
52 match_len
= RtlCompareMemory( packet
->reportBuffer
, expect
->report_buf
, expect
->report_len
);
53 ok( match_len
== expect
->report_len
, "unexpected data:\n" );
54 if (match_len
== expect
->report_len
) return;
56 for (i
= 0; i
< packet
->reportBufferLen
;)
58 char buffer
[256], *buf
= buffer
;
59 buf
+= sprintf( buf
, "%08lx ", i
);
60 do buf
+= sprintf( buf
, " %02x", packet
->reportBuffer
[i
] );
61 while (++i
% 16 && i
< packet
->reportBufferLen
);
62 ok( 0, " %s\n", buffer
);
69 struct hid_expect
*pos
;
70 struct hid_expect
*end
;
71 struct hid_expect spurious
;
72 struct hid_expect
*buffer
;
77 static void expect_queue_init( struct expect_queue
*queue
)
79 KeInitializeSpinLock( &queue
->lock
);
80 queue
->buffer
= ExAllocatePool( PagedPool
, EXPECT_QUEUE_BUFFER_SIZE
);
81 RtlSecureZeroMemory( queue
->buffer
, EXPECT_QUEUE_BUFFER_SIZE
);
82 queue
->pos
= queue
->buffer
;
83 queue
->end
= queue
->buffer
;
86 static void expect_queue_cleanup( struct expect_queue
*queue
)
91 KeAcquireSpinLock( &queue
->lock
, &irql
);
92 if ((irp
= queue
->pending_wait
))
94 queue
->pending_wait
= NULL
;
95 if (!IoSetCancelRoutine( irp
, NULL
)) irp
= NULL
;
97 KeReleaseSpinLock( &queue
->lock
, irql
);
101 irp
->IoStatus
.Status
= STATUS_DELETE_PENDING
;
102 IoCompleteRequest( irp
, IO_NO_INCREMENT
);
105 ExFreePool( queue
->buffer
);
108 static void expect_queue_reset( struct expect_queue
*queue
, void *buffer
, unsigned int size
)
110 struct hid_expect
*missing
, *missing_end
, *tmp
;
114 missing
= ExAllocatePool( PagedPool
, EXPECT_QUEUE_BUFFER_SIZE
);
115 RtlSecureZeroMemory( missing
, EXPECT_QUEUE_BUFFER_SIZE
);
116 missing_end
= missing
;
118 KeAcquireSpinLock( &queue
->lock
, &irql
);
120 while (tmp
< queue
->end
) *missing_end
++ = *tmp
++;
122 queue
->pos
= queue
->buffer
;
123 queue
->end
= queue
->buffer
;
125 if (size
) memcpy( queue
->end
, buffer
, size
);
126 queue
->end
= queue
->end
+ size
/ sizeof(struct hid_expect
);
127 memcpy( context
, queue
->context
, sizeof(context
) );
128 KeReleaseSpinLock( &queue
->lock
, irql
);
131 while (tmp
!= missing_end
)
133 winetest_push_context( "%s expect[%Id]", context
, tmp
- missing
);
136 todo_wine_if( tmp
->todo
)
137 win_skip( "broken (code %#lx id %u len %u)\n", tmp
->code
, tmp
->report_id
, tmp
->report_len
);
141 todo_wine_if( tmp
->todo
)
142 ok( tmp
->wine_only
, "missing (code %#lx id %u len %u)\n", tmp
->code
, tmp
->report_id
, tmp
->report_len
);
144 winetest_pop_context();
148 ExFreePool( missing
);
151 static void WINAPI
wait_cancel_routine( DEVICE_OBJECT
*device
, IRP
*irp
)
153 struct expect_queue
*queue
= irp
->Tail
.Overlay
.DriverContext
[0];
156 IoReleaseCancelSpinLock( irp
->CancelIrql
);
158 KeAcquireSpinLock( &queue
->lock
, &irql
);
159 queue
->pending_wait
= NULL
;
160 KeReleaseSpinLock( &queue
->lock
, irql
);
162 irp
->IoStatus
.Information
= 0;
163 irp
->IoStatus
.Status
= STATUS_CANCELLED
;
164 IoCompleteRequest( irp
, IO_NO_INCREMENT
);
167 static NTSTATUS
expect_queue_add_pending_locked( struct expect_queue
*queue
, IRP
*irp
)
169 if (queue
->pending_wait
) return STATUS_INVALID_PARAMETER
;
171 IoSetCancelRoutine( irp
, wait_cancel_routine
);
172 if (irp
->Cancel
&& !IoSetCancelRoutine( irp
, NULL
))
173 return STATUS_CANCELLED
;
175 irp
->Tail
.Overlay
.DriverContext
[0] = queue
;
176 IoMarkIrpPending( irp
);
177 queue
->pending_wait
= irp
;
179 return STATUS_PENDING
;
182 static NTSTATUS
expect_queue_add_pending( struct expect_queue
*queue
, IRP
*irp
)
187 KeAcquireSpinLock( &queue
->lock
, &irql
);
188 status
= expect_queue_add_pending_locked( queue
, irp
);
189 KeReleaseSpinLock( &queue
->lock
, irql
);
194 /* complete an expect report previously marked as pending, or wait for one and then for the queue to empty */
195 static NTSTATUS
expect_queue_wait_pending( struct expect_queue
*queue
, IRP
*irp
)
201 KeAcquireSpinLock( &queue
->lock
, &irql
);
202 if ((pending
= queue
->pending_wait
))
204 queue
->pending_wait
= NULL
;
205 if (!IoSetCancelRoutine( pending
, NULL
)) pending
= NULL
;
208 if (pending
&& queue
->pos
== queue
->end
) status
= STATUS_SUCCESS
;
209 else status
= expect_queue_add_pending_locked( queue
, irp
);
210 KeReleaseSpinLock( &queue
->lock
, irql
);
214 pending
->IoStatus
.Status
= STATUS_SUCCESS
;
215 IoCompleteRequest( pending
, IO_NO_INCREMENT
);
221 /* wait for the expect queue to empty */
222 static NTSTATUS
expect_queue_wait( struct expect_queue
*queue
, IRP
*irp
)
227 irp
->IoStatus
.Information
= 0;
228 KeAcquireSpinLock( &queue
->lock
, &irql
);
229 if (queue
->pos
== queue
->end
) status
= STATUS_SUCCESS
;
230 else status
= expect_queue_add_pending_locked( queue
, irp
);
231 KeReleaseSpinLock( &queue
->lock
, irql
);
236 static void expect_queue_next( struct expect_queue
*queue
, ULONG code
, HID_XFER_PACKET
*packet
, LONG
*index
,
237 struct hid_expect
*expect
, BOOL compare_buf
, char *context
, ULONG context_size
)
239 struct hid_expect
*missing
, *missing_end
, *tmp
;
240 ULONG len
= packet
->reportBufferLen
;
241 BYTE
*buf
= packet
->reportBuffer
;
242 BYTE id
= packet
->reportId
;
246 missing
= ExAllocatePool( PagedPool
, EXPECT_QUEUE_BUFFER_SIZE
);
247 RtlSecureZeroMemory( missing
, EXPECT_QUEUE_BUFFER_SIZE
);
248 missing_end
= missing
;
250 KeAcquireSpinLock( &queue
->lock
, &irql
);
252 while (tmp
< queue
->end
)
254 if (winetest_platform_is_wine
&& !tmp
->todo
) break;
255 if (!winetest_platform_is_wine
&& !tmp
->broken
&& !tmp
->wine_only
) break;
256 if (tmp
->code
== code
&& tmp
->report_id
== id
&& tmp
->report_len
== len
&&
257 (!compare_buf
|| RtlCompareMemory( tmp
->report_buf
, buf
, len
) == len
))
259 *missing_end
++ = *tmp
++;
261 *index
= tmp
- queue
->buffer
;
262 if (tmp
< queue
->end
) queue
->pos
= tmp
+ 1;
263 else tmp
= &queue
->spurious
;
266 while (queue
->pos
< queue
->end
)
268 if (winetest_platform_is_wine
|| !queue
->pos
->wine_only
) break;
272 if ((irp
= queue
->pending_wait
))
274 /* don't mark the IRP as pending if someone's already waiting */
275 if (expect
->ret_status
== STATUS_PENDING
) expect
->ret_status
= STATUS_SUCCESS
;
277 /* complete the pending wait IRP if the queue is now empty */
278 if (queue
->pos
!= queue
->end
) irp
= NULL
;
281 queue
->pending_wait
= NULL
;
282 if (!IoSetCancelRoutine( irp
, NULL
)) irp
= NULL
;
286 memcpy( context
, queue
->context
, context_size
);
287 KeReleaseSpinLock( &queue
->lock
, irql
);
291 irp
->IoStatus
.Status
= STATUS_SUCCESS
;
292 IoCompleteRequest( irp
, IO_NO_INCREMENT
);
295 ok( tmp
!= &queue
->spurious
, "%s got spurious packet\n", context
);
297 winetest_push_context( "%s expect[%Id]", context
, tmp
- queue
->buffer
);
298 todo_wine_if( tmp
->todo
)
299 ok( !tmp
->wine_only
, "found code %#lx id %u len %u\n", tmp
->code
, tmp
->report_id
, tmp
->report_len
);
300 winetest_pop_context();
303 while (tmp
!= missing_end
)
305 winetest_push_context( "%s expect[%Id]", context
, tmp
- missing
);
308 todo_wine_if( tmp
->todo
)
309 win_skip( "broken (code %#lx id %u len %u)\n", tmp
->code
, tmp
->report_id
, tmp
->report_len
);
313 todo_wine_if( tmp
->todo
)
314 ok( tmp
->wine_only
, "missing (code %#lx id %u len %u)\n", tmp
->code
, tmp
->report_id
, tmp
->report_len
);
316 winetest_pop_context();
320 ExFreePool( missing
);
329 static IRP
*irp_queue_pop( struct irp_queue
*queue
)
334 KeAcquireSpinLock( &queue
->lock
, &irql
);
335 if (IsListEmpty( &queue
->list
)) irp
= NULL
;
336 else irp
= CONTAINING_RECORD( RemoveHeadList( &queue
->list
), IRP
, Tail
.Overlay
.ListEntry
);
337 KeReleaseSpinLock( &queue
->lock
, irql
);
342 static void irp_queue_push( struct irp_queue
*queue
, IRP
*irp
)
346 KeAcquireSpinLock( &queue
->lock
, &irql
);
347 InsertTailList( &queue
->list
, &irp
->Tail
.Overlay
.ListEntry
);
348 KeReleaseSpinLock( &queue
->lock
, irql
);
351 static void irp_queue_clear( struct irp_queue
*queue
)
355 while ((irp
= irp_queue_pop( queue
)))
357 irp
->IoStatus
.Status
= STATUS_DELETE_PENDING
;
358 IoCompleteRequest( irp
, IO_NO_INCREMENT
);
362 static void irp_queue_init( struct irp_queue
*queue
)
364 KeInitializeSpinLock( &queue
->lock
);
365 InitializeListHead( &queue
->list
);
372 struct hid_expect
*pos
;
373 struct hid_expect
*end
;
374 struct hid_expect
*buffer
;
375 struct irp_queue pending
;
378 static void input_queue_init( struct input_queue
*queue
, BOOL is_polled
)
380 KeInitializeSpinLock( &queue
->lock
);
381 queue
->is_polled
= is_polled
;
382 queue
->buffer
= ExAllocatePool( PagedPool
, EXPECT_QUEUE_BUFFER_SIZE
);
383 RtlSecureZeroMemory( queue
->buffer
, EXPECT_QUEUE_BUFFER_SIZE
);
384 queue
->pos
= queue
->buffer
;
385 queue
->end
= queue
->buffer
;
386 irp_queue_init( &queue
->pending
);
389 static void input_queue_cleanup( struct input_queue
*queue
)
391 ExFreePool( queue
->buffer
);
394 static BOOL
input_queue_read_locked( struct input_queue
*queue
, IRP
*irp
)
396 IO_STACK_LOCATION
*stack
= IoGetCurrentIrpStackLocation( irp
);
397 ULONG out_size
= stack
->Parameters
.DeviceIoControl
.OutputBufferLength
;
398 struct hid_expect
*tmp
= queue
->pos
;
400 if (tmp
>= queue
->end
) return FALSE
;
401 if (tmp
->ret_length
) out_size
= tmp
->ret_length
;
403 memcpy( irp
->UserBuffer
, tmp
->report_buf
, out_size
);
404 irp
->IoStatus
.Information
= out_size
;
405 irp
->IoStatus
.Status
= tmp
->ret_status
;
406 if (tmp
< queue
->end
) queue
->pos
= tmp
+ 1;
408 /* loop on the queue data in polled mode */
409 if (queue
->is_polled
&& queue
->pos
== queue
->end
) queue
->pos
= queue
->buffer
;
413 static NTSTATUS
input_queue_read( struct input_queue
*queue
, IRP
*irp
)
418 KeAcquireSpinLock( &queue
->lock
, &irql
);
419 if (input_queue_read_locked( queue
, irp
)) status
= STATUS_SUCCESS
;
422 IoMarkIrpPending( irp
);
423 irp_queue_push( &queue
->pending
, irp
);
424 status
= STATUS_PENDING
;
426 KeReleaseSpinLock( &queue
->lock
, irql
);
431 static void input_queue_reset( struct input_queue
*queue
, void *in_buf
, ULONG in_size
)
433 struct irp_queue completed
;
438 irp_queue_init( &completed
);
440 KeAcquireSpinLock( &queue
->lock
, &irql
);
441 remaining
= queue
->end
- queue
->pos
;
442 queue
->pos
= queue
->buffer
;
443 queue
->end
= queue
->buffer
;
444 memcpy( queue
->end
, in_buf
, in_size
);
445 queue
->end
+= in_size
/ sizeof(struct hid_expect
);
447 while (!queue
->is_polled
&& queue
->pos
< queue
->end
&& (irp
= irp_queue_pop( &queue
->pending
)))
449 input_queue_read_locked( queue
, irp
);
450 irp_queue_push( &completed
, irp
);
452 KeReleaseSpinLock( &queue
->lock
, irql
);
454 if (!queue
->is_polled
) ok( !remaining
, "unread input\n" );
456 while ((irp
= irp_queue_pop( &completed
))) IoCompleteRequest( irp
, IO_NO_INCREMENT
);
462 PNP_DEVICE_STATE state
;
466 static inline struct device
*impl_from_DEVICE_OBJECT( DEVICE_OBJECT
*device
)
468 return (struct device
*)device
->DeviceExtension
;
474 struct func_device
*fdo
; /* parent FDO */
476 WCHAR instance_id
[MAX_PATH
];
477 WCHAR device_id
[MAX_PATH
];
481 DWORD report_descriptor_len
;
482 char report_descriptor_buf
[MAX_HID_DESCRIPTOR_LEN
];
485 HID_DEVICE_ATTRIBUTES attributes
;
486 struct expect_queue expect_queue
;
487 struct input_queue input_queue
;
490 static inline struct phys_device
*pdo_from_DEVICE_OBJECT( DEVICE_OBJECT
*device
)
492 struct device
*impl
= impl_from_DEVICE_OBJECT( device
);
493 return CONTAINING_RECORD( impl
, struct phys_device
, base
);
499 DEVICE_OBJECT
*pdo
; /* lower PDO */
500 UNICODE_STRING control_iface
;
501 char devices_buffer
[offsetof( DEVICE_RELATIONS
, Objects
[128] )];
502 DEVICE_RELATIONS
*devices
;
505 static inline struct func_device
*fdo_from_DEVICE_OBJECT( DEVICE_OBJECT
*device
)
507 struct device
*impl
= impl_from_DEVICE_OBJECT( device
);
508 if (impl
->is_phys
) return CONTAINING_RECORD( impl
, struct phys_device
, base
)->fdo
;
509 return CONTAINING_RECORD( impl
, struct func_device
, base
);
512 #ifdef __ASM_USE_FASTCALL_WRAPPER
513 extern void *WINAPI
wrap_fastcall_func1( void *func
, const void *a
);
514 __ASM_STDCALL_FUNC( wrap_fastcall_func1
, 8,
517 "xchgl (%esp),%ecx\n\t"
519 #define call_fastcall_func1( func, a ) wrap_fastcall_func1( func, a )
521 #define call_fastcall_func1( func, a ) func( a )
524 static NTSTATUS
remove_child_device( struct func_device
*impl
, DEVICE_OBJECT
*device
)
526 NTSTATUS status
= STATUS_SUCCESS
;
530 KeAcquireSpinLock( &impl
->base
.lock
, &irql
);
531 for (i
= 0; i
< impl
->devices
->Count
; ++i
)
532 if (impl
->devices
->Objects
[i
] == device
) break;
533 if (i
== impl
->devices
->Count
) status
= STATUS_NOT_FOUND
;
534 else impl
->devices
->Objects
[i
] = impl
->devices
->Objects
[impl
->devices
->Count
--];
535 KeReleaseSpinLock( &impl
->base
.lock
, irql
);
540 static NTSTATUS
append_child_device( struct func_device
*impl
, DEVICE_OBJECT
*device
)
545 KeAcquireSpinLock( &impl
->base
.lock
, &irql
);
546 if (offsetof( DEVICE_RELATIONS
, Objects
[impl
->devices
->Count
+ 1] ) > sizeof(impl
->devices_buffer
))
547 status
= STATUS_NO_MEMORY
;
550 impl
->devices
->Objects
[impl
->devices
->Count
++] = device
;
551 status
= STATUS_SUCCESS
;
553 KeReleaseSpinLock( &impl
->base
.lock
, irql
);
558 static DEVICE_OBJECT
*find_child_device( struct func_device
*impl
, struct hid_device_desc
*desc
)
560 DEVICE_OBJECT
*device
= NULL
, **devices
;
561 WCHAR device_id
[MAX_PATH
];
565 swprintf( device_id
, MAX_PATH
, L
"WINETEST\\VID_%04X&PID_%04X", desc
->attributes
.VendorID
,
566 desc
->attributes
.ProductID
);
567 if (desc
->is_polled
) wcscat( device_id
, L
"&POLL" );
569 KeAcquireSpinLock( &impl
->base
.lock
, &irql
);
570 devices
= impl
->devices
->Objects
;
571 for (i
= 0; i
< impl
->devices
->Count
; ++i
)
573 struct phys_device
*phys
= pdo_from_DEVICE_OBJECT( (device
= devices
[i
]) );
574 if (!wcscmp( phys
->device_id
, device_id
)) break;
577 KeReleaseSpinLock( &impl
->base
.lock
, irql
);
582 static ULONG_PTR
get_device_relations( DEVICE_OBJECT
*device
, DEVICE_RELATIONS
*previous
,
583 ULONG count
, DEVICE_OBJECT
**devices
)
585 DEVICE_RELATIONS
*relations
;
586 ULONG new_count
= count
;
588 if (previous
) new_count
+= previous
->Count
;
589 if (!(relations
= ExAllocatePool( PagedPool
, offsetof( DEVICE_RELATIONS
, Objects
[new_count
] ) )))
591 ok( 0, "Failed to allocate memory\n" );
592 return (ULONG_PTR
)previous
;
595 if (!previous
) relations
->Count
= 0;
598 memcpy( relations
, previous
, offsetof( DEVICE_RELATIONS
, Objects
[previous
->Count
] ) );
599 ExFreePool( previous
);
604 call_fastcall_func1( ObfReferenceObject
, *devices
);
605 relations
->Objects
[relations
->Count
++] = *devices
++;
608 return (ULONG_PTR
)relations
;
611 static WCHAR
*query_instance_id( DEVICE_OBJECT
*device
)
613 struct phys_device
*impl
= pdo_from_DEVICE_OBJECT( device
);
614 DWORD size
= (wcslen( impl
->instance_id
) + 1) * sizeof(WCHAR
);
617 if ((dst
= ExAllocatePool( PagedPool
, size
)))
618 memcpy( dst
, impl
->instance_id
, size
);
623 static WCHAR
*query_hardware_ids( DEVICE_OBJECT
*device
)
625 struct phys_device
*impl
= pdo_from_DEVICE_OBJECT( device
);
626 DWORD size
= (wcslen( impl
->device_id
) + 1) * sizeof(WCHAR
);
629 if ((dst
= ExAllocatePool( PagedPool
, size
+ sizeof(WCHAR
) )))
631 memcpy( dst
, impl
->device_id
, size
);
632 dst
[size
/ sizeof(WCHAR
)] = 0;
638 static WCHAR
*query_compatible_ids( DEVICE_OBJECT
*device
)
640 static const WCHAR hid_compat_id
[] = L
"WINETEST\\WINE_COMP_HID";
641 static const WCHAR hid_poll_compat_id
[] = L
"WINETEST\\WINE_COMP_POLLHID";
642 struct phys_device
*impl
= pdo_from_DEVICE_OBJECT( device
);
643 const WCHAR
*compat_id
= impl
->input_queue
.is_polled
? hid_poll_compat_id
: hid_compat_id
;
644 DWORD size
= (wcslen( compat_id
) + 1) * sizeof(WCHAR
);
647 if ((dst
= ExAllocatePool( PagedPool
, size
+ sizeof(WCHAR
) )))
649 memcpy( dst
, compat_id
, size
);
650 dst
[size
/ sizeof(WCHAR
)] = 0;
656 static WCHAR
*query_container_id( DEVICE_OBJECT
*device
)
658 static const WCHAR winetest_id
[] = L
"WINETEST";
659 DWORD size
= sizeof(winetest_id
);
662 if ((dst
= ExAllocatePool( PagedPool
, size
)))
663 memcpy( dst
, winetest_id
, sizeof(winetest_id
) );
668 typedef struct _PNP_BUS_INFORMATION
671 INTERFACE_TYPE LegacyBusType
;
673 } PNP_BUS_INFORMATION
, *PPNP_BUS_INFORMATION
;
675 static PNP_BUS_INFORMATION
*query_bus_information( DEVICE_OBJECT
*device
)
677 DWORD size
= sizeof(PNP_BUS_INFORMATION
);
678 PNP_BUS_INFORMATION
*dst
;
680 if ((dst
= ExAllocatePool( PagedPool
, size
)))
682 memset( &dst
->BusTypeGuid
, 0, sizeof(dst
->BusTypeGuid
) );
683 dst
->LegacyBusType
= PNPBus
;
690 static WCHAR
*query_device_text( DEVICE_OBJECT
*device
)
692 static const WCHAR device_text
[] = L
"Wine Test HID device";
693 DWORD size
= sizeof(device_text
);
696 if ((dst
= ExAllocatePool( PagedPool
, size
)))
697 memcpy( dst
, device_text
, size
);
702 static NTSTATUS
pdo_pnp( DEVICE_OBJECT
*device
, IRP
*irp
)
704 IO_STACK_LOCATION
*stack
= IoGetCurrentIrpStackLocation( irp
);
705 struct phys_device
*impl
= pdo_from_DEVICE_OBJECT( device
);
706 struct func_device
*fdo
= fdo_from_DEVICE_OBJECT( device
);
707 ULONG code
= stack
->MinorFunction
;
708 PNP_DEVICE_STATE state
;
712 if (winetest_debug
> 1) trace( "%s: device %p, code %#lx %s\n", __func__
, device
, code
, debugstr_pnp(code
) );
716 case IRP_MN_START_DEVICE
:
717 case IRP_MN_CANCEL_REMOVE_DEVICE
:
718 case IRP_MN_SURPRISE_REMOVAL
:
719 case IRP_MN_QUERY_REMOVE_DEVICE
:
720 case IRP_MN_REMOVE_DEVICE
:
721 state
= (code
== IRP_MN_START_DEVICE
|| code
== IRP_MN_CANCEL_REMOVE_DEVICE
) ? 0 : PNP_DEVICE_REMOVED
;
722 KeAcquireSpinLock( &impl
->base
.lock
, &irql
);
723 impl
->base
.state
= state
;
724 irp_queue_clear( &impl
->input_queue
.pending
);
725 KeReleaseSpinLock( &impl
->base
.lock
, irql
);
726 if (code
!= IRP_MN_REMOVE_DEVICE
) status
= STATUS_SUCCESS
;
729 irp
->IoStatus
.Status
= STATUS_SUCCESS
;
730 IoCompleteRequest( irp
, IO_NO_INCREMENT
);
731 if (remove_child_device( fdo
, device
))
733 input_queue_cleanup( &impl
->input_queue
);
734 expect_queue_cleanup( &impl
->expect_queue
);
735 irp
= impl
->pending_remove
;
736 IoDeleteDevice( device
);
737 if (winetest_debug
> 1) trace( "Deleted Bus PDO %p\n", device
);
740 irp
->IoStatus
.Status
= STATUS_SUCCESS
;
741 IoCompleteRequest( irp
, IO_NO_INCREMENT
);
744 return STATUS_SUCCESS
;
747 case IRP_MN_QUERY_CAPABILITIES
:
749 DEVICE_CAPABILITIES
*caps
= stack
->Parameters
.DeviceCapabilities
.Capabilities
;
751 caps
->SilentInstall
= 1;
752 caps
->SurpriseRemovalOK
= 1;
753 /* caps->RawDeviceOK = 1; */
754 status
= STATUS_SUCCESS
;
757 case IRP_MN_QUERY_ID
:
759 BUS_QUERY_ID_TYPE type
= stack
->Parameters
.QueryId
.IdType
;
762 case BusQueryDeviceID
:
763 case BusQueryHardwareIDs
:
764 irp
->IoStatus
.Information
= (ULONG_PTR
)query_hardware_ids( device
);
765 if (!irp
->IoStatus
.Information
) status
= STATUS_NO_MEMORY
;
766 else status
= STATUS_SUCCESS
;
768 case BusQueryInstanceID
:
769 irp
->IoStatus
.Information
= (ULONG_PTR
)query_instance_id( device
);
770 if (!irp
->IoStatus
.Information
) status
= STATUS_NO_MEMORY
;
771 else status
= STATUS_SUCCESS
;
773 case BusQueryCompatibleIDs
:
774 irp
->IoStatus
.Information
= (ULONG_PTR
)query_compatible_ids( device
);
775 if (!irp
->IoStatus
.Information
) status
= STATUS_NO_MEMORY
;
776 else status
= STATUS_SUCCESS
;
778 case BusQueryContainerID
:
779 irp
->IoStatus
.Information
= (ULONG_PTR
)query_container_id( device
);
780 if (!irp
->IoStatus
.Information
) status
= STATUS_NO_MEMORY
;
781 else status
= STATUS_SUCCESS
;
784 ok( 0, "IRP_MN_QUERY_ID type %u, not implemented!\n", type
);
785 status
= STATUS_NOT_SUPPORTED
;
790 case IRP_MN_QUERY_BUS_INFORMATION
:
791 irp
->IoStatus
.Information
= (ULONG_PTR
)query_bus_information( device
);
792 if (!irp
->IoStatus
.Information
) status
= STATUS_NO_MEMORY
;
793 else status
= STATUS_SUCCESS
;
795 case IRP_MN_QUERY_DEVICE_TEXT
:
796 irp
->IoStatus
.Information
= (ULONG_PTR
)query_device_text( device
);
797 if (!irp
->IoStatus
.Information
) status
= STATUS_NO_MEMORY
;
798 else status
= STATUS_SUCCESS
;
800 case IRP_MN_QUERY_PNP_DEVICE_STATE
:
801 irp
->IoStatus
.Information
= impl
->base
.state
;
802 status
= STATUS_SUCCESS
;
804 case IRP_MN_QUERY_DEVICE_RELATIONS
:
806 DEVICE_RELATION_TYPE type
= stack
->Parameters
.QueryDeviceRelations
.Type
;
810 if (winetest_debug
> 1) trace( "pdo_pnp IRP_MN_QUERY_DEVICE_RELATIONS BusRelations\n" );
811 ok( irp
->IoStatus
.Information
, "got unexpected BusRelations relations\n" );
812 status
= irp
->IoStatus
.Status
;
814 case EjectionRelations
:
815 if (winetest_debug
> 1) trace( "pdo_pnp IRP_MN_QUERY_DEVICE_RELATIONS EjectionRelations\n" );
816 ok( !irp
->IoStatus
.Information
, "got unexpected EjectionRelations relations\n" );
817 status
= irp
->IoStatus
.Status
;
819 case RemovalRelations
:
820 if (winetest_debug
> 1) trace( "pdo_pnp IRP_MN_QUERY_DEVICE_RELATIONS RemovalRelations\n" );
821 ok( irp
->IoStatus
.Information
, "got unexpected RemovalRelations relations\n" );
822 status
= irp
->IoStatus
.Status
;
824 case TargetDeviceRelation
:
825 if (winetest_debug
> 1) trace( "pdo_pnp IRP_MN_QUERY_DEVICE_RELATIONS TargetDeviceRelations\n" );
826 ok( !irp
->IoStatus
.Information
, "got unexpected TargetDeviceRelations relations\n" );
827 irp
->IoStatus
.Information
= get_device_relations( device
, (void *)irp
->IoStatus
.Information
, 1, &device
);
828 if (!irp
->IoStatus
.Information
) status
= STATUS_NO_MEMORY
;
829 else status
= STATUS_SUCCESS
;
832 ok( 0, "got unexpected IRP_MN_QUERY_DEVICE_RELATIONS type %#x\n", type
);
833 status
= irp
->IoStatus
.Status
;
839 if (winetest_debug
> 1) trace( "pdo_pnp code %#lx %s, not implemented!\n", code
, debugstr_pnp(code
) );
840 status
= irp
->IoStatus
.Status
;
844 irp
->IoStatus
.Status
= status
;
845 IoCompleteRequest( irp
, IO_NO_INCREMENT
);
849 static NTSTATUS
create_child_pdo( DEVICE_OBJECT
*device
, struct hid_device_desc
*desc
)
853 struct func_device
*fdo
= fdo_from_DEVICE_OBJECT( device
);
854 struct phys_device
*impl
;
855 UNICODE_STRING name_str
;
856 DEVICE_OBJECT
*child
;
857 WCHAR name
[MAX_PATH
];
860 if (winetest_debug
> 1) trace( "polled %u, report_id %u\n", desc
->is_polled
, desc
->use_report_id
);
862 swprintf( name
, MAX_PATH
, L
"\\Device\\WINETEST#%p&%p&%u", device
->DriverObject
, device
, index
++ );
863 RtlInitUnicodeString( &name_str
, name
);
865 if ((status
= IoCreateDevice( device
->DriverObject
, sizeof(struct phys_device
), &name_str
, 0, 0, FALSE
, &child
)))
867 ok( 0, "Failed to create gamepad device, status %#lx\n", status
);
871 impl
= pdo_from_DEVICE_OBJECT( child
);
872 KeInitializeSpinLock( &impl
->base
.lock
);
873 swprintf( impl
->device_id
, MAX_PATH
, L
"WINETEST\\VID_%04X&PID_%04X", desc
->attributes
.VendorID
,
874 desc
->attributes
.ProductID
);
875 /* use a different device ID so that driver cache select the polled driver */
876 if (desc
->is_polled
) wcscat( impl
->device_id
, L
"&POLL" );
877 swprintf( impl
->instance_id
, MAX_PATH
, L
"0&0000&0" );
878 impl
->base
.is_phys
= TRUE
;
881 impl
->use_report_id
= desc
->use_report_id
;
882 impl
->caps
= desc
->caps
;
883 impl
->attributes
= desc
->attributes
;
884 impl
->report_descriptor_len
= desc
->report_descriptor_len
;
885 memcpy( impl
->report_descriptor_buf
, desc
->report_descriptor_buf
, desc
->report_descriptor_len
);
886 input_queue_init( &impl
->input_queue
, desc
->is_polled
);
887 input_queue_reset( &impl
->input_queue
, desc
->input
, desc
->input_size
);
888 expect_queue_init( &impl
->expect_queue
);
889 expect_queue_reset( &impl
->expect_queue
, desc
->expect
, desc
->expect_size
);
890 memcpy( impl
->expect_queue
.context
, desc
->context
, desc
->context_size
);
892 if (winetest_debug
> 1) trace( "Created Bus PDO %p for Bus FDO %p\n", child
, device
);
894 append_child_device( fdo
, child
);
895 IoInvalidateDeviceRelations( fdo
->pdo
, BusRelations
);
896 return STATUS_SUCCESS
;
899 static NTSTATUS
fdo_pnp( DEVICE_OBJECT
*device
, IRP
*irp
)
901 struct func_device
*impl
= fdo_from_DEVICE_OBJECT( device
);
902 IO_STACK_LOCATION
*stack
= IoGetCurrentIrpStackLocation( irp
);
903 char relations_buffer
[sizeof(impl
->devices_buffer
)];
904 DEVICE_RELATIONS
*relations
= (void *)relations_buffer
;
905 ULONG code
= stack
->MinorFunction
;
906 PNP_DEVICE_STATE state
;
910 if (winetest_debug
> 1) trace( "%s: device %p, code %#lx %s\n", __func__
, device
, code
, debugstr_pnp(code
) );
914 case IRP_MN_START_DEVICE
:
915 case IRP_MN_CANCEL_REMOVE_DEVICE
:
916 case IRP_MN_QUERY_REMOVE_DEVICE
:
917 case IRP_MN_SURPRISE_REMOVAL
:
918 case IRP_MN_REMOVE_DEVICE
:
919 state
= (code
== IRP_MN_START_DEVICE
|| code
== IRP_MN_CANCEL_REMOVE_DEVICE
) ? 0 : PNP_DEVICE_REMOVED
;
920 KeAcquireSpinLock( &impl
->base
.lock
, &irql
);
921 impl
->base
.state
= state
;
922 if (code
== IRP_MN_REMOVE_DEVICE
) memcpy( relations
, impl
->devices
, sizeof(relations_buffer
) );
923 impl
->devices
->Count
= 0;
924 KeReleaseSpinLock( &impl
->base
.lock
, irql
);
925 IoSetDeviceInterfaceState( &impl
->control_iface
, state
!= PNP_DEVICE_REMOVED
);
926 if (code
!= IRP_MN_REMOVE_DEVICE
) status
= STATUS_SUCCESS
;
929 while (relations
->Count
--) IoDeleteDevice( relations
->Objects
[relations
->Count
] );
930 IoSkipCurrentIrpStackLocation( irp
);
931 status
= IoCallDriver( impl
->pdo
, irp
);
932 IoDetachDevice( impl
->pdo
);
933 RtlFreeUnicodeString( &impl
->control_iface
);
934 IoDeleteDevice( device
);
935 if (winetest_debug
> 1) trace( "Deleted Bus FDO %p from PDO %p, status %#lx\n", impl
, impl
->pdo
, status
);
939 case IRP_MN_QUERY_PNP_DEVICE_STATE
:
940 KeAcquireSpinLock( &impl
->base
.lock
, &irql
);
941 irp
->IoStatus
.Information
= impl
->base
.state
;
942 KeReleaseSpinLock( &impl
->base
.lock
, irql
);
943 status
= STATUS_SUCCESS
;
945 case IRP_MN_QUERY_DEVICE_RELATIONS
:
947 DEVICE_RELATION_TYPE type
= stack
->Parameters
.QueryDeviceRelations
.Type
;
951 if (winetest_debug
> 1) trace( "fdo_pnp IRP_MN_QUERY_DEVICE_RELATIONS BusRelations\n" );
952 ok( !irp
->IoStatus
.Information
, "got unexpected BusRelations relations\n" );
953 KeAcquireSpinLock( &impl
->base
.lock
, &irql
);
954 memcpy( relations
, impl
->devices
, sizeof(relations_buffer
) );
955 KeReleaseSpinLock( &impl
->base
.lock
, irql
);
956 irp
->IoStatus
.Information
= get_device_relations( device
, (void *)irp
->IoStatus
.Information
,
957 relations
->Count
, relations
->Objects
);
958 if (!irp
->IoStatus
.Information
) status
= STATUS_NO_MEMORY
;
959 else status
= STATUS_SUCCESS
;
961 case RemovalRelations
:
962 if (winetest_debug
> 1) trace( "fdo_pnp IRP_MN_QUERY_DEVICE_RELATIONS RemovalRelations\n" );
963 ok( !irp
->IoStatus
.Information
, "got unexpected RemovalRelations relations\n" );
964 irp
->IoStatus
.Information
= get_device_relations( device
, (void *)irp
->IoStatus
.Information
,
966 if (!irp
->IoStatus
.Information
) status
= STATUS_NO_MEMORY
;
967 else status
= STATUS_SUCCESS
;
970 ok( 0, "got unexpected IRP_MN_QUERY_DEVICE_RELATIONS type %#x\n", type
);
971 status
= irp
->IoStatus
.Status
;
976 case IRP_MN_QUERY_CAPABILITIES
:
978 DEVICE_CAPABILITIES
*caps
= stack
->Parameters
.DeviceCapabilities
.Capabilities
;
979 caps
->EjectSupported
= TRUE
;
980 caps
->Removable
= TRUE
;
981 caps
->SilentInstall
= TRUE
;
982 caps
->SurpriseRemovalOK
= TRUE
;
983 status
= STATUS_SUCCESS
;
987 if (winetest_debug
> 1) trace( "fdo_pnp code %#lx %s, not implemented!\n", code
, debugstr_pnp(code
) );
988 status
= irp
->IoStatus
.Status
;
992 irp
->IoStatus
.Status
= status
;
993 IoSkipCurrentIrpStackLocation( irp
);
994 return IoCallDriver( impl
->pdo
, irp
);
997 static NTSTATUS WINAPI
driver_pnp( DEVICE_OBJECT
*device
, IRP
*irp
)
999 struct device
*impl
= impl_from_DEVICE_OBJECT( device
);
1000 if (impl
->is_phys
) return pdo_pnp( device
, irp
);
1001 return fdo_pnp( device
, irp
);
1004 static NTSTATUS
pdo_internal_ioctl( DEVICE_OBJECT
*device
, IRP
*irp
)
1006 IO_STACK_LOCATION
*stack
= IoGetCurrentIrpStackLocation( irp
);
1007 struct phys_device
*impl
= pdo_from_DEVICE_OBJECT( device
);
1008 const ULONG in_size
= stack
->Parameters
.DeviceIoControl
.InputBufferLength
;
1009 ULONG out_size
= stack
->Parameters
.DeviceIoControl
.OutputBufferLength
;
1010 const ULONG code
= stack
->Parameters
.DeviceIoControl
.IoControlCode
;
1011 struct hid_expect expect
= {0};
1018 if ((!impl
->input_queue
.is_polled
|| code
!= IOCTL_HID_READ_REPORT
) && winetest_debug
> 1)
1019 trace( "%s: device %p, code %#lx %s\n", __func__
, device
, code
, debugstr_ioctl(code
) );
1021 KeAcquireSpinLock( &impl
->base
.lock
, &irql
);
1022 removed
= impl
->base
.state
== PNP_DEVICE_REMOVED
;
1023 KeReleaseSpinLock( &impl
->base
.lock
, irql
);
1027 irp
->IoStatus
.Status
= STATUS_DELETE_PENDING
;
1028 IoCompleteRequest( irp
, IO_NO_INCREMENT
);
1029 return STATUS_DELETE_PENDING
;
1032 winetest_push_context( "id %d%s", impl
->use_report_id
, impl
->input_queue
.is_polled
? " poll" : "" );
1036 case IOCTL_HID_GET_DEVICE_DESCRIPTOR
:
1038 HID_DESCRIPTOR
*desc
= irp
->UserBuffer
;
1040 ok( !in_size
, "got input size %lu\n", in_size
);
1041 ok( out_size
== sizeof(*desc
), "got output size %lu\n", out_size
);
1043 if (out_size
== sizeof(*desc
))
1045 ok( !desc
->bLength
, "got size %u\n", desc
->bLength
);
1047 desc
->bLength
= sizeof(*desc
);
1048 desc
->bDescriptorType
= HID_HID_DESCRIPTOR_TYPE
;
1049 desc
->bcdHID
= HID_REVISION
;
1051 desc
->bNumDescriptors
= 1;
1052 desc
->DescriptorList
[0].bReportType
= HID_REPORT_DESCRIPTOR_TYPE
;
1053 desc
->DescriptorList
[0].wReportLength
= impl
->report_descriptor_len
;
1054 irp
->IoStatus
.Information
= sizeof(*desc
);
1056 status
= STATUS_SUCCESS
;
1060 case IOCTL_HID_GET_REPORT_DESCRIPTOR
:
1061 ok( !in_size
, "got input size %lu\n", in_size
);
1062 ok( out_size
== impl
->report_descriptor_len
, "got output size %lu\n", out_size
);
1064 if (out_size
== impl
->report_descriptor_len
)
1066 memcpy( irp
->UserBuffer
, impl
->report_descriptor_buf
, impl
->report_descriptor_len
);
1067 irp
->IoStatus
.Information
= impl
->report_descriptor_len
;
1069 status
= STATUS_SUCCESS
;
1072 case IOCTL_HID_GET_DEVICE_ATTRIBUTES
:
1073 ok( !in_size
, "got input size %lu\n", in_size
);
1074 ok( out_size
== sizeof(impl
->attributes
), "got output size %lu\n", out_size
);
1076 if (out_size
== sizeof(impl
->attributes
))
1078 memcpy( irp
->UserBuffer
, &impl
->attributes
, sizeof(impl
->attributes
) );
1079 irp
->IoStatus
.Information
= sizeof(impl
->attributes
);
1081 status
= STATUS_SUCCESS
;
1084 case IOCTL_HID_READ_REPORT
:
1086 ULONG expected_size
= impl
->caps
.InputReportByteLength
- (impl
->use_report_id
? 0 : 1);
1087 ok( !in_size
, "got input size %lu\n", in_size
);
1088 ok( out_size
== expected_size
, "got output size %lu\n", out_size
);
1089 status
= input_queue_read( &impl
->input_queue
, irp
);
1093 case IOCTL_HID_WRITE_REPORT
:
1095 HID_XFER_PACKET
*packet
= irp
->UserBuffer
;
1097 ok( in_size
== sizeof(*packet
), "got input size %lu\n", in_size
);
1098 ok( !out_size
, "got output size %lu\n", out_size
);
1099 ok( !!packet
->reportBuffer
, "got buffer %p\n", packet
->reportBuffer
);
1101 expect_queue_next( &impl
->expect_queue
, code
, packet
, &index
, &expect
, TRUE
, context
, sizeof(context
) );
1102 winetest_push_context( "%s expect[%ld]", context
, index
);
1103 ok( code
== expect
.code
, "got %#lx, expected %#lx\n", code
, expect
.code
);
1104 ok( packet
->reportId
== expect
.report_id
, "got id %u\n", packet
->reportId
);
1105 ok( packet
->reportBufferLen
== expect
.report_len
, "got len %lu\n", packet
->reportBufferLen
);
1106 check_buffer( packet
, &expect
);
1107 winetest_pop_context();
1109 irp
->IoStatus
.Information
= expect
.ret_length
? expect
.ret_length
: expect
.report_len
;
1110 status
= expect
.ret_status
;
1111 if (status
== STATUS_PENDING
) status
= expect_queue_add_pending( &impl
->expect_queue
, irp
);
1115 case IOCTL_HID_GET_INPUT_REPORT
:
1117 HID_XFER_PACKET
*packet
= irp
->UserBuffer
;
1119 ok( !in_size
, "got input size %lu\n", in_size
);
1120 ok( out_size
== sizeof(*packet
), "got output size %lu\n", out_size
);
1121 ok( !!packet
->reportBuffer
, "got buffer %p\n", packet
->reportBuffer
);
1123 expect_queue_next( &impl
->expect_queue
, code
, packet
, &index
, &expect
, FALSE
, context
, sizeof(context
) );
1124 winetest_push_context( "%s expect[%ld]", context
, index
);
1125 ok( code
== expect
.code
, "got %#lx, expected %#lx\n", code
, expect
.code
);
1126 ok( packet
->reportId
== expect
.report_id
, "got id %u\n", packet
->reportId
);
1127 ok( packet
->reportBufferLen
== expect
.report_len
, "got len %lu\n", packet
->reportBufferLen
);
1128 winetest_pop_context();
1130 irp
->IoStatus
.Information
= expect
.ret_length
? expect
.ret_length
: expect
.report_len
;
1131 memcpy( packet
->reportBuffer
, expect
.report_buf
, irp
->IoStatus
.Information
);
1132 status
= expect
.ret_status
;
1133 if (status
== STATUS_PENDING
) status
= expect_queue_add_pending( &impl
->expect_queue
, irp
);
1137 case IOCTL_HID_SET_OUTPUT_REPORT
:
1139 HID_XFER_PACKET
*packet
= irp
->UserBuffer
;
1141 ok( in_size
== sizeof(*packet
), "got input size %lu\n", in_size
);
1142 ok( !out_size
, "got output size %lu\n", out_size
);
1143 ok( !!packet
->reportBuffer
, "got buffer %p\n", packet
->reportBuffer
);
1145 expect_queue_next( &impl
->expect_queue
, code
, packet
, &index
, &expect
, TRUE
, context
, sizeof(context
) );
1146 winetest_push_context( "%s expect[%ld]", context
, index
);
1147 ok( code
== expect
.code
, "got %#lx, expected %#lx\n", code
, expect
.code
);
1148 ok( packet
->reportId
== expect
.report_id
, "got id %u\n", packet
->reportId
);
1149 ok( packet
->reportBufferLen
== expect
.report_len
, "got len %lu\n", packet
->reportBufferLen
);
1150 check_buffer( packet
, &expect
);
1151 winetest_pop_context();
1153 irp
->IoStatus
.Information
= expect
.ret_length
? expect
.ret_length
: expect
.report_len
;
1154 status
= expect
.ret_status
;
1155 if (status
== STATUS_PENDING
) status
= expect_queue_add_pending( &impl
->expect_queue
, irp
);
1159 case IOCTL_HID_GET_FEATURE
:
1161 HID_XFER_PACKET
*packet
= irp
->UserBuffer
;
1163 ok( !in_size
, "got input size %lu\n", in_size
);
1164 ok( out_size
== sizeof(*packet
), "got output size %lu\n", out_size
);
1165 ok( !!packet
->reportBuffer
, "got buffer %p\n", packet
->reportBuffer
);
1167 expect_queue_next( &impl
->expect_queue
, code
, packet
, &index
, &expect
, FALSE
, context
, sizeof(context
) );
1168 winetest_push_context( "%s expect[%ld]", context
, index
);
1169 ok( code
== expect
.code
, "got %#lx, expected %#lx\n", code
, expect
.code
);
1170 ok( packet
->reportId
== expect
.report_id
, "got id %u\n", packet
->reportId
);
1171 ok( packet
->reportBufferLen
== expect
.report_len
, "got len %lu\n", packet
->reportBufferLen
);
1172 winetest_pop_context();
1174 irp
->IoStatus
.Information
= expect
.ret_length
? expect
.ret_length
: expect
.report_len
;
1175 memcpy( packet
->reportBuffer
, expect
.report_buf
, irp
->IoStatus
.Information
);
1176 status
= expect
.ret_status
;
1177 if (status
== STATUS_PENDING
) status
= expect_queue_add_pending( &impl
->expect_queue
, irp
);
1181 case IOCTL_HID_SET_FEATURE
:
1183 HID_XFER_PACKET
*packet
= irp
->UserBuffer
;
1185 ok( in_size
== sizeof(*packet
), "got input size %lu\n", in_size
);
1186 ok( !out_size
, "got output size %lu\n", out_size
);
1187 ok( !!packet
->reportBuffer
, "got buffer %p\n", packet
->reportBuffer
);
1189 expect_queue_next( &impl
->expect_queue
, code
, packet
, &index
, &expect
, TRUE
, context
, sizeof(context
) );
1190 winetest_push_context( "%s expect[%ld]", context
, index
);
1191 ok( code
== expect
.code
, "got %#lx, expected %#lx\n", code
, expect
.code
);
1192 ok( packet
->reportId
== expect
.report_id
, "got id %u\n", packet
->reportId
);
1193 ok( packet
->reportBufferLen
== expect
.report_len
, "got len %lu\n", packet
->reportBufferLen
);
1194 check_buffer( packet
, &expect
);
1195 winetest_pop_context();
1197 irp
->IoStatus
.Information
= expect
.ret_length
? expect
.ret_length
: expect
.report_len
;
1198 status
= expect
.ret_status
;
1199 if (status
== STATUS_PENDING
) status
= expect_queue_add_pending( &impl
->expect_queue
, irp
);
1203 case IOCTL_HID_GET_STRING
:
1204 memcpy( irp
->UserBuffer
, L
"Wine Test", sizeof(L
"Wine Test") );
1205 irp
->IoStatus
.Information
= sizeof(L
"Wine Test");
1206 status
= STATUS_SUCCESS
;
1209 case IOCTL_GET_PHYSICAL_DESCRIPTOR
:
1210 irp
->IoStatus
.Information
= 0;
1211 status
= STATUS_NOT_SUPPORTED
;
1215 ok( 0, "unexpected call\n" );
1216 status
= irp
->IoStatus
.Status
;
1220 winetest_pop_context();
1222 if (status
!= STATUS_PENDING
)
1224 irp
->IoStatus
.Status
= status
;
1225 IoCompleteRequest( irp
, IO_NO_INCREMENT
);
1230 static NTSTATUS
fdo_internal_ioctl( DEVICE_OBJECT
*device
, IRP
*irp
)
1232 IO_STACK_LOCATION
*stack
= IoGetCurrentIrpStackLocation( irp
);
1233 ULONG code
= stack
->Parameters
.DeviceIoControl
.IoControlCode
;
1235 if (winetest_debug
> 1) trace( "%s: device %p, code %#lx %s\n", __func__
, device
, code
, debugstr_ioctl(code
) );
1236 ok( 0, "unexpected call\n" );
1238 irp
->IoStatus
.Status
= STATUS_NOT_SUPPORTED
;
1239 IoCompleteRequest( irp
, IO_NO_INCREMENT
);
1240 return STATUS_NOT_SUPPORTED
;
1243 static NTSTATUS WINAPI
driver_internal_ioctl( DEVICE_OBJECT
*device
, IRP
*irp
)
1245 struct device
*impl
= impl_from_DEVICE_OBJECT( device
);
1246 if (impl
->is_phys
) return pdo_internal_ioctl( device
, irp
);
1247 return fdo_internal_ioctl( device
, irp
);
1250 static NTSTATUS
pdo_handle_ioctl( struct phys_device
*impl
, IRP
*irp
, ULONG code
, void *in_buffer
, ULONG in_size
)
1256 case IOCTL_WINETEST_HID_SET_EXPECT
:
1257 if (in_size
> EXPECT_QUEUE_BUFFER_SIZE
) return STATUS_BUFFER_OVERFLOW
;
1258 expect_queue_reset( &impl
->expect_queue
, in_buffer
, in_size
);
1259 return STATUS_SUCCESS
;
1260 case IOCTL_WINETEST_HID_WAIT_EXPECT
:
1262 struct wait_expect_params
*wait_params
= (struct wait_expect_params
*)in_buffer
;
1263 if (in_size
< sizeof(*wait_params
)) return STATUS_BUFFER_TOO_SMALL
;
1264 if (!wait_params
->wait_pending
) return expect_queue_wait( &impl
->expect_queue
, irp
);
1265 else return expect_queue_wait_pending( &impl
->expect_queue
, irp
);
1267 case IOCTL_WINETEST_HID_SEND_INPUT
:
1268 if (in_size
> EXPECT_QUEUE_BUFFER_SIZE
) return STATUS_BUFFER_OVERFLOW
;
1269 input_queue_reset( &impl
->input_queue
, in_buffer
, in_size
);
1270 return STATUS_SUCCESS
;
1271 case IOCTL_WINETEST_HID_SET_CONTEXT
:
1272 if (in_size
> sizeof(impl
->expect_queue
.context
)) return STATUS_BUFFER_OVERFLOW
;
1273 KeAcquireSpinLock( &impl
->expect_queue
.lock
, &irql
);
1274 memcpy( impl
->expect_queue
.context
, in_buffer
, in_size
);
1275 KeReleaseSpinLock( &impl
->expect_queue
.lock
, irql
);
1276 return STATUS_SUCCESS
;
1277 case IOCTL_WINETEST_REMOVE_DEVICE
:
1278 KeAcquireSpinLock( &impl
->base
.lock
, &irql
);
1279 impl
->base
.state
= PNP_DEVICE_REMOVED
;
1280 irp_queue_clear( &impl
->input_queue
.pending
);
1281 KeReleaseSpinLock( &impl
->base
.lock
, irql
);
1282 impl
->pending_remove
= irp
;
1283 IoMarkIrpPending( irp
);
1284 return STATUS_PENDING
;
1285 case IOCTL_WINETEST_CREATE_DEVICE
:
1286 ok( 0, "unexpected call\n" );
1287 return irp
->IoStatus
.Status
;
1289 ok( 0, "unexpected call\n" );
1290 return irp
->IoStatus
.Status
;
1294 static NTSTATUS
pdo_ioctl( DEVICE_OBJECT
*device
, IRP
*irp
)
1296 IO_STACK_LOCATION
*stack
= IoGetCurrentIrpStackLocation( irp
);
1297 struct phys_device
*impl
= pdo_from_DEVICE_OBJECT( device
);
1298 ULONG in_size
= stack
->Parameters
.DeviceIoControl
.InputBufferLength
;
1299 struct hid_device_desc
*desc
= irp
->AssociatedIrp
.SystemBuffer
;
1300 ULONG code
= stack
->Parameters
.DeviceIoControl
.IoControlCode
;
1303 if (winetest_debug
> 1) trace( "%s: device %p, code %#lx %s\n", __func__
, device
, code
, debugstr_ioctl(code
) );
1305 status
= pdo_handle_ioctl( impl
, irp
, code
, desc
+ 1, in_size
- sizeof(*desc
) );
1307 if (status
!= STATUS_PENDING
)
1309 irp
->IoStatus
.Status
= status
;
1310 IoCompleteRequest( irp
, IO_NO_INCREMENT
);
1315 static NTSTATUS
fdo_ioctl( DEVICE_OBJECT
*device
, IRP
*irp
)
1317 IO_STACK_LOCATION
*stack
= IoGetCurrentIrpStackLocation( irp
);
1318 ULONG in_size
= stack
->Parameters
.DeviceIoControl
.InputBufferLength
;
1319 struct hid_device_desc
*desc
= irp
->AssociatedIrp
.SystemBuffer
;
1320 ULONG code
= stack
->Parameters
.DeviceIoControl
.IoControlCode
;
1321 struct func_device
*impl
= fdo_from_DEVICE_OBJECT( device
);
1322 struct phys_device
*pdo
;
1325 if (winetest_debug
> 1) trace( "%s: device %p, code %#lx %s\n", __func__
, device
, code
, debugstr_ioctl(code
) );
1329 case IOCTL_WINETEST_CREATE_DEVICE
:
1330 if (in_size
< sizeof(*desc
)) status
= STATUS_INVALID_PARAMETER
;
1331 else status
= create_child_pdo( device
, desc
);
1333 case IOCTL_WINETEST_REMOVE_DEVICE
:
1334 if (in_size
< sizeof(*desc
))
1335 status
= STATUS_INVALID_PARAMETER
;
1336 else if (!(device
= find_child_device( impl
, desc
)) || remove_child_device( impl
, device
))
1337 status
= STATUS_NO_SUCH_DEVICE
;
1340 status
= pdo_ioctl( device
, irp
);
1341 IoInvalidateDeviceRelations( impl
->pdo
, BusRelations
);
1345 case IOCTL_WINETEST_HID_SET_EXPECT
:
1346 case IOCTL_WINETEST_HID_WAIT_EXPECT
:
1347 case IOCTL_WINETEST_HID_SEND_INPUT
:
1348 case IOCTL_WINETEST_HID_SET_CONTEXT
:
1349 if (in_size
< sizeof(*desc
))
1350 status
= STATUS_INVALID_PARAMETER
;
1351 else if (!(device
= find_child_device( impl
, desc
)) || !(pdo
= pdo_from_DEVICE_OBJECT( device
)))
1352 status
= STATUS_NO_SUCH_DEVICE
;
1354 status
= pdo_handle_ioctl( pdo
, irp
, code
, desc
+ 1, in_size
- sizeof(*desc
) );
1357 ok( 0, "unexpected call\n" );
1358 status
= irp
->IoStatus
.Status
;
1362 irp
->IoStatus
.Status
= status
;
1363 IoCompleteRequest( irp
, IO_NO_INCREMENT
);
1367 static NTSTATUS WINAPI
driver_ioctl( DEVICE_OBJECT
*device
, IRP
*irp
)
1369 struct device
*impl
= impl_from_DEVICE_OBJECT( device
);
1370 if (impl
->is_phys
) return pdo_ioctl( device
, irp
);
1371 return fdo_ioctl( device
, irp
);
1374 static NTSTATUS WINAPI
driver_add_device( DRIVER_OBJECT
*driver
, DEVICE_OBJECT
*device
)
1376 struct func_device
*impl
;
1377 DEVICE_OBJECT
*child
;
1380 if (winetest_debug
> 1) trace( "%s: driver %p, device %p\n", __func__
, driver
, device
);
1382 if ((status
= IoCreateDevice( driver
, sizeof(struct func_device
), NULL
, FILE_DEVICE_BUS_EXTENDER
, 0, FALSE
, &child
)))
1384 ok( 0, "Failed to create FDO, status %#lx.\n", status
);
1388 impl
= (struct func_device
*)child
->DeviceExtension
;
1389 impl
->devices
= (void *)impl
->devices_buffer
;
1390 KeInitializeSpinLock( &impl
->base
.lock
);
1393 status
= IoRegisterDeviceInterface( impl
->pdo
, &control_class
, NULL
, &impl
->control_iface
);
1394 ok( !status
, "IoRegisterDeviceInterface returned %#lx\n", status
);
1396 if (winetest_debug
> 1) trace( "Created Bus FDO %p for PDO %p\n", child
, device
);
1398 IoAttachDeviceToDeviceStack( child
, device
);
1399 child
->Flags
&= ~DO_DEVICE_INITIALIZING
;
1401 return STATUS_SUCCESS
;
1404 static NTSTATUS WINAPI
driver_create( DEVICE_OBJECT
*device
, IRP
*irp
)
1406 if (winetest_debug
> 1) trace( "%s: device %p, irp %p\n", __func__
, device
, irp
);
1408 irp
->IoStatus
.Status
= STATUS_SUCCESS
;
1409 IoCompleteRequest( irp
, IO_NO_INCREMENT
);
1410 return STATUS_SUCCESS
;
1413 static NTSTATUS WINAPI
driver_close( DEVICE_OBJECT
*device
, IRP
*irp
)
1415 if (winetest_debug
> 1) trace( "%s: device %p, irp %p\n", __func__
, device
, irp
);
1417 irp
->IoStatus
.Status
= STATUS_SUCCESS
;
1418 IoCompleteRequest( irp
, IO_NO_INCREMENT
);
1419 return STATUS_SUCCESS
;
1422 static void WINAPI
driver_unload( DRIVER_OBJECT
*driver
)
1424 if (winetest_debug
> 1) trace( "%s: driver %p\n", __func__
, driver
);
1428 NTSTATUS WINAPI
DriverEntry( DRIVER_OBJECT
*driver
, UNICODE_STRING
*registry
)
1432 if ((status
= winetest_init())) return status
;
1433 if (winetest_debug
> 1) trace( "%s: driver %p\n", __func__
, driver
);
1435 driver
->DriverExtension
->AddDevice
= driver_add_device
;
1436 driver
->DriverUnload
= driver_unload
;
1437 driver
->MajorFunction
[IRP_MJ_PNP
] = driver_pnp
;
1438 driver
->MajorFunction
[IRP_MJ_DEVICE_CONTROL
] = driver_ioctl
;
1439 driver
->MajorFunction
[IRP_MJ_INTERNAL_DEVICE_CONTROL
] = driver_internal_ioctl
;
1440 driver
->MajorFunction
[IRP_MJ_CREATE
] = driver_create
;
1441 driver
->MajorFunction
[IRP_MJ_CLOSE
] = driver_close
;
1443 return STATUS_SUCCESS
;