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) {