[PATCH 1/5] dinput: Factor object enumeration checks and offset mapping.

Rémi Bernon rbernon at codeweavers.com
Wed Oct 20 03:41:06 CDT 2021


Signed-off-by: Rémi Bernon <rbernon at codeweavers.com>
---
 dlls/dinput/device.c       | 39 ++++++++++++++++++++++++++++++++------
 dlls/dinput/joystick_hid.c | 26 +++++++------------------
 dlls/dinput/keyboard.c     | 19 ++-----------------
 dlls/dinput/mouse.c        | 20 ++-----------------
 4 files changed, 44 insertions(+), 60 deletions(-)

diff --git a/dlls/dinput/device.c b/dlls/dinput/device.c
index cdaa76cd504..2b2c4646e31 100644
--- a/dlls/dinput/device.c
+++ b/dlls/dinput/device.c
@@ -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;
diff --git a/dlls/dinput/joystick_hid.c b/dlls/dinput/joystick_hid.c
index 3dc43c450e4..2dec33e3ccd 100644
--- a/dlls/dinput/joystick_hid.c
+++ b/dlls/dinput/joystick_hid.c
@@ -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;
         }
     }
diff --git a/dlls/dinput/keyboard.c b/dlls/dinput/keyboard.c
index 0c2a1b839ff..ad91c948fbc 100644
--- a/dlls/dinput/keyboard.c
+++ b/dlls/dinput/keyboard.c
@@ -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;
     }
 
diff --git a/dlls/dinput/mouse.c b/dlls/dinput/mouse.c
index 3553a5af94d..5b3ec2d1f20 100644
--- a/dlls/dinput/mouse.c
+++ b/dlls/dinput/mouse.c
@@ -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;
     }
 
-- 
2.33.0




More information about the wine-devel mailing list