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:
parent
90a0b7c706
commit
ec3e51bb10
|
@ -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, ¶ms );
|
||||
hr = impl->vtbl->enum_objects( iface, &filter, DIDFT_AXIS, set_object_property, ¶ms );
|
||||
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, ¶ms );
|
||||
hr = impl->vtbl->enum_objects( iface, &filter, DIDFT_AXIS, set_object_property, ¶ms );
|
||||
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;
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue