[PATCH 4/5] dinput/tests: Create all HID devices from the Bus driver.

Rémi Bernon rbernon at codeweavers.com
Tue Mar 22 05:41:40 CDT 2022


Signed-off-by: Rémi Bernon <rbernon at codeweavers.com>
---
 dlls/dinput/tests/dinput_test.h    |  20 +-
 dlls/dinput/tests/driver_bus.c     |  11 +-
 dlls/dinput/tests/driver_hid.h     |   2 +-
 dlls/dinput/tests/force_feedback.c |  71 +++----
 dlls/dinput/tests/hid.c            | 285 +++++++++--------------------
 dlls/dinput/tests/hotplug.c        |  38 ++--
 dlls/dinput/tests/joystick8.c      | 240 +++++++++++++++---------
 7 files changed, 318 insertions(+), 349 deletions(-)

diff --git a/dlls/dinput/tests/dinput_test.h b/dlls/dinput/tests/dinput_test.h
index 46ea8109c9a..8fefb0c8c42 100644
--- a/dlls/dinput/tests/dinput_test.h
+++ b/dlls/dinput/tests/dinput_test.h
@@ -44,6 +44,7 @@
 #include "driver_hid.h"
 
 #define EXPECT_VIDPID MAKELONG( 0x1209, 0x0001 )
+extern const HID_DEVICE_ATTRIBUTES default_attributes;
 extern const WCHAR expect_vidpid_str[];
 extern const GUID expect_guid_product;
 extern const WCHAR expect_path[];
@@ -53,17 +54,13 @@ extern HANDLE device_added, device_removed;
 extern HINSTANCE instance;
 extern BOOL localized; /* object names get translated */
 
-BOOL hid_device_start(void);
-void hid_device_stop(void);
+BOOL hid_device_start( struct hid_device_desc *desc );
+void hid_device_stop( struct hid_device_desc *desc );
 BOOL bus_device_start(void);
 void bus_device_stop(void);
 
 void cleanup_registry_keys(void);
 
-#define dinput_driver_start( a, b, c, d, e ) dinput_driver_start_( __FILE__, __LINE__, a, b, c, d, e )
-BOOL dinput_driver_start_( const char *file, int line, const BYTE *desc_buf, ULONG desc_len,
-                           const HIDP_CAPS *caps, struct hid_expect *expect, ULONG expect_size );
-
 #define dinput_test_init() dinput_test_init_( __FILE__, __LINE__ )
 BOOL dinput_test_init_( const char *file, int line );
 void dinput_test_exit(void);
@@ -71,6 +68,17 @@ void dinput_test_exit(void);
 HRESULT dinput_test_create_device( DWORD version, DIDEVICEINSTANCEW *devinst, IDirectInputDevice8W **device );
 DWORD WINAPI dinput_test_device_thread( void *stop_event );
 
+#define fill_context( line, a, b )                                                                 \
+    do                                                                                             \
+    {                                                                                              \
+        const char *source_file;                                                                   \
+        source_file = strrchr( __FILE__, '/' );                                                    \
+        if (!source_file) source_file = strrchr( __FILE__, '\\' );                                 \
+        if (!source_file) source_file = __FILE__;                                                  \
+        else source_file++;                                                                        \
+        snprintf( a, b, "%s:%d", source_file, line );                                              \
+    } while (0)
+
 #define check_member_( file, line, val, exp, fmt, member )                                         \
     ok_(file, line)( (val).member == (exp).member, "got " #member " " fmt "\n", (val).member )
 #define check_member( val, exp, fmt, member )                                                      \
diff --git a/dlls/dinput/tests/driver_bus.c b/dlls/dinput/tests/driver_bus.c
index 959e620e8f6..16b32e97442 100644
--- a/dlls/dinput/tests/driver_bus.c
+++ b/dlls/dinput/tests/driver_bus.c
@@ -500,7 +500,7 @@ static NTSTATUS append_child_device( struct func_device *impl, DEVICE_OBJECT *de
     return status;
 }
 
-static DEVICE_OBJECT *find_child_device( struct func_device *impl, struct bus_device_desc *desc )
+static DEVICE_OBJECT *find_child_device( struct func_device *impl, struct hid_device_desc *desc )
 {
     DEVICE_OBJECT *device = NULL, **devices;
     WCHAR device_id[MAX_PATH];
@@ -785,7 +785,7 @@ static NTSTATUS pdo_pnp( DEVICE_OBJECT *device, IRP *irp )
     return status;
 }
 
-static NTSTATUS create_child_pdo( DEVICE_OBJECT *device, struct bus_device_desc *desc )
+static NTSTATUS create_child_pdo( DEVICE_OBJECT *device, struct hid_device_desc *desc )
 {
     static ULONG index;
 
@@ -954,7 +954,8 @@ static NTSTATUS WINAPI pdo_internal_ioctl( DEVICE_OBJECT *device, IRP *irp )
     KIRQL irql;
     LONG index;
 
-    if (winetest_debug > 1) trace( "%s: device %p, code %#lx %s\n", __func__, device, code, debugstr_ioctl(code) );
+    if ((!impl->input_queue.is_polled || code != IOCTL_HID_READ_REPORT) && winetest_debug > 1)
+        trace( "%s: device %p, code %#lx %s\n", __func__, device, code, debugstr_ioctl(code) );
 
     KeAcquireSpinLock( &impl->base.lock, &irql );
     removed = impl->base.state == PNP_DEVICE_REMOVED;
@@ -1248,7 +1249,7 @@ static NTSTATUS WINAPI fdo_ioctl( DEVICE_OBJECT *device, IRP *irp )
     switch (code)
     {
     case IOCTL_WINETEST_CREATE_DEVICE:
-        if (in_size < sizeof(struct bus_device_desc)) status = STATUS_INVALID_PARAMETER;
+        if (in_size < sizeof(struct hid_device_desc)) status = STATUS_INVALID_PARAMETER;
         else status = create_child_pdo( device, irp->AssociatedIrp.SystemBuffer );
         break;
     case IOCTL_WINETEST_REMOVE_DEVICE:
@@ -1259,7 +1260,7 @@ static NTSTATUS WINAPI fdo_ioctl( DEVICE_OBJECT *device, IRP *irp )
             IoInvalidateDeviceRelations( impl->pdo, BusRelations );
             return status;
         }
-        status = STATUS_SUCCESS;
+        status = STATUS_NO_SUCH_DEVICE;
         break;
     default:
         ok( 0, "unexpected call\n" );
diff --git a/dlls/dinput/tests/driver_hid.h b/dlls/dinput/tests/driver_hid.h
index 0bc8e34ccc9..1010499fc41 100644
--- a/dlls/dinput/tests/driver_hid.h
+++ b/dlls/dinput/tests/driver_hid.h
@@ -62,7 +62,7 @@ struct hid_expect
 };
 
 /* create/remove device */
-struct bus_device_desc
+struct hid_device_desc
 {
     BOOL is_polled;
     BOOL use_report_id;
diff --git a/dlls/dinput/tests/force_feedback.c b/dlls/dinput/tests/force_feedback.c
index 855d716e87c..b0c940c9cd6 100644
--- a/dlls/dinput/tests/force_feedback.c
+++ b/dlls/dinput/tests/force_feedback.c
@@ -1968,9 +1968,11 @@ static BOOL test_force_feedback_joystick( DWORD version )
 #undef REPORT_ID_OR_USAGE_PAGE
 #include "pop_hid_macros.h"
 
-    static const HIDP_CAPS hid_caps =
+    struct hid_device_desc desc =
     {
-        .InputReportByteLength = 5,
+        .use_report_id = TRUE,
+        .caps = { .InputReportByteLength = 5 },
+        .attributes = default_attributes,
     };
     const DIDEVCAPS expect_caps =
     {
@@ -2032,8 +2034,8 @@ static BOOL test_force_feedback_joystick( DWORD version )
         .guidProduct = expect_guid_product,
         .dwDevType = version >= 0x800 ? DIDEVTYPE_HID | (DI8DEVTYPEJOYSTICK_LIMITED << 8) | DI8DEVTYPE_JOYSTICK
                                       : DIDEVTYPE_HID | (DIDEVTYPEJOYSTICK_UNKNOWN << 8) | DIDEVTYPE_JOYSTICK,
-        .tszInstanceName = L"Wine test root driver",
-        .tszProductName = L"Wine test root driver",
+        .tszInstanceName = L"Wine Test",
+        .tszProductName = L"Wine Test",
         .guidFFDriver = IID_IDirectInputPIDDriver,
         .wUsagePage = HID_USAGE_PAGE_GENERIC,
         .wUsage = HID_USAGE_GENERIC_JOYSTICK,
@@ -2774,7 +2776,6 @@ static BOOL test_force_feedback_joystick( DWORD version )
         },
     };
     DIDEVICEINSTANCEW devinst = {.dwSize = sizeof(DIDEVICEINSTANCEW)};
-    WCHAR cwd[MAX_PATH], tempdir[MAX_PATH];
     IDirectInputDevice8W *device = NULL;
     DIDEVICEOBJECTDATA objdata = {0};
     DIEFFECTINFOW effectinfo = {0};
@@ -2787,13 +2788,13 @@ static BOOL test_force_feedback_joystick( DWORD version )
     HWND hwnd;
 
     winetest_push_context( "%#lx", version );
-
-    GetCurrentDirectoryW( ARRAY_SIZE(cwd), cwd );
-    GetTempPathW( ARRAY_SIZE(tempdir), tempdir );
-    SetCurrentDirectoryW( tempdir );
-
     cleanup_registry_keys();
-    if (!dinput_driver_start( report_descriptor, sizeof(report_descriptor), &hid_caps, NULL, 0 )) goto done;
+
+    desc.report_descriptor_len = sizeof(report_descriptor);
+    memcpy( desc.report_descriptor_buf, report_descriptor, sizeof(report_descriptor) );
+    fill_context( __LINE__, desc.context, ARRAY_SIZE(desc.context) );
+
+    if (!hid_device_start( &desc )) goto done;
     if (FAILED(hr = dinput_test_create_device( version, &devinst, &device ))) goto done;
 
     check_dinput_devices( version, &devinst );
@@ -2805,9 +2806,7 @@ static BOOL test_force_feedback_joystick( DWORD version )
     check_member_guid( devinst, expect_devinst, guidInstance );
     check_member_guid( devinst, expect_devinst, guidProduct );
     check_member( devinst, expect_devinst, "%#lx", dwDevType );
-    todo_wine
     check_member_wstr( devinst, expect_devinst, tszInstanceName );
-    todo_wine
     check_member_wstr( devinst, expect_devinst, tszProductName );
     check_member_guid( devinst, expect_devinst, guidFFDriver );
     check_member( devinst, expect_devinst, "%04x", wUsagePage );
@@ -2996,9 +2995,8 @@ static BOOL test_force_feedback_joystick( DWORD version )
     CloseHandle( file );
 
 done:
-    hid_device_stop();
+    hid_device_stop( &desc );
     cleanup_registry_keys();
-    SetCurrentDirectoryW( cwd );
     winetest_pop_context();
 
     return device != NULL;
@@ -3421,9 +3419,11 @@ static void test_device_managed_effect(void)
     };
 #include "pop_hid_macros.h"
 
-    static const HIDP_CAPS hid_caps =
+    struct hid_device_desc desc =
     {
-        .InputReportByteLength = 5,
+        .use_report_id = TRUE,
+        .caps = { .InputReportByteLength = 5 },
+        .attributes = default_attributes,
     };
     struct hid_expect expect_acquire[] =
     {
@@ -3889,23 +3889,24 @@ static void test_device_managed_effect(void)
         },
     };
     DIDEVICEINSTANCEW devinst = {.dwSize = sizeof(DIDEVICEINSTANCEW)};
-    WCHAR cwd[MAX_PATH], tempdir[MAX_PATH];
     IDirectInputDevice8W *device;
     IDirectInputEffect *effect, *effect2;
+    DIEFFECT effect_desc;
     HANDLE file, event;
     ULONG res, ref;
-    DIEFFECT desc;
     DWORD flags;
     HRESULT hr;
     HWND hwnd;
 
-    GetCurrentDirectoryW( ARRAY_SIZE(cwd), cwd );
-    GetTempPathW( ARRAY_SIZE(tempdir), tempdir );
-    SetCurrentDirectoryW( tempdir );
-
     cleanup_registry_keys();
-    if (!dinput_driver_start( report_descriptor, sizeof(report_descriptor), &hid_caps,
-                              expect_pool, sizeof(expect_pool) )) goto done;
+
+    desc.report_descriptor_len = sizeof(report_descriptor);
+    memcpy( desc.report_descriptor_buf, report_descriptor, sizeof(report_descriptor) );
+    desc.expect_size = sizeof(expect_pool);
+    memcpy( desc.expect, expect_pool, sizeof(expect_pool) );
+    fill_context( __LINE__, desc.context, ARRAY_SIZE(desc.context) );
+
+    if (!hid_device_start( &desc )) goto done;
     if (FAILED(hr = dinput_test_create_device( DIRECTINPUT_VERSION, &devinst, &device ))) goto done;
 
     hr = IDirectInputDevice8_GetProperty( device, DIPROP_GUIDANDPATH, &prop_guid_path.diph );
@@ -4252,10 +4253,10 @@ static void test_device_managed_effect(void)
     ok( ref == 0, "Release returned %ld\n", ref );
 
     /* start delay has no direct effect on effect status */
-    desc = expect_desc;
-    desc.dwStartDelay = 32767000;
+    effect_desc = expect_desc;
+    effect_desc.dwStartDelay = 32767000;
     set_hid_expect( file, expect_create_delay, sizeof(expect_create_delay) );
-    hr = IDirectInputDevice8_CreateEffect( device, &GUID_Spring, &desc, &effect, NULL );
+    hr = IDirectInputDevice8_CreateEffect( device, &GUID_Spring, &effect_desc, &effect, NULL );
     ok( hr == DI_OK, "CreateEffect returned %#lx\n", hr );
     set_hid_expect( file, NULL, 0 );
     res = 0xdeadbeef;
@@ -4276,11 +4277,11 @@ static void test_device_managed_effect(void)
     set_hid_expect( file, NULL, 0 );
 
     /* duration has no direct effect on effect status */
-    desc = expect_desc;
-    desc.dwDuration = 100;
-    desc.dwStartDelay = 0;
+    effect_desc = expect_desc;
+    effect_desc.dwDuration = 100;
+    effect_desc.dwStartDelay = 0;
     set_hid_expect( file, expect_create_duration, sizeof(expect_create_duration) );
-    hr = IDirectInputDevice8_CreateEffect( device, &GUID_Spring, &desc, &effect, NULL );
+    hr = IDirectInputDevice8_CreateEffect( device, &GUID_Spring, &effect_desc, &effect, NULL );
     ok( hr == DI_OK, "CreateEffect returned %#lx\n", hr );
     set_hid_expect( file, NULL, 0 );
     res = 0xdeadbeef;
@@ -4314,15 +4315,15 @@ static void test_device_managed_effect(void)
     CloseHandle( file );
 
 done:
-    hid_device_stop();
+    hid_device_stop( &desc );
     cleanup_registry_keys();
-    SetCurrentDirectoryW( cwd );
     winetest_pop_context();
 }
 
 START_TEST( force_feedback )
 {
     if (!dinput_test_init()) return;
+    if (!bus_device_start()) goto done;
 
     CoInitialize( NULL );
     if (test_force_feedback_joystick( 0x800 ))
@@ -4333,5 +4334,7 @@ START_TEST( force_feedback )
     }
     CoUninitialize();
 
+done:
+    bus_device_stop();
     dinput_test_exit();
 }
diff --git a/dlls/dinput/tests/hid.c b/dlls/dinput/tests/hid.c
index 0ee6ab61fea..5ac14031dde 100644
--- a/dlls/dinput/tests/hid.c
+++ b/dlls/dinput/tests/hid.c
@@ -62,9 +62,16 @@
 HINSTANCE instance;
 BOOL localized; /* object names get translated */
 
+const HID_DEVICE_ATTRIBUTES default_attributes =
+{
+    .Size = sizeof(HID_DEVICE_ATTRIBUTES),
+    .VendorID = LOWORD(EXPECT_VIDPID),
+    .ProductID = HIWORD(EXPECT_VIDPID),
+    .VersionNumber = 0x0100,
+};
 const WCHAR expect_vidpid_str[] = L"VID_1209&PID_0001";
 const GUID expect_guid_product = {EXPECT_VIDPID, 0x0000, 0x0000, {0x00, 0x00, 'P', 'I', 'D', 'V', 'I', 'D'}};
-const WCHAR expect_path[] = L"\\\\?\\hid#winetest#1&2fafeb0&";
+const WCHAR expect_path[] = L"\\\\?\\hid#vid_1209&pid_0001#2&";
 const WCHAR expect_path_end[] = L"&0000#{4d1e55b2-f16f-11cf-88cb-001111000030}";
 HANDLE device_added, device_removed;
 static BOOL hid_device_created;
@@ -558,6 +565,7 @@ static void pnp_driver_stop( BOOL bus )
     todo_wine_if(!ret && GetLastError() == ERROR_ACCESS_DENIED) /* Wine doesn't unload device drivers correctly */
     ok( ret || GetLastError() == ERROR_FILE_NOT_FOUND, "Failed to delete file, error %lu\n", GetLastError() );
     ret = DeleteFileW( L"C:/windows/system32/drivers/winetest_hid_poll.sys" );
+    todo_wine_if(!ret && GetLastError() == ERROR_ACCESS_DENIED) /* Wine doesn't unload device drivers correctly */
     ok( ret || GetLastError() == ERROR_FILE_NOT_FOUND, "Failed to delete file, error %lu\n", GetLastError() );
 }
 
@@ -727,14 +735,41 @@ static BOOL pnp_driver_start( BOOL bus )
     return ret || GetLastError() == ERROR_SERVICE_ALREADY_RUNNING;
 }
 
-void hid_device_stop(void)
+void hid_device_stop( struct hid_device_desc *desc )
 {
-    pnp_driver_stop( FALSE );
+    HANDLE control;
+    BOOL ret;
+
+    ResetEvent( device_removed );
+
+    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_REMOVE_DEVICE, desc, sizeof(*desc), NULL, 0, INFINITE );
+    ok( ret || GetLastError() == ERROR_FILE_NOT_FOUND, "IOCTL_WINETEST_REMOVE_DEVICE failed, last error %lu\n", GetLastError() );
+    CloseHandle( control );
+
+    if (ret) WaitForSingleObject( device_removed, INFINITE );
 }
 
-BOOL hid_device_start(void)
+BOOL hid_device_start( struct hid_device_desc *desc )
 {
-    return pnp_driver_start( FALSE );
+    HANDLE control;
+    BOOL ret;
+
+    ResetEvent( device_added );
+
+    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() );
+    CloseHandle( control );
+
+    WaitForSingleObject( device_added, INFINITE );
+    hid_device_created = TRUE;
+
+    return TRUE;
 }
 
 void bus_device_stop(void)
@@ -903,16 +938,6 @@ BOOL sync_ioctl_( const char *file, int line, HANDLE device, DWORD code, void *i
     return ret;
 }
 
-#define fill_context( line, a, b ) \
-    do { \
-        const char *source_file; \
-        source_file = strrchr( __FILE__, '/' ); \
-        if (!source_file) source_file = strrchr( __FILE__, '\\' ); \
-        if (!source_file) source_file = __FILE__; \
-        else source_file++; \
-        snprintf( a, b, "%s:%d", source_file, line ); \
-    } while (0)
-
 void set_hid_expect_( const char *file, int line, HANDLE device, struct hid_expect *expect, DWORD expect_size )
 {
     char context[64];
@@ -2480,20 +2505,16 @@ static void test_hidp( HANDLE file, HANDLE async_file, int report_id, BOOL polle
     HidD_FreePreparsedData( preparsed_data );
 }
 
-static void test_hid_device( DWORD report_id, DWORD polled, const HIDP_CAPS *expect_caps )
+static void test_hid_device( DWORD report_id, DWORD polled, const HIDP_CAPS *expect_caps, WORD vid, WORD pid )
 {
     ULONG count, poll_freq, out_len;
     WCHAR device_path[MAX_PATH];
     HANDLE file, async_file;
-    OBJECT_ATTRIBUTES attr;
-    UNICODE_STRING string;
-    IO_STATUS_BLOCK io;
-    NTSTATUS status;
     BOOL ret;
 
     winetest_push_context( "id %ld%s", report_id, polled ? " poll" : "" );
 
-    swprintf( device_path, MAX_PATH, L"\\\\?\\hid#winetest#" );
+    swprintf( device_path, MAX_PATH, L"\\\\?\\hid#vid_%04x&pid_%04x", vid, pid );
     ret = find_hid_device_path( device_path );
     ok( ret, "Failed to find HID device matching %s\n", debugstr_w( device_path ) );
 
@@ -2612,12 +2633,6 @@ static void test_hid_device( DWORD report_id, DWORD polled, const HIDP_CAPS *exp
     CloseHandle( async_file );
     CloseHandle( file );
 
-    RtlInitUnicodeString( &string, L"\\??\\root#winetest#0#{deadbeef-29ef-4538-a5fd-b69573a362c0}" );
-    InitializeObjectAttributes( &attr, &string, OBJ_CASE_INSENSITIVE, NULL, NULL );
-    status = NtOpenFile( &file, SYNCHRONIZE, &attr, &io, 0, FILE_SYNCHRONOUS_IO_NONALERT );
-    todo_wine
-    ok( status == STATUS_UNSUCCESSFUL, "got %#lx\n", status );
-
     winetest_pop_context();
 }
 
@@ -2869,13 +2884,6 @@ static void test_hid_driver( DWORD report_id, DWORD polled )
 #undef REPORT_ID_OR_USAGE_PAGE
 #include "pop_hid_macros.h"
 
-    static const HID_DEVICE_ATTRIBUTES attributes =
-    {
-        .Size = sizeof(HID_DEVICE_ATTRIBUTES),
-        .VendorID = 0x1209,
-        .ProductID = 0x0001,
-        .VersionNumber = 0x0100,
-    };
     const HIDP_CAPS caps =
     {
         .Usage = HID_USAGE_GENERIC_JOYSTICK,
@@ -2899,49 +2907,22 @@ static void test_hid_driver( DWORD report_id, DWORD polled )
         .ret_length = 3,
         .ret_status = STATUS_SUCCESS,
     };
+    struct hid_device_desc desc =
+    {
+        .is_polled = polled,
+        .use_report_id = report_id,
+        .caps = caps,
+        .attributes = default_attributes,
+    };
 
-    WCHAR cwd[MAX_PATH], tempdir[MAX_PATH];
-    char context[64];
-    LSTATUS status;
-    HKEY hkey;
+    desc.report_descriptor_len = sizeof(report_desc);
+    memcpy( desc.report_descriptor_buf, report_desc, sizeof(report_desc) );
+    desc.input_size = polled ? sizeof(expect_in) : 0;
+    memcpy( desc.input, &expect_in, sizeof(expect_in) );
+    fill_context( __LINE__, desc.context, ARRAY_SIZE(desc.context) );
 
-    GetCurrentDirectoryW( ARRAY_SIZE(cwd), cwd );
-    GetTempPathW( ARRAY_SIZE(tempdir), tempdir );
-    SetCurrentDirectoryW( tempdir );
-
-    status = RegCreateKeyExW( HKEY_LOCAL_MACHINE, L"System\\CurrentControlSet\\Services\\winetest",
-                              0, NULL, REG_OPTION_VOLATILE, KEY_ALL_ACCESS, NULL, &hkey, NULL );
-    ok( !status, "RegCreateKeyExW returned %#lx\n", status );
-
-    status = RegSetValueExW( hkey, L"ReportID", 0, REG_DWORD, (void *)&report_id, sizeof(report_id) );
-    ok( !status, "RegSetValueExW returned %#lx\n", status );
-
-    status = RegSetValueExW( hkey, L"PolledMode", 0, REG_DWORD, (void *)&polled, sizeof(polled) );
-    ok( !status, "RegSetValueExW returned %#lx\n", status );
-
-    status = RegSetValueExW( hkey, L"Descriptor", 0, REG_BINARY, (void *)report_desc, sizeof(report_desc) );
-    ok( !status, "RegSetValueExW returned %#lx\n", status );
-
-    status = RegSetValueExW( hkey, L"Attributes", 0, REG_BINARY, (void *)&attributes, sizeof(attributes) );
-    ok( !status, "RegSetValueExW returned %#lx\n", status );
-
-    status = RegSetValueExW( hkey, L"Caps", 0, REG_BINARY, (void *)&caps, sizeof(caps) );
-    ok( !status, "RegSetValueExW returned %#lx\n", status );
-
-    status = RegSetValueExW( hkey, L"Expect", 0, REG_BINARY, NULL, 0 );
-    ok( !status, "RegSetValueExW returned %#lx\n", status );
-
-    status = RegSetValueExW( hkey, L"Input", 0, REG_BINARY, (void *)&expect_in, polled ? sizeof(expect_in) : 0 );
-    ok( !status, "RegSetValueExW returned %#lx\n", status );
-
-    fill_context( __LINE__, context, ARRAY_SIZE(context) );
-    status = RegSetValueExW( hkey, L"Context", 0, REG_BINARY, (void *)context, sizeof(context) );
-    ok( !status, "RegSetValueExW returned %#lx\n", status );
-
-    if (hid_device_start()) test_hid_device( report_id, polled, &caps );
-    hid_device_stop();
-
-    SetCurrentDirectoryW( cwd );
+    if (hid_device_start( &desc )) test_hid_device( report_id, polled, &caps, desc.attributes.VendorID, desc.attributes.ProductID );
+    hid_device_stop( &desc );
 }
 
 /* undocumented HID internal preparsed data structure */
@@ -3111,18 +3092,10 @@ static void test_hidp_kdr(void)
     };
 #include "pop_hid_macros.h"
 
-    static const HIDP_CAPS expect_hidp_caps =
+    struct hid_device_desc desc =
     {
-        .Usage = HID_USAGE_GENERIC_JOYSTICK,
-        .UsagePage = HID_USAGE_PAGE_GENERIC,
-        .InputReportByteLength = 15,
-    };
-    static const HID_DEVICE_ATTRIBUTES attributes =
-    {
-        .Size = sizeof(HID_DEVICE_ATTRIBUTES),
-        .VendorID = 0x1209,
-        .ProductID = 0x0001,
-        .VersionNumber = 0x0100,
+        .caps = { .InputReportByteLength = 15 },
+        .attributes = default_attributes,
     };
     static const struct hidp_kdr expect_kdr =
     {
@@ -3250,53 +3223,21 @@ static void test_hidp_kdr(void)
         },
     };
 
-    WCHAR cwd[MAX_PATH], tempdir[MAX_PATH];
     PHIDP_PREPARSED_DATA preparsed_data;
-    DWORD i, report_id = 0, polled = 0;
     WCHAR device_path[MAX_PATH];
     struct hidp_kdr *kdr;
-    char context[64];
-    LSTATUS status;
     HANDLE file;
-    HKEY hkey;
     BOOL ret;
+    DWORD i;
 
-    GetCurrentDirectoryW( ARRAY_SIZE(cwd), cwd );
-    GetTempPathW( ARRAY_SIZE(tempdir), tempdir );
-    SetCurrentDirectoryW( tempdir );
+    desc.report_descriptor_len = sizeof(report_desc);
+    memcpy( desc.report_descriptor_buf, report_desc, sizeof(report_desc) );
+    fill_context( __LINE__, desc.context, ARRAY_SIZE(desc.context) );
 
-    status = RegCreateKeyExW( HKEY_LOCAL_MACHINE, L"System\\CurrentControlSet\\Services\\winetest",
-                              0, NULL, REG_OPTION_VOLATILE, KEY_ALL_ACCESS, NULL, &hkey, NULL );
-    ok( !status, "RegCreateKeyExW returned %#lx\n", status );
+    if (!hid_device_start( &desc )) goto done;
 
-    status = RegSetValueExW( hkey, L"ReportID", 0, REG_DWORD, (void *)&report_id, sizeof(report_id) );
-    ok( !status, "RegSetValueExW returned %#lx\n", status );
-
-    status = RegSetValueExW( hkey, L"PolledMode", 0, REG_DWORD, (void *)&polled, sizeof(polled) );
-    ok( !status, "RegSetValueExW returned %#lx\n", status );
-
-    status = RegSetValueExW( hkey, L"Descriptor", 0, REG_BINARY, (void *)report_desc, sizeof(report_desc) );
-    ok( !status, "RegSetValueExW returned %#lx\n", status );
-
-    status = RegSetValueExW( hkey, L"Attributes", 0, REG_BINARY, (void *)&attributes, sizeof(attributes) );
-    ok( !status, "RegSetValueExW returned %#lx\n", status );
-
-    status = RegSetValueExW( hkey, L"Caps", 0, REG_BINARY, (void *)&expect_hidp_caps, sizeof(expect_hidp_caps) );
-    ok( !status, "RegSetValueExW returned %#lx\n", status );
-
-    status = RegSetValueExW( hkey, L"Expect", 0, REG_BINARY, NULL, 0 );
-    ok( !status, "RegSetValueExW returned %#lx\n", status );
-
-    status = RegSetValueExW( hkey, L"Input", 0, REG_BINARY, NULL, 0 );
-    ok( !status, "RegSetValueExW returned %#lx\n", status );
-
-    fill_context( __LINE__, context, ARRAY_SIZE(context) );
-    status = RegSetValueExW( hkey, L"Context", 0, REG_BINARY, (void *)context, sizeof(context) );
-    ok( !status, "RegSetValueExW returned %#lx\n", status );
-
-    if (!hid_device_start()) goto done;
-
-    swprintf( device_path, MAX_PATH, L"\\\\?\\hid#winetest#" );
+    swprintf( device_path, MAX_PATH, L"\\\\?\\hid#vid_%04x&pid_%04x", desc.attributes.VendorID,
+              desc.attributes.ProductID );
     ret = find_hid_device_path( device_path );
     ok( ret, "Failed to find HID device matching %s\n", debugstr_w( device_path ) );
 
@@ -3397,8 +3338,7 @@ static void test_hidp_kdr(void)
     CloseHandle( file );
 
 done:
-    hid_device_stop();
-    SetCurrentDirectoryW( cwd );
+    hid_device_stop( &desc );
 }
 
 void cleanup_registry_keys(void)
@@ -3434,46 +3374,6 @@ void cleanup_registry_keys(void)
     RegCloseKey( root_key );
 }
 
-BOOL dinput_driver_start_( const char *file, int line, const BYTE *desc_buf, ULONG desc_len,
-                           const HIDP_CAPS *caps, struct hid_expect *expect, ULONG expect_size )
-{
-    static const HID_DEVICE_ATTRIBUTES attributes =
-    {
-        .Size = sizeof(HID_DEVICE_ATTRIBUTES),
-        .VendorID = LOWORD( EXPECT_VIDPID ),
-        .ProductID = HIWORD( EXPECT_VIDPID ),
-        .VersionNumber = 0x0100,
-    };
-    DWORD report_id = 1;
-    DWORD polled = 0;
-    char context[64];
-    LSTATUS status;
-    HKEY hkey;
-
-    status = RegCreateKeyExW( HKEY_LOCAL_MACHINE, L"System\\CurrentControlSet\\Services\\winetest",
-                              0, NULL, REG_OPTION_VOLATILE, KEY_ALL_ACCESS, NULL, &hkey, NULL );
-    ok_(file, line)( !status, "RegCreateKeyExW returned %#lx\n", status );
-    status = RegSetValueExW( hkey, L"ReportID", 0, REG_DWORD, (void *)&report_id, sizeof(report_id) );
-    ok_(file, line)( !status, "RegSetValueExW returned %#lx\n", status );
-    status = RegSetValueExW( hkey, L"PolledMode", 0, REG_DWORD, (void *)&polled, sizeof(polled) );
-    ok_(file, line)( !status, "RegSetValueExW returned %#lx\n", status );
-    status = RegSetValueExW( hkey, L"Descriptor", 0, REG_BINARY, (void *)desc_buf, desc_len );
-    ok_(file, line)( !status, "RegSetValueExW returned %#lx\n", status );
-    status = RegSetValueExW( hkey, L"Attributes", 0, REG_BINARY, (void *)&attributes, sizeof(attributes) );
-    ok_(file, line)( !status, "RegSetValueExW returned %#lx\n", status );
-    status = RegSetValueExW( hkey, L"Caps", 0, REG_BINARY, (void *)caps, sizeof(*caps) );
-    ok_(file, line)( !status, "RegSetValueExW returned %#lx\n", status );
-    status = RegSetValueExW( hkey, L"Expect", 0, REG_BINARY, (void *)expect, expect_size );
-    ok_(file, line)( !status, "RegSetValueExW returned %#lx\n", status );
-    status = RegSetValueExW( hkey, L"Input", 0, REG_BINARY, NULL, 0 );
-    ok_(file, line)( !status, "RegSetValueExW returned %#lx\n", status );
-    fill_context( line, context, ARRAY_SIZE(context) );
-    status = RegSetValueExW( hkey, L"Context", 0, REG_BINARY, (void *)context, sizeof(context) );
-    ok_(file, line)( !status, "RegSetValueExW returned %#lx\n", status );
-
-    return hid_device_start();
-}
-
 static LRESULT CALLBACK monitor_wndproc( HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam )
 {
     if (msg == WM_DEVICECHANGE)
@@ -3708,43 +3608,20 @@ DWORD WINAPI dinput_test_device_thread( void *stop_event )
     {
         .InputReportByteLength = 3,
     };
+    struct hid_device_desc desc =
+    {
+        .use_report_id = TRUE,
+        .caps = caps,
+        .attributes = attributes,
+    };
 
-    WCHAR cwd[MAX_PATH], tempdir[MAX_PATH];
-    DWORD report_id = 1, polled = 0;
-    char context[64];
-    LSTATUS status;
-    HKEY hkey;
+    desc.report_descriptor_len = sizeof(gamepad_desc);
+    memcpy( desc.report_descriptor_buf, gamepad_desc, sizeof(gamepad_desc) );
+    fill_context( __LINE__, desc.context, ARRAY_SIZE(desc.context) );
 
-    GetCurrentDirectoryW( ARRAY_SIZE(cwd), cwd );
-    GetTempPathW( ARRAY_SIZE(tempdir), tempdir );
-    SetCurrentDirectoryW( tempdir );
-
-    status = RegCreateKeyExW( HKEY_LOCAL_MACHINE, L"System\\CurrentControlSet\\Services\\winetest",
-                              0, NULL, REG_OPTION_VOLATILE, KEY_ALL_ACCESS, NULL, &hkey, NULL );
-    ok( !status, "RegCreateKeyExW returned %#lx\n", status );
-    status = RegSetValueExW( hkey, L"ReportID", 0, REG_DWORD, (void *)&report_id, sizeof(report_id) );
-    ok( !status, "RegSetValueExW returned %#lx\n", status );
-    status = RegSetValueExW( hkey, L"PolledMode", 0, REG_DWORD, (void *)&polled, sizeof(polled) );
-    ok( !status, "RegSetValueExW returned %#lx\n", status );
-    status = RegSetValueExW( hkey, L"Descriptor", 0, REG_BINARY, (void *)gamepad_desc, sizeof(gamepad_desc) );
-    ok( !status, "RegSetValueExW returned %#lx\n", status );
-    status = RegSetValueExW( hkey, L"Attributes", 0, REG_BINARY, (void *)&attributes, sizeof(attributes) );
-    ok( !status, "RegSetValueExW returned %#lx\n", status );
-    status = RegSetValueExW( hkey, L"Caps", 0, REG_BINARY, (void *)&caps, sizeof(caps) );
-    ok( !status, "RegSetValueExW returned %#lx\n", status );
-    status = RegSetValueExW( hkey, L"Expect", 0, REG_BINARY, NULL, 0 );
-    ok( !status, "RegSetValueExW returned %#lx\n", status );
-    status = RegSetValueExW( hkey, L"Input", 0, REG_BINARY, NULL, 0 );
-    ok( !status, "RegSetValueExW returned %#lx\n", status );
-    fill_context( __LINE__, context, ARRAY_SIZE(context) );
-    status = RegSetValueExW( hkey, L"Context", 0, REG_BINARY, (void *)context, sizeof(context) );
-    ok( !status, "RegSetValueExW returned %#lx\n", status );
-
-    hid_device_start();
+    hid_device_start( &desc );
     WaitForSingleObject( stop_event, INFINITE );
-    hid_device_stop();
-
-    SetCurrentDirectoryW( cwd );
+    hid_device_stop( &desc );
 
     return 0;
 }
@@ -3781,7 +3658,7 @@ static void test_bus_driver(void)
         .NumberInputValueCaps = 1,
         .NumberInputDataIndices = 1,
     };
-    struct bus_device_desc desc = { .caps = caps, .attributes = attributes, };
+    struct hid_device_desc desc = { .caps = caps, .attributes = attributes, };
 
     WCHAR device_path[MAX_PATH];
     HANDLE control;
@@ -3837,11 +3714,15 @@ START_TEST( hid )
     if (!dinput_test_init()) return;
 
     test_bus_driver();
+
+    if (!bus_device_start()) goto done;
     test_hidp_kdr();
     test_hid_driver( 0, FALSE );
     test_hid_driver( 1, FALSE );
     test_hid_driver( 0, TRUE );
     test_hid_driver( 1, TRUE );
 
+done:
+    bus_device_stop();
     dinput_test_exit();
 }
diff --git a/dlls/dinput/tests/hotplug.c b/dlls/dinput/tests/hotplug.c
index e212f874be3..2d000317c9f 100644
--- a/dlls/dinput/tests/hotplug.c
+++ b/dlls/dinput/tests/hotplug.c
@@ -48,6 +48,7 @@
 #define WIDL_using_Windows_Gaming_Input
 #define WIDL_using_Windows_Gaming_Input_Custom
 #include "windows.gaming.input.custom.h"
+#undef Size
 
 #define MAKE_FUNC(f) static typeof(f) *p ## f
 MAKE_FUNC( RoGetActivationFactory );
@@ -134,9 +135,11 @@ static BOOL test_input_lost( DWORD version )
     };
 #include "pop_hid_macros.h"
 
-    static const HIDP_CAPS hid_caps =
+    struct hid_device_desc desc =
     {
-        .InputReportByteLength = 1,
+        .use_report_id = TRUE,
+        .caps = { .InputReportByteLength = 1 },
+        .attributes = default_attributes,
     };
     static const DIPROPDWORD buffer_size =
     {
@@ -152,7 +155,6 @@ static BOOL test_input_lost( DWORD version )
 
     DIDEVICEINSTANCEW devinst = {.dwSize = sizeof(DIDEVICEINSTANCEW)};
     DIDEVICEOBJECTDATA objdata[32] = {{0}};
-    WCHAR cwd[MAX_PATH], tempdir[MAX_PATH];
     IDirectInputDevice8W *device = NULL;
     ULONG ref, count, size;
     DIJOYSTATE2 state;
@@ -160,12 +162,13 @@ static BOOL test_input_lost( DWORD version )
 
     winetest_push_context( "%#lx", version );
 
-    GetCurrentDirectoryW( ARRAY_SIZE(cwd), cwd );
-    GetTempPathW( ARRAY_SIZE(tempdir), tempdir );
-    SetCurrentDirectoryW( tempdir );
-
     cleanup_registry_keys();
-    if (!dinput_driver_start( report_desc, sizeof(report_desc), &hid_caps, NULL, 0 )) goto done;
+
+    desc.report_descriptor_len = sizeof(report_desc);
+    memcpy( desc.report_descriptor_buf, report_desc, sizeof(report_desc) );
+    fill_context( __LINE__, desc.context, ARRAY_SIZE(desc.context) );
+
+    if (!hid_device_start( &desc )) goto done;
     if (FAILED(hr = dinput_test_create_device( version, &devinst, &device ))) goto done;
 
     hr = IDirectInputDevice8_SetDataFormat( device, &c_dfDIJoystick2 );
@@ -185,7 +188,7 @@ static BOOL test_input_lost( DWORD version )
     ok( hr == DI_OK, "GetDeviceData returned %#lx\n", hr );
     ok( count == 0, "got %lu expected 0\n", count );
 
-    hid_device_stop();
+    hid_device_stop( &desc );
 
     hr = IDirectInputDevice8_GetDeviceState( device, sizeof(state), &state );
     ok( hr == DIERR_INPUTLOST, "GetDeviceState returned %#lx\n", hr );
@@ -205,22 +208,20 @@ static BOOL test_input_lost( DWORD version )
     hr = IDirectInputDevice8_Unacquire( device );
     ok( hr == DI_NOEFFECT, "Unacquire returned: %#lx\n", hr );
 
-    dinput_driver_start( report_desc, sizeof(report_desc), &hid_caps, NULL, 0 );
+    fill_context( __LINE__, desc.context, ARRAY_SIZE(desc.context) );
+    hid_device_start( &desc );
 
     hr = IDirectInputDevice8_Acquire( device );
-    todo_wine
-    ok( hr == DIERR_UNPLUGGED, "Acquire returned %#lx\n", hr );
+    ok( hr == S_OK, "Acquire returned %#lx\n", hr );
     hr = IDirectInputDevice8_GetDeviceState( device, sizeof(state), &state );
-    todo_wine
-    ok( hr == DIERR_NOTACQUIRED, "GetDeviceState returned %#lx\n", hr );
+    ok( hr == S_OK, "GetDeviceState returned %#lx\n", hr );
 
     ref = IDirectInputDevice8_Release( device );
     ok( ref == 0, "Release returned %ld\n", ref );
 
 done:
-    hid_device_stop();
+    hid_device_stop( &desc );
     cleanup_registry_keys();
-    SetCurrentDirectoryW( cwd );
 
     winetest_pop_context();
     return device != NULL;
@@ -255,7 +256,7 @@ static LRESULT CALLBACK devnotify_wndproc( HWND hwnd, UINT msg, WPARAM wparam, L
         if (device_change_all && (device_change_count == 0 || device_change_count == 3))
         {
             expect_guid = control_class;
-            expect_prefix = L"\\\\?\\ROOT#";
+            expect_prefix = L"\\\\?\\WINETEST#";
         }
         else
         {
@@ -1218,6 +1219,7 @@ next:
 START_TEST( hotplug )
 {
     if (!dinput_test_init()) return;
+    if (!bus_device_start()) goto done;
 
     CoInitialize( NULL );
     if (test_input_lost( 0x500 ))
@@ -1230,5 +1232,7 @@ START_TEST( hotplug )
     }
     CoUninitialize();
 
+done:
+    bus_device_stop();
     dinput_test_exit();
 }
diff --git a/dlls/dinput/tests/joystick8.c b/dlls/dinput/tests/joystick8.c
index ca7cc9a1a32..597846d9f57 100644
--- a/dlls/dinput/tests/joystick8.c
+++ b/dlls/dinput/tests/joystick8.c
@@ -45,6 +45,7 @@
 #define WIDL_using_Windows_Devices_Haptics
 #define WIDL_using_Windows_Gaming_Input
 #include "windows.gaming.input.h"
+#undef Size
 
 #define MAKE_FUNC(f) static typeof(f) *p ## f
 MAKE_FUNC( RoGetActivationFactory );
@@ -398,9 +399,11 @@ static void test_simple_joystick( DWORD version )
 #undef REPORT_ID_OR_USAGE_PAGE
 #include "pop_hid_macros.h"
 
-    static const HIDP_CAPS hid_caps =
+    struct hid_device_desc desc =
     {
-        .InputReportByteLength = 9,
+        .use_report_id = TRUE,
+        .caps = { .InputReportByteLength = 9 },
+        .attributes = default_attributes,
     };
     const DIDEVCAPS expect_caps =
     {
@@ -494,8 +497,8 @@ static void test_simple_joystick( DWORD version )
         .guidProduct = expect_guid_product,
         .dwDevType = version >= 0x800 ? DIDEVTYPE_HID | (DI8DEVTYPEJOYSTICK_LIMITED << 8) | DI8DEVTYPE_JOYSTICK
                                       : DIDEVTYPE_HID | (DIDEVTYPEJOYSTICK_RUDDER << 8) | DIDEVTYPE_JOYSTICK,
-        .tszInstanceName = L"Wine test root driver",
-        .tszProductName = L"Wine test root driver",
+        .tszInstanceName = L"Wine Test",
+        .tszProductName = L"Wine Test",
         .guidFFDriver = GUID_NULL,
         .wUsagePage = HID_USAGE_PAGE_GENERIC,
         .wUsage = HID_USAGE_GENERIC_JOYSTICK,
@@ -775,7 +778,6 @@ static void test_simple_joystick( DWORD version )
         },
     };
     DIOBJECTDATAFORMAT objdataformat[32] = {{0}};
-    WCHAR cwd[MAX_PATH], tempdir[MAX_PATH];
     DIDEVICEOBJECTDATA objdata[32] = {{0}};
     DIDEVICEOBJECTINSTANCEW objinst = {0};
     DIDEVICEOBJECTINSTANCEW expect_obj;
@@ -791,18 +793,18 @@ static void test_simple_joystick( DWORD version )
     char buffer[1024];
     DIJOYSTATE2 state;
     HRESULT hr;
-    WCHAR *tmp;
     GUID guid;
     HWND hwnd;
 
     winetest_push_context( "%#lx", version );
 
-    GetCurrentDirectoryW( ARRAY_SIZE(cwd), cwd );
-    GetTempPathW( ARRAY_SIZE(tempdir), tempdir );
-    SetCurrentDirectoryW( tempdir );
-
     cleanup_registry_keys();
-    if (!dinput_driver_start( report_desc, sizeof(report_desc), &hid_caps, NULL, 0 )) goto done;
+
+    desc.report_descriptor_len = sizeof(report_desc);
+    memcpy( desc.report_descriptor_buf, report_desc, sizeof(report_desc) );
+    fill_context( __LINE__, desc.context, ARRAY_SIZE(desc.context) );
+
+    if (!hid_device_start( &desc )) goto done;
     if (FAILED(hr = dinput_test_create_device( version, &devinst, &device ))) goto done;
 
     check_dinput_devices( version, &devinst );
@@ -854,9 +856,7 @@ static void test_simple_joystick( DWORD version )
     check_member_guid( devinst, expect_devinst, guidProduct );
     todo_wine_if( version < 0x0800 )
     check_member( devinst, expect_devinst, "%#lx", dwDevType );
-    todo_wine
     check_member_wstr( devinst, expect_devinst, tszInstanceName );
-    todo_wine
     check_member_wstr( devinst, expect_devinst, tszProductName );
 
     memset( &devinst, 0, sizeof(devinst) );
@@ -869,9 +869,7 @@ static void test_simple_joystick( DWORD version )
     check_member_guid( devinst, expect_devinst, guidProduct );
     todo_wine_if( version < 0x0800 )
     check_member( devinst, expect_devinst, "%#lx", dwDevType );
-    todo_wine
     check_member_wstr( devinst, expect_devinst, tszInstanceName );
-    todo_wine
     check_member_wstr( devinst, expect_devinst, tszProductName );
     check_member_guid( devinst, expect_devinst, guidFFDriver );
     check_member( devinst, expect_devinst, "%04x", wUsagePage );
@@ -928,22 +926,16 @@ static void test_simple_joystick( DWORD version )
     todo_wine
     ok( !wcsncmp( prop_guid_path.wszPath, expect_path, wcslen( expect_path ) ), "got path %s\n",
         debugstr_w(prop_guid_path.wszPath) );
-    if (!(tmp = wcsrchr( prop_guid_path.wszPath, '&' )))
-        todo_wine ok( 0, "got path %s\n", debugstr_w(prop_guid_path.wszPath) );
-    else
-    {
-        ok( !wcscmp( wcsrchr( prop_guid_path.wszPath, '&' ), expect_path_end ), "got path %s\n",
-            debugstr_w(prop_guid_path.wszPath) );
-    }
+    todo_wine
+    ok( !wcscmp( wcsrchr( prop_guid_path.wszPath, '&' ), expect_path_end ), "got path %s\n",
+        debugstr_w(prop_guid_path.wszPath) );
 
     hr = IDirectInputDevice8_GetProperty( device, DIPROP_INSTANCENAME, &prop_string.diph );
     ok( hr == DI_OK, "GetProperty DIPROP_INSTANCENAME returned %#lx\n", hr );
-    todo_wine
     ok( !wcscmp( prop_string.wsz, expect_devinst.tszInstanceName ), "got instance %s\n",
         debugstr_w(prop_string.wsz) );
     hr = IDirectInputDevice8_GetProperty( device, DIPROP_PRODUCTNAME, &prop_string.diph );
     ok( hr == DI_OK, "GetProperty DIPROP_PRODUCTNAME returned %#lx\n", hr );
-    todo_wine
     ok( !wcscmp( prop_string.wsz, expect_devinst.tszProductName ), "got product %s\n",
         debugstr_w(prop_string.wsz) );
     hr = IDirectInputDevice8_GetProperty( device, DIPROP_TYPENAME, &prop_string.diph );
@@ -1730,7 +1722,6 @@ static void test_simple_joystick( DWORD version )
     ok( hr == DI_OK, "SetProperty DIPROP_PRODUCTNAME returned %#lx\n", hr );
     hr = IDirectInputDevice8_GetProperty( device, DIPROP_PRODUCTNAME, &prop_string.diph );
     ok( hr == DI_OK, "GetProperty DIPROP_PRODUCTNAME returned %#lx\n", hr );
-    todo_wine
     ok( !wcscmp( prop_string.wsz, expect_devinst.tszProductName ), "got product %s\n",
         debugstr_w(prop_string.wsz) );
 
@@ -2084,9 +2075,8 @@ static void test_simple_joystick( DWORD version )
     CloseHandle( file );
 
 done:
-    hid_device_stop();
+    hid_device_stop( &desc );
     cleanup_registry_keys();
-    SetCurrentDirectoryW( cwd );
     winetest_pop_context();
 }
 
@@ -2473,8 +2463,8 @@ static BOOL test_device_types( DWORD version )
             .guidProduct = expect_guid_product,
             .dwDevType = version >= 0x800 ? DIDEVTYPE_HID|(DI8DEVTYPESUPPLEMENTAL_UNKNOWN << 8)|DI8DEVTYPE_SUPPLEMENTAL
                                           : DIDEVTYPE_HID|(DIDEVTYPEJOYSTICK_UNKNOWN << 8)|DIDEVTYPE_JOYSTICK,
-            .tszInstanceName = L"Wine test root driver",
-            .tszProductName = L"Wine test root driver",
+            .tszInstanceName = L"Wine Test",
+            .tszProductName = L"Wine Test",
             .guidFFDriver = GUID_NULL,
             .wUsagePage = HID_USAGE_PAGE_GENERIC,
             .wUsage = HID_USAGE_GENERIC_JOYSTICK,
@@ -2485,8 +2475,8 @@ static BOOL test_device_types( DWORD version )
             .guidProduct = expect_guid_product,
             .dwDevType = version >= 0x800 ? DIDEVTYPE_HID|(DI8DEVTYPEJOYSTICK_LIMITED << 8)|DI8DEVTYPE_JOYSTICK
                                           : DIDEVTYPE_HID|(DIDEVTYPEJOYSTICK_UNKNOWN << 8)|DIDEVTYPE_JOYSTICK,
-            .tszInstanceName = L"Wine test root driver",
-            .tszProductName = L"Wine test root driver",
+            .tszInstanceName = L"Wine Test",
+            .tszProductName = L"Wine Test",
             .guidFFDriver = GUID_NULL,
             .wUsagePage = HID_USAGE_PAGE_GENERIC,
             .wUsage = HID_USAGE_GENERIC_JOYSTICK,
@@ -2497,8 +2487,8 @@ static BOOL test_device_types( DWORD version )
             .guidProduct = expect_guid_product,
             .dwDevType = version >= 0x800 ? DIDEVTYPE_HID|(DI8DEVTYPEGAMEPAD_STANDARD << 8)|DI8DEVTYPE_GAMEPAD
                                           : DIDEVTYPE_HID|(DIDEVTYPEJOYSTICK_GAMEPAD << 8)|DIDEVTYPE_JOYSTICK,
-            .tszInstanceName = L"Wine test root driver",
-            .tszProductName = L"Wine test root driver",
+            .tszInstanceName = L"Wine Test",
+            .tszProductName = L"Wine Test",
             .guidFFDriver = GUID_NULL,
             .wUsagePage = HID_USAGE_PAGE_GENERIC,
             .wUsage = HID_USAGE_GENERIC_GAMEPAD,
@@ -2509,8 +2499,8 @@ static BOOL test_device_types( DWORD version )
             .guidProduct = expect_guid_product,
             .dwDevType = version >= 0x800 ? DIDEVTYPE_HID|(DI8DEVTYPEJOYSTICK_STANDARD << 8)|DI8DEVTYPE_JOYSTICK
                                           : DIDEVTYPE_HID|(DIDEVTYPEJOYSTICK_UNKNOWN << 8)|DIDEVTYPE_JOYSTICK,
-            .tszInstanceName = L"Wine test root driver",
-            .tszProductName = L"Wine test root driver",
+            .tszInstanceName = L"Wine Test",
+            .tszProductName = L"Wine Test",
             .guidFFDriver = GUID_NULL,
             .wUsagePage = HID_USAGE_PAGE_GENERIC,
             .wUsage = HID_USAGE_GENERIC_JOYSTICK,
@@ -2521,8 +2511,8 @@ static BOOL test_device_types( DWORD version )
             .guidProduct = expect_guid_product,
             .dwDevType = version >= 0x800 ? DIDEVTYPE_HID|(DI8DEVTYPEDRIVING_LIMITED << 8)|DI8DEVTYPE_DRIVING
                                           : DIDEVTYPE_HID|(DIDEVTYPEJOYSTICK_WHEEL << 8)|DIDEVTYPE_JOYSTICK,
-            .tszInstanceName = L"Wine test root driver",
-            .tszProductName = L"Wine test root driver",
+            .tszInstanceName = L"Wine Test",
+            .tszProductName = L"Wine Test",
             .guidFFDriver = GUID_NULL,
             .wUsagePage = HID_USAGE_PAGE_GENERIC,
             .wUsage = HID_USAGE_GENERIC_JOYSTICK,
@@ -2533,8 +2523,8 @@ static BOOL test_device_types( DWORD version )
             .guidProduct = expect_guid_product,
             .dwDevType = version >= 0x800 ? DIDEVTYPE_HID|(DI8DEVTYPEDRIVING_DUALPEDALS << 8)|DI8DEVTYPE_DRIVING
                                           : DIDEVTYPE_HID|(DIDEVTYPEJOYSTICK_WHEEL << 8)|DIDEVTYPE_JOYSTICK,
-            .tszInstanceName = L"Wine test root driver",
-            .tszProductName = L"Wine test root driver",
+            .tszInstanceName = L"Wine Test",
+            .tszProductName = L"Wine Test",
             .guidFFDriver = GUID_NULL,
             .wUsagePage = HID_USAGE_PAGE_GENERIC,
             .wUsage = HID_USAGE_GENERIC_JOYSTICK,
@@ -2545,20 +2535,24 @@ static BOOL test_device_types( DWORD version )
             .guidProduct = expect_guid_product,
             .dwDevType = version >= 0x800 ? DIDEVTYPE_HID|(DI8DEVTYPEDRIVING_THREEPEDALS << 8)|DI8DEVTYPE_DRIVING
                                           : DIDEVTYPE_HID|(DIDEVTYPEJOYSTICK_WHEEL << 8)|DIDEVTYPE_JOYSTICK,
-            .tszInstanceName = L"Wine test root driver",
-            .tszProductName = L"Wine test root driver",
+            .tszInstanceName = L"Wine Test",
+            .tszProductName = L"Wine Test",
             .guidFFDriver = GUID_NULL,
             .wUsagePage = HID_USAGE_PAGE_GENERIC,
             .wUsage = HID_USAGE_GENERIC_JOYSTICK,
         },
     };
+    struct hid_device_desc desc =
+    {
+        .use_report_id = TRUE,
+        .attributes = default_attributes,
+    };
 
     C_ASSERT(ARRAY_SIZE(expect_caps) == ARRAY_SIZE(device_desc));
     C_ASSERT(ARRAY_SIZE(expect_devinst) == ARRAY_SIZE(device_desc));
 
     DIDEVICEINSTANCEW devinst = {.dwSize = sizeof(DIDEVICEINSTANCEW)};
     DIDEVCAPS caps = {.dwSize = sizeof(DIDEVCAPS)};
-    WCHAR cwd[MAX_PATH], tempdir[MAX_PATH];
     IDirectInputDevice8W *device;
     BOOL success = TRUE;
     ULONG i, ref;
@@ -2569,13 +2563,14 @@ static BOOL test_device_types( DWORD version )
     for (i = 0; i < ARRAY_SIZE(device_desc) && success; ++i)
     {
         winetest_push_context( "desc[%ld]", i );
-        GetCurrentDirectoryW( ARRAY_SIZE(cwd), cwd );
-        GetTempPathW( ARRAY_SIZE(tempdir), tempdir );
-        SetCurrentDirectoryW( tempdir );
-
         cleanup_registry_keys();
-        if (!dinput_driver_start( device_desc[i].report_desc_buf, device_desc[i].report_desc_len,
-                                  &device_desc[i].hid_caps, NULL, 0 ))
+
+        desc.caps = device_desc[i].hid_caps;
+        desc.report_descriptor_len = device_desc[i].report_desc_len;
+        memcpy( desc.report_descriptor_buf, device_desc[i].report_desc_buf, device_desc[i].report_desc_len );
+        fill_context( __LINE__, desc.context, ARRAY_SIZE(desc.context) );
+
+        if (!hid_device_start( &desc ))
         {
             success = FALSE;
             goto done;
@@ -2616,9 +2611,8 @@ static BOOL test_device_types( DWORD version )
         ok( ref == 0, "Release returned %ld\n", ref );
 
     done:
-        hid_device_stop();
+        hid_device_stop( &desc );
         cleanup_registry_keys();
-        SetCurrentDirectoryW( cwd );
         winetest_pop_context();
     }
 
@@ -2659,9 +2653,11 @@ static void test_driving_wheel_axes(void)
 #undef REPORT_ID_OR_USAGE_PAGE
 #include "pop_hid_macros.h"
 
-    static const HIDP_CAPS hid_caps =
+    struct hid_device_desc desc =
     {
-        .InputReportByteLength = 7,
+        .use_report_id = TRUE,
+        .caps = { .InputReportByteLength = 7 },
+        .attributes = default_attributes,
     };
     const DIDEVCAPS expect_caps =
     {
@@ -2676,8 +2672,8 @@ static void test_driving_wheel_axes(void)
         .guidInstance = expect_guid_product,
         .guidProduct = expect_guid_product,
         .dwDevType = DIDEVTYPE_HID | (DI8DEVTYPEDRIVING_LIMITED << 8) | DI8DEVTYPE_DRIVING,
-        .tszInstanceName = L"Wine test root driver",
-        .tszProductName = L"Wine test root driver",
+        .tszInstanceName = L"Wine Test",
+        .tszProductName = L"Wine Test",
         .guidFFDriver = GUID_NULL,
         .wUsagePage = HID_USAGE_PAGE_GENERIC,
         .wUsage = HID_USAGE_GENERIC_JOYSTICK,
@@ -2780,19 +2776,19 @@ static void test_driving_wheel_axes(void)
         .expect_objs = expect_objects,
     };
 
-    WCHAR cwd[MAX_PATH], tempdir[MAX_PATH];
     DIDEVICEINSTANCEW devinst = {0};
     IDirectInputDevice8W *device;
     DIDEVCAPS caps = {0};
     HRESULT hr;
     ULONG ref;
 
-    GetCurrentDirectoryW( ARRAY_SIZE(cwd), cwd );
-    GetTempPathW( ARRAY_SIZE(tempdir), tempdir );
-    SetCurrentDirectoryW( tempdir );
-
     cleanup_registry_keys();
-    if (!dinput_driver_start( report_desc, sizeof(report_desc), &hid_caps, NULL, 0 )) goto done;
+
+    desc.report_descriptor_len = sizeof(report_desc);
+    memcpy( desc.report_descriptor_buf, report_desc, sizeof(report_desc) );
+    fill_context( __LINE__, desc.context, ARRAY_SIZE(desc.context) );
+
+    if (!hid_device_start( &desc )) goto done;
     if (FAILED(hr = dinput_test_create_device( DIRECTINPUT_VERSION, &devinst, &device ))) goto done;
 
     check_dinput_devices( DIRECTINPUT_VERSION, &devinst );
@@ -2806,9 +2802,7 @@ static void test_driving_wheel_axes(void)
     check_member_guid( devinst, expect_devinst, guidInstance );
     check_member_guid( devinst, expect_devinst, guidProduct );
     check_member( devinst, expect_devinst, "%#lx", dwDevType );
-    todo_wine
     check_member_wstr( devinst, expect_devinst, tszInstanceName );
-    todo_wine
     check_member_wstr( devinst, expect_devinst, tszProductName );
     check_member_guid( devinst, expect_devinst, guidFFDriver );
     check_member( devinst, expect_devinst, "%04x", wUsagePage );
@@ -2842,9 +2836,8 @@ static void test_driving_wheel_axes(void)
     ok( ref == 0, "Release returned %ld\n", ref );
 
 done:
-    hid_device_stop();
+    hid_device_stop( &desc );
     cleanup_registry_keys();
-    SetCurrentDirectoryW( cwd );
     winetest_pop_context();
 }
 
@@ -2899,9 +2892,11 @@ static BOOL test_winmm_joystick(void)
     };
 #include "pop_hid_macros.h"
 
-    static const HIDP_CAPS hid_caps =
+    struct hid_device_desc desc =
     {
-        .InputReportByteLength = 18,
+        .use_report_id = TRUE,
+        .caps = { .InputReportByteLength = 18 },
+        .attributes = default_attributes,
     };
     static const JOYCAPS2W expect_regcaps =
     {
@@ -2976,7 +2971,6 @@ static BOOL test_winmm_joystick(void)
             .dwHow = DIPH_DEVICE,
         },
     };
-    WCHAR cwd[MAX_PATH], tempdir[MAX_PATH];
     IDirectInputDevice8W *device = NULL;
     DIDEVICEINSTANCEW devinst = {0};
     JOYCAPS2W caps = {0};
@@ -2985,10 +2979,6 @@ static BOOL test_winmm_joystick(void)
     HRESULT hr;
     UINT ret;
 
-    GetCurrentDirectoryW( ARRAY_SIZE(cwd), cwd );
-    GetTempPathW( ARRAY_SIZE(tempdir), tempdir );
-    SetCurrentDirectoryW( tempdir );
-
     cleanup_registry_keys();
 
     ret = joyGetNumDevs();
@@ -3028,7 +3018,11 @@ static BOOL test_winmm_joystick(void)
     check_member_guid( caps, expect_regcaps, ProductGuid );
     check_member_guid( caps, expect_regcaps, NameGuid );
 
-    if (!dinput_driver_start( report_desc, sizeof(report_desc), &hid_caps, NULL, 0 )) goto done;
+    desc.report_descriptor_len = sizeof(report_desc);
+    memcpy( desc.report_descriptor_buf, report_desc, sizeof(report_desc) );
+    fill_context( __LINE__, desc.context, ARRAY_SIZE(desc.context) );
+
+    if (!hid_device_start( &desc )) goto done;
 
     ret = joyGetNumDevs();
     ok( ret == 16, "joyGetNumDevs returned %u\n", ret );
@@ -3200,9 +3194,8 @@ static BOOL test_winmm_joystick(void)
     CloseHandle( file );
 
 done:
-    hid_device_stop();
+    hid_device_stop( &desc );
     cleanup_registry_keys();
-    SetCurrentDirectoryW( cwd );
 
     return device != NULL;
 }
@@ -3235,6 +3228,68 @@ static void check_runtimeclass_( int line, IInspectable *inspectable, const WCHA
     pWindowsDeleteString( str );
 }
 
+struct controller_handler
+{
+    IEventHandler_RawGameController IEventHandler_RawGameController_iface;
+    HANDLE event;
+    BOOL invoked;
+};
+
+static inline struct controller_handler *impl_from_IEventHandler_RawGameController( IEventHandler_RawGameController *iface )
+{
+    return CONTAINING_RECORD( iface, struct controller_handler, IEventHandler_RawGameController_iface );
+}
+
+static HRESULT WINAPI controller_handler_QueryInterface( IEventHandler_RawGameController *iface, REFIID iid, void **out )
+{
+    if (IsEqualGUID( iid, &IID_IUnknown ) ||
+        IsEqualGUID( iid, &IID_IAgileObject ) ||
+        IsEqualGUID( iid, &IID_IEventHandler_RawGameController ))
+    {
+        IUnknown_AddRef( iface );
+        *out = iface;
+        return S_OK;
+    }
+
+    trace( "%s not implemented, returning E_NOINTERFACE.\n", debugstr_guid( iid ) );
+    *out = NULL;
+    return E_NOINTERFACE;
+}
+
+static ULONG WINAPI controller_handler_AddRef( IEventHandler_RawGameController *iface )
+{
+    return 2;
+}
+
+static ULONG WINAPI controller_handler_Release( IEventHandler_RawGameController *iface )
+{
+    return 1;
+}
+
+static HRESULT WINAPI controller_handler_Invoke( IEventHandler_RawGameController *iface,
+                                                 IInspectable *sender, IRawGameController *controller )
+{
+    struct controller_handler *impl = impl_from_IEventHandler_RawGameController( iface );
+
+    trace( "iface %p, sender %p, controller %p\n", iface, sender, controller );
+
+    ok( sender == NULL, "got sender %p\n", sender );
+    SetEvent( impl->event );
+    impl->invoked = TRUE;
+
+    return S_OK;
+}
+
+static const IEventHandler_RawGameControllerVtbl controller_handler_vtbl =
+{
+    controller_handler_QueryInterface,
+    controller_handler_AddRef,
+    controller_handler_Release,
+    controller_handler_Invoke,
+};
+
+static struct controller_handler controller_added = {{&controller_handler_vtbl}};
+
 static void test_windows_gaming_input(void)
 {
 #include "psh_hid_macros.h"
@@ -3282,9 +3337,11 @@ static void test_windows_gaming_input(void)
     };
 #include "pop_hid_macros.h"
 
-    static const HIDP_CAPS hid_caps =
+    struct hid_device_desc desc =
     {
-        .InputReportByteLength = 8,
+        .use_report_id = TRUE,
+        .caps = { .InputReportByteLength = 8 },
+        .attributes = default_attributes,
     };
     static const WCHAR *controller_class_name = RuntimeClass_Windows_Gaming_Input_RawGameController;
     static const WCHAR *gamepad_class_name = RuntimeClass_Windows_Gaming_Input_Gamepad;
@@ -3292,7 +3349,7 @@ static void test_windows_gaming_input(void)
     IRawGameController *raw_controller, *tmp_raw_controller;
     IVectorView_RawGameController *controllers_view;
     IRawGameControllerStatics *controller_statics;
-    WCHAR cwd[MAX_PATH], tempdir[MAX_PATH];
+    EventRegistrationToken controller_added_token;
     IVectorView_Gamepad *gamepads_view;
     IGamepadStatics *gamepad_statics;
     IGameController *game_controller;
@@ -3302,10 +3359,6 @@ static void test_windows_gaming_input(void)
 
     if (!load_combase_functions()) return;
 
-    GetCurrentDirectoryW( ARRAY_SIZE(cwd), cwd );
-    GetTempPathW( ARRAY_SIZE(tempdir), tempdir );
-    SetCurrentDirectoryW( tempdir );
-
     cleanup_registry_keys();
 
     hr = pRoInitialize( RO_INIT_MULTITHREADED );
@@ -3329,7 +3382,21 @@ static void test_windows_gaming_input(void)
     ok( hr == S_OK, "get_Size returned %#lx\n", hr );
     ok( size == 0, "got size %u\n", size );
 
-    if (!dinput_driver_start( report_desc, sizeof(report_desc), &hid_caps, NULL, 0 )) goto done;
+    controller_added.event = CreateEventW( NULL, FALSE, FALSE, NULL );
+    ok( !!controller_added.event, "CreateEventW failed, error %lu\n", GetLastError() );
+
+    hr = IRawGameControllerStatics_add_RawGameControllerAdded( controller_statics, &controller_added.IEventHandler_RawGameController_iface,
+                                                               &controller_added_token );
+    ok( hr == S_OK, "add_RawGameControllerAdded returned %#lx\n", hr );
+    ok( controller_added_token.value, "got token %I64u\n", controller_added_token.value );
+
+    desc.report_descriptor_len = sizeof(report_desc);
+    memcpy( desc.report_descriptor_buf, report_desc, sizeof(report_desc) );
+    fill_context( __LINE__, desc.context, ARRAY_SIZE(desc.context) );
+
+    if (!hid_device_start( &desc )) goto done;
+    WaitForSingleObject( controller_added.event, INFINITE );
+    CloseHandle( controller_added.event );
 
     hr = IVectorView_RawGameController_get_Size( controllers_view, &size );
     ok( hr == S_OK, "get_Size returned %#lx\n", hr );
@@ -3392,17 +3459,20 @@ static void test_windows_gaming_input(void)
     IGameController_Release( game_controller );
     IRawGameController_Release( raw_controller );
 
+    hr = IRawGameControllerStatics_remove_RawGameControllerAdded( controller_statics, controller_added_token );
+    ok( hr == S_OK, "remove_RawGameControllerAdded returned %#lx\n", hr );
+
     IRawGameControllerStatics_Release( controller_statics );
 
 done:
-    hid_device_stop();
+    hid_device_stop( &desc );
     cleanup_registry_keys();
-    SetCurrentDirectoryW( cwd );
 }
 
 START_TEST( joystick8 )
 {
     if (!dinput_test_init()) return;
+    if (!bus_device_start()) goto done;
 
     CoInitialize( NULL );
     if (test_device_types( 0x800 ))
@@ -3423,5 +3493,7 @@ START_TEST( joystick8 )
     }
     CoUninitialize();
 
+done:
+    bus_device_stop();
     dinput_test_exit();
 }
-- 
2.35.1




More information about the wine-devel mailing list