[PATCH] dinput: Support default DIPROP_BUFFERSIZE buffer size

Alistair Leslie-Hughes leslie_alistair at hotmail.com
Sat Jan 11 20:01:36 CST 2020


When a program calls SetProperty with DIPROP_BUFFERSIZE, dinput records
this value for GetProperty but only uses it when the device can support
that number of buffers otherwise it ignores this value..

In the case of game "Far Cry 5", it passes through (DWORD)-1 which
cause HeapAlloc to fail ((DWORD)-1 * sizeof(DIDEVICEOBJECTDATA)).

Since there is no real way of working out the max value, I've capped it at 100 as
the default value is 20.

MSDN reference.
https://docs.microsoft.com/en-us/previous-versions/windows/desktop/ee417908(v=vs.85)

Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=45732

Signed-off-by: Alistair Leslie-Hughes <leslie_alistair at hotmail.com>
---
 dlls/dinput/device.c              | 14 ++++++++++----
 dlls/dinput/device_private.h      |  3 ++-
 dlls/dinput/joystick_linux.c      |  4 ++++
 dlls/dinput/joystick_linuxinput.c |  4 ++++
 dlls/dinput/joystick_osx.c        |  4 ++++
 dlls/dinput/keyboard.c            |  3 +++
 dlls/dinput/mouse.c               |  3 +++
 dlls/dinput/tests/device.c        | 14 ++++++++++++++
 8 files changed, 44 insertions(+), 5 deletions(-)

diff --git a/dlls/dinput/device.c b/dlls/dinput/device.c
index 28329d03b5..1604075f84 100644
--- a/dlls/dinput/device.c
+++ b/dlls/dinput/device.c
@@ -1307,7 +1307,7 @@ HRESULT WINAPI IDirectInputDevice2WImpl_GetProperty(LPDIRECTINPUTDEVICE8W iface,
 
             if (pdiph->dwSize != sizeof(DIPROPDWORD)) return DIERR_INVALIDPARAM;
 
-            pd->dwData = This->queue_len;
+            pd->dwData = This->buffersize;
             TRACE("buffersize = %d\n", pd->dwData);
             break;
         }
@@ -1396,12 +1396,18 @@ HRESULT WINAPI IDirectInputDevice2WImpl_SetProperty(
             TRACE("buffersize = %d\n", pd->dwData);
 
             EnterCriticalSection(&This->crit);
+
+            This->buffersize  = pd->dwData;
+
+            This->queue_len = This->buffersize > 100 ? 100 : This->buffersize;
+            if (This->buffersize > 100)
+                WARN("Trying to set large buffer size %d\n", pd->dwData);
+
             HeapFree(GetProcessHeap(), 0, This->data_queue);
 
-            This->data_queue = !pd->dwData ? NULL : HeapAlloc(GetProcessHeap(), 0,
-                                pd->dwData * sizeof(DIDEVICEOBJECTDATA));
+            This->data_queue = !This->queue_len ? NULL : HeapAlloc(GetProcessHeap(), 0,
+                                This->queue_len * sizeof(DIDEVICEOBJECTDATA));
             This->queue_head = This->queue_tail = This->overflow = 0;
-            This->queue_len  = pd->dwData;
 
             LeaveCriticalSection(&This->crit);
             break;
diff --git a/dlls/dinput/device_private.h b/dlls/dinput/device_private.h
index 27e9c26286..23d9e2eebc 100644
--- a/dlls/dinput/device_private.h
+++ b/dlls/dinput/device_private.h
@@ -71,10 +71,11 @@ struct IDirectInputDeviceImpl
     DI_EVENT_PROC               event_proc;  /* function to receive mouse & keyboard events */
 
     LPDIDEVICEOBJECTDATA        data_queue;  /* buffer for 'GetDeviceData'.                 */
-    int                         queue_len;   /* size of the queue - set in 'SetProperty'    */
+    int                         queue_len;   /* valid size of the queue                     */
     int                         queue_head;  /* position to write new event into queue      */
     int                         queue_tail;  /* next event to read from queue               */
     BOOL                        overflow;    /* return DI_BUFFEROVERFLOW in 'GetDeviceData' */
+    DWORD                       buffersize;  /* size of the queue - set in 'SetProperty'    */
 
     DataFormat                  data_format; /* user data format and wine to user format converter */
 
diff --git a/dlls/dinput/joystick_linux.c b/dlls/dinput/joystick_linux.c
index afdf659b4a..1e7bf72936 100644
--- a/dlls/dinput/joystick_linux.c
+++ b/dlls/dinput/joystick_linux.c
@@ -501,6 +501,10 @@ static HRESULT alloc_device(REFGUID rguid, IDirectInputImpl *dinput,
     newDevice->generic.base.ref = 1;
     newDevice->generic.base.dinput = dinput;
     newDevice->generic.base.guid = *rguid;
+    newDevice->generic.base.buffersize = 20;
+    newDevice->generic.base.queue_len = 20;
+    newDevice->generic.base.data_queue = HeapAlloc(GetProcessHeap(), 0,
+                newDevice->generic.base.queue_len * sizeof(DIDEVICEOBJECTDATA));
     InitializeCriticalSection(&newDevice->generic.base.crit);
     newDevice->generic.base.crit.DebugInfo->Spare[0] = (DWORD_PTR)(__FILE__ ": JoystickImpl*->generic.base.crit");
 
diff --git a/dlls/dinput/joystick_linuxinput.c b/dlls/dinput/joystick_linuxinput.c
index b5418d805c..98283a1eed 100644
--- a/dlls/dinput/joystick_linuxinput.c
+++ b/dlls/dinput/joystick_linuxinput.c
@@ -471,6 +471,10 @@ static JoystickImpl *alloc_device(REFGUID rguid, IDirectInputImpl *dinput, unsig
     newDevice->generic.base.ref    = 1;
     newDevice->generic.base.guid   = *rguid;
     newDevice->generic.base.dinput = dinput;
+    newDevice->generic.base.buffersize = 20;
+    newDevice->generic.base.queue_len = 20;
+    newDevice->generic.base.data_queue = HeapAlloc(GetProcessHeap(), 0,
+                newDevice->generic.base.queue_len * sizeof(DIDEVICEOBJECTDATA));
     newDevice->generic.joy_polldev = joy_polldev;
     newDevice->joyfd       = -1;
     newDevice->joydev      = &joydevs[index];
diff --git a/dlls/dinput/joystick_osx.c b/dlls/dinput/joystick_osx.c
index 990f5d1f07..c48cad1f5a 100644
--- a/dlls/dinput/joystick_osx.c
+++ b/dlls/dinput/joystick_osx.c
@@ -1168,6 +1168,10 @@ static HRESULT alloc_device(REFGUID rguid, IDirectInputImpl *dinput,
     newDevice->generic.base.ref = 1;
     newDevice->generic.base.dinput = dinput;
     newDevice->generic.base.guid = *rguid;
+    newDevice->generic.base.buffersize = 20;
+    newDevice->generic.base.queue_len = 20;
+    newDevice->generic.base.data_queue = HeapAlloc(GetProcessHeap(), 0,
+                newDevice->generic.base.queue_len * sizeof(DIDEVICEOBJECTDATA));
     InitializeCriticalSection(&newDevice->generic.base.crit);
     newDevice->generic.base.crit.DebugInfo->Spare[0] = (DWORD_PTR)(__FILE__ ": JoystickImpl*->generic.base.crit");
 
diff --git a/dlls/dinput/keyboard.c b/dlls/dinput/keyboard.c
index 47f28cac52..15a6be4dee 100644
--- a/dlls/dinput/keyboard.c
+++ b/dlls/dinput/keyboard.c
@@ -268,6 +268,9 @@ static SysKeyboardImpl *alloc_device(REFGUID rguid, IDirectInputImpl *dinput)
     InitializeCriticalSection(&newDevice->base.crit);
     newDevice->base.crit.DebugInfo->Spare[0] = (DWORD_PTR)(__FILE__ ": SysKeyboardImpl*->base.crit");
     newDevice->subtype = get_keyboard_subtype();
+    newDevice->base.buffersize = 20;
+    newDevice->base.queue_len = 20;
+    newDevice->base.data_queue = HeapAlloc(GetProcessHeap(), 0, newDevice->base.queue_len * sizeof(DIDEVICEOBJECTDATA));
 
     /* Create copy of default data format */
     if (!(df = HeapAlloc(GetProcessHeap(), 0, c_dfDIKeyboard.dwSize))) goto failed;
diff --git a/dlls/dinput/mouse.c b/dlls/dinput/mouse.c
index 08ace2f4e9..59c8c9dad8 100644
--- a/dlls/dinput/mouse.c
+++ b/dlls/dinput/mouse.c
@@ -214,6 +214,9 @@ static SysMouseImpl *alloc_device(REFGUID rguid, IDirectInputImpl *dinput)
     newDevice->base.crit.DebugInfo->Spare[0] = (DWORD_PTR)(__FILE__ ": SysMouseImpl*->base.crit");
     newDevice->base.dinput = dinput;
     newDevice->base.event_proc = dinput_mouse_hook;
+    newDevice->base.buffersize = 20;
+    newDevice->base.queue_len = 20;
+    newDevice->base.data_queue = HeapAlloc(GetProcessHeap(), 0, newDevice->base.queue_len * sizeof(DIDEVICEOBJECTDATA));
 
     get_app_key(&hkey, &appkey);
     if (!get_config_key(hkey, appkey, "MouseWarpOverride", buffer, sizeof(buffer)))
diff --git a/dlls/dinput/tests/device.c b/dlls/dinput/tests/device.c
index a2a5a65686..4dd16c70d2 100644
--- a/dlls/dinput/tests/device.c
+++ b/dlls/dinput/tests/device.c
@@ -106,8 +106,22 @@ static void test_object_info(IDirectInputDeviceA *device, HWND hwnd)
     dp.diph.dwHeaderSize = sizeof(DIPROPHEADER);
     dp.diph.dwHow = DIPH_DEVICE;
     dp.diph.dwObj = 0;
+    dp.dwData = -1;
+
+    hr = IDirectInputDevice_GetProperty(device, DIPROP_BUFFERSIZE, &dp.diph);
+    ok(hr == DI_OK, "Failed: %08x\n", hr);
+    ok(dp.dwData == 20, "got %d\n", dp.dwData);
+
+    dp.dwData = -1;
+    hr = IDirectInputDevice_SetProperty(device, DIPROP_BUFFERSIZE, (LPCDIPROPHEADER)&dp.diph);
+    ok(hr == DI_OK, "SetProperty() failed: %08x\n", hr);
+
     dp.dwData = 0;
+    hr = IDirectInputDevice_GetProperty(device, DIPROP_BUFFERSIZE, &dp.diph);
+    ok(hr == DI_OK, "Failed: %08x\n", hr);
+    ok(dp.dwData == -1, "got %d\n", dp.dwData);
 
+    dp.dwData = 0;
     hr = IDirectInputDevice_SetProperty(device, DIPROP_BUFFERSIZE, (LPCDIPROPHEADER)&dp.diph);
     ok(hr == DI_OK, "SetProperty() failed: %08x\n", hr);
     cnt = 5;
-- 
2.24.1




More information about the wine-devel mailing list