Signed-off-by: Rémi Bernon rbernon@codeweavers.com --- dlls/dinput/tests/driver.c | 7 + dlls/dinput/tests/driver_bus.c | 413 ++++++++++++++++++++++++++++++++- dlls/dinput/tests/driver_hid.h | 11 + dlls/dinput/tests/hid.c | 17 +- 4 files changed, 440 insertions(+), 8 deletions(-)
diff --git a/dlls/dinput/tests/driver.c b/dlls/dinput/tests/driver.c index 54a281072f9..38b4776a3f0 100644 --- a/dlls/dinput/tests/driver.c +++ b/dlls/dinput/tests/driver.c @@ -772,6 +772,13 @@ static NTSTATUS WINAPI driver_ioctl( DEVICE_OBJECT *device, IRP *irp ) irp->IoStatus.Status = STATUS_SUCCESS; IoCompleteRequest( irp, IO_NO_INCREMENT ); return STATUS_SUCCESS; + + case IOCTL_WINETEST_REMOVE_DEVICE: + case IOCTL_WINETEST_CREATE_DEVICE: + ok( 0, "unexpected call\n" ); + irp->IoStatus.Status = STATUS_NOT_SUPPORTED; + IoCompleteRequest( irp, IO_NO_INCREMENT ); + return STATUS_NOT_SUPPORTED; }
return hidclass_driver_ioctl( device, irp ); diff --git a/dlls/dinput/tests/driver_bus.c b/dlls/dinput/tests/driver_bus.c index aad7f3e2889..01f6e9ec9ee 100644 --- a/dlls/dinput/tests/driver_bus.c +++ b/dlls/dinput/tests/driver_bus.c @@ -41,6 +41,7 @@ struct device { KSPIN_LOCK lock; PNP_DEVICE_STATE state; + BOOL is_phys; };
static inline struct device *impl_from_DEVICE_OBJECT( DEVICE_OBJECT *device ) @@ -48,16 +49,34 @@ static inline struct device *impl_from_DEVICE_OBJECT( DEVICE_OBJECT *device ) return (struct device *)device->DeviceExtension; }
+struct phys_device +{ + struct device base; + struct func_device *fdo; /* parent FDO */ + + WCHAR instance_id[MAX_PATH]; + WCHAR device_id[MAX_PATH]; +}; + +static inline struct phys_device *pdo_from_DEVICE_OBJECT( DEVICE_OBJECT *device ) +{ + struct device *impl = impl_from_DEVICE_OBJECT( device ); + return CONTAINING_RECORD( impl, struct phys_device, base ); +} + struct func_device { struct device base; DEVICE_OBJECT *pdo; /* lower PDO */ UNICODE_STRING control_iface; + char devices_buffer[offsetof( DEVICE_RELATIONS, Objects[128] )]; + DEVICE_RELATIONS *devices; };
static inline struct func_device *fdo_from_DEVICE_OBJECT( DEVICE_OBJECT *device ) { struct device *impl = impl_from_DEVICE_OBJECT( device ); + if (impl->is_phys) return CONTAINING_RECORD( impl, struct phys_device, base )->fdo; return CONTAINING_RECORD( impl, struct func_device, base ); }
@@ -73,6 +92,62 @@ __ASM_STDCALL_FUNC( wrap_fastcall_func1, 8, #define call_fastcall_func1( func, a ) func( a ) #endif
+static NTSTATUS remove_child_device( struct func_device *impl, DEVICE_OBJECT *device ) +{ + NTSTATUS status = STATUS_SUCCESS; + KIRQL irql; + ULONG i; + + KeAcquireSpinLock( &impl->base.lock, &irql ); + for (i = 0; i < impl->devices->Count; ++i) + if (impl->devices->Objects[i] == device) break; + if (i == impl->devices->Count) status = STATUS_NOT_FOUND; + else impl->devices->Objects[i] = impl->devices->Objects[impl->devices->Count--]; + KeReleaseSpinLock( &impl->base.lock, irql ); + + return status; +} + +static NTSTATUS append_child_device( struct func_device *impl, DEVICE_OBJECT *device ) +{ + NTSTATUS status; + KIRQL irql; + + KeAcquireSpinLock( &impl->base.lock, &irql ); + if (offsetof( DEVICE_RELATIONS, Objects[impl->devices->Count + 1] ) > sizeof(impl->devices_buffer)) + status = STATUS_NO_MEMORY; + else + { + impl->devices->Objects[impl->devices->Count++] = device; + status = STATUS_SUCCESS; + } + KeReleaseSpinLock( &impl->base.lock, irql ); + + return status; +} + +static DEVICE_OBJECT *find_child_device( struct func_device *impl, struct bus_device_desc *desc ) +{ + DEVICE_OBJECT *device = NULL, **devices; + WCHAR device_id[MAX_PATH]; + KIRQL irql; + ULONG i; + + swprintf( device_id, MAX_PATH, L"WINETEST\VID_%04X&PID_%04X", desc->vid, desc->pid ); + + KeAcquireSpinLock( &impl->base.lock, &irql ); + devices = impl->devices->Objects; + for (i = 0; i < impl->devices->Count; ++i) + { + struct phys_device *phys = pdo_from_DEVICE_OBJECT( (device = devices[i]) ); + if (!wcscmp( phys->device_id, device_id )) break; + else device = NULL; + } + KeReleaseSpinLock( &impl->base.lock, irql ); + + return device; +} + static ULONG_PTR get_device_relations( DEVICE_OBJECT *device, DEVICE_RELATIONS *previous, ULONG count, DEVICE_OBJECT **devices ) { @@ -102,10 +177,268 @@ static ULONG_PTR get_device_relations( DEVICE_OBJECT *device, DEVICE_RELATIONS * return (ULONG_PTR)relations; }
+static WCHAR *query_instance_id( DEVICE_OBJECT *device ) +{ + struct phys_device *impl = pdo_from_DEVICE_OBJECT( device ); + DWORD size = (wcslen( impl->instance_id ) + 1) * sizeof(WCHAR); + WCHAR *dst; + + if ((dst = ExAllocatePool( PagedPool, size ))) + memcpy( dst, impl->instance_id, size ); + + return dst; +} + +static WCHAR *query_hardware_ids( DEVICE_OBJECT *device ) +{ + struct phys_device *impl = pdo_from_DEVICE_OBJECT( device ); + DWORD size = (wcslen( impl->device_id ) + 1) * sizeof(WCHAR); + WCHAR *dst; + + if ((dst = ExAllocatePool( PagedPool, size + sizeof(WCHAR) ))) + { + memcpy( dst, impl->device_id, size ); + dst[size / sizeof(WCHAR)] = 0; + } + + return dst; +} + +static WCHAR *query_compatible_ids( DEVICE_OBJECT *device ) +{ + DWORD size = 0; + WCHAR *dst; + + if ((dst = ExAllocatePool( PagedPool, size + sizeof(WCHAR) ))) + dst[size / sizeof(WCHAR)] = 0; + + return dst; +} + +static WCHAR *query_container_id( DEVICE_OBJECT *device ) +{ + static const WCHAR winetest_id[] = L"WINETEST"; + DWORD size = sizeof(winetest_id); + WCHAR *dst; + + if ((dst = ExAllocatePool( PagedPool, size ))) + memcpy( dst, winetest_id, sizeof(winetest_id) ); + + return dst; +} + +typedef struct _PNP_BUS_INFORMATION +{ + GUID BusTypeGuid; + INTERFACE_TYPE LegacyBusType; + ULONG BusNumber; +} PNP_BUS_INFORMATION, *PPNP_BUS_INFORMATION; + +static PNP_BUS_INFORMATION *query_bus_information( DEVICE_OBJECT *device ) +{ + DWORD size = sizeof(PNP_BUS_INFORMATION); + PNP_BUS_INFORMATION *dst; + + if ((dst = ExAllocatePool( PagedPool, size ))) + { + memset( &dst->BusTypeGuid, 0, sizeof(dst->BusTypeGuid) ); + dst->LegacyBusType = PNPBus; + dst->BusNumber = 0; + } + + return dst; +} + +static WCHAR *query_device_text( DEVICE_OBJECT *device ) +{ + static const WCHAR device_text[] = L"Wine Test HID device"; + DWORD size = sizeof(device_text); + WCHAR *dst; + + if ((dst = ExAllocatePool( PagedPool, size ))) + memcpy( dst, device_text, size ); + + return dst; +} + +static NTSTATUS pdo_pnp( DEVICE_OBJECT *device, IRP *irp ) +{ + IO_STACK_LOCATION *stack = IoGetCurrentIrpStackLocation( irp ); + struct phys_device *impl = pdo_from_DEVICE_OBJECT( device ); + struct func_device *fdo = fdo_from_DEVICE_OBJECT( device ); + ULONG code = stack->MinorFunction; + PNP_DEVICE_STATE state; + NTSTATUS status; + KIRQL irql; + + if (winetest_debug > 1) trace( "%s: device %p, code %#lx %s\n", __func__, device, code, debugstr_pnp(code) ); + + switch (code) + { + case IRP_MN_START_DEVICE: + case IRP_MN_CANCEL_REMOVE_DEVICE: + case IRP_MN_SURPRISE_REMOVAL: + case IRP_MN_QUERY_REMOVE_DEVICE: + case IRP_MN_REMOVE_DEVICE: + state = (code == IRP_MN_START_DEVICE || code == IRP_MN_CANCEL_REMOVE_DEVICE) ? 0 : PNP_DEVICE_REMOVED; + KeAcquireSpinLock( &impl->base.lock, &irql ); + impl->base.state = state; + KeReleaseSpinLock( &impl->base.lock, irql ); + if (code != IRP_MN_REMOVE_DEVICE) status = STATUS_SUCCESS; + else + { + irp->IoStatus.Status = STATUS_SUCCESS; + IoCompleteRequest( irp, IO_NO_INCREMENT ); + if (remove_child_device( fdo, device )) + { + IoDeleteDevice( device ); + if (winetest_debug > 1) trace( "Deleted Bus PDO %p\n", device ); + } + return STATUS_SUCCESS; + } + break; + case IRP_MN_QUERY_CAPABILITIES: + { + DEVICE_CAPABILITIES *caps = stack->Parameters.DeviceCapabilities.Capabilities; + caps->Removable = 1; + caps->SilentInstall = 1; + caps->SurpriseRemovalOK = 1; + /* caps->RawDeviceOK = 1; */ + status = STATUS_SUCCESS; + break; + } + case IRP_MN_QUERY_ID: + { + BUS_QUERY_ID_TYPE type = stack->Parameters.QueryId.IdType; + switch (type) + { + case BusQueryDeviceID: + case BusQueryHardwareIDs: + irp->IoStatus.Information = (ULONG_PTR)query_hardware_ids( device ); + if (!irp->IoStatus.Information) status = STATUS_NO_MEMORY; + else status = STATUS_SUCCESS; + break; + case BusQueryInstanceID: + irp->IoStatus.Information = (ULONG_PTR)query_instance_id( device ); + if (!irp->IoStatus.Information) status = STATUS_NO_MEMORY; + else status = STATUS_SUCCESS; + break; + case BusQueryCompatibleIDs: + irp->IoStatus.Information = (ULONG_PTR)query_compatible_ids( device ); + if (!irp->IoStatus.Information) status = STATUS_NO_MEMORY; + else status = STATUS_SUCCESS; + break; + case BusQueryContainerID: + irp->IoStatus.Information = (ULONG_PTR)query_container_id( device ); + if (!irp->IoStatus.Information) status = STATUS_NO_MEMORY; + else status = STATUS_SUCCESS; + break; + default: + ok( 0, "IRP_MN_QUERY_ID type %u, not implemented!\n", type ); + status = STATUS_NOT_SUPPORTED; + break; + } + break; + } + case IRP_MN_QUERY_BUS_INFORMATION: + irp->IoStatus.Information = (ULONG_PTR)query_bus_information( device ); + if (!irp->IoStatus.Information) status = STATUS_NO_MEMORY; + else status = STATUS_SUCCESS; + break; + case IRP_MN_QUERY_DEVICE_TEXT: + irp->IoStatus.Information = (ULONG_PTR)query_device_text( device ); + if (!irp->IoStatus.Information) status = STATUS_NO_MEMORY; + else status = STATUS_SUCCESS; + break; + case IRP_MN_QUERY_PNP_DEVICE_STATE: + irp->IoStatus.Information = impl->base.state; + status = STATUS_SUCCESS; + break; + case IRP_MN_QUERY_DEVICE_RELATIONS: + { + DEVICE_RELATION_TYPE type = stack->Parameters.QueryDeviceRelations.Type; + switch (type) + { + case BusRelations: + if (winetest_debug > 1) trace( "pdo_pnp IRP_MN_QUERY_DEVICE_RELATIONS BusRelations\n" ); + ok( irp->IoStatus.Information, "got unexpected BusRelations relations\n" ); + status = irp->IoStatus.Status; + break; + case EjectionRelations: + if (winetest_debug > 1) trace( "pdo_pnp IRP_MN_QUERY_DEVICE_RELATIONS EjectionRelations\n" ); + ok( !irp->IoStatus.Information, "got unexpected EjectionRelations relations\n" ); + status = irp->IoStatus.Status; + break; + case RemovalRelations: + if (winetest_debug > 1) trace( "pdo_pnp IRP_MN_QUERY_DEVICE_RELATIONS RemovalRelations\n" ); + ok( irp->IoStatus.Information, "got unexpected RemovalRelations relations\n" ); + status = irp->IoStatus.Status; + break; + case TargetDeviceRelation: + if (winetest_debug > 1) trace( "pdo_pnp IRP_MN_QUERY_DEVICE_RELATIONS TargetDeviceRelations\n" ); + ok( !irp->IoStatus.Information, "got unexpected TargetDeviceRelations relations\n" ); + irp->IoStatus.Information = get_device_relations( device, (void *)irp->IoStatus.Information, 1, &device ); + if (!irp->IoStatus.Information) status = STATUS_NO_MEMORY; + else status = STATUS_SUCCESS; + break; + default: + ok( 0, "got unexpected IRP_MN_QUERY_DEVICE_RELATIONS type %#x\n", type ); + status = irp->IoStatus.Status; + break; + } + break; + } + default: + if (winetest_debug > 1) trace( "pdo_pnp code %#lx %s, not implemented!\n", code, debugstr_pnp(code) ); + status = irp->IoStatus.Status; + break; + } + + irp->IoStatus.Status = status; + IoCompleteRequest( irp, IO_NO_INCREMENT ); + return status; +} + +static NTSTATUS create_child_pdo( DEVICE_OBJECT *device, struct bus_device_desc *desc ) +{ + static ULONG index; + + struct func_device *fdo = fdo_from_DEVICE_OBJECT( device ); + struct phys_device *impl; + UNICODE_STRING name_str; + DEVICE_OBJECT *child; + WCHAR name[MAX_PATH]; + NTSTATUS status; + + swprintf( name, MAX_PATH, L"\Device\WINETEST#%p&%p&%u", device->DriverObject, device, index++ ); + RtlInitUnicodeString( &name_str, name ); + + if ((status = IoCreateDevice( device->DriverObject, sizeof(struct phys_device), &name_str, 0, 0, FALSE, &child ))) + { + ok( 0, "Failed to create gamepad device, status %#lx\n", status ); + return status; + } + + impl = pdo_from_DEVICE_OBJECT( child ); + KeInitializeSpinLock( &impl->base.lock ); + swprintf( impl->device_id, MAX_PATH, L"WINETEST\VID_%04X&PID_%04X", desc->vid, desc->pid ); + swprintf( impl->instance_id, MAX_PATH, L"0&0000&0" ); + impl->base.is_phys = TRUE; + impl->fdo = fdo; + + if (winetest_debug > 1) trace( "Created Bus PDO %p for Bus FDO %p\n", child, device ); + + append_child_device( fdo, child ); + IoInvalidateDeviceRelations( fdo->pdo, BusRelations ); + return STATUS_SUCCESS; +} + static NTSTATUS fdo_pnp( DEVICE_OBJECT *device, IRP *irp ) { struct func_device *impl = fdo_from_DEVICE_OBJECT( device ); IO_STACK_LOCATION *stack = IoGetCurrentIrpStackLocation( irp ); + char relations_buffer[sizeof(impl->devices_buffer)]; + DEVICE_RELATIONS *relations = (void *)relations_buffer; ULONG code = stack->MinorFunction; PNP_DEVICE_STATE state; NTSTATUS status; @@ -123,11 +456,14 @@ static NTSTATUS fdo_pnp( DEVICE_OBJECT *device, IRP *irp ) state = (code == IRP_MN_START_DEVICE || code == IRP_MN_CANCEL_REMOVE_DEVICE) ? 0 : PNP_DEVICE_REMOVED; KeAcquireSpinLock( &impl->base.lock, &irql ); impl->base.state = state; + if (code == IRP_MN_REMOVE_DEVICE) memcpy( relations, impl->devices, sizeof(relations_buffer) ); + impl->devices->Count = 0; KeReleaseSpinLock( &impl->base.lock, irql ); IoSetDeviceInterfaceState( &impl->control_iface, state != PNP_DEVICE_REMOVED ); if (code != IRP_MN_REMOVE_DEVICE) status = STATUS_SUCCESS; else { + while (relations->Count--) IoDeleteDevice( relations->Objects[relations->Count] ); IoSkipCurrentIrpStackLocation( irp ); status = IoCallDriver( impl->pdo, irp ); IoDetachDevice( impl->pdo ); @@ -151,7 +487,11 @@ static NTSTATUS fdo_pnp( DEVICE_OBJECT *device, IRP *irp ) case BusRelations: if (winetest_debug > 1) trace( "fdo_pnp IRP_MN_QUERY_DEVICE_RELATIONS BusRelations\n" ); ok( !irp->IoStatus.Information, "got unexpected BusRelations relations\n" ); - irp->IoStatus.Information = get_device_relations( device, (void *)irp->IoStatus.Information, 0, NULL ); + KeAcquireSpinLock( &impl->base.lock, &irql ); + memcpy( relations, impl->devices, sizeof(relations_buffer) ); + KeReleaseSpinLock( &impl->base.lock, irql ); + irp->IoStatus.Information = get_device_relations( device, (void *)irp->IoStatus.Information, + relations->Count, relations->Objects ); if (!irp->IoStatus.Information) status = STATUS_NO_MEMORY; else status = STATUS_SUCCESS; break; @@ -193,10 +533,45 @@ static NTSTATUS fdo_pnp( DEVICE_OBJECT *device, IRP *irp )
static NTSTATUS WINAPI driver_pnp( DEVICE_OBJECT *device, IRP *irp ) { + struct device *impl = impl_from_DEVICE_OBJECT( device ); + if (impl->is_phys) return pdo_pnp( device, irp ); return fdo_pnp( device, irp ); }
+static NTSTATUS WINAPI pdo_internal_ioctl( DEVICE_OBJECT *device, IRP *irp ) +{ + IO_STACK_LOCATION *stack = IoGetCurrentIrpStackLocation( irp ); + ULONG code = stack->Parameters.DeviceIoControl.IoControlCode; + + if (winetest_debug > 1) trace( "%s: device %p, code %#lx %s\n", __func__, device, code, debugstr_ioctl(code) ); + ok( 0, "unexpected call\n" ); + + irp->IoStatus.Status = STATUS_NOT_SUPPORTED; + IoCompleteRequest( irp, IO_NO_INCREMENT ); + return STATUS_NOT_SUPPORTED; +} + +static NTSTATUS WINAPI fdo_internal_ioctl( DEVICE_OBJECT *device, IRP *irp ) +{ + IO_STACK_LOCATION *stack = IoGetCurrentIrpStackLocation( irp ); + ULONG code = stack->Parameters.DeviceIoControl.IoControlCode; + + if (winetest_debug > 1) trace( "%s: device %p, code %#lx %s\n", __func__, device, code, debugstr_ioctl(code) ); + ok( 0, "unexpected call\n" ); + + irp->IoStatus.Status = STATUS_NOT_SUPPORTED; + IoCompleteRequest( irp, IO_NO_INCREMENT ); + return STATUS_NOT_SUPPORTED; +} + static NTSTATUS WINAPI driver_internal_ioctl( DEVICE_OBJECT *device, IRP *irp ) +{ + struct device *impl = impl_from_DEVICE_OBJECT( device ); + if (impl->is_phys) return pdo_internal_ioctl( device, irp ); + return fdo_internal_ioctl( device, irp ); +} + +static NTSTATUS WINAPI pdo_ioctl( DEVICE_OBJECT *device, IRP *irp ) { IO_STACK_LOCATION *stack = IoGetCurrentIrpStackLocation( irp ); ULONG code = stack->Parameters.DeviceIoControl.IoControlCode; @@ -209,17 +584,44 @@ static NTSTATUS WINAPI driver_internal_ioctl( DEVICE_OBJECT *device, IRP *irp ) return STATUS_NOT_SUPPORTED; }
-static NTSTATUS WINAPI driver_ioctl( DEVICE_OBJECT *device, IRP *irp ) +static NTSTATUS WINAPI fdo_ioctl( DEVICE_OBJECT *device, IRP *irp ) { IO_STACK_LOCATION *stack = IoGetCurrentIrpStackLocation( irp ); + ULONG in_size = stack->Parameters.DeviceIoControl.InputBufferLength; ULONG code = stack->Parameters.DeviceIoControl.IoControlCode; + struct func_device *impl = fdo_from_DEVICE_OBJECT( device ); + NTSTATUS status;
if (winetest_debug > 1) trace( "%s: device %p, code %#lx %s\n", __func__, device, code, debugstr_ioctl(code) ); - ok( 0, "unexpected call\n" );
- irp->IoStatus.Status = STATUS_NOT_SUPPORTED; + switch (code) + { + case IOCTL_WINETEST_CREATE_DEVICE: + if (in_size < sizeof(struct bus_device_desc)) status = STATUS_INVALID_PARAMETER; + else status = create_child_pdo( device, irp->AssociatedIrp.SystemBuffer ); + break; + case IOCTL_WINETEST_REMOVE_DEVICE: + if ((device = find_child_device( impl, irp->AssociatedIrp.SystemBuffer )) && + !remove_child_device( impl, device )) + IoInvalidateDeviceRelations( impl->pdo, BusRelations ); + status = STATUS_SUCCESS; + break; + default: + ok( 0, "unexpected call\n" ); + status = irp->IoStatus.Status; + break; + } + + irp->IoStatus.Status = status; IoCompleteRequest( irp, IO_NO_INCREMENT ); - return STATUS_NOT_SUPPORTED; + return status; +} + +static NTSTATUS WINAPI driver_ioctl( DEVICE_OBJECT *device, IRP *irp ) +{ + struct device *impl = impl_from_DEVICE_OBJECT( device ); + if (impl->is_phys) return pdo_ioctl( device, irp ); + return fdo_ioctl( device, irp ); }
static NTSTATUS WINAPI driver_add_device( DRIVER_OBJECT *driver, DEVICE_OBJECT *device ) @@ -237,6 +639,7 @@ static NTSTATUS WINAPI driver_add_device( DRIVER_OBJECT *driver, DEVICE_OBJECT * }
impl = (struct func_device *)child->DeviceExtension; + impl->devices = (void *)impl->devices_buffer; KeInitializeSpinLock( &impl->base.lock ); impl->pdo = device;
diff --git a/dlls/dinput/tests/driver_hid.h b/dlls/dinput/tests/driver_hid.h index 80073a6ae3f..8ac91e5cc81 100644 --- a/dlls/dinput/tests/driver_hid.h +++ b/dlls/dinput/tests/driver_hid.h @@ -43,6 +43,8 @@ DEFINE_GUID(control_class,0xdeadbeef,0x29ef,0x4538,0xa5,0xfd,0xb6,0x95,0x73,0xa3 #define IOCTL_WINETEST_HID_WAIT_EXPECT CTL_CODE(FILE_DEVICE_KEYBOARD, 0x801, METHOD_NEITHER, FILE_ANY_ACCESS) #define IOCTL_WINETEST_HID_SEND_INPUT CTL_CODE(FILE_DEVICE_KEYBOARD, 0x802, METHOD_IN_DIRECT, FILE_ANY_ACCESS) #define IOCTL_WINETEST_HID_SET_CONTEXT CTL_CODE(FILE_DEVICE_KEYBOARD, 0x803, METHOD_IN_DIRECT, FILE_ANY_ACCESS) +#define IOCTL_WINETEST_CREATE_DEVICE CTL_CODE(FILE_DEVICE_KEYBOARD, 0x804, METHOD_IN_DIRECT, FILE_ANY_ACCESS) +#define IOCTL_WINETEST_REMOVE_DEVICE CTL_CODE(FILE_DEVICE_KEYBOARD, 0x805, METHOD_IN_DIRECT, FILE_ANY_ACCESS)
struct hid_expect { @@ -57,6 +59,13 @@ struct hid_expect BYTE report_buf[128]; };
+/* create/remove device */ +struct bus_device_desc +{ + WORD vid; + WORD pid; +}; + /* kernel/user shared data */ struct winetest_shared_data { @@ -136,6 +145,8 @@ static inline const char *debugstr_ioctl( ULONG code ) case IOCTL_WINETEST_HID_WAIT_EXPECT: return "IOCTL_WINETEST_HID_WAIT_EXPECT"; case IOCTL_WINETEST_HID_SEND_INPUT: return "IOCTL_WINETEST_HID_SEND_INPUT"; case IOCTL_WINETEST_HID_SET_CONTEXT: return "IOCTL_WINETEST_HID_SET_CONTEXT"; + case IOCTL_WINETEST_CREATE_DEVICE: return "IOCTL_WINETEST_CREATE_DEVICE"; + case IOCTL_WINETEST_REMOVE_DEVICE: return "IOCTL_WINETEST_REMOVE_DEVICE"; default: return "unknown"; } } diff --git a/dlls/dinput/tests/hid.c b/dlls/dinput/tests/hid.c index bcaf949eb9c..e61ff11b925 100644 --- a/dlls/dinput/tests/hid.c +++ b/dlls/dinput/tests/hid.c @@ -427,7 +427,8 @@ static void unload_driver( SC_HANDLE service ) ret = QueryServiceStatus( service, &status ); ok( ret, "QueryServiceStatus failed: %lu\n", GetLastError() ); } - ok( status.dwCurrentState == SERVICE_STOPPED, "expected SERVICE_STOPPED, got %lu\n", status.dwCurrentState ); + ok( status.dwCurrentState == SERVICE_STOPPED || !status.dwCurrentState, + "expected SERVICE_STOPPED, got %lu\n", status.dwCurrentState );
DeleteService( service ); CloseServiceHandle( service ); @@ -493,8 +494,8 @@ static void pnp_driver_stop( BOOL bus ) GetFullPathNameW( L"winetest.inf", ARRAY_SIZE(path), path, NULL ); ret = SetupCopyOEMInfW( path, NULL, 0, 0, dest, ARRAY_SIZE(dest), NULL, &filepart ); ok( ret, "Failed to copy INF, error %lu\n", GetLastError() ); - ret = SetupUninstallOEMInfW( filepart, 0, NULL ); - ok( ret, "Failed to uninstall INF, error %lu\n", GetLastError() ); + ret = SetupUninstallOEMInfW( filepart, SUOI_FORCEDELETE, NULL ); + ok( ret, "Failed to uninstall INF, error %lx\n", GetLastError() );
ret = DeleteFileW( L"winetest.cat" ); ok( ret, "Failed to delete file, error %lu\n", GetLastError() ); @@ -3611,7 +3612,12 @@ DWORD WINAPI dinput_test_device_thread( void *stop_event )
static void test_bus_driver(void) { + struct bus_device_desc desc = + { + .vid = LOWORD(EXPECT_VIDPID), .pid = HIWORD(EXPECT_VIDPID), + }; HANDLE control; + BOOL ret;
if (!bus_device_start()) goto done;
@@ -3631,6 +3637,11 @@ static void test_bus_driver(void) control = CreateFileW( L"\\?\root#winetest#0#{deadbeef-29ef-4538-a5fd-b69573a362c0}", 0, 0, NULL, OPEN_EXISTING, 0, NULL ); ok( control != INVALID_HANDLE_VALUE, "CreateFile failed, error %lu\n", GetLastError() ); + ret = sync_ioctl( control, IOCTL_WINETEST_CREATE_DEVICE, &desc, sizeof(desc), NULL, 0, INFINITE ); + ok( ret, "IOCTL_WINETEST_CREATE_DEVICE failed, last error %lu\n", GetLastError() ); + + ret = sync_ioctl( control, IOCTL_WINETEST_REMOVE_DEVICE, &desc, sizeof(desc), NULL, 0, INFINITE ); + ok( ret, "IOCTL_WINETEST_REMOVE_DEVICE failed, last error %lu\n", GetLastError() ); CloseHandle( control );
done: