dinput: Factor object enumeration checks and offset mapping.

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 2021-10-20 11:29:29 +02:00 committed by Alexandre Julliard
parent 90a0b7c706
commit ec3e51bb10
4 changed files with 44 additions and 60 deletions

View File

@ -1186,6 +1186,24 @@ HRESULT WINAPI IDirectInputDevice2WImpl_EnumObjects( IDirectInputDevice8W *iface
return DI_OK;
}
static HRESULT enum_object_filter_init( IDirectInputDeviceImpl *impl, DIPROPHEADER *filter )
{
DIDATAFORMAT *format = impl->data_format.wine_df;
int i, *offsets = impl->data_format.offsets;
if (filter->dwHow > DIPH_BYUSAGE) return DIERR_INVALIDPARAM;
if (filter->dwHow == DIPH_BYUSAGE && !(impl->instance.dwDevType & DIDEVTYPE_HID)) return DIERR_UNSUPPORTED;
if (filter->dwHow != DIPH_BYOFFSET) return DI_OK;
if (!offsets) return DIERR_NOTFOUND;
for (i = 0; i < format->dwNumObjs; ++i) if (offsets[i] == filter->dwObj) break;
if (i == format->dwNumObjs) return DIERR_NOTFOUND;
filter->dwObj = format->rgodf[i].dwOfs;
return DI_OK;
}
static BOOL CALLBACK find_object( const DIDEVICEOBJECTINSTANCEW *instance, void *context )
{
*(DIDEVICEOBJECTINSTANCEW *)context = *instance;
@ -1198,6 +1216,7 @@ HRESULT WINAPI IDirectInputDevice2WImpl_GetProperty( IDirectInputDevice8W *iface
IDirectInputDeviceImpl *impl = impl_from_IDirectInputDevice8W( iface );
DWORD object_mask = DIDFT_AXIS | DIDFT_BUTTON | DIDFT_POV;
DIDEVICEOBJECTINSTANCEW instance;
DIPROPHEADER filter;
HRESULT hr;
TRACE( "iface %p, guid %s, header %p\n", iface, debugstr_guid( guid ), header );
@ -1206,6 +1225,9 @@ HRESULT WINAPI IDirectInputDevice2WImpl_GetProperty( IDirectInputDevice8W *iface
if (header->dwHeaderSize != sizeof(DIPROPHEADER)) return DIERR_INVALIDPARAM;
if (!IS_DIPROP( guid )) return DI_OK;
filter = *header;
if (FAILED(hr = enum_object_filter_init( impl, &filter ))) return hr;
switch (LOWORD( guid ))
{
case (DWORD_PTR)DIPROP_PRODUCTNAME:
@ -1228,7 +1250,7 @@ HRESULT WINAPI IDirectInputDevice2WImpl_GetProperty( IDirectInputDevice8W *iface
case (DWORD_PTR)DIPROP_RANGE:
if (header->dwSize != sizeof(DIPROPRANGE)) return DIERR_INVALIDPARAM;
if (header->dwHow == DIPH_DEVICE) return DIERR_UNSUPPORTED;
hr = impl->vtbl->enum_objects( iface, header, object_mask, find_object, &instance );
hr = impl->vtbl->enum_objects( iface, &filter, object_mask, find_object, &instance );
if (FAILED(hr)) return hr;
if (hr == DIENUM_CONTINUE) return DIERR_NOTFOUND;
if (!(instance.dwType & DIDFT_AXIS)) return DIERR_UNSUPPORTED;
@ -1239,7 +1261,7 @@ HRESULT WINAPI IDirectInputDevice2WImpl_GetProperty( IDirectInputDevice8W *iface
case (DWORD_PTR)DIPROP_GRANULARITY:
if (header->dwSize != sizeof(DIPROPDWORD)) return DIERR_INVALIDPARAM;
if (header->dwHow == DIPH_DEVICE) return DIERR_UNSUPPORTED;
hr = impl->vtbl->enum_objects( iface, header, object_mask, find_object, &instance );
hr = impl->vtbl->enum_objects( iface, &filter, object_mask, find_object, &instance );
if (FAILED(hr)) return hr;
if (hr == DIENUM_CONTINUE) return DIERR_NOTFOUND;
if (!(instance.dwType & DIDFT_AXIS)) return DIERR_UNSUPPORTED;
@ -1247,7 +1269,7 @@ HRESULT WINAPI IDirectInputDevice2WImpl_GetProperty( IDirectInputDevice8W *iface
case (DWORD_PTR)DIPROP_KEYNAME:
if (header->dwSize != sizeof(DIPROPSTRING)) return DIERR_INVALIDPARAM;
hr = impl->vtbl->enum_objects( iface, header, object_mask, find_object, &instance );
hr = impl->vtbl->enum_objects( iface, &filter, object_mask, find_object, &instance );
if (FAILED(hr)) return hr;
if (hr == DIENUM_CONTINUE) return DIERR_NOTFOUND;
if (!(instance.dwType & DIDFT_BUTTON)) return DIERR_UNSUPPORTED;
@ -1317,6 +1339,7 @@ HRESULT WINAPI IDirectInputDevice2WImpl_SetProperty( IDirectInputDevice8W *iface
{
struct set_object_property_params params = {.iface = iface, .header = header, .property = LOWORD( guid )};
IDirectInputDeviceImpl *impl = impl_from_IDirectInputDevice8W( iface );
DIPROPHEADER filter;
HRESULT hr;
TRACE( "iface %p, guid %s, header %p\n", iface, debugstr_guid( guid ), header );
@ -1325,6 +1348,9 @@ HRESULT WINAPI IDirectInputDevice2WImpl_SetProperty( IDirectInputDevice8W *iface
if (header->dwHeaderSize != sizeof(DIPROPHEADER)) return DIERR_INVALIDPARAM;
if (!IS_DIPROP( guid )) return DI_OK;
filter = *header;
if (FAILED(hr = enum_object_filter_init( impl, &filter ))) return hr;
switch (LOWORD( guid ))
{
case (DWORD_PTR)DIPROP_RANGE:
@ -1332,7 +1358,7 @@ HRESULT WINAPI IDirectInputDevice2WImpl_SetProperty( IDirectInputDevice8W *iface
const DIPROPRANGE *value = (const DIPROPRANGE *)header;
if (header->dwSize != sizeof(DIPROPRANGE)) return DIERR_INVALIDPARAM;
if (value->lMin > value->lMax) return DIERR_INVALIDPARAM;
hr = impl->vtbl->enum_objects( iface, header, DIDFT_AXIS, set_object_property, &params );
hr = impl->vtbl->enum_objects( iface, &filter, DIDFT_AXIS, set_object_property, &params );
if (FAILED(hr)) return hr;
return DI_OK;
}
@ -1342,7 +1368,7 @@ HRESULT WINAPI IDirectInputDevice2WImpl_SetProperty( IDirectInputDevice8W *iface
const DIPROPDWORD *value = (const DIPROPDWORD *)header;
if (header->dwSize != sizeof(DIPROPDWORD)) return DIERR_INVALIDPARAM;
if (value->dwData > 10000) return DIERR_INVALIDPARAM;
hr = impl->vtbl->enum_objects( iface, header, DIDFT_AXIS, set_object_property, &params );
hr = impl->vtbl->enum_objects( iface, &filter, DIDFT_AXIS, set_object_property, &params );
if (FAILED(hr)) return hr;
return DI_OK;
}
@ -1473,7 +1499,7 @@ HRESULT WINAPI IDirectInputDevice2WImpl_GetObjectInfo( IDirectInputDevice8W *ifa
DWORD obj, DWORD how )
{
IDirectInputDeviceImpl *impl = impl_from_IDirectInputDevice8W( iface );
const DIPROPHEADER filter =
DIPROPHEADER filter =
{
.dwSize = sizeof(filter),
.dwHeaderSize = sizeof(filter),
@ -1488,6 +1514,7 @@ HRESULT WINAPI IDirectInputDevice2WImpl_GetObjectInfo( IDirectInputDevice8W *ifa
if (instance->dwSize != sizeof(DIDEVICEOBJECTINSTANCE_DX3W) && instance->dwSize != sizeof(DIDEVICEOBJECTINSTANCEW))
return DIERR_INVALIDPARAM;
if (how == DIPH_DEVICE) return DIERR_INVALIDPARAM;
if (FAILED(hr = enum_object_filter_init( impl, &filter ))) return hr;
hr = impl->vtbl->enum_objects( iface, &filter, DIDFT_ALL, get_object_info, instance );
if (FAILED(hr)) return hr;

View File

@ -392,28 +392,16 @@ static void set_axis_type( DIDEVICEOBJECTINSTANCEW *instance, BOOL *seen, DWORD
seen[i] = TRUE;
}
static BOOL enum_objects( struct hid_joystick *impl, const DIPROPHEADER *header, DWORD flags,
static BOOL enum_objects( struct hid_joystick *impl, const DIPROPHEADER *filter, DWORD flags,
enum_object_callback callback, void *data )
{
DWORD collection = 0, object = 0, axis = 0, button = 0, pov = 0, value_ofs = 0, button_ofs = 0, i, j;
DWORD collection = 0, object = 0, axis = 0, button = 0, pov = 0, value_ofs = 0, button_ofs = 0, j;
struct hid_preparsed_data *preparsed = (struct hid_preparsed_data *)impl->preparsed;
DIDEVICEOBJECTINSTANCEW instance = {.dwSize = sizeof(DIDEVICEOBJECTINSTANCEW)};
struct hid_value_caps *caps, *caps_end, *nary, *nary_end, *effect_caps;
DIDATAFORMAT *format = impl->base.data_format.wine_df;
int *offsets = impl->base.data_format.offsets;
struct hid_collection_node *node, *node_end;
DIPROPHEADER filter = *header;
BOOL ret, seen_axis[6] = {0};
if (filter.dwHow == DIPH_BYOFFSET)
{
if (!offsets) return DIENUM_CONTINUE;
for (i = 0; i < format->dwNumObjs; ++i)
if (offsets[i] == filter.dwObj) break;
if (i == format->dwNumObjs) return DIENUM_CONTINUE;
filter.dwObj = format->rgodf[i].dwOfs;
}
button_ofs += impl->caps.NumberInputValueCaps * sizeof(LONG);
button_ofs += impl->caps.NumberOutputValueCaps * sizeof(LONG);
button_ofs += impl->caps.NumberFeatureValueCaps * sizeof(LONG);
@ -489,7 +477,7 @@ static BOOL enum_objects( struct hid_joystick *impl, const DIPROPHEADER *header,
instance.dwDimension = caps->units;
instance.wExponent = caps->units_exp;
check_pid_effect_axis_caps( impl, &instance );
ret = enum_object( impl, &filter, flags, callback, caps, &instance, data );
ret = enum_object( impl, filter, flags, callback, caps, &instance, data );
if (ret != DIENUM_CONTINUE) return ret;
value_ofs += sizeof(LONG);
object++;
@ -532,7 +520,7 @@ static BOOL enum_objects( struct hid_joystick *impl, const DIPROPHEADER *header,
instance.wCollectionNumber = caps->link_collection;
instance.dwDimension = caps->units;
instance.wExponent = caps->units_exp;
ret = enum_object( impl, &filter, flags, callback, caps, &instance, data );
ret = enum_object( impl, filter, flags, callback, caps, &instance, data );
if (ret != DIENUM_CONTINUE) return ret;
button_ofs++;
object++;
@ -567,7 +555,7 @@ static BOOL enum_objects( struct hid_joystick *impl, const DIPROPHEADER *header,
instance.wCollectionNumber = nary->link_collection;
instance.dwDimension = caps->units;
instance.wExponent = caps->units_exp;
ret = enum_object( impl, &filter, flags, callback, nary, &instance, data );
ret = enum_object( impl, filter, flags, callback, nary, &instance, data );
if (ret != DIENUM_CONTINUE) return ret;
button_ofs++;
}
@ -586,7 +574,7 @@ static BOOL enum_objects( struct hid_joystick *impl, const DIPROPHEADER *header,
instance.wCollectionNumber = caps->link_collection;
instance.dwDimension = caps->units;
instance.wExponent = caps->units_exp;
ret = enum_object( impl, &filter, flags, callback, caps, &instance, data );
ret = enum_object( impl, filter, flags, callback, caps, &instance, data );
if (ret != DIENUM_CONTINUE) return ret;
if (caps->flags & HID_VALUE_CAPS_IS_BUTTON) button_ofs++;
@ -612,7 +600,7 @@ static BOOL enum_objects( struct hid_joystick *impl, const DIPROPHEADER *header,
instance.wCollectionNumber = node->parent;
instance.dwDimension = 0;
instance.wExponent = 0;
ret = enum_object( impl, &filter, flags, callback, NULL, &instance, data );
ret = enum_object( impl, filter, flags, callback, NULL, &instance, data );
if (ret != DIENUM_CONTINUE) return ret;
}
}

View File

@ -302,7 +302,7 @@ static BOOL try_enum_object( const DIPROPHEADER *filter, DWORD flags, LPDIENUMDE
return DIENUM_CONTINUE;
}
static HRESULT keyboard_internal_enum_objects( IDirectInputDevice8W *iface, const DIPROPHEADER *header, DWORD flags,
static HRESULT keyboard_internal_enum_objects( IDirectInputDevice8W *iface, const DIPROPHEADER *filter, DWORD flags,
LPDIENUMDEVICEOBJECTSCALLBACKW callback, void *context )
{
SysKeyboardImpl *impl = impl_from_IDirectInputDevice8W( iface );
@ -314,31 +314,16 @@ static HRESULT keyboard_internal_enum_objects( IDirectInputDevice8W *iface, cons
.dwOfs = DIK_ESCAPE,
.dwType = DIDFT_PSHBUTTON | DIDFT_MAKEINSTANCE( DIK_ESCAPE ),
};
DIDATAFORMAT *format = impl->base.data_format.wine_df;
int *offsets = impl->base.data_format.offsets;
DIPROPHEADER filter = *header;
DWORD i, dik;
BOOL ret;
if (header->dwHow != DIPH_DEVICE && header->dwHow != DIPH_BYOFFSET && header->dwHow != DIPH_BYID)
return DIERR_UNSUPPORTED;
if (filter.dwHow == DIPH_BYOFFSET)
{
if (!offsets) return DIENUM_CONTINUE;
for (i = 0; i < format->dwNumObjs; ++i)
if (offsets[i] == filter.dwObj) break;
if (i == format->dwNumObjs) return DIENUM_CONTINUE;
filter.dwObj = format->rgodf[i].dwOfs;
}
for (i = 0; i < 512; ++i)
{
if (!GetKeyNameTextW( i << 16, instance.tszName, ARRAY_SIZE(instance.tszName) )) continue;
if (!(dik = map_dik_code( i, 0, subtype, impl->base.dinput->dwVersion ))) continue;
instance.dwOfs = dik;
instance.dwType = DIDFT_PSHBUTTON | DIDFT_MAKEINSTANCE( dik );
ret = try_enum_object( &filter, flags, callback, &instance, context );
ret = try_enum_object( filter, flags, callback, &instance, context );
if (ret != DIENUM_CONTINUE) return DIENUM_STOP;
}

View File

@ -575,7 +575,7 @@ static BOOL try_enum_object( const DIPROPHEADER *filter, DWORD flags, LPDIENUMDE
return DIENUM_CONTINUE;
}
static HRESULT mouse_internal_enum_objects( IDirectInputDevice8W *iface, const DIPROPHEADER *header, DWORD flags,
static HRESULT mouse_internal_enum_objects( IDirectInputDevice8W *iface, const DIPROPHEADER *filter, DWORD flags,
LPDIENUMDEVICEOBJECTSCALLBACKW callback, void *context )
{
DIDEVICEOBJECTINSTANCEW instances[] =
@ -640,28 +640,12 @@ static HRESULT mouse_internal_enum_objects( IDirectInputDevice8W *iface, const D
.tszName = L"Button 4",
},
};
SysMouseImpl *impl = impl_from_IDirectInputDevice8W( iface );
DIDATAFORMAT *format = impl->base.data_format.wine_df;
int *offsets = impl->base.data_format.offsets;
DIPROPHEADER filter = *header;
BOOL ret;
DWORD i;
if (header->dwHow != DIPH_DEVICE && header->dwHow != DIPH_BYOFFSET && header->dwHow != DIPH_BYID)
return DIERR_UNSUPPORTED;
if (filter.dwHow == DIPH_BYOFFSET)
{
if (!offsets) return DIENUM_CONTINUE;
for (i = 0; i < format->dwNumObjs; ++i)
if (offsets[i] == filter.dwObj) break;
if (i == format->dwNumObjs) return DIENUM_CONTINUE;
filter.dwObj = format->rgodf[i].dwOfs;
}
for (i = 0; i < ARRAY_SIZE(instances); ++i)
{
ret = try_enum_object( &filter, flags, callback, instances + i, context );
ret = try_enum_object( filter, flags, callback, instances + i, context );
if (ret != DIENUM_CONTINUE) return DIENUM_STOP;
}