dinput/tests: Create all HID devices from the Bus driver.

Signed-off-by: Rémi Bernon <rbernon@codeweavers.com>
Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
Rémi Bernon 2022-03-22 11:41:40 +01:00 committed by Alexandre Julliard
parent 2a52c8dcd2
commit 2644f63617
7 changed files with 318 additions and 349 deletions

View File

@ -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 ) \

View File

@ -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;
@ -1252,7 +1253,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:
@ -1263,7 +1264,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" );

View File

@ -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;

View File

@ -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 );
@ -2999,9 +2998,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;
@ -3424,9 +3422,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[] =
{
@ -3892,23 +3892,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 );
@ -4255,10 +4256,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;
@ -4279,11 +4280,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;
@ -4317,15 +4318,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 ))
@ -4336,5 +4337,7 @@ START_TEST( force_feedback )
}
CoUninitialize();
done:
bus_device_stop();
dinput_test_exit();
}

View File

@ -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();
}

View File

@ -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();
}

View File

@ -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();
}