wined3d: Check the wined3d resource type and usage instead of the GL target in textur...
[wine.git] / dlls / dinput / tests / driver_bus.c
blobc0d181c58a50274683f5485a18a15defbae4a63e
1 /*
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
21 #if 0
22 #pragma makedep testdll
23 #endif
25 #include <stdarg.h>
26 #include <stdio.h>
28 #include "ntstatus.h"
29 #define WIN32_NO_STATUS
30 #include "windef.h"
31 #include "winbase.h"
32 #include "winternl.h"
33 #include "winioctl.h"
34 #include "ddk/wdm.h"
35 #include "ddk/hidsdi.h"
36 #include "ddk/hidport.h"
38 #include "wine/list.h"
40 #define WINE_DRIVER_TEST
41 #include "initguid.h"
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 )
50 ULONG match_len, i;
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 );
66 struct expect_queue
68 KSPIN_LOCK lock;
69 struct hid_expect *pos;
70 struct hid_expect *end;
71 struct hid_expect spurious;
72 struct hid_expect *buffer;
73 IRP *pending_wait;
74 char context[64];
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 )
88 KIRQL irql;
89 IRP *irp;
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 );
99 if (irp)
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;
111 char context[64];
112 KIRQL irql;
114 missing = ExAllocatePool( PagedPool, EXPECT_QUEUE_BUFFER_SIZE );
115 RtlSecureZeroMemory( missing, EXPECT_QUEUE_BUFFER_SIZE );
116 missing_end = missing;
118 KeAcquireSpinLock( &queue->lock, &irql );
119 tmp = queue->pos;
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 );
130 tmp = missing;
131 while (tmp != missing_end)
133 winetest_push_context( "%s expect[%Id]", context, tmp - missing );
134 if (tmp->broken)
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 );
139 else
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();
145 tmp++;
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];
154 KIRQL irql;
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 )
184 NTSTATUS status;
185 KIRQL irql;
187 KeAcquireSpinLock( &queue->lock, &irql );
188 status = expect_queue_add_pending_locked( queue, irp );
189 KeReleaseSpinLock( &queue->lock, irql );
191 return status;
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 )
197 NTSTATUS status;
198 IRP *pending;
199 KIRQL irql;
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 );
212 if (pending)
214 pending->IoStatus.Status = STATUS_SUCCESS;
215 IoCompleteRequest( pending, IO_NO_INCREMENT );
218 return status;
221 /* wait for the expect queue to empty */
222 static NTSTATUS expect_queue_wait( struct expect_queue *queue, IRP *irp )
224 NTSTATUS status;
225 KIRQL irql;
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 );
233 return status;
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;
243 IRP *irp = NULL;
244 KIRQL irql;
246 missing = ExAllocatePool( PagedPool, EXPECT_QUEUE_BUFFER_SIZE );
247 RtlSecureZeroMemory( missing, EXPECT_QUEUE_BUFFER_SIZE );
248 missing_end = missing;
250 KeAcquireSpinLock( &queue->lock, &irql );
251 tmp = queue->pos;
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))
258 break;
259 *missing_end++ = *tmp++;
261 *index = tmp - queue->buffer;
262 if (tmp < queue->end) queue->pos = tmp + 1;
263 else tmp = &queue->spurious;
264 *expect = *tmp;
266 while (queue->pos < queue->end)
268 if (winetest_platform_is_wine || !queue->pos->wine_only) break;
269 queue->pos++;
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;
279 else
281 queue->pending_wait = NULL;
282 if (!IoSetCancelRoutine( irp, NULL )) irp = NULL;
286 memcpy( context, queue->context, context_size );
287 KeReleaseSpinLock( &queue->lock, irql );
289 if (irp)
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();
302 tmp = missing;
303 while (tmp != missing_end)
305 winetest_push_context( "%s expect[%Id]", context, tmp - missing );
306 if (tmp->broken)
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 );
311 else
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();
317 tmp++;
320 ExFreePool( missing );
323 struct irp_queue
325 KSPIN_LOCK lock;
326 LIST_ENTRY list;
329 static IRP *irp_queue_pop( struct irp_queue *queue )
331 KIRQL irql;
332 IRP *irp;
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 );
339 return irp;
342 static void irp_queue_push( struct irp_queue *queue, IRP *irp )
344 KIRQL irql;
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 )
353 IRP *irp;
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 );
368 struct input_queue
370 KSPIN_LOCK lock;
371 BOOL is_polled;
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;
410 return TRUE;
413 static NTSTATUS input_queue_read( struct input_queue *queue, IRP *irp )
415 NTSTATUS status;
416 KIRQL irql;
418 KeAcquireSpinLock( &queue->lock, &irql );
419 if (input_queue_read_locked( queue, irp )) status = STATUS_SUCCESS;
420 else
422 IoMarkIrpPending( irp );
423 irp_queue_push( &queue->pending, irp );
424 status = STATUS_PENDING;
426 KeReleaseSpinLock( &queue->lock, irql );
428 return status;
431 static void input_queue_reset( struct input_queue *queue, void *in_buf, ULONG in_size )
433 struct irp_queue completed;
434 ULONG remaining;
435 KIRQL irql;
436 IRP *irp;
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 );
459 struct device
461 KSPIN_LOCK lock;
462 PNP_DEVICE_STATE state;
463 BOOL is_phys;
466 static inline struct device *impl_from_DEVICE_OBJECT( DEVICE_OBJECT *device )
468 return (struct device *)device->DeviceExtension;
471 struct phys_device
473 struct device base;
474 struct func_device *fdo; /* parent FDO */
476 WCHAR instance_id[MAX_PATH];
477 WCHAR device_id[MAX_PATH];
478 IRP *pending_remove;
480 BOOL use_report_id;
481 DWORD report_descriptor_len;
482 char report_descriptor_buf[MAX_HID_DESCRIPTOR_LEN];
484 HIDP_CAPS caps;
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 );
496 struct func_device
498 struct 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,
515 "popl %ecx\n\t"
516 "popl %eax\n\t"
517 "xchgl (%esp),%ecx\n\t"
518 "jmp *%eax" );
519 #define call_fastcall_func1( func, a ) wrap_fastcall_func1( func, a )
520 #else
521 #define call_fastcall_func1( func, a ) func( a )
522 #endif
524 static NTSTATUS remove_child_device( struct func_device *impl, DEVICE_OBJECT *device )
526 NTSTATUS status = STATUS_SUCCESS;
527 KIRQL irql;
528 ULONG i;
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 );
537 return status;
540 static NTSTATUS append_child_device( struct func_device *impl, DEVICE_OBJECT *device )
542 NTSTATUS status;
543 KIRQL irql;
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;
548 else
550 impl->devices->Objects[impl->devices->Count++] = device;
551 status = STATUS_SUCCESS;
553 KeReleaseSpinLock( &impl->base.lock, irql );
555 return status;
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];
562 KIRQL irql;
563 ULONG i;
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;
575 else device = NULL;
577 KeReleaseSpinLock( &impl->base.lock, irql );
579 return device;
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;
596 else
598 memcpy( relations, previous, offsetof( DEVICE_RELATIONS, Objects[previous->Count] ) );
599 ExFreePool( previous );
602 while (count--)
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);
615 WCHAR *dst;
617 if ((dst = ExAllocatePool( PagedPool, size )))
618 memcpy( dst, impl->instance_id, size );
620 return dst;
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);
627 WCHAR *dst;
629 if ((dst = ExAllocatePool( PagedPool, size + sizeof(WCHAR) )))
631 memcpy( dst, impl->device_id, size );
632 dst[size / sizeof(WCHAR)] = 0;
635 return dst;
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);
645 WCHAR *dst;
647 if ((dst = ExAllocatePool( PagedPool, size + sizeof(WCHAR) )))
649 memcpy( dst, compat_id, size );
650 dst[size / sizeof(WCHAR)] = 0;
653 return dst;
656 static WCHAR *query_container_id( DEVICE_OBJECT *device )
658 static const WCHAR winetest_id[] = L"WINETEST";
659 DWORD size = sizeof(winetest_id);
660 WCHAR *dst;
662 if ((dst = ExAllocatePool( PagedPool, size )))
663 memcpy( dst, winetest_id, sizeof(winetest_id) );
665 return dst;
668 typedef struct _PNP_BUS_INFORMATION
670 GUID BusTypeGuid;
671 INTERFACE_TYPE LegacyBusType;
672 ULONG BusNumber;
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;
684 dst->BusNumber = 0;
687 return dst;
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);
694 WCHAR *dst;
696 if ((dst = ExAllocatePool( PagedPool, size )))
697 memcpy( dst, device_text, size );
699 return dst;
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;
709 NTSTATUS status;
710 KIRQL irql;
712 if (winetest_debug > 1) trace( "%s: device %p, code %#lx %s\n", __func__, device, code, debugstr_pnp(code) );
714 switch (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;
727 else
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 );
738 if (irp)
740 irp->IoStatus.Status = STATUS_SUCCESS;
741 IoCompleteRequest( irp, IO_NO_INCREMENT );
744 return STATUS_SUCCESS;
746 break;
747 case IRP_MN_QUERY_CAPABILITIES:
749 DEVICE_CAPABILITIES *caps = stack->Parameters.DeviceCapabilities.Capabilities;
750 caps->Removable = 1;
751 caps->SilentInstall = 1;
752 caps->SurpriseRemovalOK = 1;
753 /* caps->RawDeviceOK = 1; */
754 status = STATUS_SUCCESS;
755 break;
757 case IRP_MN_QUERY_ID:
759 BUS_QUERY_ID_TYPE type = stack->Parameters.QueryId.IdType;
760 switch (type)
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;
767 break;
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;
772 break;
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;
777 break;
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;
782 break;
783 default:
784 ok( 0, "IRP_MN_QUERY_ID type %u, not implemented!\n", type );
785 status = STATUS_NOT_SUPPORTED;
786 break;
788 break;
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;
794 break;
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;
799 break;
800 case IRP_MN_QUERY_PNP_DEVICE_STATE:
801 irp->IoStatus.Information = impl->base.state;
802 status = STATUS_SUCCESS;
803 break;
804 case IRP_MN_QUERY_DEVICE_RELATIONS:
806 DEVICE_RELATION_TYPE type = stack->Parameters.QueryDeviceRelations.Type;
807 switch (type)
809 case BusRelations:
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;
813 break;
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;
818 break;
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;
823 break;
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;
830 break;
831 default:
832 ok( 0, "got unexpected IRP_MN_QUERY_DEVICE_RELATIONS type %#x\n", type );
833 status = irp->IoStatus.Status;
834 break;
836 break;
838 default:
839 if (winetest_debug > 1) trace( "pdo_pnp code %#lx %s, not implemented!\n", code, debugstr_pnp(code) );
840 status = irp->IoStatus.Status;
841 break;
844 irp->IoStatus.Status = status;
845 IoCompleteRequest( irp, IO_NO_INCREMENT );
846 return status;
849 static NTSTATUS create_child_pdo( DEVICE_OBJECT *device, struct hid_device_desc *desc )
851 static ULONG index;
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];
858 NTSTATUS status;
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 );
868 return 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;
879 impl->fdo = fdo;
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;
907 NTSTATUS status;
908 KIRQL irql;
910 if (winetest_debug > 1) trace( "%s: device %p, code %#lx %s\n", __func__, device, code, debugstr_pnp(code) );
912 switch (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;
927 else
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 );
936 return status;
938 break;
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;
944 break;
945 case IRP_MN_QUERY_DEVICE_RELATIONS:
947 DEVICE_RELATION_TYPE type = stack->Parameters.QueryDeviceRelations.Type;
948 switch (type)
950 case BusRelations:
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;
960 break;
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,
965 1, &impl->pdo );
966 if (!irp->IoStatus.Information) status = STATUS_NO_MEMORY;
967 else status = STATUS_SUCCESS;
968 break;
969 default:
970 ok( 0, "got unexpected IRP_MN_QUERY_DEVICE_RELATIONS type %#x\n", type );
971 status = irp->IoStatus.Status;
972 break;
974 break;
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;
984 break;
986 default:
987 if (winetest_debug > 1) trace( "fdo_pnp code %#lx %s, not implemented!\n", code, debugstr_pnp(code) );
988 status = irp->IoStatus.Status;
989 break;
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};
1012 char context[64];
1013 NTSTATUS status;
1014 BOOL removed;
1015 KIRQL irql;
1016 LONG index;
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 );
1025 if (removed)
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" : "" );
1034 switch (code)
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;
1050 desc->bCountry = 0;
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;
1057 break;
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;
1070 break;
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;
1082 break;
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 );
1090 break;
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 );
1112 break;
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 );
1134 break;
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 );
1156 break;
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 );
1178 break;
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 );
1200 break;
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;
1207 break;
1209 case IOCTL_GET_PHYSICAL_DESCRIPTOR:
1210 irp->IoStatus.Information = 0;
1211 status = STATUS_NOT_SUPPORTED;
1212 break;
1214 default:
1215 ok( 0, "unexpected call\n" );
1216 status = irp->IoStatus.Status;
1217 break;
1220 winetest_pop_context();
1222 if (status != STATUS_PENDING)
1224 irp->IoStatus.Status = status;
1225 IoCompleteRequest( irp, IO_NO_INCREMENT );
1227 return status;
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 )
1252 KIRQL irql;
1254 switch (code)
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;
1288 default:
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;
1301 NTSTATUS status;
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 );
1312 return status;
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;
1323 NTSTATUS status;
1325 if (winetest_debug > 1) trace( "%s: device %p, code %#lx %s\n", __func__, device, code, debugstr_ioctl(code) );
1327 switch (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 );
1332 break;
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;
1338 else
1340 status = pdo_ioctl( device, irp );
1341 IoInvalidateDeviceRelations( impl->pdo, BusRelations );
1342 return status;
1344 break;
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;
1353 else
1354 status = pdo_handle_ioctl( pdo, irp, code, desc + 1, in_size - sizeof(*desc) );
1355 break;
1356 default:
1357 ok( 0, "unexpected call\n" );
1358 status = irp->IoStatus.Status;
1359 break;
1362 irp->IoStatus.Status = status;
1363 IoCompleteRequest( irp, IO_NO_INCREMENT );
1364 return status;
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;
1378 NTSTATUS status;
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 );
1385 return status;
1388 impl = (struct func_device *)child->DeviceExtension;
1389 impl->devices = (void *)impl->devices_buffer;
1390 KeInitializeSpinLock( &impl->base.lock );
1391 impl->pdo = device;
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 );
1425 winetest_cleanup();
1428 NTSTATUS WINAPI DriverEntry( DRIVER_OBJECT *driver, UNICODE_STRING *registry )
1430 NTSTATUS status;
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;