-- v2: dinput: Rewrite IDirectInput8_EnumDevicesBySemantics. dinput: Implement DIDBAM_PRESERVE BuildActionMap flag. dinput: Check device type in BuildActionMap for specific semantics. dinput: Load action map from registry before resetting guid. dinput: Trace formats in (Build|Set)ActionMap and EnumDevicesBySemantics. dinput/tests: Add more IDirectInput8_EnumDevicesBySemantics tests. dinput/tests: Test BuildActionMap cases with multiple devices.
From: Rémi Bernon rbernon@codeweavers.com
--- dlls/dinput/tests/joystick8.c | 207 ++++++++++++++++++++++++++++++++-- 1 file changed, 198 insertions(+), 9 deletions(-)
diff --git a/dlls/dinput/tests/joystick8.c b/dlls/dinput/tests/joystick8.c index a74dab6dc52..6ef752b5677 100644 --- a/dlls/dinput/tests/joystick8.c +++ b/dlls/dinput/tests/joystick8.c @@ -51,6 +51,7 @@
DEFINE_GUID(GUID_action_mapping_1,0x00000001,0x0002,0x0003,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b); DEFINE_GUID(GUID_action_mapping_2,0x00010001,0x0002,0x0003,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b); +DEFINE_GUID(GUID_map_other_device,0x00020001,0x0002,0x0003,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b);
static HRESULT (WINAPI *pRoGetActivationFactory)( HSTRING, REFIID, void** ); static HRESULT (WINAPI *pRoInitialize)( RO_INIT_TYPE ); @@ -208,8 +209,8 @@ static BOOL CALLBACK check_no_created_effect_objects( IDirectInputEffect *effect return DIENUM_CONTINUE; }
-#define check_diactionw( a, b ) check_diactionw_( __LINE__, a, b ) -static void check_diactionw_( int line, const DIACTIONW *actual, const DIACTIONW *expected ) +#define check_diactionw( a, b ) check_diactionw_( __LINE__, a, b, FALSE ) +static void check_diactionw_( int line, const DIACTIONW *actual, const DIACTIONW *expected, BOOL todo ) { check_member_( __FILE__, line, *actual, *expected, "%#Ix", uAppData ); check_member_( __FILE__, line, *actual, *expected, "%#lx", dwSemantic ); @@ -218,13 +219,15 @@ static void check_diactionw_( int line, const DIACTIONW *actual, const DIACTIONW check_member_wstr_( __FILE__, line, *actual, *expected, lptszActionName ); else check_member_( __FILE__, line, *actual, *expected, "%p", lptszActionName ); + todo_wine_if( todo ) check_member_guid_( __FILE__, line, *actual, *expected, guidInstance ); check_member_( __FILE__, line, *actual, *expected, "%#lx", dwObjID ); + todo_wine_if( todo ) check_member_( __FILE__, line, *actual, *expected, "%#lx", dwHow ); }
-#define check_diactionformatw( a, b ) check_diactionformatw_( __LINE__, a, b ) -static void check_diactionformatw_( int line, const DIACTIONFORMATW *actual, const DIACTIONFORMATW *expected ) +#define check_diactionformatw( a, b ) check_diactionformatw_( __LINE__, a, b, FALSE ) +static void check_diactionformatw_( int line, const DIACTIONFORMATW *actual, const DIACTIONFORMATW *expected, BOOL todo ) { DWORD i; check_member_( __FILE__, line, *actual, *expected, "%#lx", dwSize ); @@ -234,7 +237,7 @@ static void check_diactionformatw_( int line, const DIACTIONFORMATW *actual, con for (i = 0; i < min( actual->dwNumActions, expected->dwNumActions ); ++i) { winetest_push_context( "action[%lu]", i ); - check_diactionw_( line, actual->rgoAction + i, expected->rgoAction + i ); + check_diactionw_( line, actual->rgoAction + i, expected->rgoAction + i, todo && i >= 2 ); winetest_pop_context(); if (expected->dwActionSize != sizeof(DIACTIONW)) break; if (actual->dwActionSize != sizeof(DIACTIONW)) break; @@ -451,6 +454,68 @@ static void test_action_map( IDirectInputDevice8W *device, HANDLE file, HANDLE e .dwHow = DIAH_DEFAULT, .dwObjID = DIDFT_ABSAXIS | DIDFT_MAKEINSTANCE( 0 ), }, + { + .dwSemantic = DIAXIS_ANY_Y_1, + .guidInstance = expect_guid_product, + .dwHow = DIAH_DEFAULT, + .dwObjID = DIDFT_ABSAXIS | DIDFT_MAKEINSTANCE( 1 ), + }, + { + .dwSemantic = DIMOUSE_WHEEL, + }, + { + .dwSemantic = 0x81000410, + }, + }; + const DIACTIONW expect_actions_3[] = + { + { + .dwSemantic = DIAXIS_DRIVINGR_STEER, + .guidInstance = expect_guid_product, + .dwHow = DIAH_DEFAULT, + .dwObjID = DIDFT_ABSAXIS | DIDFT_MAKEINSTANCE( 0 ), + }, + { + .dwSemantic = DIAXIS_ANY_Y_1, + .guidInstance = expect_guid_product, + .dwHow = DIAH_DEFAULT, + .dwObjID = DIDFT_ABSAXIS | DIDFT_MAKEINSTANCE( 1 ), + }, + { + .dwSemantic = DIMOUSE_WHEEL, + .dwObjID = DIDFT_RELAXIS | DIDFT_MAKEINSTANCE( 2 ), + }, + { + .dwSemantic = 0x81000410, + .dwObjID = DIDFT_PSHBUTTON | DIDFT_MAKEINSTANCE( 0x10 ), + }, + }; + const DIACTIONW expect_actions_4[] = + { + { + .dwSemantic = DIAXIS_DRIVINGR_STEER, + .guidInstance = expect_guid_product, + .dwHow = DIAH_DEFAULT, + .dwObjID = DIDFT_ABSAXIS | DIDFT_MAKEINSTANCE( 0 ), + }, + { + .dwSemantic = DIAXIS_ANY_Y_1, + .guidInstance = expect_guid_product, + .dwHow = DIAH_DEFAULT, + .dwObjID = DIDFT_ABSAXIS | DIDFT_MAKEINSTANCE( 1 ), + }, + { + .dwSemantic = DIMOUSE_WHEEL, + .guidInstance = GUID_SysMouse, + .dwObjID = DIDFT_RELAXIS | DIDFT_MAKEINSTANCE( 2 ), + .dwHow = DIAH_DEFAULT, + }, + { + .dwSemantic = 0x81000410, + .guidInstance = GUID_SysKeyboard, + .dwObjID = DIDFT_PSHBUTTON | DIDFT_MAKEINSTANCE( 0x10 ), + .dwHow = DIAH_DEFAULT, + }, }; const DIACTIONW expect_filled_actions[ARRAY_SIZE(expect_actions)] = { @@ -520,6 +585,25 @@ static void test_action_map( IDirectInputDevice8W *device, HANDLE file, HANDLE e .lptszActionName = L"Steer", .uAppData = 8, }, + { + .dwSemantic = DIAXIS_ANY_Y_1, + .guidInstance = expect_guid_product, + .dwHow = DIAH_DEFAULT, + .dwObjID = DIDFT_ABSAXIS | DIDFT_MAKEINSTANCE( 1 ), + .lptszActionName = L"Y Axis", + .uAppData = 9, + }, + { + .dwSemantic = DIMOUSE_WHEEL, + .lptszActionName = L"Wheel", + .uAppData = 10, + }, + { + .dwSemantic = 0x81000410, + .lptszActionName = L"Key", + .dwFlags = DIA_APPFIXED, + .uAppData = 11, + }, }; const DIACTIONFORMATW expect_action_format_1 = { @@ -541,7 +625,29 @@ static void test_action_map( IDirectInputDevice8W *device, HANDLE file, HANDLE e .rgoAction = (DIACTIONW *)expect_actions, .dwGenre = DIVIRTUAL_DRIVING_RACE, .guidActionMap = GUID_action_mapping_2, - .dwCRC = 0x9a7bb5e6, + .dwCRC = 0x6981e1f7, + }; + const DIACTIONFORMATW expect_action_format_3 = + { + .dwSize = sizeof(DIACTIONFORMATW), + .dwActionSize = sizeof(DIACTIONW), + .dwNumActions = ARRAY_SIZE(expect_actions_3), + .dwDataSize = 4 * ARRAY_SIZE(expect_actions_3), + .rgoAction = (DIACTIONW *)expect_actions_3, + .dwGenre = DIVIRTUAL_DRIVING_RACE, + .guidActionMap = GUID_action_mapping_2, + .dwCRC = 0xf8748d65, + }; + const DIACTIONFORMATW expect_action_format_4 = + { + .dwSize = sizeof(DIACTIONFORMATW), + .dwActionSize = sizeof(DIACTIONW), + .dwNumActions = ARRAY_SIZE(expect_actions_4), + .dwDataSize = 4 * ARRAY_SIZE(expect_actions_4), + .rgoAction = (DIACTIONW *)expect_actions_4, + .dwGenre = DIVIRTUAL_DRIVING_RACE, + .guidActionMap = GUID_action_mapping_2, + .dwCRC = 0xf8748d65, }; const DIACTIONFORMATW expect_action_format_2_filled = { @@ -556,7 +662,7 @@ static void test_action_map( IDirectInputDevice8W *device, HANDLE file, HANDLE e .lAxisMin = -128, .lAxisMax = +128, .tszActionMap = L"Action Map Filled", - .dwCRC = 0x3d98f717, + .dwCRC = 0x5ebf86a6, }; struct hid_expect injected_input[] = { @@ -594,14 +700,17 @@ static void test_action_map( IDirectInputDevice8W *device, HANDLE file, HANDLE e { 0, 0, 0, -1, 0, 0, 0, -43}, {+128, 0, 0, -1, 0, 0, 0, -128}, }; - const DIDEVICEOBJECTDATA expect_objdata[8] = + const DIDEVICEOBJECTDATA expect_objdata[11] = { + {.dwOfs = 0x20, .dwData = +128, .uAppData = 9}, {.dwOfs = 0x1c, .dwData = +128, .uAppData = 8}, {.dwOfs = 0xc, .dwData = +31500, .uAppData = 4}, {.dwOfs = 0, .dwData = +128, .uAppData = 1}, + {.dwOfs = 0x20, .dwData = -67, .uAppData = 9}, {.dwOfs = 0x1c, .dwData = -43, .uAppData = 8}, {.dwOfs = 0xc, .dwData = -1, .uAppData = 4}, {.dwOfs = 0, .dwData = 0, .uAppData = 1}, + {.dwOfs = 0x20, .dwData = -128, .uAppData = 9}, {.dwOfs = 0x1c, .dwData = -128, .uAppData = 8}, {.dwOfs = 0, .dwData = +128, .uAppData = 1}, }; @@ -629,6 +738,9 @@ static void test_action_map( IDirectInputDevice8W *device, HANDLE file, HANDLE e {.dwSemantic = DIAXIS_ANY_Z_2}, {.dwSemantic = DIAXIS_ANY_4}, {.dwSemantic = DIAXIS_DRIVINGR_STEER}, + {.dwSemantic = DIAXIS_ANY_Y_1}, + {.dwSemantic = DIMOUSE_WHEEL}, + {.dwSemantic = 0x81000410}, }; DIACTIONFORMATW action_format_1 = { @@ -650,6 +762,16 @@ static void test_action_map( IDirectInputDevice8W *device, HANDLE file, HANDLE e .dwGenre = DIVIRTUAL_DRIVING_RACE, .guidActionMap = GUID_action_mapping_2, }; + DIACTIONFORMATW action_format_3 = + { + .dwSize = sizeof(DIACTIONFORMATW), + .dwActionSize = sizeof(*default_actions), + .dwNumActions = ARRAY_SIZE(expect_actions_3), + .dwDataSize = 4 * ARRAY_SIZE(expect_actions_3), + .rgoAction = default_actions, + .dwGenre = DIVIRTUAL_DRIVING_RACE, + .guidActionMap = GUID_action_mapping_2, + }; DIACTIONW filled_actions[ARRAY_SIZE(expect_actions)] = { { @@ -722,6 +844,26 @@ static void test_action_map( IDirectInputDevice8W *device, HANDLE file, HANDLE e .lptszActionName = L"Steer", .uAppData = 8, }, + { + .dwSemantic = DIAXIS_ANY_Y_1, + .guidInstance = expect_guid_product, + .dwObjID = DIDFT_ABSAXIS | DIDFT_MAKEINSTANCE( 1 ), + .lptszActionName = L"Y Axis", + .uAppData = 9, + }, + { + .dwSemantic = DIMOUSE_WHEEL, + .guidInstance = expect_guid_product, + .lptszActionName = L"Wheel", + .uAppData = 10, + }, + { + .dwSemantic = 0x81000410, + .guidInstance = expect_guid_product, + .lptszActionName = L"Key", + .dwFlags = DIA_APPFIXED, + .uAppData = 11, + }, }; DIACTIONFORMATW action_format_2_filled = { @@ -775,7 +917,9 @@ static void test_action_map( IDirectInputDevice8W *device, HANDLE file, HANDLE e DIDEVICEOBJECTDATA objdata[ARRAY_SIZE(expect_objdata)]; DIACTIONW actions[ARRAY_SIZE(expect_actions)]; DWORD state[ARRAY_SIZE(expect_actions)]; + IDirectInputDevice8W *mouse, *keyboard; DIACTIONFORMATW action_format; + IDirectInput8W *dinput; WCHAR username[256]; DWORD i, res, flags; HRESULT hr; @@ -901,6 +1045,13 @@ static void test_action_map( IDirectInputDevice8W *device, HANDLE file, HANDLE e ok( hr == DI_OK, "BuildActionMap returned %#lx\n", hr ); check_diactionformatw( &action_format, &expect_action_format_2 );
+ action_format = action_format_2; + action_format.rgoAction = actions; + memcpy( actions, default_actions, sizeof(default_actions) ); + hr = IDirectInputDevice8_BuildActionMap( device, &action_format, L"username", DIDBAM_PRESERVE ); + ok( hr == DI_OK, "BuildActionMap returned %#lx\n", hr ); + check_diactionformatw( &action_format, &expect_action_format_2 ); + hr = IDirectInputDevice8_SetActionMap( device, &action_format, L"username", DIDSAM_DEFAULT ); ok( hr == DI_OK, "SetActionMap returned %#lx\n", hr );
@@ -1054,7 +1205,7 @@ static void test_action_map( IDirectInputDevice8W *device, HANDLE file, HANDLE e hr = IDirectInputDevice8_GetDeviceData( device, sizeof(*objdata), objdata, &res, DIGDD_PEEK ); todo_wine ok( hr == DI_BUFFEROVERFLOW, "GetDeviceData returned %#lx\n", hr ); - ok( res == 8, "got %lu expected %u\n", res, 8 ); + ok( res == ARRAY_SIZE(objdata), "got %lu expected %u\n", res, 8 ); while (res--) { winetest_push_context( "%lu", res ); @@ -1123,6 +1274,44 @@ static void test_action_map( IDirectInputDevice8W *device, HANDLE file, HANDLE e hr = IDirectInputDevice_GetProperty( device, DIPROP_USERNAME, &prop_username.diph ); ok( hr == DI_NOEFFECT, "GetProperty returned %#lx\n", hr ); ok( !wcscmp( prop_username.wsz, L"" ), "got username %s\n", debugstr_w(prop_username.wsz) ); + + + /* test BuildActionMap with multiple devices */ + + hr = DirectInput8Create( instance, 0x800, &IID_IDirectInput8W, (void **)&dinput, NULL ); + ok( hr == DI_OK, "DirectInput8Create returned %#lx\n", hr ); + + hr = IDirectInput8_CreateDevice( dinput, &GUID_SysMouse, &mouse, NULL ); + ok( hr == DI_OK, "DirectInput8Create returned %#lx\n", hr ); + hr = IDirectInput8_CreateDevice( dinput, &GUID_SysKeyboard, &keyboard, NULL ); + ok( hr == DI_OK, "DirectInput8Create returned %#lx\n", hr ); + + action_format = action_format_3; + action_format.rgoAction = actions; + memcpy( actions, default_actions + 7, sizeof(expect_actions_3) ); + hr = IDirectInputDevice8_BuildActionMap( mouse, &action_format, L"username", DIDBAM_DEFAULT ); + ok( hr == DI_OK, "BuildActionMap returned %#lx\n", hr ); + hr = IDirectInputDevice8_BuildActionMap( keyboard, &action_format, L"username", DIDBAM_DEFAULT ); + ok( hr == DI_OK, "BuildActionMap returned %#lx\n", hr ); + hr = IDirectInputDevice8_BuildActionMap( device, &action_format, L"username", DIDBAM_DEFAULT ); + ok( hr == DI_OK, "BuildActionMap returned %#lx\n", hr ); + check_diactionformatw( &action_format, &expect_action_format_3 ); + + action_format = action_format_3; + action_format.rgoAction = actions; + memcpy( actions, default_actions + 7, sizeof(expect_actions_4) ); + hr = IDirectInputDevice8_BuildActionMap( mouse, &action_format, L"username", DIDBAM_PRESERVE ); + ok( hr == DI_OK, "BuildActionMap returned %#lx\n", hr ); + hr = IDirectInputDevice8_BuildActionMap( keyboard, &action_format, L"username", DIDBAM_PRESERVE ); + ok( hr == DI_OK, "BuildActionMap returned %#lx\n", hr ); + hr = IDirectInputDevice8_BuildActionMap( device, &action_format, L"username", DIDBAM_PRESERVE ); + ok( hr == DI_OK, "BuildActionMap returned %#lx\n", hr ); + check_diactionformatw_( __LINE__, &action_format, &expect_action_format_4, TRUE ); + + IDirectInputDevice8_Release( keyboard ); + IDirectInputDevice8_Release( mouse ); + + IDirectInput8_Release( dinput ); }
static void test_simple_joystick( DWORD version )
From: Rémi Bernon rbernon@codeweavers.com
--- dlls/dinput/tests/joystick8.c | 92 ++++++++++++++++++++++++++++++++++- 1 file changed, 91 insertions(+), 1 deletion(-)
diff --git a/dlls/dinput/tests/joystick8.c b/dlls/dinput/tests/joystick8.c index 6ef752b5677..4f4b9b0d5f0 100644 --- a/dlls/dinput/tests/joystick8.c +++ b/dlls/dinput/tests/joystick8.c @@ -408,6 +408,76 @@ static void check_dinput_devices( DWORD version, DIDEVICEINSTANCEW *devinst ) } }
+static BOOL CALLBACK enum_devices_by_semantic( const DIDEVICEINSTANCEW *instance, IDirectInputDevice8W *device, + DWORD flags, DWORD remaining, void *context ) +{ + const DIDEVICEINSTANCEW expect_joystick = + { + .dwSize = sizeof(DIDEVICEINSTANCEW), + .guidInstance = expect_guid_product, + .guidProduct = expect_guid_product, + .dwDevType = DIDEVTYPE_HID | (DI8DEVTYPEJOYSTICK_LIMITED << 8) | DI8DEVTYPE_JOYSTICK, + .tszInstanceName = L"Wine Test", + .tszProductName = L"Wine Test", + .wUsagePage = HID_USAGE_PAGE_GENERIC, + .wUsage = HID_USAGE_GENERIC_JOYSTICK, + }; + const DIDEVICEINSTANCEW expect_keyboard = + { + .dwSize = sizeof(DIDEVICEINSTANCEW), + .guidInstance = GUID_SysKeyboard, + .guidProduct = GUID_SysKeyboard, + .dwDevType = (DI8DEVTYPEKEYBOARD_PCENH << 8) | DI8DEVTYPE_KEYBOARD, + .tszInstanceName = L"Keyboard", + .tszProductName = L"Keyboard", + }; + const DIDEVICEINSTANCEW expect_mouse = + { + .dwSize = sizeof(DIDEVICEINSTANCEW), + .guidInstance = GUID_SysMouse, + .guidProduct = GUID_SysMouse, + .dwDevType = (DI8DEVTYPEMOUSE_UNKNOWN << 8) | DI8DEVTYPE_MOUSE, + .tszInstanceName = L"Mouse", + .tszProductName = L"Mouse", + }; + const DIDEVICEINSTANCEW *expect_instance = NULL; + + ok( remaining <= 2, "got remaining %lu\n", remaining ); + + if (remaining == 2) + { + expect_instance = &expect_joystick; + todo_wine ok( flags == (context ? 3 : 0), "got flags %#lx\n", flags ); + } + else if (remaining == 1) + { + expect_instance = &expect_keyboard; + ok( flags == 1, "got flags %#lx\n", flags ); + } + else if (remaining == 0) + { + expect_instance = &expect_mouse; + ok( flags == 1, "got flags %#lx\n", flags ); + } + + check_member( *instance, *expect_instance, "%#lx", dwSize ); + if (expect_instance != &expect_joystick) check_member_guid( *instance, *expect_instance, guidInstance ); + check_member_guid( *instance, *expect_instance, guidProduct ); + todo_wine_if( expect_instance == &expect_mouse ) + check_member( *instance, *expect_instance, "%#lx", dwDevType ); + if (!localized) + { + check_member_wstr( *instance, *expect_instance, tszInstanceName ); + todo_wine_if( expect_instance != &expect_joystick ) + check_member_wstr( *instance, *expect_instance, tszProductName ); + } + check_member_guid( *instance, *expect_instance, guidFFDriver ); + check_member( *instance, *expect_instance, "%#x", wUsagePage ); + check_member( *instance, *expect_instance, "%#x", wUsage ); + + return DIENUM_CONTINUE; +} + static void test_action_map( IDirectInputDevice8W *device, HANDLE file, HANDLE event ) { const DIACTIONW expect_actions[] = @@ -1276,7 +1346,7 @@ static void test_action_map( IDirectInputDevice8W *device, HANDLE file, HANDLE e ok( !wcscmp( prop_username.wsz, L"" ), "got username %s\n", debugstr_w(prop_username.wsz) );
- /* test BuildActionMap with multiple devices */ + /* test BuildActionMap with multiple devices and EnumDevicesBySemantics */
hr = DirectInput8Create( instance, 0x800, &IID_IDirectInput8W, (void **)&dinput, NULL ); ok( hr == DI_OK, "DirectInput8Create returned %#lx\n", hr ); @@ -1311,6 +1381,26 @@ static void test_action_map( IDirectInputDevice8W *device, HANDLE file, HANDLE e IDirectInputDevice8_Release( keyboard ); IDirectInputDevice8_Release( mouse );
+ action_format = action_format_2; + action_format.rgoAction = actions; + memcpy( actions, default_actions, sizeof(default_actions) ); + hr = IDirectInput8_EnumDevicesBySemantics( dinput, NULL, &action_format, enum_devices_by_semantic, (void *)0xdeadbeef, 0 ); + ok( hr == DI_OK, "EnumDevicesBySemantics returned %#lx\n", hr ); + + action_format = action_format_3; + action_format.rgoAction = actions; + memcpy( actions, default_actions + 7, sizeof(expect_actions_4) ); + hr = IDirectInput8_EnumDevicesBySemantics( dinput, NULL, &action_format, enum_devices_by_semantic, (void *)0xdeadbeef, 0 ); + ok( hr == DI_OK, "EnumDevicesBySemantics returned %#lx\n", hr ); + + action_format = action_format_3; + action_format.rgoAction = actions; + memcpy( actions, default_actions + 9, 2 * sizeof(DIACTIONW) ); + action_format.dwNumActions = 2; + action_format.dwDataSize = 8; + hr = IDirectInput8_EnumDevicesBySemantics( dinput, NULL, &action_format, enum_devices_by_semantic, NULL, 0 ); + ok( hr == DI_OK, "EnumDevicesBySemantics returned %#lx\n", hr ); + IDirectInput8_Release( dinput ); }
From: Rémi Bernon rbernon@codeweavers.com
--- dlls/dinput/device.c | 24 ++++++++++++++++++++++-- dlls/dinput/dinput.c | 12 ++++++++++++ 2 files changed, 34 insertions(+), 2 deletions(-)
diff --git a/dlls/dinput/device.c b/dlls/dinput/device.c index 41baa630989..b9f38330800 100644 --- a/dlls/dinput/device.c +++ b/dlls/dinput/device.c @@ -1815,7 +1815,7 @@ static HRESULT WINAPI dinput_device_BuildActionMap( IDirectInputDevice8W *iface, BOOL load_success = FALSE; BOOL *mapped;
- FIXME( "iface %p, format %p, username %s, flags %#lx stub!\n", iface, format, + TRACE( "iface %p, format %p, username %s, flags %#lx\n", iface, format, debugstr_w(username), flags );
if (!format) return DIERR_INVALIDPARAM; @@ -1825,6 +1825,16 @@ static HRESULT WINAPI dinput_device_BuildActionMap( IDirectInputDevice8W *iface, if (format->dwNumActions * 4 != format->dwDataSize) return DIERR_INVALIDPARAM;
+ TRACE( "format guid %s, genre %#lx, name %s\n", debugstr_guid(&format->guidActionMap), + format->dwGenre, debugstr_w(format->tszActionMap) ); + for (i = 0; i < format->dwNumActions; i++) + { + DIACTIONW *action = format->rgoAction + i; + TRACE( " %lu: app_data %#Ix, semantic %#lx, flags %#lx, instance %s, obj_id %#lx, how %#lx, name %s\n", + i, action->uAppData, action->dwSemantic, action->dwFlags, debugstr_guid(&action->guidInstance), + action->dwObjID, action->dwHow, debugstr_w(action->lptszActionName) ); + } + action_end = format->rgoAction + format->dwNumActions; for (action = format->rgoAction; action < action_end; action++) { @@ -1968,12 +1978,22 @@ static HRESULT WINAPI dinput_device_SetActionMap( IDirectInputDevice8W *iface, D int i, index; HRESULT hr;
- FIXME( "iface %p, format %p, username %s, flags %#lx stub!\n", iface, format, + TRACE( "iface %p, format %p, username %s, flags %#lx\n", iface, format, debugstr_w(username), flags );
if (!format) return DIERR_INVALIDPARAM; if (flags != DIDSAM_DEFAULT && flags != DIDSAM_FORCESAVE && flags != DIDSAM_NOUSER) return DIERR_INVALIDPARAM;
+ TRACE( "format guid %s, genre %#lx, name %s\n", debugstr_guid(&format->guidActionMap), + format->dwGenre, debugstr_w(format->tszActionMap) ); + for (i = 0; i < format->dwNumActions; i++) + { + DIACTIONW *action = format->rgoAction + i; + TRACE( " %u: app_data %#Ix, semantic %#lx, flags %#lx, instance %s, obj_id %#lx, how %#lx, name %s\n", + i, action->uAppData, action->dwSemantic, action->dwFlags, debugstr_guid(&action->guidInstance), + action->dwObjID, action->dwHow, debugstr_w(action->lptszActionName) ); + } + if (!(data_format.rgodf = malloc( sizeof(DIOBJECTDATAFORMAT) * format->dwNumActions ))) return DIERR_OUTOFMEMORY; data_format.dwDataSize = format->dwDataSize;
diff --git a/dlls/dinput/dinput.c b/dlls/dinput/dinput.c index 998573ad20d..cac47de74a4 100644 --- a/dlls/dinput/dinput.c +++ b/dlls/dinput/dinput.c @@ -519,6 +519,18 @@ static HRESULT WINAPI dinput8_EnumDevicesBySemantics( IDirectInput8W *iface, con FIXME( "iface %p, username %s, action_format %p, callback %p, context %p, flags %#lx stub!\n", iface, debugstr_w(username), action_format, callback, context, flags );
+ if (!action_format) return DIERR_INVALIDPARAM; + + TRACE( "format guid %s, genre %#lx, name %s\n", debugstr_guid(&action_format->guidActionMap), + action_format->dwGenre, debugstr_w(action_format->tszActionMap) ); + for (i = 0; i < action_format->dwNumActions; i++) + { + DIACTIONW *action = action_format->rgoAction + i; + TRACE( " %u: app_data %#Ix, semantic %#lx, flags %#lx, instance %s, obj_id %#lx, how %#lx, name %s\n", + i, action->uAppData, action->dwSemantic, action->dwFlags, debugstr_guid(&action->guidInstance), + action->dwObjID, action->dwHow, debugstr_w(action->lptszActionName) ); + } + didevi.dwSize = sizeof(didevi);
hr = IDirectInput8_EnumDevices( &impl->IDirectInput8W_iface, DI8DEVCLASS_GAMECTRL,
From: Rémi Bernon rbernon@codeweavers.com
--- dlls/dinput/device.c | 20 +++++++++++--------- 1 file changed, 11 insertions(+), 9 deletions(-)
diff --git a/dlls/dinput/device.c b/dlls/dinput/device.c index b9f38330800..8b5d5a566bf 100644 --- a/dlls/dinput/device.c +++ b/dlls/dinput/device.c @@ -1812,7 +1812,6 @@ static HRESULT WINAPI dinput_device_BuildActionMap( IDirectInputDevice8W *iface, DIACTIONW *action, *action_end; DWORD i, username_len = MAX_PATH; WCHAR username_buf[MAX_PATH]; - BOOL load_success = FALSE; BOOL *mapped;
TRACE( "iface %p, format %p, username %s, flags %#lx\n", iface, format, @@ -1840,12 +1839,7 @@ static HRESULT WINAPI dinput_device_BuildActionMap( IDirectInputDevice8W *iface, { if (!action->dwSemantic) return DIERR_INVALIDPARAM; if (action->dwFlags & DIA_APPMAPPED) action->dwHow = DIAH_APPREQUESTED; - else if (action->dwFlags & DIA_APPNOMAP) continue; - else - { - action->dwHow = 0; - action->guidInstance = GUID_NULL; - } + else action->dwHow = 0; }
/* Unless asked the contrary by these flags, try to load a previous mapping */ @@ -1854,10 +1848,18 @@ static HRESULT WINAPI dinput_device_BuildActionMap( IDirectInputDevice8W *iface, /* Retrieve logged user name if necessary */ if (username == NULL) GetUserNameW( username_buf, &username_len ); else lstrcpynW( username_buf, username, MAX_PATH ); - load_success = load_mapping_settings( impl, format, username_buf ); + load_mapping_settings( impl, format, username_buf ); + } + + action_end = format->rgoAction + format->dwNumActions; + for (action = format->rgoAction; action < action_end; action++) + { + if (action->dwHow == DIAH_APPREQUESTED || action->dwHow == DIAH_USERCONFIG) continue; + if (action->dwFlags & DIA_APPNOMAP) continue; + action->guidInstance = GUID_NULL; + action->dwHow = 0; }
- if (load_success) return DI_OK; if (!(mapped = calloc( impl->device_format.dwNumObjs, sizeof(*mapped) ))) return DIERR_OUTOFMEMORY;
action_end = format->rgoAction + format->dwNumActions;
From: Rémi Bernon rbernon@codeweavers.com
--- dlls/dinput/device.c | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-)
diff --git a/dlls/dinput/device.c b/dlls/dinput/device.c index 8b5d5a566bf..a152d552f5d 100644 --- a/dlls/dinput/device.c +++ b/dlls/dinput/device.c @@ -1785,7 +1785,8 @@ static HRESULT WINAPI dinput_device_WriteEffectToFile( IDirectInputDevice8W *ifa return DI_OK; }
-static BOOL object_matches_semantic( const DIOBJECTDATAFORMAT *object, DWORD semantic, BOOL exact ) +static BOOL object_matches_semantic( const DIDEVICEINSTANCEW *instance, const DIOBJECTDATAFORMAT *object, + DWORD semantic, BOOL exact ) { DWORD value = semantic & 0xff, axis = (semantic >> 15) & 3, type;
@@ -1799,7 +1800,15 @@ static BOOL object_matches_semantic( const DIOBJECTDATAFORMAT *object, DWORD sem }
if (!(DIDFT_GETTYPE( object->dwType ) & type)) return FALSE; - if ((semantic & 0xf0000000) == 0x80000000) return object->dwOfs == value; + if ((semantic & 0xf0000000) == 0x80000000) + { + switch (semantic & 0x0f000000) + { + case 0x01000000: return (instance->dwDevType & 0xf) == DIDEVTYPE_KEYBOARD && object->dwOfs == value; + case 0x02000000: return (instance->dwDevType & 0xf) == DIDEVTYPE_MOUSE && object->dwOfs == value; + default: return FALSE; + } + } if (axis && (axis - 1) != DIDFT_GETINSTANCE( object->dwType )) return FALSE; return !exact || !value || value == DIDFT_GETINSTANCE( object->dwType ) + 1; } @@ -1872,7 +1881,7 @@ static HRESULT WINAPI dinput_device_BuildActionMap( IDirectInputDevice8W *iface, for (object = impl->device_format.rgodf; object < object_end; object++) { if (mapped[object - impl->device_format.rgodf]) continue; - if (!object_matches_semantic( object, action->dwSemantic, TRUE )) continue; + if (!object_matches_semantic( &impl->instance, object, action->dwSemantic, TRUE )) continue; if ((action->dwFlags & DIA_FORCEFEEDBACK) && !(object->dwType & DIDFT_FFACTUATOR)) continue; action->dwObjID = object->dwType; action->guidInstance = impl->guid; @@ -1891,7 +1900,7 @@ static HRESULT WINAPI dinput_device_BuildActionMap( IDirectInputDevice8W *iface, for (object = impl->device_format.rgodf; object < object_end; object++) { if (mapped[object - impl->device_format.rgodf]) continue; - if (!object_matches_semantic( object, action->dwSemantic, FALSE )) continue; + if (!object_matches_semantic( &impl->instance, object, action->dwSemantic, FALSE )) continue; if ((action->dwFlags & DIA_FORCEFEEDBACK) && !(object->dwType & DIDFT_FFACTUATOR)) continue; action->dwObjID = object->dwType; action->guidInstance = impl->guid;
From: Rémi Bernon rbernon@codeweavers.com
--- dlls/dinput/device.c | 4 ++++ dlls/dinput/tests/joystick8.c | 14 ++++++-------- 2 files changed, 10 insertions(+), 8 deletions(-)
diff --git a/dlls/dinput/device.c b/dlls/dinput/device.c index a152d552f5d..b4b39f0595e 100644 --- a/dlls/dinput/device.c +++ b/dlls/dinput/device.c @@ -1847,6 +1847,8 @@ static HRESULT WINAPI dinput_device_BuildActionMap( IDirectInputDevice8W *iface, for (action = format->rgoAction; action < action_end; action++) { if (!action->dwSemantic) return DIERR_INVALIDPARAM; + if (flags == DIDBAM_PRESERVE && !IsEqualCLSID( &action->guidInstance, &GUID_NULL ) && + !IsEqualCLSID( &action->guidInstance, &impl->guid )) continue; if (action->dwFlags & DIA_APPMAPPED) action->dwHow = DIAH_APPREQUESTED; else action->dwHow = 0; } @@ -1864,6 +1866,8 @@ static HRESULT WINAPI dinput_device_BuildActionMap( IDirectInputDevice8W *iface, for (action = format->rgoAction; action < action_end; action++) { if (action->dwHow == DIAH_APPREQUESTED || action->dwHow == DIAH_USERCONFIG) continue; + if (flags == DIDBAM_PRESERVE && !IsEqualCLSID( &action->guidInstance, &GUID_NULL ) && + !IsEqualCLSID( &action->guidInstance, &impl->guid )) continue; if (action->dwFlags & DIA_APPNOMAP) continue; action->guidInstance = GUID_NULL; action->dwHow = 0; diff --git a/dlls/dinput/tests/joystick8.c b/dlls/dinput/tests/joystick8.c index 4f4b9b0d5f0..a7420240b68 100644 --- a/dlls/dinput/tests/joystick8.c +++ b/dlls/dinput/tests/joystick8.c @@ -209,8 +209,8 @@ static BOOL CALLBACK check_no_created_effect_objects( IDirectInputEffect *effect return DIENUM_CONTINUE; }
-#define check_diactionw( a, b ) check_diactionw_( __LINE__, a, b, FALSE ) -static void check_diactionw_( int line, const DIACTIONW *actual, const DIACTIONW *expected, BOOL todo ) +#define check_diactionw( a, b ) check_diactionw_( __LINE__, a, b ) +static void check_diactionw_( int line, const DIACTIONW *actual, const DIACTIONW *expected ) { check_member_( __FILE__, line, *actual, *expected, "%#Ix", uAppData ); check_member_( __FILE__, line, *actual, *expected, "%#lx", dwSemantic ); @@ -219,15 +219,13 @@ static void check_diactionw_( int line, const DIACTIONW *actual, const DIACTIONW check_member_wstr_( __FILE__, line, *actual, *expected, lptszActionName ); else check_member_( __FILE__, line, *actual, *expected, "%p", lptszActionName ); - todo_wine_if( todo ) check_member_guid_( __FILE__, line, *actual, *expected, guidInstance ); check_member_( __FILE__, line, *actual, *expected, "%#lx", dwObjID ); - todo_wine_if( todo ) check_member_( __FILE__, line, *actual, *expected, "%#lx", dwHow ); }
-#define check_diactionformatw( a, b ) check_diactionformatw_( __LINE__, a, b, FALSE ) -static void check_diactionformatw_( int line, const DIACTIONFORMATW *actual, const DIACTIONFORMATW *expected, BOOL todo ) +#define check_diactionformatw( a, b ) check_diactionformatw_( __LINE__, a, b ) +static void check_diactionformatw_( int line, const DIACTIONFORMATW *actual, const DIACTIONFORMATW *expected ) { DWORD i; check_member_( __FILE__, line, *actual, *expected, "%#lx", dwSize ); @@ -237,7 +235,7 @@ static void check_diactionformatw_( int line, const DIACTIONFORMATW *actual, con for (i = 0; i < min( actual->dwNumActions, expected->dwNumActions ); ++i) { winetest_push_context( "action[%lu]", i ); - check_diactionw_( line, actual->rgoAction + i, expected->rgoAction + i, todo && i >= 2 ); + check_diactionw_( line, actual->rgoAction + i, expected->rgoAction + i ); winetest_pop_context(); if (expected->dwActionSize != sizeof(DIACTIONW)) break; if (actual->dwActionSize != sizeof(DIACTIONW)) break; @@ -1376,7 +1374,7 @@ static void test_action_map( IDirectInputDevice8W *device, HANDLE file, HANDLE e ok( hr == DI_OK, "BuildActionMap returned %#lx\n", hr ); hr = IDirectInputDevice8_BuildActionMap( device, &action_format, L"username", DIDBAM_PRESERVE ); ok( hr == DI_OK, "BuildActionMap returned %#lx\n", hr ); - check_diactionformatw_( __LINE__, &action_format, &expect_action_format_4, TRUE ); + check_diactionformatw( &action_format, &expect_action_format_4 );
IDirectInputDevice8_Release( keyboard ); IDirectInputDevice8_Release( mouse );
From: Rémi Bernon rbernon@codeweavers.com
Simplifying and fixing it. --- dlls/dinput/device.c | 6 +- dlls/dinput/device_private.h | 2 + dlls/dinput/dinput.c | 198 +++++++++++++++------------------- dlls/dinput/tests/joystick8.c | 2 +- 4 files changed, 90 insertions(+), 118 deletions(-)
diff --git a/dlls/dinput/device.c b/dlls/dinput/device.c index b4b39f0595e..19c3241e51f 100644 --- a/dlls/dinput/device.c +++ b/dlls/dinput/device.c @@ -1785,7 +1785,7 @@ static HRESULT WINAPI dinput_device_WriteEffectToFile( IDirectInputDevice8W *ifa return DI_OK; }
-static BOOL object_matches_semantic( const DIDEVICEINSTANCEW *instance, const DIOBJECTDATAFORMAT *object, +BOOL device_object_matches_semantic( const DIDEVICEINSTANCEW *instance, const DIOBJECTDATAFORMAT *object, DWORD semantic, BOOL exact ) { DWORD value = semantic & 0xff, axis = (semantic >> 15) & 3, type; @@ -1885,7 +1885,7 @@ static HRESULT WINAPI dinput_device_BuildActionMap( IDirectInputDevice8W *iface, for (object = impl->device_format.rgodf; object < object_end; object++) { if (mapped[object - impl->device_format.rgodf]) continue; - if (!object_matches_semantic( &impl->instance, object, action->dwSemantic, TRUE )) continue; + if (!device_object_matches_semantic( &impl->instance, object, action->dwSemantic, TRUE )) continue; if ((action->dwFlags & DIA_FORCEFEEDBACK) && !(object->dwType & DIDFT_FFACTUATOR)) continue; action->dwObjID = object->dwType; action->guidInstance = impl->guid; @@ -1904,7 +1904,7 @@ static HRESULT WINAPI dinput_device_BuildActionMap( IDirectInputDevice8W *iface, for (object = impl->device_format.rgodf; object < object_end; object++) { if (mapped[object - impl->device_format.rgodf]) continue; - if (!object_matches_semantic( &impl->instance, object, action->dwSemantic, FALSE )) continue; + if (!device_object_matches_semantic( &impl->instance, object, action->dwSemantic, FALSE )) continue; if ((action->dwFlags & DIA_FORCEFEEDBACK) && !(object->dwType & DIDFT_FFACTUATOR)) continue; action->dwObjID = object->dwType; action->guidInstance = impl->guid; diff --git a/dlls/dinput/device_private.h b/dlls/dinput/device_private.h index 5563618ff12..13201cc7178 100644 --- a/dlls/dinput/device_private.h +++ b/dlls/dinput/device_private.h @@ -128,6 +128,8 @@ extern void dinput_device_internal_release( struct dinput_device *device );
extern HRESULT dinput_device_init_device_format( IDirectInputDevice8W *iface ); extern int dinput_device_object_index_from_id( IDirectInputDevice8W *iface, DWORD id ); +extern BOOL device_object_matches_semantic( const DIDEVICEINSTANCEW *instance, const DIOBJECTDATAFORMAT *object, + DWORD semantic, BOOL exact );
extern BOOL get_app_key(HKEY*, HKEY*) DECLSPEC_HIDDEN; extern DWORD get_config_key( HKEY, HKEY, const WCHAR *, WCHAR *, DWORD ) DECLSPEC_HIDDEN; diff --git a/dlls/dinput/dinput.c b/dlls/dinput/dinput.c index cac47de74a4..f3003b652d8 100644 --- a/dlls/dinput/dinput.c +++ b/dlls/dinput/dinput.c @@ -45,19 +45,6 @@ static inline struct dinput *impl_from_IDirectInput8W( IDirectInput8W *iface ) return CONTAINING_RECORD( iface, struct dinput, IDirectInput8W_iface ); }
-static DWORD diactionformat_priorityW( DIACTIONFORMATW *action_format, DWORD genre ) -{ - int i; - DWORD priorityFlags = 0; - - /* If there's at least one action for the device it's priority 1 */ - for (i = 0; i < action_format->dwNumActions; i++) - if ((action_format->rgoAction[i].dwSemantic & genre) == genre) - priorityFlags |= DIEDBS_MAPPEDPRI1; - - return priorityFlags; -} - #if defined __i386__ && defined _MSC_VER __declspec(naked) BOOL enum_callback_wrapper(void *callback, const void *instance, void *ref) { @@ -438,65 +425,82 @@ static HRESULT WINAPI dinput8_FindDevice( IDirectInput8W *iface, const GUID *gui return IDirectInput7_FindDevice( &impl->IDirectInput7W_iface, guid, name, instance_guid ); }
-static BOOL should_enumerate_device( const WCHAR *username, DWORD flags, struct list *device_players, const GUID *guid ) +struct enum_device_by_semantics_params { - BOOL should_enumerate = TRUE; - struct DevicePlayer *device_player; + IDirectInput8W *iface; + const WCHAR *username; + DWORD flags;
- /* Check if user owns impl device */ - if (flags & DIEDBSFL_THISUSER && username && *username) + IDirectInputDevice8W *devices[128]; + DWORD device_count; +}; + +static BOOL CALLBACK enum_device_by_semantics( const DIDEVICEINSTANCEW *instance, void *context ) +{ + struct enum_device_by_semantics_params *params = context; + DIDEVCAPS caps = {.dwSize = sizeof(caps)}; + DIPROPSTRING prop_username = { - should_enumerate = FALSE; - LIST_FOR_EACH_ENTRY( device_player, device_players, struct DevicePlayer, entry ) + .diph = { - if (IsEqualGUID( &device_player->instance_guid, guid )) - { - if (*device_player->username && !wcscmp( username, device_player->username )) - return TRUE; /* Device username matches */ - break; - } - } - } + .dwSize = sizeof(DIPROPSTRING), + .dwHeaderSize = sizeof(DIPROPHEADER), + .dwHow = DIPH_DEVICE, + }, + }; + IDirectInputDevice8W *device; + BOOL ret = DIENUM_CONTINUE; + HRESULT hr;
- /* Check if impl device is not owned by anyone */ - if (flags & DIEDBSFL_AVAILABLEDEVICES) + if (params->device_count >= ARRAY_SIZE(params->devices)) return DIENUM_STOP; + + if (FAILED(hr = IDirectInput8_CreateDevice( params->iface, &instance->guidInstance, &device, NULL ))) { - BOOL found = FALSE; - should_enumerate = FALSE; - LIST_FOR_EACH_ENTRY( device_player, device_players, struct DevicePlayer, entry ) - { - if (IsEqualGUID( &device_player->instance_guid, guid )) - { - if (*device_player->username) found = TRUE; - break; - } - } - if (!found) return TRUE; /* Device does not have a username */ + WARN( "Failed to create device, hr %#lx\n", hr ); + return DIENUM_CONTINUE; }
- return should_enumerate; + if (FAILED(hr = IDirectInputDevice8_GetCapabilities( device, &caps ))) + WARN( "Failed to get device capabilities, hr %#lx\n", hr ); + if ((params->flags & DIEDBSFL_FORCEFEEDBACK) && !caps.dwFFDriverVersion) goto done; + + if (FAILED(hr = IDirectInputDevice8_GetProperty( device, DIPROP_USERNAME, &prop_username.diph ))) + WARN( "Failed to get device capabilities, hr %#lx\n", hr ); + else if ((params->flags & DIEDBSFL_THISUSER) && *params->username && wcscmp( params->username, prop_username.wsz )) + goto done; + else if ((params->flags & DIEDBSFL_AVAILABLEDEVICES) && *prop_username.wsz) + goto done; + + IDirectInputDevice_AddRef( device ); + params->devices[params->device_count++] = device; + +done: + IDirectInputDevice8_Release( device ); + return ret; }
-struct enum_device_by_semantics_params +struct enum_device_object_semantics_params { - IDirectInput8W *iface; - const WCHAR *username; + DIDEVICEINSTANCEW instance; + DIACTIONFORMATW *format; DWORD flags; - - DIDEVICEINSTANCEW *instances; - DWORD instance_count; };
-static BOOL CALLBACK enum_device_by_semantics( const DIDEVICEINSTANCEW *instance, void *context ) +static BOOL CALLBACK enum_device_object_semantics( const DIDEVICEOBJECTINSTANCEW *obj, void *args ) { - struct enum_device_by_semantics_params *params = context; - struct dinput *impl = impl_from_IDirectInput8W( params->iface ); + struct enum_device_object_semantics_params *params = args; + DIACTIONFORMATW *format = params->format; + UINT i;
- if (should_enumerate_device( params->username, params->flags, &impl->device_players, &instance->guidInstance )) + for (i = 0; format && i < format->dwNumActions; i++) { - params->instance_count++; - params->instances = realloc( params->instances, sizeof(DIDEVICEINSTANCEW) * params->instance_count ); - params->instances[params->instance_count - 1] = *instance; + DIOBJECTDATAFORMAT object_format = {.dwType = obj->dwType, .dwOfs = obj->dwOfs}; + BYTE dev_type = params->instance.dwDevType & 0xf; + DIACTIONW *action = format->rgoAction + i; + + if (!device_object_matches_semantic( ¶ms->instance, &object_format, action->dwSemantic, FALSE )) continue; + if (!(action->dwSemantic & 0x4000)) params->flags |= DIEDBS_MAPPEDPRI1; + else if (dev_type != DIDEVTYPE_KEYBOARD && dev_type != DIDEVTYPE_MOUSE) params->flags |= DIEDBS_MAPPEDPRI2; }
return DIENUM_CONTINUE; @@ -505,18 +509,13 @@ static BOOL CALLBACK enum_device_by_semantics( const DIDEVICEINSTANCEW *instance static HRESULT WINAPI dinput8_EnumDevicesBySemantics( IDirectInput8W *iface, const WCHAR *username, DIACTIONFORMATW *action_format, LPDIENUMDEVICESBYSEMANTICSCBW callback, void *context, DWORD flags ) { - struct enum_device_by_semantics_params params = {.iface = iface, .username = username, .flags = flags}; - DWORD callbackFlags, enum_flags = DIEDFL_ATTACHEDONLY | (flags & DIEDFL_FORCEFEEDBACK); - static const GUID *guids[2] = {&GUID_SysKeyboard, &GUID_SysMouse}; - static const DWORD actionMasks[] = {DIKEYBOARD_MASK, DIMOUSE_MASK}; + struct enum_device_by_semantics_params params = {.iface = iface, .username = username ? username : L"", .flags = flags}; + DWORD enum_flags = DIEDFL_ATTACHEDONLY | (flags & DIEDFL_FORCEFEEDBACK); struct dinput *impl = impl_from_IDirectInput8W( iface ); - IDirectInputDevice8W *device; - DIDEVICEINSTANCEW didevi; unsigned int i = 0; HRESULT hr; - int remain;
- FIXME( "iface %p, username %s, action_format %p, callback %p, context %p, flags %#lx stub!\n", + TRACE( "iface %p, username %s, action_format %p, callback %p, context %p, flags %#lx\n", iface, debugstr_w(username), action_format, callback, context, flags );
if (!action_format) return DIERR_INVALIDPARAM; @@ -531,64 +530,35 @@ static HRESULT WINAPI dinput8_EnumDevicesBySemantics( IDirectInput8W *iface, con action->dwObjID, action->dwHow, debugstr_w(action->lptszActionName) ); }
- didevi.dwSize = sizeof(didevi); - - hr = IDirectInput8_EnumDevices( &impl->IDirectInput8W_iface, DI8DEVCLASS_GAMECTRL, - enum_device_by_semantics, ¶ms, enum_flags ); - if (FAILED(hr)) + if (FAILED(hr = IDirectInput8_EnumDevices( &impl->IDirectInput8W_iface, DI8DEVCLASS_ALL, + enum_device_by_semantics, ¶ms, enum_flags ))) { - free( params.instances ); - return hr; + WARN( "Failed to enumerate devices, hr %#lx\n", hr ); + goto cleanup; }
- remain = params.instance_count; - /* Add keyboard and mouse to remaining device count */ - if (!(flags & DIEDBSFL_FORCEFEEDBACK)) + while (params.device_count--) { - for (i = 0; i < ARRAY_SIZE(guids); i++) - { - if (should_enumerate_device( username, flags, &impl->device_players, guids[i] )) remain++; - } - } - - for (i = 0; i < params.instance_count; i++) - { - callbackFlags = diactionformat_priorityW( action_format, action_format->dwGenre ); - IDirectInput_CreateDevice( iface, ¶ms.instances[i].guidInstance, &device, NULL ); - - if (callback( ¶ms.instances[i], device, callbackFlags, --remain, context ) == DIENUM_STOP) - { - free( params.instances ); - IDirectInputDevice_Release( device ); - return DI_OK; - } - IDirectInputDevice_Release( device ); - } - - free( params.instances ); - - if (flags & DIEDBSFL_FORCEFEEDBACK) return DI_OK; - - /* Enumerate keyboard and mouse */ - for (i = 0; i < ARRAY_SIZE(guids); i++) - { - if (should_enumerate_device( username, flags, &impl->device_players, guids[i] )) - { - callbackFlags = diactionformat_priorityW( action_format, actionMasks[i] ); - - IDirectInput_CreateDevice( iface, guids[i], &device, NULL ); - IDirectInputDevice_GetDeviceInfo( device, &didevi ); - - if (callback( &didevi, device, callbackFlags, --remain, context ) == DIENUM_STOP) - { - IDirectInputDevice_Release( device ); - return DI_OK; - } - IDirectInputDevice_Release( device ); - } + struct enum_device_object_semantics_params object_params = {.instance = {.dwSize = sizeof(DIDEVICEINSTANCEW)}, .format = action_format}; + IDirectInputDevice8W *device = params.devices[params.device_count]; + BOOL ret = DIENUM_STOP; + + if (FAILED(hr = IDirectInputDevice8_GetDeviceInfo( device, &object_params.instance ))) + WARN( "Failed to get device %p info, hr %#lx\n", device, hr ); + else if (FAILED(hr = IDirectInputDevice8_EnumObjects( device, enum_device_object_semantics, &object_params, DIDFT_ALL ))) + WARN( "Failed to enumerate device %p objects, hr %#lx\n", device, hr ); + else + ret = callback( &object_params.instance, device, object_params.flags, params.device_count, context ); + + IDirectInputDevice8_Release( device ); + if (ret == DIENUM_STOP) goto cleanup; }
return DI_OK; + +cleanup: + while (params.device_count--) IDirectInputDevice8_Release( params.devices[params.device_count] ); + return hr; }
static HRESULT WINAPI dinput8_ConfigureDevices( IDirectInput8W *iface, LPDICONFIGUREDEVICESCALLBACK callback, diff --git a/dlls/dinput/tests/joystick8.c b/dlls/dinput/tests/joystick8.c index a7420240b68..7aee83e5a37 100644 --- a/dlls/dinput/tests/joystick8.c +++ b/dlls/dinput/tests/joystick8.c @@ -445,7 +445,7 @@ static BOOL CALLBACK enum_devices_by_semantic( const DIDEVICEINSTANCEW *instance if (remaining == 2) { expect_instance = &expect_joystick; - todo_wine ok( flags == (context ? 3 : 0), "got flags %#lx\n", flags ); + ok( flags == (context ? 3 : 0), "got flags %#lx\n", flags ); } else if (remaining == 1) {
Hi,
It looks like your patch introduced the new failures shown below. Please investigate and fix them before resubmitting your patch. If they are not new, fixing them anyway would help a lot. Otherwise please ask for the known failures list to be updated.
The tests also ran into some preexisting test failures. If you know how to fix them that would be helpful. See the TestBot job for the details:
The full results can be found at: https://testbot.winehq.org/JobDetails.pl?Key=131101
Your paranoid android.
=== w8 (32 bit report) ===
dinput: joystick8.c:1281: Test failed: 0x800: 4: got dwData -71
v2: Remove unnecessary format checks and avoid leaking devices on `EnumDevicesBySemantics` enumeration interruption.