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
25 #define WIN32_NO_STATUS
31 #include "ddk/hidsdi.h"
32 #include "ddk/hidport.h"
34 #include "wine/list.h"
37 #include "driver_hid.h"
39 typedef ULONG PNP_DEVICE_STATE
;
40 #define PNP_DEVICE_REMOVED 8
42 #define check_buffer( a, b ) check_buffer_( __LINE__, a, b )
43 static void check_buffer_( int line
, HID_XFER_PACKET
*packet
, struct hid_expect
*expect
)
47 match_len
= RtlCompareMemory( packet
->reportBuffer
, expect
->report_buf
, expect
->report_len
);
48 ok( match_len
== expect
->report_len
, "unexpected data:\n" );
49 if (match_len
== expect
->report_len
) return;
51 for (i
= 0; i
< packet
->reportBufferLen
;)
53 char buffer
[256], *buf
= buffer
;
54 buf
+= sprintf( buf
, "%08lx ", i
);
55 do buf
+= sprintf( buf
, " %02x", packet
->reportBuffer
[i
] );
56 while (++i
% 16 && i
< packet
->reportBufferLen
);
57 ok( 0, " %s\n", buffer
);
61 #define EXPECT_QUEUE_BUFFER_SIZE (64 * sizeof(struct hid_expect))
66 struct hid_expect
*pos
;
67 struct hid_expect
*end
;
68 struct hid_expect spurious
;
69 struct hid_expect
*buffer
;
74 static void expect_queue_init( struct expect_queue
*queue
)
76 KeInitializeSpinLock( &queue
->lock
);
77 queue
->buffer
= ExAllocatePool( PagedPool
, EXPECT_QUEUE_BUFFER_SIZE
);
78 RtlSecureZeroMemory( queue
->buffer
, EXPECT_QUEUE_BUFFER_SIZE
);
79 queue
->pos
= queue
->buffer
;
80 queue
->end
= queue
->buffer
;
83 static void expect_queue_cleanup( struct expect_queue
*queue
)
88 KeAcquireSpinLock( &queue
->lock
, &irql
);
89 if ((irp
= queue
->pending_wait
))
91 queue
->pending_wait
= NULL
;
92 if (!IoSetCancelRoutine( irp
, NULL
)) irp
= NULL
;
94 KeReleaseSpinLock( &queue
->lock
, irql
);
98 irp
->IoStatus
.Status
= STATUS_DELETE_PENDING
;
99 IoCompleteRequest( irp
, IO_NO_INCREMENT
);
102 ExFreePool( queue
->buffer
);
105 static void expect_queue_reset( struct expect_queue
*queue
, void *buffer
, unsigned int size
)
107 struct hid_expect
*missing
, *missing_end
, *tmp
;
111 missing
= ExAllocatePool( PagedPool
, EXPECT_QUEUE_BUFFER_SIZE
);
112 RtlSecureZeroMemory( missing
, EXPECT_QUEUE_BUFFER_SIZE
);
113 missing_end
= missing
;
115 KeAcquireSpinLock( &queue
->lock
, &irql
);
117 while (tmp
< queue
->end
) *missing_end
++ = *tmp
++;
119 queue
->pos
= queue
->buffer
;
120 queue
->end
= queue
->buffer
;
122 if (size
) memcpy( queue
->end
, buffer
, size
);
123 queue
->end
= queue
->end
+ size
/ sizeof(struct hid_expect
);
124 memcpy( context
, queue
->context
, sizeof(context
) );
125 KeReleaseSpinLock( &queue
->lock
, irql
);
128 while (tmp
!= missing_end
)
130 winetest_push_context( "%s expect[%Id]", context
, tmp
- missing
);
133 todo_wine_if( tmp
->todo
)
134 win_skip( "broken (code %#lx id %u len %u)\n", tmp
->code
, tmp
->report_id
, tmp
->report_len
);
138 todo_wine_if( tmp
->todo
)
139 ok( tmp
->wine_only
, "missing (code %#lx id %u len %u)\n", tmp
->code
, tmp
->report_id
, tmp
->report_len
);
141 winetest_pop_context();
145 ExFreePool( missing
);
148 static void WINAPI
wait_cancel_routine( DEVICE_OBJECT
*device
, IRP
*irp
)
150 struct expect_queue
*queue
= irp
->Tail
.Overlay
.DriverContext
[0];
153 IoReleaseCancelSpinLock( irp
->CancelIrql
);
155 KeAcquireSpinLock( &queue
->lock
, &irql
);
156 queue
->pending_wait
= NULL
;
157 KeReleaseSpinLock( &queue
->lock
, irql
);
159 irp
->IoStatus
.Information
= 0;
160 irp
->IoStatus
.Status
= STATUS_CANCELLED
;
161 IoCompleteRequest( irp
, IO_NO_INCREMENT
);
164 static NTSTATUS
expect_queue_add_pending_locked( struct expect_queue
*queue
, IRP
*irp
)
166 if (queue
->pending_wait
) return STATUS_INVALID_PARAMETER
;
168 IoSetCancelRoutine( irp
, wait_cancel_routine
);
169 if (irp
->Cancel
&& !IoSetCancelRoutine( irp
, NULL
))
170 return STATUS_CANCELLED
;
172 irp
->Tail
.Overlay
.DriverContext
[0] = queue
;
173 IoMarkIrpPending( irp
);
174 queue
->pending_wait
= irp
;
176 return STATUS_PENDING
;
179 static NTSTATUS
expect_queue_add_pending( struct expect_queue
*queue
, IRP
*irp
)
184 KeAcquireSpinLock( &queue
->lock
, &irql
);
185 status
= expect_queue_add_pending_locked( queue
, irp
);
186 KeReleaseSpinLock( &queue
->lock
, irql
);
191 /* complete an expect report previously marked as pending, or wait for one and then for the queue to empty */
192 static NTSTATUS
expect_queue_wait_pending( struct expect_queue
*queue
, IRP
*irp
)
198 KeAcquireSpinLock( &queue
->lock
, &irql
);
199 if ((pending
= queue
->pending_wait
))
201 queue
->pending_wait
= NULL
;
202 if (!IoSetCancelRoutine( pending
, NULL
)) pending
= NULL
;
205 if (pending
&& queue
->pos
== queue
->end
) status
= STATUS_SUCCESS
;
206 else status
= expect_queue_add_pending_locked( queue
, irp
);
207 KeReleaseSpinLock( &queue
->lock
, irql
);
211 pending
->IoStatus
.Status
= STATUS_SUCCESS
;
212 IoCompleteRequest( pending
, IO_NO_INCREMENT
);
218 /* wait for the expect queue to empty */
219 static NTSTATUS
expect_queue_wait( struct expect_queue
*queue
, IRP
*irp
)
224 irp
->IoStatus
.Information
= 0;
225 KeAcquireSpinLock( &queue
->lock
, &irql
);
226 if (queue
->pos
== queue
->end
) status
= STATUS_SUCCESS
;
227 else status
= expect_queue_add_pending_locked( queue
, irp
);
228 KeReleaseSpinLock( &queue
->lock
, irql
);
233 static void expect_queue_next( struct expect_queue
*queue
, ULONG code
, HID_XFER_PACKET
*packet
, LONG
*index
,
234 struct hid_expect
*expect
, BOOL compare_buf
, char *context
, ULONG context_size
)
236 struct hid_expect
*missing
, *missing_end
, *tmp
;
237 ULONG len
= packet
->reportBufferLen
;
238 BYTE
*buf
= packet
->reportBuffer
;
239 BYTE id
= packet
->reportId
;
243 missing
= ExAllocatePool( PagedPool
, EXPECT_QUEUE_BUFFER_SIZE
);
244 RtlSecureZeroMemory( missing
, EXPECT_QUEUE_BUFFER_SIZE
);
245 missing_end
= missing
;
247 KeAcquireSpinLock( &queue
->lock
, &irql
);
249 while (tmp
< queue
->end
)
251 if (running_under_wine
&& !tmp
->todo
) break;
252 if (!running_under_wine
&& !tmp
->broken
&& !tmp
->wine_only
) break;
253 if (tmp
->code
== code
&& tmp
->report_id
== id
&& tmp
->report_len
== len
&&
254 (!compare_buf
|| RtlCompareMemory( tmp
->report_buf
, buf
, len
) == len
))
256 *missing_end
++ = *tmp
++;
258 *index
= tmp
- queue
->buffer
;
259 if (tmp
< queue
->end
) queue
->pos
= tmp
+ 1;
260 else tmp
= &queue
->spurious
;
263 while (queue
->pos
< queue
->end
)
265 if (running_under_wine
|| !queue
->pos
->wine_only
) break;
269 if ((irp
= queue
->pending_wait
))
271 /* don't mark the IRP as pending if someone's already waiting */
272 if (expect
->ret_status
== STATUS_PENDING
) expect
->ret_status
= STATUS_SUCCESS
;
274 /* complete the pending wait IRP if the queue is now empty */
275 if (queue
->pos
!= queue
->end
) irp
= NULL
;
278 queue
->pending_wait
= NULL
;
279 if (!IoSetCancelRoutine( irp
, NULL
)) irp
= NULL
;
283 memcpy( context
, queue
->context
, context_size
);
284 KeReleaseSpinLock( &queue
->lock
, irql
);
288 irp
->IoStatus
.Status
= STATUS_SUCCESS
;
289 IoCompleteRequest( irp
, IO_NO_INCREMENT
);
292 ok( tmp
!= &queue
->spurious
, "%s got spurious packet\n", context
);
294 winetest_push_context( "%s expect[%Id]", context
, tmp
- queue
->buffer
);
295 todo_wine_if( tmp
->todo
)
296 ok( !tmp
->wine_only
, "found code %#lx id %u len %u\n", tmp
->code
, tmp
->report_id
, tmp
->report_len
);
297 winetest_pop_context();
300 while (tmp
!= missing_end
)
302 winetest_push_context( "%s expect[%Id]", context
, tmp
- missing
);
305 todo_wine_if( tmp
->todo
)
306 win_skip( "broken (code %#lx id %u len %u)\n", tmp
->code
, tmp
->report_id
, tmp
->report_len
);
310 todo_wine_if( tmp
->todo
)
311 ok( tmp
->wine_only
, "missing (code %#lx id %u len %u)\n", tmp
->code
, tmp
->report_id
, tmp
->report_len
);
313 winetest_pop_context();
317 ExFreePool( missing
);
326 static IRP
*irp_queue_pop( struct irp_queue
*queue
)
331 KeAcquireSpinLock( &queue
->lock
, &irql
);
332 if (IsListEmpty( &queue
->list
)) irp
= NULL
;
333 else irp
= CONTAINING_RECORD( RemoveHeadList( &queue
->list
), IRP
, Tail
.Overlay
.ListEntry
);
334 KeReleaseSpinLock( &queue
->lock
, irql
);
339 static void irp_queue_push( struct irp_queue
*queue
, IRP
*irp
)
343 KeAcquireSpinLock( &queue
->lock
, &irql
);
344 InsertTailList( &queue
->list
, &irp
->Tail
.Overlay
.ListEntry
);
345 KeReleaseSpinLock( &queue
->lock
, irql
);
348 static void irp_queue_clear( struct irp_queue
*queue
)
352 while ((irp
= irp_queue_pop( queue
)))
354 irp
->IoStatus
.Status
= STATUS_DELETE_PENDING
;
355 IoCompleteRequest( irp
, IO_NO_INCREMENT
);
359 static void irp_queue_init( struct irp_queue
*queue
)
361 KeInitializeSpinLock( &queue
->lock
);
362 InitializeListHead( &queue
->list
);
369 struct hid_expect
*pos
;
370 struct hid_expect
*end
;
371 struct hid_expect
*buffer
;
372 struct irp_queue pending
;
375 static void input_queue_init( struct input_queue
*queue
, BOOL is_polled
)
377 KeInitializeSpinLock( &queue
->lock
);
378 queue
->is_polled
= is_polled
;
379 queue
->buffer
= ExAllocatePool( PagedPool
, EXPECT_QUEUE_BUFFER_SIZE
);
380 RtlSecureZeroMemory( queue
->buffer
, EXPECT_QUEUE_BUFFER_SIZE
);
381 queue
->pos
= queue
->buffer
;
382 queue
->end
= queue
->buffer
;
383 irp_queue_init( &queue
->pending
);
386 static void input_queue_cleanup( struct input_queue
*queue
)
388 ExFreePool( queue
->buffer
);
391 static BOOL
input_queue_read_locked( struct input_queue
*queue
, IRP
*irp
)
393 IO_STACK_LOCATION
*stack
= IoGetCurrentIrpStackLocation( irp
);
394 ULONG out_size
= stack
->Parameters
.DeviceIoControl
.OutputBufferLength
;
395 struct hid_expect
*tmp
= queue
->pos
;
397 if (tmp
>= queue
->end
) return FALSE
;
398 if (tmp
->ret_length
) out_size
= tmp
->ret_length
;
400 memcpy( irp
->UserBuffer
, tmp
->report_buf
, out_size
);
401 irp
->IoStatus
.Information
= out_size
;
402 irp
->IoStatus
.Status
= tmp
->ret_status
;
403 if (tmp
< queue
->end
) queue
->pos
= tmp
+ 1;
405 /* loop on the queue data in polled mode */
406 if (queue
->is_polled
&& queue
->pos
== queue
->end
) queue
->pos
= queue
->buffer
;
410 static NTSTATUS
input_queue_read( struct input_queue
*queue
, IRP
*irp
)
415 KeAcquireSpinLock( &queue
->lock
, &irql
);
416 if (input_queue_read_locked( queue
, irp
)) status
= STATUS_SUCCESS
;
419 IoMarkIrpPending( irp
);
420 irp_queue_push( &queue
->pending
, irp
);
421 status
= STATUS_PENDING
;
423 KeReleaseSpinLock( &queue
->lock
, irql
);
428 static void input_queue_reset( struct input_queue
*queue
, void *in_buf
, ULONG in_size
)
430 struct irp_queue completed
;
435 irp_queue_init( &completed
);
437 KeAcquireSpinLock( &queue
->lock
, &irql
);
438 remaining
= queue
->end
- queue
->pos
;
439 queue
->pos
= queue
->buffer
;
440 queue
->end
= queue
->buffer
;
441 memcpy( queue
->end
, in_buf
, in_size
);
442 queue
->end
+= in_size
/ sizeof(struct hid_expect
);
444 while (!queue
->is_polled
&& queue
->pos
< queue
->end
&& (irp
= irp_queue_pop( &queue
->pending
)))
446 input_queue_read_locked( queue
, irp
);
447 irp_queue_push( &completed
, irp
);
449 KeReleaseSpinLock( &queue
->lock
, irql
);
451 if (!queue
->is_polled
) ok( !remaining
, "unread input\n" );
453 while ((irp
= irp_queue_pop( &completed
))) IoCompleteRequest( irp
, IO_NO_INCREMENT
);
459 PNP_DEVICE_STATE state
;
463 static inline struct device
*impl_from_DEVICE_OBJECT( DEVICE_OBJECT
*device
)
465 return (struct device
*)device
->DeviceExtension
;
471 struct func_device
*fdo
; /* parent FDO */
473 WCHAR instance_id
[MAX_PATH
];
474 WCHAR device_id
[MAX_PATH
];
478 DWORD report_descriptor_len
;
479 char report_descriptor_buf
[MAX_HID_DESCRIPTOR_LEN
];
482 HID_DEVICE_ATTRIBUTES attributes
;
483 struct expect_queue expect_queue
;
484 struct input_queue input_queue
;
487 static inline struct phys_device
*pdo_from_DEVICE_OBJECT( DEVICE_OBJECT
*device
)
489 struct device
*impl
= impl_from_DEVICE_OBJECT( device
);
490 return CONTAINING_RECORD( impl
, struct phys_device
, base
);
496 DEVICE_OBJECT
*pdo
; /* lower PDO */
497 UNICODE_STRING control_iface
;
498 char devices_buffer
[offsetof( DEVICE_RELATIONS
, Objects
[128] )];
499 DEVICE_RELATIONS
*devices
;
502 static inline struct func_device
*fdo_from_DEVICE_OBJECT( DEVICE_OBJECT
*device
)
504 struct device
*impl
= impl_from_DEVICE_OBJECT( device
);
505 if (impl
->is_phys
) return CONTAINING_RECORD( impl
, struct phys_device
, base
)->fdo
;
506 return CONTAINING_RECORD( impl
, struct func_device
, base
);
509 #ifdef __ASM_USE_FASTCALL_WRAPPER
510 extern void *WINAPI
wrap_fastcall_func1( void *func
, const void *a
);
511 __ASM_STDCALL_FUNC( wrap_fastcall_func1
, 8,
514 "xchgl (%esp),%ecx\n\t"
516 #define call_fastcall_func1( func, a ) wrap_fastcall_func1( func, a )
518 #define call_fastcall_func1( func, a ) func( a )
521 static NTSTATUS
remove_child_device( struct func_device
*impl
, DEVICE_OBJECT
*device
)
523 NTSTATUS status
= STATUS_SUCCESS
;
527 KeAcquireSpinLock( &impl
->base
.lock
, &irql
);
528 for (i
= 0; i
< impl
->devices
->Count
; ++i
)
529 if (impl
->devices
->Objects
[i
] == device
) break;
530 if (i
== impl
->devices
->Count
) status
= STATUS_NOT_FOUND
;
531 else impl
->devices
->Objects
[i
] = impl
->devices
->Objects
[impl
->devices
->Count
--];
532 KeReleaseSpinLock( &impl
->base
.lock
, irql
);
537 static NTSTATUS
append_child_device( struct func_device
*impl
, DEVICE_OBJECT
*device
)
542 KeAcquireSpinLock( &impl
->base
.lock
, &irql
);
543 if (offsetof( DEVICE_RELATIONS
, Objects
[impl
->devices
->Count
+ 1] ) > sizeof(impl
->devices_buffer
))
544 status
= STATUS_NO_MEMORY
;
547 impl
->devices
->Objects
[impl
->devices
->Count
++] = device
;
548 status
= STATUS_SUCCESS
;
550 KeReleaseSpinLock( &impl
->base
.lock
, irql
);
555 static DEVICE_OBJECT
*find_child_device( struct func_device
*impl
, struct hid_device_desc
*desc
)
557 DEVICE_OBJECT
*device
= NULL
, **devices
;
558 WCHAR device_id
[MAX_PATH
];
562 swprintf( device_id
, MAX_PATH
, L
"WINETEST\\VID_%04X&PID_%04X", desc
->attributes
.VendorID
,
563 desc
->attributes
.ProductID
);
564 if (desc
->is_polled
) wcscat( device_id
, L
"&POLL" );
566 KeAcquireSpinLock( &impl
->base
.lock
, &irql
);
567 devices
= impl
->devices
->Objects
;
568 for (i
= 0; i
< impl
->devices
->Count
; ++i
)
570 struct phys_device
*phys
= pdo_from_DEVICE_OBJECT( (device
= devices
[i
]) );
571 if (!wcscmp( phys
->device_id
, device_id
)) break;
574 KeReleaseSpinLock( &impl
->base
.lock
, irql
);
579 static ULONG_PTR
get_device_relations( DEVICE_OBJECT
*device
, DEVICE_RELATIONS
*previous
,
580 ULONG count
, DEVICE_OBJECT
**devices
)
582 DEVICE_RELATIONS
*relations
;
583 ULONG new_count
= count
;
585 if (previous
) new_count
+= previous
->Count
;
586 if (!(relations
= ExAllocatePool( PagedPool
, offsetof( DEVICE_RELATIONS
, Objects
[new_count
] ) )))
588 ok( 0, "Failed to allocate memory\n" );
589 return (ULONG_PTR
)previous
;
592 if (!previous
) relations
->Count
= 0;
595 memcpy( relations
, previous
, offsetof( DEVICE_RELATIONS
, Objects
[previous
->Count
] ) );
596 ExFreePool( previous
);
601 call_fastcall_func1( ObfReferenceObject
, *devices
);
602 relations
->Objects
[relations
->Count
++] = *devices
++;
605 return (ULONG_PTR
)relations
;
608 static WCHAR
*query_instance_id( DEVICE_OBJECT
*device
)
610 struct phys_device
*impl
= pdo_from_DEVICE_OBJECT( device
);
611 DWORD size
= (wcslen( impl
->instance_id
) + 1) * sizeof(WCHAR
);
614 if ((dst
= ExAllocatePool( PagedPool
, size
)))
615 memcpy( dst
, impl
->instance_id
, size
);
620 static WCHAR
*query_hardware_ids( DEVICE_OBJECT
*device
)
622 struct phys_device
*impl
= pdo_from_DEVICE_OBJECT( device
);
623 DWORD size
= (wcslen( impl
->device_id
) + 1) * sizeof(WCHAR
);
626 if ((dst
= ExAllocatePool( PagedPool
, size
+ sizeof(WCHAR
) )))
628 memcpy( dst
, impl
->device_id
, size
);
629 dst
[size
/ sizeof(WCHAR
)] = 0;
635 static WCHAR
*query_compatible_ids( DEVICE_OBJECT
*device
)
637 static const WCHAR hid_compat_id
[] = L
"WINETEST\\WINE_COMP_HID";
638 static const WCHAR hid_poll_compat_id
[] = L
"WINETEST\\WINE_COMP_POLLHID";
639 struct phys_device
*impl
= pdo_from_DEVICE_OBJECT( device
);
640 const WCHAR
*compat_id
= impl
->input_queue
.is_polled
? hid_poll_compat_id
: hid_compat_id
;
641 DWORD size
= (wcslen( compat_id
) + 1) * sizeof(WCHAR
);
644 if ((dst
= ExAllocatePool( PagedPool
, size
+ sizeof(WCHAR
) )))
646 memcpy( dst
, compat_id
, size
);
647 dst
[size
/ sizeof(WCHAR
)] = 0;
653 static WCHAR
*query_container_id( DEVICE_OBJECT
*device
)
655 static const WCHAR winetest_id
[] = L
"WINETEST";
656 DWORD size
= sizeof(winetest_id
);
659 if ((dst
= ExAllocatePool( PagedPool
, size
)))
660 memcpy( dst
, winetest_id
, sizeof(winetest_id
) );
665 typedef struct _PNP_BUS_INFORMATION
668 INTERFACE_TYPE LegacyBusType
;
670 } PNP_BUS_INFORMATION
, *PPNP_BUS_INFORMATION
;
672 static PNP_BUS_INFORMATION
*query_bus_information( DEVICE_OBJECT
*device
)
674 DWORD size
= sizeof(PNP_BUS_INFORMATION
);
675 PNP_BUS_INFORMATION
*dst
;
677 if ((dst
= ExAllocatePool( PagedPool
, size
)))
679 memset( &dst
->BusTypeGuid
, 0, sizeof(dst
->BusTypeGuid
) );
680 dst
->LegacyBusType
= PNPBus
;
687 static WCHAR
*query_device_text( DEVICE_OBJECT
*device
)
689 static const WCHAR device_text
[] = L
"Wine Test HID device";
690 DWORD size
= sizeof(device_text
);
693 if ((dst
= ExAllocatePool( PagedPool
, size
)))
694 memcpy( dst
, device_text
, size
);
699 static NTSTATUS
pdo_pnp( DEVICE_OBJECT
*device
, IRP
*irp
)
701 IO_STACK_LOCATION
*stack
= IoGetCurrentIrpStackLocation( irp
);
702 struct phys_device
*impl
= pdo_from_DEVICE_OBJECT( device
);
703 struct func_device
*fdo
= fdo_from_DEVICE_OBJECT( device
);
704 ULONG code
= stack
->MinorFunction
;
705 PNP_DEVICE_STATE state
;
709 if (winetest_debug
> 1) trace( "%s: device %p, code %#lx %s\n", __func__
, device
, code
, debugstr_pnp(code
) );
713 case IRP_MN_START_DEVICE
:
714 case IRP_MN_CANCEL_REMOVE_DEVICE
:
715 case IRP_MN_SURPRISE_REMOVAL
:
716 case IRP_MN_QUERY_REMOVE_DEVICE
:
717 case IRP_MN_REMOVE_DEVICE
:
718 state
= (code
== IRP_MN_START_DEVICE
|| code
== IRP_MN_CANCEL_REMOVE_DEVICE
) ? 0 : PNP_DEVICE_REMOVED
;
719 KeAcquireSpinLock( &impl
->base
.lock
, &irql
);
720 impl
->base
.state
= state
;
721 irp_queue_clear( &impl
->input_queue
.pending
);
722 KeReleaseSpinLock( &impl
->base
.lock
, irql
);
723 if (code
!= IRP_MN_REMOVE_DEVICE
) status
= STATUS_SUCCESS
;
726 irp
->IoStatus
.Status
= STATUS_SUCCESS
;
727 IoCompleteRequest( irp
, IO_NO_INCREMENT
);
728 if (remove_child_device( fdo
, device
))
730 input_queue_cleanup( &impl
->input_queue
);
731 expect_queue_cleanup( &impl
->expect_queue
);
732 irp
= impl
->pending_remove
;
733 IoDeleteDevice( device
);
734 if (winetest_debug
> 1) trace( "Deleted Bus PDO %p\n", device
);
737 irp
->IoStatus
.Status
= STATUS_SUCCESS
;
738 IoCompleteRequest( irp
, IO_NO_INCREMENT
);
741 return STATUS_SUCCESS
;
744 case IRP_MN_QUERY_CAPABILITIES
:
746 DEVICE_CAPABILITIES
*caps
= stack
->Parameters
.DeviceCapabilities
.Capabilities
;
748 caps
->SilentInstall
= 1;
749 caps
->SurpriseRemovalOK
= 1;
750 /* caps->RawDeviceOK = 1; */
751 status
= STATUS_SUCCESS
;
754 case IRP_MN_QUERY_ID
:
756 BUS_QUERY_ID_TYPE type
= stack
->Parameters
.QueryId
.IdType
;
759 case BusQueryDeviceID
:
760 case BusQueryHardwareIDs
:
761 irp
->IoStatus
.Information
= (ULONG_PTR
)query_hardware_ids( device
);
762 if (!irp
->IoStatus
.Information
) status
= STATUS_NO_MEMORY
;
763 else status
= STATUS_SUCCESS
;
765 case BusQueryInstanceID
:
766 irp
->IoStatus
.Information
= (ULONG_PTR
)query_instance_id( device
);
767 if (!irp
->IoStatus
.Information
) status
= STATUS_NO_MEMORY
;
768 else status
= STATUS_SUCCESS
;
770 case BusQueryCompatibleIDs
:
771 irp
->IoStatus
.Information
= (ULONG_PTR
)query_compatible_ids( device
);
772 if (!irp
->IoStatus
.Information
) status
= STATUS_NO_MEMORY
;
773 else status
= STATUS_SUCCESS
;
775 case BusQueryContainerID
:
776 irp
->IoStatus
.Information
= (ULONG_PTR
)query_container_id( device
);
777 if (!irp
->IoStatus
.Information
) status
= STATUS_NO_MEMORY
;
778 else status
= STATUS_SUCCESS
;
781 ok( 0, "IRP_MN_QUERY_ID type %u, not implemented!\n", type
);
782 status
= STATUS_NOT_SUPPORTED
;
787 case IRP_MN_QUERY_BUS_INFORMATION
:
788 irp
->IoStatus
.Information
= (ULONG_PTR
)query_bus_information( device
);
789 if (!irp
->IoStatus
.Information
) status
= STATUS_NO_MEMORY
;
790 else status
= STATUS_SUCCESS
;
792 case IRP_MN_QUERY_DEVICE_TEXT
:
793 irp
->IoStatus
.Information
= (ULONG_PTR
)query_device_text( device
);
794 if (!irp
->IoStatus
.Information
) status
= STATUS_NO_MEMORY
;
795 else status
= STATUS_SUCCESS
;
797 case IRP_MN_QUERY_PNP_DEVICE_STATE
:
798 irp
->IoStatus
.Information
= impl
->base
.state
;
799 status
= STATUS_SUCCESS
;
801 case IRP_MN_QUERY_DEVICE_RELATIONS
:
803 DEVICE_RELATION_TYPE type
= stack
->Parameters
.QueryDeviceRelations
.Type
;
807 if (winetest_debug
> 1) trace( "pdo_pnp IRP_MN_QUERY_DEVICE_RELATIONS BusRelations\n" );
808 ok( irp
->IoStatus
.Information
, "got unexpected BusRelations relations\n" );
809 status
= irp
->IoStatus
.Status
;
811 case EjectionRelations
:
812 if (winetest_debug
> 1) trace( "pdo_pnp IRP_MN_QUERY_DEVICE_RELATIONS EjectionRelations\n" );
813 ok( !irp
->IoStatus
.Information
, "got unexpected EjectionRelations relations\n" );
814 status
= irp
->IoStatus
.Status
;
816 case RemovalRelations
:
817 if (winetest_debug
> 1) trace( "pdo_pnp IRP_MN_QUERY_DEVICE_RELATIONS RemovalRelations\n" );
818 ok( irp
->IoStatus
.Information
, "got unexpected RemovalRelations relations\n" );
819 status
= irp
->IoStatus
.Status
;
821 case TargetDeviceRelation
:
822 if (winetest_debug
> 1) trace( "pdo_pnp IRP_MN_QUERY_DEVICE_RELATIONS TargetDeviceRelations\n" );
823 ok( !irp
->IoStatus
.Information
, "got unexpected TargetDeviceRelations relations\n" );
824 irp
->IoStatus
.Information
= get_device_relations( device
, (void *)irp
->IoStatus
.Information
, 1, &device
);
825 if (!irp
->IoStatus
.Information
) status
= STATUS_NO_MEMORY
;
826 else status
= STATUS_SUCCESS
;
829 ok( 0, "got unexpected IRP_MN_QUERY_DEVICE_RELATIONS type %#x\n", type
);
830 status
= irp
->IoStatus
.Status
;
836 if (winetest_debug
> 1) trace( "pdo_pnp code %#lx %s, not implemented!\n", code
, debugstr_pnp(code
) );
837 status
= irp
->IoStatus
.Status
;
841 irp
->IoStatus
.Status
= status
;
842 IoCompleteRequest( irp
, IO_NO_INCREMENT
);
846 static NTSTATUS
create_child_pdo( DEVICE_OBJECT
*device
, struct hid_device_desc
*desc
)
850 struct func_device
*fdo
= fdo_from_DEVICE_OBJECT( device
);
851 struct phys_device
*impl
;
852 UNICODE_STRING name_str
;
853 DEVICE_OBJECT
*child
;
854 WCHAR name
[MAX_PATH
];
857 if (winetest_debug
> 1) trace( "polled %u, report_id %u\n", desc
->is_polled
, desc
->use_report_id
);
859 swprintf( name
, MAX_PATH
, L
"\\Device\\WINETEST#%p&%p&%u", device
->DriverObject
, device
, index
++ );
860 RtlInitUnicodeString( &name_str
, name
);
862 if ((status
= IoCreateDevice( device
->DriverObject
, sizeof(struct phys_device
), &name_str
, 0, 0, FALSE
, &child
)))
864 ok( 0, "Failed to create gamepad device, status %#lx\n", status
);
868 impl
= pdo_from_DEVICE_OBJECT( child
);
869 KeInitializeSpinLock( &impl
->base
.lock
);
870 swprintf( impl
->device_id
, MAX_PATH
, L
"WINETEST\\VID_%04X&PID_%04X", desc
->attributes
.VendorID
,
871 desc
->attributes
.ProductID
);
872 /* use a different device ID so that driver cache select the polled driver */
873 if (desc
->is_polled
) wcscat( impl
->device_id
, L
"&POLL" );
874 swprintf( impl
->instance_id
, MAX_PATH
, L
"0&0000&0" );
875 impl
->base
.is_phys
= TRUE
;
878 impl
->use_report_id
= desc
->use_report_id
;
879 impl
->caps
= desc
->caps
;
880 impl
->attributes
= desc
->attributes
;
881 impl
->report_descriptor_len
= desc
->report_descriptor_len
;
882 memcpy( impl
->report_descriptor_buf
, desc
->report_descriptor_buf
, desc
->report_descriptor_len
);
883 input_queue_init( &impl
->input_queue
, desc
->is_polled
);
884 input_queue_reset( &impl
->input_queue
, desc
->input
, desc
->input_size
);
885 expect_queue_init( &impl
->expect_queue
);
886 expect_queue_reset( &impl
->expect_queue
, desc
->expect
, desc
->expect_size
);
887 memcpy( impl
->expect_queue
.context
, desc
->context
, desc
->context_size
);
889 if (winetest_debug
> 1) trace( "Created Bus PDO %p for Bus FDO %p\n", child
, device
);
891 append_child_device( fdo
, child
);
892 IoInvalidateDeviceRelations( fdo
->pdo
, BusRelations
);
893 return STATUS_SUCCESS
;
896 static NTSTATUS
fdo_pnp( DEVICE_OBJECT
*device
, IRP
*irp
)
898 struct func_device
*impl
= fdo_from_DEVICE_OBJECT( device
);
899 IO_STACK_LOCATION
*stack
= IoGetCurrentIrpStackLocation( irp
);
900 char relations_buffer
[sizeof(impl
->devices_buffer
)];
901 DEVICE_RELATIONS
*relations
= (void *)relations_buffer
;
902 ULONG code
= stack
->MinorFunction
;
903 PNP_DEVICE_STATE state
;
907 if (winetest_debug
> 1) trace( "%s: device %p, code %#lx %s\n", __func__
, device
, code
, debugstr_pnp(code
) );
911 case IRP_MN_START_DEVICE
:
912 case IRP_MN_CANCEL_REMOVE_DEVICE
:
913 case IRP_MN_QUERY_REMOVE_DEVICE
:
914 case IRP_MN_SURPRISE_REMOVAL
:
915 case IRP_MN_REMOVE_DEVICE
:
916 state
= (code
== IRP_MN_START_DEVICE
|| code
== IRP_MN_CANCEL_REMOVE_DEVICE
) ? 0 : PNP_DEVICE_REMOVED
;
917 KeAcquireSpinLock( &impl
->base
.lock
, &irql
);
918 impl
->base
.state
= state
;
919 if (code
== IRP_MN_REMOVE_DEVICE
) memcpy( relations
, impl
->devices
, sizeof(relations_buffer
) );
920 impl
->devices
->Count
= 0;
921 KeReleaseSpinLock( &impl
->base
.lock
, irql
);
922 IoSetDeviceInterfaceState( &impl
->control_iface
, state
!= PNP_DEVICE_REMOVED
);
923 if (code
!= IRP_MN_REMOVE_DEVICE
) status
= STATUS_SUCCESS
;
926 while (relations
->Count
--) IoDeleteDevice( relations
->Objects
[relations
->Count
] );
927 IoSkipCurrentIrpStackLocation( irp
);
928 status
= IoCallDriver( impl
->pdo
, irp
);
929 IoDetachDevice( impl
->pdo
);
930 RtlFreeUnicodeString( &impl
->control_iface
);
931 IoDeleteDevice( device
);
932 if (winetest_debug
> 1) trace( "Deleted Bus FDO %p from PDO %p, status %#lx\n", impl
, impl
->pdo
, status
);
936 case IRP_MN_QUERY_PNP_DEVICE_STATE
:
937 KeAcquireSpinLock( &impl
->base
.lock
, &irql
);
938 irp
->IoStatus
.Information
= impl
->base
.state
;
939 KeReleaseSpinLock( &impl
->base
.lock
, irql
);
940 status
= STATUS_SUCCESS
;
942 case IRP_MN_QUERY_DEVICE_RELATIONS
:
944 DEVICE_RELATION_TYPE type
= stack
->Parameters
.QueryDeviceRelations
.Type
;
948 if (winetest_debug
> 1) trace( "fdo_pnp IRP_MN_QUERY_DEVICE_RELATIONS BusRelations\n" );
949 ok( !irp
->IoStatus
.Information
, "got unexpected BusRelations relations\n" );
950 KeAcquireSpinLock( &impl
->base
.lock
, &irql
);
951 memcpy( relations
, impl
->devices
, sizeof(relations_buffer
) );
952 KeReleaseSpinLock( &impl
->base
.lock
, irql
);
953 irp
->IoStatus
.Information
= get_device_relations( device
, (void *)irp
->IoStatus
.Information
,
954 relations
->Count
, relations
->Objects
);
955 if (!irp
->IoStatus
.Information
) status
= STATUS_NO_MEMORY
;
956 else status
= STATUS_SUCCESS
;
958 case RemovalRelations
:
959 if (winetest_debug
> 1) trace( "fdo_pnp IRP_MN_QUERY_DEVICE_RELATIONS RemovalRelations\n" );
960 ok( !irp
->IoStatus
.Information
, "got unexpected RemovalRelations relations\n" );
961 irp
->IoStatus
.Information
= get_device_relations( device
, (void *)irp
->IoStatus
.Information
,
963 if (!irp
->IoStatus
.Information
) status
= STATUS_NO_MEMORY
;
964 else status
= STATUS_SUCCESS
;
967 ok( 0, "got unexpected IRP_MN_QUERY_DEVICE_RELATIONS type %#x\n", type
);
968 status
= irp
->IoStatus
.Status
;
973 case IRP_MN_QUERY_CAPABILITIES
:
975 DEVICE_CAPABILITIES
*caps
= stack
->Parameters
.DeviceCapabilities
.Capabilities
;
976 caps
->EjectSupported
= TRUE
;
977 caps
->Removable
= TRUE
;
978 caps
->SilentInstall
= TRUE
;
979 caps
->SurpriseRemovalOK
= TRUE
;
980 status
= STATUS_SUCCESS
;
984 if (winetest_debug
> 1) trace( "fdo_pnp code %#lx %s, not implemented!\n", code
, debugstr_pnp(code
) );
985 status
= irp
->IoStatus
.Status
;
989 irp
->IoStatus
.Status
= status
;
990 IoSkipCurrentIrpStackLocation( irp
);
991 return IoCallDriver( impl
->pdo
, irp
);
994 static NTSTATUS WINAPI
driver_pnp( DEVICE_OBJECT
*device
, IRP
*irp
)
996 struct device
*impl
= impl_from_DEVICE_OBJECT( device
);
997 if (impl
->is_phys
) return pdo_pnp( device
, irp
);
998 return fdo_pnp( device
, irp
);
1001 static NTSTATUS WINAPI
pdo_internal_ioctl( DEVICE_OBJECT
*device
, IRP
*irp
)
1003 IO_STACK_LOCATION
*stack
= IoGetCurrentIrpStackLocation( irp
);
1004 struct phys_device
*impl
= pdo_from_DEVICE_OBJECT( device
);
1005 const ULONG in_size
= stack
->Parameters
.DeviceIoControl
.InputBufferLength
;
1006 ULONG out_size
= stack
->Parameters
.DeviceIoControl
.OutputBufferLength
;
1007 const ULONG code
= stack
->Parameters
.DeviceIoControl
.IoControlCode
;
1008 struct hid_expect expect
= {0};
1015 if ((!impl
->input_queue
.is_polled
|| code
!= IOCTL_HID_READ_REPORT
) && winetest_debug
> 1)
1016 trace( "%s: device %p, code %#lx %s\n", __func__
, device
, code
, debugstr_ioctl(code
) );
1018 KeAcquireSpinLock( &impl
->base
.lock
, &irql
);
1019 removed
= impl
->base
.state
== PNP_DEVICE_REMOVED
;
1020 KeReleaseSpinLock( &impl
->base
.lock
, irql
);
1024 irp
->IoStatus
.Status
= STATUS_DELETE_PENDING
;
1025 IoCompleteRequest( irp
, IO_NO_INCREMENT
);
1026 return STATUS_DELETE_PENDING
;
1029 winetest_push_context( "id %d%s", impl
->use_report_id
, impl
->input_queue
.is_polled
? " poll" : "" );
1033 case IOCTL_HID_GET_DEVICE_DESCRIPTOR
:
1035 HID_DESCRIPTOR
*desc
= irp
->UserBuffer
;
1037 ok( !in_size
, "got input size %lu\n", in_size
);
1038 ok( out_size
== sizeof(*desc
), "got output size %lu\n", out_size
);
1040 if (out_size
== sizeof(*desc
))
1042 ok( !desc
->bLength
, "got size %u\n", desc
->bLength
);
1044 desc
->bLength
= sizeof(*desc
);
1045 desc
->bDescriptorType
= HID_HID_DESCRIPTOR_TYPE
;
1046 desc
->bcdHID
= HID_REVISION
;
1048 desc
->bNumDescriptors
= 1;
1049 desc
->DescriptorList
[0].bReportType
= HID_REPORT_DESCRIPTOR_TYPE
;
1050 desc
->DescriptorList
[0].wReportLength
= impl
->report_descriptor_len
;
1051 irp
->IoStatus
.Information
= sizeof(*desc
);
1053 status
= STATUS_SUCCESS
;
1057 case IOCTL_HID_GET_REPORT_DESCRIPTOR
:
1058 ok( !in_size
, "got input size %lu\n", in_size
);
1059 ok( out_size
== impl
->report_descriptor_len
, "got output size %lu\n", out_size
);
1061 if (out_size
== impl
->report_descriptor_len
)
1063 memcpy( irp
->UserBuffer
, impl
->report_descriptor_buf
, impl
->report_descriptor_len
);
1064 irp
->IoStatus
.Information
= impl
->report_descriptor_len
;
1066 status
= STATUS_SUCCESS
;
1069 case IOCTL_HID_GET_DEVICE_ATTRIBUTES
:
1070 ok( !in_size
, "got input size %lu\n", in_size
);
1071 ok( out_size
== sizeof(impl
->attributes
), "got output size %lu\n", out_size
);
1073 if (out_size
== sizeof(impl
->attributes
))
1075 memcpy( irp
->UserBuffer
, &impl
->attributes
, sizeof(impl
->attributes
) );
1076 irp
->IoStatus
.Information
= sizeof(impl
->attributes
);
1078 status
= STATUS_SUCCESS
;
1081 case IOCTL_HID_READ_REPORT
:
1083 ULONG expected_size
= impl
->caps
.InputReportByteLength
- (impl
->use_report_id
? 0 : 1);
1084 ok( !in_size
, "got input size %lu\n", in_size
);
1085 ok( out_size
== expected_size
, "got output size %lu\n", out_size
);
1086 status
= input_queue_read( &impl
->input_queue
, irp
);
1090 case IOCTL_HID_WRITE_REPORT
:
1092 HID_XFER_PACKET
*packet
= irp
->UserBuffer
;
1094 ok( in_size
== sizeof(*packet
), "got input size %lu\n", in_size
);
1095 ok( !out_size
, "got output size %lu\n", out_size
);
1096 ok( !!packet
->reportBuffer
, "got buffer %p\n", packet
->reportBuffer
);
1098 expect_queue_next( &impl
->expect_queue
, code
, packet
, &index
, &expect
, TRUE
, context
, sizeof(context
) );
1099 winetest_push_context( "%s expect[%ld]", context
, index
);
1100 ok( code
== expect
.code
, "got %#lx, expected %#lx\n", code
, expect
.code
);
1101 ok( packet
->reportId
== expect
.report_id
, "got id %u\n", packet
->reportId
);
1102 ok( packet
->reportBufferLen
== expect
.report_len
, "got len %lu\n", packet
->reportBufferLen
);
1103 check_buffer( packet
, &expect
);
1104 winetest_pop_context();
1106 irp
->IoStatus
.Information
= expect
.ret_length
? expect
.ret_length
: expect
.report_len
;
1107 status
= expect
.ret_status
;
1108 if (status
== STATUS_PENDING
) status
= expect_queue_add_pending( &impl
->expect_queue
, irp
);
1112 case IOCTL_HID_GET_INPUT_REPORT
:
1114 HID_XFER_PACKET
*packet
= irp
->UserBuffer
;
1116 ok( !in_size
, "got input size %lu\n", in_size
);
1117 ok( out_size
== sizeof(*packet
), "got output size %lu\n", out_size
);
1118 ok( !!packet
->reportBuffer
, "got buffer %p\n", packet
->reportBuffer
);
1120 expect_queue_next( &impl
->expect_queue
, code
, packet
, &index
, &expect
, FALSE
, context
, sizeof(context
) );
1121 winetest_push_context( "%s expect[%ld]", context
, index
);
1122 ok( code
== expect
.code
, "got %#lx, expected %#lx\n", code
, expect
.code
);
1123 ok( packet
->reportId
== expect
.report_id
, "got id %u\n", packet
->reportId
);
1124 ok( packet
->reportBufferLen
== expect
.report_len
, "got len %lu\n", packet
->reportBufferLen
);
1125 winetest_pop_context();
1127 irp
->IoStatus
.Information
= expect
.ret_length
? expect
.ret_length
: expect
.report_len
;
1128 memcpy( packet
->reportBuffer
, expect
.report_buf
, irp
->IoStatus
.Information
);
1129 status
= expect
.ret_status
;
1130 if (status
== STATUS_PENDING
) status
= expect_queue_add_pending( &impl
->expect_queue
, irp
);
1134 case IOCTL_HID_SET_OUTPUT_REPORT
:
1136 HID_XFER_PACKET
*packet
= irp
->UserBuffer
;
1138 ok( in_size
== sizeof(*packet
), "got input size %lu\n", in_size
);
1139 ok( !out_size
, "got output size %lu\n", out_size
);
1140 ok( !!packet
->reportBuffer
, "got buffer %p\n", packet
->reportBuffer
);
1142 expect_queue_next( &impl
->expect_queue
, code
, packet
, &index
, &expect
, TRUE
, context
, sizeof(context
) );
1143 winetest_push_context( "%s expect[%ld]", context
, index
);
1144 ok( code
== expect
.code
, "got %#lx, expected %#lx\n", code
, expect
.code
);
1145 ok( packet
->reportId
== expect
.report_id
, "got id %u\n", packet
->reportId
);
1146 ok( packet
->reportBufferLen
== expect
.report_len
, "got len %lu\n", packet
->reportBufferLen
);
1147 check_buffer( packet
, &expect
);
1148 winetest_pop_context();
1150 irp
->IoStatus
.Information
= expect
.ret_length
? expect
.ret_length
: expect
.report_len
;
1151 status
= expect
.ret_status
;
1152 if (status
== STATUS_PENDING
) status
= expect_queue_add_pending( &impl
->expect_queue
, irp
);
1156 case IOCTL_HID_GET_FEATURE
:
1158 HID_XFER_PACKET
*packet
= irp
->UserBuffer
;
1160 ok( !in_size
, "got input size %lu\n", in_size
);
1161 ok( out_size
== sizeof(*packet
), "got output size %lu\n", out_size
);
1162 ok( !!packet
->reportBuffer
, "got buffer %p\n", packet
->reportBuffer
);
1164 expect_queue_next( &impl
->expect_queue
, code
, packet
, &index
, &expect
, FALSE
, context
, sizeof(context
) );
1165 winetest_push_context( "%s expect[%ld]", context
, index
);
1166 ok( code
== expect
.code
, "got %#lx, expected %#lx\n", code
, expect
.code
);
1167 ok( packet
->reportId
== expect
.report_id
, "got id %u\n", packet
->reportId
);
1168 ok( packet
->reportBufferLen
== expect
.report_len
, "got len %lu\n", packet
->reportBufferLen
);
1169 winetest_pop_context();
1171 irp
->IoStatus
.Information
= expect
.ret_length
? expect
.ret_length
: expect
.report_len
;
1172 memcpy( packet
->reportBuffer
, expect
.report_buf
, irp
->IoStatus
.Information
);
1173 status
= expect
.ret_status
;
1174 if (status
== STATUS_PENDING
) status
= expect_queue_add_pending( &impl
->expect_queue
, irp
);
1178 case IOCTL_HID_SET_FEATURE
:
1180 HID_XFER_PACKET
*packet
= irp
->UserBuffer
;
1182 ok( in_size
== sizeof(*packet
), "got input size %lu\n", in_size
);
1183 ok( !out_size
, "got output size %lu\n", out_size
);
1184 ok( !!packet
->reportBuffer
, "got buffer %p\n", packet
->reportBuffer
);
1186 expect_queue_next( &impl
->expect_queue
, code
, packet
, &index
, &expect
, TRUE
, context
, sizeof(context
) );
1187 winetest_push_context( "%s expect[%ld]", context
, index
);
1188 ok( code
== expect
.code
, "got %#lx, expected %#lx\n", code
, expect
.code
);
1189 ok( packet
->reportId
== expect
.report_id
, "got id %u\n", packet
->reportId
);
1190 ok( packet
->reportBufferLen
== expect
.report_len
, "got len %lu\n", packet
->reportBufferLen
);
1191 check_buffer( packet
, &expect
);
1192 winetest_pop_context();
1194 irp
->IoStatus
.Information
= expect
.ret_length
? expect
.ret_length
: expect
.report_len
;
1195 status
= expect
.ret_status
;
1196 if (status
== STATUS_PENDING
) status
= expect_queue_add_pending( &impl
->expect_queue
, irp
);
1200 case IOCTL_HID_GET_STRING
:
1201 memcpy( irp
->UserBuffer
, L
"Wine Test", sizeof(L
"Wine Test") );
1202 irp
->IoStatus
.Information
= sizeof(L
"Wine Test");
1203 status
= STATUS_SUCCESS
;
1206 case IOCTL_GET_PHYSICAL_DESCRIPTOR
:
1207 irp
->IoStatus
.Information
= 0;
1208 status
= STATUS_NOT_SUPPORTED
;
1212 ok( 0, "unexpected call\n" );
1213 status
= irp
->IoStatus
.Status
;
1217 winetest_pop_context();
1219 if (status
!= STATUS_PENDING
)
1221 irp
->IoStatus
.Status
= status
;
1222 IoCompleteRequest( irp
, IO_NO_INCREMENT
);
1227 static NTSTATUS WINAPI
fdo_internal_ioctl( DEVICE_OBJECT
*device
, IRP
*irp
)
1229 IO_STACK_LOCATION
*stack
= IoGetCurrentIrpStackLocation( irp
);
1230 ULONG code
= stack
->Parameters
.DeviceIoControl
.IoControlCode
;
1232 if (winetest_debug
> 1) trace( "%s: device %p, code %#lx %s\n", __func__
, device
, code
, debugstr_ioctl(code
) );
1233 ok( 0, "unexpected call\n" );
1235 irp
->IoStatus
.Status
= STATUS_NOT_SUPPORTED
;
1236 IoCompleteRequest( irp
, IO_NO_INCREMENT
);
1237 return STATUS_NOT_SUPPORTED
;
1240 static NTSTATUS WINAPI
driver_internal_ioctl( DEVICE_OBJECT
*device
, IRP
*irp
)
1242 struct device
*impl
= impl_from_DEVICE_OBJECT( device
);
1243 if (impl
->is_phys
) return pdo_internal_ioctl( device
, irp
);
1244 return fdo_internal_ioctl( device
, irp
);
1247 static NTSTATUS WINAPI
pdo_ioctl( DEVICE_OBJECT
*device
, IRP
*irp
)
1249 IO_STACK_LOCATION
*stack
= IoGetCurrentIrpStackLocation( irp
);
1250 struct phys_device
*impl
= pdo_from_DEVICE_OBJECT( device
);
1251 ULONG in_size
= stack
->Parameters
.DeviceIoControl
.InputBufferLength
;
1252 ULONG code
= stack
->Parameters
.DeviceIoControl
.IoControlCode
;
1256 if (winetest_debug
> 1) trace( "%s: device %p, code %#lx %s\n", __func__
, device
, code
, debugstr_ioctl(code
) );
1260 case IOCTL_WINETEST_HID_SET_EXPECT
:
1261 expect_queue_reset( &impl
->expect_queue
, irp
->AssociatedIrp
.SystemBuffer
, in_size
);
1262 status
= STATUS_SUCCESS
;
1264 case IOCTL_WINETEST_HID_WAIT_EXPECT
:
1266 struct wait_expect_params wait_params
= *(struct wait_expect_params
*)irp
->AssociatedIrp
.SystemBuffer
;
1267 if (!wait_params
.wait_pending
) status
= expect_queue_wait( &impl
->expect_queue
, irp
);
1268 else status
= expect_queue_wait_pending( &impl
->expect_queue
, irp
);
1271 case IOCTL_WINETEST_HID_SEND_INPUT
:
1272 input_queue_reset( &impl
->input_queue
, irp
->AssociatedIrp
.SystemBuffer
, in_size
);
1273 status
= STATUS_SUCCESS
;
1275 case IOCTL_WINETEST_HID_SET_CONTEXT
:
1276 KeAcquireSpinLock( &impl
->expect_queue
.lock
, &irql
);
1277 memcpy( impl
->expect_queue
.context
, irp
->AssociatedIrp
.SystemBuffer
, in_size
);
1278 KeReleaseSpinLock( &impl
->expect_queue
.lock
, irql
);
1279 status
= STATUS_SUCCESS
;
1281 case IOCTL_WINETEST_REMOVE_DEVICE
:
1282 KeAcquireSpinLock( &impl
->base
.lock
, &irql
);
1283 impl
->base
.state
= PNP_DEVICE_REMOVED
;
1284 irp_queue_clear( &impl
->input_queue
.pending
);
1285 KeReleaseSpinLock( &impl
->base
.lock
, irql
);
1286 impl
->pending_remove
= irp
;
1287 IoMarkIrpPending( irp
);
1288 status
= STATUS_PENDING
;
1290 case IOCTL_WINETEST_CREATE_DEVICE
:
1291 ok( 0, "unexpected call\n" );
1292 status
= irp
->IoStatus
.Status
;
1295 ok( 0, "unexpected call\n" );
1296 status
= irp
->IoStatus
.Status
;
1300 if (status
!= STATUS_PENDING
)
1302 irp
->IoStatus
.Status
= status
;
1303 IoCompleteRequest( irp
, IO_NO_INCREMENT
);
1308 static NTSTATUS WINAPI
fdo_ioctl( DEVICE_OBJECT
*device
, IRP
*irp
)
1310 IO_STACK_LOCATION
*stack
= IoGetCurrentIrpStackLocation( irp
);
1311 ULONG in_size
= stack
->Parameters
.DeviceIoControl
.InputBufferLength
;
1312 ULONG code
= stack
->Parameters
.DeviceIoControl
.IoControlCode
;
1313 struct func_device
*impl
= fdo_from_DEVICE_OBJECT( device
);
1316 if (winetest_debug
> 1) trace( "%s: device %p, code %#lx %s\n", __func__
, device
, code
, debugstr_ioctl(code
) );
1320 case IOCTL_WINETEST_CREATE_DEVICE
:
1321 if (in_size
< sizeof(struct hid_device_desc
)) status
= STATUS_INVALID_PARAMETER
;
1322 else status
= create_child_pdo( device
, irp
->AssociatedIrp
.SystemBuffer
);
1324 case IOCTL_WINETEST_REMOVE_DEVICE
:
1325 if ((device
= find_child_device( impl
, irp
->AssociatedIrp
.SystemBuffer
)) &&
1326 !remove_child_device( impl
, device
))
1328 status
= pdo_ioctl( device
, irp
);
1329 IoInvalidateDeviceRelations( impl
->pdo
, BusRelations
);
1332 status
= STATUS_NO_SUCH_DEVICE
;
1335 ok( 0, "unexpected call\n" );
1336 status
= irp
->IoStatus
.Status
;
1340 irp
->IoStatus
.Status
= status
;
1341 IoCompleteRequest( irp
, IO_NO_INCREMENT
);
1345 static NTSTATUS WINAPI
driver_ioctl( DEVICE_OBJECT
*device
, IRP
*irp
)
1347 struct device
*impl
= impl_from_DEVICE_OBJECT( device
);
1348 if (impl
->is_phys
) return pdo_ioctl( device
, irp
);
1349 return fdo_ioctl( device
, irp
);
1352 static NTSTATUS WINAPI
driver_add_device( DRIVER_OBJECT
*driver
, DEVICE_OBJECT
*device
)
1354 struct func_device
*impl
;
1355 DEVICE_OBJECT
*child
;
1358 if (winetest_debug
> 1) trace( "%s: driver %p, device %p\n", __func__
, driver
, device
);
1360 if ((status
= IoCreateDevice( driver
, sizeof(struct func_device
), NULL
, FILE_DEVICE_BUS_EXTENDER
, 0, FALSE
, &child
)))
1362 ok( 0, "Failed to create FDO, status %#lx.\n", status
);
1366 impl
= (struct func_device
*)child
->DeviceExtension
;
1367 impl
->devices
= (void *)impl
->devices_buffer
;
1368 KeInitializeSpinLock( &impl
->base
.lock
);
1371 status
= IoRegisterDeviceInterface( impl
->pdo
, &control_class
, NULL
, &impl
->control_iface
);
1372 ok( !status
, "IoRegisterDeviceInterface returned %#lx\n", status
);
1374 if (winetest_debug
> 1) trace( "Created Bus FDO %p for PDO %p\n", child
, device
);
1376 IoAttachDeviceToDeviceStack( child
, device
);
1377 child
->Flags
&= ~DO_DEVICE_INITIALIZING
;
1379 return STATUS_SUCCESS
;
1382 static NTSTATUS WINAPI
driver_create( DEVICE_OBJECT
*device
, IRP
*irp
)
1384 if (winetest_debug
> 1) trace( "%s: device %p, irp %p\n", __func__
, device
, irp
);
1386 irp
->IoStatus
.Status
= STATUS_SUCCESS
;
1387 IoCompleteRequest( irp
, IO_NO_INCREMENT
);
1388 return STATUS_SUCCESS
;
1391 static NTSTATUS WINAPI
driver_close( DEVICE_OBJECT
*device
, IRP
*irp
)
1393 if (winetest_debug
> 1) trace( "%s: device %p, irp %p\n", __func__
, device
, irp
);
1395 irp
->IoStatus
.Status
= STATUS_SUCCESS
;
1396 IoCompleteRequest( irp
, IO_NO_INCREMENT
);
1397 return STATUS_SUCCESS
;
1400 static void WINAPI
driver_unload( DRIVER_OBJECT
*driver
)
1402 if (winetest_debug
> 1) trace( "%s: driver %p\n", __func__
, driver
);
1406 NTSTATUS WINAPI
DriverEntry( DRIVER_OBJECT
*driver
, UNICODE_STRING
*registry
)
1410 if ((status
= winetest_init())) return status
;
1411 if (winetest_debug
> 1) trace( "%s: driver %p\n", __func__
, driver
);
1413 driver
->DriverExtension
->AddDevice
= driver_add_device
;
1414 driver
->DriverUnload
= driver_unload
;
1415 driver
->MajorFunction
[IRP_MJ_PNP
] = driver_pnp
;
1416 driver
->MajorFunction
[IRP_MJ_DEVICE_CONTROL
] = driver_ioctl
;
1417 driver
->MajorFunction
[IRP_MJ_INTERNAL_DEVICE_CONTROL
] = driver_internal_ioctl
;
1418 driver
->MajorFunction
[IRP_MJ_CREATE
] = driver_create
;
1419 driver
->MajorFunction
[IRP_MJ_CLOSE
] = driver_close
;
1421 return STATUS_SUCCESS
;