>From 287684346feac09e17ce45a5a39645ad61e9e534 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?R=C3=A9mi=20Bernon?= <rbernon@codeweavers.com>
Date: Mon, 5 Oct 2020 12:44:47 +0200
Subject: [PATCH 01/39] dinput: Introduce direct_input_device_alloc helper.

To factory device allocation and initialization.
---
 dlls/dinput/device.c              | 16 ++++++++++++++++
 dlls/dinput/device_private.h      |  3 +++
 dlls/dinput/joystick_linux.c      | 20 ++++----------------
 dlls/dinput/joystick_linuxinput.c | 16 ++++------------
 dlls/dinput/joystick_osx.c        | 19 +++----------------
 dlls/dinput/keyboard.c            | 12 +++---------
 dlls/dinput/mouse.c               | 15 ++++-----------
 7 files changed, 37 insertions(+), 64 deletions(-)

diff --git a/dlls/dinput/device.c b/dlls/dinput/device.c
index 198e903fc2e..0c8d7445b08 100644
--- a/dlls/dinput/device.c
+++ b/dlls/dinput/device.c
@@ -1870,3 +1870,19 @@ HRESULT WINAPI IDirectInputDevice8WImpl_GetImageInfo(LPDIRECTINPUTDEVICE8W iface
     
     return DI_OK;
 }
+
+HRESULT direct_input_device_alloc(SIZE_T size, const IDirectInputDevice8WVtbl *vtblw,
+        const IDirectInputDevice8AVtbl *vtbla, const GUID *guid, IDirectInputImpl *dinput, void **out)
+{
+    IDirectInputDeviceImpl *This;
+    if (!(This = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, size))) return DIERR_OUTOFMEMORY;
+    This->IDirectInputDevice8A_iface.lpVtbl = vtbla;
+    This->IDirectInputDevice8W_iface.lpVtbl = vtblw;
+    This->ref = 1;
+    This->guid = *guid;
+    InitializeCriticalSection(&This->crit);
+    This->dinput = dinput;
+    IDirectInput_AddRef(&dinput->IDirectInput7A_iface);
+    *out = This;
+    return DI_OK;
+}
diff --git a/dlls/dinput/device_private.h b/dlls/dinput/device_private.h
index 2fac4f0e61e..1c727e71f46 100644
--- a/dlls/dinput/device_private.h
+++ b/dlls/dinput/device_private.h
@@ -86,6 +86,9 @@ struct IDirectInputDeviceImpl
     ActionMap                  *action_map;  /* array of mappings */
 };
 
+extern HRESULT direct_input_device_alloc(SIZE_T size, const IDirectInputDevice8WVtbl *vtblw,
+        const IDirectInputDevice8AVtbl *vtbla, const GUID *guid, IDirectInputImpl *dinput, void **out) DECLSPEC_HIDDEN;
+
 extern BOOL get_app_key(HKEY*, HKEY*) DECLSPEC_HIDDEN;
 extern DWORD get_config_key(HKEY, HKEY, const char*, char*, DWORD) DECLSPEC_HIDDEN;
 
diff --git a/dlls/dinput/joystick_linux.c b/dlls/dinput/joystick_linux.c
index 2b26eb806d3..fd4ba4e0e71 100644
--- a/dlls/dinput/joystick_linux.c
+++ b/dlls/dinput/joystick_linux.c
@@ -473,12 +473,10 @@ static HRESULT alloc_device(REFGUID rguid, IDirectInputImpl *dinput,
 
     TRACE("%s %p %p %hu\n", debugstr_guid(rguid), dinput, pdev, index);
 
-    newDevice = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(JoystickImpl));
-    if (newDevice == 0) {
-        WARN("out of memory\n");
-        *pdev = 0;
-        return DIERR_OUTOFMEMORY;
-    }
+    *pdev = NULL;
+    if (FAILED(hr = direct_input_device_alloc(sizeof(JoystickImpl), &JoystickWvt, &JoystickAvt, rguid, dinput, (void **)&newDevice)))
+        return hr;
+    newDevice->generic.base.crit.DebugInfo->Spare[0] = (DWORD_PTR)(__FILE__ ": JoystickImpl*->generic.base.crit");
 
     newDevice->joydev = &joystick_devices[index];
     newDevice->joyfd = -1;
@@ -496,14 +494,6 @@ static HRESULT alloc_device(REFGUID rguid, IDirectInputImpl *dinput,
         newDevice->generic.devcaps.dwButtons = 128;
     }
 
-    newDevice->generic.base.IDirectInputDevice8A_iface.lpVtbl = &JoystickAvt;
-    newDevice->generic.base.IDirectInputDevice8W_iface.lpVtbl = &JoystickWvt;
-    newDevice->generic.base.ref = 1;
-    newDevice->generic.base.dinput = dinput;
-    newDevice->generic.base.guid = *rguid;
-    InitializeCriticalSection(&newDevice->generic.base.crit);
-    newDevice->generic.base.crit.DebugInfo->Spare[0] = (DWORD_PTR)(__FILE__ ": JoystickImpl*->generic.base.crit");
-
     /* setup_dinput_options may change these */
     newDevice->generic.deadzone = 0;
 
@@ -552,8 +542,6 @@ static HRESULT alloc_device(REFGUID rguid, IDirectInputImpl *dinput,
         newDevice->generic.props[i].lSaturation = 0;
     }
 
-    IDirectInput_AddRef(&newDevice->generic.base.dinput->IDirectInput7A_iface);
-
     newDevice->generic.devcaps.dwSize = sizeof(newDevice->generic.devcaps);
     newDevice->generic.devcaps.dwFlags = DIDC_ATTACHED;
 
diff --git a/dlls/dinput/joystick_linuxinput.c b/dlls/dinput/joystick_linuxinput.c
index 102de8269b9..4e1b3f83391 100644
--- a/dlls/dinput/joystick_linuxinput.c
+++ b/dlls/dinput/joystick_linuxinput.c
@@ -463,14 +463,10 @@ static JoystickImpl *alloc_device(REFGUID rguid, IDirectInputImpl *dinput, unsig
     int default_axis_map[WINE_JOYSTICK_MAX_AXES + WINE_JOYSTICK_MAX_POVS*2];
     DIDEVICEINSTANCEW ddi;
 
-    newDevice = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(JoystickImpl));
-    if (!newDevice) return NULL;
-
-    newDevice->generic.base.IDirectInputDevice8A_iface.lpVtbl = &JoystickAvt;
-    newDevice->generic.base.IDirectInputDevice8W_iface.lpVtbl = &JoystickWvt;
-    newDevice->generic.base.ref    = 1;
-    newDevice->generic.base.guid   = *rguid;
-    newDevice->generic.base.dinput = dinput;
+    if (FAILED(direct_input_device_alloc(sizeof(JoystickImpl), &JoystickWvt, &JoystickAvt, rguid, dinput, (void **)&newDevice)))
+        return NULL;
+    newDevice->generic.base.crit.DebugInfo->Spare[0] = (DWORD_PTR)(__FILE__ ": JoystickImpl*->base.crit");
+
     newDevice->generic.joy_polldev = joy_polldev;
     newDevice->joyfd       = -1;
     newDevice->joydev      = &joydevs[index];
@@ -484,8 +480,6 @@ static JoystickImpl *alloc_device(REFGUID rguid, IDirectInputImpl *dinput, unsig
        enabled. */
     newDevice->ff_autocenter = 1;
     newDevice->ff_gain = 0xFFFF;
-    InitializeCriticalSection(&newDevice->generic.base.crit);
-    newDevice->generic.base.crit.DebugInfo->Spare[0] = (DWORD_PTR)(__FILE__ ": JoystickImpl*->base.crit");
 
     /* Count number of available axes - supported Axis & POVs */
     for (i = 0; i < ABS_MAX; i++)
@@ -593,8 +587,6 @@ static JoystickImpl *alloc_device(REFGUID rguid, IDirectInputImpl *dinput, unsig
     if (newDevice->joydev->has_ff)
         newDevice->generic.devcaps.dwFlags |= DIDC_FORCEFEEDBACK;
 
-    IDirectInput_AddRef(&newDevice->generic.base.dinput->IDirectInput7A_iface);
-
     return newDevice;
 
 failed:
diff --git a/dlls/dinput/joystick_osx.c b/dlls/dinput/joystick_osx.c
index 4ec72465500..3631448ea78 100644
--- a/dlls/dinput/joystick_osx.c
+++ b/dlls/dinput/joystick_osx.c
@@ -1096,12 +1096,9 @@ static HRESULT alloc_device(REFGUID rguid, IDirectInputImpl *dinput,
 
     TRACE("%s %p %p %hu\n", debugstr_guid(rguid), dinput, pdev, index);
 
-    newDevice = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(JoystickImpl));
-    if (newDevice == 0) {
-        WARN("out of memory\n");
-        *pdev = 0;
-        return DIERR_OUTOFMEMORY;
-    }
+    if (FAILED(hr = direct_input_device_alloc(sizeof(JoystickImpl), &JoystickWvt, &JoystickAvt, rguid, dinput, (void **)&newDevice)))
+        return hr;
+    newDevice->generic.base.crit.DebugInfo->Spare[0] = (DWORD_PTR)(__FILE__ ": JoystickImpl*->generic.base.crit");
 
     newDevice->id = index;
 
@@ -1163,14 +1160,6 @@ static HRESULT alloc_device(REFGUID rguid, IDirectInputImpl *dinput,
         newDevice->generic.devcaps.dwButtons = 128;
     }
 
-    newDevice->generic.base.IDirectInputDevice8A_iface.lpVtbl = &JoystickAvt;
-    newDevice->generic.base.IDirectInputDevice8W_iface.lpVtbl = &JoystickWvt;
-    newDevice->generic.base.ref = 1;
-    newDevice->generic.base.dinput = dinput;
-    newDevice->generic.base.guid = *rguid;
-    InitializeCriticalSection(&newDevice->generic.base.crit);
-    newDevice->generic.base.crit.DebugInfo->Spare[0] = (DWORD_PTR)(__FILE__ ": JoystickImpl*->generic.base.crit");
-
     /* Create copy of default data format */
     if (!(df = HeapAlloc(GetProcessHeap(), 0, c_dfDIJoystick2.dwSize))) goto FAILED;
     memcpy(df, &c_dfDIJoystick2, c_dfDIJoystick2.dwSize);
@@ -1240,8 +1229,6 @@ static HRESULT alloc_device(REFGUID rguid, IDirectInputImpl *dinput,
     /* initialize default properties */
     get_osx_device_elements_props(newDevice);
 
-    IDirectInput_AddRef(&newDevice->generic.base.dinput->IDirectInput7A_iface);
-
     newDevice->generic.devcaps.dwSize = sizeof(newDevice->generic.devcaps);
     newDevice->generic.devcaps.dwFlags |= DIDC_ATTACHED;
     if (newDevice->generic.base.dinput->dwVersion >= 0x0800)
diff --git a/dlls/dinput/keyboard.c b/dlls/dinput/keyboard.c
index 9981372d957..46f0ce140e0 100644
--- a/dlls/dinput/keyboard.c
+++ b/dlls/dinput/keyboard.c
@@ -258,14 +258,10 @@ static SysKeyboardImpl *alloc_device(REFGUID rguid, IDirectInputImpl *dinput)
     LPDIDATAFORMAT df = NULL;
     int i, idx = 0;
 
-    newDevice = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(SysKeyboardImpl));
-    newDevice->base.IDirectInputDevice8A_iface.lpVtbl = &SysKeyboardAvt;
-    newDevice->base.IDirectInputDevice8W_iface.lpVtbl = &SysKeyboardWvt;
-    newDevice->base.ref = 1;
-    memcpy(&newDevice->base.guid, rguid, sizeof(*rguid));
-    newDevice->base.dinput = dinput;
-    InitializeCriticalSection(&newDevice->base.crit);
+    if (FAILED(direct_input_device_alloc(sizeof(SysKeyboardImpl), &SysKeyboardWvt, &SysKeyboardAvt, rguid, dinput, (void **)&newDevice)))
+        return NULL;
     newDevice->base.crit.DebugInfo->Spare[0] = (DWORD_PTR)(__FILE__ ": SysKeyboardImpl*->base.crit");
+
     newDevice->subtype = get_keyboard_subtype();
 
     /* Create copy of default data format */
@@ -288,8 +284,6 @@ static SysKeyboardImpl *alloc_device(REFGUID rguid, IDirectInputImpl *dinput)
     df->dwNumObjs = idx;
 
     newDevice->base.data_format.wine_df = df;
-    IDirectInput_AddRef(&newDevice->base.dinput->IDirectInput7A_iface);
-
     return newDevice;
 
 failed:
diff --git a/dlls/dinput/mouse.c b/dlls/dinput/mouse.c
index e50731fda41..a741110419c 100644
--- a/dlls/dinput/mouse.c
+++ b/dlls/dinput/mouse.c
@@ -201,16 +201,11 @@ static SysMouseImpl *alloc_device(REFGUID rguid, IDirectInputImpl *dinput)
     char buffer[20];
     HKEY hkey, appkey;
 
-    newDevice = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(SysMouseImpl));
-    if (!newDevice) return NULL;
-    newDevice->base.IDirectInputDevice8A_iface.lpVtbl = &SysMouseAvt;
-    newDevice->base.IDirectInputDevice8W_iface.lpVtbl = &SysMouseWvt;
-    newDevice->base.ref = 1;
-    newDevice->base.dwCoopLevel = DISCL_NONEXCLUSIVE | DISCL_BACKGROUND;
-    newDevice->base.guid = *rguid;
-    InitializeCriticalSection(&newDevice->base.crit);
+    if (FAILED(direct_input_device_alloc(sizeof(SysMouseImpl), &SysMouseWvt, &SysMouseAvt, rguid, dinput, (void **)&newDevice)))
+        return NULL;
     newDevice->base.crit.DebugInfo->Spare[0] = (DWORD_PTR)(__FILE__ ": SysMouseImpl*->base.crit");
-    newDevice->base.dinput = dinput;
+
+    newDevice->base.dwCoopLevel = DISCL_NONEXCLUSIVE | DISCL_BACKGROUND;
 
     get_app_key(&hkey, &appkey);
     if (!get_config_key(hkey, appkey, "MouseWarpOverride", buffer, sizeof(buffer)))
@@ -237,8 +232,6 @@ static SysMouseImpl *alloc_device(REFGUID rguid, IDirectInputImpl *dinput)
             df->rgodf[i].dwType = DIDFT_MAKEINSTANCE(i) | DIDFT_PSHBUTTON;
 
     newDevice->base.data_format.wine_df = df;
-    IDirectInput_AddRef(&newDevice->base.dinput->IDirectInput7A_iface);
-
     if (dinput->dwVersion >= 0x0800)
     {
         newDevice->base.use_raw_input = TRUE;
-- 
2.28.0

>From e214144f908df44c4dafada30208c41a899c1dfb Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?R=C3=A9mi=20Bernon?= <rbernon@codeweavers.com>
Date: Mon, 5 Oct 2020 12:44:47 +0200
Subject: [PATCH 02/39] dinput: Factor IDirectInputDeviceA implementation.

As a IDirectInputDeviceW wrapper.
---
 dlls/dinput/Makefile.in           |   1 +
 dlls/dinput/ansi.c                | 562 ++++++++++++++++++++++++++++++
 dlls/dinput/device.c              | 255 +-------------
 dlls/dinput/device_private.h      |  63 +---
 dlls/dinput/joystick.c            | 159 ---------
 dlls/dinput/joystick_linux.c      |  73 +---
 dlls/dinput/joystick_linuxinput.c | 197 +----------
 dlls/dinput/joystick_osx.c        |  85 +----
 dlls/dinput/joystick_private.h    |  13 -
 dlls/dinput/keyboard.c            | 160 +--------
 dlls/dinput/mouse.c               | 168 +--------
 dlls/dinput8/Makefile.in          |   1 +
 12 files changed, 579 insertions(+), 1158 deletions(-)
 create mode 100644 dlls/dinput/ansi.c

diff --git a/dlls/dinput/Makefile.in b/dlls/dinput/Makefile.in
index ae65fd4d93e..a22c8a72180 100644
--- a/dlls/dinput/Makefile.in
+++ b/dlls/dinput/Makefile.in
@@ -5,6 +5,7 @@ EXTRADEFS = -DDIRECTINPUT_VERSION=0x0700
 EXTRALIBS = $(IOKIT_LIBS) $(FORCEFEEDBACK_LIBS)
 
 C_SRCS = \
+	ansi.c \
 	config.c \
 	data_formats.c \
 	device.c \
diff --git a/dlls/dinput/ansi.c b/dlls/dinput/ansi.c
new file mode 100644
index 00000000000..edfbfb878cd
--- /dev/null
+++ b/dlls/dinput/ansi.c
@@ -0,0 +1,562 @@
+/*
+ * Ansi interface wrappers
+ *
+ * Copyright 2020 Rémi Bernon for CodeWeavers
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+#include <stdarg.h>
+#include <string.h>
+
+#include "windef.h"
+#include "winbase.h"
+#include "winreg.h"
+#include "winuser.h"
+#include "winerror.h"
+#include "dinput.h"
+
+#include "device_private.h"
+#include "dinput_private.h"
+
+#include "wine/debug.h"
+
+WINE_DEFAULT_DEBUG_CHANNEL(dinput);
+
+static IDirectInputDeviceImpl *impl_from_IDirectInputDevice8A(IDirectInputDevice8A *iface)
+{
+    return CONTAINING_RECORD(iface, IDirectInputDeviceImpl, IDirectInputDevice8A_iface);
+}
+static IDirectInputDevice8W *IDirectInputDevice8W_from_impl(IDirectInputDeviceImpl *This)
+{
+    return &This->IDirectInputDevice8W_iface;
+}
+
+static void dideviceobjectinstance_wtoa(const DIDEVICEOBJECTINSTANCEW *didoiw, DIDEVICEOBJECTINSTANCEA *didoia)
+{
+    didoia->guidType = didoiw->guidType;
+    didoia->dwOfs = didoiw->dwOfs;
+    didoia->dwType = didoiw->dwType;
+    didoia->dwFlags = didoiw->dwFlags;
+    WideCharToMultiByte(CP_ACP, 0, didoiw->tszName, -1, didoia->tszName, sizeof(didoia->tszName), NULL, NULL);
+    if (didoia->dwSize <= FIELD_OFFSET(DIDEVICEOBJECTINSTANCEA, dwFFMaxForce)) return;
+    didoia->dwFFMaxForce = didoiw->dwFFMaxForce;
+    didoia->dwFFForceResolution = didoiw->dwFFForceResolution;
+    didoia->wCollectionNumber = didoiw->wCollectionNumber;
+    didoia->wDesignatorIndex = didoiw->wDesignatorIndex;
+    didoia->wUsagePage = didoiw->wUsagePage;
+    didoia->wUsage = didoiw->wUsage;
+    didoia->dwDimension = didoiw->dwDimension;
+    didoia->wExponent = didoiw->wExponent;
+    didoia->wReserved = didoiw->wReserved;
+}
+
+static void dideviceinstance_wtoa(const DIDEVICEINSTANCEW *didiw, DIDEVICEINSTANCEA *didia)
+{
+    didia->guidInstance = didiw->guidInstance;
+    didia->guidProduct = didiw->guidProduct;
+    didia->dwDevType = didiw->dwDevType;
+    WideCharToMultiByte(CP_ACP, 0, didiw->tszInstanceName, -1, didia->tszInstanceName, sizeof(didia->tszInstanceName), NULL, NULL);
+    WideCharToMultiByte(CP_ACP, 0, didiw->tszProductName, -1, didia->tszProductName, sizeof(didia->tszProductName), NULL, NULL);
+    if (didia->dwSize <= FIELD_OFFSET(DIDEVICEINSTANCEA, guidFFDriver)) return;
+    didia->guidFFDriver = didiw->guidFFDriver;
+    didia->wUsagePage = didiw->wUsagePage;
+    didia->wUsage = didiw->wUsage;
+}
+
+static void dieffectinfo_wtoa(const DIEFFECTINFOW *dieiw, DIEFFECTINFOA *dieia)
+{
+    dieia->guid = dieiw->guid;
+    dieia->dwEffType = dieiw->dwEffType;
+    dieia->dwStaticParams = dieiw->dwStaticParams;
+    dieia->dwDynamicParams = dieiw->dwDynamicParams;
+    WideCharToMultiByte(CP_ACP, 0, dieiw->tszName, -1, dieia->tszName, sizeof(dieia->tszName), NULL, NULL);
+}
+
+static WCHAR *string_atow(const char *str)
+{
+    WCHAR *strw;
+    int len;
+    if (!str) return NULL;
+    len = MultiByteToWideChar(CP_ACP, 0, str, -1, NULL, 0);
+    strw = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
+    MultiByteToWideChar(CP_ACP, 0, str, -1, strw, len);
+    return strw;
+}
+
+static void diactionformat_wtoa(const DIACTIONFORMATW *diafw, DIACTIONFORMATA *diafa)
+{
+    DWORD i;
+    if (diafa->dwActionSize != sizeof(DIACTIONA))
+    {
+        FIXME("Unsupported action format size\n");
+        return;
+    }
+    diafa->dwDataSize = diafw->dwDataSize;
+    diafa->dwNumActions = diafw->dwNumActions;
+    for (i = 0; i < diafw->dwNumActions; ++i)
+    {
+        diafa->rgoAction[i].uAppData = diafw->rgoAction[i].uAppData;
+        diafa->rgoAction[i].dwSemantic = diafw->rgoAction[i].dwSemantic;
+        diafa->rgoAction[i].dwFlags = diafw->rgoAction[i].dwFlags;
+        diafa->rgoAction[i].guidInstance = diafw->rgoAction[i].guidInstance;
+        diafa->rgoAction[i].dwObjID = diafw->rgoAction[i].dwObjID;
+        diafa->rgoAction[i].dwHow = diafw->rgoAction[i].dwHow;
+    }
+    diafa->guidActionMap = diafw->guidActionMap;
+    diafa->dwGenre = diafw->dwGenre;
+    diafa->dwBufferSize = diafw->dwBufferSize;
+    diafa->lAxisMin = diafw->lAxisMin;
+    diafa->lAxisMax = diafw->lAxisMax;
+    diafa->hInstString = diafw->hInstString;
+    diafa->ftTimeStamp = diafw->ftTimeStamp;
+    diafa->dwCRC = diafw->dwCRC;
+    WideCharToMultiByte(CP_ACP, 0, diafw->tszActionMap, -1, diafa->tszActionMap, sizeof(diafa->tszActionMap), NULL, NULL);
+}
+
+static void diactionformat_atow(const DIACTIONFORMATA *diafa, DIACTIONFORMATW *diafw)
+{
+    DWORD i;
+    if (diafa->dwActionSize != sizeof(DIACTIONA))
+    {
+        FIXME("Unsupported action format size\n");
+        return;
+    }
+    diafw->dwDataSize = diafa->dwDataSize;
+    diafw->dwNumActions = diafa->dwNumActions;
+    for (i = 0; i < diafw->dwNumActions; ++i)
+    {
+        diafw->rgoAction[i].uAppData = diafa->rgoAction[i].uAppData;
+        diafw->rgoAction[i].dwSemantic = diafa->rgoAction[i].dwSemantic;
+        diafw->rgoAction[i].dwFlags = diafa->rgoAction[i].dwFlags;
+        diafw->rgoAction[i].guidInstance = diafa->rgoAction[i].guidInstance;
+        diafw->rgoAction[i].dwObjID = diafa->rgoAction[i].dwObjID;
+        diafw->rgoAction[i].dwHow = diafa->rgoAction[i].dwHow;
+    }
+    diafw->guidActionMap = diafa->guidActionMap;
+    diafw->dwGenre = diafa->dwGenre;
+    diafw->dwBufferSize = diafa->dwBufferSize;
+    diafw->lAxisMin = diafa->lAxisMin;
+    diafw->lAxisMax = diafa->lAxisMax;
+    diafw->hInstString = diafa->hInstString;
+    diafw->ftTimeStamp = diafa->ftTimeStamp;
+    diafw->dwCRC = diafa->dwCRC;
+    MultiByteToWideChar(CP_ACP, 0, diafa->tszActionMap, -1, diafw->tszActionMap, sizeof(diafw->tszActionMap) / sizeof(WCHAR));
+}
+
+static void dideviceimageinfo_wtoa(const DIDEVICEIMAGEINFOW *didiiw, DIDEVICEIMAGEINFOA *didiia)
+{
+    WideCharToMultiByte(CP_ACP, 0, didiiw->tszImagePath, -1, didiia->tszImagePath, sizeof(didiia->tszImagePath), NULL, NULL);
+    didiia->dwFlags = didiiw->dwFlags;
+    didiia->dwViewID = didiiw->dwViewID;
+    didiia->rcOverlay = didiiw->rcOverlay;
+    didiia->dwObjID = didiiw->dwObjID;
+    didiia->dwcValidPts = didiiw->dwcValidPts;
+    didiia->rgptCalloutLine[0] = didiiw->rgptCalloutLine[0];
+    didiia->rgptCalloutLine[1] = didiiw->rgptCalloutLine[1];
+    didiia->rgptCalloutLine[2] = didiiw->rgptCalloutLine[2];
+    didiia->rgptCalloutLine[3] = didiiw->rgptCalloutLine[3];
+    didiia->rgptCalloutLine[4] = didiiw->rgptCalloutLine[4];
+    didiia->rcCalloutRect = didiiw->rcCalloutRect;
+    didiia->dwTextAlign = didiiw->dwTextAlign;
+}
+
+static void dideviceimageinfoheader_wtoa(const DIDEVICEIMAGEINFOHEADERW *didiihw, DIDEVICEIMAGEINFOHEADERA *didiiha)
+{
+    DWORD i;
+    didiiha->dwSizeImageInfo = didiihw->dwSizeImageInfo;
+    didiiha->dwcViews = didiihw->dwcViews;
+    didiiha->dwcButtons = didiihw->dwcButtons;
+    didiiha->dwcAxes = didiihw->dwcAxes;
+    didiiha->dwcPOVs = didiihw->dwcPOVs;
+    didiiha->dwBufferSize = didiihw->dwBufferSize;
+    didiiha->dwBufferUsed = didiihw->dwBufferUsed;
+    for (i = 0; i < didiihw->dwBufferUsed / didiihw->dwSizeImageInfo; ++i)
+        dideviceimageinfo_wtoa((const DIDEVICEIMAGEINFOW *)((const char *)didiihw->lprgImageInfoArray + i * didiihw->dwSizeImageInfo),
+                (DIDEVICEIMAGEINFOA *)((char *)didiiha->lprgImageInfoArray + i * didiiha->dwSizeImageInfo));
+    didiiha->dwBufferUsed = didiihw->dwBufferUsed / sizeof(DIDEVICEIMAGEINFOW) * sizeof(DIDEVICEIMAGEINFOA);
+}
+
+static HRESULT STDMETHODCALLTYPE direct_input_device_a_QueryInterface(IDirectInputDevice8A *iface, REFIID iid, void **out)
+{
+    IDirectInputDeviceImpl *This = impl_from_IDirectInputDevice8A(iface);
+    TRACE("iface %p, iid %s, out %p.\n", iface, debugstr_guid(iid), out);
+    return IDirectInputDevice8_QueryInterface(IDirectInputDevice8W_from_impl(This), iid, out);
+}
+
+static ULONG STDMETHODCALLTYPE direct_input_device_a_AddRef(IDirectInputDevice8A *iface)
+{
+    IDirectInputDeviceImpl *This = impl_from_IDirectInputDevice8A(iface);
+    TRACE("iface %p.\n", iface);
+    return IDirectInputDevice8_AddRef(IDirectInputDevice8W_from_impl(This));
+}
+
+static ULONG STDMETHODCALLTYPE direct_input_device_a_Release(IDirectInputDevice8A *iface)
+{
+    IDirectInputDeviceImpl *This = impl_from_IDirectInputDevice8A(iface);
+    TRACE("iface %p.\n", iface);
+    return IDirectInputDevice8_Release(IDirectInputDevice8W_from_impl(This));
+}
+
+static HRESULT STDMETHODCALLTYPE direct_input_device_a_GetCapabilities(IDirectInputDevice8A *iface, DIDEVCAPS *caps)
+{
+    IDirectInputDeviceImpl *This = impl_from_IDirectInputDevice8A(iface);
+    TRACE("iface %p, caps %p.\n", iface, caps);
+    return IDirectInputDevice8_GetCapabilities(IDirectInputDevice8W_from_impl(This), caps);
+}
+
+struct direct_input_device_a_enum_objects_params
+{
+    LPDIENUMDEVICEOBJECTSCALLBACKA callback;
+    void *ref;
+};
+
+static BOOL CALLBACK direct_input_device_a_enum_objects_callback(const DIDEVICEOBJECTINSTANCEW *didoiw, void *ref)
+{
+    struct direct_input_device_a_enum_objects_params *params = ref;
+    DIDEVICEOBJECTINSTANCEA didoia = {sizeof(didoia)};
+    dideviceobjectinstance_wtoa(didoiw, &didoia);
+    return params->callback(&didoia, params->ref);
+}
+
+static HRESULT STDMETHODCALLTYPE direct_input_device_a_EnumObjects(IDirectInputDevice8A *iface,
+        LPDIENUMDEVICEOBJECTSCALLBACKA callback, void *ref, DWORD flags)
+{
+    struct direct_input_device_a_enum_objects_params params = {callback, ref};
+    IDirectInputDeviceImpl *This = impl_from_IDirectInputDevice8A(iface);
+    TRACE("iface %p, callback %p, ref %p, flags %#x.\n", iface, callback, ref, flags);
+    if (!callback) return DIERR_INVALIDPARAM;
+    return IDirectInputDevice8_EnumObjects(IDirectInputDevice8W_from_impl(This),
+            direct_input_device_a_enum_objects_callback, &params, flags);
+}
+
+static HRESULT STDMETHODCALLTYPE direct_input_device_a_GetProperty(IDirectInputDevice8A *iface, REFGUID guid, DIPROPHEADER *diph)
+{
+    IDirectInputDeviceImpl *This = impl_from_IDirectInputDevice8A(iface);
+    TRACE("iface %p, guid %s, diph %p.\n", iface, debugstr_guid(guid), diph);
+    return IDirectInputDevice8_GetProperty(IDirectInputDevice8W_from_impl(This), guid, diph);
+}
+
+static HRESULT STDMETHODCALLTYPE direct_input_device_a_SetProperty(IDirectInputDevice8A *iface, REFGUID guid, const DIPROPHEADER *diph)
+{
+    IDirectInputDeviceImpl *This = impl_from_IDirectInputDevice8A(iface);
+    TRACE("iface %p, guid %s, diph %p.\n", iface, debugstr_guid(guid), diph);
+    return IDirectInputDevice8_SetProperty(IDirectInputDevice8W_from_impl(This), guid, diph);
+}
+
+static HRESULT STDMETHODCALLTYPE direct_input_device_a_Acquire(IDirectInputDevice8A *iface)
+{
+    IDirectInputDeviceImpl *This = impl_from_IDirectInputDevice8A(iface);
+    TRACE("iface %p.\n", iface);
+    return IDirectInputDevice8_Acquire(IDirectInputDevice8W_from_impl(This));
+}
+
+static HRESULT STDMETHODCALLTYPE direct_input_device_a_Unacquire(IDirectInputDevice8A *iface)
+{
+    IDirectInputDeviceImpl *This = impl_from_IDirectInputDevice8A(iface);
+    TRACE("iface %p.\n", iface);
+    return IDirectInputDevice8_Unacquire(IDirectInputDevice8W_from_impl(This));
+}
+
+static HRESULT STDMETHODCALLTYPE direct_input_device_a_GetDeviceData(IDirectInputDevice8A *iface, DWORD dodsize,
+        DIDEVICEOBJECTDATA *dod, DWORD *entries, DWORD flags)
+{
+    IDirectInputDeviceImpl *This = impl_from_IDirectInputDevice8A(iface);
+    TRACE("iface %p, dodsize %u, dod %p, flags %#x.\n", iface, dodsize, entries, flags);
+    return IDirectInputDevice8_GetDeviceData(IDirectInputDevice8W_from_impl(This), dodsize, dod, entries, flags);
+}
+
+static HRESULT STDMETHODCALLTYPE direct_input_device_a_GetDeviceState(IDirectInputDevice8A *iface, DWORD count, void *data)
+{
+    IDirectInputDeviceImpl *This = impl_from_IDirectInputDevice8A(iface);
+    TRACE("iface %p, count %u, data %p.\n", iface, count, data);
+    return IDirectInputDevice8_GetDeviceState(IDirectInputDevice8W_from_impl(This), count, data);
+}
+
+static HRESULT STDMETHODCALLTYPE direct_input_device_a_SetDataFormat(IDirectInputDevice8A *iface, const DIDATAFORMAT *didf)
+{
+    IDirectInputDeviceImpl *This = impl_from_IDirectInputDevice8A(iface);
+    TRACE("iface %p, didf %p.\n", iface, didf);
+    return IDirectInputDevice8_SetDataFormat(IDirectInputDevice8W_from_impl(This), didf);
+}
+
+static HRESULT STDMETHODCALLTYPE direct_input_device_a_SetEventNotification(IDirectInputDevice8A *iface, HANDLE event)
+{
+    IDirectInputDeviceImpl *This = impl_from_IDirectInputDevice8A(iface);
+    TRACE("iface %p, event %p.\n", iface, event);
+    return IDirectInputDevice8_SetEventNotification(IDirectInputDevice8W_from_impl(This), event);
+}
+
+static HRESULT STDMETHODCALLTYPE direct_input_device_a_SetCooperativeLevel(IDirectInputDevice8A *iface, HWND window, DWORD flags)
+{
+    IDirectInputDeviceImpl *This = impl_from_IDirectInputDevice8A(iface);
+    TRACE("iface %p, window %p, flags %#x.\n", iface, window, flags);
+    return IDirectInputDevice8_SetCooperativeLevel(IDirectInputDevice8W_from_impl(This), window, flags);
+}
+
+static HRESULT STDMETHODCALLTYPE direct_input_device_a_GetObjectInfo(IDirectInputDevice8A *iface,
+        DIDEVICEOBJECTINSTANCEA *didoi, DWORD obj, DWORD how)
+{
+    IDirectInputDeviceImpl *This = impl_from_IDirectInputDevice8A(iface);
+    DIDEVICEOBJECTINSTANCEW didoiw = {sizeof(didoiw)};
+    HRESULT hr;
+    TRACE("iface %p, didoi %p, obj %u, how %u.\n", iface, didoi, obj, how);
+    if (!didoi) return E_POINTER;
+    if (didoi->dwSize != sizeof(DIDEVICEOBJECTINSTANCEA) && didoi->dwSize != sizeof(DIDEVICEOBJECTINSTANCE_DX3A)) return DIERR_INVALIDPARAM;
+    hr = IDirectInputDevice8_GetObjectInfo(IDirectInputDevice8W_from_impl(This), &didoiw, obj, how);
+    dideviceobjectinstance_wtoa(&didoiw, didoi);
+    return hr;
+}
+
+static HRESULT STDMETHODCALLTYPE direct_input_device_a_GetDeviceInfo(IDirectInputDevice8A *iface, DIDEVICEINSTANCEA *didi)
+{
+    IDirectInputDeviceImpl *This = impl_from_IDirectInputDevice8A(iface);
+    DIDEVICEINSTANCEW didiw = {sizeof(didiw)};
+    HRESULT hr;
+    TRACE("iface %p, didoi %p.\n", iface, didi);
+    if (!didi) return E_POINTER;
+    if (didi->dwSize != sizeof(DIDEVICEINSTANCEA) && didi->dwSize != sizeof(DIDEVICEINSTANCE_DX3A)) return DIERR_INVALIDPARAM;
+    hr = IDirectInputDevice8_GetDeviceInfo(IDirectInputDevice8W_from_impl(This), &didiw);
+    dideviceinstance_wtoa(&didiw, didi);
+    return hr;
+}
+
+static HRESULT STDMETHODCALLTYPE direct_input_device_a_RunControlPanel(IDirectInputDevice8A *iface, HWND owner, DWORD flags)
+{
+    IDirectInputDeviceImpl *This = impl_from_IDirectInputDevice8A(iface);
+    TRACE("iface %p, owner %p, flags %#x.\n", iface, owner, flags);
+    return IDirectInputDevice8_RunControlPanel(IDirectInputDevice8W_from_impl(This), owner, flags);
+}
+
+static HRESULT STDMETHODCALLTYPE direct_input_device_a_Initialize(IDirectInputDevice8A *iface, HINSTANCE instance,
+        DWORD version, REFGUID guid)
+{
+    IDirectInputDeviceImpl *This = impl_from_IDirectInputDevice8A(iface);
+    TRACE("iface %p, instance %p, version %#x, guid %s.\n", iface, instance, version, debugstr_guid(guid));
+    return IDirectInputDevice8_Initialize(IDirectInputDevice8W_from_impl(This), instance, version, guid);
+}
+
+static HRESULT STDMETHODCALLTYPE direct_input_device_a_CreateEffect(IDirectInputDevice8A *iface, REFGUID guid,
+        const DIEFFECT *effect, LPDIRECTINPUTEFFECT *out, IUnknown *outer)
+{
+    IDirectInputDeviceImpl *This = impl_from_IDirectInputDevice8A(iface);
+    TRACE("iface %p, guid %s, effect %p, out %p, outer %p.\n", iface, debugstr_guid(guid), effect, out, outer);
+    return IDirectInputDevice8_CreateEffect(IDirectInputDevice8W_from_impl(This), guid, effect, out, outer);
+}
+
+struct direct_input_device_a_enum_effects_params
+{
+    LPDIENUMEFFECTSCALLBACKA callback;
+    void *ref;
+};
+
+static BOOL CALLBACK direct_input_device_a_enum_effects_callback(const DIEFFECTINFOW *dieiw, void *ref)
+{
+    struct direct_input_device_a_enum_effects_params *params = ref;
+    DIEFFECTINFOA dieia = {sizeof(dieia)};
+    dieffectinfo_wtoa(dieiw, &dieia);
+    return params->callback(&dieia, params->ref);
+}
+
+static HRESULT STDMETHODCALLTYPE direct_input_device_a_EnumEffects(IDirectInputDevice8A *iface,
+        LPDIENUMEFFECTSCALLBACKA callback, void *ref, DWORD type)
+{
+    struct direct_input_device_a_enum_effects_params params = {callback, ref};
+    IDirectInputDeviceImpl *This = impl_from_IDirectInputDevice8A(iface);
+    TRACE("iface %p, callback %p, ref %p, type %d.\n", iface, callback, ref, type);
+    if (!callback) return DIERR_INVALIDPARAM;
+    return IDirectInputDevice8_EnumEffects(IDirectInputDevice8W_from_impl(This),
+            direct_input_device_a_enum_effects_callback, &params, type);
+}
+
+static HRESULT STDMETHODCALLTYPE direct_input_device_a_GetEffectInfo(IDirectInputDevice8A *iface, DIEFFECTINFOA *diei, REFGUID guid)
+{
+    IDirectInputDeviceImpl *This = impl_from_IDirectInputDevice8A(iface);
+    DIEFFECTINFOW dieiw = {sizeof(dieiw)};
+    HRESULT hr;
+    TRACE("iface %p, diei %p, guid %s.\n", iface, diei, debugstr_guid(guid));
+    if (!diei) return E_POINTER;
+    if (diei->dwSize != sizeof(DIEFFECTINFOA)) return DIERR_INVALIDPARAM;
+    hr = IDirectInputDevice8_GetEffectInfo(IDirectInputDevice8W_from_impl(This), &dieiw, guid);
+    dieffectinfo_wtoa(&dieiw, diei);
+    return hr;
+}
+
+static HRESULT STDMETHODCALLTYPE direct_input_device_a_GetForceFeedbackState(IDirectInputDevice8A *iface, DWORD *state)
+{
+    IDirectInputDeviceImpl *This = impl_from_IDirectInputDevice8A(iface);
+    TRACE("iface %p, state %p.\n", iface, state);
+    return IDirectInputDevice8_GetForceFeedbackState(IDirectInputDevice8W_from_impl(This), state);
+}
+
+static HRESULT STDMETHODCALLTYPE direct_input_device_a_SendForceFeedbackCommand(IDirectInputDevice8A *iface, DWORD flags)
+{
+    IDirectInputDeviceImpl *This = impl_from_IDirectInputDevice8A(iface);
+    TRACE("iface %p, flags %#x.\n", iface, flags);
+    return IDirectInputDevice8_SendForceFeedbackCommand(IDirectInputDevice8W_from_impl(This), flags);
+}
+
+static HRESULT STDMETHODCALLTYPE direct_input_device_a_EnumCreatedEffectObjects(IDirectInputDevice8A *iface,
+        LPDIENUMCREATEDEFFECTOBJECTSCALLBACK callback, void *ref, DWORD flags)
+{
+    IDirectInputDeviceImpl *This = impl_from_IDirectInputDevice8A(iface);
+    TRACE("iface %p, callback %p, ref %p, flags %#x.\n", iface, callback, ref, flags);
+    return IDirectInputDevice8_EnumCreatedEffectObjects(IDirectInputDevice8W_from_impl(This), callback, ref, flags);
+}
+
+static HRESULT STDMETHODCALLTYPE direct_input_device_a_Escape(IDirectInputDevice8A *iface, DIEFFESCAPE *escape)
+{
+    IDirectInputDeviceImpl *This = impl_from_IDirectInputDevice8A(iface);
+    TRACE("iface %p, escape %p.\n", iface, escape);
+    return IDirectInputDevice8_Escape(IDirectInputDevice8W_from_impl(This), escape);
+}
+
+static HRESULT STDMETHODCALLTYPE direct_input_device_a_Poll(IDirectInputDevice8A *iface)
+{
+    IDirectInputDeviceImpl *This = impl_from_IDirectInputDevice8A(iface);
+    TRACE("iface %p.\n", iface);
+    return IDirectInputDevice8_Poll(IDirectInputDevice8W_from_impl(This));
+}
+
+static HRESULT STDMETHODCALLTYPE direct_input_device_a_SendDeviceData(IDirectInputDevice8A *iface, DWORD count,
+        const DIDEVICEOBJECTDATA *didod, DWORD *inout, DWORD flags)
+{
+    IDirectInputDeviceImpl *This = impl_from_IDirectInputDevice8A(iface);
+    TRACE("iface %p, count %u, didod %p, inout %p, flags %#x.\n", iface, count, didod, inout, flags);
+    return IDirectInputDevice8_SendDeviceData(IDirectInputDevice8W_from_impl(This), count, didod, inout, flags);
+}
+
+static HRESULT STDMETHODCALLTYPE direct_input_device_a_EnumEffectsInFile(IDirectInputDevice8A *iface,
+        const char *filename, LPDIENUMEFFECTSINFILECALLBACK callback, void *ref, DWORD flags)
+{
+    IDirectInputDeviceImpl *This = impl_from_IDirectInputDevice8A(iface);
+    WCHAR buffer[MAX_PATH], *filenamew = buffer;
+    TRACE("iface %p, filename %s, callback %p, ref %p, flags %#x.\n", iface, debugstr_a(filename), callback, ref, flags);
+    if (!filename) filenamew = NULL;
+    else MultiByteToWideChar(CP_ACP, 0, filename, -1, buffer, MAX_PATH);
+    return IDirectInputDevice8_EnumEffectsInFile(IDirectInputDevice8W_from_impl(This), filenamew, callback, ref, flags);
+}
+
+static HRESULT STDMETHODCALLTYPE direct_input_device_a_WriteEffectToFile(IDirectInputDevice8A *iface,
+        const char *filename, DWORD entries, DIFILEEFFECT *dife, DWORD flags)
+{
+    IDirectInputDeviceImpl *This = impl_from_IDirectInputDevice8A(iface);
+    WCHAR buffer[MAX_PATH], *filenamew = buffer;
+    TRACE("iface %p, filename %s, entries %u, dife %p, flags %#x.\n", iface, debugstr_a(filename), entries, dife, flags);
+    if (!filename) filenamew = NULL;
+    else MultiByteToWideChar(CP_ACP, 0, filename, -1, buffer, MAX_PATH);
+    return IDirectInputDevice8_WriteEffectToFile(IDirectInputDevice8W_from_impl(This), filenamew, entries, dife, flags);
+}
+
+static HRESULT STDMETHODCALLTYPE direct_input_device_a_BuildActionMap(IDirectInputDevice8A *iface,
+        DIACTIONFORMATA *diaf, const char *username, DWORD flags)
+{
+    IDirectInputDeviceImpl *This = impl_from_IDirectInputDevice8A(iface);
+    DIACTIONFORMATW diafw = {sizeof(diafw), sizeof(DIACTIONW)};
+    HRESULT hr;
+    WCHAR *usernamew = string_atow(username);
+    TRACE("iface %p, diaf %p, username %s, flags %#x.\n", iface, diaf, debugstr_a(username), flags);
+    if (!diaf) return E_POINTER;
+    if (diaf->dwSize != sizeof(DIACTIONFORMATA)) return DIERR_INVALIDPARAM;
+    if (diaf->dwActionSize != sizeof(DIACTIONA)) return DIERR_INVALIDPARAM;
+    diafw.dwNumActions = diaf->dwNumActions;
+    diafw.rgoAction = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, diaf->dwNumActions * sizeof(DIACTIONW));
+    diactionformat_atow(diaf, &diafw);
+    hr = IDirectInputDevice8_BuildActionMap(IDirectInputDevice8W_from_impl(This), &diafw, usernamew, flags);
+    diactionformat_wtoa(&diafw, diaf);
+    HeapFree(GetProcessHeap(), 0, diafw.rgoAction);
+    HeapFree(GetProcessHeap(), 0, usernamew);
+    return hr;
+}
+
+static HRESULT STDMETHODCALLTYPE direct_input_device_a_SetActionMap(IDirectInputDevice8A *iface, DIACTIONFORMATA *diaf,
+        const char *username, DWORD flags)
+{
+    IDirectInputDeviceImpl *This = impl_from_IDirectInputDevice8A(iface);
+    DIACTIONFORMATW diafw = {sizeof(diafw), sizeof(DIACTIONW)};
+    HRESULT hr;
+    WCHAR *usernamew = string_atow(username);
+    TRACE("iface %p, diaf %p, username %s, flags %#x.\n", iface, diaf, debugstr_a(username), flags);
+    if (!diaf) return E_POINTER;
+    if (diaf->dwSize != sizeof(DIACTIONFORMATA)) return DIERR_INVALIDPARAM;
+    if (diaf->dwActionSize != sizeof(DIACTIONA)) return DIERR_INVALIDPARAM;
+    diafw.dwNumActions = diaf->dwNumActions;
+    diafw.rgoAction = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, diaf->dwNumActions * sizeof(DIACTIONW));
+    diactionformat_atow(diaf, &diafw);
+    hr = IDirectInputDevice8_SetActionMap(IDirectInputDevice8W_from_impl(This), &diafw, usernamew, flags);
+    diactionformat_wtoa(&diafw, diaf);
+    HeapFree(GetProcessHeap(), 0, diafw.rgoAction);
+    HeapFree(GetProcessHeap(), 0, usernamew);
+    return hr;
+}
+
+static HRESULT STDMETHODCALLTYPE direct_input_device_a_GetImageInfo(IDirectInputDevice8A *iface, DIDEVICEIMAGEINFOHEADERA *didiih)
+{
+    IDirectInputDeviceImpl *This = impl_from_IDirectInputDevice8A(iface);
+    DIDEVICEIMAGEINFOHEADERW didiihw = {sizeof(didiihw), sizeof(DIDEVICEIMAGEINFOW)};
+    HRESULT hr;
+    TRACE("iface %p, didiih %p.\n", iface, didiih);
+    if (!didiih) return E_POINTER;
+    if (didiih->dwSize != sizeof(DIDEVICEIMAGEINFOHEADERA)) return DIERR_INVALIDPARAM;
+    if (didiih->dwSizeImageInfo != sizeof(DIDEVICEIMAGEINFOA)) return DIERR_INVALIDPARAM;
+    didiihw.dwBufferSize = didiih->dwBufferSize / didiih->dwSizeImageInfo * didiihw.dwSizeImageInfo;
+    didiihw.lprgImageInfoArray = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, didiihw.dwBufferSize);
+    if (!didiihw.lprgImageInfoArray) return E_OUTOFMEMORY;
+    hr = IDirectInputDevice8_GetImageInfo(IDirectInputDevice8W_from_impl(This), &didiihw);
+    dideviceimageinfoheader_wtoa(&didiihw, didiih);
+    HeapFree(GetProcessHeap(), 0, didiihw.lprgImageInfoArray);
+    return hr;
+}
+
+const IDirectInputDevice8AVtbl direct_input_device_a_vtbl =
+{
+    /*** IUnknown methods ***/
+    direct_input_device_a_QueryInterface,
+    direct_input_device_a_AddRef,
+    direct_input_device_a_Release,
+    /*** IDirectInputDeviceA methods ***/
+    direct_input_device_a_GetCapabilities,
+    direct_input_device_a_EnumObjects,
+    direct_input_device_a_GetProperty,
+    direct_input_device_a_SetProperty,
+    direct_input_device_a_Acquire,
+    direct_input_device_a_Unacquire,
+    direct_input_device_a_GetDeviceState,
+    direct_input_device_a_GetDeviceData,
+    direct_input_device_a_SetDataFormat,
+    direct_input_device_a_SetEventNotification,
+    direct_input_device_a_SetCooperativeLevel,
+    direct_input_device_a_GetObjectInfo,
+    direct_input_device_a_GetDeviceInfo,
+    direct_input_device_a_RunControlPanel,
+    direct_input_device_a_Initialize,
+    /*** IDirectInputDevice2A methods ***/
+    direct_input_device_a_CreateEffect,
+    direct_input_device_a_EnumEffects,
+    direct_input_device_a_GetEffectInfo,
+    direct_input_device_a_GetForceFeedbackState,
+    direct_input_device_a_SendForceFeedbackCommand,
+    direct_input_device_a_EnumCreatedEffectObjects,
+    direct_input_device_a_Escape,
+    direct_input_device_a_Poll,
+    direct_input_device_a_SendDeviceData,
+    /*** IDirectInputDevice7A methods ***/
+    direct_input_device_a_EnumEffectsInFile,
+    direct_input_device_a_WriteEffectToFile,
+    /*** IDirectInputDevice8A methods ***/
+    direct_input_device_a_BuildActionMap,
+    direct_input_device_a_SetActionMap,
+    direct_input_device_a_GetImageInfo
+};
diff --git a/dlls/dinput/device.c b/dlls/dinput/device.c
index 0c8d7445b08..c3052aa4319 100644
--- a/dlls/dinput/device.c
+++ b/dlls/dinput/device.c
@@ -28,6 +28,7 @@
 
 #include <stdarg.h>
 #include <string.h>
+#include <assert.h>
 #include "wine/debug.h"
 #include "wine/unicode.h"
 #include "windef.h"
@@ -1009,13 +1010,6 @@ HRESULT WINAPI IDirectInputDevice2WImpl_Acquire(LPDIRECTINPUTDEVICE8W iface)
     return res;
 }
 
-HRESULT WINAPI IDirectInputDevice2AImpl_Acquire(LPDIRECTINPUTDEVICE8A iface)
-{
-    IDirectInputDeviceImpl *This = impl_from_IDirectInputDevice8A(iface);
-    return IDirectInputDevice2WImpl_Acquire(IDirectInputDevice8W_from_impl(This));
-}
-
-
 /******************************************************************************
  *	Unacquire
  */
@@ -1039,12 +1033,6 @@ HRESULT WINAPI IDirectInputDevice2WImpl_Unacquire(LPDIRECTINPUTDEVICE8W iface)
     return res;
 }
 
-HRESULT WINAPI IDirectInputDevice2AImpl_Unacquire(LPDIRECTINPUTDEVICE8A iface)
-{
-    IDirectInputDeviceImpl *This = impl_from_IDirectInputDevice8A(iface);
-    return IDirectInputDevice2WImpl_Unacquire(IDirectInputDevice8W_from_impl(This));
-}
-
 /******************************************************************************
  *	IDirectInputDeviceA
  */
@@ -1070,12 +1058,6 @@ HRESULT WINAPI IDirectInputDevice2WImpl_SetDataFormat(LPDIRECTINPUTDEVICE8W ifac
     return res;
 }
 
-HRESULT WINAPI IDirectInputDevice2AImpl_SetDataFormat(LPDIRECTINPUTDEVICE8A iface, LPCDIDATAFORMAT df)
-{
-    IDirectInputDeviceImpl *This = impl_from_IDirectInputDevice8A(iface);
-    return IDirectInputDevice2WImpl_SetDataFormat(IDirectInputDevice8W_from_impl(This), df);
-}
-
 /******************************************************************************
   *     SetCooperativeLevel
   *
@@ -1117,12 +1099,6 @@ HRESULT WINAPI IDirectInputDevice2WImpl_SetCooperativeLevel(LPDIRECTINPUTDEVICE8
     return DI_OK;
 }
 
-HRESULT WINAPI IDirectInputDevice2AImpl_SetCooperativeLevel(LPDIRECTINPUTDEVICE8A iface, HWND hwnd, DWORD dwflags)
-{
-    IDirectInputDeviceImpl *This = impl_from_IDirectInputDevice8A(iface);
-    return IDirectInputDevice2WImpl_SetCooperativeLevel(IDirectInputDevice8W_from_impl(This), hwnd, dwflags);
-}
-
 /******************************************************************************
   *     SetEventNotification : specifies event to be sent on state change
   */
@@ -1138,12 +1114,6 @@ HRESULT WINAPI IDirectInputDevice2WImpl_SetEventNotification(LPDIRECTINPUTDEVICE
     return DI_OK;
 }
 
-HRESULT WINAPI IDirectInputDevice2AImpl_SetEventNotification(LPDIRECTINPUTDEVICE8A iface, HANDLE event)
-{
-    IDirectInputDeviceImpl *This = impl_from_IDirectInputDevice8A(iface);
-    return IDirectInputDevice2WImpl_SetEventNotification(IDirectInputDevice8W_from_impl(This), event);
-}
-
 
 ULONG WINAPI IDirectInputDevice2WImpl_Release(LPDIRECTINPUTDEVICE8W iface)
 {
@@ -1177,12 +1147,6 @@ ULONG WINAPI IDirectInputDevice2WImpl_Release(LPDIRECTINPUTDEVICE8W iface)
     return ref;
 }
 
-ULONG WINAPI IDirectInputDevice2AImpl_Release(LPDIRECTINPUTDEVICE8A iface)
-{
-    IDirectInputDeviceImpl *This = impl_from_IDirectInputDevice8A(iface);
-    return IDirectInputDevice2WImpl_Release(IDirectInputDevice8W_from_impl(This));
-}
-
 HRESULT WINAPI IDirectInputDevice2WImpl_QueryInterface(LPDIRECTINPUTDEVICE8W iface, REFIID riid, LPVOID *ppobj)
 {
     IDirectInputDeviceImpl *This = impl_from_IDirectInputDevice8W(iface);
@@ -1212,12 +1176,6 @@ HRESULT WINAPI IDirectInputDevice2WImpl_QueryInterface(LPDIRECTINPUTDEVICE8W ifa
     return E_NOINTERFACE;
 }
 
-HRESULT WINAPI IDirectInputDevice2AImpl_QueryInterface(LPDIRECTINPUTDEVICE8A iface, REFIID riid, LPVOID *ppobj)
-{
-    IDirectInputDeviceImpl *This = impl_from_IDirectInputDevice8A(iface);
-    return IDirectInputDevice2WImpl_QueryInterface(IDirectInputDevice8W_from_impl(This), riid, ppobj);
-}
-
 ULONG WINAPI IDirectInputDevice2WImpl_AddRef(LPDIRECTINPUTDEVICE8W iface)
 {
     IDirectInputDeviceImpl *This = impl_from_IDirectInputDevice8W(iface);
@@ -1226,42 +1184,6 @@ ULONG WINAPI IDirectInputDevice2WImpl_AddRef(LPDIRECTINPUTDEVICE8W iface)
     return ref;
 }
 
-ULONG WINAPI IDirectInputDevice2AImpl_AddRef(LPDIRECTINPUTDEVICE8A iface)
-{
-    IDirectInputDeviceImpl *This = impl_from_IDirectInputDevice8A(iface);
-    return IDirectInputDevice2WImpl_AddRef(IDirectInputDevice8W_from_impl(This));
-}
-
-HRESULT WINAPI IDirectInputDevice2AImpl_EnumObjects(LPDIRECTINPUTDEVICE8A iface,
-        LPDIENUMDEVICEOBJECTSCALLBACKA lpCallback, LPVOID lpvRef, DWORD dwFlags)
-{
-    IDirectInputDeviceImpl *This = impl_from_IDirectInputDevice8A(iface);
-    DIDEVICEOBJECTINSTANCEA ddoi;
-    int i;
-
-    TRACE("(%p)->(%p,%p flags:%08x)\n", This, lpCallback, lpvRef, dwFlags);
-    TRACE("  - flags = ");
-    _dump_EnumObjects_flags(dwFlags);
-    TRACE("\n");
-
-    /* Only the fields till dwFFMaxForce are relevant */
-    memset(&ddoi, 0, sizeof(ddoi));
-    ddoi.dwSize = FIELD_OFFSET(DIDEVICEOBJECTINSTANCEA, dwFFMaxForce);
-
-    for (i = 0; i < This->data_format.wine_df->dwNumObjs; i++)
-    {
-        LPDIOBJECTDATAFORMAT odf = dataformat_to_odf(This->data_format.wine_df, i);
-
-        if (dwFlags != DIDFT_ALL && !(dwFlags & DIDFT_GETTYPE(odf->dwType))) continue;
-        if (IDirectInputDevice_GetObjectInfo(iface, &ddoi, odf->dwType, DIPH_BYID) != DI_OK)
-            continue;
-
-	if (lpCallback(&ddoi, lpvRef) != DIENUM_CONTINUE) break;
-    }
-
-    return DI_OK;
-}
-
 HRESULT WINAPI IDirectInputDevice2WImpl_EnumObjects(LPDIRECTINPUTDEVICE8W iface,
         LPDIENUMDEVICEOBJECTSCALLBACKW lpCallback, LPVOID lpvRef, DWORD dwFlags)
 {
@@ -1350,12 +1272,6 @@ HRESULT WINAPI IDirectInputDevice2WImpl_GetProperty(LPDIRECTINPUTDEVICE8W iface,
     return DI_OK;
 }
 
-HRESULT WINAPI IDirectInputDevice2AImpl_GetProperty(LPDIRECTINPUTDEVICE8A iface, REFGUID rguid, LPDIPROPHEADER pdiph)
-{
-    IDirectInputDeviceImpl *This = impl_from_IDirectInputDevice8A(iface);
-    return IDirectInputDevice2WImpl_GetProperty(IDirectInputDevice8W_from_impl(This), rguid, pdiph);
-}
-
 /******************************************************************************
  *	SetProperty
  */
@@ -1449,45 +1365,6 @@ HRESULT WINAPI IDirectInputDevice2WImpl_SetProperty(
     return DI_OK;
 }
 
-HRESULT WINAPI IDirectInputDevice2AImpl_SetProperty(
-        LPDIRECTINPUTDEVICE8A iface, REFGUID rguid, LPCDIPROPHEADER pdiph)
-{
-    IDirectInputDeviceImpl *This = impl_from_IDirectInputDevice8A(iface);
-    return IDirectInputDevice2WImpl_SetProperty(IDirectInputDevice8W_from_impl(This), rguid, pdiph);
-}
-
-HRESULT WINAPI IDirectInputDevice2AImpl_GetObjectInfo(
-	LPDIRECTINPUTDEVICE8A iface,
-	LPDIDEVICEOBJECTINSTANCEA pdidoi,
-	DWORD dwObj,
-	DWORD dwHow)
-{
-    IDirectInputDeviceImpl *This = impl_from_IDirectInputDevice8A(iface);
-    DIDEVICEOBJECTINSTANCEW didoiW;
-    HRESULT res;
-
-    if (!pdidoi ||
-        (pdidoi->dwSize != sizeof(DIDEVICEOBJECTINSTANCEA) &&
-         pdidoi->dwSize != sizeof(DIDEVICEOBJECTINSTANCE_DX3A)))
-        return DIERR_INVALIDPARAM;
-
-    didoiW.dwSize = sizeof(didoiW);
-    res = IDirectInputDevice2WImpl_GetObjectInfo(IDirectInputDevice8W_from_impl(This), &didoiW, dwObj, dwHow);
-    if (res == DI_OK)
-    {
-        DWORD dwSize = pdidoi->dwSize;
-
-        memset(pdidoi, 0, pdidoi->dwSize);
-        pdidoi->dwSize   = dwSize;
-        pdidoi->guidType = didoiW.guidType;
-        pdidoi->dwOfs    = didoiW.dwOfs;
-        pdidoi->dwType   = didoiW.dwType;
-        pdidoi->dwFlags  = didoiW.dwFlags;
-    }
-
-    return res;
-}
-
 HRESULT WINAPI IDirectInputDevice2WImpl_GetObjectInfo(
 	LPDIRECTINPUTDEVICE8W iface,
 	LPDIDEVICEOBJECTINSTANCEW pdidoi,
@@ -1597,13 +1474,6 @@ HRESULT WINAPI IDirectInputDevice2WImpl_GetDeviceData(LPDIRECTINPUTDEVICE8W ifac
     return ret;
 }
 
-HRESULT WINAPI IDirectInputDevice2AImpl_GetDeviceData(LPDIRECTINPUTDEVICE8A iface, DWORD dodsize,
-                                                      LPDIDEVICEOBJECTDATA dod, LPDWORD entries, DWORD flags)
-{
-    IDirectInputDeviceImpl *This = impl_from_IDirectInputDevice8A(iface);
-    return IDirectInputDevice2WImpl_GetDeviceData(IDirectInputDevice8W_from_impl(This), dodsize, dod, entries, flags);
-}
-
 HRESULT WINAPI IDirectInputDevice2WImpl_RunControlPanel(LPDIRECTINPUTDEVICE8W iface, HWND hwndOwner, DWORD dwFlags)
 {
     IDirectInputDeviceImpl *This = impl_from_IDirectInputDevice8W(iface);
@@ -1612,12 +1482,6 @@ HRESULT WINAPI IDirectInputDevice2WImpl_RunControlPanel(LPDIRECTINPUTDEVICE8W if
     return DI_OK;
 }
 
-HRESULT WINAPI IDirectInputDevice2AImpl_RunControlPanel(LPDIRECTINPUTDEVICE8A iface, HWND hwndOwner, DWORD dwFlags)
-{
-    IDirectInputDeviceImpl *This = impl_from_IDirectInputDevice8A(iface);
-    return IDirectInputDevice2WImpl_RunControlPanel(IDirectInputDevice8W_from_impl(This), hwndOwner, dwFlags);
-}
-
 HRESULT WINAPI IDirectInputDevice2WImpl_Initialize(LPDIRECTINPUTDEVICE8W iface, HINSTANCE hinst, DWORD dwVersion,
                                                    REFGUID rguid)
 {
@@ -1626,13 +1490,6 @@ HRESULT WINAPI IDirectInputDevice2WImpl_Initialize(LPDIRECTINPUTDEVICE8W iface,
     return DI_OK;
 }
 
-HRESULT WINAPI IDirectInputDevice2AImpl_Initialize(LPDIRECTINPUTDEVICE8A iface, HINSTANCE hinst, DWORD dwVersion,
-                                                   REFGUID rguid)
-{
-    IDirectInputDeviceImpl *This = impl_from_IDirectInputDevice8A(iface);
-    return IDirectInputDevice2WImpl_Initialize(IDirectInputDevice8W_from_impl(This), hinst, dwVersion, rguid);
-}
-
 /******************************************************************************
  *	IDirectInputDevice2A
  */
@@ -1648,25 +1505,6 @@ HRESULT WINAPI IDirectInputDevice2WImpl_CreateEffect(LPDIRECTINPUTDEVICE8W iface
     return DIERR_UNSUPPORTED;
 }
 
-HRESULT WINAPI IDirectInputDevice2AImpl_CreateEffect(LPDIRECTINPUTDEVICE8A iface, REFGUID rguid, LPCDIEFFECT lpeff,
-                                                     LPDIRECTINPUTEFFECT *ppdef, LPUNKNOWN pUnkOuter)
-{
-    IDirectInputDeviceImpl *This = impl_from_IDirectInputDevice8A(iface);
-    return IDirectInputDevice2WImpl_CreateEffect(IDirectInputDevice8W_from_impl(This), rguid, lpeff, ppdef, pUnkOuter);
-}
-
-HRESULT WINAPI IDirectInputDevice2AImpl_EnumEffects(
-	LPDIRECTINPUTDEVICE8A iface,
-	LPDIENUMEFFECTSCALLBACKA lpCallback,
-	LPVOID lpvRef,
-	DWORD dwFlags)
-{
-    IDirectInputDeviceImpl *This = impl_from_IDirectInputDevice8A(iface);
-    FIXME("%p)->(%p,%p,0x%08x): stub!\n", This, lpCallback, lpvRef, dwFlags);
-
-    return DI_OK;
-}
-
 HRESULT WINAPI IDirectInputDevice2WImpl_EnumEffects(
 	LPDIRECTINPUTDEVICE8W iface,
 	LPDIENUMEFFECTSCALLBACKW lpCallback,
@@ -1679,16 +1517,6 @@ HRESULT WINAPI IDirectInputDevice2WImpl_EnumEffects(
     return DI_OK;
 }
 
-HRESULT WINAPI IDirectInputDevice2AImpl_GetEffectInfo(
-	LPDIRECTINPUTDEVICE8A iface,
-	LPDIEFFECTINFOA lpdei,
-	REFGUID rguid)
-{
-    IDirectInputDeviceImpl *This = impl_from_IDirectInputDevice8A(iface);
-    FIXME("(%p)->(%p,%s): stub!\n", This, lpdei, debugstr_guid(rguid));
-    return DI_OK;
-}
-
 HRESULT WINAPI IDirectInputDevice2WImpl_GetEffectInfo(
 	LPDIRECTINPUTDEVICE8W iface,
 	LPDIEFFECTINFOW lpdei,
@@ -1706,12 +1534,6 @@ HRESULT WINAPI IDirectInputDevice2WImpl_GetForceFeedbackState(LPDIRECTINPUTDEVIC
     return DI_OK;
 }
 
-HRESULT WINAPI IDirectInputDevice2AImpl_GetForceFeedbackState(LPDIRECTINPUTDEVICE8A iface, LPDWORD pdwOut)
-{
-    IDirectInputDeviceImpl *This = impl_from_IDirectInputDevice8A(iface);
-    return IDirectInputDevice2WImpl_GetForceFeedbackState(IDirectInputDevice8W_from_impl(This), pdwOut);
-}
-
 HRESULT WINAPI IDirectInputDevice2WImpl_SendForceFeedbackCommand(LPDIRECTINPUTDEVICE8W iface, DWORD dwFlags)
 {
     IDirectInputDeviceImpl *This = impl_from_IDirectInputDevice8W(iface);
@@ -1719,12 +1541,6 @@ HRESULT WINAPI IDirectInputDevice2WImpl_SendForceFeedbackCommand(LPDIRECTINPUTDE
     return DI_NOEFFECT;
 }
 
-HRESULT WINAPI IDirectInputDevice2AImpl_SendForceFeedbackCommand(LPDIRECTINPUTDEVICE8A iface, DWORD dwFlags)
-{
-    IDirectInputDeviceImpl *This = impl_from_IDirectInputDevice8A(iface);
-    return IDirectInputDevice2WImpl_SendForceFeedbackCommand(IDirectInputDevice8W_from_impl(This), dwFlags);
-}
-
 HRESULT WINAPI IDirectInputDevice2WImpl_EnumCreatedEffectObjects(LPDIRECTINPUTDEVICE8W iface,
         LPDIENUMCREATEDEFFECTOBJECTSCALLBACK lpCallback, LPVOID lpvRef, DWORD dwFlags)
 {
@@ -1733,13 +1549,6 @@ HRESULT WINAPI IDirectInputDevice2WImpl_EnumCreatedEffectObjects(LPDIRECTINPUTDE
     return DI_OK;
 }
 
-HRESULT WINAPI IDirectInputDevice2AImpl_EnumCreatedEffectObjects(LPDIRECTINPUTDEVICE8A iface,
-        LPDIENUMCREATEDEFFECTOBJECTSCALLBACK lpCallback, LPVOID lpvRef, DWORD dwFlags)
-{
-    IDirectInputDeviceImpl *This = impl_from_IDirectInputDevice8A(iface);
-    return IDirectInputDevice2WImpl_EnumCreatedEffectObjects(IDirectInputDevice8W_from_impl(This), lpCallback, lpvRef, dwFlags);
-}
-
 HRESULT WINAPI IDirectInputDevice2WImpl_Escape(LPDIRECTINPUTDEVICE8W iface, LPDIEFFESCAPE lpDIEEsc)
 {
     IDirectInputDeviceImpl *This = impl_from_IDirectInputDevice8W(iface);
@@ -1747,12 +1556,6 @@ HRESULT WINAPI IDirectInputDevice2WImpl_Escape(LPDIRECTINPUTDEVICE8W iface, LPDI
     return DI_OK;
 }
 
-HRESULT WINAPI IDirectInputDevice2AImpl_Escape(LPDIRECTINPUTDEVICE8A iface, LPDIEFFESCAPE lpDIEEsc)
-{
-    IDirectInputDeviceImpl *This = impl_from_IDirectInputDevice8A(iface);
-    return IDirectInputDevice2WImpl_Escape(IDirectInputDevice8W_from_impl(This), lpDIEEsc);
-}
-
 HRESULT WINAPI IDirectInputDevice2WImpl_Poll(LPDIRECTINPUTDEVICE8W iface)
 {
     IDirectInputDeviceImpl *This = impl_from_IDirectInputDevice8W(iface);
@@ -1763,12 +1566,6 @@ HRESULT WINAPI IDirectInputDevice2WImpl_Poll(LPDIRECTINPUTDEVICE8W iface)
     return DI_OK;
 }
 
-HRESULT WINAPI IDirectInputDevice2AImpl_Poll(LPDIRECTINPUTDEVICE8A iface)
-{
-    IDirectInputDeviceImpl *This = impl_from_IDirectInputDevice8A(iface);
-    return IDirectInputDevice2WImpl_Poll(IDirectInputDevice8W_from_impl(This));
-}
-
 HRESULT WINAPI IDirectInputDevice2WImpl_SendDeviceData(LPDIRECTINPUTDEVICE8W iface, DWORD cbObjectData,
                                                        LPCDIDEVICEOBJECTDATA rgdod, LPDWORD pdwInOut,
                                                        DWORD dwFlags)
@@ -1779,27 +1576,6 @@ HRESULT WINAPI IDirectInputDevice2WImpl_SendDeviceData(LPDIRECTINPUTDEVICE8W ifa
     return DI_OK;
 }
 
-HRESULT WINAPI IDirectInputDevice2AImpl_SendDeviceData(LPDIRECTINPUTDEVICE8A iface, DWORD cbObjectData,
-                                                       LPCDIDEVICEOBJECTDATA rgdod, LPDWORD pdwInOut,
-                                                       DWORD dwFlags)
-{
-    IDirectInputDeviceImpl *This = impl_from_IDirectInputDevice8A(iface);
-    return IDirectInputDevice2WImpl_SendDeviceData(IDirectInputDevice8W_from_impl(This), cbObjectData, rgdod,
-                                                   pdwInOut, dwFlags);
-}
-
-HRESULT WINAPI IDirectInputDevice7AImpl_EnumEffectsInFile(LPDIRECTINPUTDEVICE8A iface,
-							  LPCSTR lpszFileName,
-							  LPDIENUMEFFECTSINFILECALLBACK pec,
-							  LPVOID pvRef,
-							  DWORD dwFlags)
-{
-    IDirectInputDeviceImpl *This = impl_from_IDirectInputDevice8A(iface);
-    FIXME("(%p)->(%s,%p,%p,%08x): stub !\n", This, lpszFileName, pec, pvRef, dwFlags);
-    
-    return DI_OK;
-}
-
 HRESULT WINAPI IDirectInputDevice7WImpl_EnumEffectsInFile(LPDIRECTINPUTDEVICE8W iface,
 							  LPCWSTR lpszFileName,
 							  LPDIENUMEFFECTSINFILECALLBACK pec,
@@ -1812,18 +1588,6 @@ HRESULT WINAPI IDirectInputDevice7WImpl_EnumEffectsInFile(LPDIRECTINPUTDEVICE8W
     return DI_OK;
 }
 
-HRESULT WINAPI IDirectInputDevice7AImpl_WriteEffectToFile(LPDIRECTINPUTDEVICE8A iface,
-							  LPCSTR lpszFileName,
-							  DWORD dwEntries,
-							  LPDIFILEEFFECT rgDiFileEft,
-							  DWORD dwFlags)
-{
-    IDirectInputDeviceImpl *This = impl_from_IDirectInputDevice8A(iface);
-    FIXME("(%p)->(%s,%08x,%p,%08x): stub !\n", This, lpszFileName, dwEntries, rgDiFileEft, dwFlags);
-    
-    return DI_OK;
-}
-
 HRESULT WINAPI IDirectInputDevice7WImpl_WriteEffectToFile(LPDIRECTINPUTDEVICE8W iface,
 							  LPCWSTR lpszFileName,
 							  DWORD dwEntries,
@@ -1853,15 +1617,6 @@ HRESULT WINAPI IDirectInputDevice8WImpl_BuildActionMap(LPDIRECTINPUTDEVICE8W ifa
     return DI_OK;
 }
 
-HRESULT WINAPI IDirectInputDevice8AImpl_GetImageInfo(LPDIRECTINPUTDEVICE8A iface,
-						     LPDIDEVICEIMAGEINFOHEADERA lpdiDevImageInfoHeader)
-{
-    IDirectInputDeviceImpl *This = impl_from_IDirectInputDevice8A(iface);
-    FIXME("(%p)->(%p): stub !\n", This, lpdiDevImageInfoHeader);
-    
-    return DI_OK;
-}
-
 HRESULT WINAPI IDirectInputDevice8WImpl_GetImageInfo(LPDIRECTINPUTDEVICE8W iface,
 						     LPDIDEVICEIMAGEINFOHEADERW lpdiDevImageInfoHeader)
 {
@@ -1871,13 +1626,13 @@ HRESULT WINAPI IDirectInputDevice8WImpl_GetImageInfo(LPDIRECTINPUTDEVICE8W iface
     return DI_OK;
 }
 
-HRESULT direct_input_device_alloc(SIZE_T size, const IDirectInputDevice8WVtbl *vtblw,
-        const IDirectInputDevice8AVtbl *vtbla, const GUID *guid, IDirectInputImpl *dinput, void **out)
+HRESULT direct_input_device_alloc(SIZE_T size, const IDirectInputDevice8WVtbl *vtbl, const GUID *guid,
+        IDirectInputImpl *dinput, void **out)
 {
     IDirectInputDeviceImpl *This;
     if (!(This = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, size))) return DIERR_OUTOFMEMORY;
-    This->IDirectInputDevice8A_iface.lpVtbl = vtbla;
-    This->IDirectInputDevice8W_iface.lpVtbl = vtblw;
+    This->IDirectInputDevice8A_iface.lpVtbl = &direct_input_device_a_vtbl;
+    This->IDirectInputDevice8W_iface.lpVtbl = vtbl;
     This->ref = 1;
     This->guid = *guid;
     InitializeCriticalSection(&This->crit);
diff --git a/dlls/dinput/device_private.h b/dlls/dinput/device_private.h
index 1c727e71f46..9a0202840c4 100644
--- a/dlls/dinput/device_private.h
+++ b/dlls/dinput/device_private.h
@@ -86,8 +86,10 @@ struct IDirectInputDeviceImpl
     ActionMap                  *action_map;  /* array of mappings */
 };
 
-extern HRESULT direct_input_device_alloc(SIZE_T size, const IDirectInputDevice8WVtbl *vtblw,
-        const IDirectInputDevice8AVtbl *vtbla, const GUID *guid, IDirectInputImpl *dinput, void **out) DECLSPEC_HIDDEN;
+extern const IDirectInputDevice8AVtbl direct_input_device_a_vtbl DECLSPEC_HIDDEN;
+
+extern HRESULT direct_input_device_alloc(SIZE_T size, const IDirectInputDevice8WVtbl *vtbl, const GUID *guid,
+        IDirectInputImpl *dinput, void **out) DECLSPEC_HIDDEN;
 
 extern BOOL get_app_key(HKEY*, HKEY*) DECLSPEC_HIDDEN;
 extern DWORD get_config_key(HKEY, HKEY, const char*, char*, DWORD) DECLSPEC_HIDDEN;
@@ -135,110 +137,55 @@ extern HRESULT _build_action_map(LPDIRECTINPUTDEVICE8W iface, LPDIACTIONFORMATW
 extern HRESULT _set_action_map(LPDIRECTINPUTDEVICE8W iface, LPDIACTIONFORMATW lpdiaf, LPCWSTR lpszUserName, DWORD dwFlags, LPCDIDATAFORMAT df) DECLSPEC_HIDDEN;
 
 /* And the stubs */
-extern HRESULT WINAPI IDirectInputDevice2AImpl_Acquire(LPDIRECTINPUTDEVICE8A iface) DECLSPEC_HIDDEN;
 extern HRESULT WINAPI IDirectInputDevice2WImpl_Acquire(LPDIRECTINPUTDEVICE8W iface) DECLSPEC_HIDDEN;
-extern HRESULT WINAPI IDirectInputDevice2AImpl_Unacquire(LPDIRECTINPUTDEVICE8A iface) DECLSPEC_HIDDEN;
 extern HRESULT WINAPI IDirectInputDevice2WImpl_Unacquire(LPDIRECTINPUTDEVICE8W iface) DECLSPEC_HIDDEN;
-extern HRESULT WINAPI IDirectInputDevice2AImpl_SetDataFormat(LPDIRECTINPUTDEVICE8A iface, LPCDIDATAFORMAT df) DECLSPEC_HIDDEN;
 extern HRESULT WINAPI IDirectInputDevice2WImpl_SetDataFormat(LPDIRECTINPUTDEVICE8W iface, LPCDIDATAFORMAT df) DECLSPEC_HIDDEN;
-extern HRESULT WINAPI IDirectInputDevice2AImpl_SetCooperativeLevel(LPDIRECTINPUTDEVICE8A iface, HWND hwnd, DWORD dwflags) DECLSPEC_HIDDEN;
 extern HRESULT WINAPI IDirectInputDevice2WImpl_SetCooperativeLevel(LPDIRECTINPUTDEVICE8W iface, HWND hwnd, DWORD dwflags) DECLSPEC_HIDDEN;
-extern HRESULT WINAPI IDirectInputDevice2AImpl_SetEventNotification(LPDIRECTINPUTDEVICE8A iface, HANDLE hnd) DECLSPEC_HIDDEN;
 extern HRESULT WINAPI IDirectInputDevice2WImpl_SetEventNotification(LPDIRECTINPUTDEVICE8W iface, HANDLE hnd) DECLSPEC_HIDDEN;
-extern ULONG WINAPI IDirectInputDevice2AImpl_Release(LPDIRECTINPUTDEVICE8A iface)  DECLSPEC_HIDDEN;
 extern ULONG WINAPI IDirectInputDevice2WImpl_Release(LPDIRECTINPUTDEVICE8W iface) DECLSPEC_HIDDEN;
-extern HRESULT WINAPI IDirectInputDevice2AImpl_QueryInterface(LPDIRECTINPUTDEVICE8A iface, REFIID riid, LPVOID *ppobj) DECLSPEC_HIDDEN;
 extern HRESULT WINAPI IDirectInputDevice2WImpl_QueryInterface(LPDIRECTINPUTDEVICE8W iface, REFIID riid, LPVOID *ppobj) DECLSPEC_HIDDEN;
-extern ULONG WINAPI IDirectInputDevice2AImpl_AddRef(LPDIRECTINPUTDEVICE8A iface) DECLSPEC_HIDDEN;
 extern ULONG WINAPI IDirectInputDevice2WImpl_AddRef(LPDIRECTINPUTDEVICE8W iface) DECLSPEC_HIDDEN;
-extern HRESULT WINAPI IDirectInputDevice2AImpl_EnumObjects(
-	LPDIRECTINPUTDEVICE8A iface,
-	LPDIENUMDEVICEOBJECTSCALLBACKA lpCallback,
-	LPVOID lpvRef,
-	DWORD dwFlags)  DECLSPEC_HIDDEN;
 extern HRESULT WINAPI IDirectInputDevice2WImpl_EnumObjects(
 	LPDIRECTINPUTDEVICE8W iface,
 	LPDIENUMDEVICEOBJECTSCALLBACKW lpCallback,
 	LPVOID lpvRef,
 	DWORD dwFlags)  DECLSPEC_HIDDEN;
-extern HRESULT WINAPI IDirectInputDevice2AImpl_GetProperty(LPDIRECTINPUTDEVICE8A iface, REFGUID rguid, LPDIPROPHEADER pdiph) DECLSPEC_HIDDEN;
 extern HRESULT WINAPI IDirectInputDevice2WImpl_GetProperty(LPDIRECTINPUTDEVICE8W iface, REFGUID rguid, LPDIPROPHEADER pdiph) DECLSPEC_HIDDEN;
-extern HRESULT WINAPI IDirectInputDevice2AImpl_SetProperty(LPDIRECTINPUTDEVICE8A iface, REFGUID rguid, LPCDIPROPHEADER pdiph) DECLSPEC_HIDDEN;
 extern HRESULT WINAPI IDirectInputDevice2WImpl_SetProperty(LPDIRECTINPUTDEVICE8W iface, REFGUID rguid, LPCDIPROPHEADER pdiph) DECLSPEC_HIDDEN;
-extern HRESULT WINAPI IDirectInputDevice2AImpl_GetObjectInfo(
-	LPDIRECTINPUTDEVICE8A iface,
-	LPDIDEVICEOBJECTINSTANCEA pdidoi,
-	DWORD dwObj,
-	DWORD dwHow)  DECLSPEC_HIDDEN;
 extern HRESULT WINAPI IDirectInputDevice2WImpl_GetObjectInfo(LPDIRECTINPUTDEVICE8W iface, 
 							     LPDIDEVICEOBJECTINSTANCEW pdidoi,
 							     DWORD dwObj,
 							     DWORD dwHow) DECLSPEC_HIDDEN;
-extern HRESULT WINAPI IDirectInputDevice2AImpl_GetDeviceData(LPDIRECTINPUTDEVICE8A iface, DWORD dodsize, LPDIDEVICEOBJECTDATA dod,
-                                                             LPDWORD entries, DWORD flags) DECLSPEC_HIDDEN;
 extern HRESULT WINAPI IDirectInputDevice2WImpl_GetDeviceData(LPDIRECTINPUTDEVICE8W iface, DWORD dodsize, LPDIDEVICEOBJECTDATA dod,
                                                              LPDWORD entries, DWORD flags) DECLSPEC_HIDDEN;
-extern HRESULT WINAPI IDirectInputDevice2AImpl_RunControlPanel(LPDIRECTINPUTDEVICE8A iface, HWND hwndOwner, DWORD dwFlags) DECLSPEC_HIDDEN;
 extern HRESULT WINAPI IDirectInputDevice2WImpl_RunControlPanel(LPDIRECTINPUTDEVICE8W iface, HWND hwndOwner, DWORD dwFlags) DECLSPEC_HIDDEN;
-extern HRESULT WINAPI IDirectInputDevice2AImpl_Initialize(LPDIRECTINPUTDEVICE8A iface, HINSTANCE hinst, DWORD dwVersion,
-                                                          REFGUID rguid) DECLSPEC_HIDDEN;
 extern HRESULT WINAPI IDirectInputDevice2WImpl_Initialize(LPDIRECTINPUTDEVICE8W iface, HINSTANCE hinst, DWORD dwVersion,
                                                           REFGUID rguid) DECLSPEC_HIDDEN;
-extern HRESULT WINAPI IDirectInputDevice2AImpl_CreateEffect(LPDIRECTINPUTDEVICE8A iface, REFGUID rguid, LPCDIEFFECT lpeff,
-                                                            LPDIRECTINPUTEFFECT *ppdef, LPUNKNOWN pUnkOuter) DECLSPEC_HIDDEN;
 extern HRESULT WINAPI IDirectInputDevice2WImpl_CreateEffect(LPDIRECTINPUTDEVICE8W iface, REFGUID rguid, LPCDIEFFECT lpeff,
                                                             LPDIRECTINPUTEFFECT *ppdef, LPUNKNOWN pUnkOuter) DECLSPEC_HIDDEN;
-extern HRESULT WINAPI IDirectInputDevice2AImpl_EnumEffects(
-	LPDIRECTINPUTDEVICE8A iface,
-	LPDIENUMEFFECTSCALLBACKA lpCallback,
-	LPVOID lpvRef,
-	DWORD dwFlags)  DECLSPEC_HIDDEN;
 extern HRESULT WINAPI IDirectInputDevice2WImpl_EnumEffects(
 	LPDIRECTINPUTDEVICE8W iface,
 	LPDIENUMEFFECTSCALLBACKW lpCallback,
 	LPVOID lpvRef,
 	DWORD dwFlags)  DECLSPEC_HIDDEN;
-extern HRESULT WINAPI IDirectInputDevice2AImpl_GetEffectInfo(
-	LPDIRECTINPUTDEVICE8A iface,
-	LPDIEFFECTINFOA lpdei,
-	REFGUID rguid)  DECLSPEC_HIDDEN;
 extern HRESULT WINAPI IDirectInputDevice2WImpl_GetEffectInfo(
 	LPDIRECTINPUTDEVICE8W iface,
 	LPDIEFFECTINFOW lpdei,
 	REFGUID rguid)  DECLSPEC_HIDDEN;
-extern HRESULT WINAPI IDirectInputDevice2AImpl_GetForceFeedbackState(LPDIRECTINPUTDEVICE8A iface, LPDWORD pdwOut) DECLSPEC_HIDDEN;
 extern HRESULT WINAPI IDirectInputDevice2WImpl_GetForceFeedbackState(LPDIRECTINPUTDEVICE8W iface, LPDWORD pdwOut) DECLSPEC_HIDDEN;
-extern HRESULT WINAPI IDirectInputDevice2AImpl_SendForceFeedbackCommand(LPDIRECTINPUTDEVICE8A iface, DWORD dwFlags) DECLSPEC_HIDDEN;
 extern HRESULT WINAPI IDirectInputDevice2WImpl_SendForceFeedbackCommand(LPDIRECTINPUTDEVICE8W iface, DWORD dwFlags) DECLSPEC_HIDDEN;
-extern HRESULT WINAPI IDirectInputDevice2AImpl_EnumCreatedEffectObjects(LPDIRECTINPUTDEVICE8A iface,
-                                                                        LPDIENUMCREATEDEFFECTOBJECTSCALLBACK lpCallback,
-                                                                        LPVOID lpvRef, DWORD dwFlags) DECLSPEC_HIDDEN;
 extern HRESULT WINAPI IDirectInputDevice2WImpl_EnumCreatedEffectObjects(LPDIRECTINPUTDEVICE8W iface,
                                                                         LPDIENUMCREATEDEFFECTOBJECTSCALLBACK lpCallback,
                                                                         LPVOID lpvRef, DWORD dwFlags) DECLSPEC_HIDDEN;
-extern HRESULT WINAPI IDirectInputDevice2AImpl_Escape(LPDIRECTINPUTDEVICE8A iface, LPDIEFFESCAPE lpDIEEsc) DECLSPEC_HIDDEN;
 extern HRESULT WINAPI IDirectInputDevice2WImpl_Escape(LPDIRECTINPUTDEVICE8W iface, LPDIEFFESCAPE lpDIEEsc) DECLSPEC_HIDDEN;
-extern HRESULT WINAPI IDirectInputDevice2AImpl_Poll(LPDIRECTINPUTDEVICE8A iface) DECLSPEC_HIDDEN;
 extern HRESULT WINAPI IDirectInputDevice2WImpl_Poll(LPDIRECTINPUTDEVICE8W iface) DECLSPEC_HIDDEN;
-extern HRESULT WINAPI IDirectInputDevice2AImpl_SendDeviceData(LPDIRECTINPUTDEVICE8A iface, DWORD cbObjectData,
-                                                              LPCDIDEVICEOBJECTDATA rgdod, LPDWORD pdwInOut, DWORD dwFlags) DECLSPEC_HIDDEN;
 extern HRESULT WINAPI IDirectInputDevice2WImpl_SendDeviceData(LPDIRECTINPUTDEVICE8W iface, DWORD cbObjectData,
                                                               LPCDIDEVICEOBJECTDATA rgdod, LPDWORD pdwInOut, DWORD dwFlags) DECLSPEC_HIDDEN;
-extern HRESULT WINAPI IDirectInputDevice7AImpl_EnumEffectsInFile(LPDIRECTINPUTDEVICE8A iface,
-								 LPCSTR lpszFileName,
-								 LPDIENUMEFFECTSINFILECALLBACK pec,
-								 LPVOID pvRef,
-								 DWORD dwFlags)  DECLSPEC_HIDDEN;
 extern HRESULT WINAPI IDirectInputDevice7WImpl_EnumEffectsInFile(LPDIRECTINPUTDEVICE8W iface,
 								 LPCWSTR lpszFileName,
 								 LPDIENUMEFFECTSINFILECALLBACK pec,
 								 LPVOID pvRef,
 								 DWORD dwFlags)  DECLSPEC_HIDDEN;
-extern HRESULT WINAPI IDirectInputDevice7AImpl_WriteEffectToFile(LPDIRECTINPUTDEVICE8A iface,
-								 LPCSTR lpszFileName,
-								 DWORD dwEntries,
-								 LPDIFILEEFFECT rgDiFileEft,
-								 DWORD dwFlags)  DECLSPEC_HIDDEN;
 extern HRESULT WINAPI IDirectInputDevice7WImpl_WriteEffectToFile(LPDIRECTINPUTDEVICE8W iface,
 								 LPCWSTR lpszFileName,
 								 DWORD dwEntries,
@@ -248,8 +195,6 @@ extern HRESULT WINAPI IDirectInputDevice8WImpl_BuildActionMap(LPDIRECTINPUTDEVIC
 							      LPDIACTIONFORMATW lpdiaf,
 							      LPCWSTR lpszUserName,
 							      DWORD dwFlags) DECLSPEC_HIDDEN;
-extern HRESULT WINAPI IDirectInputDevice8AImpl_GetImageInfo(LPDIRECTINPUTDEVICE8A iface,
-							    LPDIDEVICEIMAGEINFOHEADERA lpdiDevImageInfoHeader) DECLSPEC_HIDDEN;
 extern HRESULT WINAPI IDirectInputDevice8WImpl_GetImageInfo(LPDIRECTINPUTDEVICE8W iface,
 							    LPDIDEVICEIMAGEINFOHEADERW lpdiDevImageInfoHeader) DECLSPEC_HIDDEN;
 
diff --git a/dlls/dinput/joystick.c b/dlls/dinput/joystick.c
index 2eab4d3a33d..497bde4a293 100644
--- a/dlls/dinput/joystick.c
+++ b/dlls/dinput/joystick.c
@@ -471,12 +471,6 @@ HRESULT WINAPI JoystickWGenericImpl_SetProperty(LPDIRECTINPUTDEVICE8W iface, REF
     return DI_OK;
 }
 
-HRESULT WINAPI JoystickAGenericImpl_SetProperty(LPDIRECTINPUTDEVICE8A iface, REFGUID rguid, LPCDIPROPHEADER ph)
-{
-    JoystickGenericImpl *This = impl_from_IDirectInputDevice8A(iface);
-    return JoystickWGenericImpl_SetProperty(IDirectInputDevice8W_from_impl(This), rguid, ph);
-}
-
 #define DEBUG_TYPE(x) case (x): str = #x; break
 void _dump_DIDEVCAPS(const DIDEVCAPS *lpDIDevCaps)
 {
@@ -552,12 +546,6 @@ HRESULT WINAPI JoystickWGenericImpl_GetCapabilities(LPDIRECTINPUTDEVICE8W iface,
     return DI_OK;
 }
 
-HRESULT WINAPI JoystickAGenericImpl_GetCapabilities(LPDIRECTINPUTDEVICE8A iface, LPDIDEVCAPS lpDIDevCaps)
-{
-    JoystickGenericImpl *This = impl_from_IDirectInputDevice8A(iface);
-    return JoystickWGenericImpl_GetCapabilities(IDirectInputDevice8W_from_impl(This), lpDIDevCaps);
-}
-
 /******************************************************************************
   *     GetObjectInfo : get object info
   */
@@ -584,27 +572,6 @@ HRESULT WINAPI JoystickWGenericImpl_GetObjectInfo(LPDIRECTINPUTDEVICE8W iface,
     return res;
 }
 
-HRESULT WINAPI JoystickAGenericImpl_GetObjectInfo(LPDIRECTINPUTDEVICE8A iface,
-        LPDIDEVICEOBJECTINSTANCEA pdidoi, DWORD dwObj, DWORD dwHow)
-{
-    JoystickGenericImpl *This = impl_from_IDirectInputDevice8A(iface);
-    HRESULT res;
-    DIDEVICEOBJECTINSTANCEW didoiW;
-    DWORD dwSize = pdidoi->dwSize;
-
-    didoiW.dwSize = sizeof(didoiW);
-    res = JoystickWGenericImpl_GetObjectInfo(IDirectInputDevice8W_from_impl(This), &didoiW, dwObj, dwHow);
-    if (res != DI_OK) return res;
-
-    memset(pdidoi, 0, pdidoi->dwSize);
-    memcpy(pdidoi, &didoiW, FIELD_OFFSET(DIDEVICEOBJECTINSTANCEW, tszName));
-    pdidoi->dwSize = dwSize;
-    WideCharToMultiByte(CP_ACP, 0, didoiW.tszName, -1, pdidoi->tszName,
-                        sizeof(pdidoi->tszName), NULL, NULL);
-
-    return res;
-}
-
 /******************************************************************************
   *     GetProperty : get input device properties
   */
@@ -678,60 +645,6 @@ HRESULT WINAPI JoystickWGenericImpl_GetProperty(LPDIRECTINPUTDEVICE8W iface, REF
     return DI_OK;
 }
 
-HRESULT WINAPI JoystickAGenericImpl_GetProperty(LPDIRECTINPUTDEVICE8A iface, REFGUID rguid, LPDIPROPHEADER pdiph)
-{
-    JoystickGenericImpl *This = impl_from_IDirectInputDevice8A(iface);
-    return JoystickWGenericImpl_GetProperty(IDirectInputDevice8W_from_impl(This), rguid, pdiph);
-}
-
-/******************************************************************************
-  *     GetDeviceInfo : get information about a device's identity
-  */
-HRESULT WINAPI JoystickAGenericImpl_GetDeviceInfo(
-    LPDIRECTINPUTDEVICE8A iface,
-    LPDIDEVICEINSTANCEA pdidi)
-{
-    JoystickGenericImpl *This = impl_from_IDirectInputDevice8A(iface);
-    DIPROPDWORD pd;
-    DWORD index = 0;
-
-    TRACE("(%p,%p)\n", This, pdidi);
-
-    if (pdidi == NULL) {
-        WARN("invalid pointer\n");
-        return E_POINTER;
-    }
-
-    if ((pdidi->dwSize != sizeof(DIDEVICEINSTANCE_DX3A)) &&
-        (pdidi->dwSize != sizeof(DIDEVICEINSTANCEA))) {
-        WARN("invalid parameter: pdidi->dwSize = %d\n", pdidi->dwSize);
-        return DIERR_INVALIDPARAM;
-    }
-
-    /* Try to get joystick index */
-    pd.diph.dwSize = sizeof(pd);
-    pd.diph.dwHeaderSize = sizeof(pd.diph);
-    pd.diph.dwObj = 0;
-    pd.diph.dwHow = DIPH_DEVICE;
-    if (SUCCEEDED(IDirectInputDevice2_GetProperty(iface, DIPROP_JOYSTICKID, &pd.diph)))
-        index = pd.dwData;
-
-    /* Return joystick */
-    pdidi->guidInstance = This->guidInstance;
-    pdidi->guidProduct = This->guidProduct;
-    /* we only support traditional joysticks for now */
-    pdidi->dwDevType = This->devcaps.dwDevType;
-    snprintf(pdidi->tszInstanceName, MAX_PATH, "Joystick %d", index);
-    lstrcpynA(pdidi->tszProductName, This->name, MAX_PATH);
-    if (pdidi->dwSize > sizeof(DIDEVICEINSTANCE_DX3A)) {
-        pdidi->guidFFDriver = GUID_NULL;
-        pdidi->wUsagePage = 0;
-        pdidi->wUsage = 0;
-    }
-
-    return DI_OK;
-}
-
 /******************************************************************************
   *     GetDeviceInfo : get information about a device's identity
   */
@@ -792,12 +705,6 @@ HRESULT WINAPI JoystickWGenericImpl_Poll(LPDIRECTINPUTDEVICE8W iface)
     return DI_OK;
 }
 
-HRESULT WINAPI JoystickAGenericImpl_Poll(LPDIRECTINPUTDEVICE8A iface)
-{
-    JoystickGenericImpl *This = impl_from_IDirectInputDevice8A(iface);
-    return JoystickWGenericImpl_Poll(IDirectInputDevice8W_from_impl(This));
-}
-
 /******************************************************************************
   *     GetDeviceState : returns the "state" of the joystick.
   *
@@ -822,13 +729,6 @@ HRESULT WINAPI JoystickWGenericImpl_GetDeviceState(LPDIRECTINPUTDEVICE8W iface,
     return DI_OK;
 }
 
-HRESULT WINAPI JoystickAGenericImpl_GetDeviceState(LPDIRECTINPUTDEVICE8A iface, DWORD len, LPVOID ptr)
-{
-    JoystickGenericImpl *This = impl_from_IDirectInputDevice8A(iface);
-    return JoystickWGenericImpl_GetDeviceState(IDirectInputDevice8W_from_impl(This), len, ptr);
-}
-
-
 HRESULT WINAPI JoystickWGenericImpl_BuildActionMap(LPDIRECTINPUTDEVICE8W iface,
                                                    LPDIACTIONFORMATW lpdiaf,
                                                    LPCWSTR lpszUserName,
@@ -881,36 +781,6 @@ HRESULT WINAPI JoystickWGenericImpl_BuildActionMap(LPDIRECTINPUTDEVICE8W iface,
     return IDirectInputDevice8WImpl_BuildActionMap(iface, lpdiaf, lpszUserName, dwFlags);
 }
 
-HRESULT WINAPI JoystickAGenericImpl_BuildActionMap(LPDIRECTINPUTDEVICE8A iface,
-                                                   LPDIACTIONFORMATA lpdiaf,
-                                                   LPCSTR lpszUserName,
-                                                   DWORD dwFlags)
-{
-    JoystickGenericImpl *This = impl_from_IDirectInputDevice8A(iface);
-    DIACTIONFORMATW diafW;
-    HRESULT hr;
-    WCHAR *lpszUserNameW = NULL;
-    int username_size;
-
-    diafW.rgoAction = HeapAlloc(GetProcessHeap(), 0, sizeof(DIACTIONW)*lpdiaf->dwNumActions);
-    _copy_diactionformatAtoW(&diafW, lpdiaf);
-
-    if (lpszUserName != NULL)
-    {
-        username_size = MultiByteToWideChar(CP_ACP, 0, lpszUserName, -1, NULL, 0);
-        lpszUserNameW = HeapAlloc(GetProcessHeap(), 0, sizeof(WCHAR)*username_size);
-        MultiByteToWideChar(CP_ACP, 0, lpszUserName, -1, lpszUserNameW, username_size);
-    }
-
-    hr = JoystickWGenericImpl_BuildActionMap(&This->base.IDirectInputDevice8W_iface, &diafW, lpszUserNameW, dwFlags);
-
-    _copy_diactionformatWtoA(lpdiaf, &diafW);
-    HeapFree(GetProcessHeap(), 0, diafW.rgoAction);
-    HeapFree(GetProcessHeap(), 0, lpszUserNameW);
-
-    return hr;
-}
-
 HRESULT WINAPI JoystickWGenericImpl_SetActionMap(LPDIRECTINPUTDEVICE8W iface,
                                                  LPDIACTIONFORMATW lpdiaf,
                                                  LPCWSTR lpszUserName,
@@ -923,35 +793,6 @@ HRESULT WINAPI JoystickWGenericImpl_SetActionMap(LPDIRECTINPUTDEVICE8W iface,
     return _set_action_map(iface, lpdiaf, lpszUserName, dwFlags, This->base.data_format.wine_df);
 }
 
-HRESULT WINAPI JoystickAGenericImpl_SetActionMap(LPDIRECTINPUTDEVICE8A iface,
-                                                 LPDIACTIONFORMATA lpdiaf,
-                                                 LPCSTR lpszUserName,
-                                                 DWORD dwFlags)
-{
-    JoystickGenericImpl *This = impl_from_IDirectInputDevice8A(iface);
-    DIACTIONFORMATW diafW;
-    HRESULT hr;
-    WCHAR *lpszUserNameW = NULL;
-    int username_size;
-
-    diafW.rgoAction = HeapAlloc(GetProcessHeap(), 0, sizeof(DIACTIONW)*lpdiaf->dwNumActions);
-    _copy_diactionformatAtoW(&diafW, lpdiaf);
-
-    if (lpszUserName != NULL)
-    {
-        username_size = MultiByteToWideChar(CP_ACP, 0, lpszUserName, -1, NULL, 0);
-        lpszUserNameW = HeapAlloc(GetProcessHeap(), 0, sizeof(WCHAR)*username_size);
-        MultiByteToWideChar(CP_ACP, 0, lpszUserName, -1, lpszUserNameW, username_size);
-    }
-
-    hr = JoystickWGenericImpl_SetActionMap(&This->base.IDirectInputDevice8W_iface, &diafW, lpszUserNameW, dwFlags);
-
-    HeapFree(GetProcessHeap(), 0, diafW.rgoAction);
-    HeapFree(GetProcessHeap(), 0, lpszUserNameW);
-
-    return hr;
-}
-
 /*
  * This maps the read value (from the input event) to a value in the
  * 'wanted' range.
diff --git a/dlls/dinput/joystick_linux.c b/dlls/dinput/joystick_linux.c
index fd4ba4e0e71..29066f514cc 100644
--- a/dlls/dinput/joystick_linux.c
+++ b/dlls/dinput/joystick_linux.c
@@ -90,7 +90,6 @@ struct JoyDev
 };
 
 typedef struct JoystickImpl JoystickImpl;
-static const IDirectInputDevice8AVtbl JoystickAvt;
 static const IDirectInputDevice8WVtbl JoystickWvt;
 struct JoystickImpl
 {
@@ -474,7 +473,7 @@ static HRESULT alloc_device(REFGUID rguid, IDirectInputImpl *dinput,
     TRACE("%s %p %p %hu\n", debugstr_guid(rguid), dinput, pdev, index);
 
     *pdev = NULL;
-    if (FAILED(hr = direct_input_device_alloc(sizeof(JoystickImpl), &JoystickWvt, &JoystickAvt, rguid, dinput, (void **)&newDevice)))
+    if (FAILED(hr = direct_input_device_alloc(sizeof(JoystickImpl), &JoystickWvt, rguid, dinput, (void **)&newDevice)))
         return hr;
     newDevice->generic.base.crit.DebugInfo->Spare[0] = (DWORD_PTR)(__FILE__ ": JoystickImpl*->generic.base.crit");
 
@@ -687,12 +686,6 @@ static HRESULT WINAPI JoystickLinuxWImpl_Acquire(LPDIRECTINPUTDEVICE8W iface)
     return DI_OK;
 }
 
-static HRESULT WINAPI JoystickLinuxAImpl_Acquire(LPDIRECTINPUTDEVICE8A iface)
-{
-    JoystickImpl *This = impl_from_IDirectInputDevice8A(iface);
-    return JoystickLinuxWImpl_Acquire(IDirectInputDevice8W_from_impl(This));
-}
-
 /******************************************************************************
   *     GetProperty : get input device properties
   */
@@ -756,31 +749,9 @@ static HRESULT WINAPI JoystickLinuxWImpl_GetProperty(LPDIRECTINPUTDEVICE8W iface
     return DI_OK;
 }
 
-static HRESULT WINAPI JoystickLinuxAImpl_GetProperty(LPDIRECTINPUTDEVICE8A iface, REFGUID rguid, LPDIPROPHEADER pdiph)
-{
-    JoystickImpl *This = impl_from_IDirectInputDevice8A(iface);
-    return JoystickLinuxWImpl_GetProperty(IDirectInputDevice8W_from_impl(This), rguid, pdiph);
-}
-
 /******************************************************************************
   *     GetDeviceInfo : get information about a device's identity
   */
-static HRESULT WINAPI JoystickLinuxAImpl_GetDeviceInfo(LPDIRECTINPUTDEVICE8A iface, LPDIDEVICEINSTANCEA ddi)
-{
-    JoystickImpl *This = impl_from_IDirectInputDevice8A(iface);
-
-    TRACE("(%p) %p\n", This, ddi);
-
-    if (ddi == NULL) return E_POINTER;
-    if ((ddi->dwSize != sizeof(DIDEVICEINSTANCE_DX3A)) &&
-        (ddi->dwSize != sizeof(DIDEVICEINSTANCEA)))
-        return DIERR_INVALIDPARAM;
-
-    fill_joystick_dideviceinstanceA( ddi, This->generic.base.dinput->dwVersion,
-                                     get_joystick_index(&This->generic.base.guid) );
-    return DI_OK;
-}
-
 static HRESULT WINAPI JoystickLinuxWImpl_GetDeviceInfo(LPDIRECTINPUTDEVICE8W iface, LPDIDEVICEINSTANCEW ddi)
 {
     JoystickImpl *This = impl_from_IDirectInputDevice8W(iface);
@@ -822,12 +793,6 @@ static HRESULT WINAPI JoystickLinuxWImpl_Unacquire(LPDIRECTINPUTDEVICE8W iface)
     return DI_NOEFFECT;
 }
 
-static HRESULT WINAPI JoystickLinuxAImpl_Unacquire(LPDIRECTINPUTDEVICE8A iface)
-{
-    JoystickImpl *This = impl_from_IDirectInputDevice8A(iface);
-    return JoystickLinuxWImpl_Unacquire(IDirectInputDevice8W_from_impl(This));
-}
-
 static void joy_polldev(LPDIRECTINPUTDEVICE8A iface)
 {
     struct pollfd plfd;
@@ -903,42 +868,6 @@ static void joy_polldev(LPDIRECTINPUTDEVICE8A iface)
     }
 }
 
-static const IDirectInputDevice8AVtbl JoystickAvt =
-{
-	IDirectInputDevice2AImpl_QueryInterface,
-	IDirectInputDevice2AImpl_AddRef,
-        IDirectInputDevice2AImpl_Release,
-	JoystickAGenericImpl_GetCapabilities,
-        IDirectInputDevice2AImpl_EnumObjects,
-	JoystickLinuxAImpl_GetProperty,
-	JoystickAGenericImpl_SetProperty,
-	JoystickLinuxAImpl_Acquire,
-	JoystickLinuxAImpl_Unacquire,
-	JoystickAGenericImpl_GetDeviceState,
-	IDirectInputDevice2AImpl_GetDeviceData,
-	IDirectInputDevice2AImpl_SetDataFormat,
-	IDirectInputDevice2AImpl_SetEventNotification,
-	IDirectInputDevice2AImpl_SetCooperativeLevel,
-	JoystickAGenericImpl_GetObjectInfo,
-	JoystickLinuxAImpl_GetDeviceInfo,
-	IDirectInputDevice2AImpl_RunControlPanel,
-	IDirectInputDevice2AImpl_Initialize,
-	IDirectInputDevice2AImpl_CreateEffect,
-	IDirectInputDevice2AImpl_EnumEffects,
-	IDirectInputDevice2AImpl_GetEffectInfo,
-	IDirectInputDevice2AImpl_GetForceFeedbackState,
-	IDirectInputDevice2AImpl_SendForceFeedbackCommand,
-	IDirectInputDevice2AImpl_EnumCreatedEffectObjects,
-	IDirectInputDevice2AImpl_Escape,
-	JoystickAGenericImpl_Poll,
-	IDirectInputDevice2AImpl_SendDeviceData,
-	IDirectInputDevice7AImpl_EnumEffectsInFile,
-	IDirectInputDevice7AImpl_WriteEffectToFile,
-	JoystickAGenericImpl_BuildActionMap,
-	JoystickAGenericImpl_SetActionMap,
-	IDirectInputDevice8AImpl_GetImageInfo
-};
-
 static const IDirectInputDevice8WVtbl JoystickWvt =
 {
     IDirectInputDevice2WImpl_QueryInterface,
diff --git a/dlls/dinput/joystick_linuxinput.c b/dlls/dinput/joystick_linuxinput.c
index 4e1b3f83391..b285369f80f 100644
--- a/dlls/dinput/joystick_linuxinput.c
+++ b/dlls/dinput/joystick_linuxinput.c
@@ -92,7 +92,6 @@ HRESULT linuxinput_get_info_W(int fd, REFGUID rguid, LPDIEFFECTINFOW info);
 static HRESULT WINAPI JoystickWImpl_SendForceFeedbackCommand(LPDIRECTINPUTDEVICE8W iface, DWORD dwFlags);
 
 typedef struct JoystickImpl JoystickImpl;
-static const IDirectInputDevice8AVtbl JoystickAvt;
 static const IDirectInputDevice8WVtbl JoystickWvt;
 
 struct JoyDev {
@@ -463,7 +462,7 @@ static JoystickImpl *alloc_device(REFGUID rguid, IDirectInputImpl *dinput, unsig
     int default_axis_map[WINE_JOYSTICK_MAX_AXES + WINE_JOYSTICK_MAX_POVS*2];
     DIDEVICEINSTANCEW ddi;
 
-    if (FAILED(direct_input_device_alloc(sizeof(JoystickImpl), &JoystickWvt, &JoystickAvt, rguid, dinput, (void **)&newDevice)))
+    if (FAILED(direct_input_device_alloc(sizeof(JoystickImpl), &JoystickWvt, rguid, dinput, (void **)&newDevice)))
         return NULL;
     newDevice->generic.base.crit.DebugInfo->Spare[0] = (DWORD_PTR)(__FILE__ ": JoystickImpl*->base.crit");
 
@@ -729,12 +728,6 @@ static HRESULT WINAPI JoystickWImpl_Acquire(LPDIRECTINPUTDEVICE8W iface)
     return DI_OK;
 }
 
-static HRESULT WINAPI JoystickAImpl_Acquire(LPDIRECTINPUTDEVICE8A iface)
-{
-    JoystickImpl *This = impl_from_IDirectInputDevice8A(iface);
-    return JoystickWImpl_Acquire(IDirectInputDevice8W_from_impl(This));
-}
-
 /******************************************************************************
   *     Unacquire : frees the joystick
   */
@@ -767,12 +760,6 @@ static HRESULT WINAPI JoystickWImpl_Unacquire(LPDIRECTINPUTDEVICE8W iface)
     return res;
 }
 
-static HRESULT WINAPI JoystickAImpl_Unacquire(LPDIRECTINPUTDEVICE8A iface)
-{
-    JoystickImpl *This = impl_from_IDirectInputDevice8A(iface);
-    return JoystickWImpl_Unacquire(IDirectInputDevice8W_from_impl(This));
-}
-
 /* 
  * set the current state of the js device as it would be with the middle
  * values on the axes
@@ -954,12 +941,6 @@ static HRESULT WINAPI JoystickWImpl_SetProperty(LPDIRECTINPUTDEVICE8W iface, REF
   return DI_OK;
 }
 
-static HRESULT WINAPI JoystickAImpl_SetProperty(LPDIRECTINPUTDEVICE8A iface, REFGUID rguid, LPCDIPROPHEADER ph)
-{
-    JoystickImpl *This = impl_from_IDirectInputDevice8A(iface);
-    return JoystickWImpl_SetProperty(IDirectInputDevice8W_from_impl(This), rguid, ph);
-}
-
 /******************************************************************************
   *     GetProperty : get input device properties
   */
@@ -1040,12 +1021,6 @@ static HRESULT WINAPI JoystickWImpl_GetProperty(LPDIRECTINPUTDEVICE8W iface, REF
     return DI_OK;
 }
 
-static HRESULT WINAPI JoystickAImpl_GetProperty(LPDIRECTINPUTDEVICE8A iface, REFGUID rguid, LPDIPROPHEADER pdiph)
-{
-    JoystickImpl *This = impl_from_IDirectInputDevice8A(iface);
-    return JoystickWImpl_GetProperty(IDirectInputDevice8W_from_impl(This), rguid, pdiph);
-}
-
 /****************************************************************************** 
   *	CreateEffect - Create a new FF effect with the specified params
   */
@@ -1108,91 +1083,9 @@ static HRESULT WINAPI JoystickWImpl_CreateEffect(LPDIRECTINPUTDEVICE8W iface, RE
 #endif /* HAVE_STRUCT_FF_EFFECT_DIRECTION */
 }
 
-static HRESULT WINAPI JoystickAImpl_CreateEffect(LPDIRECTINPUTDEVICE8A iface, REFGUID rguid,
-                                                 LPCDIEFFECT lpeff, LPDIRECTINPUTEFFECT *ppdef,
-                                                 LPUNKNOWN pUnkOuter)
-{
-    JoystickImpl *This = impl_from_IDirectInputDevice8A(iface);
-    return JoystickWImpl_CreateEffect(IDirectInputDevice8W_from_impl(This), rguid, lpeff, ppdef, pUnkOuter);
-}
-
 /*******************************************************************************
  *	EnumEffects - Enumerate available FF effects
  */
-static HRESULT WINAPI JoystickAImpl_EnumEffects(LPDIRECTINPUTDEVICE8A iface,
-						LPDIENUMEFFECTSCALLBACKA lpCallback,
-						LPVOID pvRef,
-						DWORD dwEffType)
-{
-#ifdef HAVE_STRUCT_FF_EFFECT_DIRECTION
-    DIEFFECTINFOA dei; /* feif */
-    DWORD type = DIEFT_GETTYPE(dwEffType);
-    JoystickImpl* This = impl_from_IDirectInputDevice8A(iface);
-
-    TRACE("(this=%p,%p,%d) type=%d\n", This, pvRef, dwEffType, type);
-
-    dei.dwSize = sizeof(DIEFFECTINFOA);          
-
-    if ((type == DIEFT_ALL || type == DIEFT_CONSTANTFORCE)
-	&& test_bit(This->joydev->ffbits, FF_CONSTANT)) {
-	IDirectInputDevice8_GetEffectInfo(iface, &dei, &GUID_ConstantForce);
-	(*lpCallback)(&dei, pvRef);
-    }
-
-    if ((type == DIEFT_ALL || type == DIEFT_PERIODIC)
-	&& test_bit(This->joydev->ffbits, FF_PERIODIC)) {
-	if (test_bit(This->joydev->ffbits, FF_SQUARE)) {
-	    IDirectInputDevice8_GetEffectInfo(iface, &dei, &GUID_Square);
-	    (*lpCallback)(&dei, pvRef);
-	}
-	if (test_bit(This->joydev->ffbits, FF_SINE)) {
-            IDirectInputDevice8_GetEffectInfo(iface, &dei, &GUID_Sine);
-	    (*lpCallback)(&dei, pvRef);
-	}
-	if (test_bit(This->joydev->ffbits, FF_TRIANGLE)) {
-	    IDirectInputDevice8_GetEffectInfo(iface, &dei, &GUID_Triangle);
-	    (*lpCallback)(&dei, pvRef);
-	}
-	if (test_bit(This->joydev->ffbits, FF_SAW_UP)) {
-	    IDirectInputDevice8_GetEffectInfo(iface, &dei, &GUID_SawtoothUp);
-	    (*lpCallback)(&dei, pvRef);
-	}
-	if (test_bit(This->joydev->ffbits, FF_SAW_DOWN)) {
-	    IDirectInputDevice8_GetEffectInfo(iface, &dei, &GUID_SawtoothDown);
-	    (*lpCallback)(&dei, pvRef);
-	}
-    } 
-
-    if ((type == DIEFT_ALL || type == DIEFT_RAMPFORCE)
-	&& test_bit(This->joydev->ffbits, FF_RAMP)) {
-        IDirectInputDevice8_GetEffectInfo(iface, &dei, &GUID_RampForce);
-        (*lpCallback)(&dei, pvRef);
-    }
-
-    if (type == DIEFT_ALL || type == DIEFT_CONDITION) {
-	if (test_bit(This->joydev->ffbits, FF_SPRING)) {
-	    IDirectInputDevice8_GetEffectInfo(iface, &dei, &GUID_Spring);
-	    (*lpCallback)(&dei, pvRef);
-	}
-	if (test_bit(This->joydev->ffbits, FF_DAMPER)) {
-	    IDirectInputDevice8_GetEffectInfo(iface, &dei, &GUID_Damper);
-	    (*lpCallback)(&dei, pvRef);
-	}
-	if (test_bit(This->joydev->ffbits, FF_INERTIA)) {
-	    IDirectInputDevice8_GetEffectInfo(iface, &dei, &GUID_Inertia);
-	    (*lpCallback)(&dei, pvRef);
-	}
-	if (test_bit(This->joydev->ffbits, FF_FRICTION)) {
-	    IDirectInputDevice8_GetEffectInfo(iface, &dei, &GUID_Friction);
-	    (*lpCallback)(&dei, pvRef);
-	}
-    }
-
-#endif
-
-    return DI_OK;
-}
-
 static HRESULT WINAPI JoystickWImpl_EnumEffects(LPDIRECTINPUTDEVICE8W iface,
                                                 LPDIENUMEFFECTSCALLBACKW lpCallback,
                                                 LPVOID pvRef,
@@ -1276,21 +1169,6 @@ static HRESULT WINAPI JoystickWImpl_EnumEffects(LPDIRECTINPUTDEVICE8W iface,
 /*******************************************************************************
  *      GetEffectInfo - Get information about a particular effect 
  */
-static HRESULT WINAPI JoystickAImpl_GetEffectInfo(LPDIRECTINPUTDEVICE8A iface,
-						  LPDIEFFECTINFOA pdei,
-						  REFGUID guid)
-{
-    JoystickImpl* This = impl_from_IDirectInputDevice8A(iface);
-
-    TRACE("(this=%p,%p,%s)\n", This, pdei, _dump_dinput_GUID(guid));
-
-#ifdef HAVE_STRUCT_FF_EFFECT_DIRECTION
-    return linuxinput_get_info_A(This->joyfd, guid, pdei); 
-#else
-    return DI_OK;
-#endif
-}
-
 static HRESULT WINAPI JoystickWImpl_GetEffectInfo(LPDIRECTINPUTDEVICE8W iface,
                                                   LPDIEFFECTINFOW pdei,
                                                   REFGUID guid)
@@ -1326,12 +1204,6 @@ static HRESULT WINAPI JoystickWImpl_GetForceFeedbackState(LPDIRECTINPUTDEVICE8W
     return DI_OK;
 }
 
-static HRESULT WINAPI JoystickAImpl_GetForceFeedbackState(LPDIRECTINPUTDEVICE8A iface, LPDWORD pdwOut)
-{
-    JoystickImpl *This = impl_from_IDirectInputDevice8A(iface);
-    return JoystickWImpl_GetForceFeedbackState(IDirectInputDevice8W_from_impl(This), pdwOut);
-}
-
 /*******************************************************************************
  *      SendForceFeedbackCommand - Send a command to the device's FF system
  */
@@ -1385,12 +1257,6 @@ static HRESULT WINAPI JoystickWImpl_SendForceFeedbackCommand(LPDIRECTINPUTDEVICE
 #endif
 }
 
-static HRESULT WINAPI JoystickAImpl_SendForceFeedbackCommand(LPDIRECTINPUTDEVICE8A iface, DWORD dwFlags)
-{
-    JoystickImpl *This = impl_from_IDirectInputDevice8A(iface);
-    return JoystickWImpl_SendForceFeedbackCommand(IDirectInputDevice8W_from_impl(This), dwFlags);
-}
-
 /*******************************************************************************
  *      EnumCreatedEffectObjects - Enumerate all the effects that have been
  *		created for this device.
@@ -1417,34 +1283,9 @@ static HRESULT WINAPI JoystickWImpl_EnumCreatedEffectObjects(LPDIRECTINPUTDEVICE
     return DI_OK;
 }
 
-static HRESULT WINAPI JoystickAImpl_EnumCreatedEffectObjects(LPDIRECTINPUTDEVICE8A iface,
-                                                             LPDIENUMCREATEDEFFECTOBJECTSCALLBACK lpCallback,
-                                                             LPVOID pvRef, DWORD dwFlags)
-{
-    JoystickImpl *This = impl_from_IDirectInputDevice8A(iface);
-    return JoystickWImpl_EnumCreatedEffectObjects(IDirectInputDevice8W_from_impl(This), lpCallback, pvRef, dwFlags);
-}
-
 /******************************************************************************
   *     GetDeviceInfo : get information about a device's identity
   */
-static HRESULT WINAPI JoystickAImpl_GetDeviceInfo(LPDIRECTINPUTDEVICE8A iface,
-                                                  LPDIDEVICEINSTANCEA pdidi)
-{
-    JoystickImpl *This = impl_from_IDirectInputDevice8A(iface);
-
-    TRACE("(%p) %p\n", This, pdidi);
-
-    if (pdidi == NULL) return E_POINTER;
-    if ((pdidi->dwSize != sizeof(DIDEVICEINSTANCE_DX3A)) &&
-        (pdidi->dwSize != sizeof(DIDEVICEINSTANCEA)))
-        return DIERR_INVALIDPARAM;
-
-    fill_joystick_dideviceinstanceA(pdidi, This->generic.base.dinput->dwVersion,
-                                    get_joystick_index(&This->generic.base.guid));
-    return DI_OK;
-}
-
 static HRESULT WINAPI JoystickWImpl_GetDeviceInfo(LPDIRECTINPUTDEVICE8W iface,
                                                   LPDIDEVICEINSTANCEW pdidi)
 {
@@ -1462,42 +1303,6 @@ static HRESULT WINAPI JoystickWImpl_GetDeviceInfo(LPDIRECTINPUTDEVICE8W iface,
     return DI_OK;
 }
 
-static const IDirectInputDevice8AVtbl JoystickAvt =
-{
-	IDirectInputDevice2AImpl_QueryInterface,
-	IDirectInputDevice2AImpl_AddRef,
-        IDirectInputDevice2AImpl_Release,
-        JoystickAGenericImpl_GetCapabilities,
-        IDirectInputDevice2AImpl_EnumObjects,
-	JoystickAImpl_GetProperty,
-	JoystickAImpl_SetProperty,
-	JoystickAImpl_Acquire,
-	JoystickAImpl_Unacquire,
-        JoystickAGenericImpl_GetDeviceState,
-	IDirectInputDevice2AImpl_GetDeviceData,
-        IDirectInputDevice2AImpl_SetDataFormat,
-	IDirectInputDevice2AImpl_SetEventNotification,
-	IDirectInputDevice2AImpl_SetCooperativeLevel,
-        JoystickAGenericImpl_GetObjectInfo,
-	JoystickAImpl_GetDeviceInfo,
-	IDirectInputDevice2AImpl_RunControlPanel,
-	IDirectInputDevice2AImpl_Initialize,
-	JoystickAImpl_CreateEffect,
-	JoystickAImpl_EnumEffects,
-	JoystickAImpl_GetEffectInfo,
-	JoystickAImpl_GetForceFeedbackState,
-	JoystickAImpl_SendForceFeedbackCommand,
-	JoystickAImpl_EnumCreatedEffectObjects,
-	IDirectInputDevice2AImpl_Escape,
-        JoystickAGenericImpl_Poll,
-	IDirectInputDevice2AImpl_SendDeviceData,
-	IDirectInputDevice7AImpl_EnumEffectsInFile,
-        IDirectInputDevice7AImpl_WriteEffectToFile,
-        JoystickAGenericImpl_BuildActionMap,
-        JoystickAGenericImpl_SetActionMap,
-        IDirectInputDevice8AImpl_GetImageInfo
-};
-
 static const IDirectInputDevice8WVtbl JoystickWvt =
 {
     IDirectInputDevice2WImpl_QueryInterface,
diff --git a/dlls/dinput/joystick_osx.c b/dlls/dinput/joystick_osx.c
index 3631448ea78..8dde986be3e 100644
--- a/dlls/dinput/joystick_osx.c
+++ b/dlls/dinput/joystick_osx.c
@@ -99,7 +99,6 @@ WINE_DEFAULT_DEBUG_CHANNEL(dinput);
 static CFMutableArrayRef device_main_elements = NULL;
 
 typedef struct JoystickImpl JoystickImpl;
-static const IDirectInputDevice8AVtbl JoystickAvt;
 static const IDirectInputDevice8WVtbl JoystickWvt;
 
 struct JoystickImpl
@@ -1096,7 +1095,7 @@ static HRESULT alloc_device(REFGUID rguid, IDirectInputImpl *dinput,
 
     TRACE("%s %p %p %hu\n", debugstr_guid(rguid), dinput, pdev, index);
 
-    if (FAILED(hr = direct_input_device_alloc(sizeof(JoystickImpl), &JoystickWvt, &JoystickAvt, rguid, dinput, (void **)&newDevice)))
+    if (FAILED(hr = direct_input_device_alloc(sizeof(JoystickImpl), &JoystickWvt, rguid, dinput, (void **)&newDevice)))
         return hr;
     newDevice->generic.base.crit.DebugInfo->Spare[0] = (DWORD_PTR)(__FILE__ ": JoystickImpl*->generic.base.crit");
 
@@ -1378,12 +1377,6 @@ static HRESULT WINAPI JoystickWImpl_GetProperty(LPDIRECTINPUTDEVICE8W iface, REF
     return DI_OK;
 }
 
-static HRESULT WINAPI JoystickAImpl_GetProperty(LPDIRECTINPUTDEVICE8A iface, REFGUID rguid, LPDIPROPHEADER pdiph)
-{
-    JoystickImpl *This = impl_from_IDirectInputDevice8A(iface);
-    return JoystickWImpl_GetProperty(IDirectInputDevice8W_from_impl(This), rguid, pdiph);
-}
-
 static HRESULT osx_set_autocenter(JoystickImpl *This,
         const DIPROPDWORD *header)
 {
@@ -1427,24 +1420,6 @@ static HRESULT WINAPI JoystickWImpl_SetProperty(IDirectInputDevice8W *iface,
     return JoystickWGenericImpl_SetProperty(iface, prop, header);
 }
 
-static HRESULT WINAPI JoystickAImpl_SetProperty(IDirectInputDevice8A *iface,
-        const GUID *prop, const DIPROPHEADER *header)
-{
-    JoystickImpl *This = impl_from_IDirectInputDevice8A(iface);
-
-    TRACE("%p %s %p\n", This, debugstr_guid(prop), header);
-
-    switch(LOWORD(prop))
-    {
-    case (DWORD_PTR)DIPROP_AUTOCENTER:
-        return osx_set_autocenter(This, (const DIPROPDWORD *)header);
-    case (DWORD_PTR)DIPROP_FFGAIN:
-        return osx_set_ffgain(This, (const DIPROPDWORD *)header);
-    }
-
-    return JoystickAGenericImpl_SetProperty(iface, prop, header);
-}
-
 static CFUUIDRef effect_win_to_mac(const GUID *effect)
 {
 #define DO_MAP(X) \
@@ -1510,18 +1485,6 @@ static HRESULT WINAPI JoystickWImpl_CreateEffect(IDirectInputDevice8W *iface,
     return S_OK;
 }
 
-static HRESULT WINAPI JoystickAImpl_CreateEffect(IDirectInputDevice8A *iface,
-        const GUID *type, const DIEFFECT *params, IDirectInputEffect **out,
-        IUnknown *outer)
-{
-    JoystickImpl *This = impl_from_IDirectInputDevice8A(iface);
-
-    TRACE("(%p)->(%s %p %p %p)\n", This, debugstr_guid(type), params, out, outer);
-
-    return JoystickWImpl_CreateEffect(&This->generic.base.IDirectInputDevice8W_iface,
-            type, params, out, outer);
-}
-
 static HRESULT WINAPI JoystickWImpl_SendForceFeedbackCommand(IDirectInputDevice8W *iface,
         DWORD flags)
 {
@@ -1542,16 +1505,6 @@ static HRESULT WINAPI JoystickWImpl_SendForceFeedbackCommand(IDirectInputDevice8
     return S_OK;
 }
 
-static HRESULT WINAPI JoystickAImpl_SendForceFeedbackCommand(IDirectInputDevice8A *iface,
-        DWORD flags)
-{
-    JoystickImpl *This = impl_from_IDirectInputDevice8A(iface);
-
-    TRACE("%p 0x%x\n", This, flags);
-
-    return JoystickWImpl_SendForceFeedbackCommand(&This->generic.base.IDirectInputDevice8W_iface, flags);
-}
-
 const struct dinput_device joystick_osx_device = {
   "Wine OS X joystick driver",
   joydev_enum_deviceA,
@@ -1559,42 +1512,6 @@ const struct dinput_device joystick_osx_device = {
   joydev_create_device
 };
 
-static const IDirectInputDevice8AVtbl JoystickAvt =
-{
-    IDirectInputDevice2AImpl_QueryInterface,
-    IDirectInputDevice2AImpl_AddRef,
-    IDirectInputDevice2AImpl_Release,
-    JoystickAGenericImpl_GetCapabilities,
-    IDirectInputDevice2AImpl_EnumObjects,
-    JoystickAImpl_GetProperty,
-    JoystickAImpl_SetProperty,
-    IDirectInputDevice2AImpl_Acquire,
-    IDirectInputDevice2AImpl_Unacquire,
-    JoystickAGenericImpl_GetDeviceState,
-    IDirectInputDevice2AImpl_GetDeviceData,
-    IDirectInputDevice2AImpl_SetDataFormat,
-    IDirectInputDevice2AImpl_SetEventNotification,
-    IDirectInputDevice2AImpl_SetCooperativeLevel,
-    JoystickAGenericImpl_GetObjectInfo,
-    JoystickAGenericImpl_GetDeviceInfo,
-    IDirectInputDevice2AImpl_RunControlPanel,
-    IDirectInputDevice2AImpl_Initialize,
-    JoystickAImpl_CreateEffect,
-    IDirectInputDevice2AImpl_EnumEffects,
-    IDirectInputDevice2AImpl_GetEffectInfo,
-    IDirectInputDevice2AImpl_GetForceFeedbackState,
-    JoystickAImpl_SendForceFeedbackCommand,
-    IDirectInputDevice2AImpl_EnumCreatedEffectObjects,
-    IDirectInputDevice2AImpl_Escape,
-    JoystickAGenericImpl_Poll,
-    IDirectInputDevice2AImpl_SendDeviceData,
-    IDirectInputDevice7AImpl_EnumEffectsInFile,
-    IDirectInputDevice7AImpl_WriteEffectToFile,
-    JoystickAGenericImpl_BuildActionMap,
-    JoystickAGenericImpl_SetActionMap,
-    IDirectInputDevice8AImpl_GetImageInfo
-};
-
 static const IDirectInputDevice8WVtbl JoystickWvt =
 {
     IDirectInputDevice2WImpl_QueryInterface,
diff --git a/dlls/dinput/joystick_private.h b/dlls/dinput/joystick_private.h
index b786c84decb..8bb683c20f4 100644
--- a/dlls/dinput/joystick_private.h
+++ b/dlls/dinput/joystick_private.h
@@ -62,36 +62,23 @@ BOOL device_disabled_registry(const char* name) DECLSPEC_HIDDEN;
 HRESULT WINAPI JoystickWGenericImpl_GetObjectInfo(LPDIRECTINPUTDEVICE8W iface,
         LPDIDEVICEOBJECTINSTANCEW pdidoi, DWORD dwObj, DWORD dwHow) DECLSPEC_HIDDEN;
 
-HRESULT WINAPI JoystickAGenericImpl_GetObjectInfo(LPDIRECTINPUTDEVICE8A iface,
-        LPDIDEVICEOBJECTINSTANCEA pdidoi, DWORD dwObj, DWORD dwHow) DECLSPEC_HIDDEN;
-
-HRESULT WINAPI JoystickAGenericImpl_GetProperty(LPDIRECTINPUTDEVICE8A iface, REFGUID rguid, LPDIPROPHEADER pdiph) DECLSPEC_HIDDEN;
 HRESULT WINAPI JoystickWGenericImpl_GetProperty(LPDIRECTINPUTDEVICE8W iface, REFGUID rguid, LPDIPROPHEADER pdiph) DECLSPEC_HIDDEN;
 
-HRESULT WINAPI JoystickAGenericImpl_GetCapabilities(LPDIRECTINPUTDEVICE8A iface, LPDIDEVCAPS lpDIDevCaps) DECLSPEC_HIDDEN;
 HRESULT WINAPI JoystickWGenericImpl_GetCapabilities(LPDIRECTINPUTDEVICE8W iface, LPDIDEVCAPS lpDIDevCaps) DECLSPEC_HIDDEN;
 
 void _dump_DIDEVCAPS(const DIDEVCAPS *lpDIDevCaps) DECLSPEC_HIDDEN;
 
-HRESULT WINAPI JoystickAGenericImpl_SetProperty(LPDIRECTINPUTDEVICE8A iface, REFGUID rguid, LPCDIPROPHEADER ph) DECLSPEC_HIDDEN;
 HRESULT WINAPI JoystickWGenericImpl_SetProperty(LPDIRECTINPUTDEVICE8W iface, REFGUID rguid, LPCDIPROPHEADER ph) DECLSPEC_HIDDEN;
 
-HRESULT WINAPI JoystickAGenericImpl_GetDeviceInfo( LPDIRECTINPUTDEVICE8A iface,
-    LPDIDEVICEINSTANCEA pdidi) DECLSPEC_HIDDEN;
-
 HRESULT WINAPI JoystickWGenericImpl_GetDeviceInfo( LPDIRECTINPUTDEVICE8W iface,
     LPDIDEVICEINSTANCEW pdidi) DECLSPEC_HIDDEN;
 
-HRESULT WINAPI JoystickAGenericImpl_Poll(LPDIRECTINPUTDEVICE8A iface) DECLSPEC_HIDDEN;
 HRESULT WINAPI JoystickWGenericImpl_Poll(LPDIRECTINPUTDEVICE8W iface) DECLSPEC_HIDDEN;
 
-HRESULT WINAPI JoystickAGenericImpl_GetDeviceState(LPDIRECTINPUTDEVICE8A iface, DWORD len, LPVOID ptr) DECLSPEC_HIDDEN;
 HRESULT WINAPI JoystickWGenericImpl_GetDeviceState(LPDIRECTINPUTDEVICE8W iface, DWORD len, LPVOID ptr) DECLSPEC_HIDDEN;
 
-HRESULT WINAPI JoystickAGenericImpl_BuildActionMap(LPDIRECTINPUTDEVICE8A iface, LPDIACTIONFORMATA lpdiaf, LPCSTR lpszUserName, DWORD dwFlags) DECLSPEC_HIDDEN;
 HRESULT WINAPI JoystickWGenericImpl_BuildActionMap(LPDIRECTINPUTDEVICE8W iface, LPDIACTIONFORMATW lpdiaf, LPCWSTR lpszUserName, DWORD dwFlags) DECLSPEC_HIDDEN;
 
-HRESULT WINAPI JoystickAGenericImpl_SetActionMap(LPDIRECTINPUTDEVICE8A iface, LPDIACTIONFORMATA lpdiaf, LPCSTR lpszUserName, DWORD dwFlags) DECLSPEC_HIDDEN;
 HRESULT WINAPI JoystickWGenericImpl_SetActionMap(LPDIRECTINPUTDEVICE8W iface, LPDIACTIONFORMATW lpdiaf, LPCWSTR lpszUserName, DWORD dwFlags) DECLSPEC_HIDDEN;
 
 DWORD typeFromGUID(REFGUID guid) DECLSPEC_HIDDEN;
diff --git a/dlls/dinput/keyboard.c b/dlls/dinput/keyboard.c
index 46f0ce140e0..663806360b5 100644
--- a/dlls/dinput/keyboard.c
+++ b/dlls/dinput/keyboard.c
@@ -40,7 +40,6 @@ WINE_DEFAULT_DEBUG_CHANNEL(dinput);
 
 #define WINE_DINPUT_KEYBOARD_MAX_KEYS 256
 
-static const IDirectInputDevice8AVtbl SysKeyboardAvt;
 static const IDirectInputDevice8WVtbl SysKeyboardWvt;
 
 typedef struct SysKeyboardImpl SysKeyboardImpl;
@@ -258,7 +257,7 @@ static SysKeyboardImpl *alloc_device(REFGUID rguid, IDirectInputImpl *dinput)
     LPDIDATAFORMAT df = NULL;
     int i, idx = 0;
 
-    if (FAILED(direct_input_device_alloc(sizeof(SysKeyboardImpl), &SysKeyboardWvt, &SysKeyboardAvt, rguid, dinput, (void **)&newDevice)))
+    if (FAILED(direct_input_device_alloc(sizeof(SysKeyboardImpl), &SysKeyboardWvt, rguid, dinput, (void **)&newDevice)))
         return NULL;
     newDevice->base.crit.DebugInfo->Spare[0] = (DWORD_PTR)(__FILE__ ": SysKeyboardImpl*->base.crit");
 
@@ -376,12 +375,6 @@ static HRESULT WINAPI SysKeyboardWImpl_GetDeviceState(LPDIRECTINPUTDEVICE8W ifac
     return DI_OK;
 }
 
-static HRESULT WINAPI SysKeyboardAImpl_GetDeviceState(LPDIRECTINPUTDEVICE8A iface, DWORD len, LPVOID ptr)
-{
-    SysKeyboardImpl *This = impl_from_IDirectInputDevice8A(iface);
-    return SysKeyboardWImpl_GetDeviceState(IDirectInputDevice8W_from_impl(This), len, ptr);
-}
-
 /******************************************************************************
   *     GetCapabilities : get the device capabilities
   */
@@ -417,12 +410,6 @@ static HRESULT WINAPI SysKeyboardWImpl_GetCapabilities(LPDIRECTINPUTDEVICE8W ifa
     return DI_OK;
 }
 
-static HRESULT WINAPI SysKeyboardAImpl_GetCapabilities(LPDIRECTINPUTDEVICE8A iface, LPDIDEVCAPS lpDIDevCaps)
-{
-    SysKeyboardImpl *This = impl_from_IDirectInputDevice8A(iface);
-    return SysKeyboardWImpl_GetCapabilities(IDirectInputDevice8W_from_impl(This), lpDIDevCaps);
-}
-
 static DWORD map_dik_to_scan(DWORD dik_code, DWORD subtype)
 {
     if (dik_code == DIK_PAUSE || dik_code == DIK_NUMLOCK) dik_code ^= 0x80;
@@ -461,29 +448,6 @@ static DWORD map_dik_to_scan(DWORD dik_code, DWORD subtype)
   *     GetObjectInfo : get information about a device object such as a button
   *                     or axis
   */
-static HRESULT WINAPI
-SysKeyboardAImpl_GetObjectInfo(
-	LPDIRECTINPUTDEVICE8A iface,
-	LPDIDEVICEOBJECTINSTANCEA pdidoi,
-	DWORD dwObj,
-	DWORD dwHow)
-{
-    SysKeyboardImpl *This = impl_from_IDirectInputDevice8A(iface);
-    HRESULT res;
-    LONG scan;
-
-    res = IDirectInputDevice2AImpl_GetObjectInfo(iface, pdidoi, dwObj, dwHow);
-    if (res != DI_OK) return res;
-
-    scan = map_dik_to_scan(DIDFT_GETINSTANCE(pdidoi->dwType), This->subtype);
-    if (!GetKeyNameTextA((scan & 0x80) << 17 | (scan & 0x7f) << 16,
-                         pdidoi->tszName, sizeof(pdidoi->tszName)))
-        return DIERR_OBJECTNOTFOUND;
-
-    _dump_OBJECTINSTANCEA(pdidoi);
-    return res;
-}
-
 static HRESULT WINAPI SysKeyboardWImpl_GetObjectInfo(LPDIRECTINPUTDEVICE8W iface,
 						     LPDIDEVICEOBJECTINSTANCEW pdidoi,
 						     DWORD dwObj,
@@ -508,18 +472,6 @@ static HRESULT WINAPI SysKeyboardWImpl_GetObjectInfo(LPDIRECTINPUTDEVICE8W iface
 /******************************************************************************
   *     GetDeviceInfo : get information about a device's identity
   */
-static HRESULT WINAPI SysKeyboardAImpl_GetDeviceInfo(
-	LPDIRECTINPUTDEVICE8A iface,
-	LPDIDEVICEINSTANCEA pdidi)
-{
-    SysKeyboardImpl *This = impl_from_IDirectInputDevice8A(iface);
-    TRACE("(this=%p,%p)\n", This, pdidi);
-
-    fill_keyboard_dideviceinstanceA(pdidi, This->base.dinput->dwVersion, This->subtype);
-    
-    return DI_OK;
-}
-
 static HRESULT WINAPI SysKeyboardWImpl_GetDeviceInfo(LPDIRECTINPUTDEVICE8W iface, LPDIDEVICEINSTANCEW pdidi)
 {
     SysKeyboardImpl *This = impl_from_IDirectInputDevice8W(iface);
@@ -570,18 +522,11 @@ static HRESULT WINAPI SysKeyboardWImpl_GetProperty(LPDIRECTINPUTDEVICE8W iface,
         case (DWORD_PTR) DIPROP_RANGE:
             return DIERR_UNSUPPORTED;
         default:
-            return IDirectInputDevice2AImpl_GetProperty( IDirectInputDevice8A_from_impl(This), rguid, pdiph );
+            return IDirectInputDevice2WImpl_GetProperty(IDirectInputDevice8W_from_impl(This), rguid, pdiph);
     }
     return DI_OK;
 }
 
-static HRESULT WINAPI SysKeyboardAImpl_GetProperty(LPDIRECTINPUTDEVICE8A iface,
-                                                   REFGUID rguid, LPDIPROPHEADER pdiph)
-{
-    SysKeyboardImpl *This = impl_from_IDirectInputDevice8A(iface);
-    return SysKeyboardWImpl_GetProperty(IDirectInputDevice8W_from_impl(This), rguid, pdiph);
-}
-
 static HRESULT WINAPI SysKeyboardWImpl_Acquire(LPDIRECTINPUTDEVICE8W iface)
 {
     SysKeyboardImpl *This = impl_from_IDirectInputDevice8W(iface);
@@ -599,12 +544,6 @@ static HRESULT WINAPI SysKeyboardWImpl_Acquire(LPDIRECTINPUTDEVICE8W iface)
     return res;
 }
 
-static HRESULT WINAPI SysKeyboardAImpl_Acquire(LPDIRECTINPUTDEVICE8A iface)
-{
-    SysKeyboardImpl *This = impl_from_IDirectInputDevice8A(iface);
-    return SysKeyboardWImpl_Acquire(IDirectInputDevice8W_from_impl(This));
-}
-
 static HRESULT WINAPI SysKeyboardWImpl_BuildActionMap(LPDIRECTINPUTDEVICE8W iface,
                                                       LPDIACTIONFORMATW lpdiaf,
                                                       LPCWSTR lpszUserName,
@@ -616,36 +555,6 @@ static HRESULT WINAPI SysKeyboardWImpl_BuildActionMap(LPDIRECTINPUTDEVICE8W ifac
     return  _build_action_map(iface, lpdiaf, lpszUserName, dwFlags, DIKEYBOARD_MASK, &c_dfDIKeyboard);
 }
 
-static HRESULT WINAPI SysKeyboardAImpl_BuildActionMap(LPDIRECTINPUTDEVICE8A iface,
-                                                      LPDIACTIONFORMATA lpdiaf,
-                                                      LPCSTR lpszUserName,
-                                                      DWORD dwFlags)
-{
-    SysKeyboardImpl *This = impl_from_IDirectInputDevice8A(iface);
-    DIACTIONFORMATW diafW;
-    HRESULT hr;
-    WCHAR *lpszUserNameW = NULL;
-    int username_size;
-
-    diafW.rgoAction = HeapAlloc(GetProcessHeap(), 0, sizeof(DIACTIONW)*lpdiaf->dwNumActions);
-    _copy_diactionformatAtoW(&diafW, lpdiaf);
-
-    if (lpszUserName != NULL)
-    {
-        username_size = MultiByteToWideChar(CP_ACP, 0, lpszUserName, -1, NULL, 0);
-        lpszUserNameW = HeapAlloc(GetProcessHeap(), 0, sizeof(WCHAR)*username_size);
-        MultiByteToWideChar(CP_ACP, 0, lpszUserName, -1, lpszUserNameW, username_size);
-    }
-
-    hr = SysKeyboardWImpl_BuildActionMap(&This->base.IDirectInputDevice8W_iface, &diafW, lpszUserNameW, dwFlags);
-
-    _copy_diactionformatWtoA(lpdiaf, &diafW);
-    HeapFree(GetProcessHeap(), 0, diafW.rgoAction);
-    HeapFree(GetProcessHeap(), 0, lpszUserNameW);
-
-    return hr;
-}
-
 static HRESULT WINAPI SysKeyboardWImpl_SetActionMap(LPDIRECTINPUTDEVICE8W iface,
                                                     LPDIACTIONFORMATW lpdiaf,
                                                     LPCWSTR lpszUserName,
@@ -657,71 +566,6 @@ static HRESULT WINAPI SysKeyboardWImpl_SetActionMap(LPDIRECTINPUTDEVICE8W iface,
     return _set_action_map(iface, lpdiaf, lpszUserName, dwFlags, &c_dfDIKeyboard);
 }
 
-static HRESULT WINAPI SysKeyboardAImpl_SetActionMap(LPDIRECTINPUTDEVICE8A iface,
-                                                    LPDIACTIONFORMATA lpdiaf,
-                                                    LPCSTR lpszUserName,
-                                                    DWORD dwFlags)
-{
-    SysKeyboardImpl *This = impl_from_IDirectInputDevice8A(iface);
-    DIACTIONFORMATW diafW;
-    HRESULT hr;
-    WCHAR *lpszUserNameW = NULL;
-    int username_size;
-
-    diafW.rgoAction = HeapAlloc(GetProcessHeap(), 0, sizeof(DIACTIONW)*lpdiaf->dwNumActions);
-    _copy_diactionformatAtoW(&diafW, lpdiaf);
-
-    if (lpszUserName != NULL)
-    {
-        username_size = MultiByteToWideChar(CP_ACP, 0, lpszUserName, -1, NULL, 0);
-        lpszUserNameW = HeapAlloc(GetProcessHeap(), 0, sizeof(WCHAR)*username_size);
-        MultiByteToWideChar(CP_ACP, 0, lpszUserName, -1, lpszUserNameW, username_size);
-    }
-
-    hr = SysKeyboardWImpl_SetActionMap(&This->base.IDirectInputDevice8W_iface, &diafW, lpszUserNameW, dwFlags);
-
-    HeapFree(GetProcessHeap(), 0, diafW.rgoAction);
-    HeapFree(GetProcessHeap(), 0, lpszUserNameW);
-
-    return hr;
-}
-
-static const IDirectInputDevice8AVtbl SysKeyboardAvt =
-{
-    IDirectInputDevice2AImpl_QueryInterface,
-    IDirectInputDevice2AImpl_AddRef,
-    IDirectInputDevice2AImpl_Release,
-    SysKeyboardAImpl_GetCapabilities,
-    IDirectInputDevice2AImpl_EnumObjects,
-    SysKeyboardAImpl_GetProperty,
-    IDirectInputDevice2AImpl_SetProperty,
-    SysKeyboardAImpl_Acquire,
-    IDirectInputDevice2AImpl_Unacquire,
-    SysKeyboardAImpl_GetDeviceState,
-    IDirectInputDevice2AImpl_GetDeviceData,
-    IDirectInputDevice2AImpl_SetDataFormat,
-    IDirectInputDevice2AImpl_SetEventNotification,
-    IDirectInputDevice2AImpl_SetCooperativeLevel,
-    SysKeyboardAImpl_GetObjectInfo,
-    SysKeyboardAImpl_GetDeviceInfo,
-    IDirectInputDevice2AImpl_RunControlPanel,
-    IDirectInputDevice2AImpl_Initialize,
-    IDirectInputDevice2AImpl_CreateEffect,
-    IDirectInputDevice2AImpl_EnumEffects,
-    IDirectInputDevice2AImpl_GetEffectInfo,
-    IDirectInputDevice2AImpl_GetForceFeedbackState,
-    IDirectInputDevice2AImpl_SendForceFeedbackCommand,
-    IDirectInputDevice2AImpl_EnumCreatedEffectObjects,
-    IDirectInputDevice2AImpl_Escape,
-    IDirectInputDevice2AImpl_Poll,
-    IDirectInputDevice2AImpl_SendDeviceData,
-    IDirectInputDevice7AImpl_EnumEffectsInFile,
-    IDirectInputDevice7AImpl_WriteEffectToFile,
-    SysKeyboardAImpl_BuildActionMap,
-    SysKeyboardAImpl_SetActionMap,
-    IDirectInputDevice8AImpl_GetImageInfo
-};
-
 static const IDirectInputDevice8WVtbl SysKeyboardWvt =
 {
     IDirectInputDevice2WImpl_QueryInterface,
diff --git a/dlls/dinput/mouse.c b/dlls/dinput/mouse.c
index a741110419c..2fa055cf8c9 100644
--- a/dlls/dinput/mouse.c
+++ b/dlls/dinput/mouse.c
@@ -47,7 +47,6 @@ WINE_DEFAULT_DEBUG_CHANNEL(dinput);
 #define WINE_MOUSE_Z_AXIS_INSTANCE   2
 #define WINE_MOUSE_BUTTONS_INSTANCE  3
 
-static const IDirectInputDevice8AVtbl SysMouseAvt;
 static const IDirectInputDevice8WVtbl SysMouseWvt;
 
 typedef struct SysMouseImpl SysMouseImpl;
@@ -201,7 +200,7 @@ static SysMouseImpl *alloc_device(REFGUID rguid, IDirectInputImpl *dinput)
     char buffer[20];
     HKEY hkey, appkey;
 
-    if (FAILED(direct_input_device_alloc(sizeof(SysMouseImpl), &SysMouseWvt, &SysMouseAvt, rguid, dinput, (void **)&newDevice)))
+    if (FAILED(direct_input_device_alloc(sizeof(SysMouseImpl), &SysMouseWvt, rguid, dinput, (void **)&newDevice)))
         return NULL;
     newDevice->base.crit.DebugInfo->Spare[0] = (DWORD_PTR)(__FILE__ ": SysMouseImpl*->base.crit");
 
@@ -577,12 +576,6 @@ static HRESULT WINAPI SysMouseWImpl_Acquire(LPDIRECTINPUTDEVICE8W iface)
     return DI_OK;
 }
 
-static HRESULT WINAPI SysMouseAImpl_Acquire(LPDIRECTINPUTDEVICE8A iface)
-{
-    SysMouseImpl *This = impl_from_IDirectInputDevice8A(iface);
-    return SysMouseWImpl_Acquire(IDirectInputDevice8W_from_impl(This));
-}
-
 /******************************************************************************
   *     Unacquire : frees the mouse
   */
@@ -612,12 +605,6 @@ static HRESULT WINAPI SysMouseWImpl_Unacquire(LPDIRECTINPUTDEVICE8W iface)
     return DI_OK;
 }
 
-static HRESULT WINAPI SysMouseAImpl_Unacquire(LPDIRECTINPUTDEVICE8A iface)
-{
-    SysMouseImpl *This = impl_from_IDirectInputDevice8A(iface);
-    return SysMouseWImpl_Unacquire(IDirectInputDevice8W_from_impl(This));
-}
-
 /******************************************************************************
   *     GetDeviceState : returns the "state" of the mouse.
   *
@@ -652,12 +639,6 @@ static HRESULT WINAPI SysMouseWImpl_GetDeviceState(LPDIRECTINPUTDEVICE8W iface,
     return DI_OK;
 }
 
-static HRESULT WINAPI SysMouseAImpl_GetDeviceState(LPDIRECTINPUTDEVICE8A iface, DWORD len, LPVOID ptr)
-{
-    SysMouseImpl *This = impl_from_IDirectInputDevice8A(iface);
-    return SysMouseWImpl_GetDeviceState(IDirectInputDevice8W_from_impl(This), len, ptr);
-}
-
 /******************************************************************************
   *     GetDeviceData : gets buffered input data.
   */
@@ -672,13 +653,6 @@ static HRESULT WINAPI SysMouseWImpl_GetDeviceData(LPDIRECTINPUTDEVICE8W iface,
     return res;
 }
 
-static HRESULT WINAPI SysMouseAImpl_GetDeviceData(LPDIRECTINPUTDEVICE8A iface,
-        DWORD dodsize, LPDIDEVICEOBJECTDATA dod, LPDWORD entries, DWORD flags)
-{
-    SysMouseImpl *This = impl_from_IDirectInputDevice8A(iface);
-    return SysMouseWImpl_GetDeviceData(IDirectInputDevice8W_from_impl(This), dodsize, dod, entries, flags);
-}
-
 /******************************************************************************
   *     GetProperty : get input device properties
   */
@@ -738,12 +712,6 @@ static HRESULT WINAPI SysMouseWImpl_GetProperty(LPDIRECTINPUTDEVICE8W iface, REF
     return DI_OK;
 }
 
-static HRESULT WINAPI SysMouseAImpl_GetProperty(LPDIRECTINPUTDEVICE8A iface, REFGUID rguid, LPDIPROPHEADER pdiph)
-{
-    SysMouseImpl *This = impl_from_IDirectInputDevice8A(iface);
-    return SysMouseWImpl_GetProperty(IDirectInputDevice8W_from_impl(This), rguid, pdiph);
-}
-
 /******************************************************************************
   *     GetCapabilities : get the device capabilities
   */
@@ -779,12 +747,6 @@ static HRESULT WINAPI SysMouseWImpl_GetCapabilities(LPDIRECTINPUTDEVICE8W iface,
     return DI_OK;
 }
 
-static HRESULT WINAPI SysMouseAImpl_GetCapabilities(LPDIRECTINPUTDEVICE8A iface, LPDIDEVCAPS lpDIDevCaps)
-{
-    SysMouseImpl *This = impl_from_IDirectInputDevice8A(iface);
-    return SysMouseWImpl_GetCapabilities(IDirectInputDevice8W_from_impl(This), lpDIDevCaps);
-}
-
 /******************************************************************************
   *     GetObjectInfo : get information about a device object such as a button
   *                     or axis
@@ -814,42 +776,9 @@ static HRESULT WINAPI SysMouseWImpl_GetObjectInfo(LPDIRECTINPUTDEVICE8W iface,
     return res;
 }
 
-static HRESULT WINAPI SysMouseAImpl_GetObjectInfo(LPDIRECTINPUTDEVICE8A iface,
-        LPDIDEVICEOBJECTINSTANCEA pdidoi, DWORD dwObj, DWORD dwHow)
-{
-    SysMouseImpl *This = impl_from_IDirectInputDevice8A(iface);
-    HRESULT res;
-    DIDEVICEOBJECTINSTANCEW didoiW;
-    DWORD dwSize = pdidoi->dwSize;
-
-    didoiW.dwSize = sizeof(didoiW);
-    res = SysMouseWImpl_GetObjectInfo(IDirectInputDevice8W_from_impl(This), &didoiW, dwObj, dwHow);
-    if (res != DI_OK) return res;
-
-    memset(pdidoi, 0, pdidoi->dwSize);
-    memcpy(pdidoi, &didoiW, FIELD_OFFSET(DIDEVICEOBJECTINSTANCEW, tszName));
-    pdidoi->dwSize = dwSize;
-    WideCharToMultiByte(CP_ACP, 0, didoiW.tszName, -1, pdidoi->tszName,
-                        sizeof(pdidoi->tszName), NULL, NULL);
-
-    return res;
-}
-
 /******************************************************************************
   *     GetDeviceInfo : get information about a device's identity
   */
-static HRESULT WINAPI SysMouseAImpl_GetDeviceInfo(
-	LPDIRECTINPUTDEVICE8A iface,
-	LPDIDEVICEINSTANCEA pdidi)
-{
-    SysMouseImpl *This = impl_from_IDirectInputDevice8A(iface);
-    TRACE("(this=%p,%p)\n", This, pdidi);
-
-    fill_mouse_dideviceinstanceA(pdidi, This->base.dinput->dwVersion);
-    
-    return DI_OK;
-}
-
 static HRESULT WINAPI SysMouseWImpl_GetDeviceInfo(LPDIRECTINPUTDEVICE8W iface, LPDIDEVICEINSTANCEW pdidi)
 {
     SysMouseImpl *This = impl_from_IDirectInputDevice8W(iface);
@@ -875,36 +804,6 @@ static HRESULT WINAPI SysMouseWImpl_BuildActionMap(LPDIRECTINPUTDEVICE8W iface,
     return _build_action_map(iface, lpdiaf, lpszUserName, dwFlags, DIMOUSE_MASK, &c_dfDIMouse2);
 }
 
-static HRESULT WINAPI SysMouseAImpl_BuildActionMap(LPDIRECTINPUTDEVICE8A iface,
-                                                   LPDIACTIONFORMATA lpdiaf,
-                                                   LPCSTR lpszUserName,
-                                                   DWORD dwFlags)
-{
-    SysMouseImpl *This = impl_from_IDirectInputDevice8A(iface);
-    DIACTIONFORMATW diafW;
-    HRESULT hr;
-    WCHAR *lpszUserNameW = NULL;
-    int username_size;
-
-    diafW.rgoAction = HeapAlloc(GetProcessHeap(), 0, sizeof(DIACTIONW)*lpdiaf->dwNumActions);
-    _copy_diactionformatAtoW(&diafW, lpdiaf);
-
-    if (lpszUserName != NULL)
-    {
-        username_size = MultiByteToWideChar(CP_ACP, 0, lpszUserName, -1, NULL, 0);
-        lpszUserNameW = HeapAlloc(GetProcessHeap(), 0, sizeof(WCHAR)*username_size);
-        MultiByteToWideChar(CP_ACP, 0, lpszUserName, -1, lpszUserNameW, username_size);
-    }
-
-    hr = SysMouseWImpl_BuildActionMap(&This->base.IDirectInputDevice8W_iface, &diafW, lpszUserNameW, dwFlags);
-
-    _copy_diactionformatWtoA(lpdiaf, &diafW);
-    HeapFree(GetProcessHeap(), 0, diafW.rgoAction);
-    HeapFree(GetProcessHeap(), 0, lpszUserNameW);
-
-    return hr;
-}
-
 static HRESULT WINAPI SysMouseWImpl_SetActionMap(LPDIRECTINPUTDEVICE8W iface,
                                                  LPDIACTIONFORMATW lpdiaf,
                                                  LPCWSTR lpszUserName,
@@ -916,71 +815,6 @@ static HRESULT WINAPI SysMouseWImpl_SetActionMap(LPDIRECTINPUTDEVICE8W iface,
     return _set_action_map(iface, lpdiaf, lpszUserName, dwFlags, &c_dfDIMouse2);
 }
 
-static HRESULT WINAPI SysMouseAImpl_SetActionMap(LPDIRECTINPUTDEVICE8A iface,
-                                                 LPDIACTIONFORMATA lpdiaf,
-                                                 LPCSTR lpszUserName,
-                                                 DWORD dwFlags)
-{
-    SysMouseImpl *This = impl_from_IDirectInputDevice8A(iface);
-    DIACTIONFORMATW diafW;
-    HRESULT hr;
-    WCHAR *lpszUserNameW = NULL;
-    int username_size;
-
-    diafW.rgoAction = HeapAlloc(GetProcessHeap(), 0, sizeof(DIACTIONW)*lpdiaf->dwNumActions);
-    _copy_diactionformatAtoW(&diafW, lpdiaf);
-
-    if (lpszUserName != NULL)
-    {
-        username_size = MultiByteToWideChar(CP_ACP, 0, lpszUserName, -1, NULL, 0);
-        lpszUserNameW = HeapAlloc(GetProcessHeap(), 0, sizeof(WCHAR)*username_size);
-        MultiByteToWideChar(CP_ACP, 0, lpszUserName, -1, lpszUserNameW, username_size);
-    }
-
-    hr = SysMouseWImpl_SetActionMap(&This->base.IDirectInputDevice8W_iface, &diafW, lpszUserNameW, dwFlags);
-
-    HeapFree(GetProcessHeap(), 0, diafW.rgoAction);
-    HeapFree(GetProcessHeap(), 0, lpszUserNameW);
-
-    return hr;
-}
-
-static const IDirectInputDevice8AVtbl SysMouseAvt =
-{
-    IDirectInputDevice2AImpl_QueryInterface,
-    IDirectInputDevice2AImpl_AddRef,
-    IDirectInputDevice2AImpl_Release,
-    SysMouseAImpl_GetCapabilities,
-    IDirectInputDevice2AImpl_EnumObjects,
-    SysMouseAImpl_GetProperty,
-    IDirectInputDevice2AImpl_SetProperty,
-    SysMouseAImpl_Acquire,
-    SysMouseAImpl_Unacquire,
-    SysMouseAImpl_GetDeviceState,
-    SysMouseAImpl_GetDeviceData,
-    IDirectInputDevice2AImpl_SetDataFormat,
-    IDirectInputDevice2AImpl_SetEventNotification,
-    IDirectInputDevice2AImpl_SetCooperativeLevel,
-    SysMouseAImpl_GetObjectInfo,
-    SysMouseAImpl_GetDeviceInfo,
-    IDirectInputDevice2AImpl_RunControlPanel,
-    IDirectInputDevice2AImpl_Initialize,
-    IDirectInputDevice2AImpl_CreateEffect,
-    IDirectInputDevice2AImpl_EnumEffects,
-    IDirectInputDevice2AImpl_GetEffectInfo,
-    IDirectInputDevice2AImpl_GetForceFeedbackState,
-    IDirectInputDevice2AImpl_SendForceFeedbackCommand,
-    IDirectInputDevice2AImpl_EnumCreatedEffectObjects,
-    IDirectInputDevice2AImpl_Escape,
-    IDirectInputDevice2AImpl_Poll,
-    IDirectInputDevice2AImpl_SendDeviceData,
-    IDirectInputDevice7AImpl_EnumEffectsInFile,
-    IDirectInputDevice7AImpl_WriteEffectToFile,
-    SysMouseAImpl_BuildActionMap,
-    SysMouseAImpl_SetActionMap,
-    IDirectInputDevice8AImpl_GetImageInfo
-};
-
 static const IDirectInputDevice8WVtbl SysMouseWvt =
 {
     IDirectInputDevice2WImpl_QueryInterface,
diff --git a/dlls/dinput8/Makefile.in b/dlls/dinput8/Makefile.in
index 5f0dce97caa..35b3bfb75f5 100644
--- a/dlls/dinput8/Makefile.in
+++ b/dlls/dinput8/Makefile.in
@@ -6,6 +6,7 @@ EXTRALIBS = $(IOKIT_LIBS) $(FORCEFEEDBACK_LIBS)
 PARENTSRC = ../dinput
 
 C_SRCS = \
+	ansi.c \
 	config.c \
 	data_formats.c \
 	device.c \
-- 
2.28.0

>From 612b32ae986a3cf7a37a24aa77aed3049db8058c Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?R=C3=A9mi=20Bernon?= <rbernon@codeweavers.com>
Date: Mon, 5 Oct 2020 12:44:47 +0200
Subject: [PATCH 03/39] dinput: Primarily and consistently use
 IDirectInputDevice8W.

Instead of inconsistently using IDirectInputDevice8A.
---
 dlls/dinput/device.c              | 18 +++++++++---------
 dlls/dinput/device_private.h      |  4 ++--
 dlls/dinput/dinput_main.c         | 14 +++++++-------
 dlls/dinput/dinput_private.h      |  6 +++---
 dlls/dinput/joystick.c            | 16 ++--------------
 dlls/dinput/joystick_linux.c      | 16 +++-------------
 dlls/dinput/joystick_linuxinput.c | 16 +++-------------
 dlls/dinput/joystick_osx.c        | 14 ++------------
 dlls/dinput/joystick_private.h    |  2 +-
 dlls/dinput/keyboard.c            | 18 +++---------------
 dlls/dinput/mouse.c               | 17 ++++-------------
 11 files changed, 39 insertions(+), 102 deletions(-)

diff --git a/dlls/dinput/device.c b/dlls/dinput/device.c
index c3052aa4319..6b71f93f24b 100644
--- a/dlls/dinput/device.c
+++ b/dlls/dinput/device.c
@@ -53,11 +53,11 @@ static inline IDirectInputDeviceImpl *impl_from_IDirectInputDevice8W(IDirectInpu
     return CONTAINING_RECORD(iface, IDirectInputDeviceImpl, IDirectInputDevice8W_iface);
 }
 
-static inline IDirectInputDevice8A *IDirectInputDevice8A_from_impl(IDirectInputDeviceImpl *This)
+static IDirectInputDevice8A *IDirectInputDevice8A_from_impl(IDirectInputDeviceImpl *This)
 {
     return &This->IDirectInputDevice8A_iface;
 }
-static inline IDirectInputDevice8W *IDirectInputDevice8W_from_impl(IDirectInputDeviceImpl *This)
+static IDirectInputDevice8W *IDirectInputDevice8W_from_impl(IDirectInputDeviceImpl *This)
 {
     return &This->IDirectInputDevice8W_iface;
 }
@@ -400,7 +400,7 @@ void release_DataFormat(DataFormat * format)
     format->user_df = NULL;
 }
 
-static inline LPDIOBJECTDATAFORMAT dataformat_to_odf(LPCDIDATAFORMAT df, int idx)
+static LPDIOBJECTDATAFORMAT dataformat_to_odf(LPCDIDATAFORMAT df, int idx)
 {
     if (idx < 0 || idx >= df->dwNumObjs) return NULL;
     return (LPDIOBJECTDATAFORMAT)((LPBYTE)df->rgodf + idx * df->dwObjSize);
@@ -930,10 +930,10 @@ HRESULT _set_action_map(LPDIRECTINPUTDEVICE8W iface, LPDIACTIONFORMATW lpdiaf, L
  *	queue_event - add new event to the ring queue
  */
 
-void queue_event(LPDIRECTINPUTDEVICE8A iface, int inst_id, DWORD data, DWORD time, DWORD seq)
+void queue_event(IDirectInputDevice8W *iface, int inst_id, DWORD data, DWORD time, DWORD seq)
 {
     static ULONGLONG notify_ms = 0;
-    IDirectInputDeviceImpl *This = impl_from_IDirectInputDevice8A(iface);
+    IDirectInputDeviceImpl *This = impl_from_IDirectInputDevice8W(iface);
     int next_pos, ofs = id_to_offset(&This->data_format, inst_id);
     ULONGLONG time_ms = GetTickCount64();
 
@@ -1152,8 +1152,7 @@ HRESULT WINAPI IDirectInputDevice2WImpl_QueryInterface(LPDIRECTINPUTDEVICE8W ifa
     IDirectInputDeviceImpl *This = impl_from_IDirectInputDevice8W(iface);
 
     TRACE("(%p)->(%s,%p)\n", This, debugstr_guid(riid), ppobj);
-    if (IsEqualGUID(&IID_IUnknown, riid) ||
-        IsEqualGUID(&IID_IDirectInputDeviceA,  riid) ||
+    if (IsEqualGUID(&IID_IDirectInputDeviceA,  riid) ||
         IsEqualGUID(&IID_IDirectInputDevice2A, riid) ||
         IsEqualGUID(&IID_IDirectInputDevice7A, riid) ||
         IsEqualGUID(&IID_IDirectInputDevice8A, riid))
@@ -1162,7 +1161,8 @@ HRESULT WINAPI IDirectInputDevice2WImpl_QueryInterface(LPDIRECTINPUTDEVICE8W ifa
         *ppobj = IDirectInputDevice8A_from_impl(This);
         return DI_OK;
     }
-    if (IsEqualGUID(&IID_IDirectInputDeviceW,  riid) ||
+    if (IsEqualGUID(&IID_IUnknown, riid) ||
+        IsEqualGUID(&IID_IDirectInputDeviceW,  riid) ||
         IsEqualGUID(&IID_IDirectInputDevice2W, riid) ||
         IsEqualGUID(&IID_IDirectInputDevice7W, riid) ||
         IsEqualGUID(&IID_IDirectInputDevice8W, riid))
@@ -1631,8 +1631,8 @@ HRESULT direct_input_device_alloc(SIZE_T size, const IDirectInputDevice8WVtbl *v
 {
     IDirectInputDeviceImpl *This;
     if (!(This = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, size))) return DIERR_OUTOFMEMORY;
-    This->IDirectInputDevice8A_iface.lpVtbl = &direct_input_device_a_vtbl;
     This->IDirectInputDevice8W_iface.lpVtbl = vtbl;
+    This->IDirectInputDevice8A_iface.lpVtbl = &direct_input_device_a_vtbl;
     This->ref = 1;
     This->guid = *guid;
     InitializeCriticalSection(&This->crit);
diff --git a/dlls/dinput/device_private.h b/dlls/dinput/device_private.h
index 9a0202840c4..fcab6dbedd0 100644
--- a/dlls/dinput/device_private.h
+++ b/dlls/dinput/device_private.h
@@ -57,8 +57,8 @@ typedef struct
 typedef struct IDirectInputDeviceImpl IDirectInputDeviceImpl;
 struct IDirectInputDeviceImpl
 {
-    IDirectInputDevice8A        IDirectInputDevice8A_iface;
     IDirectInputDevice8W        IDirectInputDevice8W_iface;
+    IDirectInputDevice8A        IDirectInputDevice8A_iface;
     LONG                        ref;
     GUID                        guid;
     CRITICAL_SECTION            crit;
@@ -97,7 +97,7 @@ extern DWORD get_config_key(HKEY, HKEY, const char*, char*, DWORD) DECLSPEC_HIDD
 /* Routines to do DataFormat / WineFormat conversions */
 extern void fill_DataFormat(void *out, DWORD size, const void *in, const DataFormat *df)  DECLSPEC_HIDDEN;
 extern void release_DataFormat(DataFormat *df)  DECLSPEC_HIDDEN;
-extern void queue_event(LPDIRECTINPUTDEVICE8A iface, int inst_id, DWORD data, DWORD time, DWORD seq) DECLSPEC_HIDDEN;
+extern void queue_event(IDirectInputDevice8W *iface, int inst_id, DWORD data, DWORD time, DWORD seq) DECLSPEC_HIDDEN;
 /* Helper functions to work with data format */
 extern int id_to_object(LPCDIDATAFORMAT df, int id) DECLSPEC_HIDDEN;
 extern int find_property(const DataFormat *df, LPCDIPROPHEADER ph) DECLSPEC_HIDDEN;
diff --git a/dlls/dinput/dinput_main.c b/dlls/dinput/dinput_main.c
index 45023fc104a..e3b6eeee3eb 100644
--- a/dlls/dinput/dinput_main.c
+++ b/dlls/dinput/dinput_main.c
@@ -659,7 +659,7 @@ static LRESULT WINAPI di_em_win_wndproc(HWND hwnd, UINT msg, WPARAM wparam, LPAR
         {
             EnterCriticalSection( &dinput_hook_crit );
             LIST_FOR_EACH_ENTRY( dev, &acquired_rawmouse_list, IDirectInputDeviceImpl, entry )
-                dinput_mouse_rawinput_hook( &dev->IDirectInputDevice8A_iface, wparam, lparam, &ri );
+                dinput_mouse_rawinput_hook( &dev->IDirectInputDevice8W_iface, wparam, lparam, &ri );
             LeaveCriticalSection( &dinput_hook_crit );
         }
     }
@@ -1719,13 +1719,13 @@ static LRESULT CALLBACK LL_hook_proc( int code, WPARAM wparam, LPARAM lparam )
     LIST_FOR_EACH_ENTRY( dev, &acquired_mouse_list, IDirectInputDeviceImpl, entry )
     {
         TRACE("calling dinput_mouse_hook (%p %lx %lx)\n", dev, wparam, lparam);
-        skip |= dinput_mouse_hook( &dev->IDirectInputDevice8A_iface, wparam, lparam );
+        skip |= dinput_mouse_hook( &dev->IDirectInputDevice8W_iface, wparam, lparam );
     }
     LIST_FOR_EACH_ENTRY( dev, &acquired_keyboard_list, IDirectInputDeviceImpl, entry )
     {
         if (dev->use_raw_input) continue;
         TRACE("calling dinput_keyboard_hook (%p %lx %lx)\n", dev, wparam, lparam);
-        skip |= dinput_keyboard_hook( &dev->IDirectInputDevice8A_iface, wparam, lparam );
+        skip |= dinput_keyboard_hook( &dev->IDirectInputDevice8W_iface, wparam, lparam );
     }
     LeaveCriticalSection( &dinput_hook_crit );
 
@@ -1750,7 +1750,7 @@ static LRESULT CALLBACK callwndproc_proc( int code, WPARAM wparam, LPARAM lparam
         if (msg->hwnd == dev->win && msg->hwnd != foreground)
         {
             TRACE( "%p window is not foreground - unacquiring %p\n", dev->win, dev );
-            IDirectInputDevice_Unacquire( &dev->IDirectInputDevice8A_iface );
+            IDirectInputDevice_Unacquire( &dev->IDirectInputDevice8W_iface );
         }
     }
     LIST_FOR_EACH_ENTRY_SAFE( dev, next, &acquired_mouse_list, IDirectInputDeviceImpl, entry )
@@ -1758,7 +1758,7 @@ static LRESULT CALLBACK callwndproc_proc( int code, WPARAM wparam, LPARAM lparam
         if (msg->hwnd == dev->win && msg->hwnd != foreground)
         {
             TRACE( "%p window is not foreground - unacquiring %p\n", dev->win, dev );
-            IDirectInputDevice_Unacquire( &dev->IDirectInputDevice8A_iface );
+            IDirectInputDevice_Unacquire( &dev->IDirectInputDevice8W_iface );
         }
     }
     LIST_FOR_EACH_ENTRY_SAFE( dev, next, &acquired_rawmouse_list, IDirectInputDeviceImpl, entry )
@@ -1766,7 +1766,7 @@ static LRESULT CALLBACK callwndproc_proc( int code, WPARAM wparam, LPARAM lparam
         if (msg->hwnd == dev->win && msg->hwnd != foreground)
         {
             TRACE( "%p window is not foreground - unacquiring %p\n", dev->win, dev );
-            IDirectInputDevice_Unacquire( &dev->IDirectInputDevice8A_iface );
+            IDirectInputDevice_Unacquire( &dev->IDirectInputDevice8W_iface );
         }
     }
     LIST_FOR_EACH_ENTRY_SAFE( dev, next, &acquired_keyboard_list, IDirectInputDeviceImpl, entry )
@@ -1774,7 +1774,7 @@ static LRESULT CALLBACK callwndproc_proc( int code, WPARAM wparam, LPARAM lparam
         if (msg->hwnd == dev->win && msg->hwnd != foreground)
         {
             TRACE( "%p window is not foreground - unacquiring %p\n", dev->win, dev );
-            IDirectInputDevice_Unacquire( &dev->IDirectInputDevice8A_iface );
+            IDirectInputDevice_Unacquire( &dev->IDirectInputDevice8W_iface );
         }
     }
     LeaveCriticalSection( &dinput_hook_crit );
diff --git a/dlls/dinput/dinput_private.h b/dlls/dinput/dinput_private.h
index c0c88da9674..e9205234a65 100644
--- a/dlls/dinput/dinput_private.h
+++ b/dlls/dinput/dinput_private.h
@@ -71,9 +71,9 @@ extern const struct dinput_device joystick_osx_device DECLSPEC_HIDDEN;
 
 extern void dinput_hooks_acquire_device(LPDIRECTINPUTDEVICE8W iface);
 extern void dinput_hooks_unacquire_device(LPDIRECTINPUTDEVICE8W iface);
-extern int dinput_mouse_hook(LPDIRECTINPUTDEVICE8A iface, WPARAM wparam, LPARAM lparam);
-extern int dinput_keyboard_hook(LPDIRECTINPUTDEVICE8A iface, WPARAM wparam, LPARAM lparam);
-extern void dinput_mouse_rawinput_hook( LPDIRECTINPUTDEVICE8A iface, WPARAM wparam, LPARAM lparam, RAWINPUT *raw );
+extern int dinput_mouse_hook(IDirectInputDevice8W *iface, WPARAM wparam, LPARAM lparam);
+extern int dinput_keyboard_hook(IDirectInputDevice8W *iface, WPARAM wparam, LPARAM lparam);
+extern void dinput_mouse_rawinput_hook( IDirectInputDevice8W *iface, WPARAM wparam, LPARAM lparam, RAWINPUT *raw );
 
 extern void check_dinput_hooks(LPDIRECTINPUTDEVICE8W, BOOL) DECLSPEC_HIDDEN;
 extern void check_dinput_events(void) DECLSPEC_HIDDEN;
diff --git a/dlls/dinput/joystick.c b/dlls/dinput/joystick.c
index 497bde4a293..fcc968f0d71 100644
--- a/dlls/dinput/joystick.c
+++ b/dlls/dinput/joystick.c
@@ -60,22 +60,10 @@ const GUID DInput_PIDVID_Product_GUID = { /* device_pidvid-0000-0000-0000-504944
     0x00000000, 0x0000, 0x0000, {0x00, 0x00, 0x50, 0x49, 0x44, 0x56, 0x49, 0x44}
 };
 
-static inline JoystickGenericImpl *impl_from_IDirectInputDevice8A(IDirectInputDevice8A *iface)
-{
-    return CONTAINING_RECORD(CONTAINING_RECORD(iface, IDirectInputDeviceImpl, IDirectInputDevice8A_iface), JoystickGenericImpl, base);
-}
 static inline JoystickGenericImpl *impl_from_IDirectInputDevice8W(IDirectInputDevice8W *iface)
 {
     return CONTAINING_RECORD(CONTAINING_RECORD(iface, IDirectInputDeviceImpl, IDirectInputDevice8W_iface), JoystickGenericImpl, base);
 }
-static inline IDirectInputDevice8A *IDirectInputDevice8A_from_impl(JoystickGenericImpl *This)
-{
-    return &This->base.IDirectInputDevice8A_iface;
-}
-static inline IDirectInputDevice8W *IDirectInputDevice8W_from_impl(JoystickGenericImpl *This)
-{
-    return &This->base.IDirectInputDevice8W_iface;
-}
 
 DWORD typeFromGUID(REFGUID guid)
 {
@@ -701,7 +689,7 @@ HRESULT WINAPI JoystickWGenericImpl_Poll(LPDIRECTINPUTDEVICE8W iface)
         return DIERR_NOTACQUIRED;
     }
 
-    This->joy_polldev(IDirectInputDevice8A_from_impl(This));
+    This->joy_polldev(iface);
     return DI_OK;
 }
 
@@ -721,7 +709,7 @@ HRESULT WINAPI JoystickWGenericImpl_GetDeviceState(LPDIRECTINPUTDEVICE8W iface,
     }
 
     /* update joystick state */
-    This->joy_polldev(IDirectInputDevice8A_from_impl(This));
+    This->joy_polldev(iface);
 
     /* convert and copy data to user supplied buffer */
     fill_DataFormat(ptr, len, &This->js, &This->base.data_format);
diff --git a/dlls/dinput/joystick_linux.c b/dlls/dinput/joystick_linux.c
index 29066f514cc..76e7e2bcaab 100644
--- a/dlls/dinput/joystick_linux.c
+++ b/dlls/dinput/joystick_linux.c
@@ -102,22 +102,12 @@ struct JoystickImpl
         POINTL                          povs[4];
 };
 
-static inline JoystickImpl *impl_from_IDirectInputDevice8A(IDirectInputDevice8A *iface)
-{
-    return CONTAINING_RECORD(CONTAINING_RECORD(CONTAINING_RECORD(iface, IDirectInputDeviceImpl, IDirectInputDevice8A_iface),
-           JoystickGenericImpl, base), JoystickImpl, generic);
-}
 static inline JoystickImpl *impl_from_IDirectInputDevice8W(IDirectInputDevice8W *iface)
 {
     return CONTAINING_RECORD(CONTAINING_RECORD(CONTAINING_RECORD(iface, IDirectInputDeviceImpl, IDirectInputDevice8W_iface),
            JoystickGenericImpl, base), JoystickImpl, generic);
 }
 
-static inline IDirectInputDevice8W *IDirectInputDevice8W_from_impl(JoystickImpl *This)
-{
-    return &This->generic.base.IDirectInputDevice8W_iface;
-}
-
 static const GUID DInput_Wine_Joystick_GUID = { /* 9e573ed9-7734-11d2-8d4a-23903fb6bdf7 */
   0x9e573ed9,
   0x7734,
@@ -129,7 +119,7 @@ static const GUID DInput_Wine_Joystick_GUID = { /* 9e573ed9-7734-11d2-8d4a-23903
 static INT joystick_devices_count = -1;
 static struct JoyDev *joystick_devices;
 
-static void joy_polldev(LPDIRECTINPUTDEVICE8A iface);
+static void joy_polldev(IDirectInputDevice8W *iface);
 
 #define SYS_PATH_FORMAT "/sys/class/input/js%d/device/id/%s"
 static BOOL read_sys_id_variable(int index, const char *property, WORD *value)
@@ -793,11 +783,11 @@ static HRESULT WINAPI JoystickLinuxWImpl_Unacquire(LPDIRECTINPUTDEVICE8W iface)
     return DI_NOEFFECT;
 }
 
-static void joy_polldev(LPDIRECTINPUTDEVICE8A iface)
+static void joy_polldev(IDirectInputDevice8W *iface)
 {
     struct pollfd plfd;
     struct js_event jse;
-    JoystickImpl *This = impl_from_IDirectInputDevice8A(iface);
+    JoystickImpl *This = impl_from_IDirectInputDevice8W(iface);
 
     TRACE("(%p)\n", This);
 
diff --git a/dlls/dinput/joystick_linuxinput.c b/dlls/dinput/joystick_linuxinput.c
index b285369f80f..a39b727e278 100644
--- a/dlls/dinput/joystick_linuxinput.c
+++ b/dlls/dinput/joystick_linuxinput.c
@@ -136,25 +136,15 @@ struct JoystickImpl
 	int				ff_gain;
 };
 
-static inline JoystickImpl *impl_from_IDirectInputDevice8A(IDirectInputDevice8A *iface)
-{
-    return CONTAINING_RECORD(CONTAINING_RECORD(CONTAINING_RECORD(iface, IDirectInputDeviceImpl, IDirectInputDevice8A_iface),
-           JoystickGenericImpl, base), JoystickImpl, generic);
-}
 static inline JoystickImpl *impl_from_IDirectInputDevice8W(IDirectInputDevice8W *iface)
 {
     return CONTAINING_RECORD(CONTAINING_RECORD(CONTAINING_RECORD(iface, IDirectInputDeviceImpl, IDirectInputDevice8W_iface),
            JoystickGenericImpl, base), JoystickImpl, generic);
 }
 
-static inline IDirectInputDevice8W *IDirectInputDevice8W_from_impl(JoystickImpl *This)
-{
-    return &This->generic.base.IDirectInputDevice8W_iface;
-}
-
 static void fake_current_js_state(JoystickImpl *ji);
 static void find_joydevs(void);
-static void joy_polldev(LPDIRECTINPUTDEVICE8A iface);
+static void joy_polldev(IDirectInputDevice8W *iface);
 
 /* This GUID is slightly different from the linux joystick one. Take note. */
 static const GUID DInput_Wine_Joystick_Base_GUID = { /* 9e573eda-7734-11d2-8d4a-23903fb6bdf7 */
@@ -788,11 +778,11 @@ static void fake_current_js_state(JoystickImpl *ji)
 #undef CENTER_AXIS
 
 /* convert wine format offset to user format object index */
-static void joy_polldev(LPDIRECTINPUTDEVICE8A iface)
+static void joy_polldev(IDirectInputDevice8W *iface)
 {
     struct pollfd plfd;
     struct input_event ie;
-    JoystickImpl *This = impl_from_IDirectInputDevice8A(iface);
+    JoystickImpl *This = impl_from_IDirectInputDevice8W(iface);
 
     if (This->joyfd==-1)
 	return;
diff --git a/dlls/dinput/joystick_osx.c b/dlls/dinput/joystick_osx.c
index 8dde986be3e..0d14de6ba58 100644
--- a/dlls/dinput/joystick_osx.c
+++ b/dlls/dinput/joystick_osx.c
@@ -113,22 +113,12 @@ struct JoystickImpl
     struct list effects;
 };
 
-static inline JoystickImpl *impl_from_IDirectInputDevice8A(IDirectInputDevice8A *iface)
-{
-    return CONTAINING_RECORD(CONTAINING_RECORD(CONTAINING_RECORD(iface, IDirectInputDeviceImpl, IDirectInputDevice8A_iface),
-           JoystickGenericImpl, base), JoystickImpl, generic);
-}
 static inline JoystickImpl *impl_from_IDirectInputDevice8W(IDirectInputDevice8W *iface)
 {
     return CONTAINING_RECORD(CONTAINING_RECORD(CONTAINING_RECORD(iface, IDirectInputDeviceImpl, IDirectInputDevice8W_iface),
            JoystickGenericImpl, base), JoystickImpl, generic);
 }
 
-static inline IDirectInputDevice8W *IDirectInputDevice8W_from_impl(JoystickImpl *This)
-{
-    return &This->generic.base.IDirectInputDevice8W_iface;
-}
-
 typedef struct _EffectImpl {
     IDirectInputEffect IDirectInputEffect_iface;
     LONG ref;
@@ -766,9 +756,9 @@ static void get_osx_device_elements_props(JoystickImpl *device)
     }
 }
 
-static void poll_osx_device_state(LPDIRECTINPUTDEVICE8A iface)
+static void poll_osx_device_state(IDirectInputDevice8W *iface)
 {
-    JoystickImpl *device = impl_from_IDirectInputDevice8A(iface);
+    JoystickImpl *device = impl_from_IDirectInputDevice8W(iface);
     IOHIDElementRef device_main_element;
     IOHIDDeviceRef hid_device;
 
diff --git a/dlls/dinput/joystick_private.h b/dlls/dinput/joystick_private.h
index 8bb683c20f4..5327fa60566 100644
--- a/dlls/dinput/joystick_private.h
+++ b/dlls/dinput/joystick_private.h
@@ -33,7 +33,7 @@
 #define MAX_PROPS 164
 struct JoystickGenericImpl;
 
-typedef void joy_polldev_handler(LPDIRECTINPUTDEVICE8A iface);
+typedef void joy_polldev_handler(IDirectInputDevice8W *iface);
 
 typedef struct JoystickGenericImpl
 {
diff --git a/dlls/dinput/keyboard.c b/dlls/dinput/keyboard.c
index 663806360b5..63952f1f3ff 100644
--- a/dlls/dinput/keyboard.c
+++ b/dlls/dinput/keyboard.c
@@ -50,22 +50,10 @@ struct SysKeyboardImpl
     DWORD subtype;
 };
 
-static inline SysKeyboardImpl *impl_from_IDirectInputDevice8A(IDirectInputDevice8A *iface)
-{
-    return CONTAINING_RECORD(CONTAINING_RECORD(iface, IDirectInputDeviceImpl, IDirectInputDevice8A_iface), SysKeyboardImpl, base);
-}
 static inline SysKeyboardImpl *impl_from_IDirectInputDevice8W(IDirectInputDevice8W *iface)
 {
     return CONTAINING_RECORD(CONTAINING_RECORD(iface, IDirectInputDeviceImpl, IDirectInputDevice8W_iface), SysKeyboardImpl, base);
 }
-static inline IDirectInputDevice8A *IDirectInputDevice8A_from_impl(SysKeyboardImpl *This)
-{
-    return &This->base.IDirectInputDevice8A_iface;
-}
-static inline IDirectInputDevice8W *IDirectInputDevice8W_from_impl(SysKeyboardImpl *This)
-{
-    return &This->base.IDirectInputDevice8W_iface;
-}
 
 static BYTE map_dik_code(DWORD scanCode, DWORD vkCode, DWORD subType, DWORD version)
 {
@@ -102,9 +90,9 @@ static BYTE map_dik_code(DWORD scanCode, DWORD vkCode, DWORD subType, DWORD vers
     return scanCode;
 }
 
-int dinput_keyboard_hook( LPDIRECTINPUTDEVICE8A iface, WPARAM wparam, LPARAM lparam )
+int dinput_keyboard_hook( IDirectInputDevice8W *iface, WPARAM wparam, LPARAM lparam )
 {
-    SysKeyboardImpl *This = impl_from_IDirectInputDevice8A(iface);
+    SysKeyboardImpl *This = impl_from_IDirectInputDevice8W(iface);
     int dik_code, ret = This->base.dwCoopLevel & DISCL_EXCLUSIVE;
     KBDLLHOOKSTRUCT *hook = (KBDLLHOOKSTRUCT *)lparam;
     BYTE new_diks;
@@ -522,7 +510,7 @@ static HRESULT WINAPI SysKeyboardWImpl_GetProperty(LPDIRECTINPUTDEVICE8W iface,
         case (DWORD_PTR) DIPROP_RANGE:
             return DIERR_UNSUPPORTED;
         default:
-            return IDirectInputDevice2WImpl_GetProperty(IDirectInputDevice8W_from_impl(This), rguid, pdiph);
+            return IDirectInputDevice2WImpl_GetProperty(iface, rguid, pdiph);
     }
     return DI_OK;
 }
diff --git a/dlls/dinput/mouse.c b/dlls/dinput/mouse.c
index 2fa055cf8c9..57da24ddee5 100644
--- a/dlls/dinput/mouse.c
+++ b/dlls/dinput/mouse.c
@@ -77,20 +77,11 @@ struct SysMouseImpl
     WARP_MOUSE                      warp_override;
 };
 
-static inline SysMouseImpl *impl_from_IDirectInputDevice8A(IDirectInputDevice8A *iface)
-{
-    return CONTAINING_RECORD(CONTAINING_RECORD(iface, IDirectInputDeviceImpl, IDirectInputDevice8A_iface), SysMouseImpl, base);
-}
 static inline SysMouseImpl *impl_from_IDirectInputDevice8W(IDirectInputDevice8W *iface)
 {
     return CONTAINING_RECORD(CONTAINING_RECORD(iface, IDirectInputDeviceImpl, IDirectInputDevice8W_iface), SysMouseImpl, base);
 }
 
-static inline IDirectInputDevice8W *IDirectInputDevice8W_from_impl(SysMouseImpl *This)
-{
-    return &This->base.IDirectInputDevice8W_iface;
-}
-
 static void _dump_mouse_state(const DIMOUSESTATE2 *m_state)
 {
     int i;
@@ -305,9 +296,9 @@ const struct dinput_device mouse_device = {
  *	SysMouseA (DInput Mouse support)
  */
 
-void dinput_mouse_rawinput_hook( LPDIRECTINPUTDEVICE8A iface, WPARAM wparam, LPARAM lparam, RAWINPUT *ri )
+void dinput_mouse_rawinput_hook( IDirectInputDevice8W *iface, WPARAM wparam, LPARAM lparam, RAWINPUT *ri )
 {
-    SysMouseImpl* This = impl_from_IDirectInputDevice8A( iface );
+    SysMouseImpl* This = impl_from_IDirectInputDevice8W( iface );
     POINT rel, pt;
     DWORD seq;
     int i, wdata = 0;
@@ -389,10 +380,10 @@ void dinput_mouse_rawinput_hook( LPDIRECTINPUTDEVICE8A iface, WPARAM wparam, LPA
 }
 
 /* low-level mouse hook */
-int dinput_mouse_hook( LPDIRECTINPUTDEVICE8A iface, WPARAM wparam, LPARAM lparam )
+int dinput_mouse_hook( IDirectInputDevice8W *iface, WPARAM wparam, LPARAM lparam )
 {
     MSLLHOOKSTRUCT *hook = (MSLLHOOKSTRUCT *)lparam;
-    SysMouseImpl* This = impl_from_IDirectInputDevice8A(iface);
+    SysMouseImpl* This = impl_from_IDirectInputDevice8W(iface);
     int wdata = 0, inst_id = -1, ret = 0;
 
     TRACE("msg %lx @ (%d %d)\n", wparam, hook->pt.x, hook->pt.y);
-- 
2.28.0

>From aa2d90db1c316226efcc34cb076a7e5aab791767 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?R=C3=A9mi=20Bernon?= <rbernon@codeweavers.com>
Date: Mon, 5 Oct 2020 12:44:47 +0200
Subject: [PATCH 04/39] dinput: Remove unicode parameter from create_device.

---
 dlls/dinput/dinput_main.c         | 17 ++++++++---------
 dlls/dinput/dinput_private.h      |  2 +-
 dlls/dinput/joystick_linux.c      |  9 ++++-----
 dlls/dinput/joystick_linuxinput.c |  9 ++++-----
 dlls/dinput/joystick_osx.c        |  9 ++++-----
 dlls/dinput/keyboard.c            | 10 ++++------
 dlls/dinput/mouse.c               |  9 ++++-----
 7 files changed, 29 insertions(+), 36 deletions(-)

diff --git a/dlls/dinput/dinput_main.c b/dlls/dinput/dinput_main.c
index e3b6eeee3eb..c8ff3bd8bec 100644
--- a/dlls/dinput/dinput_main.c
+++ b/dlls/dinput/dinput_main.c
@@ -850,7 +850,7 @@ static HRESULT WINAPI IDirectInput2WImpl_FindDevice(LPDIRECTINPUT7W iface, REFGU
     return DI_OK;
 }
 
-static HRESULT create_device(IDirectInputImpl *This, REFGUID rguid, REFIID riid, LPVOID *pvOut, BOOL unicode)
+static HRESULT create_device(IDirectInputImpl *This, REFGUID rguid, REFIID riid, LPVOID *pvOut)
 {
     unsigned int i;
 
@@ -869,8 +869,7 @@ static HRESULT create_device(IDirectInputImpl *This, REFGUID rguid, REFIID riid,
         HRESULT ret;
 
         if (!dinput_devices[i]->create_device) continue;
-        if ((ret = dinput_devices[i]->create_device(This, rguid, riid, pvOut, unicode)) == DI_OK)
-            return DI_OK;
+        if ((ret = dinput_devices[i]->create_device(This, rguid, riid, pvOut)) == DI_OK) return DI_OK;
     }
 
     WARN("invalid device GUID %s\n", debugstr_guid(rguid));
@@ -884,7 +883,7 @@ static HRESULT WINAPI IDirectInput7AImpl_CreateDeviceEx(LPDIRECTINPUT7A iface, R
 
     TRACE("(%p)->(%s, %s, %p, %p)\n", This, debugstr_guid(rguid), debugstr_guid(riid), pvOut, lpUnknownOuter);
 
-    return create_device(This, rguid, riid, pvOut, FALSE);
+    return create_device(This, rguid, riid, pvOut);
 }
 
 static HRESULT WINAPI IDirectInput7WImpl_CreateDeviceEx(LPDIRECTINPUT7W iface, REFGUID rguid,
@@ -894,19 +893,19 @@ static HRESULT WINAPI IDirectInput7WImpl_CreateDeviceEx(LPDIRECTINPUT7W iface, R
 
     TRACE("(%p)->(%s, %s, %p, %p)\n", This, debugstr_guid(rguid), debugstr_guid(riid), pvOut, lpUnknownOuter);
 
-    return create_device(This, rguid, riid, pvOut, TRUE);
+    return create_device(This, rguid, riid, pvOut);
 }
 
 static HRESULT WINAPI IDirectInputAImpl_CreateDevice(LPDIRECTINPUT7A iface, REFGUID rguid,
                                                      LPDIRECTINPUTDEVICEA* pdev, LPUNKNOWN punk)
 {
-    return IDirectInput7AImpl_CreateDeviceEx(iface, rguid, NULL, (LPVOID*)pdev, punk);
+    return IDirectInput7AImpl_CreateDeviceEx(iface, rguid, &IID_IDirectInputDeviceA, (LPVOID *)pdev, punk);
 }
 
 static HRESULT WINAPI IDirectInputWImpl_CreateDevice(LPDIRECTINPUT7W iface, REFGUID rguid,
                                                      LPDIRECTINPUTDEVICEW* pdev, LPUNKNOWN punk)
 {
-    return IDirectInput7WImpl_CreateDeviceEx(iface, rguid, NULL, (LPVOID*)pdev, punk);
+    return IDirectInput7WImpl_CreateDeviceEx(iface, rguid, &IID_IDirectInputDeviceW, (LPVOID *)pdev, punk);
 }
 
 /*******************************************************************************
@@ -953,14 +952,14 @@ static HRESULT WINAPI IDirectInput8AImpl_CreateDevice(LPDIRECTINPUT8A iface, REF
                                                       LPDIRECTINPUTDEVICE8A* pdev, LPUNKNOWN punk)
 {
     IDirectInputImpl *This = impl_from_IDirectInput8A( iface );
-    return IDirectInput7AImpl_CreateDeviceEx( &This->IDirectInput7A_iface, rguid, NULL, (LPVOID*)pdev, punk );
+    return IDirectInput7AImpl_CreateDeviceEx(&This->IDirectInput7A_iface, rguid, &IID_IDirectInputDeviceA, (LPVOID *)pdev, punk);
 }
 
 static HRESULT WINAPI IDirectInput8WImpl_CreateDevice(LPDIRECTINPUT8W iface, REFGUID rguid,
                                                       LPDIRECTINPUTDEVICE8W* pdev, LPUNKNOWN punk)
 {
     IDirectInputImpl *This = impl_from_IDirectInput8W( iface );
-    return IDirectInput7WImpl_CreateDeviceEx( &This->IDirectInput7W_iface, rguid, NULL, (LPVOID*)pdev, punk );
+    return IDirectInput7WImpl_CreateDeviceEx(&This->IDirectInput7W_iface, rguid, &IID_IDirectInputDeviceW, (LPVOID *)pdev, punk);
 }
 
 static HRESULT WINAPI IDirectInput8AImpl_EnumDevices(LPDIRECTINPUT8A iface, DWORD dwDevType, LPDIENUMDEVICESCALLBACKA lpCallback,
diff --git a/dlls/dinput/dinput_private.h b/dlls/dinput/dinput_private.h
index e9205234a65..d174a809924 100644
--- a/dlls/dinput/dinput_private.h
+++ b/dlls/dinput/dinput_private.h
@@ -54,7 +54,7 @@ struct dinput_device {
     const char *name;
     HRESULT (*enum_deviceA)(DWORD dwDevType, DWORD dwFlags, LPDIDEVICEINSTANCEA lpddi, DWORD version, int id);
     HRESULT (*enum_deviceW)(DWORD dwDevType, DWORD dwFlags, LPDIDEVICEINSTANCEW lpddi, DWORD version, int id);
-    HRESULT (*create_device)(IDirectInputImpl *dinput, REFGUID rguid, REFIID riid, LPVOID *pdev, int unicode);
+    HRESULT (*create_device)(IDirectInputImpl *dinput, REFGUID rguid, REFIID riid, LPVOID *pdev);
 };
 
 struct DevicePlayer {
diff --git a/dlls/dinput/joystick_linux.c b/dlls/dinput/joystick_linux.c
index 76e7e2bcaab..d553c390892 100644
--- a/dlls/dinput/joystick_linux.c
+++ b/dlls/dinput/joystick_linux.c
@@ -588,11 +588,12 @@ static unsigned short get_joystick_index(REFGUID guid)
     return MAX_JOYSTICKS;
 }
 
-static HRESULT joydev_create_device(IDirectInputImpl *dinput, REFGUID rguid, REFIID riid, LPVOID *pdev, int unicode)
+static HRESULT joydev_create_device(IDirectInputImpl *dinput, REFGUID rguid, REFIID riid, LPVOID *pdev)
 {
     unsigned short index;
+    int unicode;
 
-    TRACE("%p %s %s %p %i\n", dinput, debugstr_guid(rguid), debugstr_guid(riid), pdev, unicode);
+    TRACE("%p %s %s %p\n", dinput, debugstr_guid(rguid), debugstr_guid(riid), pdev);
     find_joystick_devices();
     *pdev = NULL;
 
@@ -602,9 +603,7 @@ static HRESULT joydev_create_device(IDirectInputImpl *dinput, REFGUID rguid, REF
         JoystickImpl *This;
         HRESULT hr;
 
-        if (riid == NULL)
-            ;/* nothing */
-        else if (IsEqualGUID(&IID_IDirectInputDeviceA,  riid) ||
+        if (IsEqualGUID(&IID_IDirectInputDeviceA,  riid) ||
                  IsEqualGUID(&IID_IDirectInputDevice2A, riid) ||
                  IsEqualGUID(&IID_IDirectInputDevice7A, riid) ||
                  IsEqualGUID(&IID_IDirectInputDevice8A, riid))
diff --git a/dlls/dinput/joystick_linuxinput.c b/dlls/dinput/joystick_linuxinput.c
index a39b727e278..47e9020632c 100644
--- a/dlls/dinput/joystick_linuxinput.c
+++ b/dlls/dinput/joystick_linuxinput.c
@@ -606,11 +606,12 @@ static unsigned short get_joystick_index(REFGUID guid)
     return MAX_JOYDEV;
 }
 
-static HRESULT joydev_create_device(IDirectInputImpl *dinput, REFGUID rguid, REFIID riid, LPVOID *pdev, int unicode)
+static HRESULT joydev_create_device(IDirectInputImpl *dinput, REFGUID rguid, REFIID riid, LPVOID *pdev)
 {
     unsigned short index;
+    int unicode;
 
-    TRACE("%p %s %s %p %i\n", dinput, debugstr_guid(rguid), debugstr_guid(riid), pdev, unicode);
+    TRACE("%p %s %s %p\n", dinput, debugstr_guid(rguid), debugstr_guid(riid), pdev);
     find_joydevs();
     *pdev = NULL;
 
@@ -619,9 +620,7 @@ static HRESULT joydev_create_device(IDirectInputImpl *dinput, REFGUID rguid, REF
     {
         JoystickImpl *This;
 
-        if (riid == NULL)
-            ;/* nothing */
-        else if (IsEqualGUID(&IID_IDirectInputDeviceA,  riid) ||
+        if (IsEqualGUID(&IID_IDirectInputDeviceA,  riid) ||
                  IsEqualGUID(&IID_IDirectInputDevice2A, riid) ||
                  IsEqualGUID(&IID_IDirectInputDevice7A, riid) ||
                  IsEqualGUID(&IID_IDirectInputDevice8A, riid))
diff --git a/dlls/dinput/joystick_osx.c b/dlls/dinput/joystick_osx.c
index 0d14de6ba58..61da492a071 100644
--- a/dlls/dinput/joystick_osx.c
+++ b/dlls/dinput/joystick_osx.c
@@ -1274,12 +1274,13 @@ static unsigned short get_joystick_index(REFGUID guid)
     return 0xffff;
 }
 
-static HRESULT joydev_create_device(IDirectInputImpl *dinput, REFGUID rguid, REFIID riid, LPVOID *pdev, int unicode)
+static HRESULT joydev_create_device(IDirectInputImpl *dinput, REFGUID rguid, REFIID riid, LPVOID *pdev)
 {
     unsigned short index;
     int joystick_devices_count;
+    int unicode;
 
-    TRACE("%p %s %s %p %i\n", dinput, debugstr_guid(rguid), debugstr_guid(riid), pdev, unicode);
+    TRACE("%p %s %s %p\n", dinput, debugstr_guid(rguid), debugstr_guid(riid), pdev);
     *pdev = NULL;
 
     if ((joystick_devices_count = find_joystick_devices()) == 0)
@@ -1291,9 +1292,7 @@ static HRESULT joydev_create_device(IDirectInputImpl *dinput, REFGUID rguid, REF
         JoystickImpl *This;
         HRESULT hr;
 
-        if (riid == NULL)
-            ;/* nothing */
-        else if (IsEqualGUID(&IID_IDirectInputDeviceA,  riid) ||
+        if (IsEqualGUID(&IID_IDirectInputDeviceA,  riid) ||
                  IsEqualGUID(&IID_IDirectInputDevice2A, riid) ||
                  IsEqualGUID(&IID_IDirectInputDevice7A, riid) ||
                  IsEqualGUID(&IID_IDirectInputDevice8A, riid))
diff --git a/dlls/dinput/keyboard.c b/dlls/dinput/keyboard.c
index 63952f1f3ff..70223074e2e 100644
--- a/dlls/dinput/keyboard.c
+++ b/dlls/dinput/keyboard.c
@@ -280,19 +280,17 @@ failed:
     return NULL;
 }
 
-
-static HRESULT keyboarddev_create_device(IDirectInputImpl *dinput, REFGUID rguid, REFIID riid, LPVOID *pdev, int unicode)
+static HRESULT keyboarddev_create_device(IDirectInputImpl *dinput, REFGUID rguid, REFIID riid, LPVOID *pdev)
 {
-    TRACE("%p %s %s %p %i\n", dinput, debugstr_guid(rguid), debugstr_guid(riid), pdev, unicode);
+    int unicode;
+    TRACE("%p %s %s %p\n", dinput, debugstr_guid(rguid), debugstr_guid(riid), pdev);
     *pdev = NULL;
 
     if (IsEqualGUID(&GUID_SysKeyboard, rguid)) /* Wine Keyboard */
     {
         SysKeyboardImpl *This;
 
-        if (riid == NULL)
-            ;/* nothing */
-        else if (IsEqualGUID(&IID_IDirectInputDeviceA,  riid) ||
+        if (IsEqualGUID(&IID_IDirectInputDeviceA,  riid) ||
                  IsEqualGUID(&IID_IDirectInputDevice2A, riid) ||
                  IsEqualGUID(&IID_IDirectInputDevice7A, riid) ||
                  IsEqualGUID(&IID_IDirectInputDevice8A, riid))
diff --git a/dlls/dinput/mouse.c b/dlls/dinput/mouse.c
index 57da24ddee5..f5a49f51a07 100644
--- a/dlls/dinput/mouse.c
+++ b/dlls/dinput/mouse.c
@@ -238,18 +238,17 @@ failed:
     return NULL;
 }
 
-static HRESULT mousedev_create_device(IDirectInputImpl *dinput, REFGUID rguid, REFIID riid, LPVOID *pdev, int unicode)
+static HRESULT mousedev_create_device(IDirectInputImpl *dinput, REFGUID rguid, REFIID riid, LPVOID *pdev)
 {
-    TRACE("%p %s %s %p %i\n", dinput, debugstr_guid(rguid), debugstr_guid(riid), pdev, unicode);
+    int unicode;
+    TRACE("%p %s %s %p\n", dinput, debugstr_guid(rguid), debugstr_guid(riid), pdev);
     *pdev = NULL;
 
     if (IsEqualGUID(&GUID_SysMouse, rguid)) /* Wine Mouse */
     {
         SysMouseImpl *This;
 
-        if (riid == NULL)
-            ;/* nothing */
-        else if (IsEqualGUID(&IID_IDirectInputDeviceA,  riid) ||
+        if (IsEqualGUID(&IID_IDirectInputDeviceA,  riid) ||
                  IsEqualGUID(&IID_IDirectInputDevice2A, riid) ||
                  IsEqualGUID(&IID_IDirectInputDevice7A, riid) ||
                  IsEqualGUID(&IID_IDirectInputDevice8A, riid))
-- 
2.28.0

>From d4978e7d1190845ca61048ad4aa0b48a6c04576c Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?R=C3=A9mi=20Bernon?= <rbernon@codeweavers.com>
Date: Mon, 5 Oct 2020 12:44:47 +0200
Subject: [PATCH 05/39] dinput: Introduce dinput_create_device helper.

To simplify and factor device creation.
---
 dlls/dinput/device.c              | 20 ++++++++++++++-
 dlls/dinput/dinput_main.c         |  6 ++---
 dlls/dinput/dinput_private.h      |  7 +++++-
 dlls/dinput/joystick_linux.c      | 41 +++++--------------------------
 dlls/dinput/joystick_linuxinput.c | 41 +++++--------------------------
 dlls/dinput/joystick_osx.c        | 40 +++++-------------------------
 dlls/dinput/keyboard.c            | 41 +++++--------------------------
 dlls/dinput/mouse.c               | 41 +++++--------------------------
 8 files changed, 57 insertions(+), 180 deletions(-)

diff --git a/dlls/dinput/device.c b/dlls/dinput/device.c
index 6b71f93f24b..10b8580721a 100644
--- a/dlls/dinput/device.c
+++ b/dlls/dinput/device.c
@@ -239,7 +239,8 @@ const char *_dump_dinput_GUID(const GUID *guid) {
     return debugstr_guid(guid);
 }
 
-void _dump_DIDATAFORMAT(const DIDATAFORMAT *df) {
+void _dump_DIDATAFORMAT(const DIDATAFORMAT *df)
+{
     unsigned int i;
 
     TRACE("Dumping DIDATAFORMAT structure:\n");
@@ -1641,3 +1642,20 @@ HRESULT direct_input_device_alloc(SIZE_T size, const IDirectInputDevice8WVtbl *v
     *out = This;
     return DI_OK;
 }
+
+HRESULT dinput_create_device(const struct dinput_device *device, IDirectInputImpl *dinput, REFGUID guid, REFIID iid, void **out)
+{
+    IDirectInputDeviceImpl *This;
+    HRESULT hr;
+
+    if (!device->create_device) return E_FAIL;
+    if (FAILED(hr = device->create_device(dinput, guid, &This))) return hr;
+    if (!FAILED(hr = IDirectInputDevice8_QueryInterface(IDirectInputDevice8W_from_impl(This), iid, out)))
+    {
+        TRACE("created device %p\n", This);
+        if (TRACE_ON(dinput)) _dump_DIDATAFORMAT(This->data_format.wine_df);
+    }
+    /* IDirectInputDevice8_QueryInterface increased refcount */
+    IDirectInputDevice8_Release(IDirectInputDevice8W_from_impl(This));
+    return hr;
+}
diff --git a/dlls/dinput/dinput_main.c b/dlls/dinput/dinput_main.c
index c8ff3bd8bec..5d75cdf56e9 100644
--- a/dlls/dinput/dinput_main.c
+++ b/dlls/dinput/dinput_main.c
@@ -853,6 +853,7 @@ static HRESULT WINAPI IDirectInput2WImpl_FindDevice(LPDIRECTINPUT7W iface, REFGU
 static HRESULT create_device(IDirectInputImpl *This, REFGUID rguid, REFIID riid, LPVOID *pvOut)
 {
     unsigned int i;
+    HRESULT hr;
 
     if (pvOut)
         *pvOut = NULL;
@@ -866,10 +867,7 @@ static HRESULT create_device(IDirectInputImpl *This, REFGUID rguid, REFIID riid,
     /* Loop on all the devices to see if anyone matches the given GUID */
     for (i = 0; i < ARRAY_SIZE(dinput_devices); i++)
     {
-        HRESULT ret;
-
-        if (!dinput_devices[i]->create_device) continue;
-        if ((ret = dinput_devices[i]->create_device(This, rguid, riid, pvOut)) == DI_OK) return DI_OK;
+        if (SUCCEEDED(hr = dinput_create_device(dinput_devices[i], This, rguid, riid, pvOut))) return hr;
     }
 
     WARN("invalid device GUID %s\n", debugstr_guid(rguid));
diff --git a/dlls/dinput/dinput_private.h b/dlls/dinput/dinput_private.h
index d174a809924..ac967af4e8a 100644
--- a/dlls/dinput/dinput_private.h
+++ b/dlls/dinput/dinput_private.h
@@ -49,14 +49,19 @@ struct IDirectInputImpl
     struct list                 device_players; /* device instance guid to player name */
 };
 
+typedef struct IDirectInputDeviceImpl IDirectInputDeviceImpl;
+
 /* Function called by all devices that Wine supports */
 struct dinput_device {
     const char *name;
     HRESULT (*enum_deviceA)(DWORD dwDevType, DWORD dwFlags, LPDIDEVICEINSTANCEA lpddi, DWORD version, int id);
     HRESULT (*enum_deviceW)(DWORD dwDevType, DWORD dwFlags, LPDIDEVICEINSTANCEW lpddi, DWORD version, int id);
-    HRESULT (*create_device)(IDirectInputImpl *dinput, REFGUID rguid, REFIID riid, LPVOID *pdev);
+    HRESULT (*create_device)(IDirectInputImpl *dinput, REFGUID rguid, IDirectInputDeviceImpl **out);
 };
 
+extern HRESULT dinput_create_device(const struct dinput_device *device, IDirectInputImpl *dinput, REFGUID guid,
+        REFIID iid, void **out) DECLSPEC_HIDDEN;
+
 struct DevicePlayer {
     GUID instance_guid;
     WCHAR username[MAX_PATH];
diff --git a/dlls/dinput/joystick_linux.c b/dlls/dinput/joystick_linux.c
index d553c390892..efec79962dd 100644
--- a/dlls/dinput/joystick_linux.c
+++ b/dlls/dinput/joystick_linux.c
@@ -545,7 +545,6 @@ static HRESULT alloc_device(REFGUID rguid, IDirectInputImpl *dinput,
     newDevice->generic.devcaps.dwFFDriverVersion = 0;
 
     if (TRACE_ON(dinput)) {
-        _dump_DIDATAFORMAT(newDevice->generic.base.data_format.wine_df);
        for (i = 0; i < (newDevice->generic.device_axis_count); i++)
            TRACE("axis_map[%d] = %d\n", i, newDevice->generic.axis_map[i]);
         _dump_DIDEVCAPS(&newDevice->generic.devcaps);
@@ -588,49 +587,21 @@ static unsigned short get_joystick_index(REFGUID guid)
     return MAX_JOYSTICKS;
 }
 
-static HRESULT joydev_create_device(IDirectInputImpl *dinput, REFGUID rguid, REFIID riid, LPVOID *pdev)
+static HRESULT joydev_create_device(IDirectInputImpl *dinput, REFGUID guid, IDirectInputDeviceImpl **out)
 {
     unsigned short index;
-    int unicode;
 
-    TRACE("%p %s %s %p\n", dinput, debugstr_guid(rguid), debugstr_guid(riid), pdev);
+    TRACE("%p %s %p\n", dinput, debugstr_guid(guid), out);
     find_joystick_devices();
-    *pdev = NULL;
+    *out = NULL;
 
-    if ((index = get_joystick_index(rguid)) < MAX_JOYSTICKS &&
+    if ((index = get_joystick_index(guid)) < MAX_JOYSTICKS &&
         joystick_devices_count && index < joystick_devices_count)
     {
         JoystickImpl *This;
-        HRESULT hr;
-
-        if (IsEqualGUID(&IID_IDirectInputDeviceA,  riid) ||
-                 IsEqualGUID(&IID_IDirectInputDevice2A, riid) ||
-                 IsEqualGUID(&IID_IDirectInputDevice7A, riid) ||
-                 IsEqualGUID(&IID_IDirectInputDevice8A, riid))
-        {
-            unicode = 0;
-        }
-        else if (IsEqualGUID(&IID_IDirectInputDeviceW,  riid) ||
-                 IsEqualGUID(&IID_IDirectInputDevice2W, riid) ||
-                 IsEqualGUID(&IID_IDirectInputDevice7W, riid) ||
-                 IsEqualGUID(&IID_IDirectInputDevice8W, riid))
-        {
-            unicode = 1;
-        }
-        else
-        {
-            WARN("no interface\n");
-            return DIERR_NOINTERFACE;
-        }
-
-        hr = alloc_device(rguid, dinput, &This, index);
+        HRESULT hr = alloc_device(guid, dinput, &This, index);
         if (!This) return hr;
-
-        if (unicode)
-            *pdev = &This->generic.base.IDirectInputDevice8W_iface;
-        else
-            *pdev = &This->generic.base.IDirectInputDevice8A_iface;
-
+        *out = &This->generic.base;
         return hr;
     }
 
diff --git a/dlls/dinput/joystick_linuxinput.c b/dlls/dinput/joystick_linuxinput.c
index 47e9020632c..1c095b27c6c 100644
--- a/dlls/dinput/joystick_linuxinput.c
+++ b/dlls/dinput/joystick_linuxinput.c
@@ -606,50 +606,21 @@ static unsigned short get_joystick_index(REFGUID guid)
     return MAX_JOYDEV;
 }
 
-static HRESULT joydev_create_device(IDirectInputImpl *dinput, REFGUID rguid, REFIID riid, LPVOID *pdev)
+static HRESULT joydev_create_device(IDirectInputImpl *dinput, REFGUID guid, IDirectInputDeviceImpl **out)
 {
     unsigned short index;
-    int unicode;
 
-    TRACE("%p %s %s %p\n", dinput, debugstr_guid(rguid), debugstr_guid(riid), pdev);
+    TRACE("%p %s %p\n", dinput, debugstr_guid(guid), out);
     find_joydevs();
-    *pdev = NULL;
+    *out = NULL;
 
-    if ((index = get_joystick_index(rguid)) < MAX_JOYDEV &&
+    if ((index = get_joystick_index(guid)) < MAX_JOYDEV &&
         have_joydevs && index < have_joydevs)
     {
-        JoystickImpl *This;
-
-        if (IsEqualGUID(&IID_IDirectInputDeviceA,  riid) ||
-                 IsEqualGUID(&IID_IDirectInputDevice2A, riid) ||
-                 IsEqualGUID(&IID_IDirectInputDevice7A, riid) ||
-                 IsEqualGUID(&IID_IDirectInputDevice8A, riid))
-        {
-            unicode = 0;
-        }
-        else if (IsEqualGUID(&IID_IDirectInputDeviceW,  riid) ||
-                 IsEqualGUID(&IID_IDirectInputDevice2W, riid) ||
-                 IsEqualGUID(&IID_IDirectInputDevice7W, riid) ||
-                 IsEqualGUID(&IID_IDirectInputDevice8W, riid))
-        {
-            unicode = 1;
-        }
-        else
-        {
-            WARN("no interface\n");
-            return DIERR_NOINTERFACE;
-        }
-
-        This = alloc_device(rguid, dinput, index);
+        JoystickImpl *This = alloc_device(guid, dinput, index);
         TRACE("Created a Joystick device (%p)\n", This);
-
         if (!This) return DIERR_OUTOFMEMORY;
-
-        if (unicode)
-            *pdev = &This->generic.base.IDirectInputDevice8W_iface;
-        else
-            *pdev = &This->generic.base.IDirectInputDevice8A_iface;
-
+        *out = &This->generic.base;
         return DI_OK;
     }
 
diff --git a/dlls/dinput/joystick_osx.c b/dlls/dinput/joystick_osx.c
index 61da492a071..347e76a7bc4 100644
--- a/dlls/dinput/joystick_osx.c
+++ b/dlls/dinput/joystick_osx.c
@@ -1232,7 +1232,6 @@ static HRESULT alloc_device(REFGUID rguid, IDirectInputImpl *dinput,
 
     if (TRACE_ON(dinput)) {
         TRACE("allocated device %p\n", newDevice);
-        _dump_DIDATAFORMAT(newDevice->generic.base.data_format.wine_df);
         _dump_DIDEVCAPS(&newDevice->generic.devcaps);
     }
 
@@ -1274,51 +1273,24 @@ static unsigned short get_joystick_index(REFGUID guid)
     return 0xffff;
 }
 
-static HRESULT joydev_create_device(IDirectInputImpl *dinput, REFGUID rguid, REFIID riid, LPVOID *pdev)
+static HRESULT joydev_create_device(IDirectInputImpl *dinput, REFGUID guid, IDirectInputDeviceImpl **out)
 {
     unsigned short index;
     int joystick_devices_count;
-    int unicode;
 
-    TRACE("%p %s %s %p\n", dinput, debugstr_guid(rguid), debugstr_guid(riid), pdev);
-    *pdev = NULL;
+    TRACE("%p %s %p\n", dinput, debugstr_guid(guid), out);
+    *out = NULL;
 
     if ((joystick_devices_count = find_joystick_devices()) == 0)
         return DIERR_DEVICENOTREG;
 
-    if ((index = get_joystick_index(rguid)) < 0xffff &&
+    if ((index = get_joystick_index(guid)) < 0xffff &&
         joystick_devices_count && index < joystick_devices_count)
     {
         JoystickImpl *This;
-        HRESULT hr;
-
-        if (IsEqualGUID(&IID_IDirectInputDeviceA,  riid) ||
-                 IsEqualGUID(&IID_IDirectInputDevice2A, riid) ||
-                 IsEqualGUID(&IID_IDirectInputDevice7A, riid) ||
-                 IsEqualGUID(&IID_IDirectInputDevice8A, riid))
-        {
-            unicode = 0;
-        }
-        else if (IsEqualGUID(&IID_IDirectInputDeviceW,  riid) ||
-                 IsEqualGUID(&IID_IDirectInputDevice2W, riid) ||
-                 IsEqualGUID(&IID_IDirectInputDevice7W, riid) ||
-                 IsEqualGUID(&IID_IDirectInputDevice8W, riid))
-        {
-            unicode = 1;
-        }
-        else
-        {
-            WARN("no interface\n");
-            return DIERR_NOINTERFACE;
-        }
-
-        hr = alloc_device(rguid, dinput, &This, index);
+        HRESULT hr = alloc_device(guid, dinput, &This, index);
         if (!This) return hr;
-
-        if (unicode)
-            *pdev = &This->generic.base.IDirectInputDevice8W_iface;
-        else
-            *pdev = &This->generic.base.IDirectInputDevice8A_iface;
+        *out = &This->generic.base;
         return hr;
     }
 
diff --git a/dlls/dinput/keyboard.c b/dlls/dinput/keyboard.c
index 70223074e2e..ae4a675aec7 100644
--- a/dlls/dinput/keyboard.c
+++ b/dlls/dinput/keyboard.c
@@ -280,46 +280,17 @@ failed:
     return NULL;
 }
 
-static HRESULT keyboarddev_create_device(IDirectInputImpl *dinput, REFGUID rguid, REFIID riid, LPVOID *pdev)
+static HRESULT keyboarddev_create_device(IDirectInputImpl *dinput, REFGUID guid, IDirectInputDeviceImpl **out)
 {
-    int unicode;
-    TRACE("%p %s %s %p\n", dinput, debugstr_guid(rguid), debugstr_guid(riid), pdev);
-    *pdev = NULL;
+    TRACE("%p %s %p\n", dinput, debugstr_guid(guid), out);
+    *out = NULL;
 
-    if (IsEqualGUID(&GUID_SysKeyboard, rguid)) /* Wine Keyboard */
+    if (IsEqualGUID(&GUID_SysKeyboard, guid)) /* Wine Keyboard */
     {
-        SysKeyboardImpl *This;
-
-        if (IsEqualGUID(&IID_IDirectInputDeviceA,  riid) ||
-                 IsEqualGUID(&IID_IDirectInputDevice2A, riid) ||
-                 IsEqualGUID(&IID_IDirectInputDevice7A, riid) ||
-                 IsEqualGUID(&IID_IDirectInputDevice8A, riid))
-        {
-            unicode = 0;
-        }
-        else if (IsEqualGUID(&IID_IDirectInputDeviceW,  riid) ||
-                 IsEqualGUID(&IID_IDirectInputDevice2W, riid) ||
-                 IsEqualGUID(&IID_IDirectInputDevice7W, riid) ||
-                 IsEqualGUID(&IID_IDirectInputDevice8W, riid))
-        {
-            unicode = 1;
-        }
-        else
-        {
-            WARN("no interface\n");
-            return DIERR_NOINTERFACE;
-        }
-
-        This = alloc_device(rguid, dinput);
+        SysKeyboardImpl *This = alloc_device(guid, dinput);
         TRACE("Created a Keyboard device (%p)\n", This);
-
         if (!This) return DIERR_OUTOFMEMORY;
-
-        if (unicode)
-            *pdev = &This->base.IDirectInputDevice8W_iface;
-        else
-            *pdev = &This->base.IDirectInputDevice8A_iface;
-
+        *out = &This->base;
         return DI_OK;
     }
 
diff --git a/dlls/dinput/mouse.c b/dlls/dinput/mouse.c
index f5a49f51a07..06255bdafe5 100644
--- a/dlls/dinput/mouse.c
+++ b/dlls/dinput/mouse.c
@@ -238,46 +238,17 @@ failed:
     return NULL;
 }
 
-static HRESULT mousedev_create_device(IDirectInputImpl *dinput, REFGUID rguid, REFIID riid, LPVOID *pdev)
+static HRESULT mousedev_create_device(IDirectInputImpl *dinput, REFGUID guid, IDirectInputDeviceImpl **out)
 {
-    int unicode;
-    TRACE("%p %s %s %p\n", dinput, debugstr_guid(rguid), debugstr_guid(riid), pdev);
-    *pdev = NULL;
+    TRACE("%p %s %p\n", dinput, debugstr_guid(guid), out);
+    *out = NULL;
 
-    if (IsEqualGUID(&GUID_SysMouse, rguid)) /* Wine Mouse */
+    if (IsEqualGUID(&GUID_SysMouse, guid)) /* Wine Mouse */
     {
-        SysMouseImpl *This;
-
-        if (IsEqualGUID(&IID_IDirectInputDeviceA,  riid) ||
-                 IsEqualGUID(&IID_IDirectInputDevice2A, riid) ||
-                 IsEqualGUID(&IID_IDirectInputDevice7A, riid) ||
-                 IsEqualGUID(&IID_IDirectInputDevice8A, riid))
-        {
-            unicode = 0;
-        }
-        else if (IsEqualGUID(&IID_IDirectInputDeviceW,  riid) ||
-                 IsEqualGUID(&IID_IDirectInputDevice2W, riid) ||
-                 IsEqualGUID(&IID_IDirectInputDevice7W, riid) ||
-                 IsEqualGUID(&IID_IDirectInputDevice8W, riid))
-        {
-            unicode = 1;
-        }
-        else
-        {
-            WARN("no interface\n");
-            return DIERR_NOINTERFACE;
-        }
-
-        This = alloc_device(rguid, dinput);
+        SysMouseImpl *This = alloc_device(guid, dinput);
         TRACE("Created a Mouse device (%p)\n", This);
-
         if (!This) return DIERR_OUTOFMEMORY;
-
-        if (unicode)
-            *pdev = &This->base.IDirectInputDevice8W_iface;
-        else
-            *pdev = &This->base.IDirectInputDevice8A_iface;
-
+        *out = &This->base;
         return DI_OK;
     }
 
-- 
2.28.0

>From 48687a6e43b7703d76b2b7afb2385c86094b0895 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?R=C3=A9mi=20Bernon?= <rbernon@codeweavers.com>
Date: Mon, 5 Oct 2020 12:44:47 +0200
Subject: [PATCH 06/39] dinput: Factor IDirectInput8A implementation.

As proxy around IDirectInput8W interfaces.
---
 dlls/dinput/ansi.c           | 215 ++++++++++++++++++++
 dlls/dinput/dinput_main.c    | 378 ++---------------------------------
 dlls/dinput/dinput_private.h |   5 +-
 3 files changed, 230 insertions(+), 368 deletions(-)

diff --git a/dlls/dinput/ansi.c b/dlls/dinput/ansi.c
index edfbfb878cd..c2bd088ae6a 100644
--- a/dlls/dinput/ansi.c
+++ b/dlls/dinput/ansi.c
@@ -44,6 +44,20 @@ static IDirectInputDevice8W *IDirectInputDevice8W_from_impl(IDirectInputDeviceIm
     return &This->IDirectInputDevice8W_iface;
 }
 
+static inline IDirectInputDevice8A *IDirectInputDevice8A_from_IDirectInputDevice8W(IDirectInputDevice8W *iface)
+{
+    if (!iface) return NULL;
+    return &CONTAINING_RECORD(iface, IDirectInputDeviceImpl, IDirectInputDevice8W_iface)->IDirectInputDevice8A_iface;
+}
+static IDirectInputImpl *impl_from_IDirectInput8A(IDirectInput8A *iface)
+{
+    return CONTAINING_RECORD(iface, IDirectInputImpl, IDirectInput8A_iface);
+}
+static IDirectInput8W *IDirectInput8W_from_impl(IDirectInputImpl *This)
+{
+    return &This->IDirectInput8W_iface;
+}
+
 static void dideviceobjectinstance_wtoa(const DIDEVICEOBJECTINSTANCEW *didoiw, DIDEVICEOBJECTINSTANCEA *didoia)
 {
     didoia->guidType = didoiw->guidType;
@@ -189,6 +203,38 @@ static void dideviceimageinfoheader_wtoa(const DIDEVICEIMAGEINFOHEADERW *didiihw
     didiiha->dwBufferUsed = didiihw->dwBufferUsed / sizeof(DIDEVICEIMAGEINFOW) * sizeof(DIDEVICEIMAGEINFOA);
 }
 
+static void diconfiguredevicesparams_atow(const DICONFIGUREDEVICESPARAMSA *dicdpa, DICONFIGUREDEVICESPARAMSW *dicdpw)
+{
+    const char *username;
+    WCHAR *usernamew;
+    DWORD i, lenw = 1, lena;
+    dicdpw->dwcUsers = dicdpa->dwcUsers;
+    if (!dicdpa->lptszUserNames) dicdpw->lptszUserNames = NULL;
+    else
+    {
+        username = dicdpa->lptszUserNames;
+        for (i = 0; i < dicdpw->dwcUsers; ++i)
+        {
+            if (!(lena = strlen(username))) break;
+            lenw += MultiByteToWideChar(CP_ACP, 0, username, -1, NULL, 0);
+            username += lena + 1;
+        }
+        dicdpw->lptszUserNames = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, (lenw + 1) * sizeof(WCHAR));
+        username = dicdpa->lptszUserNames;
+        usernamew = dicdpw->lptszUserNames;
+        for (i = 0; i < dicdpw->dwcUsers; ++i)
+        {
+            if (!(lena = strlen(username))) break;
+            usernamew += MultiByteToWideChar(CP_ACP, 0, username, -1, usernamew, lenw - (usernamew - dicdpw->lptszUserNames));
+            username += lena + 1;
+        }
+    }
+    dicdpw->dwcFormats = dicdpa->dwcFormats;
+    dicdpw->hwnd = dicdpa->hwnd;
+    dicdpw->dics = dicdpa->dics;
+    dicdpw->lpUnkDDSTarget = dicdpa->lpUnkDDSTarget;
+}
+
 static HRESULT STDMETHODCALLTYPE direct_input_device_a_QueryInterface(IDirectInputDevice8A *iface, REFIID iid, void **out)
 {
     IDirectInputDeviceImpl *This = impl_from_IDirectInputDevice8A(iface);
@@ -560,3 +606,172 @@ const IDirectInputDevice8AVtbl direct_input_device_a_vtbl =
     direct_input_device_a_SetActionMap,
     direct_input_device_a_GetImageInfo
 };
+
+static HRESULT STDMETHODCALLTYPE direct_input_8_a_QueryInterface(IDirectInput8A *iface, REFIID iid, void **out)
+{
+    IDirectInputImpl *This = impl_from_IDirectInput8A(iface);
+    TRACE("iface %p, iid %s, out %p.\n", iface, debugstr_guid(iid), out);
+    return IDirectInput8_QueryInterface(IDirectInput8W_from_impl(This), iid, out);
+}
+
+static ULONG STDMETHODCALLTYPE direct_input_8_a_AddRef(IDirectInput8A *iface)
+{
+    IDirectInputImpl *This = impl_from_IDirectInput8A(iface);
+    TRACE("iface %p.\n", iface);
+    return IDirectInput8_AddRef(IDirectInput8W_from_impl(This));
+}
+
+static ULONG STDMETHODCALLTYPE direct_input_8_a_Release(IDirectInput8A *iface)
+{
+    IDirectInputImpl *This = impl_from_IDirectInput8A(iface);
+    TRACE("iface %p.\n", iface);
+    return IDirectInput8_Release(IDirectInput8W_from_impl(This));
+}
+
+static HRESULT STDMETHODCALLTYPE direct_input_8_a_CreateDevice(IDirectInput8A *iface, REFGUID guid,
+        IDirectInputDevice8A **out, IUnknown *outer)
+{
+    IDirectInputImpl *This = impl_from_IDirectInput8A(iface);
+    IDirectInputDevice8W *outw;
+    HRESULT hr;
+    TRACE("iface %p, guid %s, out %p, outer %p.\n", iface, debugstr_guid(guid), out, outer);
+    if (!out) return E_POINTER;
+    hr = IDirectInput8_CreateDevice(IDirectInput8W_from_impl(This), guid, &outw, outer);
+    *out = IDirectInputDevice8A_from_IDirectInputDevice8W(outw);
+    return hr;
+}
+
+struct direct_input_a_enum_devices_params
+{
+    LPDIENUMDEVICESCALLBACKA callback;
+    void *ref;
+};
+
+static BOOL CALLBACK direct_input_a_enum_devices_callback(const DIDEVICEINSTANCEW *didiw, void *data)
+{
+    struct direct_input_a_enum_devices_params *params = data;
+    DIDEVICEINSTANCEA didia = {sizeof(didia)};
+    dideviceinstance_wtoa(didiw, &didia);
+    return params->callback(&didia, params->ref);
+}
+
+static HRESULT STDMETHODCALLTYPE direct_input_8_a_EnumDevices(IDirectInput8A *iface, DWORD type,
+        LPDIENUMDEVICESCALLBACKA callback, void *ref, DWORD flags)
+{
+    struct direct_input_a_enum_devices_params params = {callback, ref};
+    IDirectInputImpl *This = impl_from_IDirectInput8A(iface);
+    TRACE("iface %p, callback %p, ref %p, flags %#x.\n", iface, callback, ref, flags);
+    if (!callback) return DIERR_INVALIDPARAM;
+    return IDirectInput8_EnumDevices(IDirectInput8W_from_impl(This), type, direct_input_a_enum_devices_callback, &params, flags);
+}
+
+static HRESULT STDMETHODCALLTYPE direct_input_8_a_GetDeviceStatus(IDirectInput8A *iface, REFGUID instance_guid)
+{
+    IDirectInputImpl *This = impl_from_IDirectInput8A(iface);
+    TRACE("iface %p, instance_guid %s.\n", iface, debugstr_guid(instance_guid));
+    return IDirectInput8_GetDeviceStatus(IDirectInput8W_from_impl(This), instance_guid);
+}
+
+static HRESULT STDMETHODCALLTYPE direct_input_8_a_RunControlPanel(IDirectInput8A *iface, HWND owner, DWORD flags)
+{
+    IDirectInputImpl *This = impl_from_IDirectInput8A(iface);
+    TRACE("iface %p, owner %p, flags %#x.\n", iface, owner, flags);
+    return IDirectInput8_RunControlPanel(IDirectInput8W_from_impl(This), owner, flags);
+}
+
+static HRESULT STDMETHODCALLTYPE direct_input_8_a_Initialize(IDirectInput8A *iface, HINSTANCE instance, DWORD version)
+{
+    IDirectInputImpl *This = impl_from_IDirectInput8A(iface);
+    TRACE("iface %p, instance %p, version %#x.\n", iface, instance, version);
+    return IDirectInput8_Initialize(IDirectInput8W_from_impl(This), instance, version);
+}
+
+static HRESULT STDMETHODCALLTYPE direct_input_8_a_FindDevice(IDirectInput8A *iface, REFGUID guid, const char *name, GUID *instance_guid)
+{
+    IDirectInputImpl *This = impl_from_IDirectInput8A(iface);
+    WCHAR *namew = string_atow(name);
+    HRESULT hr;
+    TRACE("iface %p, guid %s, name %s, instance_guid %s.\n", iface, debugstr_guid(guid), debugstr_a(name),
+            debugstr_guid(instance_guid));
+    hr = IDirectInput8_FindDevice(IDirectInput8W_from_impl(This), guid, namew, instance_guid);
+    HeapFree(GetProcessHeap(), 0, namew);
+    return hr;
+}
+
+struct direct_input_a_enum_devices_by_semantics_params
+{
+    LPDIENUMDEVICESBYSEMANTICSCBA callback;
+    void *ref;
+};
+
+static BOOL CALLBACK direct_input_a_enum_devices_by_semantics_callback(const DIDEVICEINSTANCEW *didiw,
+        IDirectInputDevice8W *iface, DWORD flags, DWORD remaining, void *data)
+{
+    struct direct_input_a_enum_devices_by_semantics_params *params = data;
+    DIDEVICEINSTANCEA didia = {sizeof(didia)};
+    dideviceinstance_wtoa(didiw, &didia);
+    return params->callback(&didia, IDirectInputDevice8A_from_IDirectInputDevice8W(iface), flags, remaining, params->ref);
+}
+
+static HRESULT STDMETHODCALLTYPE direct_input_8_a_EnumDevicesBySemantics(IDirectInput8A *iface, const char *username,
+        DIACTIONFORMATA *diaf, LPDIENUMDEVICESBYSEMANTICSCBA callback, void *ref, DWORD flags)
+{
+    struct direct_input_a_enum_devices_by_semantics_params params = {callback, ref};
+    IDirectInputImpl *This = impl_from_IDirectInput8A(iface);
+    DIACTIONFORMATW diafw = {sizeof(diafw), sizeof(DIACTIONW)};
+    WCHAR *usernamew = string_atow(username);
+    HRESULT hr;
+    TRACE("iface %p, username %s, diaf %p, callback %p, ref %p, flags %#x.\n", iface, debugstr_a(username), diaf,
+            callback, ref, flags);
+    if (!callback) return DIERR_INVALIDPARAM;
+    diafw.dwNumActions = diaf->dwNumActions;
+    diafw.rgoAction = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, diaf->dwNumActions * sizeof(DIACTIONW));
+    diactionformat_atow(diaf, &diafw);
+    hr = IDirectInput8_EnumDevicesBySemantics(IDirectInput8W_from_impl(This), usernamew, &diafw,
+            direct_input_a_enum_devices_by_semantics_callback, &params, flags);
+    HeapFree(GetProcessHeap(), 0, diafw.rgoAction);
+    HeapFree(GetProcessHeap(), 0, usernamew);
+    return hr;
+}
+
+static HRESULT STDMETHODCALLTYPE direct_input_8_a_ConfigureDevices(IDirectInput8A *iface,
+        LPDICONFIGUREDEVICESCALLBACK callback, DICONFIGUREDEVICESPARAMSA *dicdp, DWORD flags, void *ref)
+{
+    IDirectInputImpl *This = impl_from_IDirectInput8A(iface);
+    DICONFIGUREDEVICESPARAMSW dicdpw = {sizeof(dicdpw)};
+    DIACTIONFORMATW diafw = {sizeof(diafw), sizeof(DIACTIONW)};
+    DIACTIONFORMATA *diaf = dicdp->lprgFormats;
+    HRESULT hr;
+    DWORD i;
+    TRACE("iface %p, callback %p, dicdp %p, ref %p, flags %#x.\n", iface, callback, dicdp, ref, flags);
+    if (!callback) return DIERR_INVALIDPARAM;
+    diconfiguredevicesparams_atow(dicdp, &dicdpw);
+    diafw.dwNumActions = diaf->dwNumActions;
+    diafw.rgoAction = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, diaf->dwNumActions * sizeof(DIACTIONW));
+    diactionformat_atow(diaf, &diafw);
+    if (diafw.hInstString) for (i = 0; i < diafw.dwNumActions; ++i) diafw.rgoAction[i].uResIdString = diaf->rgoAction[i].uResIdString;
+    else for (i = 0; i < diafw.dwNumActions; ++i) diafw.rgoAction[i].lptszActionName = string_atow(diaf->rgoAction[i].lptszActionName);
+    dicdpw.lprgFormats = &diafw;
+    hr = IDirectInput8_ConfigureDevices(IDirectInput8W_from_impl(This), callback, &dicdpw, flags, ref);
+    if (!diafw.hInstString) for (i = 0; i < diafw.dwNumActions; ++i) HeapFree(GetProcessHeap(), 0, (void *)diafw.rgoAction[i].lptszActionName);
+    HeapFree(GetProcessHeap(), 0, diafw.rgoAction);
+    HeapFree(GetProcessHeap(), 0, dicdpw.lptszUserNames);
+    return hr;
+}
+
+const IDirectInput8AVtbl direct_input_8_a_vtbl =
+{
+    /*** IUnknown methods ***/
+    direct_input_8_a_QueryInterface,
+    direct_input_8_a_AddRef,
+    direct_input_8_a_Release,
+    /*** IDirectInput8A methods ***/
+    direct_input_8_a_CreateDevice,
+    direct_input_8_a_EnumDevices,
+    direct_input_8_a_GetDeviceStatus,
+    direct_input_8_a_RunControlPanel,
+    direct_input_8_a_Initialize,
+    direct_input_8_a_FindDevice,
+    direct_input_8_a_EnumDevicesBySemantics,
+    direct_input_8_a_ConfigureDevices,
+};
diff --git a/dlls/dinput/dinput_main.c b/dlls/dinput/dinput_main.c
index 5d75cdf56e9..4a57947532e 100644
--- a/dlls/dinput/dinput_main.c
+++ b/dlls/dinput/dinput_main.c
@@ -57,7 +57,6 @@ WINE_DEFAULT_DEBUG_CHANNEL(dinput);
 
 static const IDirectInput7AVtbl ddi7avt;
 static const IDirectInput7WVtbl ddi7wvt;
-static const IDirectInput8AVtbl ddi8avt;
 static const IDirectInput8WVtbl ddi8wvt;
 static const IDirectInputJoyConfig8Vtbl JoyConfig8vt;
 
@@ -71,11 +70,6 @@ static inline IDirectInputImpl *impl_from_IDirectInput7W( IDirectInput7W *iface
     return CONTAINING_RECORD( iface, IDirectInputImpl, IDirectInput7W_iface );
 }
 
-static inline IDirectInputImpl *impl_from_IDirectInput8A( IDirectInput8A *iface )
-{
-    return CONTAINING_RECORD( iface, IDirectInputImpl, IDirectInput8A_iface );
-}
-
 static inline IDirectInputImpl *impl_from_IDirectInput8W( IDirectInput8W *iface )
 {
     return CONTAINING_RECORD( iface, IDirectInputImpl, IDirectInput8W_iface );
@@ -144,7 +138,7 @@ static HRESULT create_directinput_instance(REFIID riid, LPVOID *ppDI, IDirectInp
 
     This->IDirectInput7A_iface.lpVtbl = &ddi7avt;
     This->IDirectInput7W_iface.lpVtbl = &ddi7wvt;
-    This->IDirectInput8A_iface.lpVtbl = &ddi8avt;
+    This->IDirectInput8A_iface.lpVtbl = &direct_input_8_a_vtbl;
     This->IDirectInput8W_iface.lpVtbl = &ddi8wvt;
     This->IDirectInputJoyConfig8_iface.lpVtbl = &JoyConfig8vt;
 
@@ -321,110 +315,6 @@ static void _dump_EnumDevices_dwFlags(DWORD dwFlags)
     TRACE("\n");
 }
 
-static void _dump_diactionformatA(LPDIACTIONFORMATA lpdiActionFormat)
-{
-    unsigned int i;
-
-    TRACE("diaf.dwSize = %d\n", lpdiActionFormat->dwSize);
-    TRACE("diaf.dwActionSize = %d\n", lpdiActionFormat->dwActionSize);
-    TRACE("diaf.dwDataSize = %d\n", lpdiActionFormat->dwDataSize);
-    TRACE("diaf.dwNumActions = %d\n", lpdiActionFormat->dwNumActions);
-    TRACE("diaf.rgoAction = %p\n", lpdiActionFormat->rgoAction);
-    TRACE("diaf.guidActionMap = %s\n", debugstr_guid(&lpdiActionFormat->guidActionMap));
-    TRACE("diaf.dwGenre = 0x%08x\n", lpdiActionFormat->dwGenre);
-    TRACE("diaf.dwBufferSize = %d\n", lpdiActionFormat->dwBufferSize);
-    TRACE("diaf.lAxisMin = %d\n", lpdiActionFormat->lAxisMin);
-    TRACE("diaf.lAxisMax = %d\n", lpdiActionFormat->lAxisMax);
-    TRACE("diaf.hInstString = %p\n", lpdiActionFormat->hInstString);
-    TRACE("diaf.ftTimeStamp ...\n");
-    TRACE("diaf.dwCRC = 0x%x\n", lpdiActionFormat->dwCRC);
-    TRACE("diaf.tszActionMap = %s\n", debugstr_a(lpdiActionFormat->tszActionMap));
-    for (i = 0; i < lpdiActionFormat->dwNumActions; i++)
-    {
-        TRACE("diaf.rgoAction[%u]:\n", i);
-        TRACE("\tuAppData=0x%lx\n", lpdiActionFormat->rgoAction[i].uAppData);
-        TRACE("\tdwSemantic=0x%08x\n", lpdiActionFormat->rgoAction[i].dwSemantic);
-        TRACE("\tdwFlags=0x%x\n", lpdiActionFormat->rgoAction[i].dwFlags);
-        TRACE("\tszActionName=%s\n", debugstr_a(lpdiActionFormat->rgoAction[i].u.lptszActionName));
-        TRACE("\tguidInstance=%s\n", debugstr_guid(&lpdiActionFormat->rgoAction[i].guidInstance));
-        TRACE("\tdwObjID=0x%x\n", lpdiActionFormat->rgoAction[i].dwObjID);
-        TRACE("\tdwHow=0x%x\n", lpdiActionFormat->rgoAction[i].dwHow);
-    }
-}
-
-void _copy_diactionformatAtoW(LPDIACTIONFORMATW to, LPDIACTIONFORMATA from)
-{
-    int i;
-
-    to->dwSize = sizeof(DIACTIONFORMATW);
-    to->dwActionSize = sizeof(DIACTIONW);
-    to->dwDataSize = from->dwDataSize;
-    to->dwNumActions = from->dwNumActions;
-    to->guidActionMap = from->guidActionMap;
-    to->dwGenre = from->dwGenre;
-    to->dwBufferSize = from->dwBufferSize;
-    to->lAxisMin = from->lAxisMin;
-    to->lAxisMax = from->lAxisMax;
-    to->dwCRC = from->dwCRC;
-    to->ftTimeStamp = from->ftTimeStamp;
-
-    for (i=0; i < to->dwNumActions; i++)
-    {
-        to->rgoAction[i].uAppData = from->rgoAction[i].uAppData;
-        to->rgoAction[i].dwSemantic = from->rgoAction[i].dwSemantic;
-        to->rgoAction[i].dwFlags = from->rgoAction[i].dwFlags;
-        to->rgoAction[i].guidInstance = from->rgoAction[i].guidInstance;
-        to->rgoAction[i].dwObjID = from->rgoAction[i].dwObjID;
-        to->rgoAction[i].dwHow = from->rgoAction[i].dwHow;
-    }
-}
-
-void _copy_diactionformatWtoA(LPDIACTIONFORMATA to, LPDIACTIONFORMATW from)
-{
-    int i;
-
-    to->dwSize = sizeof(DIACTIONFORMATA);
-    to->dwActionSize = sizeof(DIACTIONA);
-    to->dwDataSize = from->dwDataSize;
-    to->dwNumActions = from->dwNumActions;
-    to->guidActionMap = from->guidActionMap;
-    to->dwGenre = from->dwGenre;
-    to->dwBufferSize = from->dwBufferSize;
-    to->lAxisMin = from->lAxisMin;
-    to->lAxisMax = from->lAxisMax;
-    to->dwCRC = from->dwCRC;
-    to->ftTimeStamp = from->ftTimeStamp;
-
-    for (i=0; i < to->dwNumActions; i++)
-    {
-        to->rgoAction[i].uAppData = from->rgoAction[i].uAppData;
-        to->rgoAction[i].dwSemantic = from->rgoAction[i].dwSemantic;
-        to->rgoAction[i].dwFlags = from->rgoAction[i].dwFlags;
-        to->rgoAction[i].guidInstance = from->rgoAction[i].guidInstance;
-        to->rgoAction[i].dwObjID = from->rgoAction[i].dwObjID;
-        to->rgoAction[i].dwHow = from->rgoAction[i].dwHow;
-    }
-}
-
-/* diactionformat_priority
- *
- *  Given a DIACTIONFORMAT structure and a DI genre, returns the enumeration
- *  priority. Joysticks should pass the game genre, and mouse or keyboard their
- *  respective DI*_MASK
- */
-static DWORD diactionformat_priorityA(LPDIACTIONFORMATA lpdiaf, 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 < lpdiaf->dwNumActions; i++)
-        if ((lpdiaf->rgoAction[i].dwSemantic & genre) == genre)
-            priorityFlags |= DIEDBS_MAPPEDPRI1;
-
-    return priorityFlags;
-}
-
 static DWORD diactionformat_priorityW(LPDIACTIONFORMATW lpdiaf, DWORD genre)
 {
     int i;
@@ -910,97 +800,53 @@ static HRESULT WINAPI IDirectInputWImpl_CreateDevice(LPDIRECTINPUT7W iface, REFG
  *      DirectInput8
  */
 
-static ULONG WINAPI IDirectInput8AImpl_AddRef(LPDIRECTINPUT8A iface)
-{
-    IDirectInputImpl *This = impl_from_IDirectInput8A( iface );
-    return IDirectInputAImpl_AddRef( &This->IDirectInput7A_iface );
-}
-
 static ULONG WINAPI IDirectInput8WImpl_AddRef(LPDIRECTINPUT8W iface)
 {
     IDirectInputImpl *This = impl_from_IDirectInput8W( iface );
-    return IDirectInputAImpl_AddRef( &This->IDirectInput7A_iface );
-}
-
-static HRESULT WINAPI IDirectInput8AImpl_QueryInterface(LPDIRECTINPUT8A iface, REFIID riid, LPVOID *ppobj)
-{
-    IDirectInputImpl *This = impl_from_IDirectInput8A( iface );
-    return IDirectInputAImpl_QueryInterface( &This->IDirectInput7A_iface, riid, ppobj );
+    return IDirectInput7_AddRef(&This->IDirectInput7W_iface);
 }
 
 static HRESULT WINAPI IDirectInput8WImpl_QueryInterface(LPDIRECTINPUT8W iface, REFIID riid, LPVOID *ppobj)
 {
     IDirectInputImpl *This = impl_from_IDirectInput8W( iface );
-    return IDirectInputAImpl_QueryInterface( &This->IDirectInput7A_iface, riid, ppobj );
-}
-
-static ULONG WINAPI IDirectInput8AImpl_Release(LPDIRECTINPUT8A iface)
-{
-    IDirectInputImpl *This = impl_from_IDirectInput8A( iface );
-    return IDirectInputAImpl_Release( &This->IDirectInput7A_iface );
+    return IDirectInput7_QueryInterface(&This->IDirectInput7W_iface, riid, ppobj);
 }
 
 static ULONG WINAPI IDirectInput8WImpl_Release(LPDIRECTINPUT8W iface)
 {
     IDirectInputImpl *This = impl_from_IDirectInput8W( iface );
-    return IDirectInputAImpl_Release( &This->IDirectInput7A_iface );
-}
-
-static HRESULT WINAPI IDirectInput8AImpl_CreateDevice(LPDIRECTINPUT8A iface, REFGUID rguid,
-                                                      LPDIRECTINPUTDEVICE8A* pdev, LPUNKNOWN punk)
-{
-    IDirectInputImpl *This = impl_from_IDirectInput8A( iface );
-    return IDirectInput7AImpl_CreateDeviceEx(&This->IDirectInput7A_iface, rguid, &IID_IDirectInputDeviceA, (LPVOID *)pdev, punk);
+    return IDirectInput7_Release(&This->IDirectInput7W_iface);
 }
 
 static HRESULT WINAPI IDirectInput8WImpl_CreateDevice(LPDIRECTINPUT8W iface, REFGUID rguid,
                                                       LPDIRECTINPUTDEVICE8W* pdev, LPUNKNOWN punk)
 {
     IDirectInputImpl *This = impl_from_IDirectInput8W( iface );
-    return IDirectInput7WImpl_CreateDeviceEx(&This->IDirectInput7W_iface, rguid, &IID_IDirectInputDeviceW, (LPVOID *)pdev, punk);
-}
-
-static HRESULT WINAPI IDirectInput8AImpl_EnumDevices(LPDIRECTINPUT8A iface, DWORD dwDevType, LPDIENUMDEVICESCALLBACKA lpCallback,
-                                                     LPVOID pvRef, DWORD dwFlags)
-{
-    IDirectInputImpl *This = impl_from_IDirectInput8A( iface );
-    return IDirectInputAImpl_EnumDevices( &This->IDirectInput7A_iface, dwDevType, lpCallback, pvRef, dwFlags );
+    return IDirectInput7_CreateDeviceEx(&This->IDirectInput7W_iface, rguid, &IID_IDirectInputDeviceW, (LPVOID *)pdev, punk);
 }
 
 static HRESULT WINAPI IDirectInput8WImpl_EnumDevices(LPDIRECTINPUT8W iface, DWORD dwDevType, LPDIENUMDEVICESCALLBACKW lpCallback,
                                                      LPVOID pvRef, DWORD dwFlags)
 {
     IDirectInputImpl *This = impl_from_IDirectInput8W( iface );
-    return IDirectInputWImpl_EnumDevices( &This->IDirectInput7W_iface, dwDevType, lpCallback, pvRef, dwFlags );
-}
-
-static HRESULT WINAPI IDirectInput8AImpl_GetDeviceStatus(LPDIRECTINPUT8A iface, REFGUID rguid)
-{
-    IDirectInputImpl *This = impl_from_IDirectInput8A( iface );
-    return IDirectInputAImpl_GetDeviceStatus( &This->IDirectInput7A_iface, rguid );
+    return IDirectInput7_EnumDevices(&This->IDirectInput7W_iface, dwDevType, lpCallback, pvRef, dwFlags);
 }
 
 static HRESULT WINAPI IDirectInput8WImpl_GetDeviceStatus(LPDIRECTINPUT8W iface, REFGUID rguid)
 {
     IDirectInputImpl *This = impl_from_IDirectInput8W( iface );
-    return IDirectInputAImpl_GetDeviceStatus( &This->IDirectInput7A_iface, rguid );
-}
-
-static HRESULT WINAPI IDirectInput8AImpl_RunControlPanel(LPDIRECTINPUT8A iface, HWND hwndOwner, DWORD dwFlags)
-{
-    IDirectInputImpl *This = impl_from_IDirectInput8A( iface );
-    return IDirectInputAImpl_RunControlPanel( &This->IDirectInput7A_iface, hwndOwner, dwFlags );
+    return IDirectInput7_GetDeviceStatus(&This->IDirectInput7W_iface, rguid);
 }
 
 static HRESULT WINAPI IDirectInput8WImpl_RunControlPanel(LPDIRECTINPUT8W iface, HWND hwndOwner, DWORD dwFlags)
 {
     IDirectInputImpl *This = impl_from_IDirectInput8W( iface );
-    return IDirectInputAImpl_RunControlPanel( &This->IDirectInput7A_iface, hwndOwner, dwFlags );
+    return IDirectInput7_RunControlPanel(&This->IDirectInput7W_iface, hwndOwner, dwFlags);
 }
 
-static HRESULT WINAPI IDirectInput8AImpl_Initialize(LPDIRECTINPUT8A iface, HINSTANCE hinst, DWORD version)
+static HRESULT WINAPI IDirectInput8WImpl_Initialize(LPDIRECTINPUT8W iface, HINSTANCE hinst, DWORD version)
 {
-    IDirectInputImpl *This = impl_from_IDirectInput8A( iface );
+    IDirectInputImpl *This = impl_from_IDirectInput8W(iface);
 
     TRACE("(%p)->(%p, 0x%04x)\n", This, hinst, version);
 
@@ -1016,18 +862,6 @@ static HRESULT WINAPI IDirectInput8AImpl_Initialize(LPDIRECTINPUT8A iface, HINST
     return initialize_directinput_instance(This, version);
 }
 
-static HRESULT WINAPI IDirectInput8WImpl_Initialize(LPDIRECTINPUT8W iface, HINSTANCE hinst, DWORD version)
-{
-    IDirectInputImpl *This = impl_from_IDirectInput8W( iface );
-    return IDirectInput8AImpl_Initialize( &This->IDirectInput8A_iface, hinst, version );
-}
-
-static HRESULT WINAPI IDirectInput8AImpl_FindDevice(LPDIRECTINPUT8A iface, REFGUID rguid, LPCSTR pszName, LPGUID pguidInstance)
-{
-    IDirectInputImpl *This = impl_from_IDirectInput8A( iface );
-    return IDirectInput2AImpl_FindDevice( &This->IDirectInput7A_iface, rguid, pszName, pguidInstance );
-}
-
 static HRESULT WINAPI IDirectInput8WImpl_FindDevice(LPDIRECTINPUT8W iface, REFGUID rguid, LPCWSTR pszName, LPGUID pguidInstance)
 {
     IDirectInputImpl *This = impl_from_IDirectInput8W( iface );
@@ -1075,130 +909,6 @@ static BOOL should_enumerate_device(const WCHAR *username, DWORD dwFlags,
     return should_enumerate;
 }
 
-static HRESULT WINAPI IDirectInput8AImpl_EnumDevicesBySemantics(
-      LPDIRECTINPUT8A iface, LPCSTR ptszUserName, LPDIACTIONFORMATA lpdiActionFormat,
-      LPDIENUMDEVICESBYSEMANTICSCBA lpCallback,
-      LPVOID pvRef, DWORD dwFlags
-)
-{
-    static REFGUID guids[2] = { &GUID_SysKeyboard, &GUID_SysMouse };
-    static const DWORD actionMasks[] = { DIKEYBOARD_MASK, DIMOUSE_MASK };
-    IDirectInputImpl *This = impl_from_IDirectInput8A( iface );
-    DIDEVICEINSTANCEA didevi;
-    LPDIRECTINPUTDEVICE8A lpdid;
-    DWORD callbackFlags;
-    int i, j;
-    int device_count = 0;
-    int remain;
-    DIDEVICEINSTANCEA *didevis = 0;
-    WCHAR *username_w = 0;
-
-    FIXME("(this=%p,%s,%p,%p,%p,%04x): semi-stub\n", This, debugstr_a(ptszUserName), lpdiActionFormat,
-          lpCallback, pvRef, dwFlags);
-#define X(x) if (dwFlags & x) FIXME("\tdwFlags |= "#x"\n");
-	X(DIEDBSFL_ATTACHEDONLY)
-	X(DIEDBSFL_THISUSER)
-	X(DIEDBSFL_FORCEFEEDBACK)
-	X(DIEDBSFL_AVAILABLEDEVICES)
-	X(DIEDBSFL_MULTIMICEKEYBOARDS)
-	X(DIEDBSFL_NONGAMINGDEVICES)
-#undef X
-
-    _dump_diactionformatA(lpdiActionFormat);
-
-    didevi.dwSize = sizeof(didevi);
-
-    if (ptszUserName)
-    {
-        int len = MultiByteToWideChar(CP_ACP, 0, ptszUserName, -1, 0, 0);
-
-        username_w = HeapAlloc(GetProcessHeap(), 0, sizeof(WCHAR)*len);
-        MultiByteToWideChar(CP_ACP, 0, ptszUserName, -1, username_w, len);
-    }
-
-    /* Enumerate all the joysticks */
-    for (i = 0; i < ARRAY_SIZE(dinput_devices); i++)
-    {
-        HRESULT enumSuccess;
-
-        if (!dinput_devices[i]->enum_deviceA) continue;
-
-        for (j = 0, enumSuccess = S_OK; SUCCEEDED(enumSuccess); j++)
-        {
-            TRACE(" - checking device %u ('%s')\n", i, dinput_devices[i]->name);
-
-            /* Default behavior is to enumerate attached game controllers */
-            enumSuccess = dinput_devices[i]->enum_deviceA(DI8DEVCLASS_GAMECTRL, DIEDFL_ATTACHEDONLY | dwFlags, &didevi, This->dwVersion, j);
-            if (enumSuccess == S_OK &&
-                should_enumerate_device(username_w, dwFlags, &This->device_players, &didevi.guidInstance))
-            {
-                if (device_count++)
-                    didevis = HeapReAlloc(GetProcessHeap(), 0, didevis, sizeof(DIDEVICEINSTANCEA)*device_count);
-                else
-                    didevis = HeapAlloc(GetProcessHeap(), 0, sizeof(DIDEVICEINSTANCEA)*device_count);
-                didevis[device_count-1] = didevi;
-            }
-        }
-    }
-
-    remain = device_count;
-    /* Add keyboard and mouse to remaining device count */
-    if (!(dwFlags & DIEDBSFL_FORCEFEEDBACK))
-    {
-        for (i = 0; i < ARRAY_SIZE(guids); i++)
-        {
-            if (should_enumerate_device(username_w, dwFlags, &This->device_players, guids[i]))
-                remain++;
-        }
-    }
-
-    for (i = 0; i < device_count; i++)
-    {
-        callbackFlags = diactionformat_priorityA(lpdiActionFormat, lpdiActionFormat->dwGenre);
-        IDirectInput_CreateDevice(iface, &didevis[i].guidInstance, &lpdid, NULL);
-
-        if (lpCallback(&didevis[i], lpdid, callbackFlags, --remain, pvRef) == DIENUM_STOP)
-        {
-            IDirectInputDevice_Release(lpdid);
-            HeapFree(GetProcessHeap(), 0, didevis);
-            HeapFree(GetProcessHeap(), 0, username_w);
-            return DI_OK;
-        }
-        IDirectInputDevice_Release(lpdid);
-    }
-
-    HeapFree(GetProcessHeap(), 0, didevis);
-
-    if (dwFlags & DIEDBSFL_FORCEFEEDBACK)
-    {
-        HeapFree(GetProcessHeap(), 0, username_w);
-        return DI_OK;
-    }
-
-    /* Enumerate keyboard and mouse */
-    for (i = 0; i < ARRAY_SIZE(guids); i++)
-    {
-        if (should_enumerate_device(username_w, dwFlags, &This->device_players, guids[i]))
-        {
-            callbackFlags = diactionformat_priorityA(lpdiActionFormat, actionMasks[i]);
-
-            IDirectInput_CreateDevice(iface, guids[i], &lpdid, NULL);
-            IDirectInputDevice_GetDeviceInfo(lpdid, &didevi);
-
-            if (lpCallback(&didevi, lpdid, callbackFlags, --remain, pvRef) == DIENUM_STOP)
-            {
-                IDirectInputDevice_Release(lpdid);
-                HeapFree(GetProcessHeap(), 0, username_w);
-                return DI_OK;
-            }
-            IDirectInputDevice_Release(lpdid);
-        }
-    }
-
-    HeapFree(GetProcessHeap(), 0, username_w);
-    return DI_OK;
-}
-
 static HRESULT WINAPI IDirectInput8WImpl_EnumDevicesBySemantics(
       LPDIRECTINPUT8W iface, LPCWSTR ptszUserName, LPDIACTIONFORMATW lpdiActionFormat,
       LPDIENUMDEVICESBYSEMANTICSCBW lpCallback,
@@ -1304,54 +1014,6 @@ static HRESULT WINAPI IDirectInput8WImpl_ConfigureDevices(
     return _configure_devices(iface, lpdiCallback, lpdiCDParams, dwFlags, pvRefData);
 }
 
-static HRESULT WINAPI IDirectInput8AImpl_ConfigureDevices(
-      LPDIRECTINPUT8A iface, LPDICONFIGUREDEVICESCALLBACK lpdiCallback,
-      LPDICONFIGUREDEVICESPARAMSA lpdiCDParams, DWORD dwFlags, LPVOID pvRefData
-)
-{
-    IDirectInputImpl *This = impl_from_IDirectInput8A(iface);
-    DIACTIONFORMATW diafW;
-    DICONFIGUREDEVICESPARAMSW diCDParamsW;
-    HRESULT hr;
-    int i;
-
-     FIXME("(this=%p,%p,%p,%04x,%p): stub\n", This, lpdiCallback, lpdiCDParams, dwFlags, pvRefData);
-
-    /* Copy parameters */
-    diCDParamsW.dwSize = sizeof(DICONFIGUREDEVICESPARAMSW);
-    diCDParamsW.dwcFormats = lpdiCDParams->dwcFormats;
-    diCDParamsW.lprgFormats = &diafW;
-    diCDParamsW.hwnd = lpdiCDParams->hwnd;
-
-    diafW.rgoAction = HeapAlloc(GetProcessHeap(), 0, sizeof(DIACTIONW)*lpdiCDParams->lprgFormats->dwNumActions);
-    _copy_diactionformatAtoW(&diafW, lpdiCDParams->lprgFormats);
-
-    /* Copy action names */
-    for (i=0; i < diafW.dwNumActions; i++)
-    {
-        const char* from = lpdiCDParams->lprgFormats->rgoAction[i].u.lptszActionName;
-        int len = MultiByteToWideChar(CP_ACP, 0, from , -1, NULL , 0);
-        WCHAR *to = HeapAlloc(GetProcessHeap(), 0, sizeof(WCHAR)*len);
-
-        MultiByteToWideChar(CP_ACP, 0, from , -1, to , len);
-        diafW.rgoAction[i].u.lptszActionName = to;
-    }
-
-    hr = IDirectInput8WImpl_ConfigureDevices(&This->IDirectInput8W_iface, lpdiCallback, &diCDParamsW, dwFlags, pvRefData);
-
-    /* Copy back configuration */
-    if (SUCCEEDED(hr))
-        _copy_diactionformatWtoA(lpdiCDParams->lprgFormats, &diafW);
-
-    /* Free memory */
-    for (i=0; i < diafW.dwNumActions; i++)
-        HeapFree(GetProcessHeap(), 0, (void*) diafW.rgoAction[i].u.lptszActionName);
-
-    HeapFree(GetProcessHeap(), 0, diafW.rgoAction);
-
-    return hr;
-}
-
 /*****************************************************************************
  * IDirectInputJoyConfig8 interface
  */
@@ -1364,19 +1026,19 @@ static inline IDirectInputImpl *impl_from_IDirectInputJoyConfig8(IDirectInputJoy
 static HRESULT WINAPI JoyConfig8Impl_QueryInterface(IDirectInputJoyConfig8 *iface, REFIID riid, void** ppobj)
 {
     IDirectInputImpl *This = impl_from_IDirectInputJoyConfig8( iface );
-    return IDirectInputAImpl_QueryInterface( &This->IDirectInput7A_iface, riid, ppobj );
+    return IDirectInput7_QueryInterface(&This->IDirectInput7A_iface, riid, ppobj);
 }
 
 static ULONG WINAPI JoyConfig8Impl_AddRef(IDirectInputJoyConfig8 *iface)
 {
     IDirectInputImpl *This = impl_from_IDirectInputJoyConfig8( iface );
-    return IDirectInputAImpl_AddRef( &This->IDirectInput7A_iface );
+    return IDirectInput7_AddRef(&This->IDirectInput7A_iface);
 }
 
 static ULONG WINAPI JoyConfig8Impl_Release(IDirectInputJoyConfig8 *iface)
 {
     IDirectInputImpl *This = impl_from_IDirectInputJoyConfig8( iface );
-    return IDirectInputAImpl_Release( &This->IDirectInput7A_iface );
+    return IDirectInput7_Release(&This->IDirectInput7A_iface);
 }
 
 static HRESULT WINAPI JoyConfig8Impl_Acquire(IDirectInputJoyConfig8 *iface)
@@ -1539,20 +1201,6 @@ static const IDirectInput7WVtbl ddi7wvt = {
     IDirectInput7WImpl_CreateDeviceEx
 };
 
-static const IDirectInput8AVtbl ddi8avt = {
-    IDirectInput8AImpl_QueryInterface,
-    IDirectInput8AImpl_AddRef,
-    IDirectInput8AImpl_Release,
-    IDirectInput8AImpl_CreateDevice,
-    IDirectInput8AImpl_EnumDevices,
-    IDirectInput8AImpl_GetDeviceStatus,
-    IDirectInput8AImpl_RunControlPanel,
-    IDirectInput8AImpl_Initialize,
-    IDirectInput8AImpl_FindDevice,
-    IDirectInput8AImpl_EnumDevicesBySemantics,
-    IDirectInput8AImpl_ConfigureDevices
-};
-
 static const IDirectInput8WVtbl ddi8wvt = {
     IDirectInput8WImpl_QueryInterface,
     IDirectInput8WImpl_AddRef,
diff --git a/dlls/dinput/dinput_private.h b/dlls/dinput/dinput_private.h
index ac967af4e8a..07be7b2dd8d 100644
--- a/dlls/dinput/dinput_private.h
+++ b/dlls/dinput/dinput_private.h
@@ -49,6 +49,8 @@ struct IDirectInputImpl
     struct list                 device_players; /* device instance guid to player name */
 };
 
+extern const IDirectInput8AVtbl direct_input_8_a_vtbl DECLSPEC_HIDDEN;
+
 typedef struct IDirectInputDeviceImpl IDirectInputDeviceImpl;
 
 /* Function called by all devices that Wine supports */
@@ -83,9 +85,6 @@ extern void dinput_mouse_rawinput_hook( IDirectInputDevice8W *iface, WPARAM wpar
 extern void check_dinput_hooks(LPDIRECTINPUTDEVICE8W, BOOL) DECLSPEC_HIDDEN;
 extern void check_dinput_events(void) DECLSPEC_HIDDEN;
 
-extern void _copy_diactionformatAtoW(LPDIACTIONFORMATW, LPDIACTIONFORMATA) DECLSPEC_HIDDEN;
-extern void _copy_diactionformatWtoA(LPDIACTIONFORMATA, LPDIACTIONFORMATW) DECLSPEC_HIDDEN;
-
 extern HRESULT _configure_devices(IDirectInput8W *iface, LPDICONFIGUREDEVICESCALLBACK lpdiCallback, LPDICONFIGUREDEVICESPARAMSW lpdiCDParams, DWORD dwFlags, LPVOID pvRefData) DECLSPEC_HIDDEN;
 
 extern WCHAR* get_mapping_path(const WCHAR *device, const WCHAR *username) DECLSPEC_HIDDEN;
-- 
2.28.0

>From 5129ef74aecd6aaaa7e8b4320c6cd04d33ea3c63 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?R=C3=A9mi=20Bernon?= <rbernon@codeweavers.com>
Date: Mon, 5 Oct 2020 12:44:47 +0200
Subject: [PATCH 07/39] dinput: Factor IDirectInput7A implementation.

As a wrapper around IDirectInput7W interface, and use it consistently.
---
 dlls/dinput/ansi.c           | 115 +++++++++++++++++++++++++
 dlls/dinput/dinput_main.c    | 161 ++++-------------------------------
 dlls/dinput/dinput_private.h |   1 +
 3 files changed, 131 insertions(+), 146 deletions(-)

diff --git a/dlls/dinput/ansi.c b/dlls/dinput/ansi.c
index c2bd088ae6a..a3d49802b7c 100644
--- a/dlls/dinput/ansi.c
+++ b/dlls/dinput/ansi.c
@@ -49,6 +49,19 @@ static inline IDirectInputDevice8A *IDirectInputDevice8A_from_IDirectInputDevice
     if (!iface) return NULL;
     return &CONTAINING_RECORD(iface, IDirectInputDeviceImpl, IDirectInputDevice8W_iface)->IDirectInputDevice8A_iface;
 }
+static inline IDirectInputDeviceA *IDirectInputDeviceA_from_IDirectInputDeviceW(IDirectInputDeviceW *iface)
+{
+    return (IDirectInputDeviceA *)IDirectInputDevice8A_from_IDirectInputDevice8W((IDirectInputDevice8W *)iface);
+}
+
+static IDirectInputImpl *impl_from_IDirectInput7A(IDirectInput7A *iface)
+{
+    return CONTAINING_RECORD(iface, IDirectInputImpl, IDirectInput7A_iface);
+}
+static IDirectInput7W *IDirectInput7W_from_impl(IDirectInputImpl *This)
+{
+    return &This->IDirectInput7W_iface;
+}
 static IDirectInputImpl *impl_from_IDirectInput8A(IDirectInput8A *iface)
 {
     return CONTAINING_RECORD(iface, IDirectInputImpl, IDirectInput8A_iface);
@@ -775,3 +788,105 @@ const IDirectInput8AVtbl direct_input_8_a_vtbl =
     direct_input_8_a_EnumDevicesBySemantics,
     direct_input_8_a_ConfigureDevices,
 };
+
+static HRESULT STDMETHODCALLTYPE direct_input_7_a_QueryInterface(IDirectInput7A *iface, REFIID iid, void **out)
+{
+    IDirectInputImpl *This = impl_from_IDirectInput7A(iface);
+    TRACE("iface %p, iid %s, out %p.\n", iface, debugstr_guid(iid), out);
+    return IDirectInput7_QueryInterface(IDirectInput7W_from_impl(This), iid, out);
+}
+
+static ULONG STDMETHODCALLTYPE direct_input_7_a_AddRef(IDirectInput7A *iface)
+{
+    IDirectInputImpl *This = impl_from_IDirectInput7A(iface);
+    TRACE("iface %p.\n", iface);
+    return IDirectInput7_AddRef(IDirectInput7W_from_impl(This));
+}
+
+static ULONG STDMETHODCALLTYPE direct_input_7_a_Release(IDirectInput7A *iface)
+{
+    IDirectInputImpl *This = impl_from_IDirectInput7A(iface);
+    TRACE("iface %p.\n", iface);
+    return IDirectInput7_Release(IDirectInput7W_from_impl(This));
+}
+
+static HRESULT STDMETHODCALLTYPE direct_input_7_a_CreateDevice(IDirectInput7A *iface, REFGUID guid,
+        IDirectInputDeviceA **out, IUnknown *outer)
+{
+    IDirectInputImpl *This = impl_from_IDirectInput7A(iface);
+    IDirectInputDeviceW *outw;
+    HRESULT hr;
+    TRACE("iface %p, guid %s, out %p, outer %p.\n", iface, debugstr_guid(guid), out, outer);
+    if (!out) return E_POINTER;
+    hr = IDirectInput7_CreateDevice(IDirectInput7W_from_impl(This), guid, &outw, outer);
+    *out = IDirectInputDeviceA_from_IDirectInputDeviceW(outw);
+    return hr;
+}
+
+static HRESULT STDMETHODCALLTYPE direct_input_7_a_EnumDevices(IDirectInput7A *iface, DWORD type,
+        LPDIENUMDEVICESCALLBACKA callback, void *ref, DWORD flags)
+{
+    struct direct_input_a_enum_devices_params params = {callback, ref};
+    IDirectInputImpl *This = impl_from_IDirectInput7A(iface);
+    TRACE("iface %p, callback %p, ref %p, flags %#x.\n", iface, callback, ref, flags);
+    if (!callback) return DIERR_INVALIDPARAM;
+    return IDirectInput7_EnumDevices(IDirectInput7W_from_impl(This), type, direct_input_a_enum_devices_callback, &params, flags);
+}
+
+static HRESULT STDMETHODCALLTYPE direct_input_7_a_GetDeviceStatus(IDirectInput7A *iface, REFGUID instance_guid)
+{
+    IDirectInputImpl *This = impl_from_IDirectInput7A(iface);
+    TRACE("iface %p, instance_guid %s.\n", iface, debugstr_guid(instance_guid));
+    return IDirectInput7_GetDeviceStatus(IDirectInput7W_from_impl(This), instance_guid);
+}
+
+static HRESULT STDMETHODCALLTYPE direct_input_7_a_RunControlPanel(IDirectInput7A *iface, HWND owner, DWORD flags)
+{
+    IDirectInputImpl *This = impl_from_IDirectInput7A(iface);
+    TRACE("iface %p, owner %p, flags %#x.\n", iface, owner, flags);
+    return IDirectInput7_RunControlPanel(IDirectInput7W_from_impl(This), owner, flags);
+}
+
+static HRESULT STDMETHODCALLTYPE direct_input_7_a_Initialize(IDirectInput7A *iface, HINSTANCE instance, DWORD version)
+{
+    IDirectInputImpl *This = impl_from_IDirectInput7A(iface);
+    TRACE("iface %p, instance %p, version %#x.\n", iface, instance, version);
+    return IDirectInput7_Initialize(IDirectInput7W_from_impl(This), instance, version);
+}
+
+static HRESULT STDMETHODCALLTYPE direct_input_7_a_FindDevice(IDirectInput7A *iface, REFGUID guid, const char *name, GUID *instance_guid)
+{
+    IDirectInputImpl *This = impl_from_IDirectInput7A(iface);
+    WCHAR *namew = string_atow(name);
+    HRESULT hr;
+    TRACE("iface %p, guid %p, name %s, instance_guid %p.\n", iface, debugstr_guid(guid), debugstr_a(name), instance_guid);
+    hr = IDirectInput7_FindDevice(IDirectInput7W_from_impl(This), guid, namew, instance_guid);
+    HeapFree(GetProcessHeap(), 0, namew);
+    return hr;
+}
+
+static HRESULT STDMETHODCALLTYPE direct_input_7_a_CreateDeviceEx(IDirectInput7A *iface, REFGUID guid, REFIID iid,
+        void **out, IUnknown *outer)
+{
+    IDirectInputImpl *This = impl_from_IDirectInput7A(iface);
+    TRACE("iface %p, guid %s, iid %s, out %p, outer %p.\n", iface, debugstr_guid(guid), debugstr_guid(iid), out, outer);
+    return IDirectInput7_CreateDeviceEx(IDirectInput7W_from_impl(This), guid, iid, out, outer);
+}
+
+const IDirectInput7AVtbl direct_input_7_a_vtbl =
+{
+    /*** IUnknown methods ***/
+    direct_input_7_a_QueryInterface,
+    direct_input_7_a_AddRef,
+    direct_input_7_a_Release,
+    /*** IDirectInputA methods ***/
+    direct_input_7_a_CreateDevice,
+    direct_input_7_a_EnumDevices,
+    direct_input_7_a_GetDeviceStatus,
+    direct_input_7_a_RunControlPanel,
+    direct_input_7_a_Initialize,
+    /*** IDirectInput2A methods ***/
+    direct_input_7_a_FindDevice,
+    /*** IDirectInput7A methods ***/
+    direct_input_7_a_CreateDeviceEx,
+};
diff --git a/dlls/dinput/dinput_main.c b/dlls/dinput/dinput_main.c
index 4a57947532e..3c348964d9b 100644
--- a/dlls/dinput/dinput_main.c
+++ b/dlls/dinput/dinput_main.c
@@ -55,16 +55,10 @@
 
 WINE_DEFAULT_DEBUG_CHANNEL(dinput);
 
-static const IDirectInput7AVtbl ddi7avt;
 static const IDirectInput7WVtbl ddi7wvt;
 static const IDirectInput8WVtbl ddi8wvt;
 static const IDirectInputJoyConfig8Vtbl JoyConfig8vt;
 
-static inline IDirectInputImpl *impl_from_IDirectInput7A( IDirectInput7A *iface )
-{
-    return CONTAINING_RECORD( iface, IDirectInputImpl, IDirectInput7A_iface );
-}
-
 static inline IDirectInputImpl *impl_from_IDirectInput7W( IDirectInput7W *iface )
 {
     return CONTAINING_RECORD( iface, IDirectInputImpl, IDirectInput7W_iface );
@@ -136,7 +130,7 @@ static HRESULT create_directinput_instance(REFIID riid, LPVOID *ppDI, IDirectInp
     if (!This)
         return E_OUTOFMEMORY;
 
-    This->IDirectInput7A_iface.lpVtbl = &ddi7avt;
+    This->IDirectInput7A_iface.lpVtbl = &direct_input_7_a_vtbl;
     This->IDirectInput7W_iface.lpVtbl = &ddi7wvt;
     This->IDirectInput8A_iface.lpVtbl = &direct_input_8_a_vtbl;
     This->IDirectInput8W_iface.lpVtbl = &ddi8wvt;
@@ -361,47 +355,6 @@ __ASM_GLOBAL_FUNC( enum_callback_wrapper,
 #define enum_callback_wrapper(callback, instance, ref) (callback)((instance), (ref))
 #endif
 
-/******************************************************************************
- *	IDirectInputA_EnumDevices
- */
-static HRESULT WINAPI IDirectInputAImpl_EnumDevices(
-	LPDIRECTINPUT7A iface, DWORD dwDevType, LPDIENUMDEVICESCALLBACKA lpCallback,
-	LPVOID pvRef, DWORD dwFlags)
-{
-    IDirectInputImpl *This = impl_from_IDirectInput7A(iface);
-    DIDEVICEINSTANCEA devInstance;
-    unsigned int i;
-    int j;
-    HRESULT r;
-
-    TRACE("(this=%p,0x%04x '%s',%p,%p,0x%04x)\n",
-	  This, dwDevType, _dump_DIDEVTYPE_value(dwDevType, This->dwVersion),
-	  lpCallback, pvRef, dwFlags);
-    _dump_EnumDevices_dwFlags(dwFlags);
-
-    if (!lpCallback ||
-        dwFlags & ~(DIEDFL_ATTACHEDONLY | DIEDFL_FORCEFEEDBACK | DIEDFL_INCLUDEALIASES | DIEDFL_INCLUDEPHANTOMS | DIEDFL_INCLUDEHIDDEN) ||
-        (dwDevType > DI8DEVCLASS_GAMECTRL && dwDevType < DI8DEVTYPE_DEVICE) || dwDevType > DI8DEVTYPE_SUPPLEMENTAL)
-        return DIERR_INVALIDPARAM;
-
-    if (!This->initialized)
-        return DIERR_NOTINITIALIZED;
-
-    for (i = 0; i < ARRAY_SIZE(dinput_devices); i++) {
-        if (!dinput_devices[i]->enum_deviceA) continue;
-
-        TRACE(" Checking device %u ('%s')\n", i, dinput_devices[i]->name);
-        for (j = 0, r = S_OK; SUCCEEDED(r); j++) {
-            devInstance.dwSize = sizeof(devInstance);
-            r = dinput_devices[i]->enum_deviceA(dwDevType, dwFlags, &devInstance, This->dwVersion, j);
-            if (r == S_OK)
-                if (enum_callback_wrapper(lpCallback, &devInstance, pvRef) == DIENUM_STOP)
-                    return S_OK;
-        }
-    }
-
-    return S_OK;
-}
 /******************************************************************************
  *	IDirectInputW_EnumDevices
  */
@@ -443,24 +396,18 @@ static HRESULT WINAPI IDirectInputWImpl_EnumDevices(
     return S_OK;
 }
 
-static ULONG WINAPI IDirectInputAImpl_AddRef(LPDIRECTINPUT7A iface)
+static ULONG WINAPI IDirectInputWImpl_AddRef(LPDIRECTINPUT7W iface)
 {
-    IDirectInputImpl *This = impl_from_IDirectInput7A( iface );
+    IDirectInputImpl *This = impl_from_IDirectInput7W(iface);
     ULONG ref = InterlockedIncrement(&This->ref);
 
     TRACE( "(%p) ref %d\n", This, ref );
     return ref;
 }
 
-static ULONG WINAPI IDirectInputWImpl_AddRef(LPDIRECTINPUT7W iface)
+static ULONG WINAPI IDirectInputWImpl_Release(LPDIRECTINPUT7W iface)
 {
     IDirectInputImpl *This = impl_from_IDirectInput7W( iface );
-    return IDirectInputAImpl_AddRef( &This->IDirectInput7A_iface );
-}
-
-static ULONG WINAPI IDirectInputAImpl_Release(LPDIRECTINPUT7A iface)
-{
-    IDirectInputImpl *This = impl_from_IDirectInput7A( iface );
     ULONG ref = InterlockedDecrement( &This->ref );
 
     TRACE( "(%p) ref %d\n", This, ref );
@@ -474,15 +421,9 @@ static ULONG WINAPI IDirectInputAImpl_Release(LPDIRECTINPUT7A iface)
     return ref;
 }
 
-static ULONG WINAPI IDirectInputWImpl_Release(LPDIRECTINPUT7W iface)
+static HRESULT WINAPI IDirectInputWImpl_QueryInterface(LPDIRECTINPUT7W iface, REFIID riid, LPVOID *ppobj)
 {
     IDirectInputImpl *This = impl_from_IDirectInput7W( iface );
-    return IDirectInputAImpl_Release( &This->IDirectInput7A_iface );
-}
-
-static HRESULT WINAPI IDirectInputAImpl_QueryInterface(LPDIRECTINPUT7A iface, REFIID riid, LPVOID *ppobj)
-{
-    IDirectInputImpl *This = impl_from_IDirectInput7A( iface );
 
     TRACE( "(%p)->(%s,%p)\n", This, debugstr_guid(riid), ppobj );
 
@@ -525,12 +466,6 @@ static HRESULT WINAPI IDirectInputAImpl_QueryInterface(LPDIRECTINPUT7A iface, RE
     return E_NOINTERFACE;
 }
 
-static HRESULT WINAPI IDirectInputWImpl_QueryInterface(LPDIRECTINPUT7W iface, REFIID riid, LPVOID *ppobj)
-{
-    IDirectInputImpl *This = impl_from_IDirectInput7W( iface );
-    return IDirectInputAImpl_QueryInterface( &This->IDirectInput7A_iface, riid, ppobj );
-}
-
 static LRESULT WINAPI di_em_win_wndproc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam)
 {
     IDirectInputDeviceImpl *dev;
@@ -634,9 +569,9 @@ enum directinput_versions
     DIRECTINPUT_VERSION_700 = 0x0700,
 };
 
-static HRESULT WINAPI IDirectInputAImpl_Initialize(LPDIRECTINPUT7A iface, HINSTANCE hinst, DWORD version)
+static HRESULT WINAPI IDirectInputWImpl_Initialize(LPDIRECTINPUT7W iface, HINSTANCE hinst, DWORD version)
 {
-    IDirectInputImpl *This = impl_from_IDirectInput7A( iface );
+    IDirectInputImpl *This = impl_from_IDirectInput7W(iface);
 
     TRACE("(%p)->(%p, 0x%04x)\n", This, hinst, version);
 
@@ -655,17 +590,11 @@ static HRESULT WINAPI IDirectInputAImpl_Initialize(LPDIRECTINPUT7A iface, HINSTA
     return initialize_directinput_instance(This, version);
 }
 
-static HRESULT WINAPI IDirectInputWImpl_Initialize(LPDIRECTINPUT7W iface, HINSTANCE hinst, DWORD x)
+static HRESULT WINAPI IDirectInputWImpl_GetDeviceStatus(LPDIRECTINPUT7W iface, REFGUID rguid)
 {
     IDirectInputImpl *This = impl_from_IDirectInput7W( iface );
-    return IDirectInputAImpl_Initialize( &This->IDirectInput7A_iface, hinst, x );
-}
-
-static HRESULT WINAPI IDirectInputAImpl_GetDeviceStatus(LPDIRECTINPUT7A iface, REFGUID rguid)
-{
-    IDirectInputImpl *This = impl_from_IDirectInput7A( iface );
     HRESULT hr;
-    LPDIRECTINPUTDEVICEA device;
+    LPDIRECTINPUTDEVICEW device;
 
     TRACE( "(%p)->(%s)\n", This, debugstr_guid(rguid) );
 
@@ -681,22 +610,13 @@ static HRESULT WINAPI IDirectInputAImpl_GetDeviceStatus(LPDIRECTINPUT7A iface, R
     return DI_OK;
 }
 
-static HRESULT WINAPI IDirectInputWImpl_GetDeviceStatus(LPDIRECTINPUT7W iface, REFGUID rguid)
+static HRESULT WINAPI IDirectInputWImpl_RunControlPanel(LPDIRECTINPUT7W iface, HWND hwndOwner, DWORD dwFlags)
 {
     IDirectInputImpl *This = impl_from_IDirectInput7W( iface );
-    return IDirectInputAImpl_GetDeviceStatus( &This->IDirectInput7A_iface, rguid );
-}
-
-static HRESULT WINAPI IDirectInputAImpl_RunControlPanel(LPDIRECTINPUT7A iface,
-							HWND hwndOwner,
-							DWORD dwFlags)
-{
     WCHAR control_exeW[] = {'c','o','n','t','r','o','l','.','e','x','e',0};
     STARTUPINFOW si = {0};
     PROCESS_INFORMATION pi;
 
-    IDirectInputImpl *This = impl_from_IDirectInput7A( iface );
-
     TRACE( "(%p)->(%p, %08x)\n", This, hwndOwner, dwFlags );
 
     if (hwndOwner && !IsWindow(hwndOwner))
@@ -714,22 +634,6 @@ static HRESULT WINAPI IDirectInputAImpl_RunControlPanel(LPDIRECTINPUT7A iface,
     return DI_OK;
 }
 
-static HRESULT WINAPI IDirectInputWImpl_RunControlPanel(LPDIRECTINPUT7W iface, HWND hwndOwner, DWORD dwFlags)
-{
-    IDirectInputImpl *This = impl_from_IDirectInput7W( iface );
-    return IDirectInputAImpl_RunControlPanel( &This->IDirectInput7A_iface, hwndOwner, dwFlags );
-}
-
-static HRESULT WINAPI IDirectInput2AImpl_FindDevice(LPDIRECTINPUT7A iface, REFGUID rguid,
-						    LPCSTR pszName, LPGUID pguidInstance)
-{
-    IDirectInputImpl *This = impl_from_IDirectInput7A( iface );
-
-    FIXME( "(%p)->(%s, %s, %p): stub\n", This, debugstr_guid(rguid), pszName, pguidInstance );
-
-    return DI_OK;
-}
-
 static HRESULT WINAPI IDirectInput2WImpl_FindDevice(LPDIRECTINPUT7W iface, REFGUID rguid,
 						    LPCWSTR pszName, LPGUID pguidInstance)
 {
@@ -740,11 +644,15 @@ static HRESULT WINAPI IDirectInput2WImpl_FindDevice(LPDIRECTINPUT7W iface, REFGU
     return DI_OK;
 }
 
-static HRESULT create_device(IDirectInputImpl *This, REFGUID rguid, REFIID riid, LPVOID *pvOut)
+static HRESULT WINAPI IDirectInput7WImpl_CreateDeviceEx(LPDIRECTINPUT7W iface, REFGUID rguid, REFIID riid,
+        LPVOID *pvOut, LPUNKNOWN lpUnknownOuter)
 {
+    IDirectInputImpl *This = impl_from_IDirectInput7W(iface);
     unsigned int i;
     HRESULT hr;
 
+    TRACE("(%p)->(%s, %s, %p, %p)\n", This, debugstr_guid(rguid), debugstr_guid(riid), pvOut, lpUnknownOuter);
+
     if (pvOut)
         *pvOut = NULL;
 
@@ -764,32 +672,6 @@ static HRESULT create_device(IDirectInputImpl *This, REFGUID rguid, REFIID riid,
     return DIERR_DEVICENOTREG;
 }
 
-static HRESULT WINAPI IDirectInput7AImpl_CreateDeviceEx(LPDIRECTINPUT7A iface, REFGUID rguid,
-                                                        REFIID riid, LPVOID* pvOut, LPUNKNOWN lpUnknownOuter)
-{
-    IDirectInputImpl *This = impl_from_IDirectInput7A( iface );
-
-    TRACE("(%p)->(%s, %s, %p, %p)\n", This, debugstr_guid(rguid), debugstr_guid(riid), pvOut, lpUnknownOuter);
-
-    return create_device(This, rguid, riid, pvOut);
-}
-
-static HRESULT WINAPI IDirectInput7WImpl_CreateDeviceEx(LPDIRECTINPUT7W iface, REFGUID rguid,
-                                                        REFIID riid, LPVOID* pvOut, LPUNKNOWN lpUnknownOuter)
-{
-    IDirectInputImpl *This = impl_from_IDirectInput7W( iface );
-
-    TRACE("(%p)->(%s, %s, %p, %p)\n", This, debugstr_guid(rguid), debugstr_guid(riid), pvOut, lpUnknownOuter);
-
-    return create_device(This, rguid, riid, pvOut);
-}
-
-static HRESULT WINAPI IDirectInputAImpl_CreateDevice(LPDIRECTINPUT7A iface, REFGUID rguid,
-                                                     LPDIRECTINPUTDEVICEA* pdev, LPUNKNOWN punk)
-{
-    return IDirectInput7AImpl_CreateDeviceEx(iface, rguid, &IID_IDirectInputDeviceA, (LPVOID *)pdev, punk);
-}
-
 static HRESULT WINAPI IDirectInputWImpl_CreateDevice(LPDIRECTINPUT7W iface, REFGUID rguid,
                                                      LPDIRECTINPUTDEVICEW* pdev, LPUNKNOWN punk)
 {
@@ -1175,19 +1057,6 @@ static HRESULT WINAPI JoyConfig8Impl_OpenAppStatusKey(IDirectInputJoyConfig8 *if
     return E_NOTIMPL;
 }
 
-static const IDirectInput7AVtbl ddi7avt = {
-    IDirectInputAImpl_QueryInterface,
-    IDirectInputAImpl_AddRef,
-    IDirectInputAImpl_Release,
-    IDirectInputAImpl_CreateDevice,
-    IDirectInputAImpl_EnumDevices,
-    IDirectInputAImpl_GetDeviceStatus,
-    IDirectInputAImpl_RunControlPanel,
-    IDirectInputAImpl_Initialize,
-    IDirectInput2AImpl_FindDevice,
-    IDirectInput7AImpl_CreateDeviceEx
-};
-
 static const IDirectInput7WVtbl ddi7wvt = {
     IDirectInputWImpl_QueryInterface,
     IDirectInputWImpl_AddRef,
diff --git a/dlls/dinput/dinput_private.h b/dlls/dinput/dinput_private.h
index 07be7b2dd8d..31166539da8 100644
--- a/dlls/dinput/dinput_private.h
+++ b/dlls/dinput/dinput_private.h
@@ -49,6 +49,7 @@ struct IDirectInputImpl
     struct list                 device_players; /* device instance guid to player name */
 };
 
+extern const IDirectInput7AVtbl direct_input_7_a_vtbl DECLSPEC_HIDDEN;
 extern const IDirectInput8AVtbl direct_input_8_a_vtbl DECLSPEC_HIDDEN;
 
 typedef struct IDirectInputDeviceImpl IDirectInputDeviceImpl;
-- 
2.28.0

>From 6e5665d2804421f9349376da3b14a97f9167c9c0 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?R=C3=A9mi=20Bernon?= <rbernon@codeweavers.com>
Date: Mon, 5 Oct 2020 12:44:47 +0200
Subject: [PATCH 08/39] dinput: Introduce dinput_enum_device helper.

To wrap enum_deviceA/W calls, so that only one of the two is needed.
Unix devices won't be able to handle WCHAR easily.
---
 dlls/dinput/ansi.c           | 25 +++++++++++++++++++++++++
 dlls/dinput/dinput_main.c    | 14 ++++----------
 dlls/dinput/dinput_private.h |  2 ++
 3 files changed, 31 insertions(+), 10 deletions(-)

diff --git a/dlls/dinput/ansi.c b/dlls/dinput/ansi.c
index a3d49802b7c..81ac24f4d26 100644
--- a/dlls/dinput/ansi.c
+++ b/dlls/dinput/ansi.c
@@ -103,6 +103,19 @@ static void dideviceinstance_wtoa(const DIDEVICEINSTANCEW *didiw, DIDEVICEINSTAN
     didia->wUsage = didiw->wUsage;
 }
 
+static void dideviceinstance_atow(const DIDEVICEINSTANCEA *didia, DIDEVICEINSTANCEW *didiw)
+{
+    didiw->guidInstance = didia->guidInstance;
+    didiw->guidProduct = didia->guidProduct;
+    didiw->dwDevType = didia->dwDevType;
+    MultiByteToWideChar(CP_ACP, 0, didia->tszInstanceName, -1, didiw->tszInstanceName, sizeof(didiw->tszInstanceName));
+    MultiByteToWideChar(CP_ACP, 0, didia->tszProductName, -1, didiw->tszProductName, sizeof(didiw->tszProductName));
+    if (didiw->dwSize <= FIELD_OFFSET(DIDEVICEINSTANCEW, guidFFDriver)) return;
+    didiw->guidFFDriver = didia->guidFFDriver;
+    didiw->wUsagePage = didia->wUsagePage;
+    didiw->wUsage = didia->wUsage;
+}
+
 static void dieffectinfo_wtoa(const DIEFFECTINFOW *dieiw, DIEFFECTINFOA *dieia)
 {
     dieia->guid = dieiw->guid;
@@ -890,3 +903,15 @@ const IDirectInput7AVtbl direct_input_7_a_vtbl =
     /*** IDirectInput7A methods ***/
     direct_input_7_a_CreateDeviceEx,
 };
+
+HRESULT dinput_enum_device(const struct dinput_device *device, DWORD type, DWORD flags, DIDEVICEINSTANCEW *didi,
+        DWORD version, int index)
+{
+    DIDEVICEINSTANCEA didia = {sizeof(didia)};
+    HRESULT hr;
+    if (device->enum_deviceW) return device->enum_deviceW(type, flags, didi, version, index);
+    if (!device->enum_deviceA) return E_FAIL;
+    hr = device->enum_deviceA(type, flags, &didia, version, index);
+    dideviceinstance_atow(&didia, didi);
+    return hr;
+}
diff --git a/dlls/dinput/dinput_main.c b/dlls/dinput/dinput_main.c
index 3c348964d9b..42832b8d715 100644
--- a/dlls/dinput/dinput_main.c
+++ b/dlls/dinput/dinput_main.c
@@ -382,11 +382,10 @@ static HRESULT WINAPI IDirectInputWImpl_EnumDevices(
         return DIERR_NOTINITIALIZED;
 
     for (i = 0; i < ARRAY_SIZE(dinput_devices); i++) {
-        if (!dinput_devices[i]->enum_deviceW) continue;
         for (j = 0, r = S_OK; SUCCEEDED(r); j++) {
             devInstance.dwSize = sizeof(devInstance);
             TRACE("  - checking device %u ('%s')\n", i, dinput_devices[i]->name);
-            r = dinput_devices[i]->enum_deviceW(dwDevType, dwFlags, &devInstance, This->dwVersion, j);
+            r = dinput_enum_device(dinput_devices[i], dwDevType, dwFlags, &devInstance, This->dwVersion, j);
             if (r == S_OK)
                 if (enum_callback_wrapper(lpCallback, &devInstance, pvRef) == DIENUM_STOP)
                     return S_OK;
@@ -817,15 +816,12 @@ static HRESULT WINAPI IDirectInput8WImpl_EnumDevicesBySemantics(
     for (i = 0; i < ARRAY_SIZE(dinput_devices); i++)
     {
         HRESULT enumSuccess;
-
-        if (!dinput_devices[i]->enum_deviceW) continue;
-
         for (j = 0, enumSuccess = S_OK; SUCCEEDED(enumSuccess); j++)
         {
             TRACE(" - checking device %u ('%s')\n", i, dinput_devices[i]->name);
 
             /* Default behavior is to enumerate attached game controllers */
-            enumSuccess = dinput_devices[i]->enum_deviceW(DI8DEVCLASS_GAMECTRL, DIEDFL_ATTACHEDONLY | dwFlags, &didevi, This->dwVersion, j);
+            enumSuccess = dinput_enum_device(dinput_devices[i], DI8DEVCLASS_GAMECTRL, DIEDFL_ATTACHEDONLY | dwFlags, &didevi, This->dwVersion, j);
             if (enumSuccess == S_OK &&
                 should_enumerate_device(ptszUserName, dwFlags, &This->device_players, &didevi.guidInstance))
             {
@@ -991,13 +987,11 @@ static HRESULT WINAPI JoyConfig8Impl_GetConfig(IDirectInputJoyConfig8 *iface, UI
     /* Enumerate all joysticks in order */
     for (i = 0; i < ARRAY_SIZE(dinput_devices); i++)
     {
-        if (!dinput_devices[i]->enum_deviceA) continue;
-
         for (j = 0, r = S_OK; SUCCEEDED(r); j++)
         {
-            DIDEVICEINSTANCEA dev;
+            DIDEVICEINSTANCEW dev;
             dev.dwSize = sizeof(dev);
-            if ((r = dinput_devices[i]->enum_deviceA(DI8DEVCLASS_GAMECTRL, 0, &dev, di->dwVersion, j)) == S_OK)
+            if ((r = dinput_enum_device(dinput_devices[i], DI8DEVCLASS_GAMECTRL, 0, &dev, di->dwVersion, j)) == S_OK)
             {
                 /* Only take into account the chosen id */
                 if (found == id)
diff --git a/dlls/dinput/dinput_private.h b/dlls/dinput/dinput_private.h
index 31166539da8..472f21adb1b 100644
--- a/dlls/dinput/dinput_private.h
+++ b/dlls/dinput/dinput_private.h
@@ -64,6 +64,8 @@ struct dinput_device {
 
 extern HRESULT dinput_create_device(const struct dinput_device *device, IDirectInputImpl *dinput, REFGUID guid,
         REFIID iid, void **out) DECLSPEC_HIDDEN;
+extern HRESULT dinput_enum_device(const struct dinput_device *device, DWORD type, DWORD flags, DIDEVICEINSTANCEW *didi,
+        DWORD version, int index) DECLSPEC_HIDDEN;
 
 struct DevicePlayer {
     GUID instance_guid;
-- 
2.28.0

>From a733b44aba29cf83698d00601054d5cb1cf8ed7e Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?R=C3=A9mi=20Bernon?= <rbernon@codeweavers.com>
Date: Mon, 5 Oct 2020 12:44:47 +0200
Subject: [PATCH 09/39] dinput: Remove enum_deviceW from unix devices.

And enum_deviceA from Win32 devices.
---
 dlls/dinput/joystick_linux.c      | 31 +-----------------
 dlls/dinput/joystick_linuxinput.c | 27 +---------------
 dlls/dinput/joystick_osx.c        | 52 +------------------------------
 dlls/dinput/keyboard.c            | 47 +---------------------------
 dlls/dinput/mouse.c               | 47 +---------------------------
 5 files changed, 5 insertions(+), 199 deletions(-)

diff --git a/dlls/dinput/joystick_linux.c b/dlls/dinput/joystick_linux.c
index efec79962dd..0386bfa77e9 100644
--- a/dlls/dinput/joystick_linux.c
+++ b/dlls/dinput/joystick_linux.c
@@ -421,35 +421,6 @@ static HRESULT joydev_enum_deviceA(DWORD dwDevType, DWORD dwFlags, LPDIDEVICEINS
     return S_FALSE;
 }
 
-static HRESULT joydev_enum_deviceW(DWORD dwDevType, DWORD dwFlags, LPDIDEVICEINSTANCEW lpddi, DWORD version, int id)
-{
-    int fd = -1;
-
-    if (id >= find_joystick_devices()) return E_FAIL;
-
-    if (dwFlags & DIEDFL_FORCEFEEDBACK) {
-        WARN("force feedback not supported\n");
-        return S_FALSE;
-    }
-
-    if ((dwDevType == 0) ||
-	((dwDevType == DIDEVTYPE_JOYSTICK) && (version >= 0x0300 && version < 0x0800)) ||
-	(((dwDevType == DI8DEVCLASS_GAMECTRL) || (dwDevType == DI8DEVTYPE_JOYSTICK)) && (version >= 0x0800))) {
-        /* check whether we have a joystick */
-        if ((fd = open(joystick_devices[id].device, O_RDONLY)) == -1)
-        {
-            WARN("open(%s, O_RDONLY) failed: %s\n", joystick_devices[id].device, strerror(errno));
-            return S_FALSE;
-        }
-        fill_joystick_dideviceinstanceW( lpddi, version, id );
-        close(fd);
-        TRACE("Enumerating the linux Joystick device: %s (%s)\n", joystick_devices[id].device, joystick_devices[id].name);
-        return S_OK;
-    }
-
-    return S_FALSE;
-}
-
 static HRESULT alloc_device(REFGUID rguid, IDirectInputImpl *dinput,
                             JoystickImpl **pdev, unsigned short index)
 {
@@ -613,7 +584,7 @@ static HRESULT joydev_create_device(IDirectInputImpl *dinput, REFGUID guid, IDir
 const struct dinput_device joystick_linux_device = {
   "Wine Linux joystick driver",
   joydev_enum_deviceA,
-  joydev_enum_deviceW,
+  NULL,
   joydev_create_device
 };
 
diff --git a/dlls/dinput/joystick_linuxinput.c b/dlls/dinput/joystick_linuxinput.c
index 1c095b27c6c..c34a73ec4e0 100644
--- a/dlls/dinput/joystick_linuxinput.c
+++ b/dlls/dinput/joystick_linuxinput.c
@@ -419,31 +419,6 @@ static HRESULT joydev_enum_deviceA(DWORD dwDevType, DWORD dwFlags, LPDIDEVICEINS
   return S_FALSE;
 }
 
-static HRESULT joydev_enum_deviceW(DWORD dwDevType, DWORD dwFlags, LPDIDEVICEINSTANCEW lpddi, DWORD version, int id)
-{
-  find_joydevs();
-
-  if (id >= have_joydevs) {
-    return E_FAIL;
-  }
-
-  if (!((dwDevType == 0) ||
-        ((dwDevType == DIDEVTYPE_JOYSTICK) && (version >= 0x0300 && version < 0x0800)) ||
-        (((dwDevType == DI8DEVCLASS_GAMECTRL) || (dwDevType == DI8DEVTYPE_JOYSTICK)) && (version >= 0x0800))))
-    return S_FALSE;
-
-#ifndef HAVE_STRUCT_FF_EFFECT_DIRECTION
-  if (dwFlags & DIEDFL_FORCEFEEDBACK)
-    return S_FALSE;
-#endif
-
-  if (!(dwFlags & DIEDFL_FORCEFEEDBACK) || joydevs[id].has_ff) {
-    fill_joystick_dideviceinstanceW(lpddi, version, id);
-    return S_OK;
-  }
-  return S_FALSE;
-}
-
 static JoystickImpl *alloc_device(REFGUID rguid, IDirectInputImpl *dinput, unsigned short index)
 {
     JoystickImpl* newDevice;
@@ -631,7 +606,7 @@ static HRESULT joydev_create_device(IDirectInputImpl *dinput, REFGUID guid, IDir
 const struct dinput_device joystick_linuxinput_device = {
   "Wine Linux-input joystick driver",
   joydev_enum_deviceA,
-  joydev_enum_deviceW,
+  NULL,
   joydev_create_device
 };
 
diff --git a/dlls/dinput/joystick_osx.c b/dlls/dinput/joystick_osx.c
index 347e76a7bc4..def374d047d 100644
--- a/dlls/dinput/joystick_osx.c
+++ b/dlls/dinput/joystick_osx.c
@@ -995,56 +995,6 @@ static HRESULT joydev_enum_deviceA(DWORD dwDevType, DWORD dwFlags, LPDIDEVICEINS
     return S_FALSE;
 }
 
-static HRESULT joydev_enum_deviceW(DWORD dwDevType, DWORD dwFlags, LPDIDEVICEINSTANCEW lpddi, DWORD version, int id)
-{
-    char name[MAX_PATH];
-    char friendly[32];
-    IOHIDDeviceRef device;
-    BOOL is_joystick;
-
-    TRACE("dwDevType %u dwFlags 0x%08x version 0x%04x id %d\n", dwDevType, dwFlags, version, id);
-
-    if (id >= find_joystick_devices()) return E_FAIL;
-
-    device = get_device_ref(id);
-
-    if ((dwDevType == 0) ||
-    ((dwDevType == DIDEVTYPE_JOYSTICK) && (version >= 0x0300 && version < 0x0800)) ||
-    (((dwDevType == DI8DEVCLASS_GAMECTRL) || (dwDevType == DI8DEVTYPE_JOYSTICK)) && (version >= 0x0800))) {
-
-        if (dwFlags & DIEDFL_FORCEFEEDBACK) {
-            if(!device)
-                return S_FALSE;
-            if(get_ff(device, NULL) != S_OK)
-                return S_FALSE;
-        }
-        is_joystick = get_device_property_long(device, CFSTR(kIOHIDDeviceUsageKey)) == kHIDUsage_GD_Joystick;
-        /* Return joystick */
-        lpddi->guidInstance = DInput_Wine_OsX_Joystick_GUID;
-        lpddi->guidInstance.Data3 = id;
-        lpddi->guidProduct = DInput_PIDVID_Product_GUID;
-        lpddi->guidProduct.Data1 = make_vid_pid(device);
-        lpddi->dwDevType = get_device_type(version, is_joystick);
-        lpddi->dwDevType |= DIDEVTYPE_HID;
-        lpddi->wUsagePage = 0x01; /* Desktop */
-        if (is_joystick)
-            lpddi->wUsage = 0x04; /* Joystick */
-        else
-            lpddi->wUsage = 0x05; /* Game Pad */
-        sprintf(friendly, "Joystick %d", id);
-        MultiByteToWideChar(CP_ACP, 0, friendly, -1, lpddi->tszInstanceName, MAX_PATH);
-
-        /* get the device name */
-        get_osx_device_name(id, name, MAX_PATH);
-
-        MultiByteToWideChar(CP_ACP, 0, name, -1, lpddi->tszProductName, MAX_PATH);
-        lpddi->guidFFDriver = GUID_NULL;
-        return S_OK;
-    }
-
-    return S_FALSE;
-}
-
 static const char *osx_ff_axis_name(UInt8 axis)
 {
     static char ret[6];
@@ -1469,7 +1419,7 @@ static HRESULT WINAPI JoystickWImpl_SendForceFeedbackCommand(IDirectInputDevice8
 const struct dinput_device joystick_osx_device = {
   "Wine OS X joystick driver",
   joydev_enum_deviceA,
-  joydev_enum_deviceW,
+  NULL,
   joydev_create_device
 };
 
diff --git a/dlls/dinput/keyboard.c b/dlls/dinput/keyboard.c
index ae4a675aec7..57e057cfbe7 100644
--- a/dlls/dinput/keyboard.c
+++ b/dlls/dinput/keyboard.c
@@ -149,30 +149,6 @@ static DWORD get_keyboard_subtype(void)
     return dev_subtype;
 }
 
-static void fill_keyboard_dideviceinstanceA(LPDIDEVICEINSTANCEA lpddi, DWORD version, DWORD subtype) {
-    DWORD dwSize;
-    DIDEVICEINSTANCEA ddi;
-    
-    dwSize = lpddi->dwSize;
-
-    TRACE("%d %p\n", dwSize, lpddi);
-    
-    memset(lpddi, 0, dwSize);
-    memset(&ddi, 0, sizeof(ddi));
-
-    ddi.dwSize = dwSize;
-    ddi.guidInstance = GUID_SysKeyboard;/* DInput's GUID */
-    ddi.guidProduct = GUID_SysKeyboard;
-    if (version >= 0x0800)
-        ddi.dwDevType = DI8DEVTYPE_KEYBOARD | (subtype << 8);
-    else
-        ddi.dwDevType = DIDEVTYPE_KEYBOARD | (subtype << 8);
-    strcpy(ddi.tszInstanceName, "Keyboard");
-    strcpy(ddi.tszProductName, "Wine Keyboard");
-
-    memcpy(lpddi, &ddi, (dwSize < sizeof(ddi) ? dwSize : sizeof(ddi)));
-}
-
 static void fill_keyboard_dideviceinstanceW(LPDIDEVICEINSTANCEW lpddi, DWORD version, DWORD subtype) {
     DWORD dwSize;
     DIDEVICEINSTANCEW ddi;
@@ -197,27 +173,6 @@ static void fill_keyboard_dideviceinstanceW(LPDIDEVICEINSTANCEW lpddi, DWORD ver
     memcpy(lpddi, &ddi, (dwSize < sizeof(ddi) ? dwSize : sizeof(ddi)));
 }
  
-static HRESULT keyboarddev_enum_deviceA(DWORD dwDevType, DWORD dwFlags, LPDIDEVICEINSTANCEA lpddi, DWORD version, int id)
-{
-  if (id != 0)
-    return E_FAIL;
-
-  if (dwFlags & DIEDFL_FORCEFEEDBACK)
-    return S_FALSE;
-
-  if ((dwDevType == 0) ||
-      ((dwDevType == DIDEVTYPE_KEYBOARD) && (version < 0x0800)) ||
-      (((dwDevType == DI8DEVCLASS_KEYBOARD) || (dwDevType == DI8DEVTYPE_KEYBOARD)) && (version >= 0x0800))) {
-    TRACE("Enumerating the Keyboard device\n");
- 
-    fill_keyboard_dideviceinstanceA(lpddi, version, get_keyboard_subtype());
-    
-    return S_OK;
-  }
-
-  return S_FALSE;
-}
-
 static HRESULT keyboarddev_enum_deviceW(DWORD dwDevType, DWORD dwFlags, LPDIDEVICEINSTANCEW lpddi, DWORD version, int id)
 {
   if (id != 0)
@@ -299,7 +254,7 @@ static HRESULT keyboarddev_create_device(IDirectInputImpl *dinput, REFGUID guid,
 
 const struct dinput_device keyboard_device = {
   "Wine keyboard driver",
-  keyboarddev_enum_deviceA,
+  NULL,
   keyboarddev_enum_deviceW,
   keyboarddev_create_device
 };
diff --git a/dlls/dinput/mouse.c b/dlls/dinput/mouse.c
index 06255bdafe5..608f8392925 100644
--- a/dlls/dinput/mouse.c
+++ b/dlls/dinput/mouse.c
@@ -93,30 +93,6 @@ static void _dump_mouse_state(const DIMOUSESTATE2 *m_state)
     TRACE(")\n");
 }
 
-static void fill_mouse_dideviceinstanceA(LPDIDEVICEINSTANCEA lpddi, DWORD version) {
-    DWORD dwSize;
-    DIDEVICEINSTANCEA ddi;
-    
-    dwSize = lpddi->dwSize;
-
-    TRACE("%d %p\n", dwSize, lpddi);
-    
-    memset(lpddi, 0, dwSize);
-    memset(&ddi, 0, sizeof(ddi));
-
-    ddi.dwSize = dwSize;
-    ddi.guidInstance = GUID_SysMouse;/* DInput's GUID */
-    ddi.guidProduct = GUID_SysMouse;
-    if (version >= 0x0800)
-        ddi.dwDevType = DI8DEVTYPE_MOUSE | (DI8DEVTYPEMOUSE_TRADITIONAL << 8);
-    else
-        ddi.dwDevType = DIDEVTYPE_MOUSE | (DIDEVTYPEMOUSE_TRADITIONAL << 8);
-    strcpy(ddi.tszInstanceName, "Mouse");
-    strcpy(ddi.tszProductName, "Wine Mouse");
-
-    memcpy(lpddi, &ddi, (dwSize < sizeof(ddi) ? dwSize : sizeof(ddi)));
-}
-
 static void fill_mouse_dideviceinstanceW(LPDIDEVICEINSTANCEW lpddi, DWORD version) {
     DWORD dwSize;
     DIDEVICEINSTANCEW ddi;
@@ -141,27 +117,6 @@ static void fill_mouse_dideviceinstanceW(LPDIDEVICEINSTANCEW lpddi, DWORD versio
     memcpy(lpddi, &ddi, (dwSize < sizeof(ddi) ? dwSize : sizeof(ddi)));
 }
 
-static HRESULT mousedev_enum_deviceA(DWORD dwDevType, DWORD dwFlags, LPDIDEVICEINSTANCEA lpddi, DWORD version, int id)
-{
-    if (id != 0)
-        return E_FAIL;
-
-    if (dwFlags & DIEDFL_FORCEFEEDBACK)
-        return S_FALSE;
-
-    if ((dwDevType == 0) ||
-	((dwDevType == DIDEVTYPE_MOUSE) && (version < 0x0800)) ||
-	(((dwDevType == DI8DEVCLASS_POINTER) || (dwDevType == DI8DEVTYPE_MOUSE)) && (version >= 0x0800))) {
-	TRACE("Enumerating the mouse device\n");
-	
-	fill_mouse_dideviceinstanceA(lpddi, version);
-	
-	return S_OK;
-    }
-    
-    return S_FALSE;
-}
-
 static HRESULT mousedev_enum_deviceW(DWORD dwDevType, DWORD dwFlags, LPDIDEVICEINSTANCEW lpddi, DWORD version, int id)
 {
     if (id != 0)
@@ -257,7 +212,7 @@ static HRESULT mousedev_create_device(IDirectInputImpl *dinput, REFGUID guid, ID
 
 const struct dinput_device mouse_device = {
     "Wine mouse driver",
-    mousedev_enum_deviceA,
+    NULL,
     mousedev_enum_deviceW,
     mousedev_create_device
 };
-- 
2.28.0

>From 0e65d2db721ab9087624e9baac8a1e3f9b579864 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?R=C3=A9mi=20Bernon?= <rbernon@codeweavers.com>
Date: Tue, 6 Oct 2020 14:01:53 +0200
Subject: [PATCH 10/39] dinput: Check for registry disabled devices when
 enumerating.

---
 dlls/dinput/dinput_main.c         |  6 ++++++
 dlls/dinput/joystick.c            | 30 +++++++++++++++++++++---------
 dlls/dinput/joystick_linux.c      |  5 -----
 dlls/dinput/joystick_linuxinput.c |  8 --------
 dlls/dinput/joystick_private.h    |  2 +-
 5 files changed, 28 insertions(+), 23 deletions(-)

diff --git a/dlls/dinput/dinput_main.c b/dlls/dinput/dinput_main.c
index 42832b8d715..43986029a50 100644
--- a/dlls/dinput/dinput_main.c
+++ b/dlls/dinput/dinput_main.c
@@ -51,6 +51,7 @@
 #include "devguid.h"
 #include "dinput_private.h"
 #include "device_private.h"
+#include "joystick_private.h"
 #include "dinputd.h"
 
 WINE_DEFAULT_DEBUG_CHANNEL(dinput);
@@ -387,8 +388,11 @@ static HRESULT WINAPI IDirectInputWImpl_EnumDevices(
             TRACE("  - checking device %u ('%s')\n", i, dinput_devices[i]->name);
             r = dinput_enum_device(dinput_devices[i], dwDevType, dwFlags, &devInstance, This->dwVersion, j);
             if (r == S_OK)
+            {
+                if (device_disabled_registry(devInstance.tszProductName)) continue;
                 if (enum_callback_wrapper(lpCallback, &devInstance, pvRef) == DIENUM_STOP)
                     return S_OK;
+            }
         }
     }
 
@@ -825,6 +829,7 @@ static HRESULT WINAPI IDirectInput8WImpl_EnumDevicesBySemantics(
             if (enumSuccess == S_OK &&
                 should_enumerate_device(ptszUserName, dwFlags, &This->device_players, &didevi.guidInstance))
             {
+                if (device_disabled_registry(didevi.tszProductName)) continue;
                 if (device_count++)
                     didevis = HeapReAlloc(GetProcessHeap(), 0, didevis, sizeof(DIDEVICEINSTANCEW)*device_count);
                 else
@@ -993,6 +998,7 @@ static HRESULT WINAPI JoyConfig8Impl_GetConfig(IDirectInputJoyConfig8 *iface, UI
             dev.dwSize = sizeof(dev);
             if ((r = dinput_enum_device(dinput_devices[i], DI8DEVCLASS_GAMECTRL, 0, &dev, di->dwVersion, j)) == S_OK)
             {
+                if (device_disabled_registry(dev.tszProductName)) continue;
                 /* Only take into account the chosen id */
                 if (found == id)
                 {
diff --git a/dlls/dinput/joystick.c b/dlls/dinput/joystick.c
index fcc968f0d71..94983ed837c 100644
--- a/dlls/dinput/joystick.c
+++ b/dlls/dinput/joystick.c
@@ -271,11 +271,23 @@ void dump_DIEFFECT(LPCDIEFFECT eff, REFGUID guid, DWORD dwFlags)
     }
 }
 
-BOOL device_disabled_registry(const char* name)
+static DWORD get_config_key_w( HKEY defkey, HKEY appkey, const WCHAR *name,
+                             WCHAR *buffer, DWORD size )
 {
-    static const char disabled_str[] = "disabled";
-    static const char joystick_key[] = "Joysticks";
-    char buffer[MAX_PATH];
+    if (appkey && !RegQueryValueExW( appkey, name, 0, NULL, (LPBYTE)buffer, &size ))
+        return 0;
+
+    if (defkey && !RegQueryValueExW( defkey, name, 0, NULL, (LPBYTE)buffer, &size ))
+        return 0;
+
+    return ERROR_FILE_NOT_FOUND;
+}
+
+BOOL device_disabled_registry(const WCHAR* name)
+{
+    static const WCHAR disabled_str[] = {'d','i','s','a','b','l','e','d',0};
+    static const WCHAR joystick_key[] = {'J','o','y','s','t','i','c','k','s',0};
+    WCHAR buffer[MAX_PATH];
     HKEY hkey, appkey, temp;
     BOOL do_disable = FALSE;
 
@@ -284,22 +296,22 @@ BOOL device_disabled_registry(const char* name)
     /* Joystick settings are in the 'joysticks' subkey */
     if (appkey)
     {
-        if (RegOpenKeyA(appkey, joystick_key, &temp)) temp = 0;
+        if (RegOpenKeyW(appkey, joystick_key, &temp)) temp = 0;
         RegCloseKey(appkey);
         appkey = temp;
     }
     if (hkey)
     {
-        if (RegOpenKeyA(hkey, joystick_key, &temp)) temp = 0;
+        if (RegOpenKeyW(hkey, joystick_key, &temp)) temp = 0;
         RegCloseKey(hkey);
         hkey = temp;
     }
 
     /* Look for the "controllername"="disabled" key */
-    if (!get_config_key(hkey, appkey, name, buffer, sizeof(buffer)))
-        if (!strcmp(disabled_str, buffer))
+    if (!get_config_key_w(hkey, appkey, name, buffer, sizeof(buffer)))
+        if (!strcmpW(disabled_str, buffer))
         {
-            TRACE("Disabling joystick '%s' based on registry key.\n", name);
+            TRACE("Disabling joystick '%s' based on registry key.\n", debugstr_w(name));
             do_disable = TRUE;
         }
 
diff --git a/dlls/dinput/joystick_linux.c b/dlls/dinput/joystick_linux.c
index 0386bfa77e9..335cb67b673 100644
--- a/dlls/dinput/joystick_linux.c
+++ b/dlls/dinput/joystick_linux.c
@@ -175,11 +175,6 @@ static INT find_joystick_devices(void)
         /* Append driver name */
         strcat(joydev.name, JOYDEVDRIVER);
 
-        if (device_disabled_registry(joydev.name)) {
-            close(fd);
-            continue;
-        }
-
 #ifdef JSIOCGAXES
         if (ioctl(fd, JSIOCGAXES, &joydev.axis_count) < 0)
         {
diff --git a/dlls/dinput/joystick_linuxinput.c b/dlls/dinput/joystick_linuxinput.c
index c34a73ec4e0..95fa5dacc26 100644
--- a/dlls/dinput/joystick_linuxinput.c
+++ b/dlls/dinput/joystick_linuxinput.c
@@ -264,14 +264,6 @@ static void find_joydevs(void)
         else
             joydev.name = joydev.device;
 
-        if (device_disabled_registry(joydev.name)) {
-            close(fd);
-            HeapFree(GetProcessHeap(), 0, joydev.name);
-            if (joydev.name != joydev.device)
-                HeapFree(GetProcessHeap(), 0, joydev.device);
-            continue;
-        }
-
         joydev.guid = DInput_Wine_Joystick_Base_GUID;
         joydev.guid.Data3 += have_joydevs;
 
diff --git a/dlls/dinput/joystick_private.h b/dlls/dinput/joystick_private.h
index 5327fa60566..39a837bd74c 100644
--- a/dlls/dinput/joystick_private.h
+++ b/dlls/dinput/joystick_private.h
@@ -57,7 +57,7 @@ HRESULT setup_dinput_options(JoystickGenericImpl *This, const int *default_axis_
 
 DWORD joystick_map_pov(const POINTL *p) DECLSPEC_HIDDEN;
 
-BOOL device_disabled_registry(const char* name) DECLSPEC_HIDDEN;
+extern BOOL device_disabled_registry(const WCHAR* name) DECLSPEC_HIDDEN;
 
 HRESULT WINAPI JoystickWGenericImpl_GetObjectInfo(LPDIRECTINPUTDEVICE8W iface,
         LPDIDEVICEOBJECTINSTANCEW pdidoi, DWORD dwObj, DWORD dwHow) DECLSPEC_HIDDEN;
-- 
2.28.0

>From e5e165554d036994de3759b97a358b98e4a89d1b Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?R=C3=A9mi=20Bernon?= <rbernon@codeweavers.com>
Date: Mon, 5 Oct 2020 12:44:47 +0200
Subject: [PATCH 11/39] dinput: Provide DIDEVICEINSTANCE on device init.

---
 dlls/dinput/device.c              | 18 ++++++++++++-
 dlls/dinput/device_private.h      |  4 ++-
 dlls/dinput/joystick.c            | 45 -------------------------------
 dlls/dinput/joystick_linux.c      | 35 +++++-------------------
 dlls/dinput/joystick_linuxinput.c | 33 +++++------------------
 dlls/dinput/joystick_osx.c        | 35 ++++++++++++++++++------
 dlls/dinput/joystick_private.h    |  5 ----
 dlls/dinput/keyboard.c            | 25 ++++-------------
 dlls/dinput/mouse.c               | 25 ++++-------------
 9 files changed, 69 insertions(+), 156 deletions(-)

diff --git a/dlls/dinput/device.c b/dlls/dinput/device.c
index 10b8580721a..129e8a2cb47 100644
--- a/dlls/dinput/device.c
+++ b/dlls/dinput/device.c
@@ -1366,6 +1366,21 @@ HRESULT WINAPI IDirectInputDevice2WImpl_SetProperty(
     return DI_OK;
 }
 
+HRESULT WINAPI IDirectInputDevice2WImpl_GetDeviceInfo(LPDIRECTINPUTDEVICE8W iface, LPDIDEVICEINSTANCEW didi)
+{
+    IDirectInputDeviceImpl *This = impl_from_IDirectInputDevice8W(iface);
+
+    TRACE("(%p) %p\n", This, didi);
+
+    if (didi == NULL) return E_POINTER;
+    if ((didi->dwSize != sizeof(DIDEVICEINSTANCE_DX3W)) && (didi->dwSize != sizeof(DIDEVICEINSTANCEW)))
+        return DIERR_INVALIDPARAM;
+
+    memcpy((char *)didi + sizeof(didi->dwSize), (char *)&This->info + sizeof(didi->dwSize), didi->dwSize - sizeof(didi->dwSize));
+
+    return DI_OK;
+}
+
 HRESULT WINAPI IDirectInputDevice2WImpl_GetObjectInfo(
 	LPDIRECTINPUTDEVICE8W iface,
 	LPDIDEVICEOBJECTINSTANCEW pdidoi,
@@ -1628,7 +1643,7 @@ HRESULT WINAPI IDirectInputDevice8WImpl_GetImageInfo(LPDIRECTINPUTDEVICE8W iface
 }
 
 HRESULT direct_input_device_alloc(SIZE_T size, const IDirectInputDevice8WVtbl *vtbl, const GUID *guid,
-        IDirectInputImpl *dinput, void **out)
+        const DIDEVICEINSTANCEW *info, IDirectInputImpl *dinput, void **out)
 {
     IDirectInputDeviceImpl *This;
     if (!(This = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, size))) return DIERR_OUTOFMEMORY;
@@ -1636,6 +1651,7 @@ HRESULT direct_input_device_alloc(SIZE_T size, const IDirectInputDevice8WVtbl *v
     This->IDirectInputDevice8A_iface.lpVtbl = &direct_input_device_a_vtbl;
     This->ref = 1;
     This->guid = *guid;
+    This->info = *info;
     InitializeCriticalSection(&This->crit);
     This->dinput = dinput;
     IDirectInput_AddRef(&dinput->IDirectInput7A_iface);
diff --git a/dlls/dinput/device_private.h b/dlls/dinput/device_private.h
index fcab6dbedd0..95d1ea3e5b3 100644
--- a/dlls/dinput/device_private.h
+++ b/dlls/dinput/device_private.h
@@ -61,6 +61,7 @@ struct IDirectInputDeviceImpl
     IDirectInputDevice8A        IDirectInputDevice8A_iface;
     LONG                        ref;
     GUID                        guid;
+    DIDEVICEINSTANCEW           info;
     CRITICAL_SECTION            crit;
     IDirectInputImpl           *dinput;
     struct list                 entry;       /* entry into acquired device list */
@@ -89,7 +90,7 @@ struct IDirectInputDeviceImpl
 extern const IDirectInputDevice8AVtbl direct_input_device_a_vtbl DECLSPEC_HIDDEN;
 
 extern HRESULT direct_input_device_alloc(SIZE_T size, const IDirectInputDevice8WVtbl *vtbl, const GUID *guid,
-        IDirectInputImpl *dinput, void **out) DECLSPEC_HIDDEN;
+        const DIDEVICEINSTANCEW *info, IDirectInputImpl *dinput, void **out) DECLSPEC_HIDDEN;
 
 extern BOOL get_app_key(HKEY*, HKEY*) DECLSPEC_HIDDEN;
 extern DWORD get_config_key(HKEY, HKEY, const char*, char*, DWORD) DECLSPEC_HIDDEN;
@@ -152,6 +153,7 @@ extern HRESULT WINAPI IDirectInputDevice2WImpl_EnumObjects(
 	DWORD dwFlags)  DECLSPEC_HIDDEN;
 extern HRESULT WINAPI IDirectInputDevice2WImpl_GetProperty(LPDIRECTINPUTDEVICE8W iface, REFGUID rguid, LPDIPROPHEADER pdiph) DECLSPEC_HIDDEN;
 extern HRESULT WINAPI IDirectInputDevice2WImpl_SetProperty(LPDIRECTINPUTDEVICE8W iface, REFGUID rguid, LPCDIPROPHEADER pdiph) DECLSPEC_HIDDEN;
+extern HRESULT WINAPI IDirectInputDevice2WImpl_GetDeviceInfo(LPDIRECTINPUTDEVICE8W iface, LPDIDEVICEINSTANCEW didi) DECLSPEC_HIDDEN;
 extern HRESULT WINAPI IDirectInputDevice2WImpl_GetObjectInfo(LPDIRECTINPUTDEVICE8W iface, 
 							     LPDIDEVICEOBJECTINSTANCEW pdidoi,
 							     DWORD dwObj,
diff --git a/dlls/dinput/joystick.c b/dlls/dinput/joystick.c
index 94983ed837c..72e3e8d4fd6 100644
--- a/dlls/dinput/joystick.c
+++ b/dlls/dinput/joystick.c
@@ -645,51 +645,6 @@ HRESULT WINAPI JoystickWGenericImpl_GetProperty(LPDIRECTINPUTDEVICE8W iface, REF
     return DI_OK;
 }
 
-/******************************************************************************
-  *     GetDeviceInfo : get information about a device's identity
-  */
-HRESULT WINAPI JoystickWGenericImpl_GetDeviceInfo(
-    LPDIRECTINPUTDEVICE8W iface,
-    LPDIDEVICEINSTANCEW pdidi)
-{
-    JoystickGenericImpl *This = impl_from_IDirectInputDevice8W(iface);
-    CHAR buffer[MAX_PATH];
-    DIPROPDWORD pd;
-    DWORD index = 0;
-
-    TRACE("(%p,%p)\n", iface, pdidi);
-
-    if ((pdidi->dwSize != sizeof(DIDEVICEINSTANCE_DX3W)) &&
-        (pdidi->dwSize != sizeof(DIDEVICEINSTANCEW))) {
-        WARN("invalid parameter: pdidi->dwSize = %d\n", pdidi->dwSize);
-        return DIERR_INVALIDPARAM;
-    }
-
-    /* Try to get joystick index */
-    pd.diph.dwSize = sizeof(pd);
-    pd.diph.dwHeaderSize = sizeof(pd.diph);
-    pd.diph.dwObj = 0;
-    pd.diph.dwHow = DIPH_DEVICE;
-    if (SUCCEEDED(IDirectInputDevice2_GetProperty(iface, DIPROP_JOYSTICKID, &pd.diph)))
-        index = pd.dwData;
-
-    /* Return joystick */
-    pdidi->guidInstance = This->guidInstance;
-    pdidi->guidProduct = This->guidProduct;
-    /* we only support traditional joysticks for now */
-    pdidi->dwDevType = This->devcaps.dwDevType;
-    snprintf(buffer, sizeof(buffer), "Joystick %d", index);
-    MultiByteToWideChar(CP_ACP, 0, buffer, -1, pdidi->tszInstanceName, MAX_PATH);
-    MultiByteToWideChar(CP_ACP, 0, This->name, -1, pdidi->tszProductName, MAX_PATH);
-    if (pdidi->dwSize > sizeof(DIDEVICEINSTANCE_DX3W)) {
-        pdidi->guidFFDriver = GUID_NULL;
-        pdidi->wUsagePage = 0;
-        pdidi->wUsage = 0;
-    }
-
-    return DI_OK;
-}
-
 HRESULT WINAPI JoystickWGenericImpl_Poll(LPDIRECTINPUTDEVICE8W iface)
 {
     JoystickGenericImpl *This = impl_from_IDirectInputDevice8W(iface);
diff --git a/dlls/dinput/joystick_linux.c b/dlls/dinput/joystick_linux.c
index 335cb67b673..f043b4d7fed 100644
--- a/dlls/dinput/joystick_linux.c
+++ b/dlls/dinput/joystick_linux.c
@@ -419,25 +419,24 @@ static HRESULT joydev_enum_deviceA(DWORD dwDevType, DWORD dwFlags, LPDIDEVICEINS
 static HRESULT alloc_device(REFGUID rguid, IDirectInputImpl *dinput,
                             JoystickImpl **pdev, unsigned short index)
 {
+    DIDEVICEINSTANCEW didi = {sizeof(didi)};
     DWORD i;
     JoystickImpl* newDevice;
     HRESULT hr;
     LPDIDATAFORMAT df = NULL;
     int idx = 0;
-    DIDEVICEINSTANCEW ddi;
 
     TRACE("%s %p %p %hu\n", debugstr_guid(rguid), dinput, pdev, index);
 
+    fill_joystick_dideviceinstanceW(&didi, dinput->dwVersion, index);
+
     *pdev = NULL;
-    if (FAILED(hr = direct_input_device_alloc(sizeof(JoystickImpl), &JoystickWvt, rguid, dinput, (void **)&newDevice)))
+    if (FAILED(hr = direct_input_device_alloc(sizeof(JoystickImpl), &JoystickWvt, rguid, &didi, dinput, (void **)&newDevice)))
         return hr;
     newDevice->generic.base.crit.DebugInfo->Spare[0] = (DWORD_PTR)(__FILE__ ": JoystickImpl*->generic.base.crit");
 
     newDevice->joydev = &joystick_devices[index];
     newDevice->joyfd = -1;
-    newDevice->generic.guidInstance = DInput_Wine_Joystick_GUID;
-    newDevice->generic.guidInstance.Data3 = index;
-    newDevice->generic.guidProduct = DInput_Wine_Joystick_GUID;
     newDevice->generic.joy_polldev = joy_polldev;
     newDevice->generic.name        = newDevice->joydev->name;
     newDevice->generic.device_axis_count = newDevice->joydev->axis_count;
@@ -499,10 +498,7 @@ static HRESULT alloc_device(REFGUID rguid, IDirectInputImpl *dinput,
 
     newDevice->generic.devcaps.dwSize = sizeof(newDevice->generic.devcaps);
     newDevice->generic.devcaps.dwFlags = DIDC_ATTACHED;
-
-    ddi.dwSize = sizeof(ddi);
-    fill_joystick_dideviceinstanceW(&ddi, newDevice->generic.base.dinput->dwVersion, index);
-    newDevice->generic.devcaps.dwDevType = ddi.dwDevType;
+    newDevice->generic.devcaps.dwDevType = didi.dwDevType;
 
     newDevice->generic.devcaps.dwFFSamplePeriod = 0;
     newDevice->generic.devcaps.dwFFMinTimeResolution = 0;
@@ -675,25 +671,6 @@ static HRESULT WINAPI JoystickLinuxWImpl_GetProperty(LPDIRECTINPUTDEVICE8W iface
     return DI_OK;
 }
 
-/******************************************************************************
-  *     GetDeviceInfo : get information about a device's identity
-  */
-static HRESULT WINAPI JoystickLinuxWImpl_GetDeviceInfo(LPDIRECTINPUTDEVICE8W iface, LPDIDEVICEINSTANCEW ddi)
-{
-    JoystickImpl *This = impl_from_IDirectInputDevice8W(iface);
-
-    TRACE("(%p) %p\n", This, ddi);
-
-    if (ddi == NULL) return E_POINTER;
-    if ((ddi->dwSize != sizeof(DIDEVICEINSTANCE_DX3W)) &&
-        (ddi->dwSize != sizeof(DIDEVICEINSTANCEW)))
-        return DIERR_INVALIDPARAM;
-
-    fill_joystick_dideviceinstanceW( ddi, This->generic.base.dinput->dwVersion,
-                                     get_joystick_index(&This->generic.base.guid) );
-    return DI_OK;
-}
-
 /******************************************************************************
   *     Unacquire : frees the joystick
   */
@@ -811,7 +788,7 @@ static const IDirectInputDevice8WVtbl JoystickWvt =
     IDirectInputDevice2WImpl_SetEventNotification,
     IDirectInputDevice2WImpl_SetCooperativeLevel,
     JoystickWGenericImpl_GetObjectInfo,
-    JoystickLinuxWImpl_GetDeviceInfo,
+    IDirectInputDevice2WImpl_GetDeviceInfo,
     IDirectInputDevice2WImpl_RunControlPanel,
     IDirectInputDevice2WImpl_Initialize,
     IDirectInputDevice2WImpl_CreateEffect,
diff --git a/dlls/dinput/joystick_linuxinput.c b/dlls/dinput/joystick_linuxinput.c
index 95fa5dacc26..4730ea9bc3f 100644
--- a/dlls/dinput/joystick_linuxinput.c
+++ b/dlls/dinput/joystick_linuxinput.c
@@ -413,13 +413,15 @@ static HRESULT joydev_enum_deviceA(DWORD dwDevType, DWORD dwFlags, LPDIDEVICEINS
 
 static JoystickImpl *alloc_device(REFGUID rguid, IDirectInputImpl *dinput, unsigned short index)
 {
+    DIDEVICEINSTANCEW didi = {sizeof(didi)};
     JoystickImpl* newDevice;
     LPDIDATAFORMAT df = NULL;
     int i, idx = 0;
     int default_axis_map[WINE_JOYSTICK_MAX_AXES + WINE_JOYSTICK_MAX_POVS*2];
-    DIDEVICEINSTANCEW ddi;
 
-    if (FAILED(direct_input_device_alloc(sizeof(JoystickImpl), &JoystickWvt, rguid, dinput, (void **)&newDevice)))
+    fill_joystick_dideviceinstanceW(&didi, dinput->dwVersion, index);
+
+    if (FAILED(direct_input_device_alloc(sizeof(JoystickImpl), &JoystickWvt, rguid, &didi, dinput, (void **)&newDevice)))
         return NULL;
     newDevice->generic.base.crit.DebugInfo->Spare[0] = (DWORD_PTR)(__FILE__ ": JoystickImpl*->base.crit");
 
@@ -535,10 +537,7 @@ static JoystickImpl *alloc_device(REFGUID rguid, IDirectInputImpl *dinput, unsig
     /* Fill the caps */
     newDevice->generic.devcaps.dwSize = sizeof(newDevice->generic.devcaps);
     newDevice->generic.devcaps.dwFlags = DIDC_ATTACHED;
-
-    ddi.dwSize = sizeof(ddi);
-    fill_joystick_dideviceinstanceW(&ddi, newDevice->generic.base.dinput->dwVersion, index);
-    newDevice->generic.devcaps.dwDevType = ddi.dwDevType;
+    newDevice->generic.devcaps.dwDevType = didi.dwDevType;
 
     if (newDevice->joydev->has_ff)
         newDevice->generic.devcaps.dwFlags |= DIDC_FORCEFEEDBACK;
@@ -1210,26 +1209,6 @@ static HRESULT WINAPI JoystickWImpl_EnumCreatedEffectObjects(LPDIRECTINPUTDEVICE
     return DI_OK;
 }
 
-/******************************************************************************
-  *     GetDeviceInfo : get information about a device's identity
-  */
-static HRESULT WINAPI JoystickWImpl_GetDeviceInfo(LPDIRECTINPUTDEVICE8W iface,
-                                                  LPDIDEVICEINSTANCEW pdidi)
-{
-    JoystickImpl *This = impl_from_IDirectInputDevice8W(iface);
-
-    TRACE("(%p) %p\n", This, pdidi);
-
-    if (pdidi == NULL) return E_POINTER;
-    if ((pdidi->dwSize != sizeof(DIDEVICEINSTANCE_DX3W)) &&
-        (pdidi->dwSize != sizeof(DIDEVICEINSTANCEW)))
-        return DIERR_INVALIDPARAM;
-
-    fill_joystick_dideviceinstanceW(pdidi, This->generic.base.dinput->dwVersion,
-                                    get_joystick_index(&This->generic.base.guid));
-    return DI_OK;
-}
-
 static const IDirectInputDevice8WVtbl JoystickWvt =
 {
     IDirectInputDevice2WImpl_QueryInterface,
@@ -1247,7 +1226,7 @@ static const IDirectInputDevice8WVtbl JoystickWvt =
     IDirectInputDevice2WImpl_SetEventNotification,
     IDirectInputDevice2WImpl_SetCooperativeLevel,
     JoystickWGenericImpl_GetObjectInfo,
-    JoystickWImpl_GetDeviceInfo,
+    IDirectInputDevice2WImpl_GetDeviceInfo,
     IDirectInputDevice2WImpl_RunControlPanel,
     IDirectInputDevice2WImpl_Initialize,
     JoystickWImpl_CreateEffect,
diff --git a/dlls/dinput/joystick_osx.c b/dlls/dinput/joystick_osx.c
index def374d047d..d13346f50e2 100644
--- a/dlls/dinput/joystick_osx.c
+++ b/dlls/dinput/joystick_osx.c
@@ -1019,9 +1019,30 @@ static BOOL osx_axis_has_ff(FFCAPABILITIES *ffcaps, UInt8 axis)
     return FALSE;
 }
 
+static void fill_joystick_dideviceinstanceW(LPDIDEVICEINSTANCEW didi, IOHIDDeviceRef device, DWORD version, int index, const char *name)
+{
+    char buffer[MAX_PATH];
+
+    didi->guidInstance = DInput_Wine_OsX_Joystick_GUID;
+    didi->guidInstance.Data3 = index;
+    didi->guidProduct = DInput_PIDVID_Product_GUID;
+    didi->guidProduct.Data1 = make_vid_pid(device);
+    if (version >= 0x0800) didi->dwDevType = DI8DEVTYPE_JOYSTICK | (DI8DEVTYPEJOYSTICK_STANDARD << 8);
+    else didi->dwDevType = DIDEVTYPE_JOYSTICK | (DIDEVTYPEJOYSTICK_TRADITIONAL << 8);
+
+    snprintf(buffer, sizeof(buffer), "Joystick %d", index);
+    MultiByteToWideChar(CP_ACP, 0, buffer, -1, didi->tszInstanceName, MAX_PATH);
+    MultiByteToWideChar(CP_ACP, 0, name, -1, didi->tszProductName, MAX_PATH);
+
+    didi->guidFFDriver = GUID_NULL;
+    didi->wUsagePage = 0;
+    didi->wUsage = 0;
+}
+
 static HRESULT alloc_device(REFGUID rguid, IDirectInputImpl *dinput,
                             JoystickImpl **pdev, unsigned short index)
 {
+    DIDEVICEINSTANCEW didi = {sizeof(didi)};
     DWORD i;
     IOHIDDeviceRef device;
     JoystickImpl* newDevice;
@@ -1035,18 +1056,16 @@ static HRESULT alloc_device(REFGUID rguid, IDirectInputImpl *dinput,
 
     TRACE("%s %p %p %hu\n", debugstr_guid(rguid), dinput, pdev, index);
 
-    if (FAILED(hr = direct_input_device_alloc(sizeof(JoystickImpl), &JoystickWvt, rguid, dinput, (void **)&newDevice)))
+    device = get_device_ref(index);
+
+    fill_joystick_dideviceinstanceW(&didi, device, dinput->dwVersion, index, name);
+
+    if (FAILED(hr = direct_input_device_alloc(sizeof(JoystickImpl), &JoystickWvt, rguid, &didi, dinput, (void **)&newDevice)))
         return hr;
     newDevice->generic.base.crit.DebugInfo->Spare[0] = (DWORD_PTR)(__FILE__ ": JoystickImpl*->generic.base.crit");
 
     newDevice->id = index;
 
-    device = get_device_ref(index);
-
-    newDevice->generic.guidInstance = DInput_Wine_OsX_Joystick_GUID;
-    newDevice->generic.guidInstance.Data3 = index;
-    newDevice->generic.guidProduct = DInput_PIDVID_Product_GUID;
-    newDevice->generic.guidProduct.Data1 = make_vid_pid(device);
     newDevice->generic.joy_polldev = poll_osx_device_state;
 
     /* get the device name */
@@ -1440,7 +1459,7 @@ static const IDirectInputDevice8WVtbl JoystickWvt =
     IDirectInputDevice2WImpl_SetEventNotification,
     IDirectInputDevice2WImpl_SetCooperativeLevel,
     JoystickWGenericImpl_GetObjectInfo,
-    JoystickWGenericImpl_GetDeviceInfo,
+    IDirectInputDevice2WImpl_GetDeviceInfo,
     IDirectInputDevice2WImpl_RunControlPanel,
     IDirectInputDevice2WImpl_Initialize,
     JoystickWImpl_CreateEffect,
diff --git a/dlls/dinput/joystick_private.h b/dlls/dinput/joystick_private.h
index 39a837bd74c..b82632c39d2 100644
--- a/dlls/dinput/joystick_private.h
+++ b/dlls/dinput/joystick_private.h
@@ -42,8 +42,6 @@ typedef struct JoystickGenericImpl
     ObjProps    props[MAX_PROPS];
     DIDEVCAPS   devcaps;
     DIJOYSTATE2 js;     /* wine data */
-    GUID        guidProduct;
-    GUID        guidInstance;
     char        *name;
     int         device_axis_count;      /* Total number of axes in the device */
     int        *axis_map;               /* User axes remapping */
@@ -70,9 +68,6 @@ void _dump_DIDEVCAPS(const DIDEVCAPS *lpDIDevCaps) DECLSPEC_HIDDEN;
 
 HRESULT WINAPI JoystickWGenericImpl_SetProperty(LPDIRECTINPUTDEVICE8W iface, REFGUID rguid, LPCDIPROPHEADER ph) DECLSPEC_HIDDEN;
 
-HRESULT WINAPI JoystickWGenericImpl_GetDeviceInfo( LPDIRECTINPUTDEVICE8W iface,
-    LPDIDEVICEINSTANCEW pdidi) DECLSPEC_HIDDEN;
-
 HRESULT WINAPI JoystickWGenericImpl_Poll(LPDIRECTINPUTDEVICE8W iface) DECLSPEC_HIDDEN;
 
 HRESULT WINAPI JoystickWGenericImpl_GetDeviceState(LPDIRECTINPUTDEVICE8W iface, DWORD len, LPVOID ptr) DECLSPEC_HIDDEN;
diff --git a/dlls/dinput/keyboard.c b/dlls/dinput/keyboard.c
index 57e057cfbe7..11d41a2ce4c 100644
--- a/dlls/dinput/keyboard.c
+++ b/dlls/dinput/keyboard.c
@@ -196,11 +196,14 @@ static HRESULT keyboarddev_enum_deviceW(DWORD dwDevType, DWORD dwFlags, LPDIDEVI
 
 static SysKeyboardImpl *alloc_device(REFGUID rguid, IDirectInputImpl *dinput)
 {
+    DIDEVICEINSTANCEW didi = {sizeof(didi)};
     SysKeyboardImpl* newDevice;
     LPDIDATAFORMAT df = NULL;
     int i, idx = 0;
 
-    if (FAILED(direct_input_device_alloc(sizeof(SysKeyboardImpl), &SysKeyboardWvt, rguid, dinput, (void **)&newDevice)))
+    fill_keyboard_dideviceinstanceW(&didi, dinput->dwVersion, get_keyboard_subtype());
+
+    if (FAILED(direct_input_device_alloc(sizeof(SysKeyboardImpl), &SysKeyboardWvt, rguid, &didi, dinput, (void **)&newDevice)))
         return NULL;
     newDevice->base.crit.DebugInfo->Spare[0] = (DWORD_PTR)(__FILE__ ": SysKeyboardImpl*->base.crit");
 
@@ -381,24 +384,6 @@ static HRESULT WINAPI SysKeyboardWImpl_GetObjectInfo(LPDIRECTINPUTDEVICE8W iface
     return res;
 }
 
-/******************************************************************************
-  *     GetDeviceInfo : get information about a device's identity
-  */
-static HRESULT WINAPI SysKeyboardWImpl_GetDeviceInfo(LPDIRECTINPUTDEVICE8W iface, LPDIDEVICEINSTANCEW pdidi)
-{
-    SysKeyboardImpl *This = impl_from_IDirectInputDevice8W(iface);
-    TRACE("(this=%p,%p)\n", This, pdidi);
-
-    if (pdidi->dwSize != sizeof(DIDEVICEINSTANCEW)) {
-        WARN(" dinput3 not supported yet...\n");
-	return DI_OK;
-    }
-
-    fill_keyboard_dideviceinstanceW(pdidi, This->base.dinput->dwVersion, This->subtype);
-    
-    return DI_OK;
-}
-
 /******************************************************************************
  *      GetProperty : Retrieves information about the input device.
  */
@@ -495,7 +480,7 @@ static const IDirectInputDevice8WVtbl SysKeyboardWvt =
     IDirectInputDevice2WImpl_SetEventNotification,
     IDirectInputDevice2WImpl_SetCooperativeLevel,
     SysKeyboardWImpl_GetObjectInfo,
-    SysKeyboardWImpl_GetDeviceInfo,
+    IDirectInputDevice2WImpl_GetDeviceInfo,
     IDirectInputDevice2WImpl_RunControlPanel,
     IDirectInputDevice2WImpl_Initialize,
     IDirectInputDevice2WImpl_CreateEffect,
diff --git a/dlls/dinput/mouse.c b/dlls/dinput/mouse.c
index 608f8392925..0e3a8976033 100644
--- a/dlls/dinput/mouse.c
+++ b/dlls/dinput/mouse.c
@@ -140,13 +140,16 @@ static HRESULT mousedev_enum_deviceW(DWORD dwDevType, DWORD dwFlags, LPDIDEVICEI
 
 static SysMouseImpl *alloc_device(REFGUID rguid, IDirectInputImpl *dinput)
 {
+    DIDEVICEINSTANCEW didi = {sizeof(didi)};
     SysMouseImpl* newDevice;
     LPDIDATAFORMAT df = NULL;
     unsigned i;
     char buffer[20];
     HKEY hkey, appkey;
 
-    if (FAILED(direct_input_device_alloc(sizeof(SysMouseImpl), &SysMouseWvt, rguid, dinput, (void **)&newDevice)))
+    fill_mouse_dideviceinstanceW(&didi, dinput->dwVersion);
+
+    if (FAILED(direct_input_device_alloc(sizeof(SysMouseImpl), &SysMouseWvt, rguid, &didi, dinput, (void **)&newDevice)))
         return NULL;
     newDevice->base.crit.DebugInfo->Spare[0] = (DWORD_PTR)(__FILE__ ": SysMouseImpl*->base.crit");
 
@@ -692,24 +695,6 @@ static HRESULT WINAPI SysMouseWImpl_GetObjectInfo(LPDIRECTINPUTDEVICE8W iface,
     return res;
 }
 
-/******************************************************************************
-  *     GetDeviceInfo : get information about a device's identity
-  */
-static HRESULT WINAPI SysMouseWImpl_GetDeviceInfo(LPDIRECTINPUTDEVICE8W iface, LPDIDEVICEINSTANCEW pdidi)
-{
-    SysMouseImpl *This = impl_from_IDirectInputDevice8W(iface);
-    TRACE("(this=%p,%p)\n", This, pdidi);
-
-    if (pdidi->dwSize != sizeof(DIDEVICEINSTANCEW)) {
-        WARN(" dinput3 not supported yet...\n");
-	return DI_OK;
-    }
-
-    fill_mouse_dideviceinstanceW(pdidi, This->base.dinput->dwVersion);
-    
-    return DI_OK;
-}
-
 static HRESULT WINAPI SysMouseWImpl_BuildActionMap(LPDIRECTINPUTDEVICE8W iface,
                                                    LPDIACTIONFORMATW lpdiaf,
                                                    LPCWSTR lpszUserName,
@@ -748,7 +733,7 @@ static const IDirectInputDevice8WVtbl SysMouseWvt =
     IDirectInputDevice2WImpl_SetEventNotification,
     IDirectInputDevice2WImpl_SetCooperativeLevel,
     SysMouseWImpl_GetObjectInfo,
-    SysMouseWImpl_GetDeviceInfo,
+    IDirectInputDevice2WImpl_GetDeviceInfo,
     IDirectInputDevice2WImpl_RunControlPanel,
     IDirectInputDevice2WImpl_Initialize,
     IDirectInputDevice2WImpl_CreateEffect,
-- 
2.28.0

>From a42f6d7ad35f1e4b05c395c0af4bcf1e2356ebe1 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?R=C3=A9mi=20Bernon?= <rbernon@codeweavers.com>
Date: Mon, 5 Oct 2020 12:44:47 +0200
Subject: [PATCH 12/39] dinput: Provide VID/PID and index on device init.

---
 dlls/dinput/device.c              |  7 +++++--
 dlls/dinput/device_private.h      |  7 +++++--
 dlls/dinput/joystick_linux.c      | 26 +++++++++++---------------
 dlls/dinput/joystick_linuxinput.c | 25 +++++++++++--------------
 dlls/dinput/joystick_osx.c        | 18 +++++++++---------
 dlls/dinput/keyboard.c            |  2 +-
 dlls/dinput/mouse.c               |  2 +-
 7 files changed, 43 insertions(+), 44 deletions(-)

diff --git a/dlls/dinput/device.c b/dlls/dinput/device.c
index 129e8a2cb47..a2c1b638cfc 100644
--- a/dlls/dinput/device.c
+++ b/dlls/dinput/device.c
@@ -1642,8 +1642,8 @@ HRESULT WINAPI IDirectInputDevice8WImpl_GetImageInfo(LPDIRECTINPUTDEVICE8W iface
     return DI_OK;
 }
 
-HRESULT direct_input_device_alloc(SIZE_T size, const IDirectInputDevice8WVtbl *vtbl, const GUID *guid,
-        const DIDEVICEINSTANCEW *info, IDirectInputImpl *dinput, void **out)
+HRESULT direct_input_device_alloc(SIZE_T size, const IDirectInputDevice8WVtbl *vtbl, const GUID *guid, WORD vid,
+        WORD pid, WORD iid, const DIDEVICEINSTANCEW *info, IDirectInputImpl *dinput, void **out)
 {
     IDirectInputDeviceImpl *This;
     if (!(This = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, size))) return DIERR_OUTOFMEMORY;
@@ -1651,6 +1651,9 @@ HRESULT direct_input_device_alloc(SIZE_T size, const IDirectInputDevice8WVtbl *v
     This->IDirectInputDevice8A_iface.lpVtbl = &direct_input_device_a_vtbl;
     This->ref = 1;
     This->guid = *guid;
+    This->vendor_id = vid;
+    This->product_id = pid;
+    This->instance_id = iid;
     This->info = *info;
     InitializeCriticalSection(&This->crit);
     This->dinput = dinput;
diff --git a/dlls/dinput/device_private.h b/dlls/dinput/device_private.h
index 95d1ea3e5b3..52a7b3c3dc7 100644
--- a/dlls/dinput/device_private.h
+++ b/dlls/dinput/device_private.h
@@ -61,6 +61,9 @@ struct IDirectInputDeviceImpl
     IDirectInputDevice8A        IDirectInputDevice8A_iface;
     LONG                        ref;
     GUID                        guid;
+    WORD                        vendor_id;
+    WORD                        product_id;
+    WORD                        instance_id;
     DIDEVICEINSTANCEW           info;
     CRITICAL_SECTION            crit;
     IDirectInputImpl           *dinput;
@@ -89,8 +92,8 @@ struct IDirectInputDeviceImpl
 
 extern const IDirectInputDevice8AVtbl direct_input_device_a_vtbl DECLSPEC_HIDDEN;
 
-extern HRESULT direct_input_device_alloc(SIZE_T size, const IDirectInputDevice8WVtbl *vtbl, const GUID *guid,
-        const DIDEVICEINSTANCEW *info, IDirectInputImpl *dinput, void **out) DECLSPEC_HIDDEN;
+extern HRESULT direct_input_device_alloc(SIZE_T size, const IDirectInputDevice8WVtbl *vtbl, const GUID *guid, WORD vid,
+        WORD pid, WORD iid, const DIDEVICEINSTANCEW *info, IDirectInputImpl *dinput, void **out) DECLSPEC_HIDDEN;
 
 extern BOOL get_app_key(HKEY*, HKEY*) DECLSPEC_HIDDEN;
 extern DWORD get_config_key(HKEY, HKEY, const char*, char*, DWORD) DECLSPEC_HIDDEN;
diff --git a/dlls/dinput/joystick_linux.c b/dlls/dinput/joystick_linux.c
index f043b4d7fed..75d677c58a6 100644
--- a/dlls/dinput/joystick_linux.c
+++ b/dlls/dinput/joystick_linux.c
@@ -419,6 +419,7 @@ static HRESULT joydev_enum_deviceA(DWORD dwDevType, DWORD dwFlags, LPDIDEVICEINS
 static HRESULT alloc_device(REFGUID rguid, IDirectInputImpl *dinput,
                             JoystickImpl **pdev, unsigned short index)
 {
+    struct JoyDev *joydev = &joystick_devices[index];
     DIDEVICEINSTANCEW didi = {sizeof(didi)};
     DWORD i;
     JoystickImpl* newDevice;
@@ -431,11 +432,12 @@ static HRESULT alloc_device(REFGUID rguid, IDirectInputImpl *dinput,
     fill_joystick_dideviceinstanceW(&didi, dinput->dwVersion, index);
 
     *pdev = NULL;
-    if (FAILED(hr = direct_input_device_alloc(sizeof(JoystickImpl), &JoystickWvt, rguid, &didi, dinput, (void **)&newDevice)))
+    if (FAILED(hr = direct_input_device_alloc(sizeof(JoystickImpl), &JoystickWvt, rguid, joydev->vendor_id,
+                       joydev->product_id, index, &didi, dinput, (void **)&newDevice)))
         return hr;
     newDevice->generic.base.crit.DebugInfo->Spare[0] = (DWORD_PTR)(__FILE__ ": JoystickImpl*->generic.base.crit");
 
-    newDevice->joydev = &joystick_devices[index];
+    newDevice->joydev = joydev;
     newDevice->joyfd = -1;
     newDevice->generic.joy_polldev = joy_polldev;
     newDevice->generic.name        = newDevice->joydev->name;
@@ -625,10 +627,8 @@ static HRESULT WINAPI JoystickLinuxWImpl_GetProperty(LPDIRECTINPUTDEVICE8W iface
         case (DWORD_PTR) DIPROP_VIDPID:
         {
             LPDIPROPDWORD pd = (LPDIPROPDWORD)pdiph;
-
-            if (!This->joydev->product_id || !This->joydev->vendor_id)
-                return DIERR_UNSUPPORTED;
-            pd->dwData = MAKELONG(This->joydev->vendor_id, This->joydev->product_id);
+            if (!This->generic.base.vendor_id || !This->generic.base.product_id) return DIERR_UNSUPPORTED;
+            pd->dwData = MAKELONG(This->generic.base.vendor_id, This->generic.base.product_id);
             TRACE("DIPROP_VIDPID(%08x)\n", pd->dwData);
             break;
         }
@@ -636,7 +636,7 @@ static HRESULT WINAPI JoystickLinuxWImpl_GetProperty(LPDIRECTINPUTDEVICE8W iface
         {
             LPDIPROPDWORD pd = (LPDIPROPDWORD)pdiph;
 
-            pd->dwData = get_joystick_index(&This->generic.base.guid);
+            pd->dwData = This->generic.base.instance_id;
             TRACE("DIPROP_JOYSTICKID(%d)\n", pd->dwData);
             break;
         }
@@ -650,15 +650,11 @@ static HRESULT WINAPI JoystickLinuxWImpl_GetProperty(LPDIRECTINPUTDEVICE8W iface
 
             BOOL is_gamepad;
             LPDIPROPGUIDANDPATH pd = (LPDIPROPGUIDANDPATH)pdiph;
-            WORD vid = This->joydev->vendor_id;
-            WORD pid = This->joydev->product_id;
-
-            if (!pid || !vid)
-                return DIERR_UNSUPPORTED;
-
-            is_gamepad = is_xinput_device(&This->generic.devcaps, vid, pid);
+            if (!This->generic.base.vendor_id || !This->generic.base.product_id) return DIERR_UNSUPPORTED;
+            is_gamepad = is_xinput_device(&This->generic.devcaps, This->generic.base.vendor_id, This->generic.base.product_id);
             pd->guidClass = GUID_DEVCLASS_HIDCLASS;
-            sprintfW(pd->wszPath, formatW, vid, pid, is_gamepad ? igW : miW, get_joystick_index(&This->generic.base.guid));
+            sprintfW(pd->wszPath, formatW, This->generic.base.vendor_id, This->generic.base.product_id,
+                    is_gamepad ? igW : miW, This->generic.base.instance_id);
 
             TRACE("DIPROP_GUIDANDPATH(%s, %s): returning fake path\n", debugstr_guid(&pd->guidClass), debugstr_w(pd->wszPath));
             break;
diff --git a/dlls/dinput/joystick_linuxinput.c b/dlls/dinput/joystick_linuxinput.c
index 4730ea9bc3f..025943acff1 100644
--- a/dlls/dinput/joystick_linuxinput.c
+++ b/dlls/dinput/joystick_linuxinput.c
@@ -413,6 +413,7 @@ static HRESULT joydev_enum_deviceA(DWORD dwDevType, DWORD dwFlags, LPDIDEVICEINS
 
 static JoystickImpl *alloc_device(REFGUID rguid, IDirectInputImpl *dinput, unsigned short index)
 {
+    struct JoyDev *joydev = &joydevs[index];
     DIDEVICEINSTANCEW didi = {sizeof(didi)};
     JoystickImpl* newDevice;
     LPDIDATAFORMAT df = NULL;
@@ -421,13 +422,14 @@ static JoystickImpl *alloc_device(REFGUID rguid, IDirectInputImpl *dinput, unsig
 
     fill_joystick_dideviceinstanceW(&didi, dinput->dwVersion, index);
 
-    if (FAILED(direct_input_device_alloc(sizeof(JoystickImpl), &JoystickWvt, rguid, &didi, dinput, (void **)&newDevice)))
+    if (FAILED(direct_input_device_alloc(sizeof(JoystickImpl), &JoystickWvt, rguid, joydev->vendor_id,
+                joydev->product_id, index, &didi, dinput, (void **)&newDevice)))
         return NULL;
     newDevice->generic.base.crit.DebugInfo->Spare[0] = (DWORD_PTR)(__FILE__ ": JoystickImpl*->base.crit");
 
     newDevice->generic.joy_polldev = joy_polldev;
     newDevice->joyfd       = -1;
-    newDevice->joydev      = &joydevs[index];
+    newDevice->joydev = joydev;
     newDevice->generic.name        = newDevice->joydev->name;
     list_init(&newDevice->ff_effects);
 #ifdef HAVE_STRUCT_FF_EFFECT_DIRECTION
@@ -900,10 +902,8 @@ static HRESULT WINAPI JoystickWImpl_GetProperty(LPDIRECTINPUTDEVICE8W iface, REF
     case (DWORD_PTR) DIPROP_VIDPID:
     {
         LPDIPROPDWORD pd = (LPDIPROPDWORD)pdiph;
-
-        if (!This->joydev->product_id || !This->joydev->vendor_id)
-            return DIERR_UNSUPPORTED;
-        pd->dwData = MAKELONG(This->joydev->vendor_id, This->joydev->product_id);
+        if (!This->generic.base.vendor_id || !This->generic.base.product_id) return DIERR_UNSUPPORTED;
+        pd->dwData = MAKELONG(This->generic.base.vendor_id, This->generic.base.product_id);
         TRACE("DIPROP_VIDPID(%08x)\n", pd->dwData);
         break;
     }
@@ -912,7 +912,7 @@ static HRESULT WINAPI JoystickWImpl_GetProperty(LPDIRECTINPUTDEVICE8W iface, REF
     {
         LPDIPROPDWORD pd = (LPDIPROPDWORD)pdiph;
 
-        pd->dwData = get_joystick_index(&This->generic.base.guid);
+        pd->dwData = This->generic.base.instance_id;
         TRACE("DIPROP_JOYSTICKID(%d)\n", pd->dwData);
         break;
     }
@@ -926,15 +926,12 @@ static HRESULT WINAPI JoystickWImpl_GetProperty(LPDIRECTINPUTDEVICE8W iface, REF
 
         BOOL is_gamepad;
         LPDIPROPGUIDANDPATH pd = (LPDIPROPGUIDANDPATH)pdiph;
-        WORD vid = This->joydev->vendor_id;
-        WORD pid = This->joydev->product_id;
-
-        if (!pid || !vid)
-            return DIERR_UNSUPPORTED;
+        if (!This->generic.base.vendor_id || !This->generic.base.product_id) return DIERR_UNSUPPORTED;
 
-        is_gamepad = is_xinput_device(&This->generic.devcaps, vid, pid);
+        is_gamepad = is_xinput_device(&This->generic.devcaps, This->generic.base.vendor_id, This->generic.base.product_id);
         pd->guidClass = GUID_DEVCLASS_HIDCLASS;
-        sprintfW(pd->wszPath, formatW, vid, pid, is_gamepad ? igW : miW, get_joystick_index(&This->generic.base.guid));
+        sprintfW(pd->wszPath, formatW, This->generic.base.vendor_id, This->generic.base.product_id,
+                is_gamepad ? igW : miW, This->generic.base.instance_id);
 
         TRACE("DIPROP_GUIDANDPATH(%s, %s): returning fake path\n", debugstr_guid(&pd->guidClass), debugstr_w(pd->wszPath));
         break;
diff --git a/dlls/dinput/joystick_osx.c b/dlls/dinput/joystick_osx.c
index d13346f50e2..fb20a8f7c6e 100644
--- a/dlls/dinput/joystick_osx.c
+++ b/dlls/dinput/joystick_osx.c
@@ -1053,14 +1053,18 @@ static HRESULT alloc_device(REFGUID rguid, IDirectInputImpl *dinput,
     int axis_map[8]; /* max axes */
     int slider_count = 0;
     FFCAPABILITIES ffcaps;
+    WORD vendor_id, product_id;
 
     TRACE("%s %p %p %hu\n", debugstr_guid(rguid), dinput, pdev, index);
 
     device = get_device_ref(index);
+    vendor_id = get_device_property_long(device, CFSTR(kIOHIDVendorIDKey));
+    product_id = get_device_property_long(device, CFSTR(kIOHIDProductIDKey));
 
     fill_joystick_dideviceinstanceW(&didi, device, dinput->dwVersion, index, name);
 
-    if (FAILED(hr = direct_input_device_alloc(sizeof(JoystickImpl), &JoystickWvt, rguid, &didi, dinput, (void **)&newDevice)))
+    if (FAILED(hr = direct_input_device_alloc(sizeof(JoystickImpl), &JoystickWvt, rguid, vendor_id, product_id, index,
+                       &didi, dinput, (void **)&newDevice)))
         return hr;
     newDevice->generic.base.crit.DebugInfo->Spare[0] = (DWORD_PTR)(__FILE__ ": JoystickImpl*->generic.base.crit");
 
@@ -1284,17 +1288,13 @@ static HRESULT WINAPI JoystickWImpl_GetProperty(LPDIRECTINPUTDEVICE8W iface, REF
         static const WCHAR igW[] = {'i','g',0};
 
         BOOL is_gamepad;
-        IOHIDDeviceRef device = get_device_ref(This->id);
         LPDIPROPGUIDANDPATH pd = (LPDIPROPGUIDANDPATH)pdiph;
-        WORD vid = get_device_property_long(device, CFSTR(kIOHIDVendorIDKey));
-        WORD pid = get_device_property_long(device, CFSTR(kIOHIDProductIDKey));
+        if (!This->generic.base.vendor_id || !This->generic.base.product_id) return DIERR_UNSUPPORTED;
 
-        if (!pid || !vid)
-            return DIERR_UNSUPPORTED;
-
-        is_gamepad = is_xinput_device(&This->generic.devcaps, vid, pid);
+        is_gamepad = is_xinput_device(&This->generic.devcaps, This->generic.base.vendor_id, This->generic.base.product_id);
         pd->guidClass = GUID_DEVCLASS_HIDCLASS;
-        sprintfW(pd->wszPath, formatW, vid, pid, is_gamepad ? igW : miW, This->id);
+        sprintfW(pd->wszPath, formatW, This->generic.base.vendor_id, This->generic.base.product_id,
+                is_gamepad ? igW : miW, This->generic.base.instance_id);
 
         TRACE("DIPROP_GUIDANDPATH(%s, %s): returning fake path\n", debugstr_guid(&pd->guidClass), debugstr_w(pd->wszPath));
         break;
diff --git a/dlls/dinput/keyboard.c b/dlls/dinput/keyboard.c
index 11d41a2ce4c..79c57c50d28 100644
--- a/dlls/dinput/keyboard.c
+++ b/dlls/dinput/keyboard.c
@@ -203,7 +203,7 @@ static SysKeyboardImpl *alloc_device(REFGUID rguid, IDirectInputImpl *dinput)
 
     fill_keyboard_dideviceinstanceW(&didi, dinput->dwVersion, get_keyboard_subtype());
 
-    if (FAILED(direct_input_device_alloc(sizeof(SysKeyboardImpl), &SysKeyboardWvt, rguid, &didi, dinput, (void **)&newDevice)))
+    if (FAILED(direct_input_device_alloc(sizeof(SysKeyboardImpl), &SysKeyboardWvt, rguid, 0, 0, 0, &didi, dinput, (void **)&newDevice)))
         return NULL;
     newDevice->base.crit.DebugInfo->Spare[0] = (DWORD_PTR)(__FILE__ ": SysKeyboardImpl*->base.crit");
 
diff --git a/dlls/dinput/mouse.c b/dlls/dinput/mouse.c
index 0e3a8976033..f81fe92cf22 100644
--- a/dlls/dinput/mouse.c
+++ b/dlls/dinput/mouse.c
@@ -149,7 +149,7 @@ static SysMouseImpl *alloc_device(REFGUID rguid, IDirectInputImpl *dinput)
 
     fill_mouse_dideviceinstanceW(&didi, dinput->dwVersion);
 
-    if (FAILED(direct_input_device_alloc(sizeof(SysMouseImpl), &SysMouseWvt, rguid, &didi, dinput, (void **)&newDevice)))
+    if (FAILED(direct_input_device_alloc(sizeof(SysMouseImpl), &SysMouseWvt, rguid, 0, 0, 0, &didi, dinput, (void **)&newDevice)))
         return NULL;
     newDevice->base.crit.DebugInfo->Spare[0] = (DWORD_PTR)(__FILE__ ": SysMouseImpl*->base.crit");
 
-- 
2.28.0

>From c1c1363698ada02d8d3471e3197a65b0f956bb41 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?R=C3=A9mi=20Bernon?= <rbernon@codeweavers.com>
Date: Mon, 5 Oct 2020 12:44:47 +0200
Subject: [PATCH 13/39] dinput: Factor VIDPID/JOYSTICKID/GUIDANDPATH
 properties.

---
 dlls/dinput/joystick.c            | 36 ++++++++++++++++++-
 dlls/dinput/joystick_linux.c      | 59 +------------------------------
 dlls/dinput/joystick_linuxinput.c | 39 --------------------
 dlls/dinput/joystick_osx.c        | 39 +-------------------
 dlls/dinput/joystick_private.h    |  1 -
 5 files changed, 37 insertions(+), 137 deletions(-)

diff --git a/dlls/dinput/joystick.c b/dlls/dinput/joystick.c
index 72e3e8d4fd6..7acaf6b7f06 100644
--- a/dlls/dinput/joystick.c
+++ b/dlls/dinput/joystick.c
@@ -31,6 +31,7 @@
 #include "joystick_private.h"
 #include "wine/debug.h"
 #include "winreg.h"
+#include "devguid.h"
 
 WINE_DEFAULT_DEBUG_CHANNEL(dinput);
 
@@ -321,7 +322,7 @@ BOOL device_disabled_registry(const WCHAR* name)
     return do_disable;
 }
 
-BOOL is_xinput_device(const DIDEVCAPS *devcaps, WORD vid, WORD pid)
+static BOOL is_xinput_device(const DIDEVCAPS *devcaps, WORD vid, WORD pid)
 {
     int i;
 
@@ -637,6 +638,39 @@ HRESULT WINAPI JoystickWGenericImpl_GetProperty(LPDIRECTINPUTDEVICE8W iface, REF
 
             return DI_OK;
         }
+        case (DWORD_PTR) DIPROP_VIDPID:
+        {
+            LPDIPROPDWORD pd = (LPDIPROPDWORD)pdiph;
+            if (!This->base.vendor_id || !This->base.product_id) return DIERR_UNSUPPORTED;
+            pd->dwData = MAKELONG(This->base.vendor_id, This->base.product_id);
+            TRACE("vidpid(%08x)\n", pd->dwData);
+            return DI_OK;
+        }
+        case (DWORD_PTR) DIPROP_JOYSTICKID:
+        {
+            LPDIPROPDWORD pd = (LPDIPROPDWORD)pdiph;
+            pd->dwData = This->base.instance_id;
+            TRACE("joystickid(%d)\n", pd->dwData);
+            return DI_OK;
+        }
+        case (DWORD_PTR) DIPROP_GUIDANDPATH:
+        {
+            static const WCHAR formatW[] = {'\\', '\\', '?', '\\', 'h', 'i', 'd', '#', 'v', 'i', 'd', '_', '%', '0',
+                    '4', 'x', '&', 'p', 'i', 'd', '_', '%', '0', '4', 'x', '&', '%', 's', '_', '%', 'h', 'u', 0};
+            static const WCHAR miW[] = {'m', 'i', 0};
+            static const WCHAR igW[] = {'i', 'g', 0};
+
+            BOOL is_gamepad;
+            LPDIPROPGUIDANDPATH pd = (LPDIPROPGUIDANDPATH)pdiph;
+            if (!This->base.vendor_id || !This->base.product_id) return DIERR_UNSUPPORTED;
+            is_gamepad = is_xinput_device(&This->devcaps, This->base.vendor_id, This->base.product_id);
+            pd->guidClass = GUID_DEVCLASS_HIDCLASS;
+            sprintfW(pd->wszPath, formatW, This->base.vendor_id, This->base.product_id, is_gamepad ? igW : miW,
+                    This->base.instance_id);
+
+            TRACE("guidandpath(%s, %s): returning fake path\n", debugstr_guid(&pd->guidClass), debugstr_w(pd->wszPath));
+            return DI_OK;
+        }
         default:
             return IDirectInputDevice2WImpl_GetProperty(iface, rguid, pdiph);
         }
diff --git a/dlls/dinput/joystick_linux.c b/dlls/dinput/joystick_linux.c
index 75d677c58a6..4edcfd75a90 100644
--- a/dlls/dinput/joystick_linux.c
+++ b/dlls/dinput/joystick_linux.c
@@ -610,63 +610,6 @@ static HRESULT WINAPI JoystickLinuxWImpl_Acquire(LPDIRECTINPUTDEVICE8W iface)
     return DI_OK;
 }
 
-/******************************************************************************
-  *     GetProperty : get input device properties
-  */
-static HRESULT WINAPI JoystickLinuxWImpl_GetProperty(LPDIRECTINPUTDEVICE8W iface, REFGUID rguid, LPDIPROPHEADER pdiph)
-{
-    JoystickImpl *This = impl_from_IDirectInputDevice8W(iface);
-
-    TRACE("(%p)->(%s,%p)\n", This, debugstr_guid(rguid), pdiph);
-    _dump_DIPROPHEADER(pdiph);
-
-    if (!IS_DIPROP(rguid)) return DI_OK;
-
-    switch (LOWORD(rguid)) {
-
-        case (DWORD_PTR) DIPROP_VIDPID:
-        {
-            LPDIPROPDWORD pd = (LPDIPROPDWORD)pdiph;
-            if (!This->generic.base.vendor_id || !This->generic.base.product_id) return DIERR_UNSUPPORTED;
-            pd->dwData = MAKELONG(This->generic.base.vendor_id, This->generic.base.product_id);
-            TRACE("DIPROP_VIDPID(%08x)\n", pd->dwData);
-            break;
-        }
-        case (DWORD_PTR) DIPROP_JOYSTICKID:
-        {
-            LPDIPROPDWORD pd = (LPDIPROPDWORD)pdiph;
-
-            pd->dwData = This->generic.base.instance_id;
-            TRACE("DIPROP_JOYSTICKID(%d)\n", pd->dwData);
-            break;
-        }
-
-        case (DWORD_PTR) DIPROP_GUIDANDPATH:
-        {
-            static const WCHAR formatW[] = {'\\','\\','?','\\','h','i','d','#','v','i','d','_','%','0','4','x','&',
-                                            'p','i','d','_','%','0','4','x','&','%','s','_','%','h','u',0};
-            static const WCHAR miW[] = {'m','i',0};
-            static const WCHAR igW[] = {'i','g',0};
-
-            BOOL is_gamepad;
-            LPDIPROPGUIDANDPATH pd = (LPDIPROPGUIDANDPATH)pdiph;
-            if (!This->generic.base.vendor_id || !This->generic.base.product_id) return DIERR_UNSUPPORTED;
-            is_gamepad = is_xinput_device(&This->generic.devcaps, This->generic.base.vendor_id, This->generic.base.product_id);
-            pd->guidClass = GUID_DEVCLASS_HIDCLASS;
-            sprintfW(pd->wszPath, formatW, This->generic.base.vendor_id, This->generic.base.product_id,
-                    is_gamepad ? igW : miW, This->generic.base.instance_id);
-
-            TRACE("DIPROP_GUIDANDPATH(%s, %s): returning fake path\n", debugstr_guid(&pd->guidClass), debugstr_w(pd->wszPath));
-            break;
-        }
-
-    default:
-        return JoystickWGenericImpl_GetProperty(iface, rguid, pdiph);
-    }
-
-    return DI_OK;
-}
-
 /******************************************************************************
   *     Unacquire : frees the joystick
   */
@@ -774,7 +717,7 @@ static const IDirectInputDevice8WVtbl JoystickWvt =
     IDirectInputDevice2WImpl_Release,
     JoystickWGenericImpl_GetCapabilities,
     IDirectInputDevice2WImpl_EnumObjects,
-    JoystickLinuxWImpl_GetProperty,
+    JoystickWGenericImpl_GetProperty,
     JoystickWGenericImpl_SetProperty,
     JoystickLinuxWImpl_Acquire,
     JoystickLinuxWImpl_Unacquire,
diff --git a/dlls/dinput/joystick_linuxinput.c b/dlls/dinput/joystick_linuxinput.c
index 025943acff1..365d0d9572c 100644
--- a/dlls/dinput/joystick_linuxinput.c
+++ b/dlls/dinput/joystick_linuxinput.c
@@ -898,45 +898,6 @@ static HRESULT WINAPI JoystickWImpl_GetProperty(LPDIRECTINPUTDEVICE8W iface, REF
         TRACE("DIPROP_FFGAIN(%d)\n", pd->dwData);
         break;
     }
-
-    case (DWORD_PTR) DIPROP_VIDPID:
-    {
-        LPDIPROPDWORD pd = (LPDIPROPDWORD)pdiph;
-        if (!This->generic.base.vendor_id || !This->generic.base.product_id) return DIERR_UNSUPPORTED;
-        pd->dwData = MAKELONG(This->generic.base.vendor_id, This->generic.base.product_id);
-        TRACE("DIPROP_VIDPID(%08x)\n", pd->dwData);
-        break;
-    }
-
-    case (DWORD_PTR) DIPROP_JOYSTICKID:
-    {
-        LPDIPROPDWORD pd = (LPDIPROPDWORD)pdiph;
-
-        pd->dwData = This->generic.base.instance_id;
-        TRACE("DIPROP_JOYSTICKID(%d)\n", pd->dwData);
-        break;
-    }
-
-    case (DWORD_PTR) DIPROP_GUIDANDPATH:
-    {
-        static const WCHAR formatW[] = {'\\','\\','?','\\','h','i','d','#','v','i','d','_','%','0','4','x','&',
-                                        'p','i','d','_','%','0','4','x','&','%','s','_','%','h','u',0};
-        static const WCHAR miW[] = {'m','i',0};
-        static const WCHAR igW[] = {'i','g',0};
-
-        BOOL is_gamepad;
-        LPDIPROPGUIDANDPATH pd = (LPDIPROPGUIDANDPATH)pdiph;
-        if (!This->generic.base.vendor_id || !This->generic.base.product_id) return DIERR_UNSUPPORTED;
-
-        is_gamepad = is_xinput_device(&This->generic.devcaps, This->generic.base.vendor_id, This->generic.base.product_id);
-        pd->guidClass = GUID_DEVCLASS_HIDCLASS;
-        sprintfW(pd->wszPath, formatW, This->generic.base.vendor_id, This->generic.base.product_id,
-                is_gamepad ? igW : miW, This->generic.base.instance_id);
-
-        TRACE("DIPROP_GUIDANDPATH(%s, %s): returning fake path\n", debugstr_guid(&pd->guidClass), debugstr_w(pd->wszPath));
-        break;
-    }
-
     default:
         return JoystickWGenericImpl_GetProperty(iface, rguid, pdiph);
     }
diff --git a/dlls/dinput/joystick_osx.c b/dlls/dinput/joystick_osx.c
index fb20a8f7c6e..0e9278d83b7 100644
--- a/dlls/dinput/joystick_osx.c
+++ b/dlls/dinput/joystick_osx.c
@@ -1270,43 +1270,6 @@ static HRESULT joydev_create_device(IDirectInputImpl *dinput, REFGUID guid, IDir
     return DIERR_DEVICENOTREG;
 }
 
-static HRESULT WINAPI JoystickWImpl_GetProperty(LPDIRECTINPUTDEVICE8W iface, REFGUID rguid, LPDIPROPHEADER pdiph)
-{
-    JoystickImpl *This = impl_from_IDirectInputDevice8W(iface);
-
-    TRACE("(%p)->(%s,%p)\n", This, debugstr_guid(rguid), pdiph);
-    _dump_DIPROPHEADER(pdiph);
-
-    if (!IS_DIPROP(rguid)) return DI_OK;
-
-    switch (LOWORD(rguid)) {
-    case (DWORD_PTR) DIPROP_GUIDANDPATH:
-    {
-        static const WCHAR formatW[] = {'\\','\\','?','\\','h','i','d','#','v','i','d','_','%','0','4','x','&',
-                                        'p','i','d','_','%','0','4','x','&','%','s','_','%','i',0};
-        static const WCHAR miW[] = {'m','i',0};
-        static const WCHAR igW[] = {'i','g',0};
-
-        BOOL is_gamepad;
-        LPDIPROPGUIDANDPATH pd = (LPDIPROPGUIDANDPATH)pdiph;
-        if (!This->generic.base.vendor_id || !This->generic.base.product_id) return DIERR_UNSUPPORTED;
-
-        is_gamepad = is_xinput_device(&This->generic.devcaps, This->generic.base.vendor_id, This->generic.base.product_id);
-        pd->guidClass = GUID_DEVCLASS_HIDCLASS;
-        sprintfW(pd->wszPath, formatW, This->generic.base.vendor_id, This->generic.base.product_id,
-                is_gamepad ? igW : miW, This->generic.base.instance_id);
-
-        TRACE("DIPROP_GUIDANDPATH(%s, %s): returning fake path\n", debugstr_guid(&pd->guidClass), debugstr_w(pd->wszPath));
-        break;
-    }
-
-    default:
-        return JoystickWGenericImpl_GetProperty(iface, rguid, pdiph);
-    }
-
-    return DI_OK;
-}
-
 static HRESULT osx_set_autocenter(JoystickImpl *This,
         const DIPROPDWORD *header)
 {
@@ -1449,7 +1412,7 @@ static const IDirectInputDevice8WVtbl JoystickWvt =
     IDirectInputDevice2WImpl_Release,
     JoystickWGenericImpl_GetCapabilities,
     IDirectInputDevice2WImpl_EnumObjects,
-    JoystickWImpl_GetProperty,
+    JoystickWGenericImpl_GetProperty,
     JoystickWImpl_SetProperty,
     IDirectInputDevice2WImpl_Acquire,
     IDirectInputDevice2WImpl_Unacquire,
diff --git a/dlls/dinput/joystick_private.h b/dlls/dinput/joystick_private.h
index b82632c39d2..ca32d1b08fb 100644
--- a/dlls/dinput/joystick_private.h
+++ b/dlls/dinput/joystick_private.h
@@ -78,6 +78,5 @@ HRESULT WINAPI JoystickWGenericImpl_SetActionMap(LPDIRECTINPUTDEVICE8W iface, LP
 
 DWORD typeFromGUID(REFGUID guid) DECLSPEC_HIDDEN;
 void dump_DIEFFECT(LPCDIEFFECT eff, REFGUID guid, DWORD dwFlags) DECLSPEC_HIDDEN;
-BOOL is_xinput_device(const DIDEVCAPS *devcaps, WORD vid, WORD pid) DECLSPEC_HIDDEN;
 
 #endif /* __WINE_DLLS_DINPUT_JOYSTICK_PRIVATE_H */
-- 
2.28.0

>From f725ca3fed4537d765729e73ae55b7649275f3e3 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?R=C3=A9mi=20Bernon?= <rbernon@codeweavers.com>
Date: Mon, 5 Oct 2020 12:44:47 +0200
Subject: [PATCH 14/39] dinput: Introduce unix vtable for joystick devices.

And use it for Poll.
---
 dlls/dinput/joystick.c            |  4 ++--
 dlls/dinput/joystick_linux.c      | 29 +++++++++++++++++++++++++----
 dlls/dinput/joystick_linuxinput.c | 29 +++++++++++++++++++++++++----
 dlls/dinput/joystick_osx.c        | 28 ++++++++++++++++++++++++----
 dlls/dinput/joystick_private.h    | 11 ++++++++---
 5 files changed, 84 insertions(+), 17 deletions(-)

diff --git a/dlls/dinput/joystick.c b/dlls/dinput/joystick.c
index 7acaf6b7f06..1bb7ed95180 100644
--- a/dlls/dinput/joystick.c
+++ b/dlls/dinput/joystick.c
@@ -690,7 +690,7 @@ HRESULT WINAPI JoystickWGenericImpl_Poll(LPDIRECTINPUTDEVICE8W iface)
         return DIERR_NOTACQUIRED;
     }
 
-    This->joy_polldev(iface);
+    This->unix_funcs->poll(This->unix_ptr);
     return DI_OK;
 }
 
@@ -710,7 +710,7 @@ HRESULT WINAPI JoystickWGenericImpl_GetDeviceState(LPDIRECTINPUTDEVICE8W iface,
     }
 
     /* update joystick state */
-    This->joy_polldev(iface);
+    This->unix_funcs->poll(This->unix_ptr);
 
     /* convert and copy data to user supplied buffer */
     fill_DataFormat(ptr, len, &This->js, &This->base.data_format);
diff --git a/dlls/dinput/joystick_linux.c b/dlls/dinput/joystick_linux.c
index 4edcfd75a90..8d0500ba035 100644
--- a/dlls/dinput/joystick_linux.c
+++ b/dlls/dinput/joystick_linux.c
@@ -107,6 +107,20 @@ static inline JoystickImpl *impl_from_IDirectInputDevice8W(IDirectInputDevice8W
     return CONTAINING_RECORD(CONTAINING_RECORD(CONTAINING_RECORD(iface, IDirectInputDeviceImpl, IDirectInputDevice8W_iface),
            JoystickGenericImpl, base), JoystickImpl, generic);
 }
+static inline IDirectInputDevice8W *IDirectInputDevice8W_from_impl(JoystickImpl *This)
+{
+    return &This->generic.base.IDirectInputDevice8W_iface;
+}
+
+static inline struct unix_joystick *unix_joystick_from_impl(JoystickImpl *This)
+{
+    return (struct unix_joystick *)This;
+}
+
+static inline JoystickImpl *impl_from_unix_joystick(struct unix_joystick *ptr)
+{
+    return (JoystickImpl *)ptr;
+}
 
 static const GUID DInput_Wine_Joystick_GUID = { /* 9e573ed9-7734-11d2-8d4a-23903fb6bdf7 */
   0x9e573ed9,
@@ -119,7 +133,12 @@ static const GUID DInput_Wine_Joystick_GUID = { /* 9e573ed9-7734-11d2-8d4a-23903
 static INT joystick_devices_count = -1;
 static struct JoyDev *joystick_devices;
 
-static void joy_polldev(IDirectInputDevice8W *iface);
+static void CDECL unix_joystick_poll(struct unix_joystick *ptr);
+
+static const struct unix_joystick_vtbl unix_joystick_vtbl =
+{
+    unix_joystick_poll,
+};
 
 #define SYS_PATH_FORMAT "/sys/class/input/js%d/device/id/%s"
 static BOOL read_sys_id_variable(int index, const char *property, WORD *value)
@@ -436,10 +455,11 @@ static HRESULT alloc_device(REFGUID rguid, IDirectInputImpl *dinput,
                        joydev->product_id, index, &didi, dinput, (void **)&newDevice)))
         return hr;
     newDevice->generic.base.crit.DebugInfo->Spare[0] = (DWORD_PTR)(__FILE__ ": JoystickImpl*->generic.base.crit");
+    newDevice->generic.unix_funcs = &unix_joystick_vtbl;
+    newDevice->generic.unix_ptr = unix_joystick_from_impl(newDevice);
 
     newDevice->joydev = joydev;
     newDevice->joyfd = -1;
-    newDevice->generic.joy_polldev = joy_polldev;
     newDevice->generic.name        = newDevice->joydev->name;
     newDevice->generic.device_axis_count = newDevice->joydev->axis_count;
     newDevice->generic.devcaps.dwButtons = newDevice->joydev->button_count;
@@ -635,11 +655,12 @@ static HRESULT WINAPI JoystickLinuxWImpl_Unacquire(LPDIRECTINPUTDEVICE8W iface)
     return DI_NOEFFECT;
 }
 
-static void joy_polldev(IDirectInputDevice8W *iface)
+static void CDECL unix_joystick_poll(struct unix_joystick *ptr)
 {
     struct pollfd plfd;
     struct js_event jse;
-    JoystickImpl *This = impl_from_IDirectInputDevice8W(iface);
+    JoystickImpl *This = impl_from_unix_joystick(ptr);
+    IDirectInputDevice8W *iface = IDirectInputDevice8W_from_impl(This);
 
     TRACE("(%p)\n", This);
 
diff --git a/dlls/dinput/joystick_linuxinput.c b/dlls/dinput/joystick_linuxinput.c
index 365d0d9572c..c72b5919f87 100644
--- a/dlls/dinput/joystick_linuxinput.c
+++ b/dlls/dinput/joystick_linuxinput.c
@@ -141,10 +141,29 @@ static inline JoystickImpl *impl_from_IDirectInputDevice8W(IDirectInputDevice8W
     return CONTAINING_RECORD(CONTAINING_RECORD(CONTAINING_RECORD(iface, IDirectInputDeviceImpl, IDirectInputDevice8W_iface),
            JoystickGenericImpl, base), JoystickImpl, generic);
 }
+static inline IDirectInputDevice8W *IDirectInputDevice8W_from_impl(JoystickImpl *This)
+{
+    return &This->generic.base.IDirectInputDevice8W_iface;
+}
+
+static inline struct unix_joystick *unix_joystick_from_impl(JoystickImpl *This)
+{
+    return (struct unix_joystick *)This;
+}
+
+static inline JoystickImpl *impl_from_unix_joystick(struct unix_joystick *ptr)
+{
+    return (JoystickImpl *)ptr;
+}
 
 static void fake_current_js_state(JoystickImpl *ji);
 static void find_joydevs(void);
-static void joy_polldev(IDirectInputDevice8W *iface);
+static void CDECL unix_joystick_poll(struct unix_joystick *ptr);
+
+static const struct unix_joystick_vtbl unix_joystick_vtbl =
+{
+    unix_joystick_poll,
+};
 
 /* This GUID is slightly different from the linux joystick one. Take note. */
 static const GUID DInput_Wine_Joystick_Base_GUID = { /* 9e573eda-7734-11d2-8d4a-23903fb6bdf7 */
@@ -426,8 +445,9 @@ static JoystickImpl *alloc_device(REFGUID rguid, IDirectInputImpl *dinput, unsig
                 joydev->product_id, index, &didi, dinput, (void **)&newDevice)))
         return NULL;
     newDevice->generic.base.crit.DebugInfo->Spare[0] = (DWORD_PTR)(__FILE__ ": JoystickImpl*->base.crit");
+    newDevice->generic.unix_funcs = &unix_joystick_vtbl;
+    newDevice->generic.unix_ptr = unix_joystick_from_impl(newDevice);
 
-    newDevice->generic.joy_polldev = joy_polldev;
     newDevice->joyfd       = -1;
     newDevice->joydev = joydev;
     newDevice->generic.name        = newDevice->joydev->name;
@@ -716,11 +736,12 @@ static void fake_current_js_state(JoystickImpl *ji)
 #undef CENTER_AXIS
 
 /* convert wine format offset to user format object index */
-static void joy_polldev(IDirectInputDevice8W *iface)
+static void CDECL unix_joystick_poll(struct unix_joystick *ptr)
 {
     struct pollfd plfd;
     struct input_event ie;
-    JoystickImpl *This = impl_from_IDirectInputDevice8W(iface);
+    JoystickImpl *This = impl_from_unix_joystick(ptr);
+    IDirectInputDevice8W *iface = IDirectInputDevice8W_from_impl(This);
 
     if (This->joyfd==-1)
 	return;
diff --git a/dlls/dinput/joystick_osx.c b/dlls/dinput/joystick_osx.c
index 0e9278d83b7..c0ce7547aa9 100644
--- a/dlls/dinput/joystick_osx.c
+++ b/dlls/dinput/joystick_osx.c
@@ -118,6 +118,20 @@ static inline JoystickImpl *impl_from_IDirectInputDevice8W(IDirectInputDevice8W
     return CONTAINING_RECORD(CONTAINING_RECORD(CONTAINING_RECORD(iface, IDirectInputDeviceImpl, IDirectInputDevice8W_iface),
            JoystickGenericImpl, base), JoystickImpl, generic);
 }
+static inline IDirectInputDevice8W *IDirectInputDevice8W_from_impl(JoystickImpl *This)
+{
+    return &This->generic.base.IDirectInputDevice8W_iface;
+}
+
+static inline struct unix_joystick *unix_joystick_from_impl(JoystickImpl *This)
+{
+    return (struct unix_joystick *)This;
+}
+
+static inline JoystickImpl *impl_from_unix_joystick(struct unix_joystick *ptr)
+{
+    return (JoystickImpl *)ptr;
+}
 
 typedef struct _EffectImpl {
     IDirectInputEffect IDirectInputEffect_iface;
@@ -756,9 +770,10 @@ static void get_osx_device_elements_props(JoystickImpl *device)
     }
 }
 
-static void poll_osx_device_state(IDirectInputDevice8W *iface)
+static void CDECL unix_joystick_poll(struct unix_joystick *ptr)
 {
-    JoystickImpl *device = impl_from_IDirectInputDevice8W(iface);
+    JoystickImpl *device = impl_from_unix_joystick(ptr);
+    IDirectInputDevice8W *iface = IDirectInputDevice8W_from_impl(device);
     IOHIDElementRef device_main_element;
     IOHIDDeviceRef hid_device;
 
@@ -928,6 +943,11 @@ static void poll_osx_device_state(IDirectInputDevice8W *iface)
     }
 }
 
+static const struct unix_joystick_vtbl unix_joystick_vtbl =
+{
+    unix_joystick_poll,
+};
+
 static INT find_joystick_devices(void)
 {
     static INT joystick_devices_count = -1;
@@ -1067,11 +1087,11 @@ static HRESULT alloc_device(REFGUID rguid, IDirectInputImpl *dinput,
                        &didi, dinput, (void **)&newDevice)))
         return hr;
     newDevice->generic.base.crit.DebugInfo->Spare[0] = (DWORD_PTR)(__FILE__ ": JoystickImpl*->generic.base.crit");
+    newDevice->generic.unix_funcs = &unix_joystick_vtbl;
+    newDevice->generic.unix_ptr = unix_joystick_from_impl(newDevice);
 
     newDevice->id = index;
 
-    newDevice->generic.joy_polldev = poll_osx_device_state;
-
     /* get the device name */
     get_osx_device_name(index, name, MAX_PATH);
     TRACE("Name %s\n",name);
diff --git a/dlls/dinput/joystick_private.h b/dlls/dinput/joystick_private.h
index ca32d1b08fb..82f0f61bc80 100644
--- a/dlls/dinput/joystick_private.h
+++ b/dlls/dinput/joystick_private.h
@@ -33,11 +33,18 @@
 #define MAX_PROPS 164
 struct JoystickGenericImpl;
 
-typedef void joy_polldev_handler(IDirectInputDevice8W *iface);
+struct unix_joystick;
+
+struct unix_joystick_vtbl
+{
+    void (CDECL *poll)(struct unix_joystick *ptr);
+};
 
 typedef struct JoystickGenericImpl
 {
     struct IDirectInputDeviceImpl base;
+    const struct unix_joystick_vtbl *unix_funcs;
+    struct unix_joystick *unix_ptr;
 
     ObjProps    props[MAX_PROPS];
     DIDEVCAPS   devcaps;
@@ -46,8 +53,6 @@ typedef struct JoystickGenericImpl
     int         device_axis_count;      /* Total number of axes in the device */
     int        *axis_map;               /* User axes remapping */
     LONG        deadzone;               /* Default dead-zone */
-
-    joy_polldev_handler *joy_polldev;
 } JoystickGenericImpl;
 
 LONG joystick_map_axis(ObjProps *props, int val) DECLSPEC_HIDDEN;
-- 
2.28.0

>From 065b717c9a582ce32de2fab340114dcf302e0f0c Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?R=C3=A9mi=20Bernon?= <rbernon@codeweavers.com>
Date: Mon, 5 Oct 2020 22:45:21 +0200
Subject: [PATCH 15/39] dinput: Use the unix vtable for Acquire/Unacquire.

---
 dlls/dinput/joystick.c            | 27 ++++++++++++
 dlls/dinput/joystick_linux.c      | 29 +++++--------
 dlls/dinput/joystick_linuxinput.c | 68 ++++++++++++++-----------------
 dlls/dinput/joystick_osx.c        |  2 +
 dlls/dinput/joystick_private.h    |  7 ++++
 5 files changed, 78 insertions(+), 55 deletions(-)

diff --git a/dlls/dinput/joystick.c b/dlls/dinput/joystick.c
index 1bb7ed95180..f6f50896700 100644
--- a/dlls/dinput/joystick.c
+++ b/dlls/dinput/joystick.c
@@ -472,6 +472,33 @@ HRESULT WINAPI JoystickWGenericImpl_SetProperty(LPDIRECTINPUTDEVICE8W iface, REF
     return DI_OK;
 }
 
+HRESULT WINAPI JoystickWGenericImpl_Acquire(LPDIRECTINPUTDEVICE8W iface)
+{
+    JoystickGenericImpl *This = impl_from_IDirectInputDevice8W(iface);
+    HRESULT hr;
+
+    TRACE("(%p)\n", This);
+
+    if ((hr = IDirectInputDevice2WImpl_Acquire(iface)) != DI_OK) return hr;
+    if (!This->unix_funcs->acquire) return hr;
+    if (SUCCEEDED(hr = This->unix_funcs->acquire(This->unix_ptr))) return hr;
+    IDirectInputDevice2WImpl_Unacquire(iface);
+    return hr;
+}
+
+HRESULT WINAPI JoystickWGenericImpl_Unacquire(LPDIRECTINPUTDEVICE8W iface)
+{
+    JoystickGenericImpl *This = impl_from_IDirectInputDevice8W(iface);
+    HRESULT hr;
+
+    TRACE("(%p)\n", This);
+
+    if ((hr = IDirectInputDevice2WImpl_Unacquire(iface)) != DI_OK) return hr;
+    IDirectInputDevice8_SendForceFeedbackCommand(iface, DISFFC_RESET);
+    if (!This->unix_funcs->unacquire) return hr;
+    return This->unix_funcs->unacquire(This->unix_ptr);
+}
+
 #define DEBUG_TYPE(x) case (x): str = #x; break
 void _dump_DIDEVCAPS(const DIDEVCAPS *lpDIDevCaps)
 {
diff --git a/dlls/dinput/joystick_linux.c b/dlls/dinput/joystick_linux.c
index 8d0500ba035..3301e77d08b 100644
--- a/dlls/dinput/joystick_linux.c
+++ b/dlls/dinput/joystick_linux.c
@@ -135,8 +135,13 @@ static struct JoyDev *joystick_devices;
 
 static void CDECL unix_joystick_poll(struct unix_joystick *ptr);
 
+static HRESULT CDECL unix_joystick_acquire(struct unix_joystick *ptr);
+static HRESULT CDECL unix_joystick_unacquire(struct unix_joystick *ptr);
+
 static const struct unix_joystick_vtbl unix_joystick_vtbl =
 {
+    unix_joystick_acquire,
+    unix_joystick_unacquire,
     unix_joystick_poll,
 };
 
@@ -604,17 +609,12 @@ const struct dinput_device joystick_linux_device = {
 /******************************************************************************
   *     Acquire : gets exclusive control of the joystick
   */
-static HRESULT WINAPI JoystickLinuxWImpl_Acquire(LPDIRECTINPUTDEVICE8W iface)
+static HRESULT CDECL unix_joystick_acquire(struct unix_joystick *ptr)
 {
-    JoystickImpl *This = impl_from_IDirectInputDevice8W(iface);
-    HRESULT res;
+    JoystickImpl *This = impl_from_unix_joystick(ptr);
 
     TRACE("(%p)\n",This);
 
-    res = IDirectInputDevice2WImpl_Acquire(iface);
-    if (res != DI_OK)
-        return res;
-
     /* open the joystick device */
     if (This->joyfd==-1) {
         TRACE("opening joystick device %s\n", This->joydev->device);
@@ -622,7 +622,6 @@ static HRESULT WINAPI JoystickLinuxWImpl_Acquire(LPDIRECTINPUTDEVICE8W iface)
         This->joyfd = open(This->joydev->device, O_RDONLY);
         if (This->joyfd==-1) {
             ERR("open(%s) failed: %s\n", This->joydev->device, strerror(errno));
-            IDirectInputDevice2WImpl_Unacquire(iface);
             return DIERR_NOTFOUND;
         }
     }
@@ -633,18 +632,12 @@ static HRESULT WINAPI JoystickLinuxWImpl_Acquire(LPDIRECTINPUTDEVICE8W iface)
 /******************************************************************************
   *     Unacquire : frees the joystick
   */
-static HRESULT WINAPI JoystickLinuxWImpl_Unacquire(LPDIRECTINPUTDEVICE8W iface)
+static HRESULT CDECL unix_joystick_unacquire(struct unix_joystick *ptr)
 {
-    JoystickImpl *This = impl_from_IDirectInputDevice8W(iface);
-    HRESULT res;
+    JoystickImpl *This = impl_from_unix_joystick(ptr);
 
     TRACE("(%p)\n",This);
 
-    res = IDirectInputDevice2WImpl_Unacquire(iface);
-
-    if (res != DI_OK)
-        return res;
-
     if (This->joyfd!=-1) {
         TRACE("closing joystick device\n");
         close(This->joyfd);
@@ -740,8 +733,8 @@ static const IDirectInputDevice8WVtbl JoystickWvt =
     IDirectInputDevice2WImpl_EnumObjects,
     JoystickWGenericImpl_GetProperty,
     JoystickWGenericImpl_SetProperty,
-    JoystickLinuxWImpl_Acquire,
-    JoystickLinuxWImpl_Unacquire,
+    JoystickWGenericImpl_Acquire,
+    JoystickWGenericImpl_Unacquire,
     JoystickWGenericImpl_GetDeviceState,
     IDirectInputDevice2WImpl_GetDeviceData,
     IDirectInputDevice2WImpl_SetDataFormat,
diff --git a/dlls/dinput/joystick_linuxinput.c b/dlls/dinput/joystick_linuxinput.c
index c72b5919f87..62308e615f3 100644
--- a/dlls/dinput/joystick_linuxinput.c
+++ b/dlls/dinput/joystick_linuxinput.c
@@ -89,8 +89,6 @@ HRESULT linuxinput_create_effect(int* fd, REFGUID rguid, struct list *parent_lis
 HRESULT linuxinput_get_info_A(int fd, REFGUID rguid, LPDIEFFECTINFOA info);
 HRESULT linuxinput_get_info_W(int fd, REFGUID rguid, LPDIEFFECTINFOW info);
 
-static HRESULT WINAPI JoystickWImpl_SendForceFeedbackCommand(LPDIRECTINPUTDEVICE8W iface, DWORD dwFlags);
-
 typedef struct JoystickImpl JoystickImpl;
 static const IDirectInputDevice8WVtbl JoystickWvt;
 
@@ -160,8 +158,13 @@ static void fake_current_js_state(JoystickImpl *ji);
 static void find_joydevs(void);
 static void CDECL unix_joystick_poll(struct unix_joystick *ptr);
 
+static HRESULT CDECL unix_joystick_acquire(struct unix_joystick *ptr);
+static HRESULT CDECL unix_joystick_unacquire(struct unix_joystick *ptr);
+
 static const struct unix_joystick_vtbl unix_joystick_vtbl =
 {
+    unix_joystick_acquire,
+    unix_joystick_unacquire,
     unix_joystick_poll,
 };
 
@@ -626,26 +629,18 @@ const struct dinput_device joystick_linuxinput_device = {
 /******************************************************************************
   *     Acquire : gets exclusive control of the joystick
   */
-static HRESULT WINAPI JoystickWImpl_Acquire(LPDIRECTINPUTDEVICE8W iface)
+static HRESULT CDECL unix_joystick_acquire(struct unix_joystick *ptr)
 {
-    JoystickImpl *This = impl_from_IDirectInputDevice8W(iface);
-    HRESULT res;
+    JoystickImpl *This = impl_from_unix_joystick(ptr);
 
     TRACE("(this=%p)\n",This);
 
-    if ((res = IDirectInputDevice2WImpl_Acquire(iface)) != DI_OK)
-    {
-        WARN("Failed to acquire: %x\n", res);
-        return res;
-    }
-
     if ((This->joyfd = open(This->joydev->device, O_RDWR)) == -1)
     {
         if ((This->joyfd = open(This->joydev->device, O_RDONLY)) == -1)
         {
             /* Couldn't open the device at all */
             ERR("Failed to open device %s: %d %s\n", This->joydev->device, errno, strerror(errno));
-            IDirectInputDevice2WImpl_Unacquire(iface);
             return DIERR_NOTFOUND;
         }
         else
@@ -679,33 +674,32 @@ static HRESULT WINAPI JoystickWImpl_Acquire(LPDIRECTINPUTDEVICE8W iface)
 /******************************************************************************
   *     Unacquire : frees the joystick
   */
-static HRESULT WINAPI JoystickWImpl_Unacquire(LPDIRECTINPUTDEVICE8W iface)
+static HRESULT CDECL unix_joystick_unacquire(struct unix_joystick *ptr)
 {
-    JoystickImpl *This = impl_from_IDirectInputDevice8W(iface);
-    HRESULT res;
+    JoystickImpl *This = impl_from_unix_joystick(ptr);
 
     TRACE("(this=%p)\n",This);
-    res = IDirectInputDevice2WImpl_Unacquire(iface);
-    if (res==DI_OK && This->joyfd!=-1) {
-      struct input_event event;
-
-      /* Stop and unload all effects */
-      JoystickWImpl_SendForceFeedbackCommand(iface, DISFFC_RESET);
-
-      /* Enable autocenter. */
-      event.type = EV_FF;
-      event.code = FF_AUTOCENTER;
-      /* TODO: Read autocenter strength before disabling it, and use it here
-       * instead of 0xFFFF (maximum strength).
-       */
-      event.value = 0xFFFF;
-      if (write(This->joyfd, &event, sizeof(event)) == -1)
-        ERR("Failed to set autocenter to %04x: %d %s\n", event.value, errno, strerror(errno));
-
-      close(This->joyfd);
-      This->joyfd = -1;
+
+    if (This->joyfd != -1)
+    {
+        struct input_event event;
+
+        /* Enable autocenter. */
+        event.type = EV_FF;
+        event.code = FF_AUTOCENTER;
+        /* TODO: Read autocenter strength before disabling it, and use it here
+         * instead of 0xFFFF (maximum strength).
+         */
+        event.value = 0xFFFF;
+        if (write(This->joyfd, &event, sizeof(event)) == -1)
+            ERR("Failed to set autocenter to %04x: %d %s\n", event.value, errno, strerror(errno));
+
+        close(This->joyfd);
+        This->joyfd = -1;
+        return DI_OK;
     }
-    return res;
+
+    return DI_NOEFFECT;
 }
 
 /* 
@@ -1197,8 +1191,8 @@ static const IDirectInputDevice8WVtbl JoystickWvt =
     IDirectInputDevice2WImpl_EnumObjects,
     JoystickWImpl_GetProperty,
     JoystickWImpl_SetProperty,
-    JoystickWImpl_Acquire,
-    JoystickWImpl_Unacquire,
+    JoystickWGenericImpl_Acquire,
+    JoystickWGenericImpl_Unacquire,
     JoystickWGenericImpl_GetDeviceState,
     IDirectInputDevice2WImpl_GetDeviceData,
     IDirectInputDevice2WImpl_SetDataFormat,
diff --git a/dlls/dinput/joystick_osx.c b/dlls/dinput/joystick_osx.c
index c0ce7547aa9..87111669633 100644
--- a/dlls/dinput/joystick_osx.c
+++ b/dlls/dinput/joystick_osx.c
@@ -945,6 +945,8 @@ static void CDECL unix_joystick_poll(struct unix_joystick *ptr)
 
 static const struct unix_joystick_vtbl unix_joystick_vtbl =
 {
+    NULL,
+    NULL,
     unix_joystick_poll,
 };
 
diff --git a/dlls/dinput/joystick_private.h b/dlls/dinput/joystick_private.h
index 82f0f61bc80..e7e64e26cd1 100644
--- a/dlls/dinput/joystick_private.h
+++ b/dlls/dinput/joystick_private.h
@@ -37,6 +37,9 @@ struct unix_joystick;
 
 struct unix_joystick_vtbl
 {
+    HRESULT (CDECL *acquire)(struct unix_joystick *ptr);
+    HRESULT (CDECL *unacquire)(struct unix_joystick *ptr);
+
     void (CDECL *poll)(struct unix_joystick *ptr);
 };
 
@@ -73,6 +76,10 @@ void _dump_DIDEVCAPS(const DIDEVCAPS *lpDIDevCaps) DECLSPEC_HIDDEN;
 
 HRESULT WINAPI JoystickWGenericImpl_SetProperty(LPDIRECTINPUTDEVICE8W iface, REFGUID rguid, LPCDIPROPHEADER ph) DECLSPEC_HIDDEN;
 
+HRESULT WINAPI JoystickWGenericImpl_Acquire(LPDIRECTINPUTDEVICE8W iface) DECLSPEC_HIDDEN;
+
+HRESULT WINAPI JoystickWGenericImpl_Unacquire(LPDIRECTINPUTDEVICE8W iface) DECLSPEC_HIDDEN;
+
 HRESULT WINAPI JoystickWGenericImpl_Poll(LPDIRECTINPUTDEVICE8W iface) DECLSPEC_HIDDEN;
 
 HRESULT WINAPI JoystickWGenericImpl_GetDeviceState(LPDIRECTINPUTDEVICE8W iface, DWORD len, LPVOID ptr) DECLSPEC_HIDDEN;
-- 
2.28.0

>From de6d92b932833a9584689f78481d0a0941522092 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?R=C3=A9mi=20Bernon?= <rbernon@codeweavers.com>
Date: Mon, 5 Oct 2020 22:47:50 +0200
Subject: [PATCH 16/39] dinput: Use the unix vtable for SetProperty.

---
 dlls/dinput/joystick.c            |  33 ++++++++
 dlls/dinput/joystick_linux.c      |   2 +
 dlls/dinput/joystick_linuxinput.c | 120 ++++++++----------------------
 dlls/dinput/joystick_osx.c        |  36 +++------
 dlls/dinput/joystick_private.h    |   6 ++
 5 files changed, 85 insertions(+), 112 deletions(-)

diff --git a/dlls/dinput/joystick.c b/dlls/dinput/joystick.c
index f6f50896700..011018b2a4f 100644
--- a/dlls/dinput/joystick.c
+++ b/dlls/dinput/joystick.c
@@ -343,6 +343,7 @@ HRESULT WINAPI JoystickWGenericImpl_SetProperty(LPDIRECTINPUTDEVICE8W iface, REF
     JoystickGenericImpl *This = impl_from_IDirectInputDevice8W(iface);
     DWORD i;
     ObjProps remap_props;
+    HRESULT hr;
 
     TRACE("(%p,%s,%p)\n",This,debugstr_guid(rguid),ph);
 
@@ -464,6 +465,22 @@ HRESULT WINAPI JoystickWGenericImpl_SetProperty(LPDIRECTINPUTDEVICE8W iface, REF
           FIXME("DIPROP_CALIBRATIONMODE(%d)\n", pd->dwData);
           break;
         }
+        case (DWORD_PTR)DIPROP_AUTOCENTER:
+        {
+            LPCDIPROPDWORD pd = (LPCDIPROPDWORD)ph;
+            if (!This->unix_funcs->ff_set_autocenter) return DIERR_UNSUPPORTED;
+            if (FAILED(hr = This->unix_funcs->ff_set_autocenter(This->unix_ptr, pd->dwData))) return hr;
+            This->ff_autocenter = pd->dwData;
+            return DI_OK;
+        }
+        case (DWORD_PTR)DIPROP_FFGAIN:
+        {
+            LPCDIPROPDWORD pd = (LPCDIPROPDWORD)ph;
+            if (!This->unix_funcs->ff_set_gain) return DIERR_UNSUPPORTED;
+            if (FAILED(hr = This->unix_funcs->ff_set_gain(This->unix_ptr, pd->dwData))) return hr;
+            This->ff_gain = pd->dwData;
+            return DI_OK;
+        }
         default:
             return IDirectInputDevice2WImpl_SetProperty(iface, rguid, ph);
         }
@@ -698,6 +715,22 @@ HRESULT WINAPI JoystickWGenericImpl_GetProperty(LPDIRECTINPUTDEVICE8W iface, REF
             TRACE("guidandpath(%s, %s): returning fake path\n", debugstr_guid(&pd->guidClass), debugstr_w(pd->wszPath));
             return DI_OK;
         }
+        case (DWORD_PTR)DIPROP_AUTOCENTER:
+        {
+            LPDIPROPDWORD pd = (LPDIPROPDWORD)pdiph;
+            if (!This->unix_funcs->ff_set_autocenter) return DIERR_UNSUPPORTED;
+            pd->dwData = This->ff_autocenter;
+            TRACE("autocenter(%d)\n", pd->dwData);
+            return DI_OK;
+        }
+        case (DWORD_PTR)DIPROP_FFGAIN:
+        {
+            LPDIPROPDWORD pd = (LPDIPROPDWORD)pdiph;
+            if (!This->unix_funcs->ff_set_gain) return DIERR_UNSUPPORTED;
+            pd->dwData = This->ff_gain;
+            TRACE("ffgain(%d)\n", pd->dwData);
+            return DI_OK;
+        }
         default:
             return IDirectInputDevice2WImpl_GetProperty(iface, rguid, pdiph);
         }
diff --git a/dlls/dinput/joystick_linux.c b/dlls/dinput/joystick_linux.c
index 3301e77d08b..f1ca6451428 100644
--- a/dlls/dinput/joystick_linux.c
+++ b/dlls/dinput/joystick_linux.c
@@ -142,6 +142,8 @@ static const struct unix_joystick_vtbl unix_joystick_vtbl =
 {
     unix_joystick_acquire,
     unix_joystick_unacquire,
+    NULL,
+    NULL,
     unix_joystick_poll,
 };
 
diff --git a/dlls/dinput/joystick_linuxinput.c b/dlls/dinput/joystick_linuxinput.c
index 62308e615f3..eeb4d9bd220 100644
--- a/dlls/dinput/joystick_linuxinput.c
+++ b/dlls/dinput/joystick_linuxinput.c
@@ -161,10 +161,15 @@ static void CDECL unix_joystick_poll(struct unix_joystick *ptr);
 static HRESULT CDECL unix_joystick_acquire(struct unix_joystick *ptr);
 static HRESULT CDECL unix_joystick_unacquire(struct unix_joystick *ptr);
 
+static HRESULT CDECL unix_joystick_ff_set_autocenter(struct unix_joystick *ptr, DWORD value);
+static HRESULT CDECL unix_joystick_ff_set_gain(struct unix_joystick *ptr, DWORD value);
+
 static const struct unix_joystick_vtbl unix_joystick_vtbl =
 {
     unix_joystick_acquire,
     unix_joystick_unacquire,
+    unix_joystick_ff_set_autocenter,
+    unix_joystick_ff_set_gain,
     unix_joystick_poll,
 };
 
@@ -463,6 +468,8 @@ static JoystickImpl *alloc_device(REFGUID rguid, IDirectInputImpl *dinput, unsig
        enabled. */
     newDevice->ff_autocenter = 1;
     newDevice->ff_gain = 0xFFFF;
+    newDevice->generic.ff_autocenter = DIPROPAUTOCENTER_ON;
+    newDevice->generic.ff_gain = 10000;
 
     /* Count number of available axes - supported Axis & POVs */
     for (i = 0; i < ABS_MAX; i++)
@@ -702,6 +709,29 @@ static HRESULT CDECL unix_joystick_unacquire(struct unix_joystick *ptr)
     return DI_NOEFFECT;
 }
 
+static HRESULT CDECL unix_joystick_ff_set_autocenter(struct unix_joystick *ptr, DWORD value)
+{
+    JoystickImpl *This = impl_from_unix_joystick(ptr);
+    This->ff_autocenter = value == DIPROPAUTOCENTER_ON;
+    return DI_OK;
+}
+
+static HRESULT CDECL unix_joystick_ff_set_gain(struct unix_joystick *ptr, DWORD value)
+{
+    JoystickImpl *This = impl_from_unix_joystick(ptr);
+    struct input_event event;
+
+    This->ff_gain = MulDiv(value, 0xFFFF, 10000);
+    if (!This->generic.base.acquired) return DI_OK;
+
+    event.type = EV_FF;
+    event.code = FF_GAIN;
+    event.value = This->ff_gain;
+    if (write(This->joyfd, &event, sizeof(event)) == -1)
+        ERR("Failed to set gain (%i): %d %s\n", This->ff_gain, errno, strerror(errno));
+    return DI_OK;
+}
+
 /* 
  * set the current state of the js device as it would be with the middle
  * values on the axes
@@ -834,92 +864,6 @@ static void CDECL unix_joystick_poll(struct unix_joystick *ptr)
     }
 }
 
-/******************************************************************************
-  *     SetProperty : change input device properties
-  */
-static HRESULT WINAPI JoystickWImpl_SetProperty(LPDIRECTINPUTDEVICE8W iface, REFGUID rguid, LPCDIPROPHEADER ph)
-{
-  JoystickImpl *This = impl_from_IDirectInputDevice8W(iface);
-
-  if (!ph) {
-    WARN("invalid argument\n");
-    return DIERR_INVALIDPARAM;
-  }
-
-  TRACE("(this=%p,%s,%p)\n",This,debugstr_guid(rguid),ph);
-  TRACE("ph.dwSize = %d, ph.dwHeaderSize =%d, ph.dwObj = %d, ph.dwHow= %d\n",
-        ph->dwSize, ph->dwHeaderSize, ph->dwObj, ph->dwHow);
-
-  if (IS_DIPROP(rguid)) {
-    switch (LOWORD(rguid)) {
-    case (DWORD_PTR)DIPROP_AUTOCENTER: {
-      LPCDIPROPDWORD pd = (LPCDIPROPDWORD)ph;
-
-      TRACE("autocenter(%d)\n", pd->dwData);
-      This->ff_autocenter = pd->dwData == DIPROPAUTOCENTER_ON;
-
-      break;
-    }
-    case (DWORD_PTR)DIPROP_FFGAIN: {
-      LPCDIPROPDWORD pd = (LPCDIPROPDWORD)ph;
-
-      TRACE("DIPROP_FFGAIN(%d)\n", pd->dwData);
-      This->ff_gain = MulDiv(pd->dwData, 0xFFFF, 10000);
-      if (This->generic.base.acquired) {
-        /* Update immediately. */
-        struct input_event event;
-
-        event.type = EV_FF;
-        event.code = FF_GAIN;
-        event.value = This->ff_gain;
-        if (write(This->joyfd, &event, sizeof(event)) == -1)
-          ERR("Failed to set gain (%i): %d %s\n", This->ff_gain, errno, strerror(errno));
-      }
-      break;
-    }
-    default:
-      return JoystickWGenericImpl_SetProperty(iface, rguid, ph);
-    }
-  }
-  return DI_OK;
-}
-
-/******************************************************************************
-  *     GetProperty : get input device properties
-  */
-static HRESULT WINAPI JoystickWImpl_GetProperty(LPDIRECTINPUTDEVICE8W iface, REFGUID rguid, LPDIPROPHEADER pdiph)
-{
-    JoystickImpl *This = impl_from_IDirectInputDevice8W(iface);
-
-    TRACE("(%p)->(%s,%p)\n", This, debugstr_guid(rguid), pdiph);
-    _dump_DIPROPHEADER(pdiph);
-
-    if (!IS_DIPROP(rguid)) return DI_OK;
-
-    switch (LOWORD(rguid)) {
-    case (DWORD_PTR) DIPROP_AUTOCENTER:
-    {
-        LPDIPROPDWORD pd = (LPDIPROPDWORD)pdiph;
-
-        pd->dwData = This->ff_autocenter ? DIPROPAUTOCENTER_ON : DIPROPAUTOCENTER_OFF;
-        TRACE("autocenter(%d)\n", pd->dwData);
-        break;
-    }
-    case (DWORD_PTR) DIPROP_FFGAIN:
-    {
-        LPDIPROPDWORD pd = (LPDIPROPDWORD)pdiph;
-
-        pd->dwData = MulDiv(This->ff_gain, 10000, 0xFFFF);
-        TRACE("DIPROP_FFGAIN(%d)\n", pd->dwData);
-        break;
-    }
-    default:
-        return JoystickWGenericImpl_GetProperty(iface, rguid, pdiph);
-    }
-
-    return DI_OK;
-}
-
 /****************************************************************************** 
   *	CreateEffect - Create a new FF effect with the specified params
   */
@@ -1189,8 +1133,8 @@ static const IDirectInputDevice8WVtbl JoystickWvt =
     IDirectInputDevice2WImpl_Release,
     JoystickWGenericImpl_GetCapabilities,
     IDirectInputDevice2WImpl_EnumObjects,
-    JoystickWImpl_GetProperty,
-    JoystickWImpl_SetProperty,
+    JoystickWGenericImpl_GetProperty,
+    JoystickWGenericImpl_SetProperty,
     JoystickWGenericImpl_Acquire,
     JoystickWGenericImpl_Unacquire,
     JoystickWGenericImpl_GetDeviceState,
diff --git a/dlls/dinput/joystick_osx.c b/dlls/dinput/joystick_osx.c
index 87111669633..f129b666b2f 100644
--- a/dlls/dinput/joystick_osx.c
+++ b/dlls/dinput/joystick_osx.c
@@ -943,10 +943,15 @@ static void CDECL unix_joystick_poll(struct unix_joystick *ptr)
     }
 }
 
+static HRESULT CDECL unix_joystick_ff_set_autocenter(struct unix_joystick *ptr, DWORD value);
+static HRESULT CDECL unix_joystick_ff_set_gain(struct unix_joystick *ptr, DWORD value);
+
 static const struct unix_joystick_vtbl unix_joystick_vtbl =
 {
     NULL,
     NULL,
+    unix_joystick_ff_set_autocenter,
+    unix_joystick_ff_set_gain,
     unix_joystick_poll,
 };
 
@@ -1292,49 +1297,32 @@ static HRESULT joydev_create_device(IDirectInputImpl *dinput, REFGUID guid, IDir
     return DIERR_DEVICENOTREG;
 }
 
-static HRESULT osx_set_autocenter(JoystickImpl *This,
-        const DIPROPDWORD *header)
+static HRESULT CDECL unix_joystick_ff_set_autocenter(struct unix_joystick *ptr, DWORD value)
 {
+    JoystickImpl *This = impl_from_unix_joystick(ptr);
     UInt32 v;
     HRESULT hr;
     if(!This->ff)
         return DIERR_UNSUPPORTED;
-    v = header->dwData;
+    v = value;
     hr = osx_to_win32_hresult(FFDeviceSetForceFeedbackProperty(This->ff, FFPROP_AUTOCENTER, &v));
     TRACE("returning: %08x\n", hr);
     return hr;
 }
 
-static HRESULT osx_set_ffgain(JoystickImpl *This, const DIPROPDWORD *header)
+static HRESULT CDECL unix_joystick_ff_set_gain(struct unix_joystick *ptr, DWORD value)
 {
+    JoystickImpl *This = impl_from_unix_joystick(ptr);
     UInt32 v;
     HRESULT hr;
     if(!This->ff)
         return DIERR_UNSUPPORTED;
-    v = header->dwData;
+    v = value;
     hr = osx_to_win32_hresult(FFDeviceSetForceFeedbackProperty(This->ff, FFPROP_FFGAIN, &v));
     TRACE("returning: %08x\n", hr);
     return hr;
 }
 
-static HRESULT WINAPI JoystickWImpl_SetProperty(IDirectInputDevice8W *iface,
-        const GUID *prop, const DIPROPHEADER *header)
-{
-    JoystickImpl *This = impl_from_IDirectInputDevice8W(iface);
-
-    TRACE("%p %s %p\n", This, debugstr_guid(prop), header);
-
-    switch(LOWORD(prop))
-    {
-    case (DWORD_PTR)DIPROP_AUTOCENTER:
-        return osx_set_autocenter(This, (const DIPROPDWORD *)header);
-    case (DWORD_PTR)DIPROP_FFGAIN:
-        return osx_set_ffgain(This, (const DIPROPDWORD *)header);
-    }
-
-    return JoystickWGenericImpl_SetProperty(iface, prop, header);
-}
-
 static CFUUIDRef effect_win_to_mac(const GUID *effect)
 {
 #define DO_MAP(X) \
@@ -1435,7 +1423,7 @@ static const IDirectInputDevice8WVtbl JoystickWvt =
     JoystickWGenericImpl_GetCapabilities,
     IDirectInputDevice2WImpl_EnumObjects,
     JoystickWGenericImpl_GetProperty,
-    JoystickWImpl_SetProperty,
+    JoystickWGenericImpl_SetProperty,
     IDirectInputDevice2WImpl_Acquire,
     IDirectInputDevice2WImpl_Unacquire,
     JoystickWGenericImpl_GetDeviceState,
diff --git a/dlls/dinput/joystick_private.h b/dlls/dinput/joystick_private.h
index e7e64e26cd1..c7d1669fe1f 100644
--- a/dlls/dinput/joystick_private.h
+++ b/dlls/dinput/joystick_private.h
@@ -40,6 +40,9 @@ struct unix_joystick_vtbl
     HRESULT (CDECL *acquire)(struct unix_joystick *ptr);
     HRESULT (CDECL *unacquire)(struct unix_joystick *ptr);
 
+    HRESULT (CDECL *ff_set_autocenter)(struct unix_joystick *ptr, DWORD value);
+    HRESULT (CDECL *ff_set_gain)(struct unix_joystick *ptr, DWORD value);
+
     void (CDECL *poll)(struct unix_joystick *ptr);
 };
 
@@ -56,6 +59,9 @@ typedef struct JoystickGenericImpl
     int         device_axis_count;      /* Total number of axes in the device */
     int        *axis_map;               /* User axes remapping */
     LONG        deadzone;               /* Default dead-zone */
+
+    DWORD ff_autocenter;
+    DWORD ff_gain;
 } JoystickGenericImpl;
 
 LONG joystick_map_axis(ObjProps *props, int val) DECLSPEC_HIDDEN;
-- 
2.28.0

>From 8544b781fa8adbc90f0dc50be21d808ad1c5df1e Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?R=C3=A9mi=20Bernon?= <rbernon@codeweavers.com>
Date: Mon, 5 Oct 2020 22:50:24 +0200
Subject: [PATCH 17/39] dinput: Use the unix vtable for CreateEffect.

---
 dlls/dinput/joystick.c            | 40 ++++++++++++++
 dlls/dinput/joystick_linux.c      |  1 +
 dlls/dinput/joystick_linuxinput.c | 91 ++++++++-----------------------
 dlls/dinput/joystick_osx.c        | 30 +++++-----
 dlls/dinput/joystick_private.h    |  9 +++
 5 files changed, 86 insertions(+), 85 deletions(-)

diff --git a/dlls/dinput/joystick.c b/dlls/dinput/joystick.c
index 011018b2a4f..d80dd7d5caf 100644
--- a/dlls/dinput/joystick.c
+++ b/dlls/dinput/joystick.c
@@ -739,6 +739,46 @@ HRESULT WINAPI JoystickWGenericImpl_GetProperty(LPDIRECTINPUTDEVICE8W iface, REF
     return DI_OK;
 }
 
+HRESULT WINAPI JoystickWGenericImpl_CreateEffect(LPDIRECTINPUTDEVICE8W iface, REFGUID rguid, LPCDIEFFECT lpeff,
+        LPDIRECTINPUTEFFECT *ppdef, LPUNKNOWN pUnkOuter)
+{
+    JoystickGenericImpl *This = impl_from_IDirectInputDevice8W(iface);
+    effect_list_item *item = NULL;
+    HRESULT hr;
+
+    TRACE("(this=%p,%p,%p,%p,%p)\n", This, rguid, lpeff, ppdef, pUnkOuter);
+
+    if (!ppdef) return E_POINTER;
+    *ppdef = NULL;
+
+    if (!This->unix_funcs->create_effect) return DIERR_UNSUPPORTED;
+    if (!(item = HeapAlloc(GetProcessHeap(), 0, sizeof(*item)))) return DIERR_OUTOFMEMORY;
+    if (FAILED(hr = This->unix_funcs->create_effect(This->unix_ptr, rguid, lpeff, &item->entry, &item->ref)))
+    {
+        HeapFree(GetProcessHeap(), 0, item);
+        return hr;
+    }
+    list_add_tail(&This->ff_effects, &item->entry);
+    *ppdef = item->ref;
+    if (pUnkOuter != NULL) FIXME("Interface aggregation not implemented.\n");
+    return DI_OK;
+}
+
+HRESULT WINAPI JoystickWGenericImpl_EnumCreatedEffectObjects(LPDIRECTINPUTDEVICE8W iface,
+        LPDIENUMCREATEDEFFECTOBJECTSCALLBACK lpCallback, LPVOID pvRef, DWORD dwFlags)
+{
+    JoystickGenericImpl *This = impl_from_IDirectInputDevice8W(iface);
+    effect_list_item *itr, *ptr;
+
+    TRACE("(this=%p,%p,%p,%d)\n", This, lpCallback, pvRef, dwFlags);
+
+    if (!lpCallback) return DIERR_INVALIDPARAM;
+    if (dwFlags != 0) FIXME("Flags specified, but no flags exist yet (DX9)!\n");
+    LIST_FOR_EACH_ENTRY_SAFE(itr, ptr, &This->ff_effects, effect_list_item, entry)
+        (*lpCallback)(itr->ref, pvRef);
+    return DI_OK;
+}
+
 HRESULT WINAPI JoystickWGenericImpl_Poll(LPDIRECTINPUTDEVICE8W iface)
 {
     JoystickGenericImpl *This = impl_from_IDirectInputDevice8W(iface);
diff --git a/dlls/dinput/joystick_linux.c b/dlls/dinput/joystick_linux.c
index f1ca6451428..615d9432718 100644
--- a/dlls/dinput/joystick_linux.c
+++ b/dlls/dinput/joystick_linux.c
@@ -144,6 +144,7 @@ static const struct unix_joystick_vtbl unix_joystick_vtbl =
     unix_joystick_unacquire,
     NULL,
     NULL,
+    NULL,
     unix_joystick_poll,
 };
 
diff --git a/dlls/dinput/joystick_linuxinput.c b/dlls/dinput/joystick_linuxinput.c
index eeb4d9bd220..92985b937db 100644
--- a/dlls/dinput/joystick_linuxinput.c
+++ b/dlls/dinput/joystick_linuxinput.c
@@ -128,7 +128,6 @@ struct JoystickImpl
 	BYTE				buttons[KEY_MAX];
 
 	/* Force feedback variables */
-        struct list                     ff_effects;
 	int				ff_state;
 	int				ff_autocenter;
 	int				ff_gain;
@@ -164,12 +163,20 @@ static HRESULT CDECL unix_joystick_unacquire(struct unix_joystick *ptr);
 static HRESULT CDECL unix_joystick_ff_set_autocenter(struct unix_joystick *ptr, DWORD value);
 static HRESULT CDECL unix_joystick_ff_set_gain(struct unix_joystick *ptr, DWORD value);
 
+static HRESULT CDECL unix_joystick_create_effect(struct unix_joystick *ptr, REFGUID guid, const DIEFFECT *effect,
+        struct list *entry, IDirectInputEffect **out);
+
 static const struct unix_joystick_vtbl unix_joystick_vtbl =
 {
     unix_joystick_acquire,
     unix_joystick_unacquire,
     unix_joystick_ff_set_autocenter,
     unix_joystick_ff_set_gain,
+#ifdef HAVE_STRUCT_FF_EFFECT_DIRECTION
+    unix_joystick_create_effect,
+#else
+    NULL,
+#endif
     unix_joystick_poll,
 };
 
@@ -459,7 +466,7 @@ static JoystickImpl *alloc_device(REFGUID rguid, IDirectInputImpl *dinput, unsig
     newDevice->joyfd       = -1;
     newDevice->joydev = joydev;
     newDevice->generic.name        = newDevice->joydev->name;
-    list_init(&newDevice->ff_effects);
+    list_init(&newDevice->generic.ff_effects);
 #ifdef HAVE_STRUCT_FF_EFFECT_DIRECTION
     newDevice->ff_state    = FF_STATUS_STOPPED;
 #endif
@@ -867,63 +874,35 @@ static void CDECL unix_joystick_poll(struct unix_joystick *ptr)
 /****************************************************************************** 
   *	CreateEffect - Create a new FF effect with the specified params
   */
-static HRESULT WINAPI JoystickWImpl_CreateEffect(LPDIRECTINPUTDEVICE8W iface, REFGUID rguid,
-                                                 LPCDIEFFECT lpeff, LPDIRECTINPUTEFFECT *ppdef,
-                                                 LPUNKNOWN pUnkOuter)
+static HRESULT CDECL unix_joystick_create_effect(struct unix_joystick *ptr, REFGUID guid, const DIEFFECT *effect,
+        struct list *entry, IDirectInputEffect **out)
 {
-#ifdef HAVE_STRUCT_FF_EFFECT_DIRECTION
-    effect_list_item* new_effect = NULL;
     HRESULT retval = DI_OK;
-#endif
-
-    JoystickImpl* This = impl_from_IDirectInputDevice8W(iface);
-    TRACE("(this=%p,%p,%p,%p,%p)\n", This, rguid, lpeff, ppdef, pUnkOuter);
+    JoystickImpl* This = impl_from_unix_joystick(ptr);
+    TRACE("(this=%p,%p,%p,%p,%p)\n", This, guid, effect, entry, out);
 
-    *ppdef = NULL;
+    *out = NULL;
     if (!This->joydev->has_ff)
     {
         TRACE("No force feedback support\n");
         return DIERR_UNSUPPORTED;
     }
 
-#ifndef HAVE_STRUCT_FF_EFFECT_DIRECTION
-    TRACE("not available (compiled w/o force feedback support)\n");
-    return DIERR_UNSUPPORTED;
-#else
-
-    if (!(new_effect = HeapAlloc(GetProcessHeap(), 0, sizeof(*new_effect))))
-        return DIERR_OUTOFMEMORY;
+    retval = linuxinput_create_effect(&This->joyfd, guid, entry, out);
+    if (retval != DI_OK) return retval;
 
-    retval = linuxinput_create_effect(&This->joyfd, rguid, &new_effect->entry, &new_effect->ref);
-    if (retval != DI_OK)
+    if (effect != NULL)
     {
-        HeapFree(GetProcessHeap(), 0, new_effect);
-        return retval;
-    }
-
-    if (lpeff != NULL)
-    {
-        retval = IDirectInputEffect_SetParameters(new_effect->ref, lpeff,
+        retval = IDirectInputEffect_SetParameters(*out, effect,
             DIEP_AXES | DIEP_DIRECTION | DIEP_DURATION | DIEP_ENVELOPE |
             DIEP_GAIN | DIEP_SAMPLEPERIOD | DIEP_STARTDELAY | DIEP_TRIGGERBUTTON |
             DIEP_TRIGGERREPEATINTERVAL | DIEP_TYPESPECIFICPARAMS);
 
         if (retval != DI_OK && retval != DI_DOWNLOADSKIPPED)
-        {
-            HeapFree(GetProcessHeap(), 0, new_effect);
             return retval;
-        }
     }
 
-    list_add_tail(&This->ff_effects, &new_effect->entry);
-    *ppdef = new_effect->ref;
-
-    if (pUnkOuter != NULL)
-	FIXME("Interface aggregation not implemented.\n");
-
     return DI_OK;
-
-#endif /* HAVE_STRUCT_FF_EFFECT_DIRECTION */
 }
 
 /*******************************************************************************
@@ -1063,7 +1042,7 @@ static HRESULT WINAPI JoystickWImpl_SendForceFeedbackCommand(LPDIRECTINPUTDEVICE
         effect_list_item *itr;
 
         /* Stop all effects */
-        LIST_FOR_EACH_ENTRY(itr, &This->ff_effects, effect_list_item, entry)
+        LIST_FOR_EACH_ENTRY(itr, &This->generic.ff_effects, effect_list_item, entry)
             IDirectInputEffect_Stop(itr->ref);
         break;
     }
@@ -1073,7 +1052,7 @@ static HRESULT WINAPI JoystickWImpl_SendForceFeedbackCommand(LPDIRECTINPUTDEVICE
         effect_list_item *itr;
 
         /* Stop and unload all effects. It is not true that effects are released */
-        LIST_FOR_EACH_ENTRY(itr, &This->ff_effects, effect_list_item, entry)
+        LIST_FOR_EACH_ENTRY(itr, &This->generic.ff_effects, effect_list_item, entry)
         {
             IDirectInputEffect_Stop(itr->ref);
             IDirectInputEffect_Unload(itr->ref);
@@ -1100,32 +1079,6 @@ static HRESULT WINAPI JoystickWImpl_SendForceFeedbackCommand(LPDIRECTINPUTDEVICE
 #endif
 }
 
-/*******************************************************************************
- *      EnumCreatedEffectObjects - Enumerate all the effects that have been
- *		created for this device.
- */
-static HRESULT WINAPI JoystickWImpl_EnumCreatedEffectObjects(LPDIRECTINPUTDEVICE8W iface,
-                                                             LPDIENUMCREATEDEFFECTOBJECTSCALLBACK lpCallback,
-                                                             LPVOID pvRef, DWORD dwFlags)
-{
-    /* this function is safe to call on non-ff-enabled builds */
-    JoystickImpl* This = impl_from_IDirectInputDevice8W(iface);
-    effect_list_item *itr, *ptr;
-
-    TRACE("(this=%p,%p,%p,%d)\n", This, lpCallback, pvRef, dwFlags);
-
-    if (!lpCallback)
-	return DIERR_INVALIDPARAM;
-
-    if (dwFlags != 0)
-	FIXME("Flags specified, but no flags exist yet (DX9)!\n");
-
-    LIST_FOR_EACH_ENTRY_SAFE(itr, ptr, &This->ff_effects, effect_list_item, entry)
-        (*lpCallback)(itr->ref, pvRef);
-
-    return DI_OK;
-}
-
 static const IDirectInputDevice8WVtbl JoystickWvt =
 {
     IDirectInputDevice2WImpl_QueryInterface,
@@ -1146,12 +1099,12 @@ static const IDirectInputDevice8WVtbl JoystickWvt =
     IDirectInputDevice2WImpl_GetDeviceInfo,
     IDirectInputDevice2WImpl_RunControlPanel,
     IDirectInputDevice2WImpl_Initialize,
-    JoystickWImpl_CreateEffect,
+    JoystickWGenericImpl_CreateEffect,
     JoystickWImpl_EnumEffects,
     JoystickWImpl_GetEffectInfo,
     JoystickWImpl_GetForceFeedbackState,
     JoystickWImpl_SendForceFeedbackCommand,
-    JoystickWImpl_EnumCreatedEffectObjects,
+    JoystickWGenericImpl_EnumCreatedEffectObjects,
     IDirectInputDevice2WImpl_Escape,
     JoystickWGenericImpl_Poll,
     IDirectInputDevice2WImpl_SendDeviceData,
diff --git a/dlls/dinput/joystick_osx.c b/dlls/dinput/joystick_osx.c
index f129b666b2f..079063fd35f 100644
--- a/dlls/dinput/joystick_osx.c
+++ b/dlls/dinput/joystick_osx.c
@@ -110,7 +110,6 @@ struct JoystickImpl
     CFArrayRef             elements;
     ObjProps               **propmap;
     FFDeviceObjectReference ff;
-    struct list effects;
 };
 
 static inline JoystickImpl *impl_from_IDirectInputDevice8W(IDirectInputDevice8W *iface)
@@ -946,12 +945,16 @@ static void CDECL unix_joystick_poll(struct unix_joystick *ptr)
 static HRESULT CDECL unix_joystick_ff_set_autocenter(struct unix_joystick *ptr, DWORD value);
 static HRESULT CDECL unix_joystick_ff_set_gain(struct unix_joystick *ptr, DWORD value);
 
+static HRESULT CDECL unix_joystick_create_effect(struct unix_joystick *ptr, REFGUID guid, const DIEFFECT *params,
+        struct list *entry, IDirectInputEffect **out);
+
 static const struct unix_joystick_vtbl unix_joystick_vtbl =
 {
     NULL,
     NULL,
     unix_joystick_ff_set_autocenter,
     unix_joystick_ff_set_gain,
+    unix_joystick_create_effect,
     unix_joystick_poll,
 };
 
@@ -1107,7 +1110,7 @@ static HRESULT alloc_device(REFGUID rguid, IDirectInputImpl *dinput,
     newDevice->generic.name = HeapAlloc(GetProcessHeap(),0,strlen(name) + 1);
     strcpy(newDevice->generic.name, name);
 
-    list_init(&newDevice->effects);
+    list_init(&newDevice->generic.ff_effects);
     if(get_ff(device, &newDevice->ff) == S_OK){
         newDevice->generic.devcaps.dwFlags |= DIDC_FORCEFEEDBACK;
 
@@ -1345,16 +1348,15 @@ static CFUUIDRef effect_win_to_mac(const GUID *effect)
     return 0;
 }
 
-static HRESULT WINAPI JoystickWImpl_CreateEffect(IDirectInputDevice8W *iface,
-        const GUID *type, const DIEFFECT *params, IDirectInputEffect **out,
-        IUnknown *outer)
+static HRESULT CDECL unix_joystick_create_effect(struct unix_joystick *ptr, REFGUID guid, const DIEFFECT *params,
+        struct list *entry, IDirectInputEffect **out)
 {
-    JoystickImpl *This = impl_from_IDirectInputDevice8W(iface);
+    JoystickImpl *This = impl_from_unix_joystick(ptr);
     EffectImpl *effect;
     HRESULT hr;
 
-    TRACE("(%p)->(%s %p %p %p)\n", This, debugstr_guid(type), params, out, outer);
-    dump_DIEFFECT(params, type, 0);
+    TRACE("(%p)->(%s %p %p %p)\n", This, debugstr_guid(guid), params, entry, out);
+    dump_DIEFFECT(params, guid, 0);
 
     if(!This->ff){
         TRACE("No force feedback support\n");
@@ -1362,25 +1364,21 @@ static HRESULT WINAPI JoystickWImpl_CreateEffect(IDirectInputDevice8W *iface,
         return DIERR_UNSUPPORTED;
     }
 
-    if(outer)
-        WARN("aggregation not implemented\n");
-
     effect = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*This));
     effect->IDirectInputEffect_iface.lpVtbl = &EffectVtbl;
     effect->ref = 1;
-    effect->guid = *type;
+    effect->guid = *guid;
     effect->device = This;
 
     /* Mac's FFEFFECT and Win's DIEFFECT are binary identical. */
     hr = osx_to_win32_hresult(FFDeviceCreateEffect(This->ff,
-                effect_win_to_mac(type), (FFEFFECT*)params, &effect->effect));
+                effect_win_to_mac(guid), (FFEFFECT*)params, &effect->effect));
     if(FAILED(hr)){
         WARN("FFDeviceCreateEffect failed: %08x\n", hr);
         HeapFree(GetProcessHeap(), 0, effect);
         return hr;
     }
 
-    list_add_tail(&This->effects, &effect->entry);
     *out = &effect->IDirectInputEffect_iface;
 
     TRACE("allocated effect: %p\n", effect);
@@ -1435,12 +1433,12 @@ static const IDirectInputDevice8WVtbl JoystickWvt =
     IDirectInputDevice2WImpl_GetDeviceInfo,
     IDirectInputDevice2WImpl_RunControlPanel,
     IDirectInputDevice2WImpl_Initialize,
-    JoystickWImpl_CreateEffect,
+    JoystickWGenericImpl_CreateEffect,
     IDirectInputDevice2WImpl_EnumEffects,
     IDirectInputDevice2WImpl_GetEffectInfo,
     IDirectInputDevice2WImpl_GetForceFeedbackState,
     JoystickWImpl_SendForceFeedbackCommand,
-    IDirectInputDevice2WImpl_EnumCreatedEffectObjects,
+    JoystickWGenericImpl_EnumCreatedEffectObjects,
     IDirectInputDevice2WImpl_Escape,
     JoystickWGenericImpl_Poll,
     IDirectInputDevice2WImpl_SendDeviceData,
diff --git a/dlls/dinput/joystick_private.h b/dlls/dinput/joystick_private.h
index c7d1669fe1f..48ab9a42f38 100644
--- a/dlls/dinput/joystick_private.h
+++ b/dlls/dinput/joystick_private.h
@@ -43,6 +43,8 @@ struct unix_joystick_vtbl
     HRESULT (CDECL *ff_set_autocenter)(struct unix_joystick *ptr, DWORD value);
     HRESULT (CDECL *ff_set_gain)(struct unix_joystick *ptr, DWORD value);
 
+    HRESULT (CDECL *create_effect)(struct unix_joystick *ptr, REFGUID guid, const DIEFFECT *effect, struct list *entry, IDirectInputEffect **out);
+
     void (CDECL *poll)(struct unix_joystick *ptr);
 };
 
@@ -62,6 +64,7 @@ typedef struct JoystickGenericImpl
 
     DWORD ff_autocenter;
     DWORD ff_gain;
+    struct list ff_effects;
 } JoystickGenericImpl;
 
 LONG joystick_map_axis(ObjProps *props, int val) DECLSPEC_HIDDEN;
@@ -86,6 +89,12 @@ HRESULT WINAPI JoystickWGenericImpl_Acquire(LPDIRECTINPUTDEVICE8W iface) DECLSPE
 
 HRESULT WINAPI JoystickWGenericImpl_Unacquire(LPDIRECTINPUTDEVICE8W iface) DECLSPEC_HIDDEN;
 
+HRESULT WINAPI JoystickWGenericImpl_CreateEffect(LPDIRECTINPUTDEVICE8W iface, REFGUID rguid, LPCDIEFFECT lpeff,
+        LPDIRECTINPUTEFFECT *ppdef, LPUNKNOWN pUnkOuter) DECLSPEC_HIDDEN;
+
+HRESULT WINAPI JoystickWGenericImpl_EnumCreatedEffectObjects(LPDIRECTINPUTDEVICE8W iface,
+        LPDIENUMCREATEDEFFECTOBJECTSCALLBACK lpCallback, LPVOID pvRef, DWORD dwFlags) DECLSPEC_HIDDEN;
+
 HRESULT WINAPI JoystickWGenericImpl_Poll(LPDIRECTINPUTDEVICE8W iface) DECLSPEC_HIDDEN;
 
 HRESULT WINAPI JoystickWGenericImpl_GetDeviceState(LPDIRECTINPUTDEVICE8W iface, DWORD len, LPVOID ptr) DECLSPEC_HIDDEN;
-- 
2.28.0

>From 77c13c2bf2cfe8ddf0b4cb453b1f301903afbbf8 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?R=C3=A9mi=20Bernon?= <rbernon@codeweavers.com>
Date: Mon, 5 Oct 2020 23:29:20 +0200
Subject: [PATCH 18/39] dinput: Use the unix vtable for
 SendForceFeedbackCommand.

---
 dlls/dinput/joystick.c            | 30 ++++++++++++++++++++++++++
 dlls/dinput/joystick_linux.c      |  1 +
 dlls/dinput/joystick_linuxinput.c | 35 ++++++++-----------------------
 dlls/dinput/joystick_osx.c        |  9 ++++----
 dlls/dinput/joystick_private.h    |  3 +++
 5 files changed, 48 insertions(+), 30 deletions(-)

diff --git a/dlls/dinput/joystick.c b/dlls/dinput/joystick.c
index d80dd7d5caf..05ed7f8da3d 100644
--- a/dlls/dinput/joystick.c
+++ b/dlls/dinput/joystick.c
@@ -779,6 +779,36 @@ HRESULT WINAPI JoystickWGenericImpl_EnumCreatedEffectObjects(LPDIRECTINPUTDEVICE
     return DI_OK;
 }
 
+HRESULT WINAPI JoystickWGenericImpl_SendForceFeedbackCommand(LPDIRECTINPUTDEVICE8W iface, DWORD dwFlags)
+{
+    JoystickGenericImpl *This = impl_from_IDirectInputDevice8W(iface);
+    effect_list_item *itr;
+
+    TRACE("(this=%p,%d)\n", This, dwFlags);
+
+    if (!This->unix_funcs->create_effect) return DIERR_UNSUPPORTED;
+
+    switch (dwFlags)
+    {
+    case DISFFC_STOPALL:
+        LIST_FOR_EACH_ENTRY(itr, &This->ff_effects, effect_list_item, entry)
+            IDirectInputEffect_Stop(itr->ref);
+        break;
+    case DISFFC_RESET:
+        LIST_FOR_EACH_ENTRY(itr, &This->ff_effects, effect_list_item, entry)
+        {
+            IDirectInputEffect_Stop(itr->ref);
+            IDirectInputEffect_Unload(itr->ref);
+        }
+        break;
+    default:
+        break;
+    }
+
+    if (!This->unix_funcs->ff_send_cmd) return DI_OK;
+    return This->unix_funcs->ff_send_cmd(This->unix_ptr, dwFlags);
+}
+
 HRESULT WINAPI JoystickWGenericImpl_Poll(LPDIRECTINPUTDEVICE8W iface)
 {
     JoystickGenericImpl *This = impl_from_IDirectInputDevice8W(iface);
diff --git a/dlls/dinput/joystick_linux.c b/dlls/dinput/joystick_linux.c
index 615d9432718..5220cb2cf5e 100644
--- a/dlls/dinput/joystick_linux.c
+++ b/dlls/dinput/joystick_linux.c
@@ -145,6 +145,7 @@ static const struct unix_joystick_vtbl unix_joystick_vtbl =
     NULL,
     NULL,
     NULL,
+    NULL,
     unix_joystick_poll,
 };
 
diff --git a/dlls/dinput/joystick_linuxinput.c b/dlls/dinput/joystick_linuxinput.c
index 92985b937db..d2075099ac0 100644
--- a/dlls/dinput/joystick_linuxinput.c
+++ b/dlls/dinput/joystick_linuxinput.c
@@ -162,6 +162,7 @@ static HRESULT CDECL unix_joystick_unacquire(struct unix_joystick *ptr);
 
 static HRESULT CDECL unix_joystick_ff_set_autocenter(struct unix_joystick *ptr, DWORD value);
 static HRESULT CDECL unix_joystick_ff_set_gain(struct unix_joystick *ptr, DWORD value);
+static HRESULT CDECL unix_joystick_ff_send_cmd(struct unix_joystick *ptr, DWORD flags);
 
 static HRESULT CDECL unix_joystick_create_effect(struct unix_joystick *ptr, REFGUID guid, const DIEFFECT *effect,
         struct list *entry, IDirectInputEffect **out);
@@ -172,6 +173,7 @@ static const struct unix_joystick_vtbl unix_joystick_vtbl =
     unix_joystick_unacquire,
     unix_joystick_ff_set_autocenter,
     unix_joystick_ff_set_gain,
+    unix_joystick_ff_send_cmd,
 #ifdef HAVE_STRUCT_FF_EFFECT_DIRECTION
     unix_joystick_create_effect,
 #else
@@ -1029,48 +1031,29 @@ static HRESULT WINAPI JoystickWImpl_GetForceFeedbackState(LPDIRECTINPUTDEVICE8W
 /*******************************************************************************
  *      SendForceFeedbackCommand - Send a command to the device's FF system
  */
-static HRESULT WINAPI JoystickWImpl_SendForceFeedbackCommand(LPDIRECTINPUTDEVICE8W iface, DWORD dwFlags)
+static HRESULT CDECL unix_joystick_ff_send_cmd(struct unix_joystick *ptr, DWORD flags)
 {
-    JoystickImpl* This = impl_from_IDirectInputDevice8W(iface);
-    TRACE("(this=%p,%d)\n", This, dwFlags);
+    JoystickImpl* This = impl_from_unix_joystick(ptr);
+
+    TRACE("(this=%p,%d)\n", This, flags);
 
 #ifdef HAVE_STRUCT_FF_EFFECT_DIRECTION
-    switch (dwFlags)
+    switch (flags)
     {
     case DISFFC_STOPALL:
-    {
-        effect_list_item *itr;
-
-        /* Stop all effects */
-        LIST_FOR_EACH_ENTRY(itr, &This->generic.ff_effects, effect_list_item, entry)
-            IDirectInputEffect_Stop(itr->ref);
         break;
-    }
-
     case DISFFC_RESET:
-    {
-        effect_list_item *itr;
-
-        /* Stop and unload all effects. It is not true that effects are released */
-        LIST_FOR_EACH_ENTRY(itr, &This->generic.ff_effects, effect_list_item, entry)
-        {
-            IDirectInputEffect_Stop(itr->ref);
-            IDirectInputEffect_Unload(itr->ref);
-        }
         break;
-    }
     case DISFFC_PAUSE:
     case DISFFC_CONTINUE:
         FIXME("No support for Pause or Continue in linux\n");
         break;
-
     case DISFFC_SETACTUATORSOFF:
     case DISFFC_SETACTUATORSON:
         FIXME("No direct actuator control in linux\n");
         break;
-
     default:
-        WARN("Unknown Force Feedback Command %u!\n", dwFlags);
+        WARN("Unknown Force Feedback Command %u!\n", flags);
         return DIERR_INVALIDPARAM;
     }
     return DI_OK;
@@ -1103,7 +1086,7 @@ static const IDirectInputDevice8WVtbl JoystickWvt =
     JoystickWImpl_EnumEffects,
     JoystickWImpl_GetEffectInfo,
     JoystickWImpl_GetForceFeedbackState,
-    JoystickWImpl_SendForceFeedbackCommand,
+    JoystickWGenericImpl_SendForceFeedbackCommand,
     JoystickWGenericImpl_EnumCreatedEffectObjects,
     IDirectInputDevice2WImpl_Escape,
     JoystickWGenericImpl_Poll,
diff --git a/dlls/dinput/joystick_osx.c b/dlls/dinput/joystick_osx.c
index 079063fd35f..c6779321673 100644
--- a/dlls/dinput/joystick_osx.c
+++ b/dlls/dinput/joystick_osx.c
@@ -944,6 +944,7 @@ static void CDECL unix_joystick_poll(struct unix_joystick *ptr)
 
 static HRESULT CDECL unix_joystick_ff_set_autocenter(struct unix_joystick *ptr, DWORD value);
 static HRESULT CDECL unix_joystick_ff_set_gain(struct unix_joystick *ptr, DWORD value);
+static HRESULT CDECL unix_joystick_ff_send_cmd(struct unix_joystick *ptr, DWORD flags);
 
 static HRESULT CDECL unix_joystick_create_effect(struct unix_joystick *ptr, REFGUID guid, const DIEFFECT *params,
         struct list *entry, IDirectInputEffect **out);
@@ -954,6 +955,7 @@ static const struct unix_joystick_vtbl unix_joystick_vtbl =
     NULL,
     unix_joystick_ff_set_autocenter,
     unix_joystick_ff_set_gain,
+    unix_joystick_ff_send_cmd,
     unix_joystick_create_effect,
     unix_joystick_poll,
 };
@@ -1386,10 +1388,9 @@ static HRESULT CDECL unix_joystick_create_effect(struct unix_joystick *ptr, REFG
     return S_OK;
 }
 
-static HRESULT WINAPI JoystickWImpl_SendForceFeedbackCommand(IDirectInputDevice8W *iface,
-        DWORD flags)
+static HRESULT CDECL unix_joystick_ff_send_cmd(struct unix_joystick *ptr, DWORD flags)
 {
-    JoystickImpl *This = impl_from_IDirectInputDevice8W(iface);
+    JoystickImpl *This = impl_from_unix_joystick(ptr);
     HRESULT hr;
 
     TRACE("%p 0x%x\n", This, flags);
@@ -1437,7 +1438,7 @@ static const IDirectInputDevice8WVtbl JoystickWvt =
     IDirectInputDevice2WImpl_EnumEffects,
     IDirectInputDevice2WImpl_GetEffectInfo,
     IDirectInputDevice2WImpl_GetForceFeedbackState,
-    JoystickWImpl_SendForceFeedbackCommand,
+    JoystickWGenericImpl_SendForceFeedbackCommand,
     JoystickWGenericImpl_EnumCreatedEffectObjects,
     IDirectInputDevice2WImpl_Escape,
     JoystickWGenericImpl_Poll,
diff --git a/dlls/dinput/joystick_private.h b/dlls/dinput/joystick_private.h
index 48ab9a42f38..3bc718a55ec 100644
--- a/dlls/dinput/joystick_private.h
+++ b/dlls/dinput/joystick_private.h
@@ -42,6 +42,7 @@ struct unix_joystick_vtbl
 
     HRESULT (CDECL *ff_set_autocenter)(struct unix_joystick *ptr, DWORD value);
     HRESULT (CDECL *ff_set_gain)(struct unix_joystick *ptr, DWORD value);
+    HRESULT (CDECL *ff_send_cmd)(struct unix_joystick *ptr, DWORD flags);
 
     HRESULT (CDECL *create_effect)(struct unix_joystick *ptr, REFGUID guid, const DIEFFECT *effect, struct list *entry, IDirectInputEffect **out);
 
@@ -95,6 +96,8 @@ HRESULT WINAPI JoystickWGenericImpl_CreateEffect(LPDIRECTINPUTDEVICE8W iface, RE
 HRESULT WINAPI JoystickWGenericImpl_EnumCreatedEffectObjects(LPDIRECTINPUTDEVICE8W iface,
         LPDIENUMCREATEDEFFECTOBJECTSCALLBACK lpCallback, LPVOID pvRef, DWORD dwFlags) DECLSPEC_HIDDEN;
 
+HRESULT WINAPI JoystickWGenericImpl_SendForceFeedbackCommand(LPDIRECTINPUTDEVICE8W iface, DWORD dwFlags) DECLSPEC_HIDDEN;
+
 HRESULT WINAPI JoystickWGenericImpl_Poll(LPDIRECTINPUTDEVICE8W iface) DECLSPEC_HIDDEN;
 
 HRESULT WINAPI JoystickWGenericImpl_GetDeviceState(LPDIRECTINPUTDEVICE8W iface, DWORD len, LPVOID ptr) DECLSPEC_HIDDEN;
-- 
2.28.0

>From 7bbfaf68bf085ba0129c2a44c00bbb40292cc6a5 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?R=C3=A9mi=20Bernon?= <rbernon@codeweavers.com>
Date: Mon, 5 Oct 2020 23:30:45 +0200
Subject: [PATCH 19/39] dinput: Use the unix vtable for GetForceFeedbackState.

---
 dlls/dinput/joystick.c            | 10 ++++++++++
 dlls/dinput/joystick_linux.c      |  1 +
 dlls/dinput/joystick_linuxinput.c | 15 ++++++++-------
 dlls/dinput/joystick_osx.c        |  1 +
 dlls/dinput/joystick_private.h    |  3 +++
 5 files changed, 23 insertions(+), 7 deletions(-)

diff --git a/dlls/dinput/joystick.c b/dlls/dinput/joystick.c
index 05ed7f8da3d..f1ec15aceee 100644
--- a/dlls/dinput/joystick.c
+++ b/dlls/dinput/joystick.c
@@ -779,6 +779,16 @@ HRESULT WINAPI JoystickWGenericImpl_EnumCreatedEffectObjects(LPDIRECTINPUTDEVICE
     return DI_OK;
 }
 
+HRESULT WINAPI JoystickWGenericImpl_GetForceFeedbackState(LPDIRECTINPUTDEVICE8W iface, LPDWORD pdwOut)
+{
+    JoystickGenericImpl *This = impl_from_IDirectInputDevice8W(iface);
+
+    TRACE("(this=%p,%p)\n", This, pdwOut);
+
+    if (!This->unix_funcs->ff_get_state) return DIERR_UNSUPPORTED;
+    return This->unix_funcs->ff_get_state(This->unix_ptr, pdwOut);
+}
+
 HRESULT WINAPI JoystickWGenericImpl_SendForceFeedbackCommand(LPDIRECTINPUTDEVICE8W iface, DWORD dwFlags)
 {
     JoystickGenericImpl *This = impl_from_IDirectInputDevice8W(iface);
diff --git a/dlls/dinput/joystick_linux.c b/dlls/dinput/joystick_linux.c
index 5220cb2cf5e..59d91117a94 100644
--- a/dlls/dinput/joystick_linux.c
+++ b/dlls/dinput/joystick_linux.c
@@ -146,6 +146,7 @@ static const struct unix_joystick_vtbl unix_joystick_vtbl =
     NULL,
     NULL,
     NULL,
+    NULL,
     unix_joystick_poll,
 };
 
diff --git a/dlls/dinput/joystick_linuxinput.c b/dlls/dinput/joystick_linuxinput.c
index d2075099ac0..a4d28415d17 100644
--- a/dlls/dinput/joystick_linuxinput.c
+++ b/dlls/dinput/joystick_linuxinput.c
@@ -162,6 +162,7 @@ static HRESULT CDECL unix_joystick_unacquire(struct unix_joystick *ptr);
 
 static HRESULT CDECL unix_joystick_ff_set_autocenter(struct unix_joystick *ptr, DWORD value);
 static HRESULT CDECL unix_joystick_ff_set_gain(struct unix_joystick *ptr, DWORD value);
+static HRESULT CDECL unix_joystick_ff_get_state(struct unix_joystick *ptr, DWORD *state);
 static HRESULT CDECL unix_joystick_ff_send_cmd(struct unix_joystick *ptr, DWORD flags);
 
 static HRESULT CDECL unix_joystick_create_effect(struct unix_joystick *ptr, REFGUID guid, const DIEFFECT *effect,
@@ -173,6 +174,7 @@ static const struct unix_joystick_vtbl unix_joystick_vtbl =
     unix_joystick_unacquire,
     unix_joystick_ff_set_autocenter,
     unix_joystick_ff_set_gain,
+    unix_joystick_ff_get_state,
     unix_joystick_ff_send_cmd,
 #ifdef HAVE_STRUCT_FF_EFFECT_DIRECTION
     unix_joystick_create_effect,
@@ -1011,18 +1013,17 @@ static HRESULT WINAPI JoystickWImpl_GetEffectInfo(LPDIRECTINPUTDEVICE8W iface,
 /*******************************************************************************
  *      GetForceFeedbackState - Get information about the device's FF state 
  */
-static HRESULT WINAPI JoystickWImpl_GetForceFeedbackState(LPDIRECTINPUTDEVICE8W iface, LPDWORD pdwOut)
+static HRESULT CDECL unix_joystick_ff_get_state(struct unix_joystick *ptr, DWORD *state)
 {
-    JoystickImpl* This = impl_from_IDirectInputDevice8W(iface);
+    JoystickImpl* This = impl_from_unix_joystick(ptr);
 
-    TRACE("(this=%p,%p)\n", This, pdwOut);
+    TRACE("(this=%p,%p)\n", This, state);
 
-    (*pdwOut) = 0;
+    (*state) = 0;
 
 #ifdef HAVE_STRUCT_FF_EFFECT_DIRECTION
     /* DIGFFS_STOPPED is the only mandatory flag to report */
-    if (This->ff_state == FF_STATUS_STOPPED)
-	(*pdwOut) |= DIGFFS_STOPPED;
+    if (This->ff_state == FF_STATUS_STOPPED) (*state) |= DIGFFS_STOPPED;
 #endif
 
     return DI_OK;
@@ -1085,7 +1086,7 @@ static const IDirectInputDevice8WVtbl JoystickWvt =
     JoystickWGenericImpl_CreateEffect,
     JoystickWImpl_EnumEffects,
     JoystickWImpl_GetEffectInfo,
-    JoystickWImpl_GetForceFeedbackState,
+    JoystickWGenericImpl_GetForceFeedbackState,
     JoystickWGenericImpl_SendForceFeedbackCommand,
     JoystickWGenericImpl_EnumCreatedEffectObjects,
     IDirectInputDevice2WImpl_Escape,
diff --git a/dlls/dinput/joystick_osx.c b/dlls/dinput/joystick_osx.c
index c6779321673..56f9abb76a8 100644
--- a/dlls/dinput/joystick_osx.c
+++ b/dlls/dinput/joystick_osx.c
@@ -955,6 +955,7 @@ static const struct unix_joystick_vtbl unix_joystick_vtbl =
     NULL,
     unix_joystick_ff_set_autocenter,
     unix_joystick_ff_set_gain,
+    NULL,
     unix_joystick_ff_send_cmd,
     unix_joystick_create_effect,
     unix_joystick_poll,
diff --git a/dlls/dinput/joystick_private.h b/dlls/dinput/joystick_private.h
index 3bc718a55ec..b8239438a2b 100644
--- a/dlls/dinput/joystick_private.h
+++ b/dlls/dinput/joystick_private.h
@@ -42,6 +42,7 @@ struct unix_joystick_vtbl
 
     HRESULT (CDECL *ff_set_autocenter)(struct unix_joystick *ptr, DWORD value);
     HRESULT (CDECL *ff_set_gain)(struct unix_joystick *ptr, DWORD value);
+    HRESULT (CDECL *ff_get_state)(struct unix_joystick *ptr, DWORD *state);
     HRESULT (CDECL *ff_send_cmd)(struct unix_joystick *ptr, DWORD flags);
 
     HRESULT (CDECL *create_effect)(struct unix_joystick *ptr, REFGUID guid, const DIEFFECT *effect, struct list *entry, IDirectInputEffect **out);
@@ -96,6 +97,8 @@ HRESULT WINAPI JoystickWGenericImpl_CreateEffect(LPDIRECTINPUTDEVICE8W iface, RE
 HRESULT WINAPI JoystickWGenericImpl_EnumCreatedEffectObjects(LPDIRECTINPUTDEVICE8W iface,
         LPDIENUMCREATEDEFFECTOBJECTSCALLBACK lpCallback, LPVOID pvRef, DWORD dwFlags) DECLSPEC_HIDDEN;
 
+HRESULT WINAPI JoystickWGenericImpl_GetForceFeedbackState(LPDIRECTINPUTDEVICE8W iface, LPDWORD pdwOut) DECLSPEC_HIDDEN;
+
 HRESULT WINAPI JoystickWGenericImpl_SendForceFeedbackCommand(LPDIRECTINPUTDEVICE8W iface, DWORD dwFlags) DECLSPEC_HIDDEN;
 
 HRESULT WINAPI JoystickWGenericImpl_Poll(LPDIRECTINPUTDEVICE8W iface) DECLSPEC_HIDDEN;
-- 
2.28.0

>From 797345a7b5eda23bda94420d4c0bd7206102c24f Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?R=C3=A9mi=20Bernon?= <rbernon@codeweavers.com>
Date: Mon, 5 Oct 2020 23:32:33 +0200
Subject: [PATCH 20/39] dinput: Use the unix vtable for GetEffectInfo.

---
 dlls/dinput/effect_linuxinput.c   | 35 -------------------------------
 dlls/dinput/joystick.c            | 21 +++++++++++++++++++
 dlls/dinput/joystick_linux.c      |  1 +
 dlls/dinput/joystick_linuxinput.c | 15 +++++++------
 dlls/dinput/joystick_osx.c        |  1 +
 dlls/dinput/joystick_private.h    |  3 +++
 6 files changed, 33 insertions(+), 43 deletions(-)

diff --git a/dlls/dinput/effect_linuxinput.c b/dlls/dinput/effect_linuxinput.c
index ec4b00b873a..d5daba6daa1 100644
--- a/dlls/dinput/effect_linuxinput.c
+++ b/dlls/dinput/effect_linuxinput.c
@@ -886,41 +886,6 @@ DECLSPEC_HIDDEN HRESULT linuxinput_get_info_A(
     return DI_OK;
 }
 
-DECLSPEC_HIDDEN HRESULT linuxinput_get_info_W(
-	int fd,
-	REFGUID rguid,
-	LPDIEFFECTINFOW info)
-{
-    DWORD type = typeFromGUID(rguid);
-
-    TRACE("(%d, %s, %p) type=%d\n", fd, _dump_dinput_GUID(rguid), info, type);
-
-    if (!info) return E_POINTER;
-
-    if (info->dwSize != sizeof(DIEFFECTINFOW)) return DIERR_INVALIDPARAM;
-
-    info->guid = *rguid;
-
-    info->dwEffType = type;
-    /* the event device API does not support querying for all these things
-     * therefore we assume that we have support for them
-     * that's not as dangerous as it sounds, since drivers are allowed to
-     * ignore parameters they claim to support anyway */
-    info->dwEffType |= DIEFT_DEADBAND | DIEFT_FFATTACK | DIEFT_FFFADE
-                    | DIEFT_POSNEGCOEFFICIENTS | DIEFT_POSNEGSATURATION
-                    | DIEFT_SATURATION | DIEFT_STARTDELAY; 
-
-    /* again, assume we have support for everything */
-    info->dwStaticParams = DIEP_ALLPARAMS;
-    info->dwDynamicParams = info->dwStaticParams;
-
-    /* yes, this is windows behavior (print the GUID_Name for name) */
-    MultiByteToWideChar(CP_ACP, 0, _dump_dinput_GUID(rguid), -1, 
-                        info->tszName, MAX_PATH);
-
-    return DI_OK;
-}
-
 static const IDirectInputEffectVtbl LinuxInputEffectVtbl = {
     LinuxInputEffectImpl_QueryInterface,
     LinuxInputEffectImpl_AddRef,
diff --git a/dlls/dinput/joystick.c b/dlls/dinput/joystick.c
index f1ec15aceee..6d36bdbbbe8 100644
--- a/dlls/dinput/joystick.c
+++ b/dlls/dinput/joystick.c
@@ -739,6 +739,27 @@ HRESULT WINAPI JoystickWGenericImpl_GetProperty(LPDIRECTINPUTDEVICE8W iface, REF
     return DI_OK;
 }
 
+static void dieffectinfo_atow(const DIEFFECTINFOA *dieia, DIEFFECTINFOW *dieiw)
+{
+    dieiw->guid = dieia->guid;
+    dieiw->dwEffType = dieia->dwEffType;
+    dieiw->dwStaticParams = dieia->dwStaticParams;
+    dieiw->dwDynamicParams = dieia->dwDynamicParams;
+    MultiByteToWideChar(CP_ACP, 0, dieia->tszName, -1, dieiw->tszName, sizeof(dieiw->tszName));
+}
+
+HRESULT WINAPI JoystickWGenericImpl_GetEffectInfo(LPDIRECTINPUTDEVICE8W iface, LPDIEFFECTINFOW diei, REFGUID rguid)
+{
+    JoystickGenericImpl *This = impl_from_IDirectInputDevice8W(iface);
+    DIEFFECTINFOA dieia = {sizeof(dieia)};
+    HRESULT hr;
+    TRACE("(this=%p,%p,%s)\n", This, diei, debugstr_guid(rguid));
+    if (!This->unix_funcs->get_effect_info) return DIERR_UNSUPPORTED;
+    hr = This->unix_funcs->get_effect_info(This->unix_ptr, rguid, &dieia);
+    dieffectinfo_atow(&dieia, diei);
+    return hr;
+}
+
 HRESULT WINAPI JoystickWGenericImpl_CreateEffect(LPDIRECTINPUTDEVICE8W iface, REFGUID rguid, LPCDIEFFECT lpeff,
         LPDIRECTINPUTEFFECT *ppdef, LPUNKNOWN pUnkOuter)
 {
diff --git a/dlls/dinput/joystick_linux.c b/dlls/dinput/joystick_linux.c
index 59d91117a94..d8611d72774 100644
--- a/dlls/dinput/joystick_linux.c
+++ b/dlls/dinput/joystick_linux.c
@@ -147,6 +147,7 @@ static const struct unix_joystick_vtbl unix_joystick_vtbl =
     NULL,
     NULL,
     NULL,
+    NULL,
     unix_joystick_poll,
 };
 
diff --git a/dlls/dinput/joystick_linuxinput.c b/dlls/dinput/joystick_linuxinput.c
index a4d28415d17..6b88bec67ef 100644
--- a/dlls/dinput/joystick_linuxinput.c
+++ b/dlls/dinput/joystick_linuxinput.c
@@ -87,7 +87,6 @@ struct wine_input_absinfo {
 /* implemented in effect_linuxinput.c */
 HRESULT linuxinput_create_effect(int* fd, REFGUID rguid, struct list *parent_list_entry, LPDIRECTINPUTEFFECT* peff);
 HRESULT linuxinput_get_info_A(int fd, REFGUID rguid, LPDIEFFECTINFOA info);
-HRESULT linuxinput_get_info_W(int fd, REFGUID rguid, LPDIEFFECTINFOW info);
 
 typedef struct JoystickImpl JoystickImpl;
 static const IDirectInputDevice8WVtbl JoystickWvt;
@@ -165,6 +164,7 @@ static HRESULT CDECL unix_joystick_ff_set_gain(struct unix_joystick *ptr, DWORD
 static HRESULT CDECL unix_joystick_ff_get_state(struct unix_joystick *ptr, DWORD *state);
 static HRESULT CDECL unix_joystick_ff_send_cmd(struct unix_joystick *ptr, DWORD flags);
 
+static HRESULT CDECL unix_joystick_get_effect_info(struct unix_joystick *ptr, REFGUID guid, LPDIEFFECTINFOA diei);
 static HRESULT CDECL unix_joystick_create_effect(struct unix_joystick *ptr, REFGUID guid, const DIEFFECT *effect,
         struct list *entry, IDirectInputEffect **out);
 
@@ -176,6 +176,7 @@ static const struct unix_joystick_vtbl unix_joystick_vtbl =
     unix_joystick_ff_set_gain,
     unix_joystick_ff_get_state,
     unix_joystick_ff_send_cmd,
+    unix_joystick_get_effect_info,
 #ifdef HAVE_STRUCT_FF_EFFECT_DIRECTION
     unix_joystick_create_effect,
 #else
@@ -995,16 +996,14 @@ static HRESULT WINAPI JoystickWImpl_EnumEffects(LPDIRECTINPUTDEVICE8W iface,
 /*******************************************************************************
  *      GetEffectInfo - Get information about a particular effect 
  */
-static HRESULT WINAPI JoystickWImpl_GetEffectInfo(LPDIRECTINPUTDEVICE8W iface,
-                                                  LPDIEFFECTINFOW pdei,
-                                                  REFGUID guid)
+static HRESULT CDECL unix_joystick_get_effect_info(struct unix_joystick *ptr, REFGUID guid, DIEFFECTINFOA *diei)
 {
-    JoystickImpl* This = impl_from_IDirectInputDevice8W(iface);
+    JoystickImpl* This = impl_from_unix_joystick(ptr);
 
-    TRACE("(this=%p,%p,%s)\n", This, pdei, _dump_dinput_GUID(guid));
+    TRACE("(this=%p,%p,%s)\n", This, diei, _dump_dinput_GUID(guid));
 
 #ifdef HAVE_STRUCT_FF_EFFECT_DIRECTION
-    return linuxinput_get_info_W(This->joyfd, guid, pdei);
+    return linuxinput_get_info_A(This->joyfd, guid, diei);
 #else
     return DI_OK;
 #endif
@@ -1085,7 +1084,7 @@ static const IDirectInputDevice8WVtbl JoystickWvt =
     IDirectInputDevice2WImpl_Initialize,
     JoystickWGenericImpl_CreateEffect,
     JoystickWImpl_EnumEffects,
-    JoystickWImpl_GetEffectInfo,
+    JoystickWGenericImpl_GetEffectInfo,
     JoystickWGenericImpl_GetForceFeedbackState,
     JoystickWGenericImpl_SendForceFeedbackCommand,
     JoystickWGenericImpl_EnumCreatedEffectObjects,
diff --git a/dlls/dinput/joystick_osx.c b/dlls/dinput/joystick_osx.c
index 56f9abb76a8..f44ba2c1357 100644
--- a/dlls/dinput/joystick_osx.c
+++ b/dlls/dinput/joystick_osx.c
@@ -957,6 +957,7 @@ static const struct unix_joystick_vtbl unix_joystick_vtbl =
     unix_joystick_ff_set_gain,
     NULL,
     unix_joystick_ff_send_cmd,
+    NULL,
     unix_joystick_create_effect,
     unix_joystick_poll,
 };
diff --git a/dlls/dinput/joystick_private.h b/dlls/dinput/joystick_private.h
index b8239438a2b..f76301a5d17 100644
--- a/dlls/dinput/joystick_private.h
+++ b/dlls/dinput/joystick_private.h
@@ -45,6 +45,7 @@ struct unix_joystick_vtbl
     HRESULT (CDECL *ff_get_state)(struct unix_joystick *ptr, DWORD *state);
     HRESULT (CDECL *ff_send_cmd)(struct unix_joystick *ptr, DWORD flags);
 
+    HRESULT (CDECL *get_effect_info)(struct unix_joystick *ptr, REFGUID guid, DIEFFECTINFOA *diei);
     HRESULT (CDECL *create_effect)(struct unix_joystick *ptr, REFGUID guid, const DIEFFECT *effect, struct list *entry, IDirectInputEffect **out);
 
     void (CDECL *poll)(struct unix_joystick *ptr);
@@ -91,6 +92,8 @@ HRESULT WINAPI JoystickWGenericImpl_Acquire(LPDIRECTINPUTDEVICE8W iface) DECLSPE
 
 HRESULT WINAPI JoystickWGenericImpl_Unacquire(LPDIRECTINPUTDEVICE8W iface) DECLSPEC_HIDDEN;
 
+HRESULT WINAPI JoystickWGenericImpl_GetEffectInfo(LPDIRECTINPUTDEVICE8W iface, LPDIEFFECTINFOW pdei, REFGUID rguid) DECLSPEC_HIDDEN;
+
 HRESULT WINAPI JoystickWGenericImpl_CreateEffect(LPDIRECTINPUTDEVICE8W iface, REFGUID rguid, LPCDIEFFECT lpeff,
         LPDIRECTINPUTEFFECT *ppdef, LPUNKNOWN pUnkOuter) DECLSPEC_HIDDEN;
 
-- 
2.28.0

>From 7235aa8b461b0d177b0291371adf8676d953dd7a Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?R=C3=A9mi=20Bernon?= <rbernon@codeweavers.com>
Date: Mon, 5 Oct 2020 23:34:02 +0200
Subject: [PATCH 21/39] dinput: Use the unix vtable for EnumEffects.

---
 dlls/dinput/joystick.c            |  29 +++++++
 dlls/dinput/joystick_linux.c      |   1 +
 dlls/dinput/joystick_linuxinput.c | 121 ++++++++++++++----------------
 dlls/dinput/joystick_osx.c        |   1 +
 dlls/dinput/joystick_private.h    |   4 +
 5 files changed, 90 insertions(+), 66 deletions(-)

diff --git a/dlls/dinput/joystick.c b/dlls/dinput/joystick.c
index 6d36bdbbbe8..d2fffb4fe5e 100644
--- a/dlls/dinput/joystick.c
+++ b/dlls/dinput/joystick.c
@@ -739,6 +739,35 @@ HRESULT WINAPI JoystickWGenericImpl_GetProperty(LPDIRECTINPUTDEVICE8W iface, REF
     return DI_OK;
 }
 
+HRESULT WINAPI JoystickWGenericImpl_EnumEffects(LPDIRECTINPUTDEVICE8W iface, LPDIENUMEFFECTSCALLBACKW lpCallback,
+        LPVOID pvRef, DWORD dwEffType)
+{
+    JoystickGenericImpl *This = impl_from_IDirectInputDevice8W(iface);
+    DIEFFECTINFOW dei;
+    const GUID **guids;
+    HRESULT hr;
+    DWORD i, count;
+    BOOL acquired = This->base.acquired;
+
+    TRACE("(this=%p,%p,%d)\n", This, pvRef, dwEffType);
+    if (!This->unix_funcs->list_effects) return DI_OK;
+
+    if (FAILED(hr = This->unix_funcs->list_effects(This->unix_ptr, DIEFT_GETTYPE(dwEffType), NULL, 0, &count))) return hr;
+    if (!(guids = HeapAlloc(GetProcessHeap(), 0, sizeof(*guids) * count))) return DIERR_OUTOFMEMORY;
+    if (FAILED(hr = This->unix_funcs->list_effects(This->unix_ptr, DIEFT_GETTYPE(dwEffType), guids, count, &count))) goto done;
+
+    for (i = 0; i < count; ++i)
+    {
+        if (FAILED(hr = IDirectInputDevice8_GetEffectInfo(iface, &dei, guids[i]))) goto done;
+        (*lpCallback)(&dei, pvRef);
+    }
+
+done:
+    HeapFree(GetProcessHeap(), 0, guids);
+    if (!acquired) IDirectInputDevice8_Unacquire(iface);
+    return hr;
+}
+
 static void dieffectinfo_atow(const DIEFFECTINFOA *dieia, DIEFFECTINFOW *dieiw)
 {
     dieiw->guid = dieia->guid;
diff --git a/dlls/dinput/joystick_linux.c b/dlls/dinput/joystick_linux.c
index d8611d72774..9055565a902 100644
--- a/dlls/dinput/joystick_linux.c
+++ b/dlls/dinput/joystick_linux.c
@@ -148,6 +148,7 @@ static const struct unix_joystick_vtbl unix_joystick_vtbl =
     NULL,
     NULL,
     NULL,
+    NULL,
     unix_joystick_poll,
 };
 
diff --git a/dlls/dinput/joystick_linuxinput.c b/dlls/dinput/joystick_linuxinput.c
index 6b88bec67ef..ec5bd7eb157 100644
--- a/dlls/dinput/joystick_linuxinput.c
+++ b/dlls/dinput/joystick_linuxinput.c
@@ -164,6 +164,7 @@ static HRESULT CDECL unix_joystick_ff_set_gain(struct unix_joystick *ptr, DWORD
 static HRESULT CDECL unix_joystick_ff_get_state(struct unix_joystick *ptr, DWORD *state);
 static HRESULT CDECL unix_joystick_ff_send_cmd(struct unix_joystick *ptr, DWORD flags);
 
+static HRESULT CDECL unix_joystick_list_effects(struct unix_joystick *ptr, DWORD type, const GUID **guids, DWORD size, DWORD *count);
 static HRESULT CDECL unix_joystick_get_effect_info(struct unix_joystick *ptr, REFGUID guid, LPDIEFFECTINFOA diei);
 static HRESULT CDECL unix_joystick_create_effect(struct unix_joystick *ptr, REFGUID guid, const DIEFFECT *effect,
         struct list *entry, IDirectInputEffect **out);
@@ -176,6 +177,7 @@ static const struct unix_joystick_vtbl unix_joystick_vtbl =
     unix_joystick_ff_set_gain,
     unix_joystick_ff_get_state,
     unix_joystick_ff_send_cmd,
+    unix_joystick_list_effects,
     unix_joystick_get_effect_info,
 #ifdef HAVE_STRUCT_FF_EFFECT_DIRECTION
     unix_joystick_create_effect,
@@ -913,83 +915,70 @@ static HRESULT CDECL unix_joystick_create_effect(struct unix_joystick *ptr, REFG
 /*******************************************************************************
  *	EnumEffects - Enumerate available FF effects
  */
-static HRESULT WINAPI JoystickWImpl_EnumEffects(LPDIRECTINPUTDEVICE8W iface,
-                                                LPDIENUMEFFECTSCALLBACKW lpCallback,
-                                                LPVOID pvRef,
-                                                DWORD dwEffType)
+static HRESULT CDECL unix_joystick_list_effects(struct unix_joystick *ptr, DWORD type, const GUID **guids, DWORD size, DWORD *count)
 {
-#ifdef HAVE_STRUCT_FF_EFFECT_DIRECTION
-    /* seems silly to duplicate all this code but all the structures and functions
-     * are actually different (A/W) */
-    DIEFFECTINFOW dei; /* feif */
-    DWORD type = DIEFT_GETTYPE(dwEffType);
-    JoystickImpl* This = impl_from_IDirectInputDevice8W(iface);
-    int xfd = This->joyfd;
-
-    TRACE("(this=%p,%p,%d) type=%d fd=%d\n", This, pvRef, dwEffType, type, xfd);
-
-    dei.dwSize = sizeof(DIEFFECTINFOW);          
+    JoystickImpl* This = impl_from_unix_joystick(ptr);
+    DWORD i = 0;
 
-    if ((type == DIEFT_ALL || type == DIEFT_CONSTANTFORCE)
-	&& test_bit(This->joydev->ffbits, FF_CONSTANT)) {
-	IDirectInputDevice8_GetEffectInfo(iface, &dei, &GUID_ConstantForce);
-	(*lpCallback)(&dei, pvRef);
+#ifdef HAVE_STRUCT_FF_EFFECT_DIRECTION
+    if ((type == DIEFT_ALL || type == DIEFT_CONSTANTFORCE) && test_bit(This->joydev->ffbits, FF_CONSTANT))
+    {
+        if (guids && i < size) guids[i++] = &GUID_ConstantForce;
+        else i++;
     }
 
-    if ((type == DIEFT_ALL || type == DIEFT_PERIODIC)
-	&& test_bit(This->joydev->ffbits, FF_PERIODIC)) {
-	if (test_bit(This->joydev->ffbits, FF_SQUARE)) {
-	    IDirectInputDevice8_GetEffectInfo(iface, &dei, &GUID_Square);
-	    (*lpCallback)(&dei, pvRef);
-	}
-	if (test_bit(This->joydev->ffbits, FF_SINE)) {
-            IDirectInputDevice8_GetEffectInfo(iface, &dei, &GUID_Sine);
-	    (*lpCallback)(&dei, pvRef);
-	}
-	if (test_bit(This->joydev->ffbits, FF_TRIANGLE)) {
-	    IDirectInputDevice8_GetEffectInfo(iface, &dei, &GUID_Triangle);
-	    (*lpCallback)(&dei, pvRef);
-	}
-	if (test_bit(This->joydev->ffbits, FF_SAW_UP)) {
-	    IDirectInputDevice8_GetEffectInfo(iface, &dei, &GUID_SawtoothUp);
-	    (*lpCallback)(&dei, pvRef);
-	}
-	if (test_bit(This->joydev->ffbits, FF_SAW_DOWN)) {
-	    IDirectInputDevice8_GetEffectInfo(iface, &dei, &GUID_SawtoothDown);
-	    (*lpCallback)(&dei, pvRef);
-	}
-    } 
+    if ((type == DIEFT_ALL || type == DIEFT_PERIODIC) && test_bit(This->joydev->ffbits, FF_PERIODIC))
+    {
+        if (test_bit(This->joydev->ffbits, FF_SQUARE))
+        {
+            if (guids && i < size) guids[i++] = &GUID_Square;
+            else i++;
+        }
+        if (test_bit(This->joydev->ffbits, FF_SINE)) {
+            if (guids && i < size) guids[i++] = &GUID_Sine;
+            else i++;
+        }
+        if (test_bit(This->joydev->ffbits, FF_TRIANGLE)) {
+            if (guids && i < size) guids[i++] = &GUID_Triangle;
+            else i++;
+        }
+        if (test_bit(This->joydev->ffbits, FF_SAW_UP)) {
+            if (guids && i < size) guids[i++] = &GUID_SawtoothUp;
+            else i++;
+        }
+        if (test_bit(This->joydev->ffbits, FF_SAW_DOWN)) {
+            if (guids && i < size) guids[i++] = &GUID_SawtoothDown;
+            else i++;
+        }
+    }
 
-    if ((type == DIEFT_ALL || type == DIEFT_RAMPFORCE)
-	&& test_bit(This->joydev->ffbits, FF_RAMP)) {
-        IDirectInputDevice8_GetEffectInfo(iface, &dei, &GUID_RampForce);
-        (*lpCallback)(&dei, pvRef);
+    if ((type == DIEFT_ALL || type == DIEFT_RAMPFORCE) && test_bit(This->joydev->ffbits, FF_RAMP))
+    {
+        if (guids && i < size) guids[i++] = &GUID_RampForce;
+        else i++;
     }
 
     if (type == DIEFT_ALL || type == DIEFT_CONDITION) {
 	if (test_bit(This->joydev->ffbits, FF_SPRING)) {
-	    IDirectInputDevice8_GetEffectInfo(iface, &dei, &GUID_Spring);
-	    (*lpCallback)(&dei, pvRef);
-	}
-	if (test_bit(This->joydev->ffbits, FF_DAMPER)) {
-	    IDirectInputDevice8_GetEffectInfo(iface, &dei, &GUID_Damper);
-	    (*lpCallback)(&dei, pvRef);
-	}
-	if (test_bit(This->joydev->ffbits, FF_INERTIA)) {
-	    IDirectInputDevice8_GetEffectInfo(iface, &dei, &GUID_Inertia);
-	    (*lpCallback)(&dei, pvRef);
-	}
-	if (test_bit(This->joydev->ffbits, FF_FRICTION)) {
-	    IDirectInputDevice8_GetEffectInfo(iface, &dei, &GUID_Friction);
-	    (*lpCallback)(&dei, pvRef);
-	}
+            if (guids && i < size) guids[i++] = &GUID_Spring;
+            else i++;
+        }
+        if (test_bit(This->joydev->ffbits, FF_DAMPER)) {
+            if (guids && i < size) guids[i++] = &GUID_Damper;
+            else i++;
+        }
+        if (test_bit(This->joydev->ffbits, FF_INERTIA)) {
+            if (guids && i < size) guids[i++] = &GUID_Inertia;
+            else i++;
+        }
+        if (test_bit(This->joydev->ffbits, FF_FRICTION)) {
+            if (guids && i < size) guids[i++] = &GUID_Friction;
+            else i++;
+        }
     }
-
-    /* return to unacquired state if that's where it was */
-    if (xfd == -1)
-	IDirectInputDevice8_Unacquire(iface);
 #endif
 
+    if (count) *count = i;
     return DI_OK;
 }
 
@@ -1083,7 +1072,7 @@ static const IDirectInputDevice8WVtbl JoystickWvt =
     IDirectInputDevice2WImpl_RunControlPanel,
     IDirectInputDevice2WImpl_Initialize,
     JoystickWGenericImpl_CreateEffect,
-    JoystickWImpl_EnumEffects,
+    JoystickWGenericImpl_EnumEffects,
     JoystickWGenericImpl_GetEffectInfo,
     JoystickWGenericImpl_GetForceFeedbackState,
     JoystickWGenericImpl_SendForceFeedbackCommand,
diff --git a/dlls/dinput/joystick_osx.c b/dlls/dinput/joystick_osx.c
index f44ba2c1357..19c2e2dddf4 100644
--- a/dlls/dinput/joystick_osx.c
+++ b/dlls/dinput/joystick_osx.c
@@ -958,6 +958,7 @@ static const struct unix_joystick_vtbl unix_joystick_vtbl =
     NULL,
     unix_joystick_ff_send_cmd,
     NULL,
+    NULL,
     unix_joystick_create_effect,
     unix_joystick_poll,
 };
diff --git a/dlls/dinput/joystick_private.h b/dlls/dinput/joystick_private.h
index f76301a5d17..e479ea6b480 100644
--- a/dlls/dinput/joystick_private.h
+++ b/dlls/dinput/joystick_private.h
@@ -45,6 +45,7 @@ struct unix_joystick_vtbl
     HRESULT (CDECL *ff_get_state)(struct unix_joystick *ptr, DWORD *state);
     HRESULT (CDECL *ff_send_cmd)(struct unix_joystick *ptr, DWORD flags);
 
+    HRESULT (CDECL *list_effects)(struct unix_joystick *ptr, DWORD type, const GUID **guids, DWORD size, DWORD *count);
     HRESULT (CDECL *get_effect_info)(struct unix_joystick *ptr, REFGUID guid, DIEFFECTINFOA *diei);
     HRESULT (CDECL *create_effect)(struct unix_joystick *ptr, REFGUID guid, const DIEFFECT *effect, struct list *entry, IDirectInputEffect **out);
 
@@ -94,6 +95,9 @@ HRESULT WINAPI JoystickWGenericImpl_Unacquire(LPDIRECTINPUTDEVICE8W iface) DECLS
 
 HRESULT WINAPI JoystickWGenericImpl_GetEffectInfo(LPDIRECTINPUTDEVICE8W iface, LPDIEFFECTINFOW pdei, REFGUID rguid) DECLSPEC_HIDDEN;
 
+HRESULT WINAPI JoystickWGenericImpl_EnumEffects(LPDIRECTINPUTDEVICE8W iface, LPDIENUMEFFECTSCALLBACKW lpCallback,
+        LPVOID pvRef, DWORD dwEffType) DECLSPEC_HIDDEN;
+
 HRESULT WINAPI JoystickWGenericImpl_CreateEffect(LPDIRECTINPUTDEVICE8W iface, REFGUID rguid, LPCDIEFFECT lpeff,
         LPDIRECTINPUTEFFECT *ppdef, LPUNKNOWN pUnkOuter) DECLSPEC_HIDDEN;
 
-- 
2.28.0

>From d721587951564d31a4f7e80d37070432a8214684 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?R=C3=A9mi=20Bernon?= <rbernon@codeweavers.com>
Date: Mon, 5 Oct 2020 23:49:55 +0200
Subject: [PATCH 22/39] dinput: Introduce create_unix_joystick funtion pointer.

---
 dlls/dinput/device.c              |   2 +
 dlls/dinput/dinput_private.h      |   2 +
 dlls/dinput/joystick.c            |  21 ++++++
 dlls/dinput/joystick_linux.c      | 116 ++++++++++++------------------
 dlls/dinput/joystick_linuxinput.c |  96 ++++++++++++-------------
 dlls/dinput/joystick_osx.c        |  88 +++++++++--------------
 dlls/dinput/joystick_private.h    |   2 +
 dlls/dinput/keyboard.c            |   3 +-
 dlls/dinput/mouse.c               |   3 +-
 9 files changed, 157 insertions(+), 176 deletions(-)

diff --git a/dlls/dinput/device.c b/dlls/dinput/device.c
index a2c1b638cfc..af05fdf14f0 100644
--- a/dlls/dinput/device.c
+++ b/dlls/dinput/device.c
@@ -39,6 +39,7 @@
 #include "dinput.h"
 #include "device_private.h"
 #include "dinput_private.h"
+#include "joystick_private.h"
 
 #define WM_WINE_NOTIFY_ACTIVITY WM_USER
 
@@ -1667,6 +1668,7 @@ HRESULT dinput_create_device(const struct dinput_device *device, IDirectInputImp
     IDirectInputDeviceImpl *This;
     HRESULT hr;
 
+    if (device->create_unix_joystick) return dinput_create_unix_joystick(device, dinput, guid, iid, out);
     if (!device->create_device) return E_FAIL;
     if (FAILED(hr = device->create_device(dinput, guid, &This))) return hr;
     if (!FAILED(hr = IDirectInputDevice8_QueryInterface(IDirectInputDevice8W_from_impl(This), iid, out)))
diff --git a/dlls/dinput/dinput_private.h b/dlls/dinput/dinput_private.h
index 472f21adb1b..9f3214eb260 100644
--- a/dlls/dinput/dinput_private.h
+++ b/dlls/dinput/dinput_private.h
@@ -53,6 +53,7 @@ extern const IDirectInput7AVtbl direct_input_7_a_vtbl DECLSPEC_HIDDEN;
 extern const IDirectInput8AVtbl direct_input_8_a_vtbl DECLSPEC_HIDDEN;
 
 typedef struct IDirectInputDeviceImpl IDirectInputDeviceImpl;
+typedef struct JoystickGenericImpl JoystickGenericImpl;
 
 /* Function called by all devices that Wine supports */
 struct dinput_device {
@@ -60,6 +61,7 @@ struct dinput_device {
     HRESULT (*enum_deviceA)(DWORD dwDevType, DWORD dwFlags, LPDIDEVICEINSTANCEA lpddi, DWORD version, int id);
     HRESULT (*enum_deviceW)(DWORD dwDevType, DWORD dwFlags, LPDIDEVICEINSTANCEW lpddi, DWORD version, int id);
     HRESULT (*create_device)(IDirectInputImpl *dinput, REFGUID rguid, IDirectInputDeviceImpl **out);
+    HRESULT (*create_unix_joystick)(IDirectInputImpl *dinput, REFGUID rguid, JoystickGenericImpl **out);
 };
 
 extern HRESULT dinput_create_device(const struct dinput_device *device, IDirectInputImpl *dinput, REFGUID guid,
diff --git a/dlls/dinput/joystick.c b/dlls/dinput/joystick.c
index d2fffb4fe5e..94525875ca5 100644
--- a/dlls/dinput/joystick.c
+++ b/dlls/dinput/joystick.c
@@ -65,6 +65,10 @@ static inline JoystickGenericImpl *impl_from_IDirectInputDevice8W(IDirectInputDe
 {
     return CONTAINING_RECORD(CONTAINING_RECORD(iface, IDirectInputDeviceImpl, IDirectInputDevice8W_iface), JoystickGenericImpl, base);
 }
+static inline IDirectInputDevice8W *IDirectInputDevice8W_from_impl(JoystickGenericImpl *This)
+{
+    return &This->base.IDirectInputDevice8W_iface;
+}
 
 DWORD typeFromGUID(REFGUID guid)
 {
@@ -1169,3 +1173,20 @@ HRESULT setup_dinput_options(JoystickGenericImpl *This, const int *default_axis_
 
     return DI_OK;
 }
+
+HRESULT dinput_create_unix_joystick(const struct dinput_device *device, IDirectInputImpl *dinput, REFGUID guid, REFIID iid, void **out)
+{
+    JoystickGenericImpl *This;
+    HRESULT hr;
+
+    if (FAILED(hr = device->create_unix_joystick(dinput, guid, &This))) return hr;
+    if (FAILED(hr = IDirectInputDevice8_QueryInterface(IDirectInputDevice8W_from_impl(This), iid, out))) goto done;
+
+    TRACE("created unix joystick %p\n", This);
+    if (TRACE_ON(dinput)) _dump_DIDATAFORMAT(This->base.data_format.wine_df);
+
+done:
+    /* IDirectInputDevice8_QueryInterface increased refcount */
+    IDirectInputDevice8_Release(IDirectInputDevice8W_from_impl(This));
+    return hr;
+}
diff --git a/dlls/dinput/joystick_linux.c b/dlls/dinput/joystick_linux.c
index 9055565a902..ae75a3dbf20 100644
--- a/dlls/dinput/joystick_linux.c
+++ b/dlls/dinput/joystick_linux.c
@@ -447,23 +447,47 @@ static HRESULT joydev_enum_deviceA(DWORD dwDevType, DWORD dwFlags, LPDIDEVICEINS
     return S_FALSE;
 }
 
-static HRESULT alloc_device(REFGUID rguid, IDirectInputImpl *dinput,
-                            JoystickImpl **pdev, unsigned short index)
+/******************************************************************************
+  *     get_joystick_index : Get the joystick index from a given GUID
+  */
+static unsigned short get_joystick_index(REFGUID guid)
+{
+    GUID wine_joystick = DInput_Wine_Joystick_GUID;
+    GUID dev_guid = *guid;
+
+    wine_joystick.Data3 = 0;
+    dev_guid.Data3 = 0;
+
+    /* for the standard joystick GUID use index 0 */
+    if (IsEqualGUID(&GUID_Joystick, guid)) return 0;
+
+    /* for the wine joystick GUIDs use the index stored in Data3 */
+    if (IsEqualGUID(&wine_joystick, &dev_guid)) return guid->Data3;
+
+    return MAX_JOYSTICKS;
+}
+
+static HRESULT joydev_create_unix_joystick(IDirectInputImpl *dinput, REFGUID guid, JoystickGenericImpl **out)
 {
-    struct JoyDev *joydev = &joystick_devices[index];
+    struct JoyDev *joydev;
     DIDEVICEINSTANCEW didi = {sizeof(didi)};
-    DWORD i;
-    JoystickImpl* newDevice;
-    HRESULT hr;
     LPDIDATAFORMAT df = NULL;
-    int idx = 0;
+    JoystickImpl *newDevice;
+    HRESULT hr;
+    DWORD i, index, idx = 0;
+
+    TRACE("%p %s %p\n", dinput, debugstr_guid(guid), out);
 
-    TRACE("%s %p %p %hu\n", debugstr_guid(rguid), dinput, pdev, index);
+    find_joystick_devices();
+
+    *out = NULL;
+    if ((index = get_joystick_index(guid)) >= MAX_JOYSTICKS || !joystick_devices_count || index >= joystick_devices_count)
+        return DIERR_DEVICENOTREG;
+    joydev = &joystick_devices[index];
 
     fill_joystick_dideviceinstanceW(&didi, dinput->dwVersion, index);
 
-    *pdev = NULL;
-    if (FAILED(hr = direct_input_device_alloc(sizeof(JoystickImpl), &JoystickWvt, rguid, joydev->vendor_id,
+    if (FAILED(hr = direct_input_device_alloc(sizeof(JoystickImpl), &JoystickWvt, guid, joydev->vendor_id,
                        joydev->product_id, index, &didi, dinput, (void **)&newDevice)))
         return hr;
     newDevice->generic.base.crit.DebugInfo->Spare[0] = (DWORD_PTR)(__FILE__ ": JoystickImpl*->generic.base.crit");
@@ -472,7 +496,7 @@ static HRESULT alloc_device(REFGUID rguid, IDirectInputImpl *dinput,
 
     newDevice->joydev = joydev;
     newDevice->joyfd = -1;
-    newDevice->generic.name        = newDevice->joydev->name;
+    newDevice->generic.name = newDevice->joydev->name;
     newDevice->generic.device_axis_count = newDevice->joydev->axis_count;
     newDevice->generic.devcaps.dwButtons = newDevice->joydev->button_count;
 
@@ -486,16 +510,15 @@ static HRESULT alloc_device(REFGUID rguid, IDirectInputImpl *dinput,
     newDevice->generic.deadzone = 0;
 
     /* do any user specified configuration */
-    hr = setup_dinput_options(&newDevice->generic, newDevice->joydev->dev_axes_map);
-    if (hr != DI_OK)
-        goto FAILED1;
+    if (FAILED(hr = setup_dinput_options(&newDevice->generic, newDevice->joydev->dev_axes_map))) goto failed;
 
     /* Create copy of default data format */
-    if (!(df = HeapAlloc(GetProcessHeap(), 0, c_dfDIJoystick2.dwSize))) goto FAILED;
+    hr = DIERR_OUTOFMEMORY;
+    if (!(df = HeapAlloc(GetProcessHeap(), 0, c_dfDIJoystick2.dwSize))) goto failed;
     memcpy(df, &c_dfDIJoystick2, c_dfDIJoystick2.dwSize);
 
     df->dwNumObjs = newDevice->generic.devcaps.dwAxes + newDevice->generic.devcaps.dwPOVs + newDevice->generic.devcaps.dwButtons;
-    if (!(df->rgodf = HeapAlloc(GetProcessHeap(), 0, df->dwNumObjs * df->dwObjSize))) goto FAILED;
+    if (!(df->rgodf = HeapAlloc(GetProcessHeap(), 0, df->dwNumObjs * df->dwObjSize))) goto failed;
 
     for (i = 0; i < newDevice->generic.device_axis_count; i++)
     {
@@ -541,76 +564,31 @@ static HRESULT alloc_device(REFGUID rguid, IDirectInputImpl *dinput,
     newDevice->generic.devcaps.dwFFDriverVersion = 0;
 
     if (TRACE_ON(dinput)) {
-       for (i = 0; i < (newDevice->generic.device_axis_count); i++)
-           TRACE("axis_map[%d] = %d\n", i, newDevice->generic.axis_map[i]);
+        for (i = 0; i < (newDevice->generic.device_axis_count); i++)
+            TRACE("axis_map[%d] = %d\n", i, newDevice->generic.axis_map[i]);
         _dump_DIDEVCAPS(&newDevice->generic.devcaps);
     }
 
-    *pdev = newDevice;
-
+    *out = &newDevice->generic;
     return DI_OK;
 
-FAILED:
-    hr = DIERR_OUTOFMEMORY;
-FAILED1:
+failed:
     if (df) HeapFree(GetProcessHeap(), 0, df->rgodf);
     HeapFree(GetProcessHeap(), 0, df);
     release_DataFormat(&newDevice->generic.base.data_format);
-    HeapFree(GetProcessHeap(),0,newDevice->generic.axis_map);
-    HeapFree(GetProcessHeap(),0,newDevice);
-    *pdev = 0;
-
+    HeapFree(GetProcessHeap(), 0, newDevice->generic.axis_map);
+    HeapFree(GetProcessHeap(), 0, newDevice);
     return hr;
 }
 
-/******************************************************************************
-  *     get_joystick_index : Get the joystick index from a given GUID
-  */
-static unsigned short get_joystick_index(REFGUID guid)
-{
-    GUID wine_joystick = DInput_Wine_Joystick_GUID;
-    GUID dev_guid = *guid;
-
-    wine_joystick.Data3 = 0;
-    dev_guid.Data3 = 0;
-
-    /* for the standard joystick GUID use index 0 */
-    if(IsEqualGUID(&GUID_Joystick,guid)) return 0;
-
-    /* for the wine joystick GUIDs use the index stored in Data3 */
-    if(IsEqualGUID(&wine_joystick, &dev_guid)) return guid->Data3;
-
-    return MAX_JOYSTICKS;
-}
-
-static HRESULT joydev_create_device(IDirectInputImpl *dinput, REFGUID guid, IDirectInputDeviceImpl **out)
-{
-    unsigned short index;
-
-    TRACE("%p %s %p\n", dinput, debugstr_guid(guid), out);
-    find_joystick_devices();
-    *out = NULL;
-
-    if ((index = get_joystick_index(guid)) < MAX_JOYSTICKS &&
-        joystick_devices_count && index < joystick_devices_count)
-    {
-        JoystickImpl *This;
-        HRESULT hr = alloc_device(guid, dinput, &This, index);
-        if (!This) return hr;
-        *out = &This->generic.base;
-        return hr;
-    }
-
-    return DIERR_DEVICENOTREG;
-}
-
 #undef MAX_JOYSTICKS
 
 const struct dinput_device joystick_linux_device = {
   "Wine Linux joystick driver",
   joydev_enum_deviceA,
   NULL,
-  joydev_create_device
+  NULL,
+  joydev_create_unix_joystick
 };
 
 /******************************************************************************
diff --git a/dlls/dinput/joystick_linuxinput.c b/dlls/dinput/joystick_linuxinput.c
index ec5bd7eb157..3f561d33cbf 100644
--- a/dlls/dinput/joystick_linuxinput.c
+++ b/dlls/dinput/joystick_linuxinput.c
@@ -452,20 +452,50 @@ static HRESULT joydev_enum_deviceA(DWORD dwDevType, DWORD dwFlags, LPDIDEVICEINS
   return S_FALSE;
 }
 
-static JoystickImpl *alloc_device(REFGUID rguid, IDirectInputImpl *dinput, unsigned short index)
+/******************************************************************************
+  *     get_joystick_index : Get the joystick index from a given GUID
+  */
+static unsigned short get_joystick_index(REFGUID guid)
+{
+    GUID wine_joystick = DInput_Wine_Joystick_Base_GUID;
+    GUID dev_guid = *guid;
+
+    wine_joystick.Data3 = 0;
+    dev_guid.Data3 = 0;
+
+    /* for the standard joystick GUID use index 0 */
+    if (IsEqualGUID(&GUID_Joystick, guid)) return 0;
+
+    /* for the wine joystick GUIDs use the index stored in Data3 */
+    if (IsEqualGUID(&wine_joystick, &dev_guid)) return guid->Data3 - DInput_Wine_Joystick_Base_GUID.Data3;
+
+    return MAX_JOYDEV;
+}
+
+static HRESULT joydev_create_unix_joystick(IDirectInputImpl *dinput, REFGUID guid, JoystickGenericImpl **out)
 {
-    struct JoyDev *joydev = &joydevs[index];
+    struct JoyDev *joydev;
     DIDEVICEINSTANCEW didi = {sizeof(didi)};
-    JoystickImpl* newDevice;
     LPDIDATAFORMAT df = NULL;
-    int i, idx = 0;
+    JoystickImpl *newDevice;
+    int i, index, idx = 0;
     int default_axis_map[WINE_JOYSTICK_MAX_AXES + WINE_JOYSTICK_MAX_POVS*2];
+    HRESULT hr;
+
+    TRACE("%p %s %p\n", dinput, debugstr_guid(guid), out);
+
+    find_joydevs();
+
+    *out = NULL;
+    if ((index = get_joystick_index(guid)) >= MAX_JOYDEV || !have_joydevs || index >= have_joydevs)
+        return DIERR_DEVICENOTREG;
+    joydev = &joydevs[index];
 
     fill_joystick_dideviceinstanceW(&didi, dinput->dwVersion, index);
 
-    if (FAILED(direct_input_device_alloc(sizeof(JoystickImpl), &JoystickWvt, rguid, joydev->vendor_id,
-                joydev->product_id, index, &didi, dinput, (void **)&newDevice)))
-        return NULL;
+    if (FAILED(hr = direct_input_device_alloc(sizeof(JoystickImpl), &JoystickWvt, guid, joydev->vendor_id,
+                       joydev->product_id, index, &didi, dinput, (void **)&newDevice)))
+        return hr;
     newDevice->generic.base.crit.DebugInfo->Spare[0] = (DWORD_PTR)(__FILE__ ": JoystickImpl*->base.crit");
     newDevice->generic.unix_funcs = &unix_joystick_vtbl;
     newDevice->generic.unix_ptr = unix_joystick_from_impl(newDevice);
@@ -527,9 +557,10 @@ static JoystickImpl *alloc_device(REFGUID rguid, IDirectInputImpl *dinput, unsig
     }
 
     /* do any user specified configuration */
-    if (setup_dinput_options(&newDevice->generic, default_axis_map) != DI_OK) goto failed;
+    if (FAILED(hr = setup_dinput_options(&newDevice->generic, default_axis_map) != DI_OK)) goto failed;
 
     /* Create copy of default data format */
+    hr = DIERR_OUTOFMEMORY;
     if (!(df = HeapAlloc(GetProcessHeap(), 0, c_dfDIJoystick2.dwSize))) goto failed;
     memcpy(df, &c_dfDIJoystick2, c_dfDIJoystick2.dwSize);
     if (!(df->rgodf = HeapAlloc(GetProcessHeap(), 0, df->dwNumObjs * df->dwObjSize))) goto failed;
@@ -588,55 +619,15 @@ static JoystickImpl *alloc_device(REFGUID rguid, IDirectInputImpl *dinput, unsig
     if (newDevice->joydev->has_ff)
         newDevice->generic.devcaps.dwFlags |= DIDC_FORCEFEEDBACK;
 
-    return newDevice;
+    *out = &newDevice->generic;
+    return DI_OK;
 
 failed:
     if (df) HeapFree(GetProcessHeap(), 0, df->rgodf);
     HeapFree(GetProcessHeap(), 0, df);
     HeapFree(GetProcessHeap(), 0, newDevice->generic.axis_map);
     HeapFree(GetProcessHeap(), 0, newDevice);
-    return NULL;
-}
-
-/******************************************************************************
-  *     get_joystick_index : Get the joystick index from a given GUID
-  */
-static unsigned short get_joystick_index(REFGUID guid)
-{
-    GUID wine_joystick = DInput_Wine_Joystick_Base_GUID;
-    GUID dev_guid = *guid;
-
-    wine_joystick.Data3 = 0;
-    dev_guid.Data3 = 0;
-
-    /* for the standard joystick GUID use index 0 */
-    if(IsEqualGUID(&GUID_Joystick,guid)) return 0;
-
-    /* for the wine joystick GUIDs use the index stored in Data3 */
-    if(IsEqualGUID(&wine_joystick, &dev_guid)) return guid->Data3 - DInput_Wine_Joystick_Base_GUID.Data3;
-
-    return MAX_JOYDEV;
-}
-
-static HRESULT joydev_create_device(IDirectInputImpl *dinput, REFGUID guid, IDirectInputDeviceImpl **out)
-{
-    unsigned short index;
-
-    TRACE("%p %s %p\n", dinput, debugstr_guid(guid), out);
-    find_joydevs();
-    *out = NULL;
-
-    if ((index = get_joystick_index(guid)) < MAX_JOYDEV &&
-        have_joydevs && index < have_joydevs)
-    {
-        JoystickImpl *This = alloc_device(guid, dinput, index);
-        TRACE("Created a Joystick device (%p)\n", This);
-        if (!This) return DIERR_OUTOFMEMORY;
-        *out = &This->generic.base;
-        return DI_OK;
-    }
-
-    return DIERR_DEVICENOTREG;
+    return hr;
 }
 
 
@@ -644,7 +635,8 @@ const struct dinput_device joystick_linuxinput_device = {
   "Wine Linux-input joystick driver",
   joydev_enum_deviceA,
   NULL,
-  joydev_create_device
+  NULL,
+  joydev_create_unix_joystick
 };
 
 /******************************************************************************
diff --git a/dlls/dinput/joystick_osx.c b/dlls/dinput/joystick_osx.c
index 19c2e2dddf4..cbd761ad935 100644
--- a/dlls/dinput/joystick_osx.c
+++ b/dlls/dinput/joystick_osx.c
@@ -1074,8 +1074,27 @@ static void fill_joystick_dideviceinstanceW(LPDIDEVICEINSTANCEW didi, IOHIDDevic
     didi->wUsage = 0;
 }
 
-static HRESULT alloc_device(REFGUID rguid, IDirectInputImpl *dinput,
-                            JoystickImpl **pdev, unsigned short index)
+/******************************************************************************
+  *     get_joystick_index : Get the joystick index from a given GUID
+  */
+static unsigned short get_joystick_index(REFGUID guid)
+{
+    GUID wine_joystick = DInput_Wine_OsX_Joystick_GUID;
+    GUID dev_guid = *guid;
+
+    wine_joystick.Data3 = 0;
+    dev_guid.Data3 = 0;
+
+    /* for the standard joystick GUID use index 0 */
+    if (IsEqualGUID(&GUID_Joystick, guid)) return 0;
+
+    /* for the wine joystick GUIDs use the index stored in Data3 */
+    if (IsEqualGUID(&wine_joystick, &dev_guid)) return guid->Data3;
+
+    return 0xffff;
+}
+
+static HRESULT joydev_create_unix_joystick(IDirectInputImpl *dinput, REFGUID guid, JoystickGenericImpl **out)
 {
     DIDEVICEINSTANCEW didi = {sizeof(didi)};
     DWORD i;
@@ -1084,13 +1103,22 @@ static HRESULT alloc_device(REFGUID rguid, IDirectInputImpl *dinput,
     char name[MAX_PATH];
     HRESULT hr;
     LPDIDATAFORMAT df = NULL;
+    unsigned short index;
     int idx = 0;
     int axis_map[8]; /* max axes */
     int slider_count = 0;
+    int joystick_devices_count;
     FFCAPABILITIES ffcaps;
     WORD vendor_id, product_id;
 
-    TRACE("%s %p %p %hu\n", debugstr_guid(rguid), dinput, pdev, index);
+    TRACE("%p %s %p\n", dinput, debugstr_guid(guid), out);
+
+    *out = NULL;
+
+    if ((joystick_devices_count = find_joystick_devices()) == 0) return DIERR_DEVICENOTREG;
+
+    if ((index = get_joystick_index(guid)) >= 0xffff || !joystick_devices_count || index >= joystick_devices_count)
+        return DIERR_DEVICENOTREG;
 
     device = get_device_ref(index);
     vendor_id = get_device_property_long(device, CFSTR(kIOHIDVendorIDKey));
@@ -1098,7 +1126,7 @@ static HRESULT alloc_device(REFGUID rguid, IDirectInputImpl *dinput,
 
     fill_joystick_dideviceinstanceW(&didi, device, dinput->dwVersion, index, name);
 
-    if (FAILED(hr = direct_input_device_alloc(sizeof(JoystickImpl), &JoystickWvt, rguid, vendor_id, product_id, index,
+    if (FAILED(hr = direct_input_device_alloc(sizeof(JoystickImpl), &JoystickWvt, guid, vendor_id, product_id, index,
                        &didi, dinput, (void **)&newDevice)))
         return hr;
     newDevice->generic.base.crit.DebugInfo->Spare[0] = (DWORD_PTR)(__FILE__ ": JoystickImpl*->generic.base.crit");
@@ -1243,8 +1271,7 @@ static HRESULT alloc_device(REFGUID rguid, IDirectInputImpl *dinput,
         _dump_DIDEVCAPS(&newDevice->generic.devcaps);
     }
 
-    *pdev = newDevice;
-
+    *out = &newDevice->generic;
     return DI_OK;
 
 FAILED:
@@ -1256,55 +1283,9 @@ FAILED:
     release_DataFormat(&newDevice->generic.base.data_format);
     HeapFree(GetProcessHeap(),0,newDevice->generic.name);
     HeapFree(GetProcessHeap(),0,newDevice);
-    *pdev = 0;
-
     return hr;
 }
 
-/******************************************************************************
-  *     get_joystick_index : Get the joystick index from a given GUID
-  */
-static unsigned short get_joystick_index(REFGUID guid)
-{
-    GUID wine_joystick = DInput_Wine_OsX_Joystick_GUID;
-    GUID dev_guid = *guid;
-
-    wine_joystick.Data3 = 0;
-    dev_guid.Data3 = 0;
-
-    /* for the standard joystick GUID use index 0 */
-    if(IsEqualGUID(&GUID_Joystick,guid)) return 0;
-
-    /* for the wine joystick GUIDs use the index stored in Data3 */
-    if(IsEqualGUID(&wine_joystick, &dev_guid)) return guid->Data3;
-
-    return 0xffff;
-}
-
-static HRESULT joydev_create_device(IDirectInputImpl *dinput, REFGUID guid, IDirectInputDeviceImpl **out)
-{
-    unsigned short index;
-    int joystick_devices_count;
-
-    TRACE("%p %s %p\n", dinput, debugstr_guid(guid), out);
-    *out = NULL;
-
-    if ((joystick_devices_count = find_joystick_devices()) == 0)
-        return DIERR_DEVICENOTREG;
-
-    if ((index = get_joystick_index(guid)) < 0xffff &&
-        joystick_devices_count && index < joystick_devices_count)
-    {
-        JoystickImpl *This;
-        HRESULT hr = alloc_device(guid, dinput, &This, index);
-        if (!This) return hr;
-        *out = &This->generic.base;
-        return hr;
-    }
-
-    return DIERR_DEVICENOTREG;
-}
-
 static HRESULT CDECL unix_joystick_ff_set_autocenter(struct unix_joystick *ptr, DWORD value)
 {
     JoystickImpl *This = impl_from_unix_joystick(ptr);
@@ -1414,7 +1395,8 @@ const struct dinput_device joystick_osx_device = {
   "Wine OS X joystick driver",
   joydev_enum_deviceA,
   NULL,
-  joydev_create_device
+  NULL,
+  joydev_create_unix_joystick
 };
 
 static const IDirectInputDevice8WVtbl JoystickWvt =
diff --git a/dlls/dinput/joystick_private.h b/dlls/dinput/joystick_private.h
index e479ea6b480..87e91a21133 100644
--- a/dlls/dinput/joystick_private.h
+++ b/dlls/dinput/joystick_private.h
@@ -71,6 +71,8 @@ typedef struct JoystickGenericImpl
     struct list ff_effects;
 } JoystickGenericImpl;
 
+extern HRESULT dinput_create_unix_joystick(const struct dinput_device *device, IDirectInputImpl *dinput, REFGUID guid, REFIID iid, void **out) DECLSPEC_HIDDEN;
+
 LONG joystick_map_axis(ObjProps *props, int val) DECLSPEC_HIDDEN;
 HRESULT setup_dinput_options(JoystickGenericImpl *This, const int *default_axis_map) DECLSPEC_HIDDEN;
 
diff --git a/dlls/dinput/keyboard.c b/dlls/dinput/keyboard.c
index 79c57c50d28..b257f2b51c1 100644
--- a/dlls/dinput/keyboard.c
+++ b/dlls/dinput/keyboard.c
@@ -259,7 +259,8 @@ const struct dinput_device keyboard_device = {
   "Wine keyboard driver",
   NULL,
   keyboarddev_enum_deviceW,
-  keyboarddev_create_device
+  keyboarddev_create_device,
+  NULL
 };
 
 static HRESULT WINAPI SysKeyboardWImpl_GetDeviceState(LPDIRECTINPUTDEVICE8W iface, DWORD len, LPVOID ptr)
diff --git a/dlls/dinput/mouse.c b/dlls/dinput/mouse.c
index f81fe92cf22..c436bf5032a 100644
--- a/dlls/dinput/mouse.c
+++ b/dlls/dinput/mouse.c
@@ -217,7 +217,8 @@ const struct dinput_device mouse_device = {
     "Wine mouse driver",
     NULL,
     mousedev_enum_deviceW,
-    mousedev_create_device
+    mousedev_create_device,
+    NULL
 };
 
 /******************************************************************************
-- 
2.28.0

>From b5c3f702d9ab24dc829c7142980a8d1bd0fa0ac4 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?R=C3=A9mi=20Bernon?= <rbernon@codeweavers.com>
Date: Tue, 6 Oct 2020 02:00:13 +0200
Subject: [PATCH 23/39] dinput: Use the unix vtable for initialization.

---
 dlls/dinput/joystick.c            |   1 +
 dlls/dinput/joystick_linux.c      |  84 ++++++++++++---------
 dlls/dinput/joystick_linuxinput.c | 113 ++++++++++++++--------------
 dlls/dinput/joystick_osx.c        | 119 +++++++++++++++++-------------
 dlls/dinput/joystick_private.h    |   2 +
 5 files changed, 175 insertions(+), 144 deletions(-)

diff --git a/dlls/dinput/joystick.c b/dlls/dinput/joystick.c
index 94525875ca5..8cf7ff05a0b 100644
--- a/dlls/dinput/joystick.c
+++ b/dlls/dinput/joystick.c
@@ -1180,6 +1180,7 @@ HRESULT dinput_create_unix_joystick(const struct dinput_device *device, IDirectI
     HRESULT hr;
 
     if (FAILED(hr = device->create_unix_joystick(dinput, guid, &This))) return hr;
+    if (FAILED(hr = This->unix_funcs->init(This->unix_ptr))) goto done;
     if (FAILED(hr = IDirectInputDevice8_QueryInterface(IDirectInputDevice8W_from_impl(This), iid, out))) goto done;
 
     TRACE("created unix joystick %p\n", This);
diff --git a/dlls/dinput/joystick_linux.c b/dlls/dinput/joystick_linux.c
index ae75a3dbf20..873ee88c20c 100644
--- a/dlls/dinput/joystick_linux.c
+++ b/dlls/dinput/joystick_linux.c
@@ -138,8 +138,11 @@ static void CDECL unix_joystick_poll(struct unix_joystick *ptr);
 static HRESULT CDECL unix_joystick_acquire(struct unix_joystick *ptr);
 static HRESULT CDECL unix_joystick_unacquire(struct unix_joystick *ptr);
 
+static HRESULT CDECL unix_joystick_init(struct unix_joystick *ptr);
+
 static const struct unix_joystick_vtbl unix_joystick_vtbl =
 {
+    unix_joystick_init,
     unix_joystick_acquire,
     unix_joystick_unacquire,
     NULL,
@@ -471,10 +474,9 @@ static HRESULT joydev_create_unix_joystick(IDirectInputImpl *dinput, REFGUID gui
 {
     struct JoyDev *joydev;
     DIDEVICEINSTANCEW didi = {sizeof(didi)};
-    LPDIDATAFORMAT df = NULL;
     JoystickImpl *newDevice;
     HRESULT hr;
-    DWORD i, index, idx = 0;
+    DWORD index;
 
     TRACE("%p %s %p\n", dinput, debugstr_guid(guid), out);
 
@@ -496,33 +498,45 @@ static HRESULT joydev_create_unix_joystick(IDirectInputImpl *dinput, REFGUID gui
 
     newDevice->joydev = joydev;
     newDevice->joyfd = -1;
-    newDevice->generic.name = newDevice->joydev->name;
-    newDevice->generic.device_axis_count = newDevice->joydev->axis_count;
-    newDevice->generic.devcaps.dwButtons = newDevice->joydev->button_count;
 
-    if (newDevice->generic.devcaps.dwButtons > 128)
+    *out = &newDevice->generic;
+    return DI_OK;
+}
+
+static HRESULT CDECL unix_joystick_init(struct unix_joystick *ptr)
+{
+    JoystickImpl *This = impl_from_unix_joystick(ptr);
+    LPDIDATAFORMAT df = NULL;
+    HRESULT hr;
+    DWORD i, idx = 0;
+
+    This->generic.name = This->joydev->name;
+    This->generic.device_axis_count = This->joydev->axis_count;
+    This->generic.devcaps.dwButtons = This->joydev->button_count;
+
+    if (This->generic.devcaps.dwButtons > 128)
     {
-        WARN("Can't support %d buttons. Clamping down to 128\n", newDevice->generic.devcaps.dwButtons);
-        newDevice->generic.devcaps.dwButtons = 128;
+        WARN("Can't support %d buttons. Clamping down to 128\n", This->generic.devcaps.dwButtons);
+        This->generic.devcaps.dwButtons = 128;
     }
 
     /* setup_dinput_options may change these */
-    newDevice->generic.deadzone = 0;
+    This->generic.deadzone = 0;
 
     /* do any user specified configuration */
-    if (FAILED(hr = setup_dinput_options(&newDevice->generic, newDevice->joydev->dev_axes_map))) goto failed;
+    if (FAILED(hr = setup_dinput_options(&This->generic, This->joydev->dev_axes_map))) goto failed;
 
     /* Create copy of default data format */
     hr = DIERR_OUTOFMEMORY;
     if (!(df = HeapAlloc(GetProcessHeap(), 0, c_dfDIJoystick2.dwSize))) goto failed;
     memcpy(df, &c_dfDIJoystick2, c_dfDIJoystick2.dwSize);
 
-    df->dwNumObjs = newDevice->generic.devcaps.dwAxes + newDevice->generic.devcaps.dwPOVs + newDevice->generic.devcaps.dwButtons;
+    df->dwNumObjs = This->generic.devcaps.dwAxes + This->generic.devcaps.dwPOVs + This->generic.devcaps.dwButtons;
     if (!(df->rgodf = HeapAlloc(GetProcessHeap(), 0, df->dwNumObjs * df->dwObjSize))) goto failed;
 
-    for (i = 0; i < newDevice->generic.device_axis_count; i++)
+    for (i = 0; i < This->generic.device_axis_count; i++)
     {
-        int wine_obj = newDevice->generic.axis_map[i];
+        int wine_obj = This->generic.axis_map[i];
 
         if (wine_obj < 0) continue;
 
@@ -535,49 +549,47 @@ static HRESULT joydev_create_unix_joystick(IDirectInputImpl *dinput, REFGUID gui
             i++; /* POV takes 2 axes */
         }
     }
-    for (i = 0; i < newDevice->generic.devcaps.dwButtons; i++)
+    for (i = 0; i < This->generic.devcaps.dwButtons; i++)
     {
         memcpy(&df->rgodf[idx], &c_dfDIJoystick2.rgodf[i + 12], df->dwObjSize);
         df->rgodf[idx  ].pguid = &GUID_Button;
         df->rgodf[idx++].dwType = DIDFT_MAKEINSTANCE(i) | DIDFT_PSHBUTTON;
     }
-    newDevice->generic.base.data_format.wine_df = df;
+    This->generic.base.data_format.wine_df = df;
 
     /* initialize default properties */
     for (i = 0; i < c_dfDIJoystick2.dwNumObjs; i++) {
-        newDevice->generic.props[i].lDevMin = -32767;
-        newDevice->generic.props[i].lDevMax = +32767;
-        newDevice->generic.props[i].lMin = 0;
-        newDevice->generic.props[i].lMax = 0xffff;
-        newDevice->generic.props[i].lDeadZone = newDevice->generic.deadzone; /* % * 1000 */
-        newDevice->generic.props[i].lSaturation = 0;
+        This->generic.props[i].lDevMin = -32767;
+        This->generic.props[i].lDevMax = +32767;
+        This->generic.props[i].lMin = 0;
+        This->generic.props[i].lMax = 0xffff;
+        This->generic.props[i].lDeadZone = This->generic.deadzone; /* % * 1000 */
+        This->generic.props[i].lSaturation = 0;
     }
 
-    newDevice->generic.devcaps.dwSize = sizeof(newDevice->generic.devcaps);
-    newDevice->generic.devcaps.dwFlags = DIDC_ATTACHED;
-    newDevice->generic.devcaps.dwDevType = didi.dwDevType;
+    This->generic.devcaps.dwSize = sizeof(This->generic.devcaps);
+    This->generic.devcaps.dwFlags = DIDC_ATTACHED;
+    This->generic.devcaps.dwDevType = This->generic.base.info.dwDevType;
 
-    newDevice->generic.devcaps.dwFFSamplePeriod = 0;
-    newDevice->generic.devcaps.dwFFMinTimeResolution = 0;
-    newDevice->generic.devcaps.dwFirmwareRevision = 0;
-    newDevice->generic.devcaps.dwHardwareRevision = 0;
-    newDevice->generic.devcaps.dwFFDriverVersion = 0;
+    This->generic.devcaps.dwFFSamplePeriod = 0;
+    This->generic.devcaps.dwFFMinTimeResolution = 0;
+    This->generic.devcaps.dwFirmwareRevision = 0;
+    This->generic.devcaps.dwHardwareRevision = 0;
+    This->generic.devcaps.dwFFDriverVersion = 0;
 
     if (TRACE_ON(dinput)) {
-        for (i = 0; i < (newDevice->generic.device_axis_count); i++)
-            TRACE("axis_map[%d] = %d\n", i, newDevice->generic.axis_map[i]);
-        _dump_DIDEVCAPS(&newDevice->generic.devcaps);
+        for (i = 0; i < (This->generic.device_axis_count); i++)
+            TRACE("axis_map[%d] = %d\n", i, This->generic.axis_map[i]);
+        _dump_DIDEVCAPS(&This->generic.devcaps);
     }
 
-    *out = &newDevice->generic;
     return DI_OK;
 
 failed:
     if (df) HeapFree(GetProcessHeap(), 0, df->rgodf);
     HeapFree(GetProcessHeap(), 0, df);
-    release_DataFormat(&newDevice->generic.base.data_format);
-    HeapFree(GetProcessHeap(), 0, newDevice->generic.axis_map);
-    HeapFree(GetProcessHeap(), 0, newDevice);
+    release_DataFormat(&This->generic.base.data_format);
+    HeapFree(GetProcessHeap(), 0, This->generic.axis_map);
     return hr;
 }
 
diff --git a/dlls/dinput/joystick_linuxinput.c b/dlls/dinput/joystick_linuxinput.c
index 3f561d33cbf..5f0df95e3d0 100644
--- a/dlls/dinput/joystick_linuxinput.c
+++ b/dlls/dinput/joystick_linuxinput.c
@@ -169,8 +169,11 @@ static HRESULT CDECL unix_joystick_get_effect_info(struct unix_joystick *ptr, RE
 static HRESULT CDECL unix_joystick_create_effect(struct unix_joystick *ptr, REFGUID guid, const DIEFFECT *effect,
         struct list *entry, IDirectInputEffect **out);
 
+static HRESULT CDECL unix_joystick_init(struct unix_joystick *ptr);
+
 static const struct unix_joystick_vtbl unix_joystick_vtbl =
 {
+    unix_joystick_init,
     unix_joystick_acquire,
     unix_joystick_unacquire,
     unix_joystick_ff_set_autocenter,
@@ -476,11 +479,9 @@ static HRESULT joydev_create_unix_joystick(IDirectInputImpl *dinput, REFGUID gui
 {
     struct JoyDev *joydev;
     DIDEVICEINSTANCEW didi = {sizeof(didi)};
-    LPDIDATAFORMAT df = NULL;
     JoystickImpl *newDevice;
-    int i, index, idx = 0;
-    int default_axis_map[WINE_JOYSTICK_MAX_AXES + WINE_JOYSTICK_MAX_POVS*2];
     HRESULT hr;
+    int index;
 
     TRACE("%p %s %p\n", dinput, debugstr_guid(guid), out);
 
@@ -502,62 +503,69 @@ static HRESULT joydev_create_unix_joystick(IDirectInputImpl *dinput, REFGUID gui
 
     newDevice->joyfd       = -1;
     newDevice->joydev = joydev;
-    newDevice->generic.name        = newDevice->joydev->name;
-    list_init(&newDevice->generic.ff_effects);
+
+    *out = &newDevice->generic;
+    return DI_OK;
+}
+
+static HRESULT CDECL unix_joystick_init(struct unix_joystick *ptr)
+{
+    JoystickImpl *This = impl_from_unix_joystick(ptr);
+    LPDIDATAFORMAT df = NULL;
+    HRESULT hr;
+    int i, idx = 0, default_axis_map[WINE_JOYSTICK_MAX_AXES + WINE_JOYSTICK_MAX_POVS * 2];
+
+    This->generic.name = This->joydev->name;
+    list_init(&This->generic.ff_effects);
 #ifdef HAVE_STRUCT_FF_EFFECT_DIRECTION
-    newDevice->ff_state    = FF_STATUS_STOPPED;
+    This->ff_state = FF_STATUS_STOPPED;
 #endif
     /* There is no way in linux to query force feedback autocenter status.
        Instead, track it with ff_autocenter, and assume it's initially
        enabled. */
-    newDevice->ff_autocenter = 1;
-    newDevice->ff_gain = 0xFFFF;
-    newDevice->generic.ff_autocenter = DIPROPAUTOCENTER_ON;
-    newDevice->generic.ff_gain = 10000;
+    This->ff_autocenter = 1;
+    This->ff_gain = 0xFFFF;
+    This->generic.ff_autocenter = DIPROPAUTOCENTER_ON;
+    This->generic.ff_gain = 10000;
 
     /* Count number of available axes - supported Axis & POVs */
     for (i = 0; i < ABS_MAX; i++)
     {
-        if (idx < WINE_JOYSTICK_MAX_AXES &&
-            i < ABS_HAT0X &&
-            test_bit(newDevice->joydev->absbits, i))
+        if (idx < WINE_JOYSTICK_MAX_AXES && i < ABS_HAT0X && test_bit(This->joydev->absbits, i))
         {
-            newDevice->generic.device_axis_count++;
-            newDevice->dev_axes_to_di[i] = idx;
-            newDevice->generic.props[idx].lDevMin = newDevice->joydev->axes[i].minimum;
-            newDevice->generic.props[idx].lDevMax = newDevice->joydev->axes[i].maximum;
+            This->generic.device_axis_count++;
+            This->dev_axes_to_di[i] = idx;
+            This->generic.props[idx].lDevMin = This->joydev->axes[i].minimum;
+            This->generic.props[idx].lDevMax = This->joydev->axes[i].maximum;
             if (i >= 8 && i <= 10) /* If it's a wheel axis... */
                 default_axis_map[idx] = i - 8; /* ... remap to X/Y/Z */
             else
                 default_axis_map[idx] = i;
             idx++;
         }
-        else
-            newDevice->dev_axes_to_di[i] = -1;
+        else This->dev_axes_to_di[i] = -1;
     }
 
     for (i = 0; i < WINE_JOYSTICK_MAX_POVS; i++)
     {
-        if (test_bit(newDevice->joydev->absbits, ABS_HAT0X + i * 2) &&
-            test_bit(newDevice->joydev->absbits, ABS_HAT0Y + i * 2))
+        if (test_bit(This->joydev->absbits, ABS_HAT0X + i * 2) && test_bit(This->joydev->absbits, ABS_HAT0Y + i * 2))
         {
-            newDevice->generic.device_axis_count += 2;
-            newDevice->generic.props[idx  ].lDevMin = newDevice->joydev->axes[ABS_HAT0X + i * 2].minimum;
-            newDevice->generic.props[idx  ].lDevMax = newDevice->joydev->axes[ABS_HAT0X + i * 2].maximum;
-            newDevice->dev_axes_to_di[ABS_HAT0X + i * 2] = idx;
-            newDevice->generic.props[idx+1].lDevMin = newDevice->joydev->axes[ABS_HAT0Y + i * 2].minimum;
-            newDevice->generic.props[idx+1].lDevMax = newDevice->joydev->axes[ABS_HAT0Y + i * 2].maximum;
-            newDevice->dev_axes_to_di[ABS_HAT0Y + i * 2] = idx + 1;
+            This->generic.device_axis_count += 2;
+            This->generic.props[idx].lDevMin = This->joydev->axes[ABS_HAT0X + i * 2].minimum;
+            This->generic.props[idx].lDevMax = This->joydev->axes[ABS_HAT0X + i * 2].maximum;
+            This->dev_axes_to_di[ABS_HAT0X + i * 2] = idx;
+            This->generic.props[idx + 1].lDevMin = This->joydev->axes[ABS_HAT0Y + i * 2].minimum;
+            This->generic.props[idx + 1].lDevMax = This->joydev->axes[ABS_HAT0Y + i * 2].maximum;
+            This->dev_axes_to_di[ABS_HAT0Y + i * 2] = idx + 1;
 
             default_axis_map[idx] = default_axis_map[idx + 1] = WINE_JOYSTICK_MAX_AXES + i;
             idx += 2;
         }
-        else
-            newDevice->dev_axes_to_di[ABS_HAT0X + i * 2] = newDevice->dev_axes_to_di[ABS_HAT0Y + i * 2] = -1;
+        else This->dev_axes_to_di[ABS_HAT0X + i * 2] = This->dev_axes_to_di[ABS_HAT0Y + i * 2] = -1;
     }
 
     /* do any user specified configuration */
-    if (FAILED(hr = setup_dinput_options(&newDevice->generic, default_axis_map) != DI_OK)) goto failed;
+    if (FAILED(hr = setup_dinput_options(&This->generic, default_axis_map) != DI_OK)) goto failed;
 
     /* Create copy of default data format */
     hr = DIERR_OUTOFMEMORY;
@@ -569,9 +577,9 @@ static HRESULT joydev_create_unix_joystick(IDirectInputImpl *dinput, REFGUID gui
     /* Construct internal data format */
 
     /* Supported Axis & POVs */
-    for (i = 0, idx = 0; i < newDevice->generic.device_axis_count; i++)
+    for (i = 0, idx = 0; i < This->generic.device_axis_count; i++)
     {
-        int wine_obj = newDevice->generic.axis_map[i];
+        int wine_obj = This->generic.axis_map[i];
 
         if (wine_obj < 0) continue;
 
@@ -584,53 +592,48 @@ static HRESULT joydev_create_unix_joystick(IDirectInputImpl *dinput, REFGUID gui
             i++; /* POV takes 2 axes */
         }
 
-        newDevice->generic.props[idx].lMin        = 0;
-        newDevice->generic.props[idx].lMax        = 0xffff;
-        newDevice->generic.props[idx].lSaturation = 0;
-        newDevice->generic.props[idx].lDeadZone   = newDevice->generic.deadzone;
+        This->generic.props[idx].lMin = 0;
+        This->generic.props[idx].lMax = 0xffff;
+        This->generic.props[idx].lSaturation = 0;
+        This->generic.props[idx].lDeadZone = This->generic.deadzone;
 
         /* Linux supports force-feedback on X & Y axes only */
-        if (newDevice->joydev->has_ff && (i == 0 || i == 1))
-            df->rgodf[idx].dwFlags |= DIDOI_FFACTUATOR;
+        if (This->joydev->has_ff && (i == 0 || i == 1)) df->rgodf[idx].dwFlags |= DIDOI_FFACTUATOR;
 
         idx++;
     }
 
     /* Buttons can be anywhere, so check all */
-    for (i = 0; i < KEY_MAX && newDevice->generic.devcaps.dwButtons < WINE_JOYSTICK_MAX_BUTTONS; i++)
+    for (i = 0; i < KEY_MAX && This->generic.devcaps.dwButtons < WINE_JOYSTICK_MAX_BUTTONS; i++)
     {
-        if (!test_bit(newDevice->joydev->keybits, i)) continue;
+        if (!test_bit(This->joydev->keybits, i)) continue;
 
-        memcpy(&df->rgodf[idx], &c_dfDIJoystick2.rgodf[newDevice->generic.devcaps.dwButtons + 12], df->dwObjSize);
-        newDevice->buttons[i] = 0x80 | newDevice->generic.devcaps.dwButtons;
+        memcpy(&df->rgodf[idx], &c_dfDIJoystick2.rgodf[This->generic.devcaps.dwButtons + 12], df->dwObjSize);
+        This->buttons[i] = 0x80 | This->generic.devcaps.dwButtons;
         df->rgodf[idx  ].pguid = &GUID_Button;
-        df->rgodf[idx++].dwType = DIDFT_MAKEINSTANCE(newDevice->generic.devcaps.dwButtons++) | DIDFT_PSHBUTTON;
+        df->rgodf[idx++].dwType = DIDFT_MAKEINSTANCE(This->generic.devcaps.dwButtons++) | DIDFT_PSHBUTTON;
     }
     df->dwNumObjs = idx;
-    newDevice->generic.base.data_format.wine_df = df;
+    This->generic.base.data_format.wine_df = df;
 
-    fake_current_js_state(newDevice);
+    fake_current_js_state(This);
 
     /* Fill the caps */
-    newDevice->generic.devcaps.dwSize = sizeof(newDevice->generic.devcaps);
-    newDevice->generic.devcaps.dwFlags = DIDC_ATTACHED;
-    newDevice->generic.devcaps.dwDevType = didi.dwDevType;
+    This->generic.devcaps.dwSize = sizeof(This->generic.devcaps);
+    This->generic.devcaps.dwFlags = DIDC_ATTACHED;
+    This->generic.devcaps.dwDevType = This->generic.base.info.dwDevType;
 
-    if (newDevice->joydev->has_ff)
-        newDevice->generic.devcaps.dwFlags |= DIDC_FORCEFEEDBACK;
+    if (This->joydev->has_ff) This->generic.devcaps.dwFlags |= DIDC_FORCEFEEDBACK;
 
-    *out = &newDevice->generic;
     return DI_OK;
 
 failed:
     if (df) HeapFree(GetProcessHeap(), 0, df->rgodf);
     HeapFree(GetProcessHeap(), 0, df);
-    HeapFree(GetProcessHeap(), 0, newDevice->generic.axis_map);
-    HeapFree(GetProcessHeap(), 0, newDevice);
+    HeapFree(GetProcessHeap(), 0, This->generic.axis_map);
     return hr;
 }
 
-
 const struct dinput_device joystick_linuxinput_device = {
   "Wine Linux-input joystick driver",
   joydev_enum_deviceA,
diff --git a/dlls/dinput/joystick_osx.c b/dlls/dinput/joystick_osx.c
index cbd761ad935..2d25f50ebe2 100644
--- a/dlls/dinput/joystick_osx.c
+++ b/dlls/dinput/joystick_osx.c
@@ -949,8 +949,11 @@ static HRESULT CDECL unix_joystick_ff_send_cmd(struct unix_joystick *ptr, DWORD
 static HRESULT CDECL unix_joystick_create_effect(struct unix_joystick *ptr, REFGUID guid, const DIEFFECT *params,
         struct list *entry, IDirectInputEffect **out);
 
+static HRESULT CDECL unix_joystick_init(struct unix_joystick *ptr);
+
 static const struct unix_joystick_vtbl unix_joystick_vtbl =
 {
+    unix_joystick_init,
     NULL,
     NULL,
     unix_joystick_ff_set_autocenter,
@@ -1097,18 +1100,11 @@ static unsigned short get_joystick_index(REFGUID guid)
 static HRESULT joydev_create_unix_joystick(IDirectInputImpl *dinput, REFGUID guid, JoystickGenericImpl **out)
 {
     DIDEVICEINSTANCEW didi = {sizeof(didi)};
-    DWORD i;
     IOHIDDeviceRef device;
     JoystickImpl* newDevice;
     char name[MAX_PATH];
-    HRESULT hr;
-    LPDIDATAFORMAT df = NULL;
     unsigned short index;
-    int idx = 0;
-    int axis_map[8]; /* max axes */
-    int slider_count = 0;
     int joystick_devices_count;
-    FFCAPABILITIES ffcaps;
     WORD vendor_id, product_id;
 
     TRACE("%p %s %p\n", dinput, debugstr_guid(guid), out);
@@ -1121,6 +1117,7 @@ static HRESULT joydev_create_unix_joystick(IDirectInputImpl *dinput, REFGUID gui
         return DIERR_DEVICENOTREG;
 
     device = get_device_ref(index);
+    get_osx_device_name(index, name, MAX_PATH);
     vendor_id = get_device_property_long(device, CFSTR(kIOHIDVendorIDKey));
     product_id = get_device_property_long(device, CFSTR(kIOHIDProductIDKey));
 
@@ -1135,19 +1132,39 @@ static HRESULT joydev_create_unix_joystick(IDirectInputImpl *dinput, REFGUID gui
 
     newDevice->id = index;
 
+    *out = &newDevice->generic;
+    return DI_OK;
+}
+
+static HRESULT CDECL unix_joystick_init(struct unix_joystick *ptr)
+{
+    JoystickImpl *This = impl_from_unix_joystick(ptr);
+    IOHIDDeviceRef device;
+    LPDIDATAFORMAT df = NULL;
+    FFCAPABILITIES ffcaps;
+    char name[MAX_PATH];
+    HRESULT hr;
+    DWORD i;
+    int idx = 0;
+    int axis_map[8]; /* max axes */
+    int slider_count = 0;
+
+    device = get_device_ref(This->id);
+
     /* get the device name */
-    get_osx_device_name(index, name, MAX_PATH);
+    get_osx_device_name(This->id, name, MAX_PATH);
     TRACE("Name %s\n",name);
 
     /* copy the device name */
-    newDevice->generic.name = HeapAlloc(GetProcessHeap(),0,strlen(name) + 1);
-    strcpy(newDevice->generic.name, name);
+    This->generic.name = HeapAlloc(GetProcessHeap(), 0, strlen(name) + 1);
+    strcpy(This->generic.name, name);
 
-    list_init(&newDevice->generic.ff_effects);
-    if(get_ff(device, &newDevice->ff) == S_OK){
-        newDevice->generic.devcaps.dwFlags |= DIDC_FORCEFEEDBACK;
+    list_init(&This->generic.ff_effects);
+    if (get_ff(device, &This->ff) == S_OK)
+    {
+        This->generic.devcaps.dwFlags |= DIDC_FORCEFEEDBACK;
 
-        hr = FFDeviceGetForceFeedbackCapabilities(newDevice->ff, &ffcaps);
+        hr = FFDeviceGetForceFeedbackCapabilities(This->ff, &ffcaps);
         if(SUCCEEDED(hr)){
             TRACE("FF Capabilities:\n");
             TRACE("\tsupportedEffects: 0x%x\n", (unsigned int)ffcaps.supportedEffects);
@@ -1165,34 +1182,35 @@ static HRESULT joydev_create_unix_joystick(IDirectInputImpl *dinput, REFGUID gui
             TRACE("\tplaybackCapacity: %u\n", (unsigned int)ffcaps.playbackCapacity);
         }
 
-        hr = FFDeviceSendForceFeedbackCommand(newDevice->ff, FFSFFC_RESET);
+        hr = FFDeviceSendForceFeedbackCommand(This->ff, FFSFFC_RESET);
         if(FAILED(hr))
             WARN("FFDeviceSendForceFeedbackCommand(FFSFFC_RESET) failed: %08x\n", hr);
 
-        hr = FFDeviceSendForceFeedbackCommand(newDevice->ff, FFSFFC_SETACTUATORSON);
+        hr = FFDeviceSendForceFeedbackCommand(This->ff, FFSFFC_SETACTUATORSON);
         if(FAILED(hr))
             WARN("FFDeviceSendForceFeedbackCommand(FFSFFC_SETACTUATORSON) failed: %08x\n", hr);
     }
 
     memset(axis_map, 0, sizeof(axis_map));
-    get_osx_device_elements(newDevice, axis_map);
+    get_osx_device_elements(This, axis_map);
 
-    TRACE("%i axes %i buttons %i povs\n",newDevice->generic.devcaps.dwAxes,newDevice->generic.devcaps.dwButtons,newDevice->generic.devcaps.dwPOVs);
+    TRACE("%i axes %i buttons %i povs\n", This->generic.devcaps.dwAxes, This->generic.devcaps.dwButtons,
+            This->generic.devcaps.dwPOVs);
 
-    if (newDevice->generic.devcaps.dwButtons > 128)
+    if (This->generic.devcaps.dwButtons > 128)
     {
-        WARN("Can't support %d buttons. Clamping down to 128\n", newDevice->generic.devcaps.dwButtons);
-        newDevice->generic.devcaps.dwButtons = 128;
+        WARN("Can't support %d buttons. Clamping down to 128\n", This->generic.devcaps.dwButtons);
+        This->generic.devcaps.dwButtons = 128;
     }
 
     /* Create copy of default data format */
     if (!(df = HeapAlloc(GetProcessHeap(), 0, c_dfDIJoystick2.dwSize))) goto FAILED;
     memcpy(df, &c_dfDIJoystick2, c_dfDIJoystick2.dwSize);
 
-    df->dwNumObjs = newDevice->generic.devcaps.dwAxes + newDevice->generic.devcaps.dwPOVs + newDevice->generic.devcaps.dwButtons;
+    df->dwNumObjs = This->generic.devcaps.dwAxes + This->generic.devcaps.dwPOVs + This->generic.devcaps.dwButtons;
     if (!(df->rgodf = HeapAlloc(GetProcessHeap(), 0, df->dwNumObjs * df->dwObjSize))) goto FAILED;
 
-    for (i = 0; i < newDevice->generic.devcaps.dwAxes; i++)
+    for (i = 0; i < This->generic.devcaps.dwAxes; i++)
     {
         int wine_obj = -1;
         BOOL has_ff  = FALSE;
@@ -1200,31 +1218,31 @@ static HRESULT joydev_create_unix_joystick(IDirectInputImpl *dinput, REFGUID gui
         {
             case kHIDUsage_GD_X:
                 wine_obj = 0;
-                has_ff = (newDevice->ff != 0) && osx_axis_has_ff(&ffcaps, FFJOFS_X);
+                has_ff = (This->ff != 0) && osx_axis_has_ff(&ffcaps, FFJOFS_X);
                 break;
             case kHIDUsage_GD_Y:
                 wine_obj = 1;
-                has_ff = (newDevice->ff != 0) && osx_axis_has_ff(&ffcaps, FFJOFS_Y);
+                has_ff = (This->ff != 0) && osx_axis_has_ff(&ffcaps, FFJOFS_Y);
                 break;
             case kHIDUsage_GD_Z:
                 wine_obj = 2;
-                has_ff = (newDevice->ff != 0) && osx_axis_has_ff(&ffcaps, FFJOFS_Z);
+                has_ff = (This->ff != 0) && osx_axis_has_ff(&ffcaps, FFJOFS_Z);
                 break;
             case kHIDUsage_GD_Rx:
                 wine_obj = 3;
-                has_ff = (newDevice->ff != 0) && osx_axis_has_ff(&ffcaps, FFJOFS_RX);
+                has_ff = (This->ff != 0) && osx_axis_has_ff(&ffcaps, FFJOFS_RX);
                 break;
             case kHIDUsage_GD_Ry:
                 wine_obj = 4;
-                has_ff = (newDevice->ff != 0) && osx_axis_has_ff(&ffcaps, FFJOFS_RY);
+                has_ff = (This->ff != 0) && osx_axis_has_ff(&ffcaps, FFJOFS_RY);
                 break;
             case kHIDUsage_GD_Rz:
                 wine_obj = 5;
-                has_ff = (newDevice->ff != 0) && osx_axis_has_ff(&ffcaps, FFJOFS_RZ);
+                has_ff = (This->ff != 0) && osx_axis_has_ff(&ffcaps, FFJOFS_RZ);
                 break;
             case kHIDUsage_GD_Slider:
                 wine_obj = 6 + slider_count;
-                has_ff = (newDevice->ff != 0) && osx_axis_has_ff(&ffcaps, FFJOFS_SLIDER(slider_count));
+                has_ff = (This->ff != 0) && osx_axis_has_ff(&ffcaps, FFJOFS_SLIDER(slider_count));
                 slider_count++;
                 break;
         }
@@ -1237,52 +1255,47 @@ static HRESULT joydev_create_unix_joystick(IDirectInputImpl *dinput, REFGUID gui
         ++idx;
     }
 
-    for (i = 0; i < newDevice->generic.devcaps.dwPOVs; i++)
+    for (i = 0; i < This->generic.devcaps.dwPOVs; i++)
     {
         memcpy(&df->rgodf[idx], &c_dfDIJoystick2.rgodf[i + 8], df->dwObjSize);
         df->rgodf[idx++].dwType = DIDFT_MAKEINSTANCE(i) | DIDFT_POV;
     }
 
-    for (i = 0; i < newDevice->generic.devcaps.dwButtons; i++)
+    for (i = 0; i < This->generic.devcaps.dwButtons; i++)
     {
         memcpy(&df->rgodf[idx], &c_dfDIJoystick2.rgodf[i + 12], df->dwObjSize);
         df->rgodf[idx  ].pguid = &GUID_Button;
         df->rgodf[idx++].dwType = DIDFT_MAKEINSTANCE(i) | DIDFT_PSHBUTTON;
     }
-    newDevice->generic.base.data_format.wine_df = df;
+    This->generic.base.data_format.wine_df = df;
 
     /* initialize default properties */
-    get_osx_device_elements_props(newDevice);
+    get_osx_device_elements_props(This);
 
-    newDevice->generic.devcaps.dwSize = sizeof(newDevice->generic.devcaps);
-    newDevice->generic.devcaps.dwFlags |= DIDC_ATTACHED;
-    if (newDevice->generic.base.dinput->dwVersion >= 0x0800)
-        newDevice->generic.devcaps.dwDevType = DI8DEVTYPE_JOYSTICK | (DI8DEVTYPEJOYSTICK_STANDARD << 8);
-    else
-        newDevice->generic.devcaps.dwDevType = DIDEVTYPE_JOYSTICK | (DIDEVTYPEJOYSTICK_TRADITIONAL << 8);
-    newDevice->generic.devcaps.dwFFSamplePeriod = 0;
-    newDevice->generic.devcaps.dwFFMinTimeResolution = 0;
-    newDevice->generic.devcaps.dwFirmwareRevision = 0;
-    newDevice->generic.devcaps.dwHardwareRevision = 0;
-    newDevice->generic.devcaps.dwFFDriverVersion = 0;
+    This->generic.devcaps.dwSize = sizeof(This->generic.devcaps);
+    This->generic.devcaps.dwFlags |= DIDC_ATTACHED;
+    This->generic.devcaps.dwDevType = This->generic.base.info.dwDevType;
+    This->generic.devcaps.dwFFSamplePeriod = 0;
+    This->generic.devcaps.dwFFMinTimeResolution = 0;
+    This->generic.devcaps.dwFirmwareRevision = 0;
+    This->generic.devcaps.dwHardwareRevision = 0;
+    This->generic.devcaps.dwFFDriverVersion = 0;
 
     if (TRACE_ON(dinput)) {
-        TRACE("allocated device %p\n", newDevice);
-        _dump_DIDEVCAPS(&newDevice->generic.devcaps);
+        TRACE("allocated device %p\n", This);
+        _dump_DIDEVCAPS(&This->generic.devcaps);
     }
 
-    *out = &newDevice->generic;
     return DI_OK;
 
 FAILED:
     hr = DIERR_OUTOFMEMORY;
-    if (newDevice->ff) FFReleaseDevice(newDevice->ff);
-    if (newDevice->elements) CFRelease(newDevice->elements);
+    if (This->ff) FFReleaseDevice(This->ff);
+    if (This->elements) CFRelease(This->elements);
     if (df) HeapFree(GetProcessHeap(), 0, df->rgodf);
     HeapFree(GetProcessHeap(), 0, df);
-    release_DataFormat(&newDevice->generic.base.data_format);
-    HeapFree(GetProcessHeap(),0,newDevice->generic.name);
-    HeapFree(GetProcessHeap(),0,newDevice);
+    release_DataFormat(&This->generic.base.data_format);
+    HeapFree(GetProcessHeap(), 0, This->generic.name);
     return hr;
 }
 
diff --git a/dlls/dinput/joystick_private.h b/dlls/dinput/joystick_private.h
index 87e91a21133..8fe469edbc3 100644
--- a/dlls/dinput/joystick_private.h
+++ b/dlls/dinput/joystick_private.h
@@ -37,6 +37,8 @@ struct unix_joystick;
 
 struct unix_joystick_vtbl
 {
+    HRESULT (CDECL *init)(struct unix_joystick *ptr);
+
     HRESULT (CDECL *acquire)(struct unix_joystick *ptr);
     HRESULT (CDECL *unacquire)(struct unix_joystick *ptr);
 
-- 
2.28.0

>From a78c6e819ee36ef4e5f7f56c4f43d35315c559b6 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?R=C3=A9mi=20Bernon?= <rbernon@codeweavers.com>
Date: Tue, 6 Oct 2020 15:02:39 +0200
Subject: [PATCH 24/39] dinput: Use the unix vtable for default axis mapping.

So that we can load the registry settings from Win32 side.
---
 dlls/dinput/joystick.c            |  47 ++++++++++----
 dlls/dinput/joystick_linux.c      | 101 ++++++++++++++----------------
 dlls/dinput/joystick_linuxinput.c | 100 ++++++++++++++++++-----------
 dlls/dinput/joystick_osx.c        |   6 +-
 dlls/dinput/joystick_private.h    |   5 +-
 5 files changed, 151 insertions(+), 108 deletions(-)

diff --git a/dlls/dinput/joystick.c b/dlls/dinput/joystick.c
index 8cf7ff05a0b..ec46b25c2cc 100644
--- a/dlls/dinput/joystick.c
+++ b/dlls/dinput/joystick.c
@@ -1035,35 +1035,49 @@ DWORD joystick_map_pov(const POINTL *p)
  * Setup the dinput options.
  */
 
-HRESULT setup_dinput_options(JoystickGenericImpl *This, const int *default_axis_map)
+static char *string_wtoa(const WCHAR *strw)
+{
+    char *str;
+    int len;
+    if (!strw) return NULL;
+    len = WideCharToMultiByte(CP_ACP, 0, strw, -1, NULL, 0, NULL, NULL);
+    str = HeapAlloc(GetProcessHeap(), 0, len);
+    WideCharToMultiByte(CP_ACP, 0, strw, -1, str, len, NULL, NULL);
+    return str;
+}
+
+static HRESULT setup_dinput_options(JoystickGenericImpl *This, int default_axis_count, const int *default_axis_map)
 {
     char buffer[MAX_PATH+16];
     HKEY hkey, appkey;
     int tokens = 0;
     int axis = 0;
     int pov = 0;
+    char *name;
 
     get_app_key(&hkey, &appkey);
 
     /* get options */
 
-    if (!get_config_key(hkey, appkey, "DefaultDeadZone", buffer, sizeof(buffer)))
+    if (get_config_key(hkey, appkey, "DefaultDeadZone", buffer, sizeof(buffer))) This->deadzone = 0;
+    else
     {
         This->deadzone = atoi(buffer);
         TRACE("setting default deadzone to: \"%s\" %d\n", buffer, This->deadzone);
     }
 
-    This->axis_map = HeapAlloc(GetProcessHeap(), 0, This->device_axis_count * sizeof(int));
+    This->axis_map = HeapAlloc(GetProcessHeap(), 0, default_axis_count * sizeof(int));
     if (!This->axis_map) return DIERR_OUTOFMEMORY;
 
-    if (!get_config_key(hkey, appkey, This->name, buffer, sizeof(buffer)))
+    name = string_wtoa(This->base.info.tszProductName);
+    if (!get_config_key(hkey, appkey, name, buffer, sizeof(buffer)))
     {
         static const char *axis_names[] = {"X", "Y", "Z", "Rx", "Ry", "Rz",
                                            "Slider1", "Slider2",
                                            "POV1", "POV2", "POV3", "POV4"};
         const char *delim = ",";
         char * ptr;
-        TRACE("\"%s\" = \"%s\"\n", This->name, buffer);
+        TRACE("\"%s\" = \"%s\"\n", name, buffer);
 
         if ((ptr = strtok(buffer, delim)) != NULL)
         {
@@ -1113,11 +1127,10 @@ HRESULT setup_dinput_options(JoystickGenericImpl *This, const int *default_axis_
                 tokens++;
             } while ((ptr = strtok(NULL, delim)) != NULL);
 
-            if (tokens != This->device_axis_count)
+            if (tokens != default_axis_count)
             {
-                ERR("not all joystick axes mapped: %d axes(%d,%d), %d arguments\n",
-                    This->device_axis_count, axis, pov, tokens);
-                while (tokens < This->device_axis_count)
+                ERR("not all joystick axes mapped: %d axes(%d,%d), %d arguments\n", default_axis_count, axis, pov, tokens);
+                while (tokens < default_axis_count)
                 {
                     This->axis_map[tokens] = -1;
                     tokens++;
@@ -1132,7 +1145,7 @@ HRESULT setup_dinput_options(JoystickGenericImpl *This, const int *default_axis_
         if (default_axis_map)
         {
             /* Use default mapping from the driver */
-            for (i = 0; i < This->device_axis_count; i++)
+            for (i = 0; i < default_axis_count; i++)
             {
                 This->axis_map[i] = default_axis_map[i];
                 tokens = default_axis_map[i];
@@ -1151,7 +1164,7 @@ HRESULT setup_dinput_options(JoystickGenericImpl *This, const int *default_axis_
         else
         {
             /* No config - set default mapping. */
-            for (i = 0; i < This->device_axis_count; i++)
+            for (i = 0; i < default_axis_count; i++)
             {
                 if (i < 8)
                     This->axis_map[i] = axis++;
@@ -1170,6 +1183,7 @@ HRESULT setup_dinput_options(JoystickGenericImpl *This, const int *default_axis_
 
     if (appkey) RegCloseKey(appkey);
     if (hkey)   RegCloseKey(hkey);
+    HeapFree(GetProcessHeap(), 0, name);
 
     return DI_OK;
 }
@@ -1178,8 +1192,17 @@ HRESULT dinput_create_unix_joystick(const struct dinput_device *device, IDirectI
 {
     JoystickGenericImpl *This;
     HRESULT hr;
+    const int *default_axes_map;
+    int default_axis_count;
+
+    if (FAILED(hr = device->create_unix_joystick(dinput, guid, &This)))
+        return hr;
+    if (This->unix_funcs->get_mapping)
+    {
+        This->unix_funcs->get_mapping(This->unix_ptr, &default_axis_count, &default_axes_map);
+        if (FAILED(hr = setup_dinput_options(This, default_axis_count, default_axes_map))) goto done;
+    }
 
-    if (FAILED(hr = device->create_unix_joystick(dinput, guid, &This))) return hr;
     if (FAILED(hr = This->unix_funcs->init(This->unix_ptr))) goto done;
     if (FAILED(hr = IDirectInputDevice8_QueryInterface(IDirectInputDevice8W_from_impl(This), iid, out))) goto done;
 
diff --git a/dlls/dinput/joystick_linux.c b/dlls/dinput/joystick_linux.c
index 873ee88c20c..48c1e4b433a 100644
--- a/dlls/dinput/joystick_linux.c
+++ b/dlls/dinput/joystick_linux.c
@@ -82,7 +82,7 @@ struct JoyDev
 
     BYTE axis_count;
     BYTE button_count;
-    int  *dev_axes_map;
+    int axes_map[ABS_MAX + 1];
 
     WORD vendor_id, product_id, bus_type;
 
@@ -139,10 +139,12 @@ static HRESULT CDECL unix_joystick_acquire(struct unix_joystick *ptr);
 static HRESULT CDECL unix_joystick_unacquire(struct unix_joystick *ptr);
 
 static HRESULT CDECL unix_joystick_init(struct unix_joystick *ptr);
+static void CDECL unix_joystick_get_mapping(struct unix_joystick *ptr, int *axis_count, const int **axes_map);
 
 static const struct unix_joystick_vtbl unix_joystick_vtbl =
 {
     unix_joystick_init,
+    unix_joystick_get_mapping,
     unix_joystick_acquire,
     unix_joystick_unacquire,
     NULL,
@@ -180,7 +182,7 @@ static BOOL read_sys_id_variable(int index, const char *property, WORD *value)
 
 static INT find_joystick_devices(void)
 {
-    INT i;
+    INT i, j;
 
     if (joystick_devices_count != -1) return joystick_devices_count;
 
@@ -237,7 +239,6 @@ static INT find_joystick_devices(void)
         }
         else
         {
-            INT j;
             /* in lieu of properly reporting HID usage, detect presence of
              * "joystick buttons" and report those devices as joysticks instead of
              * gamepads */
@@ -280,54 +281,50 @@ static INT find_joystick_devices(void)
         if (ioctl(fd, JSIOCGAXMAP, axes_map) < 0)
         {
             WARN("ioctl(%s,JSIOCGAXMAP) failed: %s\n", joydev.device, strerror(errno));
-            joydev.dev_axes_map = NULL;
+            for (j = 0; j < joydev.axis_count; j++)
+                joydev.axes_map[j] = j;
         }
         else
-            if ((joydev.dev_axes_map = HeapAlloc(GetProcessHeap(), 0, joydev.axis_count * sizeof(int))))
-            {
-                INT j, found_axes = 0;
+        {
+            INT found_axes = 0;
 
-                /* Remap to DI numbers */
-                for (j = 0; j < joydev.axis_count; j++)
+            /* Remap to DI numbers */
+            for (j = 0; j < joydev.axis_count; j++)
+            {
+                if (axes_map[j] < 8)
                 {
-                    if (axes_map[j] < 8)
-                    {
-                        /* Axis match 1-to-1 */
-                        joydev.dev_axes_map[j] = j;
-                        found_axes++;
-                    }
-                    else if (axes_map[j] <= 10)
-                    {
-                        /* Axes 8 through 10 are Wheel, Gas and Brake,
-                         * remap to 0, 1 and 2
-                         */
-                        joydev.dev_axes_map[j] = axes_map[j] - 8;
-                        found_axes++;
-                    }
-                    else if (axes_map[j] == 16 ||
-                             axes_map[j] == 17)
-                    {
-                        /* POV axis */
-                        joydev.dev_axes_map[j] = 8;
-                        found_axes++;
-                    }
-                    else
-                        joydev.dev_axes_map[j] = -1;
+                    /* Axis match 1-to-1 */
+                    joydev.axes_map[j] = j;
+                    found_axes++;
                 }
-
-                /* If no axes were configured but there are axes assume a 1-to-1 (wii controller) */
-                if (joydev.axis_count && !found_axes)
+                else if (axes_map[j] <= 10)
                 {
-                    int axes_limit = min(joydev.axis_count, 8); /* generic driver limit */
+                    /* Axes 8 through 10 are Wheel, Gas and Brake,
+                     * remap to 0, 1 and 2
+                     */
+                    joydev.axes_map[j] = axes_map[j] - 8;
+                    found_axes++;
+                }
+                else if (axes_map[j] == 16 || axes_map[j] == 17)
+                {
+                    /* POV axis */
+                    joydev.axes_map[j] = 8;
+                    found_axes++;
+                }
+                else joydev.axes_map[j] = -1;
+            }
 
-                    ERR("Incoherent joystick data, advertised %d axes, detected 0. Assuming 1-to-1.\n",
-                        joydev.axis_count);
-                    for (j = 0; j < axes_limit; j++)
-                        joydev.dev_axes_map[j] = j;
+            /* If no axes were configured but there are axes assume a 1-to-1 (wii controller) */
+            if (joydev.axis_count && !found_axes)
+            {
+                int axes_limit = min(joydev.axis_count, 8); /* generic driver limit */
 
-                    joydev.axis_count = axes_limit;
-                }
+                ERR("Incoherent joystick data, advertised %d axes, detected 0. Assuming 1-to-1.\n", joydev.axis_count);
+                for (j = 0; j < axes_limit; j++) joydev.axes_map[j] = j;
+
+                joydev.axis_count = axes_limit;
             }
+        }
 
         /* Find vendor_id and product_id in sysfs */
         joydev.vendor_id  = 0;
@@ -503,6 +500,13 @@ static HRESULT joydev_create_unix_joystick(IDirectInputImpl *dinput, REFGUID gui
     return DI_OK;
 }
 
+static void CDECL unix_joystick_get_mapping(struct unix_joystick *ptr, int *axis_count, const int **axes_map)
+{
+    JoystickImpl *This = impl_from_unix_joystick(ptr);
+    *axis_count = This->joydev->axis_count;
+    *axes_map = This->joydev->axes_map;
+}
+
 static HRESULT CDECL unix_joystick_init(struct unix_joystick *ptr)
 {
     JoystickImpl *This = impl_from_unix_joystick(ptr);
@@ -510,8 +514,6 @@ static HRESULT CDECL unix_joystick_init(struct unix_joystick *ptr)
     HRESULT hr;
     DWORD i, idx = 0;
 
-    This->generic.name = This->joydev->name;
-    This->generic.device_axis_count = This->joydev->axis_count;
     This->generic.devcaps.dwButtons = This->joydev->button_count;
 
     if (This->generic.devcaps.dwButtons > 128)
@@ -520,12 +522,6 @@ static HRESULT CDECL unix_joystick_init(struct unix_joystick *ptr)
         This->generic.devcaps.dwButtons = 128;
     }
 
-    /* setup_dinput_options may change these */
-    This->generic.deadzone = 0;
-
-    /* do any user specified configuration */
-    if (FAILED(hr = setup_dinput_options(&This->generic, This->joydev->dev_axes_map))) goto failed;
-
     /* Create copy of default data format */
     hr = DIERR_OUTOFMEMORY;
     if (!(df = HeapAlloc(GetProcessHeap(), 0, c_dfDIJoystick2.dwSize))) goto failed;
@@ -534,7 +530,7 @@ static HRESULT CDECL unix_joystick_init(struct unix_joystick *ptr)
     df->dwNumObjs = This->generic.devcaps.dwAxes + This->generic.devcaps.dwPOVs + This->generic.devcaps.dwButtons;
     if (!(df->rgodf = HeapAlloc(GetProcessHeap(), 0, df->dwNumObjs * df->dwObjSize))) goto failed;
 
-    for (i = 0; i < This->generic.device_axis_count; i++)
+    for (i = 0; i < This->joydev->axis_count; i++)
     {
         int wine_obj = This->generic.axis_map[i];
 
@@ -578,8 +574,7 @@ static HRESULT CDECL unix_joystick_init(struct unix_joystick *ptr)
     This->generic.devcaps.dwFFDriverVersion = 0;
 
     if (TRACE_ON(dinput)) {
-        for (i = 0; i < (This->generic.device_axis_count); i++)
-            TRACE("axis_map[%d] = %d\n", i, This->generic.axis_map[i]);
+        for (i = 0; i < (This->joydev->axis_count); i++) TRACE("axis_map[%d] = %d\n", i, This->generic.axis_map[i]);
         _dump_DIDEVCAPS(&This->generic.devcaps);
     }
 
diff --git a/dlls/dinput/joystick_linuxinput.c b/dlls/dinput/joystick_linuxinput.c
index 5f0df95e3d0..4206012e58e 100644
--- a/dlls/dinput/joystick_linuxinput.c
+++ b/dlls/dinput/joystick_linuxinput.c
@@ -110,6 +110,14 @@ struct JoyDev {
         struct wine_input_absinfo       axes[ABS_MAX];
 
         WORD vendor_id, product_id, bus_type;
+
+    /* LUT for KEY_ to offset in rgbButtons */
+    int button_count;
+    BYTE buttons[KEY_MAX];
+    int dev_axes_to_di[ABS_MAX];
+
+    int axis_count;
+    int axes_map[WINE_JOYSTICK_MAX_AXES + WINE_JOYSTICK_MAX_POVS * 2];
 };
 
 struct JoystickImpl
@@ -120,12 +128,8 @@ struct JoystickImpl
 	/* joystick private */
 	int				joyfd;
 
-	int                             dev_axes_to_di[ABS_MAX];
         POINTL                          povs[4];
 
-	/* LUT for KEY_ to offset in rgbButtons */
-	BYTE				buttons[KEY_MAX];
-
 	/* Force feedback variables */
 	int				ff_state;
 	int				ff_autocenter;
@@ -170,10 +174,12 @@ static HRESULT CDECL unix_joystick_create_effect(struct unix_joystick *ptr, REFG
         struct list *entry, IDirectInputEffect **out);
 
 static HRESULT CDECL unix_joystick_init(struct unix_joystick *ptr);
+static void CDECL unix_joystick_get_mapping(struct unix_joystick *ptr, int *axis_count, const int **axes_map);
 
 static const struct unix_joystick_vtbl unix_joystick_vtbl =
 {
     unix_joystick_init,
+    unix_joystick_get_mapping,
     unix_joystick_acquire,
     unix_joystick_unacquire,
     unix_joystick_ff_set_autocenter,
@@ -207,7 +213,7 @@ static struct JoyDev *joydevs = NULL;
 
 static void find_joydevs(void)
 {
-    int i;
+    int i, idx;
 
     if (InterlockedCompareExchange(&have_joydevs, 0, -1) != -1)
         /* Someone beat us to it */
@@ -344,6 +350,44 @@ static void find_joydevs(void)
 	    }
 	}
 
+        /* Count number of available axes - supported Axis & POVs */
+        for (i = 0, idx = 0; i < ABS_MAX; i++)
+        {
+            if (idx < WINE_JOYSTICK_MAX_AXES && i < ABS_HAT0X && test_bit(joydev.absbits, i))
+            {
+                joydev.dev_axes_to_di[i] = idx;
+                joydev.axis_count++;
+                /* If it's a wheel axis, remap to X/Y/Z */
+                if (i >= 8 && i <= 10) joydev.axes_map[idx] = i - 8;
+                else joydev.axes_map[idx] = i;
+                idx++;
+            }
+            else joydev.dev_axes_to_di[i] = -1;
+        }
+
+        for (i = 0; i < WINE_JOYSTICK_MAX_POVS; i++)
+        {
+            if (test_bit(joydev.absbits, ABS_HAT0X + i * 2) && test_bit(joydev.absbits, ABS_HAT0Y + i * 2))
+            {
+                joydev.axis_count += 2;
+                joydev.axes_map[idx] = joydev.axes_map[idx + 1] = WINE_JOYSTICK_MAX_AXES + i;
+                joydev.dev_axes_to_di[ABS_HAT0X + i * 2] = idx;
+                joydev.dev_axes_to_di[ABS_HAT0Y + i * 2] = idx + 1;
+                idx += 2;
+            }
+            else joydev.dev_axes_to_di[ABS_HAT0X + i * 2] = joydev.dev_axes_to_di[ABS_HAT0Y + i * 2] = -1;
+        }
+
+        /* Buttons can be anywhere, so check all */
+        joydev.button_count = 0;
+        memset(joydev.buttons, 0, sizeof(joydev.buttons));
+        for (i = 0; i < KEY_MAX && joydev.button_count < WINE_JOYSTICK_MAX_BUTTONS; i++)
+        {
+            if (!test_bit(joydev.keybits, i)) continue;
+            joydev.buttons[i] = 0x80 | joydev.button_count;
+            joydev.button_count++;
+        }
+
         if (ioctl(fd, EVIOCGID, &device_id) == -1)
         {
             WARN("ioctl(EVIOCGID) failed: %d %s\n", errno, strerror(errno));
@@ -508,14 +552,20 @@ static HRESULT joydev_create_unix_joystick(IDirectInputImpl *dinput, REFGUID gui
     return DI_OK;
 }
 
+static void CDECL unix_joystick_get_mapping(struct unix_joystick *ptr, int *axis_count, const int **axes_map)
+{
+    JoystickImpl *This = impl_from_unix_joystick(ptr);
+    *axis_count = This->joydev->axis_count;
+    *axes_map = This->joydev->axes_map;
+}
+
 static HRESULT CDECL unix_joystick_init(struct unix_joystick *ptr)
 {
     JoystickImpl *This = impl_from_unix_joystick(ptr);
     LPDIDATAFORMAT df = NULL;
     HRESULT hr;
-    int i, idx = 0, default_axis_map[WINE_JOYSTICK_MAX_AXES + WINE_JOYSTICK_MAX_POVS * 2];
+    int i, idx = 0;
 
-    This->generic.name = This->joydev->name;
     list_init(&This->generic.ff_effects);
 #ifdef HAVE_STRUCT_FF_EFFECT_DIRECTION
     This->ff_state = FF_STATUS_STOPPED;
@@ -533,40 +583,24 @@ static HRESULT CDECL unix_joystick_init(struct unix_joystick *ptr)
     {
         if (idx < WINE_JOYSTICK_MAX_AXES && i < ABS_HAT0X && test_bit(This->joydev->absbits, i))
         {
-            This->generic.device_axis_count++;
-            This->dev_axes_to_di[i] = idx;
             This->generic.props[idx].lDevMin = This->joydev->axes[i].minimum;
             This->generic.props[idx].lDevMax = This->joydev->axes[i].maximum;
-            if (i >= 8 && i <= 10) /* If it's a wheel axis... */
-                default_axis_map[idx] = i - 8; /* ... remap to X/Y/Z */
-            else
-                default_axis_map[idx] = i;
             idx++;
         }
-        else This->dev_axes_to_di[i] = -1;
     }
 
     for (i = 0; i < WINE_JOYSTICK_MAX_POVS; i++)
     {
         if (test_bit(This->joydev->absbits, ABS_HAT0X + i * 2) && test_bit(This->joydev->absbits, ABS_HAT0Y + i * 2))
         {
-            This->generic.device_axis_count += 2;
             This->generic.props[idx].lDevMin = This->joydev->axes[ABS_HAT0X + i * 2].minimum;
             This->generic.props[idx].lDevMax = This->joydev->axes[ABS_HAT0X + i * 2].maximum;
-            This->dev_axes_to_di[ABS_HAT0X + i * 2] = idx;
             This->generic.props[idx + 1].lDevMin = This->joydev->axes[ABS_HAT0Y + i * 2].minimum;
             This->generic.props[idx + 1].lDevMax = This->joydev->axes[ABS_HAT0Y + i * 2].maximum;
-            This->dev_axes_to_di[ABS_HAT0Y + i * 2] = idx + 1;
-
-            default_axis_map[idx] = default_axis_map[idx + 1] = WINE_JOYSTICK_MAX_AXES + i;
             idx += 2;
         }
-        else This->dev_axes_to_di[ABS_HAT0X + i * 2] = This->dev_axes_to_di[ABS_HAT0Y + i * 2] = -1;
     }
 
-    /* do any user specified configuration */
-    if (FAILED(hr = setup_dinput_options(&This->generic, default_axis_map) != DI_OK)) goto failed;
-
     /* Create copy of default data format */
     hr = DIERR_OUTOFMEMORY;
     if (!(df = HeapAlloc(GetProcessHeap(), 0, c_dfDIJoystick2.dwSize))) goto failed;
@@ -577,7 +611,7 @@ static HRESULT CDECL unix_joystick_init(struct unix_joystick *ptr)
     /* Construct internal data format */
 
     /* Supported Axis & POVs */
-    for (i = 0, idx = 0; i < This->generic.device_axis_count; i++)
+    for (i = 0, idx = 0; i < This->joydev->axis_count; i++)
     {
         int wine_obj = This->generic.axis_map[i];
 
@@ -603,17 +637,14 @@ static HRESULT CDECL unix_joystick_init(struct unix_joystick *ptr)
         idx++;
     }
 
-    /* Buttons can be anywhere, so check all */
-    for (i = 0; i < KEY_MAX && This->generic.devcaps.dwButtons < WINE_JOYSTICK_MAX_BUTTONS; i++)
+    for (i = 0; i < This->joydev->button_count; i++)
     {
-        if (!test_bit(This->joydev->keybits, i)) continue;
-
-        memcpy(&df->rgodf[idx], &c_dfDIJoystick2.rgodf[This->generic.devcaps.dwButtons + 12], df->dwObjSize);
-        This->buttons[i] = 0x80 | This->generic.devcaps.dwButtons;
+        memcpy(&df->rgodf[idx], &c_dfDIJoystick2.rgodf[i + 12], df->dwObjSize);
         df->rgodf[idx  ].pguid = &GUID_Button;
-        df->rgodf[idx++].dwType = DIDFT_MAKEINSTANCE(This->generic.devcaps.dwButtons++) | DIDFT_PSHBUTTON;
+        df->rgodf[idx++].dwType = DIDFT_MAKEINSTANCE(i) | DIDFT_PSHBUTTON;
     }
     df->dwNumObjs = idx;
+    This->generic.devcaps.dwButtons = This->joydev->button_count;
     This->generic.base.data_format.wine_df = df;
 
     fake_current_js_state(This);
@@ -746,8 +777,7 @@ static HRESULT CDECL unix_joystick_ff_set_gain(struct unix_joystick *ptr, DWORD
  * values on the axes
  */
 #define CENTER_AXIS(a) \
-    (ji->dev_axes_to_di[a] == -1 ? 0 : joystick_map_axis( &ji->generic.props[ji->dev_axes_to_di[a]], \
-                                                          ji->joydev->axes[a].value ))
+    (ji->joydev->dev_axes_to_di[a] == -1 ? 0 : joystick_map_axis(&ji->generic.props[ji->joydev->dev_axes_to_di[a]], ji->joydev->axes[a].value))
 static void fake_current_js_state(JoystickImpl *ji)
 {
     int i;
@@ -798,7 +828,7 @@ static void CDECL unix_joystick_poll(struct unix_joystick *ptr)
 	switch (ie.type) {
 	case EV_KEY:	/* button */
         {
-            int btn = This->buttons[ie.code];
+            int btn = This->joydev->buttons[ie.code];
 
             TRACE("(%p) %d -> %d\n", This, ie.code, btn);
             if (btn & 0x80)
@@ -811,7 +841,7 @@ static void CDECL unix_joystick_poll(struct unix_joystick *ptr)
         }
 	case EV_ABS:
         {
-            int axis = This->dev_axes_to_di[ie.code];
+            int axis = This->joydev->dev_axes_to_di[ie.code];
 
             /* User axis remapping */
             if (axis < 0) break;
diff --git a/dlls/dinput/joystick_osx.c b/dlls/dinput/joystick_osx.c
index 2d25f50ebe2..fbde8fc5b3c 100644
--- a/dlls/dinput/joystick_osx.c
+++ b/dlls/dinput/joystick_osx.c
@@ -956,6 +956,7 @@ static const struct unix_joystick_vtbl unix_joystick_vtbl =
     unix_joystick_init,
     NULL,
     NULL,
+    NULL,
     unix_joystick_ff_set_autocenter,
     unix_joystick_ff_set_gain,
     NULL,
@@ -1155,10 +1156,6 @@ static HRESULT CDECL unix_joystick_init(struct unix_joystick *ptr)
     get_osx_device_name(This->id, name, MAX_PATH);
     TRACE("Name %s\n",name);
 
-    /* copy the device name */
-    This->generic.name = HeapAlloc(GetProcessHeap(), 0, strlen(name) + 1);
-    strcpy(This->generic.name, name);
-
     list_init(&This->generic.ff_effects);
     if (get_ff(device, &This->ff) == S_OK)
     {
@@ -1295,7 +1292,6 @@ FAILED:
     if (df) HeapFree(GetProcessHeap(), 0, df->rgodf);
     HeapFree(GetProcessHeap(), 0, df);
     release_DataFormat(&This->generic.base.data_format);
-    HeapFree(GetProcessHeap(), 0, This->generic.name);
     return hr;
 }
 
diff --git a/dlls/dinput/joystick_private.h b/dlls/dinput/joystick_private.h
index 8fe469edbc3..3c73bd9c41e 100644
--- a/dlls/dinput/joystick_private.h
+++ b/dlls/dinput/joystick_private.h
@@ -39,6 +39,8 @@ struct unix_joystick_vtbl
 {
     HRESULT (CDECL *init)(struct unix_joystick *ptr);
 
+    void (CDECL *get_mapping)(struct unix_joystick *ptr, int *axis_count, const int **axes_map);
+
     HRESULT (CDECL *acquire)(struct unix_joystick *ptr);
     HRESULT (CDECL *unacquire)(struct unix_joystick *ptr);
 
@@ -63,8 +65,6 @@ typedef struct JoystickGenericImpl
     ObjProps    props[MAX_PROPS];
     DIDEVCAPS   devcaps;
     DIJOYSTATE2 js;     /* wine data */
-    char        *name;
-    int         device_axis_count;      /* Total number of axes in the device */
     int        *axis_map;               /* User axes remapping */
     LONG        deadzone;               /* Default dead-zone */
 
@@ -76,7 +76,6 @@ typedef struct JoystickGenericImpl
 extern HRESULT dinput_create_unix_joystick(const struct dinput_device *device, IDirectInputImpl *dinput, REFGUID guid, REFIID iid, void **out) DECLSPEC_HIDDEN;
 
 LONG joystick_map_axis(ObjProps *props, int val) DECLSPEC_HIDDEN;
-HRESULT setup_dinput_options(JoystickGenericImpl *This, const int *default_axis_map) DECLSPEC_HIDDEN;
 
 DWORD joystick_map_pov(const POINTL *p) DECLSPEC_HIDDEN;
 
-- 
2.28.0

>From 8d5eed4a360dbf818652144c36c5a06401ead38b Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?R=C3=A9mi=20Bernon?= <rbernon@codeweavers.com>
Date: Tue, 6 Oct 2020 17:35:47 +0200
Subject: [PATCH 25/39] dinput: Use the unix vtable for initial reset.

---
 dlls/dinput/joystick.c            |  1 +
 dlls/dinput/joystick_linux.c      |  1 +
 dlls/dinput/joystick_linuxinput.c | 28 ++++++++++++++--------------
 dlls/dinput/joystick_osx.c        |  1 +
 dlls/dinput/joystick_private.h    |  1 +
 5 files changed, 18 insertions(+), 14 deletions(-)

diff --git a/dlls/dinput/joystick.c b/dlls/dinput/joystick.c
index ec46b25c2cc..c9b683007d5 100644
--- a/dlls/dinput/joystick.c
+++ b/dlls/dinput/joystick.c
@@ -1204,6 +1204,7 @@ HRESULT dinput_create_unix_joystick(const struct dinput_device *device, IDirectI
     }
 
     if (FAILED(hr = This->unix_funcs->init(This->unix_ptr))) goto done;
+    if (This->unix_funcs->reset) This->unix_funcs->reset(This->unix_ptr);
     if (FAILED(hr = IDirectInputDevice8_QueryInterface(IDirectInputDevice8W_from_impl(This), iid, out))) goto done;
 
     TRACE("created unix joystick %p\n", This);
diff --git a/dlls/dinput/joystick_linux.c b/dlls/dinput/joystick_linux.c
index 48c1e4b433a..b6f52ded2e4 100644
--- a/dlls/dinput/joystick_linux.c
+++ b/dlls/dinput/joystick_linux.c
@@ -144,6 +144,7 @@ static void CDECL unix_joystick_get_mapping(struct unix_joystick *ptr, int *axis
 static const struct unix_joystick_vtbl unix_joystick_vtbl =
 {
     unix_joystick_init,
+    NULL,
     unix_joystick_get_mapping,
     unix_joystick_acquire,
     unix_joystick_unacquire,
diff --git a/dlls/dinput/joystick_linuxinput.c b/dlls/dinput/joystick_linuxinput.c
index 4206012e58e..87aa60b85e2 100644
--- a/dlls/dinput/joystick_linuxinput.c
+++ b/dlls/dinput/joystick_linuxinput.c
@@ -156,7 +156,6 @@ static inline JoystickImpl *impl_from_unix_joystick(struct unix_joystick *ptr)
     return (JoystickImpl *)ptr;
 }
 
-static void fake_current_js_state(JoystickImpl *ji);
 static void find_joydevs(void);
 static void CDECL unix_joystick_poll(struct unix_joystick *ptr);
 
@@ -174,11 +173,13 @@ static HRESULT CDECL unix_joystick_create_effect(struct unix_joystick *ptr, REFG
         struct list *entry, IDirectInputEffect **out);
 
 static HRESULT CDECL unix_joystick_init(struct unix_joystick *ptr);
+static void CDECL unix_joystick_reset(struct unix_joystick *ptr);
 static void CDECL unix_joystick_get_mapping(struct unix_joystick *ptr, int *axis_count, const int **axes_map);
 
 static const struct unix_joystick_vtbl unix_joystick_vtbl =
 {
     unix_joystick_init,
+    unix_joystick_reset,
     unix_joystick_get_mapping,
     unix_joystick_acquire,
     unix_joystick_unacquire,
@@ -647,8 +648,6 @@ static HRESULT CDECL unix_joystick_init(struct unix_joystick *ptr)
     This->generic.devcaps.dwButtons = This->joydev->button_count;
     This->generic.base.data_format.wine_df = df;
 
-    fake_current_js_state(This);
-
     /* Fill the caps */
     This->generic.devcaps.dwSize = sizeof(This->generic.devcaps);
     This->generic.devcaps.dwFlags = DIDC_ATTACHED;
@@ -777,24 +776,25 @@ static HRESULT CDECL unix_joystick_ff_set_gain(struct unix_joystick *ptr, DWORD
  * values on the axes
  */
 #define CENTER_AXIS(a) \
-    (ji->joydev->dev_axes_to_di[a] == -1 ? 0 : joystick_map_axis(&ji->generic.props[ji->joydev->dev_axes_to_di[a]], ji->joydev->axes[a].value))
-static void fake_current_js_state(JoystickImpl *ji)
+    (This->joydev->dev_axes_to_di[a] == -1 ? 0 : joystick_map_axis(&This->generic.props[This->joydev->dev_axes_to_di[a]], This->joydev->axes[a].value))
+static void CDECL unix_joystick_reset(struct unix_joystick *ptr)
 {
+    JoystickImpl *This = impl_from_unix_joystick(ptr);
     int i;
 
     /* center the axes */
-    ji->generic.js.lX           = CENTER_AXIS(ABS_X);
-    ji->generic.js.lY           = CENTER_AXIS(ABS_Y);
-    ji->generic.js.lZ           = CENTER_AXIS(ABS_Z);
-    ji->generic.js.lRx          = CENTER_AXIS(ABS_RX);
-    ji->generic.js.lRy          = CENTER_AXIS(ABS_RY);
-    ji->generic.js.lRz          = CENTER_AXIS(ABS_RZ);
-    ji->generic.js.rglSlider[0] = CENTER_AXIS(ABS_THROTTLE);
-    ji->generic.js.rglSlider[1] = CENTER_AXIS(ABS_RUDDER);
+    This->generic.js.lX           = CENTER_AXIS(ABS_X);
+    This->generic.js.lY           = CENTER_AXIS(ABS_Y);
+    This->generic.js.lZ           = CENTER_AXIS(ABS_Z);
+    This->generic.js.lRx          = CENTER_AXIS(ABS_RX);
+    This->generic.js.lRy          = CENTER_AXIS(ABS_RY);
+    This->generic.js.lRz          = CENTER_AXIS(ABS_RZ);
+    This->generic.js.rglSlider[0] = CENTER_AXIS(ABS_THROTTLE);
+    This->generic.js.rglSlider[1] = CENTER_AXIS(ABS_RUDDER);
 
     /* POV center is -1 */
     for (i = 0; i < 4; i++)
-        ji->generic.js.rgdwPOV[i] = -1;
+        This->generic.js.rgdwPOV[i] = -1;
 }
 #undef CENTER_AXIS
 
diff --git a/dlls/dinput/joystick_osx.c b/dlls/dinput/joystick_osx.c
index fbde8fc5b3c..a6c5512c767 100644
--- a/dlls/dinput/joystick_osx.c
+++ b/dlls/dinput/joystick_osx.c
@@ -957,6 +957,7 @@ static const struct unix_joystick_vtbl unix_joystick_vtbl =
     NULL,
     NULL,
     NULL,
+    NULL,
     unix_joystick_ff_set_autocenter,
     unix_joystick_ff_set_gain,
     NULL,
diff --git a/dlls/dinput/joystick_private.h b/dlls/dinput/joystick_private.h
index 3c73bd9c41e..c2786bb4aeb 100644
--- a/dlls/dinput/joystick_private.h
+++ b/dlls/dinput/joystick_private.h
@@ -38,6 +38,7 @@ struct unix_joystick;
 struct unix_joystick_vtbl
 {
     HRESULT (CDECL *init)(struct unix_joystick *ptr);
+    void (CDECL *reset)(struct unix_joystick *ptr);
 
     void (CDECL *get_mapping)(struct unix_joystick *ptr, int *axis_count, const int **axes_map);
 
-- 
2.28.0

>From 7ab59a47a623c0425cdc3a40ee81be7cd2077834 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?R=C3=A9mi=20Bernon?= <rbernon@codeweavers.com>
Date: Tue, 6 Oct 2020 10:56:49 +0200
Subject: [PATCH 26/39] dinput: Pass props to unix joystick init.

---
 dlls/dinput/joystick.c            | 17 +++++++++++++++--
 dlls/dinput/joystick_linux.c      | 14 ++------------
 dlls/dinput/joystick_linuxinput.c | 24 ++++++++++++------------
 dlls/dinput/joystick_osx.c        | 17 ++++++-----------
 dlls/dinput/joystick_private.h    |  2 +-
 5 files changed, 36 insertions(+), 38 deletions(-)

diff --git a/dlls/dinput/joystick.c b/dlls/dinput/joystick.c
index c9b683007d5..faefe593354 100644
--- a/dlls/dinput/joystick.c
+++ b/dlls/dinput/joystick.c
@@ -1191,9 +1191,10 @@ static HRESULT setup_dinput_options(JoystickGenericImpl *This, int default_axis_
 HRESULT dinput_create_unix_joystick(const struct dinput_device *device, IDirectInputImpl *dinput, REFGUID guid, REFIID iid, void **out)
 {
     JoystickGenericImpl *This;
+    ObjProps props[MAX_PROPS];
     HRESULT hr;
     const int *default_axes_map;
-    int default_axis_count;
+    int i, default_axis_count;
 
     if (FAILED(hr = device->create_unix_joystick(dinput, guid, &This)))
         return hr;
@@ -1203,7 +1204,19 @@ HRESULT dinput_create_unix_joystick(const struct dinput_device *device, IDirectI
         if (FAILED(hr = setup_dinput_options(This, default_axis_count, default_axes_map))) goto done;
     }
 
-    if (FAILED(hr = This->unix_funcs->init(This->unix_ptr))) goto done;
+    for (i = 0; i < c_dfDIJoystick2.dwNumObjs; i++)
+    {
+        props[i].lDevMin = -32767;
+        props[i].lDevMax = +32767;
+        props[i].lMin = 0;
+        props[i].lMax = 0xffff;
+        props[i].lDeadZone = This->deadzone;
+        props[i].lSaturation = 0;
+    }
+
+    if (FAILED(hr = This->unix_funcs->init(This->unix_ptr, props))) goto done;
+    memcpy(This->props, props, sizeof(This->props));
+
     if (This->unix_funcs->reset) This->unix_funcs->reset(This->unix_ptr);
     if (FAILED(hr = IDirectInputDevice8_QueryInterface(IDirectInputDevice8W_from_impl(This), iid, out))) goto done;
 
diff --git a/dlls/dinput/joystick_linux.c b/dlls/dinput/joystick_linux.c
index b6f52ded2e4..166c8e85a2a 100644
--- a/dlls/dinput/joystick_linux.c
+++ b/dlls/dinput/joystick_linux.c
@@ -138,7 +138,7 @@ static void CDECL unix_joystick_poll(struct unix_joystick *ptr);
 static HRESULT CDECL unix_joystick_acquire(struct unix_joystick *ptr);
 static HRESULT CDECL unix_joystick_unacquire(struct unix_joystick *ptr);
 
-static HRESULT CDECL unix_joystick_init(struct unix_joystick *ptr);
+static HRESULT CDECL unix_joystick_init(struct unix_joystick *ptr, ObjProps *props);
 static void CDECL unix_joystick_get_mapping(struct unix_joystick *ptr, int *axis_count, const int **axes_map);
 
 static const struct unix_joystick_vtbl unix_joystick_vtbl =
@@ -508,7 +508,7 @@ static void CDECL unix_joystick_get_mapping(struct unix_joystick *ptr, int *axis
     *axes_map = This->joydev->axes_map;
 }
 
-static HRESULT CDECL unix_joystick_init(struct unix_joystick *ptr)
+static HRESULT CDECL unix_joystick_init(struct unix_joystick *ptr, ObjProps *props)
 {
     JoystickImpl *This = impl_from_unix_joystick(ptr);
     LPDIDATAFORMAT df = NULL;
@@ -554,16 +554,6 @@ static HRESULT CDECL unix_joystick_init(struct unix_joystick *ptr)
     }
     This->generic.base.data_format.wine_df = df;
 
-    /* initialize default properties */
-    for (i = 0; i < c_dfDIJoystick2.dwNumObjs; i++) {
-        This->generic.props[i].lDevMin = -32767;
-        This->generic.props[i].lDevMax = +32767;
-        This->generic.props[i].lMin = 0;
-        This->generic.props[i].lMax = 0xffff;
-        This->generic.props[i].lDeadZone = This->generic.deadzone; /* % * 1000 */
-        This->generic.props[i].lSaturation = 0;
-    }
-
     This->generic.devcaps.dwSize = sizeof(This->generic.devcaps);
     This->generic.devcaps.dwFlags = DIDC_ATTACHED;
     This->generic.devcaps.dwDevType = This->generic.base.info.dwDevType;
diff --git a/dlls/dinput/joystick_linuxinput.c b/dlls/dinput/joystick_linuxinput.c
index 87aa60b85e2..0bf8f34dec5 100644
--- a/dlls/dinput/joystick_linuxinput.c
+++ b/dlls/dinput/joystick_linuxinput.c
@@ -172,7 +172,7 @@ static HRESULT CDECL unix_joystick_get_effect_info(struct unix_joystick *ptr, RE
 static HRESULT CDECL unix_joystick_create_effect(struct unix_joystick *ptr, REFGUID guid, const DIEFFECT *effect,
         struct list *entry, IDirectInputEffect **out);
 
-static HRESULT CDECL unix_joystick_init(struct unix_joystick *ptr);
+static HRESULT CDECL unix_joystick_init(struct unix_joystick *ptr, ObjProps *props);
 static void CDECL unix_joystick_reset(struct unix_joystick *ptr);
 static void CDECL unix_joystick_get_mapping(struct unix_joystick *ptr, int *axis_count, const int **axes_map);
 
@@ -560,7 +560,7 @@ static void CDECL unix_joystick_get_mapping(struct unix_joystick *ptr, int *axis
     *axes_map = This->joydev->axes_map;
 }
 
-static HRESULT CDECL unix_joystick_init(struct unix_joystick *ptr)
+static HRESULT CDECL unix_joystick_init(struct unix_joystick *ptr, ObjProps *props)
 {
     JoystickImpl *This = impl_from_unix_joystick(ptr);
     LPDIDATAFORMAT df = NULL;
@@ -584,8 +584,8 @@ static HRESULT CDECL unix_joystick_init(struct unix_joystick *ptr)
     {
         if (idx < WINE_JOYSTICK_MAX_AXES && i < ABS_HAT0X && test_bit(This->joydev->absbits, i))
         {
-            This->generic.props[idx].lDevMin = This->joydev->axes[i].minimum;
-            This->generic.props[idx].lDevMax = This->joydev->axes[i].maximum;
+            props[idx].lDevMin = This->joydev->axes[i].minimum;
+            props[idx].lDevMax = This->joydev->axes[i].maximum;
             idx++;
         }
     }
@@ -594,10 +594,10 @@ static HRESULT CDECL unix_joystick_init(struct unix_joystick *ptr)
     {
         if (test_bit(This->joydev->absbits, ABS_HAT0X + i * 2) && test_bit(This->joydev->absbits, ABS_HAT0Y + i * 2))
         {
-            This->generic.props[idx].lDevMin = This->joydev->axes[ABS_HAT0X + i * 2].minimum;
-            This->generic.props[idx].lDevMax = This->joydev->axes[ABS_HAT0X + i * 2].maximum;
-            This->generic.props[idx + 1].lDevMin = This->joydev->axes[ABS_HAT0Y + i * 2].minimum;
-            This->generic.props[idx + 1].lDevMax = This->joydev->axes[ABS_HAT0Y + i * 2].maximum;
+            props[idx].lDevMin = This->joydev->axes[ABS_HAT0X + i * 2].minimum;
+            props[idx].lDevMax = This->joydev->axes[ABS_HAT0X + i * 2].maximum;
+            props[idx + 1].lDevMin = This->joydev->axes[ABS_HAT0Y + i * 2].minimum;
+            props[idx + 1].lDevMax = This->joydev->axes[ABS_HAT0Y + i * 2].maximum;
             idx += 2;
         }
     }
@@ -627,10 +627,10 @@ static HRESULT CDECL unix_joystick_init(struct unix_joystick *ptr)
             i++; /* POV takes 2 axes */
         }
 
-        This->generic.props[idx].lMin = 0;
-        This->generic.props[idx].lMax = 0xffff;
-        This->generic.props[idx].lSaturation = 0;
-        This->generic.props[idx].lDeadZone = This->generic.deadzone;
+        props[idx].lMin = 0;
+        props[idx].lMax = 0xffff;
+        props[idx].lSaturation = 0;
+        props[idx].lDeadZone = This->generic.deadzone;
 
         /* Linux supports force-feedback on X & Y axes only */
         if (This->joydev->has_ff && (i == 0 || i == 1)) df->rgodf[idx].dwFlags |= DIDOI_FFACTUATOR;
diff --git a/dlls/dinput/joystick_osx.c b/dlls/dinput/joystick_osx.c
index a6c5512c767..0a1724181bc 100644
--- a/dlls/dinput/joystick_osx.c
+++ b/dlls/dinput/joystick_osx.c
@@ -108,7 +108,6 @@ struct JoystickImpl
     /* osx private */
     int                    id;
     CFArrayRef             elements;
-    ObjProps               **propmap;
     FFDeviceObjectReference ff;
 };
 
@@ -745,7 +744,7 @@ static void get_osx_device_elements(JoystickImpl *device, int axis_map[8])
     }
 }
 
-static void get_osx_device_elements_props(JoystickImpl *device)
+static void get_osx_device_elements_props(JoystickImpl *device, ObjProps *props)
 {
     TRACE("device %p\n", device);
 
@@ -759,12 +758,8 @@ static void get_osx_device_elements_props(JoystickImpl *device)
 
             TRACE("element %s\n", debugstr_element(element));
 
-            device->generic.props[idx].lDevMin = IOHIDElementGetLogicalMin(element);
-            device->generic.props[idx].lDevMax = IOHIDElementGetLogicalMax(element);
-            device->generic.props[idx].lMin =  0;
-            device->generic.props[idx].lMax =  0xffff;
-            device->generic.props[idx].lDeadZone = 0;
-            device->generic.props[idx].lSaturation = 0;
+            props[idx].lDevMin = IOHIDElementGetLogicalMin(element);
+            props[idx].lDevMax = IOHIDElementGetLogicalMax(element);
         }
     }
 }
@@ -949,7 +944,7 @@ static HRESULT CDECL unix_joystick_ff_send_cmd(struct unix_joystick *ptr, DWORD
 static HRESULT CDECL unix_joystick_create_effect(struct unix_joystick *ptr, REFGUID guid, const DIEFFECT *params,
         struct list *entry, IDirectInputEffect **out);
 
-static HRESULT CDECL unix_joystick_init(struct unix_joystick *ptr);
+static HRESULT CDECL unix_joystick_init(struct unix_joystick *ptr, ObjProps *props);
 
 static const struct unix_joystick_vtbl unix_joystick_vtbl =
 {
@@ -1138,7 +1133,7 @@ static HRESULT joydev_create_unix_joystick(IDirectInputImpl *dinput, REFGUID gui
     return DI_OK;
 }
 
-static HRESULT CDECL unix_joystick_init(struct unix_joystick *ptr)
+static HRESULT CDECL unix_joystick_init(struct unix_joystick *ptr, ObjProps *props)
 {
     JoystickImpl *This = impl_from_unix_joystick(ptr);
     IOHIDDeviceRef device;
@@ -1268,7 +1263,7 @@ static HRESULT CDECL unix_joystick_init(struct unix_joystick *ptr)
     This->generic.base.data_format.wine_df = df;
 
     /* initialize default properties */
-    get_osx_device_elements_props(This);
+    get_osx_device_elements_props(This, props);
 
     This->generic.devcaps.dwSize = sizeof(This->generic.devcaps);
     This->generic.devcaps.dwFlags |= DIDC_ATTACHED;
diff --git a/dlls/dinput/joystick_private.h b/dlls/dinput/joystick_private.h
index c2786bb4aeb..536b77b3ea2 100644
--- a/dlls/dinput/joystick_private.h
+++ b/dlls/dinput/joystick_private.h
@@ -37,7 +37,7 @@ struct unix_joystick;
 
 struct unix_joystick_vtbl
 {
-    HRESULT (CDECL *init)(struct unix_joystick *ptr);
+    HRESULT (CDECL *init)(struct unix_joystick *ptr, ObjProps *props);
     void (CDECL *reset)(struct unix_joystick *ptr);
 
     void (CDECL *get_mapping)(struct unix_joystick *ptr, int *axis_count, const int **axes_map);
-- 
2.28.0

>From 91eb088e55ac2a72f55bc34557218afefdd4206e Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?R=C3=A9mi=20Bernon?= <rbernon@codeweavers.com>
Date: Tue, 6 Oct 2020 09:55:08 +0200
Subject: [PATCH 27/39] dinput: Fill and access props consistently.

The prop index is the dinput axis index, regardless of user remapping.
---
 dlls/dinput/device.c              |  2 +-
 dlls/dinput/device_private.h      |  1 -
 dlls/dinput/joystick_linux.c      |  2 +-
 dlls/dinput/joystick_linuxinput.c | 21 +++++++++------------
 4 files changed, 11 insertions(+), 15 deletions(-)

diff --git a/dlls/dinput/device.c b/dlls/dinput/device.c
index af05fdf14f0..9f3e5af836e 100644
--- a/dlls/dinput/device.c
+++ b/dlls/dinput/device.c
@@ -587,7 +587,7 @@ static int offset_to_object(const DataFormat *df, int offset)
     return -1;
 }
 
-int id_to_object(LPCDIDATAFORMAT df, int id)
+static int id_to_object(LPCDIDATAFORMAT df, int id)
 {
     int i;
 
diff --git a/dlls/dinput/device_private.h b/dlls/dinput/device_private.h
index 52a7b3c3dc7..3cc6eeecb91 100644
--- a/dlls/dinput/device_private.h
+++ b/dlls/dinput/device_private.h
@@ -103,7 +103,6 @@ extern void fill_DataFormat(void *out, DWORD size, const void *in, const DataFor
 extern void release_DataFormat(DataFormat *df)  DECLSPEC_HIDDEN;
 extern void queue_event(IDirectInputDevice8W *iface, int inst_id, DWORD data, DWORD time, DWORD seq) DECLSPEC_HIDDEN;
 /* Helper functions to work with data format */
-extern int id_to_object(LPCDIDATAFORMAT df, int id) DECLSPEC_HIDDEN;
 extern int find_property(const DataFormat *df, LPCDIPROPHEADER ph) DECLSPEC_HIDDEN;
 
 /* Common joystick stuff */
diff --git a/dlls/dinput/joystick_linux.c b/dlls/dinput/joystick_linux.c
index 166c8e85a2a..b4b7b36bce6 100644
--- a/dlls/dinput/joystick_linux.c
+++ b/dlls/dinput/joystick_linux.c
@@ -673,7 +673,7 @@ static void CDECL unix_joystick_poll(struct unix_joystick *ptr)
             if (number < 0) return;
             inst_id = number < 8 ?  DIDFT_MAKEINSTANCE(number) | DIDFT_ABSAXIS :
                                     DIDFT_MAKEINSTANCE(number - 8) | DIDFT_POV;
-            value = joystick_map_axis(&This->generic.props[id_to_object(This->generic.base.data_format.wine_df, inst_id)], jse.value);
+            value = joystick_map_axis(&This->generic.props[This->joydev->axes_map[jse.number]], jse.value);
 
             TRACE("changing axis %d => %d\n", jse.number, number);
             switch (number)
diff --git a/dlls/dinput/joystick_linuxinput.c b/dlls/dinput/joystick_linuxinput.c
index 0bf8f34dec5..00763269c36 100644
--- a/dlls/dinput/joystick_linuxinput.c
+++ b/dlls/dinput/joystick_linuxinput.c
@@ -582,23 +582,25 @@ static HRESULT CDECL unix_joystick_init(struct unix_joystick *ptr, ObjProps *pro
     /* Count number of available axes - supported Axis & POVs */
     for (i = 0; i < ABS_MAX; i++)
     {
-        if (idx < WINE_JOYSTICK_MAX_AXES && i < ABS_HAT0X && test_bit(This->joydev->absbits, i))
+        if ((idx = This->joydev->dev_axes_to_di[i]) >= 0)
         {
             props[idx].lDevMin = This->joydev->axes[i].minimum;
             props[idx].lDevMax = This->joydev->axes[i].maximum;
-            idx++;
         }
     }
 
     for (i = 0; i < WINE_JOYSTICK_MAX_POVS; i++)
     {
-        if (test_bit(This->joydev->absbits, ABS_HAT0X + i * 2) && test_bit(This->joydev->absbits, ABS_HAT0Y + i * 2))
+        if ((idx = This->joydev->dev_axes_to_di[ABS_HAT0X + i * 2]) >= 0)
         {
             props[idx].lDevMin = This->joydev->axes[ABS_HAT0X + i * 2].minimum;
             props[idx].lDevMax = This->joydev->axes[ABS_HAT0X + i * 2].maximum;
-            props[idx + 1].lDevMin = This->joydev->axes[ABS_HAT0Y + i * 2].minimum;
-            props[idx + 1].lDevMax = This->joydev->axes[ABS_HAT0Y + i * 2].maximum;
-            idx += 2;
+        }
+
+        if ((idx = This->joydev->dev_axes_to_di[ABS_HAT0Y + i * 2]) >= 0)
+        {
+            props[idx].lDevMin = This->joydev->axes[ABS_HAT0Y + i * 2].minimum;
+            props[idx].lDevMax = This->joydev->axes[ABS_HAT0Y + i * 2].maximum;
         }
     }
 
@@ -627,11 +629,6 @@ static HRESULT CDECL unix_joystick_init(struct unix_joystick *ptr, ObjProps *pro
             i++; /* POV takes 2 axes */
         }
 
-        props[idx].lMin = 0;
-        props[idx].lMax = 0xffff;
-        props[idx].lSaturation = 0;
-        props[idx].lDeadZone = This->generic.deadzone;
-
         /* Linux supports force-feedback on X & Y axes only */
         if (This->joydev->has_ff && (i == 0 || i == 1)) df->rgodf[idx].dwFlags |= DIDOI_FFACTUATOR;
 
@@ -850,7 +847,7 @@ static void CDECL unix_joystick_poll(struct unix_joystick *ptr)
 
             inst_id = axis < 8 ?  DIDFT_MAKEINSTANCE(axis) | DIDFT_ABSAXIS :
                                   DIDFT_MAKEINSTANCE(axis - 8) | DIDFT_POV;
-            value = joystick_map_axis(&This->generic.props[id_to_object(This->generic.base.data_format.wine_df, inst_id)], ie.value);
+            value = joystick_map_axis(&This->generic.props[This->joydev->dev_axes_to_di[ie.code]], ie.value);
 
 	    switch (axis) {
             case 0: This->generic.js.lX  = value; break;
-- 
2.28.0

>From df697c7a93bc0a702de738fec5c673ba0ba26b55 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?R=C3=A9mi=20Bernon?= <rbernon@codeweavers.com>
Date: Tue, 6 Oct 2020 15:09:11 +0200
Subject: [PATCH 28/39] dinput: Factor unix joystick dataformat initialization.

Using ObjProps to provide types and flags.
---
 dlls/dinput/device_private.h      |   2 +
 dlls/dinput/joystick.c            |  39 +++++++-
 dlls/dinput/joystick_linux.c      |  46 ++--------
 dlls/dinput/joystick_linuxinput.c |  69 +++++---------
 dlls/dinput/joystick_osx.c        | 147 +++++++++++++-----------------
 dlls/dinput/joystick_private.h    |   2 +-
 6 files changed, 136 insertions(+), 169 deletions(-)

diff --git a/dlls/dinput/device_private.h b/dlls/dinput/device_private.h
index 3cc6eeecb91..ef6bb05108f 100644
--- a/dlls/dinput/device_private.h
+++ b/dlls/dinput/device_private.h
@@ -114,6 +114,8 @@ typedef struct
     LONG lMax;
     LONG lDeadZone;
     LONG lSaturation;
+    DWORD dwType;
+    DWORD dwFlags;
 } ObjProps;
 
 extern DWORD joystick_map_pov(const POINTL *p) DECLSPEC_HIDDEN;
diff --git a/dlls/dinput/joystick.c b/dlls/dinput/joystick.c
index faefe593354..29738820e6e 100644
--- a/dlls/dinput/joystick.c
+++ b/dlls/dinput/joystick.c
@@ -1192,9 +1192,12 @@ HRESULT dinput_create_unix_joystick(const struct dinput_device *device, IDirectI
 {
     JoystickGenericImpl *This;
     ObjProps props[MAX_PROPS];
+    DIOBJECTDATAFORMAT *odf = NULL;
+    DIDATAFORMAT *df = NULL;
     HRESULT hr;
     const int *default_axes_map;
-    int i, default_axis_count;
+    int i, j, default_axis_count, prop_count;
+    WORD idx, type;
 
     if (FAILED(hr = device->create_unix_joystick(dinput, guid, &This)))
         return hr;
@@ -1212,11 +1215,41 @@ HRESULT dinput_create_unix_joystick(const struct dinput_device *device, IDirectI
         props[i].lMax = 0xffff;
         props[i].lDeadZone = This->deadzone;
         props[i].lSaturation = 0;
+        props[i].dwType = 0;
+        props[i].dwFlags = 0;
     }
 
-    if (FAILED(hr = This->unix_funcs->init(This->unix_ptr, props))) goto done;
+    if (FAILED(hr = This->unix_funcs->init(This->unix_ptr, props, &prop_count))) goto done;
     memcpy(This->props, props, sizeof(This->props));
 
+    if (!(df = HeapAlloc(GetProcessHeap(), 0, c_dfDIJoystick2.dwSize))) goto done;
+    memcpy(df, &c_dfDIJoystick2, c_dfDIJoystick2.dwSize);
+    if (!(odf = HeapAlloc(GetProcessHeap(), 0, df->dwNumObjs * df->dwObjSize))) goto done;
+
+    for (i = 0, j = 0; i < prop_count; ++i)
+    {
+       idx = DIDFT_GETINSTANCE(props[i].dwType);
+       type = DIDFT_GETTYPE(props[i].dwType);
+       if (!type) continue;
+
+       if (type == DIDFT_ABSAXIS)
+           memcpy(&odf[j], &c_dfDIJoystick2.rgodf[idx], df->dwObjSize);
+       else if (type == DIDFT_POV)
+           memcpy(&odf[j], &c_dfDIJoystick2.rgodf[idx + 8], df->dwObjSize);
+       else if (type == DIDFT_PSHBUTTON)
+       {
+           memcpy(&odf[j], &c_dfDIJoystick2.rgodf[idx + 12], df->dwObjSize);
+           odf[j].pguid = &GUID_Button;
+       }
+       odf[j].dwType = props[i].dwType;
+       odf[j].dwFlags |= props[i].dwFlags;
+       j++;
+       if (type == DIDFT_POV) i++; /* POV takes 2 axes */
+    }
+    df->dwNumObjs = j;
+    df->rgodf = odf;
+    This->base.data_format.wine_df = df;
+
     if (This->unix_funcs->reset) This->unix_funcs->reset(This->unix_ptr);
     if (FAILED(hr = IDirectInputDevice8_QueryInterface(IDirectInputDevice8W_from_impl(This), iid, out))) goto done;
 
@@ -1226,5 +1259,7 @@ HRESULT dinput_create_unix_joystick(const struct dinput_device *device, IDirectI
 done:
     /* IDirectInputDevice8_QueryInterface increased refcount */
     IDirectInputDevice8_Release(IDirectInputDevice8W_from_impl(This));
+    if (FAILED(hr) && odf) HeapFree(GetProcessHeap(), 0, odf);
+    if (FAILED(hr) && df) HeapFree(GetProcessHeap(), 0, df);
     return hr;
 }
diff --git a/dlls/dinput/joystick_linux.c b/dlls/dinput/joystick_linux.c
index b4b7b36bce6..a42767895dc 100644
--- a/dlls/dinput/joystick_linux.c
+++ b/dlls/dinput/joystick_linux.c
@@ -138,7 +138,7 @@ static void CDECL unix_joystick_poll(struct unix_joystick *ptr);
 static HRESULT CDECL unix_joystick_acquire(struct unix_joystick *ptr);
 static HRESULT CDECL unix_joystick_unacquire(struct unix_joystick *ptr);
 
-static HRESULT CDECL unix_joystick_init(struct unix_joystick *ptr, ObjProps *props);
+static HRESULT CDECL unix_joystick_init(struct unix_joystick *ptr, ObjProps *props, int *prop_count);
 static void CDECL unix_joystick_get_mapping(struct unix_joystick *ptr, int *axis_count, const int **axes_map);
 
 static const struct unix_joystick_vtbl unix_joystick_vtbl =
@@ -508,12 +508,10 @@ static void CDECL unix_joystick_get_mapping(struct unix_joystick *ptr, int *axis
     *axes_map = This->joydev->axes_map;
 }
 
-static HRESULT CDECL unix_joystick_init(struct unix_joystick *ptr, ObjProps *props)
+static HRESULT CDECL unix_joystick_init(struct unix_joystick *ptr, ObjProps *props, int *prop_count)
 {
     JoystickImpl *This = impl_from_unix_joystick(ptr);
-    LPDIDATAFORMAT df = NULL;
-    HRESULT hr;
-    DWORD i, idx = 0;
+    int i, idx = 0, wine_obj;
 
     This->generic.devcaps.dwButtons = This->joydev->button_count;
 
@@ -523,36 +521,19 @@ static HRESULT CDECL unix_joystick_init(struct unix_joystick *ptr, ObjProps *pro
         This->generic.devcaps.dwButtons = 128;
     }
 
-    /* Create copy of default data format */
-    hr = DIERR_OUTOFMEMORY;
-    if (!(df = HeapAlloc(GetProcessHeap(), 0, c_dfDIJoystick2.dwSize))) goto failed;
-    memcpy(df, &c_dfDIJoystick2, c_dfDIJoystick2.dwSize);
-
-    df->dwNumObjs = This->generic.devcaps.dwAxes + This->generic.devcaps.dwPOVs + This->generic.devcaps.dwButtons;
-    if (!(df->rgodf = HeapAlloc(GetProcessHeap(), 0, df->dwNumObjs * df->dwObjSize))) goto failed;
-
     for (i = 0; i < This->joydev->axis_count; i++)
     {
-        int wine_obj = This->generic.axis_map[i];
-
-        if (wine_obj < 0) continue;
-
-        memcpy(&df->rgodf[idx], &c_dfDIJoystick2.rgodf[wine_obj], df->dwObjSize);
-        if (wine_obj < 8)
-            df->rgodf[idx++].dwType = DIDFT_MAKEINSTANCE(wine_obj) | DIDFT_ABSAXIS;
-        else
+        if ((idx = This->joydev->axes_map[i]) >= 0)
         {
-            df->rgodf[idx++].dwType = DIDFT_MAKEINSTANCE(wine_obj - 8) | DIDFT_POV;
-            i++; /* POV takes 2 axes */
+            wine_obj = This->generic.axis_map[i];
+            if (wine_obj < 0) props[idx].dwType = 0;
+            else if (wine_obj < 8) props[idx].dwType = DIDFT_MAKEINSTANCE(wine_obj) | DIDFT_ABSAXIS;
+            else props[idx].dwType = DIDFT_MAKEINSTANCE(wine_obj - 8) | DIDFT_POV;
         }
     }
     for (i = 0; i < This->generic.devcaps.dwButtons; i++)
-    {
-        memcpy(&df->rgodf[idx], &c_dfDIJoystick2.rgodf[i + 12], df->dwObjSize);
-        df->rgodf[idx  ].pguid = &GUID_Button;
-        df->rgodf[idx++].dwType = DIDFT_MAKEINSTANCE(i) | DIDFT_PSHBUTTON;
-    }
-    This->generic.base.data_format.wine_df = df;
+        props[i + 12].dwType = DIDFT_MAKEINSTANCE(i) | DIDFT_PSHBUTTON;
+    *prop_count = i + 12;
 
     This->generic.devcaps.dwSize = sizeof(This->generic.devcaps);
     This->generic.devcaps.dwFlags = DIDC_ATTACHED;
@@ -570,13 +551,6 @@ static HRESULT CDECL unix_joystick_init(struct unix_joystick *ptr, ObjProps *pro
     }
 
     return DI_OK;
-
-failed:
-    if (df) HeapFree(GetProcessHeap(), 0, df->rgodf);
-    HeapFree(GetProcessHeap(), 0, df);
-    release_DataFormat(&This->generic.base.data_format);
-    HeapFree(GetProcessHeap(), 0, This->generic.axis_map);
-    return hr;
 }
 
 #undef MAX_JOYSTICKS
diff --git a/dlls/dinput/joystick_linuxinput.c b/dlls/dinput/joystick_linuxinput.c
index 00763269c36..152aa1a6934 100644
--- a/dlls/dinput/joystick_linuxinput.c
+++ b/dlls/dinput/joystick_linuxinput.c
@@ -172,7 +172,7 @@ static HRESULT CDECL unix_joystick_get_effect_info(struct unix_joystick *ptr, RE
 static HRESULT CDECL unix_joystick_create_effect(struct unix_joystick *ptr, REFGUID guid, const DIEFFECT *effect,
         struct list *entry, IDirectInputEffect **out);
 
-static HRESULT CDECL unix_joystick_init(struct unix_joystick *ptr, ObjProps *props);
+static HRESULT CDECL unix_joystick_init(struct unix_joystick *ptr, ObjProps *props, int *prop_count);
 static void CDECL unix_joystick_reset(struct unix_joystick *ptr);
 static void CDECL unix_joystick_get_mapping(struct unix_joystick *ptr, int *axis_count, const int **axes_map);
 
@@ -560,12 +560,10 @@ static void CDECL unix_joystick_get_mapping(struct unix_joystick *ptr, int *axis
     *axes_map = This->joydev->axes_map;
 }
 
-static HRESULT CDECL unix_joystick_init(struct unix_joystick *ptr, ObjProps *props)
+static HRESULT CDECL unix_joystick_init(struct unix_joystick *ptr, ObjProps *props, int *prop_count)
 {
     JoystickImpl *This = impl_from_unix_joystick(ptr);
-    LPDIDATAFORMAT df = NULL;
-    HRESULT hr;
-    int i, idx = 0;
+    int i, idx = 0, wine_obj;
 
     list_init(&This->generic.ff_effects);
 #ifdef HAVE_STRUCT_FF_EFFECT_DIRECTION
@@ -586,6 +584,13 @@ static HRESULT CDECL unix_joystick_init(struct unix_joystick *ptr, ObjProps *pro
         {
             props[idx].lDevMin = This->joydev->axes[i].minimum;
             props[idx].lDevMax = This->joydev->axes[i].maximum;
+
+            wine_obj = This->generic.axis_map[idx];
+            if (wine_obj < 0) props[idx].dwType = 0;
+            else if (wine_obj < 8) props[idx].dwType = DIDFT_MAKEINSTANCE(wine_obj) | DIDFT_ABSAXIS;
+            else props[idx].dwType = DIDFT_MAKEINSTANCE(wine_obj - 8) | DIDFT_POV;
+
+            if (This->joydev->has_ff && (idx == 0 || idx == 1)) props[idx].dwFlags |= DIDOI_FFACTUATOR;
         }
     }
 
@@ -595,55 +600,29 @@ static HRESULT CDECL unix_joystick_init(struct unix_joystick *ptr, ObjProps *pro
         {
             props[idx].lDevMin = This->joydev->axes[ABS_HAT0X + i * 2].minimum;
             props[idx].lDevMax = This->joydev->axes[ABS_HAT0X + i * 2].maximum;
+
+            wine_obj = This->generic.axis_map[idx];
+            if (wine_obj < 0) props[idx].dwType = 0;
+            else if (wine_obj < 8) props[idx].dwType = DIDFT_MAKEINSTANCE(wine_obj) | DIDFT_ABSAXIS;
+            else props[idx].dwType = DIDFT_MAKEINSTANCE(wine_obj - 8) | DIDFT_POV;
         }
 
         if ((idx = This->joydev->dev_axes_to_di[ABS_HAT0Y + i * 2]) >= 0)
         {
             props[idx].lDevMin = This->joydev->axes[ABS_HAT0Y + i * 2].minimum;
             props[idx].lDevMax = This->joydev->axes[ABS_HAT0Y + i * 2].maximum;
-        }
-    }
-
-    /* Create copy of default data format */
-    hr = DIERR_OUTOFMEMORY;
-    if (!(df = HeapAlloc(GetProcessHeap(), 0, c_dfDIJoystick2.dwSize))) goto failed;
-    memcpy(df, &c_dfDIJoystick2, c_dfDIJoystick2.dwSize);
-    if (!(df->rgodf = HeapAlloc(GetProcessHeap(), 0, df->dwNumObjs * df->dwObjSize))) goto failed;
-
 
-    /* Construct internal data format */
-
-    /* Supported Axis & POVs */
-    for (i = 0, idx = 0; i < This->joydev->axis_count; i++)
-    {
-        int wine_obj = This->generic.axis_map[i];
-
-        if (wine_obj < 0) continue;
-
-        memcpy(&df->rgodf[idx], &c_dfDIJoystick2.rgodf[wine_obj], df->dwObjSize);
-        if (wine_obj < 8)
-            df->rgodf[idx].dwType = DIDFT_MAKEINSTANCE(wine_obj) | DIDFT_ABSAXIS;
-        else
-        {
-            df->rgodf[idx].dwType = DIDFT_MAKEINSTANCE(wine_obj - 8) | DIDFT_POV;
-            i++; /* POV takes 2 axes */
+            wine_obj = This->generic.axis_map[idx];
+            if (wine_obj < 0) props[idx].dwType = 0;
+            else if (wine_obj < 8) props[idx].dwType = DIDFT_MAKEINSTANCE(wine_obj) | DIDFT_ABSAXIS;
+            else props[idx].dwType = DIDFT_MAKEINSTANCE(wine_obj - 8) | DIDFT_POV;
         }
-
-        /* Linux supports force-feedback on X & Y axes only */
-        if (This->joydev->has_ff && (i == 0 || i == 1)) df->rgodf[idx].dwFlags |= DIDOI_FFACTUATOR;
-
-        idx++;
     }
 
     for (i = 0; i < This->joydev->button_count; i++)
-    {
-        memcpy(&df->rgodf[idx], &c_dfDIJoystick2.rgodf[i + 12], df->dwObjSize);
-        df->rgodf[idx  ].pguid = &GUID_Button;
-        df->rgodf[idx++].dwType = DIDFT_MAKEINSTANCE(i) | DIDFT_PSHBUTTON;
-    }
-    df->dwNumObjs = idx;
+        props[i + 12].dwType = DIDFT_MAKEINSTANCE(i) | DIDFT_PSHBUTTON;
+    *prop_count = i + 12;
     This->generic.devcaps.dwButtons = This->joydev->button_count;
-    This->generic.base.data_format.wine_df = df;
 
     /* Fill the caps */
     This->generic.devcaps.dwSize = sizeof(This->generic.devcaps);
@@ -653,12 +632,6 @@ static HRESULT CDECL unix_joystick_init(struct unix_joystick *ptr, ObjProps *pro
     if (This->joydev->has_ff) This->generic.devcaps.dwFlags |= DIDC_FORCEFEEDBACK;
 
     return DI_OK;
-
-failed:
-    if (df) HeapFree(GetProcessHeap(), 0, df->rgodf);
-    HeapFree(GetProcessHeap(), 0, df);
-    HeapFree(GetProcessHeap(), 0, This->generic.axis_map);
-    return hr;
 }
 
 const struct dinput_device joystick_linuxinput_device = {
diff --git a/dlls/dinput/joystick_osx.c b/dlls/dinput/joystick_osx.c
index 0a1724181bc..380d52a52ad 100644
--- a/dlls/dinput/joystick_osx.c
+++ b/dlls/dinput/joystick_osx.c
@@ -744,8 +744,14 @@ static void get_osx_device_elements(JoystickImpl *device, int axis_map[8])
     }
 }
 
-static void get_osx_device_elements_props(JoystickImpl *device, ObjProps *props)
+static BOOL osx_axis_has_ff(FFCAPABILITIES *ffcaps, UInt8 axis);
+
+static void get_osx_device_elements_props(JoystickImpl *device, FFCAPABILITIES *ffcaps, ObjProps *props, int *prop_count)
 {
+    int button_idx = 0;
+    int pov_idx = 0;
+    int slider_idx = 0;
+
     TRACE("device %p\n", device);
 
     if (device->elements)
@@ -755,13 +761,68 @@ static void get_osx_device_elements_props(JoystickImpl *device, ObjProps *props)
         for ( idx = 0; idx < cnt; idx++ )
         {
             IOHIDElementRef element = ( IOHIDElementRef ) CFArrayGetValueAtIndex( device->elements, idx );
+            int type = IOHIDElementGetType( element );
 
             TRACE("element %s\n", debugstr_element(element));
 
             props[idx].lDevMin = IOHIDElementGetLogicalMin(element);
             props[idx].lDevMax = IOHIDElementGetLogicalMax(element);
+
+            switch(type)
+            {
+                case kIOHIDElementTypeInput_Button:
+                    if(button_idx >= 128) break;
+                    props[idx].dwType = DIDFT_MAKEINSTANCE(button_idx) | DIDFT_PSHBUTTON;
+                    button_idx++;
+                    break;
+                case kIOHIDElementTypeInput_Misc:
+                {
+                    uint32_t usage = IOHIDElementGetUsage( element );
+                    switch(usage)
+                    {
+                        case kHIDUsage_GD_Hatswitch:
+                            props[idx].dwType = DIDFT_MAKEINSTANCE(pov_idx) | DIDFT_POV;
+                            pov_idx++;
+                            break;
+                        case kHIDUsage_GD_X:
+                            props[idx].dwType = DIDFT_MAKEINSTANCE(0) | DIDFT_ABSAXIS;
+                            if ((device->ff != 0) && osx_axis_has_ff(ffcaps, FFJOFS_X)) props[idx].dwFlags |= DIDOI_FFACTUATOR;
+                            break;
+                        case kHIDUsage_GD_Y:
+                            props[idx].dwType = DIDFT_MAKEINSTANCE(1) | DIDFT_ABSAXIS;
+                            if ((device->ff != 0) && osx_axis_has_ff(ffcaps, FFJOFS_Y)) props[idx].dwFlags |= DIDOI_FFACTUATOR;
+                            break;
+                        case kHIDUsage_GD_Z:
+                            props[idx].dwType = DIDFT_MAKEINSTANCE(2) | DIDFT_ABSAXIS;
+                            if ((device->ff != 0) && osx_axis_has_ff(ffcaps, FFJOFS_Z)) props[idx].dwFlags |= DIDOI_FFACTUATOR;
+                            break;
+                        case kHIDUsage_GD_Rx:
+                            props[idx].dwType = DIDFT_MAKEINSTANCE(3) | DIDFT_ABSAXIS;
+                            if ((device->ff != 0) && osx_axis_has_ff(ffcaps, FFJOFS_RX)) props[idx].dwFlags |= DIDOI_FFACTUATOR;
+                            break;
+                        case kHIDUsage_GD_Ry:
+                            props[idx].dwType = DIDFT_MAKEINSTANCE(4) | DIDFT_ABSAXIS;
+                            if ((device->ff != 0) && osx_axis_has_ff(ffcaps, FFJOFS_RY)) props[idx].dwFlags |= DIDOI_FFACTUATOR;
+                            break;
+                        case kHIDUsage_GD_Rz:
+                            props[idx].dwType = DIDFT_MAKEINSTANCE(5) | DIDFT_ABSAXIS;
+                            if ((device->ff != 0) && osx_axis_has_ff(ffcaps, FFJOFS_RZ)) props[idx].dwFlags |= DIDOI_FFACTUATOR;
+                            break;
+                        case kHIDUsage_GD_Slider:
+                            props[idx].dwType = DIDFT_MAKEINSTANCE(6 + slider_idx) | DIDFT_ABSAXIS;
+                            if ((device->ff != 0) && osx_axis_has_ff(ffcaps, FFJOFS_SLIDER(slider_idx))) props[idx].dwFlags |= DIDOI_FFACTUATOR;
+                            slider_idx++;
+                            break;
+                        default:
+                            break;
+                    }
+                    break;
+                }
+            }
         }
+        *prop_count = idx;
     }
+    else *prop_count = 0;
 }
 
 static void CDECL unix_joystick_poll(struct unix_joystick *ptr)
@@ -944,7 +1005,7 @@ static HRESULT CDECL unix_joystick_ff_send_cmd(struct unix_joystick *ptr, DWORD
 static HRESULT CDECL unix_joystick_create_effect(struct unix_joystick *ptr, REFGUID guid, const DIEFFECT *params,
         struct list *entry, IDirectInputEffect **out);
 
-static HRESULT CDECL unix_joystick_init(struct unix_joystick *ptr, ObjProps *props);
+static HRESULT CDECL unix_joystick_init(struct unix_joystick *ptr, ObjProps *props, int *prop_count);
 
 static const struct unix_joystick_vtbl unix_joystick_vtbl =
 {
@@ -1133,18 +1194,15 @@ static HRESULT joydev_create_unix_joystick(IDirectInputImpl *dinput, REFGUID gui
     return DI_OK;
 }
 
-static HRESULT CDECL unix_joystick_init(struct unix_joystick *ptr, ObjProps *props)
+static HRESULT CDECL unix_joystick_init(struct unix_joystick *ptr, ObjProps *props, int *prop_count)
 {
     JoystickImpl *This = impl_from_unix_joystick(ptr);
     IOHIDDeviceRef device;
-    LPDIDATAFORMAT df = NULL;
     FFCAPABILITIES ffcaps;
     char name[MAX_PATH];
     HRESULT hr;
     DWORD i;
-    int idx = 0;
     int axis_map[8]; /* max axes */
-    int slider_count = 0;
 
     device = get_device_ref(This->id);
 
@@ -1196,74 +1254,8 @@ static HRESULT CDECL unix_joystick_init(struct unix_joystick *ptr, ObjProps *pro
         This->generic.devcaps.dwButtons = 128;
     }
 
-    /* Create copy of default data format */
-    if (!(df = HeapAlloc(GetProcessHeap(), 0, c_dfDIJoystick2.dwSize))) goto FAILED;
-    memcpy(df, &c_dfDIJoystick2, c_dfDIJoystick2.dwSize);
-
-    df->dwNumObjs = This->generic.devcaps.dwAxes + This->generic.devcaps.dwPOVs + This->generic.devcaps.dwButtons;
-    if (!(df->rgodf = HeapAlloc(GetProcessHeap(), 0, df->dwNumObjs * df->dwObjSize))) goto FAILED;
-
-    for (i = 0; i < This->generic.devcaps.dwAxes; i++)
-    {
-        int wine_obj = -1;
-        BOOL has_ff  = FALSE;
-        switch (axis_map[i])
-        {
-            case kHIDUsage_GD_X:
-                wine_obj = 0;
-                has_ff = (This->ff != 0) && osx_axis_has_ff(&ffcaps, FFJOFS_X);
-                break;
-            case kHIDUsage_GD_Y:
-                wine_obj = 1;
-                has_ff = (This->ff != 0) && osx_axis_has_ff(&ffcaps, FFJOFS_Y);
-                break;
-            case kHIDUsage_GD_Z:
-                wine_obj = 2;
-                has_ff = (This->ff != 0) && osx_axis_has_ff(&ffcaps, FFJOFS_Z);
-                break;
-            case kHIDUsage_GD_Rx:
-                wine_obj = 3;
-                has_ff = (This->ff != 0) && osx_axis_has_ff(&ffcaps, FFJOFS_RX);
-                break;
-            case kHIDUsage_GD_Ry:
-                wine_obj = 4;
-                has_ff = (This->ff != 0) && osx_axis_has_ff(&ffcaps, FFJOFS_RY);
-                break;
-            case kHIDUsage_GD_Rz:
-                wine_obj = 5;
-                has_ff = (This->ff != 0) && osx_axis_has_ff(&ffcaps, FFJOFS_RZ);
-                break;
-            case kHIDUsage_GD_Slider:
-                wine_obj = 6 + slider_count;
-                has_ff = (This->ff != 0) && osx_axis_has_ff(&ffcaps, FFJOFS_SLIDER(slider_count));
-                slider_count++;
-                break;
-        }
-        if (wine_obj < 0 ) continue;
-
-        memcpy(&df->rgodf[idx], &c_dfDIJoystick2.rgodf[wine_obj], df->dwObjSize);
-        df->rgodf[idx].dwType = DIDFT_MAKEINSTANCE(wine_obj) | DIDFT_ABSAXIS;
-        if(has_ff)
-            df->rgodf[idx].dwFlags |= DIDOI_FFACTUATOR;
-        ++idx;
-    }
-
-    for (i = 0; i < This->generic.devcaps.dwPOVs; i++)
-    {
-        memcpy(&df->rgodf[idx], &c_dfDIJoystick2.rgodf[i + 8], df->dwObjSize);
-        df->rgodf[idx++].dwType = DIDFT_MAKEINSTANCE(i) | DIDFT_POV;
-    }
-
-    for (i = 0; i < This->generic.devcaps.dwButtons; i++)
-    {
-        memcpy(&df->rgodf[idx], &c_dfDIJoystick2.rgodf[i + 12], df->dwObjSize);
-        df->rgodf[idx  ].pguid = &GUID_Button;
-        df->rgodf[idx++].dwType = DIDFT_MAKEINSTANCE(i) | DIDFT_PSHBUTTON;
-    }
-    This->generic.base.data_format.wine_df = df;
-
     /* initialize default properties */
-    get_osx_device_elements_props(This, props);
+    get_osx_device_elements_props(This, &ffcaps, props, prop_count);
 
     This->generic.devcaps.dwSize = sizeof(This->generic.devcaps);
     This->generic.devcaps.dwFlags |= DIDC_ATTACHED;
@@ -1280,15 +1272,6 @@ static HRESULT CDECL unix_joystick_init(struct unix_joystick *ptr, ObjProps *pro
     }
 
     return DI_OK;
-
-FAILED:
-    hr = DIERR_OUTOFMEMORY;
-    if (This->ff) FFReleaseDevice(This->ff);
-    if (This->elements) CFRelease(This->elements);
-    if (df) HeapFree(GetProcessHeap(), 0, df->rgodf);
-    HeapFree(GetProcessHeap(), 0, df);
-    release_DataFormat(&This->generic.base.data_format);
-    return hr;
 }
 
 static HRESULT CDECL unix_joystick_ff_set_autocenter(struct unix_joystick *ptr, DWORD value)
diff --git a/dlls/dinput/joystick_private.h b/dlls/dinput/joystick_private.h
index 536b77b3ea2..6fe1bfce0a9 100644
--- a/dlls/dinput/joystick_private.h
+++ b/dlls/dinput/joystick_private.h
@@ -37,7 +37,7 @@ struct unix_joystick;
 
 struct unix_joystick_vtbl
 {
-    HRESULT (CDECL *init)(struct unix_joystick *ptr, ObjProps *props);
+    HRESULT (CDECL *init)(struct unix_joystick *ptr, ObjProps *props, int *prop_count);
     void (CDECL *reset)(struct unix_joystick *ptr);
 
     void (CDECL *get_mapping)(struct unix_joystick *ptr, int *axis_count, const int **axes_map);
-- 
2.28.0

>From 0e26d6a8bd9f6b3423cde595523edf54f46754f1 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?R=C3=A9mi=20Bernon?= <rbernon@codeweavers.com>
Date: Tue, 6 Oct 2020 16:07:43 +0200
Subject: [PATCH 29/39] dinput: Factor unix joystick devcaps initialization.

---
 dlls/dinput/joystick.c            | 37 +++++++++++++++++++++---
 dlls/dinput/joystick_linux.c      | 38 ++++++++-----------------
 dlls/dinput/joystick_linuxinput.c | 15 ++--------
 dlls/dinput/joystick_osx.c        | 47 ++++---------------------------
 dlls/dinput/joystick_private.h    |  4 +--
 5 files changed, 54 insertions(+), 87 deletions(-)

diff --git a/dlls/dinput/joystick.c b/dlls/dinput/joystick.c
index 29738820e6e..de30e0aa073 100644
--- a/dlls/dinput/joystick.c
+++ b/dlls/dinput/joystick.c
@@ -521,7 +521,7 @@ HRESULT WINAPI JoystickWGenericImpl_Unacquire(LPDIRECTINPUTDEVICE8W iface)
 }
 
 #define DEBUG_TYPE(x) case (x): str = #x; break
-void _dump_DIDEVCAPS(const DIDEVCAPS *lpDIDevCaps)
+static void _dump_DIDEVCAPS(const DIDEVCAPS *lpDIDevCaps)
 {
     int type = GET_DIDEVICE_TYPE(lpDIDevCaps->dwDevType);
     const char *str, *hid = "";
@@ -1198,6 +1198,7 @@ HRESULT dinput_create_unix_joystick(const struct dinput_device *device, IDirectI
     const int *default_axes_map;
     int i, j, default_axis_count, prop_count;
     WORD idx, type;
+    BOOL has_ff = FALSE;
 
     if (FAILED(hr = device->create_unix_joystick(dinput, guid, &This)))
         return hr;
@@ -1219,7 +1220,12 @@ HRESULT dinput_create_unix_joystick(const struct dinput_device *device, IDirectI
         props[i].dwFlags = 0;
     }
 
-    if (FAILED(hr = This->unix_funcs->init(This->unix_ptr, props, &prop_count))) goto done;
+    memset(&This->devcaps, 0, sizeof(This->devcaps));
+    This->devcaps.dwSize = sizeof(This->devcaps);
+    This->devcaps.dwFlags = DIDC_ATTACHED;
+    This->devcaps.dwDevType = This->base.info.dwDevType;
+
+    if (FAILED(hr = This->unix_funcs->init(This->unix_ptr, props, &prop_count, &has_ff))) goto done;
     memcpy(This->props, props, sizeof(This->props));
 
     if (!(df = HeapAlloc(GetProcessHeap(), 0, c_dfDIJoystick2.dwSize))) goto done;
@@ -1233,13 +1239,20 @@ HRESULT dinput_create_unix_joystick(const struct dinput_device *device, IDirectI
        if (!type) continue;
 
        if (type == DIDFT_ABSAXIS)
+       {
            memcpy(&odf[j], &c_dfDIJoystick2.rgodf[idx], df->dwObjSize);
+           This->devcaps.dwAxes++;
+       }
        else if (type == DIDFT_POV)
+       {
            memcpy(&odf[j], &c_dfDIJoystick2.rgodf[idx + 8], df->dwObjSize);
+           This->devcaps.dwPOVs++;
+       }
        else if (type == DIDFT_PSHBUTTON)
        {
            memcpy(&odf[j], &c_dfDIJoystick2.rgodf[idx + 12], df->dwObjSize);
            odf[j].pguid = &GUID_Button;
+           This->devcaps.dwButtons++;
        }
        odf[j].dwType = props[i].dwType;
        odf[j].dwFlags |= props[i].dwFlags;
@@ -1250,11 +1263,27 @@ HRESULT dinput_create_unix_joystick(const struct dinput_device *device, IDirectI
     df->rgodf = odf;
     This->base.data_format.wine_df = df;
 
+    if (has_ff)
+    {
+        DIPROPDWORD prop = {};
+        This->devcaps.dwFlags |= DIDC_FORCEFEEDBACK;
+        prop.diph.dwSize = sizeof(prop);
+        prop.dwData = 10000;
+        JoystickWGenericImpl_SetProperty(IDirectInputDevice8W_from_impl(This), DIPROP_FFGAIN, &prop.diph);
+        prop.diph.dwSize = sizeof(prop);
+        prop.dwData = DIPROPAUTOCENTER_ON;
+        JoystickWGenericImpl_SetProperty(IDirectInputDevice8W_from_impl(This), DIPROP_AUTOCENTER, &prop.diph);
+    }
+
     if (This->unix_funcs->reset) This->unix_funcs->reset(This->unix_ptr);
     if (FAILED(hr = IDirectInputDevice8_QueryInterface(IDirectInputDevice8W_from_impl(This), iid, out))) goto done;
 
-    TRACE("created unix joystick %p\n", This);
-    if (TRACE_ON(dinput)) _dump_DIDATAFORMAT(This->base.data_format.wine_df);
+    if (TRACE_ON(dinput))
+    {
+        TRACE("created unix joystick %p\n", This);
+        _dump_DIDEVCAPS(&This->devcaps);
+        _dump_DIDATAFORMAT(This->base.data_format.wine_df);
+    }
 
 done:
     /* IDirectInputDevice8_QueryInterface increased refcount */
diff --git a/dlls/dinput/joystick_linux.c b/dlls/dinput/joystick_linux.c
index a42767895dc..8917d28f94b 100644
--- a/dlls/dinput/joystick_linux.c
+++ b/dlls/dinput/joystick_linux.c
@@ -138,7 +138,7 @@ static void CDECL unix_joystick_poll(struct unix_joystick *ptr);
 static HRESULT CDECL unix_joystick_acquire(struct unix_joystick *ptr);
 static HRESULT CDECL unix_joystick_unacquire(struct unix_joystick *ptr);
 
-static HRESULT CDECL unix_joystick_init(struct unix_joystick *ptr, ObjProps *props, int *prop_count);
+static HRESULT CDECL unix_joystick_init(struct unix_joystick *ptr, ObjProps *props, int *prop_count, BOOL *has_ff);
 static void CDECL unix_joystick_get_mapping(struct unix_joystick *ptr, int *axis_count, const int **axes_map);
 
 static const struct unix_joystick_vtbl unix_joystick_vtbl =
@@ -233,6 +233,12 @@ static INT find_joystick_devices(void)
         joydev.button_count = 2;
 #endif
 
+        if (joydev.button_count > 128)
+        {
+            WARN("Can't support %d buttons. Clamping down to 128\n", joydev.button_count);
+            joydev.button_count = 128;
+        }
+
         joydev.is_joystick = FALSE;
         if (ioctl(fd, JSIOCGBTNMAP, btn_map) < 0)
         {
@@ -508,19 +514,11 @@ static void CDECL unix_joystick_get_mapping(struct unix_joystick *ptr, int *axis
     *axes_map = This->joydev->axes_map;
 }
 
-static HRESULT CDECL unix_joystick_init(struct unix_joystick *ptr, ObjProps *props, int *prop_count)
+static HRESULT CDECL unix_joystick_init(struct unix_joystick *ptr, ObjProps *props, int *prop_count, BOOL *has_ff)
 {
     JoystickImpl *This = impl_from_unix_joystick(ptr);
     int i, idx = 0, wine_obj;
 
-    This->generic.devcaps.dwButtons = This->joydev->button_count;
-
-    if (This->generic.devcaps.dwButtons > 128)
-    {
-        WARN("Can't support %d buttons. Clamping down to 128\n", This->generic.devcaps.dwButtons);
-        This->generic.devcaps.dwButtons = 128;
-    }
-
     for (i = 0; i < This->joydev->axis_count; i++)
     {
         if ((idx = This->joydev->axes_map[i]) >= 0)
@@ -531,24 +529,10 @@ static HRESULT CDECL unix_joystick_init(struct unix_joystick *ptr, ObjProps *pro
             else props[idx].dwType = DIDFT_MAKEINSTANCE(wine_obj - 8) | DIDFT_POV;
         }
     }
-    for (i = 0; i < This->generic.devcaps.dwButtons; i++)
+    for (i = 0; i < This->joydev->button_count; i++)
         props[i + 12].dwType = DIDFT_MAKEINSTANCE(i) | DIDFT_PSHBUTTON;
     *prop_count = i + 12;
-
-    This->generic.devcaps.dwSize = sizeof(This->generic.devcaps);
-    This->generic.devcaps.dwFlags = DIDC_ATTACHED;
-    This->generic.devcaps.dwDevType = This->generic.base.info.dwDevType;
-
-    This->generic.devcaps.dwFFSamplePeriod = 0;
-    This->generic.devcaps.dwFFMinTimeResolution = 0;
-    This->generic.devcaps.dwFirmwareRevision = 0;
-    This->generic.devcaps.dwHardwareRevision = 0;
-    This->generic.devcaps.dwFFDriverVersion = 0;
-
-    if (TRACE_ON(dinput)) {
-        for (i = 0; i < (This->joydev->axis_count); i++) TRACE("axis_map[%d] = %d\n", i, This->generic.axis_map[i]);
-        _dump_DIDEVCAPS(&This->generic.devcaps);
-    }
+    *has_ff = FALSE;
 
     return DI_OK;
 }
@@ -635,7 +619,7 @@ static void CDECL unix_joystick_poll(struct unix_joystick *ptr)
               jse.type,jse.number,jse.value);
         if (jse.type & JS_EVENT_BUTTON)
         {
-            if (jse.number >= This->generic.devcaps.dwButtons) return;
+            if (jse.number >= This->joydev->button_count) return;
 
             inst_id = DIDFT_MAKEINSTANCE(jse.number) | DIDFT_PSHBUTTON;
             This->generic.js.rgbButtons[jse.number] = value = jse.value ? 0x80 : 0x00;
diff --git a/dlls/dinput/joystick_linuxinput.c b/dlls/dinput/joystick_linuxinput.c
index 152aa1a6934..3e65373badc 100644
--- a/dlls/dinput/joystick_linuxinput.c
+++ b/dlls/dinput/joystick_linuxinput.c
@@ -172,7 +172,7 @@ static HRESULT CDECL unix_joystick_get_effect_info(struct unix_joystick *ptr, RE
 static HRESULT CDECL unix_joystick_create_effect(struct unix_joystick *ptr, REFGUID guid, const DIEFFECT *effect,
         struct list *entry, IDirectInputEffect **out);
 
-static HRESULT CDECL unix_joystick_init(struct unix_joystick *ptr, ObjProps *props, int *prop_count);
+static HRESULT CDECL unix_joystick_init(struct unix_joystick *ptr, ObjProps *props, int *prop_count, BOOL *has_ff);
 static void CDECL unix_joystick_reset(struct unix_joystick *ptr);
 static void CDECL unix_joystick_get_mapping(struct unix_joystick *ptr, int *axis_count, const int **axes_map);
 
@@ -560,7 +560,7 @@ static void CDECL unix_joystick_get_mapping(struct unix_joystick *ptr, int *axis
     *axes_map = This->joydev->axes_map;
 }
 
-static HRESULT CDECL unix_joystick_init(struct unix_joystick *ptr, ObjProps *props, int *prop_count)
+static HRESULT CDECL unix_joystick_init(struct unix_joystick *ptr, ObjProps *props, int *prop_count, BOOL *has_ff)
 {
     JoystickImpl *This = impl_from_unix_joystick(ptr);
     int i, idx = 0, wine_obj;
@@ -574,8 +574,6 @@ static HRESULT CDECL unix_joystick_init(struct unix_joystick *ptr, ObjProps *pro
        enabled. */
     This->ff_autocenter = 1;
     This->ff_gain = 0xFFFF;
-    This->generic.ff_autocenter = DIPROPAUTOCENTER_ON;
-    This->generic.ff_gain = 10000;
 
     /* Count number of available axes - supported Axis & POVs */
     for (i = 0; i < ABS_MAX; i++)
@@ -622,14 +620,7 @@ static HRESULT CDECL unix_joystick_init(struct unix_joystick *ptr, ObjProps *pro
     for (i = 0; i < This->joydev->button_count; i++)
         props[i + 12].dwType = DIDFT_MAKEINSTANCE(i) | DIDFT_PSHBUTTON;
     *prop_count = i + 12;
-    This->generic.devcaps.dwButtons = This->joydev->button_count;
-
-    /* Fill the caps */
-    This->generic.devcaps.dwSize = sizeof(This->generic.devcaps);
-    This->generic.devcaps.dwFlags = DIDC_ATTACHED;
-    This->generic.devcaps.dwDevType = This->generic.base.info.dwDevType;
-
-    if (This->joydev->has_ff) This->generic.devcaps.dwFlags |= DIDC_FORCEFEEDBACK;
+    *has_ff = This->joydev->has_ff;
 
     return DI_OK;
 }
diff --git a/dlls/dinput/joystick_osx.c b/dlls/dinput/joystick_osx.c
index 380d52a52ad..c773b49e355 100644
--- a/dlls/dinput/joystick_osx.c
+++ b/dlls/dinput/joystick_osx.c
@@ -719,16 +719,9 @@ static void get_osx_device_elements(JoystickImpl *device, int axis_map[8])
         /* Sort buttons into correct order */
         CFArraySortValues(buttons, CFRangeMake(0, CFArrayGetCount(buttons)), button_usage_comparator, NULL);
 
-        device->generic.devcaps.dwAxes = CFArrayGetCount(axes);
-        device->generic.devcaps.dwButtons = CFArrayGetCount(buttons);
-        device->generic.devcaps.dwPOVs = CFArrayGetCount(povs);
-
-        TRACE("axes %u povs %u buttons %u\n", device->generic.devcaps.dwAxes, device->generic.devcaps.dwPOVs,
-              device->generic.devcaps.dwButtons);
-
         /* build our element array in the order that dinput expects */
-        CFArrayAppendArray(axes, povs, CFRangeMake(0, device->generic.devcaps.dwPOVs));
-        CFArrayAppendArray(axes, buttons, CFRangeMake(0, device->generic.devcaps.dwButtons));
+        CFArrayAppendArray(axes, povs, CFRangeMake(0, CFArrayGetCount(povs)));
+        CFArrayAppendArray(axes, buttons, CFRangeMake(0, CFArrayGetCount(buttons)));
         device->elements = axes;
         axes = NULL;
 
@@ -736,12 +729,6 @@ static void get_osx_device_elements(JoystickImpl *device, int axis_map[8])
         CFRelease(buttons);
         CFRelease(elements);
     }
-    else
-    {
-        device->generic.devcaps.dwAxes = 0;
-        device->generic.devcaps.dwButtons = 0;
-        device->generic.devcaps.dwPOVs = 0;
-    }
 }
 
 static BOOL osx_axis_has_ff(FFCAPABILITIES *ffcaps, UInt8 axis);
@@ -1005,7 +992,7 @@ static HRESULT CDECL unix_joystick_ff_send_cmd(struct unix_joystick *ptr, DWORD
 static HRESULT CDECL unix_joystick_create_effect(struct unix_joystick *ptr, REFGUID guid, const DIEFFECT *params,
         struct list *entry, IDirectInputEffect **out);
 
-static HRESULT CDECL unix_joystick_init(struct unix_joystick *ptr, ObjProps *props, int *prop_count);
+static HRESULT CDECL unix_joystick_init(struct unix_joystick *ptr, ObjProps *props, int *prop_count, BOOL *has_ff);
 
 static const struct unix_joystick_vtbl unix_joystick_vtbl =
 {
@@ -1194,7 +1181,7 @@ static HRESULT joydev_create_unix_joystick(IDirectInputImpl *dinput, REFGUID gui
     return DI_OK;
 }
 
-static HRESULT CDECL unix_joystick_init(struct unix_joystick *ptr, ObjProps *props, int *prop_count)
+static HRESULT CDECL unix_joystick_init(struct unix_joystick *ptr, ObjProps *props, int *prop_count, BOOL *has_ff)
 {
     JoystickImpl *This = impl_from_unix_joystick(ptr);
     IOHIDDeviceRef device;
@@ -1213,7 +1200,7 @@ static HRESULT CDECL unix_joystick_init(struct unix_joystick *ptr, ObjProps *pro
     list_init(&This->generic.ff_effects);
     if (get_ff(device, &This->ff) == S_OK)
     {
-        This->generic.devcaps.dwFlags |= DIDC_FORCEFEEDBACK;
+        *has_ff = TRUE;
 
         hr = FFDeviceGetForceFeedbackCapabilities(This->ff, &ffcaps);
         if(SUCCEEDED(hr)){
@@ -1241,36 +1228,14 @@ static HRESULT CDECL unix_joystick_init(struct unix_joystick *ptr, ObjProps *pro
         if(FAILED(hr))
             WARN("FFDeviceSendForceFeedbackCommand(FFSFFC_SETACTUATORSON) failed: %08x\n", hr);
     }
+    else *has_ff = FALSE;
 
     memset(axis_map, 0, sizeof(axis_map));
     get_osx_device_elements(This, axis_map);
 
-    TRACE("%i axes %i buttons %i povs\n", This->generic.devcaps.dwAxes, This->generic.devcaps.dwButtons,
-            This->generic.devcaps.dwPOVs);
-
-    if (This->generic.devcaps.dwButtons > 128)
-    {
-        WARN("Can't support %d buttons. Clamping down to 128\n", This->generic.devcaps.dwButtons);
-        This->generic.devcaps.dwButtons = 128;
-    }
-
     /* initialize default properties */
     get_osx_device_elements_props(This, &ffcaps, props, prop_count);
 
-    This->generic.devcaps.dwSize = sizeof(This->generic.devcaps);
-    This->generic.devcaps.dwFlags |= DIDC_ATTACHED;
-    This->generic.devcaps.dwDevType = This->generic.base.info.dwDevType;
-    This->generic.devcaps.dwFFSamplePeriod = 0;
-    This->generic.devcaps.dwFFMinTimeResolution = 0;
-    This->generic.devcaps.dwFirmwareRevision = 0;
-    This->generic.devcaps.dwHardwareRevision = 0;
-    This->generic.devcaps.dwFFDriverVersion = 0;
-
-    if (TRACE_ON(dinput)) {
-        TRACE("allocated device %p\n", This);
-        _dump_DIDEVCAPS(&This->generic.devcaps);
-    }
-
     return DI_OK;
 }
 
diff --git a/dlls/dinput/joystick_private.h b/dlls/dinput/joystick_private.h
index 6fe1bfce0a9..554d0799b4c 100644
--- a/dlls/dinput/joystick_private.h
+++ b/dlls/dinput/joystick_private.h
@@ -37,7 +37,7 @@ struct unix_joystick;
 
 struct unix_joystick_vtbl
 {
-    HRESULT (CDECL *init)(struct unix_joystick *ptr, ObjProps *props, int *prop_count);
+    HRESULT (CDECL *init)(struct unix_joystick *ptr, ObjProps *props, int *prop_count, BOOL *has_ff);
     void (CDECL *reset)(struct unix_joystick *ptr);
 
     void (CDECL *get_mapping)(struct unix_joystick *ptr, int *axis_count, const int **axes_map);
@@ -89,8 +89,6 @@ HRESULT WINAPI JoystickWGenericImpl_GetProperty(LPDIRECTINPUTDEVICE8W iface, REF
 
 HRESULT WINAPI JoystickWGenericImpl_GetCapabilities(LPDIRECTINPUTDEVICE8W iface, LPDIDEVCAPS lpDIDevCaps) DECLSPEC_HIDDEN;
 
-void _dump_DIDEVCAPS(const DIDEVCAPS *lpDIDevCaps) DECLSPEC_HIDDEN;
-
 HRESULT WINAPI JoystickWGenericImpl_SetProperty(LPDIRECTINPUTDEVICE8W iface, REFGUID rguid, LPCDIPROPHEADER ph) DECLSPEC_HIDDEN;
 
 HRESULT WINAPI JoystickWGenericImpl_Acquire(LPDIRECTINPUTDEVICE8W iface) DECLSPEC_HIDDEN;
-- 
2.28.0

>From 489a51e3ce98d7d4099ec77e96dee4d791e2c2cb Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?R=C3=A9mi=20Bernon?= <rbernon@codeweavers.com>
Date: Tue, 6 Oct 2020 11:38:18 +0200
Subject: [PATCH 30/39] dinput: Introduce win32_funcs and use it for
 queue_event.

---
 dlls/dinput/dinput_main.c         |  7 +++++++
 dlls/dinput/dinput_private.h      |  7 +++++++
 dlls/dinput/joystick.c            |  5 +++++
 dlls/dinput/joystick_linux.c      | 16 +++-------------
 dlls/dinput/joystick_linuxinput.c | 17 +++--------------
 dlls/dinput/joystick_osx.c        | 19 +++++--------------
 dlls/dinput/joystick_private.h    |  2 ++
 7 files changed, 32 insertions(+), 41 deletions(-)

diff --git a/dlls/dinput/dinput_main.c b/dlls/dinput/dinput_main.c
index 43986029a50..112a29e91be 100644
--- a/dlls/dinput/dinput_main.c
+++ b/dlls/dinput/dinput_main.c
@@ -84,6 +84,13 @@ static const struct dinput_device *dinput_devices[] =
     &joystick_osx_device
 };
 
+const struct win32_funcs win32_entry =
+{
+    dinput_unix_joystick_queue_event,
+};
+
+const struct win32_funcs *win32_funcs = &win32_entry;
+
 HINSTANCE DINPUT_instance;
 
 static const WCHAR di_em_win_w[] = {'D','I','E','m','W','i','n',0};
diff --git a/dlls/dinput/dinput_private.h b/dlls/dinput/dinput_private.h
index 9f3214eb260..7f603d303d4 100644
--- a/dlls/dinput/dinput_private.h
+++ b/dlls/dinput/dinput_private.h
@@ -64,6 +64,13 @@ struct dinput_device {
     HRESULT (*create_unix_joystick)(IDirectInputImpl *dinput, REFGUID rguid, JoystickGenericImpl **out);
 };
 
+typedef struct JoystickGenericImpl JoystickGenericImpl;
+
+struct win32_funcs
+{
+    void (CDECL *joystick_queue_event)(JoystickGenericImpl *This, int inst_id, DWORD data);
+};
+
 extern HRESULT dinput_create_device(const struct dinput_device *device, IDirectInputImpl *dinput, REFGUID guid,
         REFIID iid, void **out) DECLSPEC_HIDDEN;
 extern HRESULT dinput_enum_device(const struct dinput_device *device, DWORD type, DWORD flags, DIDEVICEINSTANCEW *didi,
diff --git a/dlls/dinput/joystick.c b/dlls/dinput/joystick.c
index de30e0aa073..39ccddb0032 100644
--- a/dlls/dinput/joystick.c
+++ b/dlls/dinput/joystick.c
@@ -1292,3 +1292,8 @@ done:
     if (FAILED(hr) && df) HeapFree(GetProcessHeap(), 0, df);
     return hr;
 }
+
+void CDECL dinput_unix_joystick_queue_event(JoystickGenericImpl *This, int inst_id, DWORD data)
+{
+    queue_event(&This->base.IDirectInputDevice8W_iface, inst_id, data, GetCurrentTime(), This->base.dinput->evsequence++);
+}
diff --git a/dlls/dinput/joystick_linux.c b/dlls/dinput/joystick_linux.c
index 8917d28f94b..6bf04c51399 100644
--- a/dlls/dinput/joystick_linux.c
+++ b/dlls/dinput/joystick_linux.c
@@ -70,6 +70,8 @@
 
 WINE_DEFAULT_DEBUG_CHANNEL(dinput);
 
+extern const struct win32_funcs *win32_funcs DECLSPEC_HIDDEN;
+
 #define JOYDEV_NEW "/dev/input/js"
 #define JOYDEV_OLD "/dev/js"
 #define JOYDEVDRIVER " (js)"
@@ -102,16 +104,6 @@ struct JoystickImpl
         POINTL                          povs[4];
 };
 
-static inline JoystickImpl *impl_from_IDirectInputDevice8W(IDirectInputDevice8W *iface)
-{
-    return CONTAINING_RECORD(CONTAINING_RECORD(CONTAINING_RECORD(iface, IDirectInputDeviceImpl, IDirectInputDevice8W_iface),
-           JoystickGenericImpl, base), JoystickImpl, generic);
-}
-static inline IDirectInputDevice8W *IDirectInputDevice8W_from_impl(JoystickImpl *This)
-{
-    return &This->generic.base.IDirectInputDevice8W_iface;
-}
-
 static inline struct unix_joystick *unix_joystick_from_impl(JoystickImpl *This)
 {
     return (struct unix_joystick *)This;
@@ -594,7 +586,6 @@ static void CDECL unix_joystick_poll(struct unix_joystick *ptr)
     struct pollfd plfd;
     struct js_event jse;
     JoystickImpl *This = impl_from_unix_joystick(ptr);
-    IDirectInputDevice8W *iface = IDirectInputDevice8W_from_impl(This);
 
     TRACE("(%p)\n", This);
 
@@ -660,8 +651,7 @@ static void CDECL unix_joystick_poll(struct unix_joystick *ptr)
                     WARN("axis %d not supported\n", number);
             }
         }
-        if (inst_id >= 0)
-            queue_event(iface, inst_id, value, GetCurrentTime(), This->generic.base.dinput->evsequence++);
+        if (inst_id >= 0) win32_funcs->joystick_queue_event(&This->generic, inst_id, value);
     }
 }
 
diff --git a/dlls/dinput/joystick_linuxinput.c b/dlls/dinput/joystick_linuxinput.c
index 3e65373badc..40a1f6a991f 100644
--- a/dlls/dinput/joystick_linuxinput.c
+++ b/dlls/dinput/joystick_linuxinput.c
@@ -68,6 +68,8 @@
 
 WINE_DEFAULT_DEBUG_CHANNEL(dinput);
 
+extern const struct win32_funcs *win32_funcs DECLSPEC_HIDDEN;
+
 #define EVDEVPREFIX "/dev/input/event"
 #define EVDEVDRIVER " (event)"
 
@@ -136,16 +138,6 @@ struct JoystickImpl
 	int				ff_gain;
 };
 
-static inline JoystickImpl *impl_from_IDirectInputDevice8W(IDirectInputDevice8W *iface)
-{
-    return CONTAINING_RECORD(CONTAINING_RECORD(CONTAINING_RECORD(iface, IDirectInputDeviceImpl, IDirectInputDevice8W_iface),
-           JoystickGenericImpl, base), JoystickImpl, generic);
-}
-static inline IDirectInputDevice8W *IDirectInputDevice8W_from_impl(JoystickImpl *This)
-{
-    return &This->generic.base.IDirectInputDevice8W_iface;
-}
-
 static inline struct unix_joystick *unix_joystick_from_impl(JoystickImpl *This)
 {
     return (struct unix_joystick *)This;
@@ -765,7 +757,6 @@ static void CDECL unix_joystick_poll(struct unix_joystick *ptr)
     struct pollfd plfd;
     struct input_event ie;
     JoystickImpl *This = impl_from_unix_joystick(ptr);
-    IDirectInputDevice8W *iface = IDirectInputDevice8W_from_impl(This);
 
     if (This->joyfd==-1)
 	return;
@@ -858,9 +849,7 @@ static void CDECL unix_joystick_poll(struct unix_joystick *ptr)
 	    TRACE("skipping event\n");
 	    break;
 	}
-        if (inst_id >= 0)
-            queue_event(iface, inst_id,
-                        value, GetCurrentTime(), This->generic.base.dinput->evsequence++);
+        if (inst_id >= 0) win32_funcs->joystick_queue_event(&This->generic, inst_id, value);
     }
 }
 
diff --git a/dlls/dinput/joystick_osx.c b/dlls/dinput/joystick_osx.c
index c773b49e355..d41dda7ddd0 100644
--- a/dlls/dinput/joystick_osx.c
+++ b/dlls/dinput/joystick_osx.c
@@ -96,6 +96,8 @@
 
 WINE_DEFAULT_DEBUG_CHANNEL(dinput);
 
+extern const struct win32_funcs *win32_funcs DECLSPEC_HIDDEN;
+
 static CFMutableArrayRef device_main_elements = NULL;
 
 typedef struct JoystickImpl JoystickImpl;
@@ -111,16 +113,6 @@ struct JoystickImpl
     FFDeviceObjectReference ff;
 };
 
-static inline JoystickImpl *impl_from_IDirectInputDevice8W(IDirectInputDevice8W *iface)
-{
-    return CONTAINING_RECORD(CONTAINING_RECORD(CONTAINING_RECORD(iface, IDirectInputDeviceImpl, IDirectInputDevice8W_iface),
-           JoystickGenericImpl, base), JoystickImpl, generic);
-}
-static inline IDirectInputDevice8W *IDirectInputDevice8W_from_impl(JoystickImpl *This)
-{
-    return &This->generic.base.IDirectInputDevice8W_iface;
-}
-
 static inline struct unix_joystick *unix_joystick_from_impl(JoystickImpl *This)
 {
     return (struct unix_joystick *)This;
@@ -815,7 +807,6 @@ static void get_osx_device_elements_props(JoystickImpl *device, FFCAPABILITIES *
 static void CDECL unix_joystick_poll(struct unix_joystick *ptr)
 {
     JoystickImpl *device = impl_from_unix_joystick(ptr);
-    IDirectInputDevice8W *iface = IDirectInputDevice8W_from_impl(device);
     IOHIDElementRef device_main_element;
     IOHIDDeviceRef hid_device;
 
@@ -866,7 +857,7 @@ static void CDECL unix_joystick_poll(struct unix_joystick *ptr)
                         if (oldVal != newVal)
                         {
                             inst_id = DIDFT_MAKEINSTANCE(button_idx) | DIDFT_PSHBUTTON;
-                            queue_event(iface,inst_id,newVal,GetCurrentTime(),device->generic.base.dinput->evsequence++);
+                            win32_funcs->joystick_queue_event(&device->generic, inst_id, newVal);
                         }
                         button_idx ++;
                     }
@@ -895,7 +886,7 @@ static void CDECL unix_joystick_poll(struct unix_joystick *ptr)
                             if (oldVal != newVal)
                             {
                                 inst_id = DIDFT_MAKEINSTANCE(pov_idx) | DIDFT_POV;
-                                queue_event(iface,inst_id,newVal,GetCurrentTime(),device->generic.base.dinput->evsequence++);
+                                win32_funcs->joystick_queue_event(&device->generic, inst_id, newVal);
                             }
                             pov_idx ++;
                             break;
@@ -968,7 +959,7 @@ static void CDECL unix_joystick_poll(struct unix_joystick *ptr)
                                  (oldVal != newVal))
                             {
                                 inst_id = DIDFT_MAKEINSTANCE(wine_obj) | DIDFT_ABSAXIS;
-                                queue_event(iface,inst_id,newVal,GetCurrentTime(),device->generic.base.dinput->evsequence++);
+                                win32_funcs->joystick_queue_event(&device->generic, inst_id, newVal);
                             }
 
                             break;
diff --git a/dlls/dinput/joystick_private.h b/dlls/dinput/joystick_private.h
index 554d0799b4c..1c0e2bc12be 100644
--- a/dlls/dinput/joystick_private.h
+++ b/dlls/dinput/joystick_private.h
@@ -82,6 +82,8 @@ DWORD joystick_map_pov(const POINTL *p) DECLSPEC_HIDDEN;
 
 extern BOOL device_disabled_registry(const WCHAR* name) DECLSPEC_HIDDEN;
 
+extern void CDECL dinput_unix_joystick_queue_event(JoystickGenericImpl *This, int inst_id, DWORD data) DECLSPEC_HIDDEN;
+
 HRESULT WINAPI JoystickWGenericImpl_GetObjectInfo(LPDIRECTINPUTDEVICE8W iface,
         LPDIDEVICEOBJECTINSTANCEW pdidoi, DWORD dwObj, DWORD dwHow) DECLSPEC_HIDDEN;
 
-- 
2.28.0

>From c8b0f704a2650fad638d79d554c2d945a1716817 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?R=C3=A9mi=20Bernon?= <rbernon@codeweavers.com>
Date: Tue, 6 Oct 2020 16:10:49 +0200
Subject: [PATCH 31/39] dinput: Use the win32_funcs callbacks for user axis
 mapping.

---
 dlls/dinput/dinput_main.c         | 3 ++-
 dlls/dinput/dinput_private.h      | 1 +
 dlls/dinput/joystick.c            | 7 +++++++
 dlls/dinput/joystick_linux.c      | 4 ++--
 dlls/dinput/joystick_linuxinput.c | 8 ++++----
 dlls/dinput/joystick_private.h    | 1 +
 6 files changed, 17 insertions(+), 7 deletions(-)

diff --git a/dlls/dinput/dinput_main.c b/dlls/dinput/dinput_main.c
index 112a29e91be..66a65b7b55e 100644
--- a/dlls/dinput/dinput_main.c
+++ b/dlls/dinput/dinput_main.c
@@ -86,7 +86,8 @@ static const struct dinput_device *dinput_devices[] =
 
 const struct win32_funcs win32_entry =
 {
-    dinput_unix_joystick_queue_event,
+    dinput_unix_joystick_get_axis,
+    dinput_unix_joystick_queue_event
 };
 
 const struct win32_funcs *win32_funcs = &win32_entry;
diff --git a/dlls/dinput/dinput_private.h b/dlls/dinput/dinput_private.h
index 7f603d303d4..58029d5b1f6 100644
--- a/dlls/dinput/dinput_private.h
+++ b/dlls/dinput/dinput_private.h
@@ -68,6 +68,7 @@ typedef struct JoystickGenericImpl JoystickGenericImpl;
 
 struct win32_funcs
 {
+    int (CDECL *joystick_get_axis)(JoystickGenericImpl *This, int index);
     void (CDECL *joystick_queue_event)(JoystickGenericImpl *This, int inst_id, DWORD data);
 };
 
diff --git a/dlls/dinput/joystick.c b/dlls/dinput/joystick.c
index 39ccddb0032..e412f49a6e2 100644
--- a/dlls/dinput/joystick.c
+++ b/dlls/dinput/joystick.c
@@ -1293,6 +1293,13 @@ done:
     return hr;
 }
 
+int CDECL dinput_unix_joystick_get_axis(JoystickGenericImpl *This, int index)
+{
+    if (!This->axis_map) return index;
+    if (index < 0) return index;
+    return This->axis_map[index];
+}
+
 void CDECL dinput_unix_joystick_queue_event(JoystickGenericImpl *This, int inst_id, DWORD data)
 {
     queue_event(&This->base.IDirectInputDevice8W_iface, inst_id, data, GetCurrentTime(), This->base.dinput->evsequence++);
diff --git a/dlls/dinput/joystick_linux.c b/dlls/dinput/joystick_linux.c
index 6bf04c51399..5f7ccf19514 100644
--- a/dlls/dinput/joystick_linux.c
+++ b/dlls/dinput/joystick_linux.c
@@ -515,7 +515,7 @@ static HRESULT CDECL unix_joystick_init(struct unix_joystick *ptr, ObjProps *pro
     {
         if ((idx = This->joydev->axes_map[i]) >= 0)
         {
-            wine_obj = This->generic.axis_map[i];
+            wine_obj = win32_funcs->joystick_get_axis(&This->generic, i);
             if (wine_obj < 0) props[idx].dwType = 0;
             else if (wine_obj < 8) props[idx].dwType = DIDFT_MAKEINSTANCE(wine_obj) | DIDFT_ABSAXIS;
             else props[idx].dwType = DIDFT_MAKEINSTANCE(wine_obj - 8) | DIDFT_POV;
@@ -617,7 +617,7 @@ static void CDECL unix_joystick_poll(struct unix_joystick *ptr)
         }
         else if (jse.type & JS_EVENT_AXIS)
         {
-            int number = This->generic.axis_map[jse.number];	/* wine format object index */
+            int number = win32_funcs->joystick_get_axis(&This->generic, jse.number);
 
             if (number < 0) return;
             inst_id = number < 8 ?  DIDFT_MAKEINSTANCE(number) | DIDFT_ABSAXIS :
diff --git a/dlls/dinput/joystick_linuxinput.c b/dlls/dinput/joystick_linuxinput.c
index 40a1f6a991f..4a21d67752f 100644
--- a/dlls/dinput/joystick_linuxinput.c
+++ b/dlls/dinput/joystick_linuxinput.c
@@ -575,7 +575,7 @@ static HRESULT CDECL unix_joystick_init(struct unix_joystick *ptr, ObjProps *pro
             props[idx].lDevMin = This->joydev->axes[i].minimum;
             props[idx].lDevMax = This->joydev->axes[i].maximum;
 
-            wine_obj = This->generic.axis_map[idx];
+            wine_obj = win32_funcs->joystick_get_axis(&This->generic, idx);
             if (wine_obj < 0) props[idx].dwType = 0;
             else if (wine_obj < 8) props[idx].dwType = DIDFT_MAKEINSTANCE(wine_obj) | DIDFT_ABSAXIS;
             else props[idx].dwType = DIDFT_MAKEINSTANCE(wine_obj - 8) | DIDFT_POV;
@@ -591,7 +591,7 @@ static HRESULT CDECL unix_joystick_init(struct unix_joystick *ptr, ObjProps *pro
             props[idx].lDevMin = This->joydev->axes[ABS_HAT0X + i * 2].minimum;
             props[idx].lDevMax = This->joydev->axes[ABS_HAT0X + i * 2].maximum;
 
-            wine_obj = This->generic.axis_map[idx];
+            wine_obj = win32_funcs->joystick_get_axis(&This->generic, idx);
             if (wine_obj < 0) props[idx].dwType = 0;
             else if (wine_obj < 8) props[idx].dwType = DIDFT_MAKEINSTANCE(wine_obj) | DIDFT_ABSAXIS;
             else props[idx].dwType = DIDFT_MAKEINSTANCE(wine_obj - 8) | DIDFT_POV;
@@ -602,7 +602,7 @@ static HRESULT CDECL unix_joystick_init(struct unix_joystick *ptr, ObjProps *pro
             props[idx].lDevMin = This->joydev->axes[ABS_HAT0Y + i * 2].minimum;
             props[idx].lDevMax = This->joydev->axes[ABS_HAT0Y + i * 2].maximum;
 
-            wine_obj = This->generic.axis_map[idx];
+            wine_obj = win32_funcs->joystick_get_axis(&This->generic, idx);
             if (wine_obj < 0) props[idx].dwType = 0;
             else if (wine_obj < 8) props[idx].dwType = DIDFT_MAKEINSTANCE(wine_obj) | DIDFT_ABSAXIS;
             else props[idx].dwType = DIDFT_MAKEINSTANCE(wine_obj - 8) | DIDFT_POV;
@@ -797,7 +797,7 @@ static void CDECL unix_joystick_poll(struct unix_joystick *ptr)
 
             /* User axis remapping */
             if (axis < 0) break;
-            axis = This->generic.axis_map[axis];
+            axis = win32_funcs->joystick_get_axis(&This->generic, axis);
             if (axis < 0) break;
 
             inst_id = axis < 8 ?  DIDFT_MAKEINSTANCE(axis) | DIDFT_ABSAXIS :
diff --git a/dlls/dinput/joystick_private.h b/dlls/dinput/joystick_private.h
index 1c0e2bc12be..b088f6c851a 100644
--- a/dlls/dinput/joystick_private.h
+++ b/dlls/dinput/joystick_private.h
@@ -82,6 +82,7 @@ DWORD joystick_map_pov(const POINTL *p) DECLSPEC_HIDDEN;
 
 extern BOOL device_disabled_registry(const WCHAR* name) DECLSPEC_HIDDEN;
 
+extern int CDECL dinput_unix_joystick_get_axis(JoystickGenericImpl *This, int index) DECLSPEC_HIDDEN;
 extern void CDECL dinput_unix_joystick_queue_event(JoystickGenericImpl *This, int inst_id, DWORD data) DECLSPEC_HIDDEN;
 
 HRESULT WINAPI JoystickWGenericImpl_GetObjectInfo(LPDIRECTINPUTDEVICE8W iface,
-- 
2.28.0

>From e26b4d04f67d2ddaa1fa2c3f56b39f32b6d1df89 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?R=C3=A9mi=20Bernon?= <rbernon@codeweavers.com>
Date: Tue, 6 Oct 2020 11:34:37 +0200
Subject: [PATCH 32/39] dinput: Update joystick button state on queue_event.

---
 dlls/dinput/dinput_private.h      |  2 +-
 dlls/dinput/joystick.c            | 14 ++++++++++++--
 dlls/dinput/joystick_linux.c      | 14 +++-----------
 dlls/dinput/joystick_linuxinput.c | 17 ++++-------------
 dlls/dinput/joystick_osx.c        | 24 ++++--------------------
 dlls/dinput/joystick_private.h    |  2 +-
 6 files changed, 25 insertions(+), 48 deletions(-)

diff --git a/dlls/dinput/dinput_private.h b/dlls/dinput/dinput_private.h
index 58029d5b1f6..41819fbd425 100644
--- a/dlls/dinput/dinput_private.h
+++ b/dlls/dinput/dinput_private.h
@@ -69,7 +69,7 @@ typedef struct JoystickGenericImpl JoystickGenericImpl;
 struct win32_funcs
 {
     int (CDECL *joystick_get_axis)(JoystickGenericImpl *This, int index);
-    void (CDECL *joystick_queue_event)(JoystickGenericImpl *This, int inst_id, DWORD data);
+    void (CDECL *joystick_queue_event)(JoystickGenericImpl *This, WORD type, int index, DWORD data);
 };
 
 extern HRESULT dinput_create_device(const struct dinput_device *device, IDirectInputImpl *dinput, REFGUID guid,
diff --git a/dlls/dinput/joystick.c b/dlls/dinput/joystick.c
index e412f49a6e2..0a9c0b3f158 100644
--- a/dlls/dinput/joystick.c
+++ b/dlls/dinput/joystick.c
@@ -1300,7 +1300,17 @@ int CDECL dinput_unix_joystick_get_axis(JoystickGenericImpl *This, int index)
     return This->axis_map[index];
 }
 
-void CDECL dinput_unix_joystick_queue_event(JoystickGenericImpl *This, int inst_id, DWORD data)
+void CDECL dinput_unix_joystick_queue_event(JoystickGenericImpl *This, WORD type, int index, DWORD data)
 {
-    queue_event(&This->base.IDirectInputDevice8W_iface, inst_id, data, GetCurrentTime(), This->base.dinput->evsequence++);
+    DWORD didft = DIDFT_MAKEINSTANCE(index) | type;
+
+    switch (type)
+    {
+    case DIDFT_PSHBUTTON:
+        if (index < 0 || index >= This->devcaps.dwButtons) return;
+        This->js.rgbButtons[index] = data;
+        break;
+    }
+
+    queue_event(&This->base.IDirectInputDevice8W_iface, didft, data, GetCurrentTime(), This->base.dinput->evsequence++);
 }
diff --git a/dlls/dinput/joystick_linux.c b/dlls/dinput/joystick_linux.c
index 5f7ccf19514..5295602984c 100644
--- a/dlls/dinput/joystick_linux.c
+++ b/dlls/dinput/joystick_linux.c
@@ -596,7 +596,6 @@ static void CDECL unix_joystick_poll(struct unix_joystick *ptr)
     while (1)
     {
         LONG value;
-        int inst_id = -1;
 
 	plfd.fd = This->joyfd;
 	plfd.events = POLLIN;
@@ -609,19 +608,11 @@ static void CDECL unix_joystick_poll(struct unix_joystick *ptr)
         TRACE("js_event: type 0x%x, number %d, value %d\n",
               jse.type,jse.number,jse.value);
         if (jse.type & JS_EVENT_BUTTON)
-        {
-            if (jse.number >= This->joydev->button_count) return;
-
-            inst_id = DIDFT_MAKEINSTANCE(jse.number) | DIDFT_PSHBUTTON;
-            This->generic.js.rgbButtons[jse.number] = value = jse.value ? 0x80 : 0x00;
-        }
+            win32_funcs->joystick_queue_event(&This->generic, DIDFT_PSHBUTTON, jse.number, jse.value ? 0x80 : 0x00);
         else if (jse.type & JS_EVENT_AXIS)
         {
             int number = win32_funcs->joystick_get_axis(&This->generic, jse.number);
-
             if (number < 0) return;
-            inst_id = number < 8 ?  DIDFT_MAKEINSTANCE(number) | DIDFT_ABSAXIS :
-                                    DIDFT_MAKEINSTANCE(number - 8) | DIDFT_POV;
             value = joystick_map_axis(&This->generic.props[This->joydev->axes_map[jse.number]], jse.value);
 
             TRACE("changing axis %d => %d\n", jse.number, number);
@@ -650,8 +641,9 @@ static void CDECL unix_joystick_poll(struct unix_joystick *ptr)
                 default:
                     WARN("axis %d not supported\n", number);
             }
+            if (number < 8) win32_funcs->joystick_queue_event(&This->generic, DIDFT_ABSAXIS, number, value);
+            else win32_funcs->joystick_queue_event(&This->generic, DIDFT_POV, number - 8, value);
         }
-        if (inst_id >= 0) win32_funcs->joystick_queue_event(&This->generic, inst_id, value);
     }
 }
 
diff --git a/dlls/dinput/joystick_linuxinput.c b/dlls/dinput/joystick_linuxinput.c
index 4a21d67752f..a7ebb95fe58 100644
--- a/dlls/dinput/joystick_linuxinput.c
+++ b/dlls/dinput/joystick_linuxinput.c
@@ -764,7 +764,6 @@ static void CDECL unix_joystick_poll(struct unix_joystick *ptr)
     while (1)
     {
         LONG value = 0;
-        int inst_id = -1;
 
 	plfd.fd = This->joyfd;
 	plfd.events = POLLIN;
@@ -781,14 +780,8 @@ static void CDECL unix_joystick_poll(struct unix_joystick *ptr)
 	case EV_KEY:	/* button */
         {
             int btn = This->joydev->buttons[ie.code];
-
             TRACE("(%p) %d -> %d\n", This, ie.code, btn);
-            if (btn & 0x80)
-            {
-                btn &= 0x7F;
-                inst_id = DIDFT_MAKEINSTANCE(btn) | DIDFT_PSHBUTTON;
-                This->generic.js.rgbButtons[btn] = value = ie.value ? 0x80 : 0x00;
-            }
+            if (btn & 0x80) win32_funcs->joystick_queue_event(&This->generic, DIDFT_PSHBUTTON, btn & 0x7f, ie.value ? 0x80 : 0x00);
             break;
         }
 	case EV_ABS:
@@ -799,9 +792,6 @@ static void CDECL unix_joystick_poll(struct unix_joystick *ptr)
             if (axis < 0) break;
             axis = win32_funcs->joystick_get_axis(&This->generic, axis);
             if (axis < 0) break;
-
-            inst_id = axis < 8 ?  DIDFT_MAKEINSTANCE(axis) | DIDFT_ABSAXIS :
-                                  DIDFT_MAKEINSTANCE(axis - 8) | DIDFT_POV;
             value = joystick_map_axis(&This->generic.props[This->joydev->dev_axes_to_di[ie.code]], ie.value);
 
 	    switch (axis) {
@@ -828,7 +818,9 @@ static void CDECL unix_joystick_poll(struct unix_joystick *ptr)
 	    default:
 		FIXME("unhandled joystick axis event (code %d, value %d)\n",ie.code,ie.value);
 	    }
-	    break;
+            if (axis < 8) win32_funcs->joystick_queue_event(&This->generic, DIDFT_ABSAXIS, axis, value);
+            else win32_funcs->joystick_queue_event(&This->generic, DIDFT_POV, axis - 8, value);
+            break;
         }
 #ifdef HAVE_STRUCT_FF_EFFECT_DIRECTION
 	case EV_FF_STATUS:
@@ -849,7 +841,6 @@ static void CDECL unix_joystick_poll(struct unix_joystick *ptr)
 	    TRACE("skipping event\n");
 	    break;
 	}
-        if (inst_id >= 0) win32_funcs->joystick_queue_event(&This->generic, inst_id, value);
     }
 }
 
diff --git a/dlls/dinput/joystick_osx.c b/dlls/dinput/joystick_osx.c
index d41dda7ddd0..ab999875170 100644
--- a/dlls/dinput/joystick_osx.c
+++ b/dlls/dinput/joystick_osx.c
@@ -826,7 +826,6 @@ static void CDECL unix_joystick_poll(struct unix_joystick *ptr)
         int button_idx = 0;
         int pov_idx = 0;
         int slider_idx = 0;
-        int inst_id;
         CFIndex idx, cnt = CFArrayGetCount( device->elements );
 
         for ( idx = 0; idx < cnt; idx++ )
@@ -850,15 +849,7 @@ static void CDECL unix_joystick_poll(struct unix_joystick *ptr)
                         if (valueRef == NULL)
                             return;
                         val = IOHIDValueGetIntegerValue(valueRef);
-                        newVal = val ? 0x80 : 0x0;
-                        oldVal = device->generic.js.rgbButtons[button_idx];
-                        device->generic.js.rgbButtons[button_idx] = newVal;
-                        TRACE("valueRef %s val %d oldVal %d newVal %d\n", debugstr_cf(valueRef), val, oldVal, newVal);
-                        if (oldVal != newVal)
-                        {
-                            inst_id = DIDFT_MAKEINSTANCE(button_idx) | DIDFT_PSHBUTTON;
-                            win32_funcs->joystick_queue_event(&device->generic, inst_id, newVal);
-                        }
+                        win32_funcs->joystick_queue_event(&device->generic, DIDFT_PSHBUTTON, button_idx, val ? 0x80 : 0x0);
                         button_idx ++;
                     }
                     break;
@@ -884,10 +875,7 @@ static void CDECL unix_joystick_poll(struct unix_joystick *ptr)
                             device->generic.js.rgdwPOV[pov_idx] = newVal;
                             TRACE("valueRef %s val %d oldVal %d newVal %d\n", debugstr_cf(valueRef), val, oldVal, newVal);
                             if (oldVal != newVal)
-                            {
-                                inst_id = DIDFT_MAKEINSTANCE(pov_idx) | DIDFT_POV;
-                                win32_funcs->joystick_queue_event(&device->generic, inst_id, newVal);
-                            }
+                                win32_funcs->joystick_queue_event(&device->generic, DIDFT_POV, pov_idx, newVal);
                             pov_idx ++;
                             break;
                         }
@@ -955,12 +943,8 @@ static void CDECL unix_joystick_poll(struct unix_joystick *ptr)
                                 break;
                             }
                             TRACE("valueRef %s val %d oldVal %d newVal %d\n", debugstr_cf(valueRef), val, oldVal, newVal);
-                            if ((wine_obj != -1) &&
-                                 (oldVal != newVal))
-                            {
-                                inst_id = DIDFT_MAKEINSTANCE(wine_obj) | DIDFT_ABSAXIS;
-                                win32_funcs->joystick_queue_event(&device->generic, inst_id, newVal);
-                            }
+                            if ((wine_obj != -1) && (oldVal != newVal))
+                                win32_funcs->joystick_queue_event(&device->generic, DIDFT_ABSAXIS, wine_obj, newVal);
 
                             break;
                         }
diff --git a/dlls/dinput/joystick_private.h b/dlls/dinput/joystick_private.h
index b088f6c851a..4dee1ae1948 100644
--- a/dlls/dinput/joystick_private.h
+++ b/dlls/dinput/joystick_private.h
@@ -83,7 +83,7 @@ DWORD joystick_map_pov(const POINTL *p) DECLSPEC_HIDDEN;
 extern BOOL device_disabled_registry(const WCHAR* name) DECLSPEC_HIDDEN;
 
 extern int CDECL dinput_unix_joystick_get_axis(JoystickGenericImpl *This, int index) DECLSPEC_HIDDEN;
-extern void CDECL dinput_unix_joystick_queue_event(JoystickGenericImpl *This, int inst_id, DWORD data) DECLSPEC_HIDDEN;
+extern void CDECL dinput_unix_joystick_queue_event(JoystickGenericImpl *This, WORD type, int index, DWORD data) DECLSPEC_HIDDEN;
 
 HRESULT WINAPI JoystickWGenericImpl_GetObjectInfo(LPDIRECTINPUTDEVICE8W iface,
         LPDIDEVICEOBJECTINSTANCEW pdidoi, DWORD dwObj, DWORD dwHow) DECLSPEC_HIDDEN;
-- 
2.28.0

>From c0d034ece76e2478d016c7e498e5f5cde82c56fd Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?R=C3=A9mi=20Bernon?= <rbernon@codeweavers.com>
Date: Tue, 6 Oct 2020 11:44:18 +0200
Subject: [PATCH 33/39] dinput: Update joystick axis and pov state on
 queue_event.

---
 dlls/dinput/joystick.c            | 19 ++++++++++++
 dlls/dinput/joystick_linux.c      | 41 ++++++--------------------
 dlls/dinput/joystick_linuxinput.c | 38 ++++++------------------
 dlls/dinput/joystick_osx.c        | 48 +++++++------------------------
 4 files changed, 47 insertions(+), 99 deletions(-)

diff --git a/dlls/dinput/joystick.c b/dlls/dinput/joystick.c
index 0a9c0b3f158..ac2e53489bb 100644
--- a/dlls/dinput/joystick.c
+++ b/dlls/dinput/joystick.c
@@ -1310,6 +1310,25 @@ void CDECL dinput_unix_joystick_queue_event(JoystickGenericImpl *This, WORD type
         if (index < 0 || index >= This->devcaps.dwButtons) return;
         This->js.rgbButtons[index] = data;
         break;
+    case DIDFT_ABSAXIS:
+        if (index < 0 || index >= This->devcaps.dwAxes) return;
+        data = joystick_map_axis(&This->props[index], data);
+        switch (index)
+        {
+        case 0: This->js.lX = data; break;
+        case 1: This->js.lY = data; break;
+        case 2: This->js.lZ = data; break;
+        case 3: This->js.lRx = data; break;
+        case 4: This->js.lRy = data; break;
+        case 5: This->js.lRz = data; break;
+        case 6: This->js.rglSlider[0] = data; break;
+        case 7: This->js.rglSlider[1] = data; break;
+        }
+        break;
+    case DIDFT_POV:
+        if (index < 0 || index >= This->devcaps.dwPOVs) return;
+        This->js.rgdwPOV[index] = data;
+        break;
     }
 
     queue_event(&This->base.IDirectInputDevice8W_iface, didft, data, GetCurrentTime(), This->base.dinput->evsequence++);
diff --git a/dlls/dinput/joystick_linux.c b/dlls/dinput/joystick_linux.c
index 5295602984c..8ca6deb90b6 100644
--- a/dlls/dinput/joystick_linux.c
+++ b/dlls/dinput/joystick_linux.c
@@ -595,8 +595,6 @@ static void CDECL unix_joystick_poll(struct unix_joystick *ptr)
     }
     while (1)
     {
-        LONG value;
-
 	plfd.fd = This->joyfd;
 	plfd.events = POLLIN;
 	if (poll(&plfd,1,0) != 1)
@@ -611,38 +609,17 @@ static void CDECL unix_joystick_poll(struct unix_joystick *ptr)
             win32_funcs->joystick_queue_event(&This->generic, DIDFT_PSHBUTTON, jse.number, jse.value ? 0x80 : 0x00);
         else if (jse.type & JS_EVENT_AXIS)
         {
-            int number = win32_funcs->joystick_get_axis(&This->generic, jse.number);
-            if (number < 0) return;
-            value = joystick_map_axis(&This->generic.props[This->joydev->axes_map[jse.number]], jse.value);
-
-            TRACE("changing axis %d => %d\n", jse.number, number);
-            switch (number)
+            int axis = win32_funcs->joystick_get_axis(&This->generic, jse.number);
+            if (axis < 0) return;
+            TRACE("changing axis %d => %d\n", jse.number, axis);
+            if (axis >= 0 && axis < 8) win32_funcs->joystick_queue_event(&This->generic, DIDFT_ABSAXIS, axis, jse.value);
+            else if (axis >= 8 && axis < 12)
             {
-                case 0: This->generic.js.lX  = value; break;
-                case 1: This->generic.js.lY  = value; break;
-                case 2: This->generic.js.lZ  = value; break;
-                case 3: This->generic.js.lRx = value; break;
-                case 4: This->generic.js.lRy = value; break;
-                case 5: This->generic.js.lRz = value; break;
-                case 6: This->generic.js.rglSlider[0] = value; break;
-                case 7: This->generic.js.rglSlider[1] = value; break;
-                case 8: case 9: case 10: case 11:
-                {
-                    int idx = number - 8;
-
-                    if (jse.number % 2)
-                        This->povs[idx].y = jse.value;
-                    else
-                        This->povs[idx].x = jse.value;
-
-                    This->generic.js.rgdwPOV[idx] = value = joystick_map_pov(&This->povs[idx]);
-                    break;
-                }
-                default:
-                    WARN("axis %d not supported\n", number);
+                if (jse.number % 2) This->povs[axis - 8].y = jse.value;
+                else This->povs[axis - 8].x = jse.value;
+                win32_funcs->joystick_queue_event(&This->generic, DIDFT_POV, axis - 8, joystick_map_pov(&This->povs[axis - 8]));
             }
-            if (number < 8) win32_funcs->joystick_queue_event(&This->generic, DIDFT_ABSAXIS, number, value);
-            else win32_funcs->joystick_queue_event(&This->generic, DIDFT_POV, number - 8, value);
+            else WARN("axis %d not supported\n", axis);
         }
     }
 }
diff --git a/dlls/dinput/joystick_linuxinput.c b/dlls/dinput/joystick_linuxinput.c
index a7ebb95fe58..b4559fffedc 100644
--- a/dlls/dinput/joystick_linuxinput.c
+++ b/dlls/dinput/joystick_linuxinput.c
@@ -763,8 +763,6 @@ static void CDECL unix_joystick_poll(struct unix_joystick *ptr)
 
     while (1)
     {
-        LONG value = 0;
-
 	plfd.fd = This->joyfd;
 	plfd.events = POLLIN;
 
@@ -787,39 +785,19 @@ static void CDECL unix_joystick_poll(struct unix_joystick *ptr)
 	case EV_ABS:
         {
             int axis = This->joydev->dev_axes_to_di[ie.code];
-
-            /* User axis remapping */
             if (axis < 0) break;
             axis = win32_funcs->joystick_get_axis(&This->generic, axis);
             if (axis < 0) break;
-            value = joystick_map_axis(&This->generic.props[This->joydev->dev_axes_to_di[ie.code]], ie.value);
-
-	    switch (axis) {
-            case 0: This->generic.js.lX  = value; break;
-            case 1: This->generic.js.lY  = value; break;
-            case 2: This->generic.js.lZ  = value; break;
-            case 3: This->generic.js.lRx = value; break;
-            case 4: This->generic.js.lRy = value; break;
-            case 5: This->generic.js.lRz = value; break;
-            case 6: This->generic.js.rglSlider[0] = value; break;
-            case 7: This->generic.js.rglSlider[1] = value; break;
-            case 8: case 9: case 10: case 11:
-            {
-                int idx = axis - 8;
-
-                if (ie.code % 2)
-                    This->povs[idx].y = ie.value;
-                else
-                    This->povs[idx].x = ie.value;
 
-                This->generic.js.rgdwPOV[idx] = value = joystick_map_pov(&This->povs[idx]);
-                break;
+            if (axis >= 0 && axis < 8) win32_funcs->joystick_queue_event(&This->generic, DIDFT_ABSAXIS, axis, ie.value);
+            else if (axis >= 8 && axis < 12)
+            {
+                if (ie.code % 2) This->povs[axis - 8].y = ie.value;
+                else This->povs[axis - 8].x = ie.value;
+                win32_funcs->joystick_queue_event(&This->generic, DIDFT_POV, axis - 8, joystick_map_pov(&This->povs[axis - 8]));
             }
-	    default:
-		FIXME("unhandled joystick axis event (code %d, value %d)\n",ie.code,ie.value);
-	    }
-            if (axis < 8) win32_funcs->joystick_queue_event(&This->generic, DIDFT_ABSAXIS, axis, value);
-            else win32_funcs->joystick_queue_event(&This->generic, DIDFT_POV, axis - 8, value);
+            else FIXME("unhandled joystick axis event (code %d, value %d)\n", ie.code, ie.value);
+
             break;
         }
 #ifdef HAVE_STRUCT_FF_EFFECT_DIRECTION
diff --git a/dlls/dinput/joystick_osx.c b/dlls/dinput/joystick_osx.c
index ab999875170..5aebf2d570b 100644
--- a/dlls/dinput/joystick_osx.c
+++ b/dlls/dinput/joystick_osx.c
@@ -831,7 +831,7 @@ static void CDECL unix_joystick_poll(struct unix_joystick *ptr)
         for ( idx = 0; idx < cnt; idx++ )
         {
             IOHIDValueRef valueRef;
-            int val, oldVal, newVal;
+            int val;
             IOHIDElementRef element = ( IOHIDElementRef ) CFArrayGetValueAtIndex( device->elements, idx );
             int type = IOHIDElementGetType( element );
 
@@ -867,15 +867,9 @@ static void CDECL unix_joystick_poll(struct unix_joystick *ptr)
                             if (valueRef == NULL)
                                 return;
                             val = IOHIDValueGetIntegerValue(valueRef);
-                            oldVal = device->generic.js.rgdwPOV[pov_idx];
-                            if (val >= 8)
-                                newVal = -1;
-                            else
-                                newVal = val * 4500;
-                            device->generic.js.rgdwPOV[pov_idx] = newVal;
-                            TRACE("valueRef %s val %d oldVal %d newVal %d\n", debugstr_cf(valueRef), val, oldVal, newVal);
-                            if (oldVal != newVal)
-                                win32_funcs->joystick_queue_event(&device->generic, DIDFT_POV, pov_idx, newVal);
+                            if (val >= 8) val = -1;
+                            else val = val * 4500;
+                            win32_funcs->joystick_queue_event(&device->generic, DIDFT_POV, pov_idx, val);
                             pov_idx ++;
                             break;
                         }
@@ -887,64 +881,44 @@ static void CDECL unix_joystick_poll(struct unix_joystick *ptr)
                         case kHIDUsage_GD_Rz:
                         case kHIDUsage_GD_Slider:
                         {
-                            int wine_obj = -1;
-
                             valueRef = NULL;
                             if (IOHIDDeviceGetValue(hid_device, element, &valueRef) != kIOReturnSuccess)
                                 return;
                             if (valueRef == NULL)
                                 return;
                             val = IOHIDValueGetIntegerValue(valueRef);
-                            newVal = joystick_map_axis(&device->generic.props[idx], val);
                             switch (usage)
                             {
                             case kHIDUsage_GD_X:
                                 TRACE("kIOHIDElementTypeInput_Misc / kHIDUsage_GD_X\n");
-                                wine_obj = 0;
-                                oldVal = device->generic.js.lX;
-                                device->generic.js.lX = newVal;
+                                win32_funcs->joystick_queue_event(&device->generic, DIDFT_ABSAXIS, 0, val);
                                 break;
                             case kHIDUsage_GD_Y:
                                 TRACE("kIOHIDElementTypeInput_Misc / kHIDUsage_GD_Y\n");
-                                wine_obj = 1;
-                                oldVal = device->generic.js.lY;
-                                device->generic.js.lY = newVal;
+                                win32_funcs->joystick_queue_event(&device->generic, DIDFT_ABSAXIS, 1, val);
                                 break;
                             case kHIDUsage_GD_Z:
                                 TRACE("kIOHIDElementTypeInput_Misc / kHIDUsage_GD_Z\n");
-                                wine_obj = 2;
-                                oldVal = device->generic.js.lZ;
-                                device->generic.js.lZ = newVal;
+                                win32_funcs->joystick_queue_event(&device->generic, DIDFT_ABSAXIS, 2, val);
                                 break;
                             case kHIDUsage_GD_Rx:
                                 TRACE("kIOHIDElementTypeInput_Misc / kHIDUsage_GD_Rx\n");
-                                wine_obj = 3;
-                                oldVal = device->generic.js.lRx;
-                                device->generic.js.lRx = newVal;
+                                win32_funcs->joystick_queue_event(&device->generic, DIDFT_ABSAXIS, 3, val);
                                 break;
                             case kHIDUsage_GD_Ry:
                                 TRACE("kIOHIDElementTypeInput_Misc / kHIDUsage_GD_Ry\n");
-                                wine_obj = 4;
-                                oldVal = device->generic.js.lRy;
-                                device->generic.js.lRy = newVal;
+                                win32_funcs->joystick_queue_event(&device->generic, DIDFT_ABSAXIS, 4, val);
                                 break;
                             case kHIDUsage_GD_Rz:
                                 TRACE("kIOHIDElementTypeInput_Misc / kHIDUsage_GD_Rz\n");
-                                wine_obj = 5;
-                                oldVal = device->generic.js.lRz;
-                                device->generic.js.lRz = newVal;
+                                win32_funcs->joystick_queue_event(&device->generic, DIDFT_ABSAXIS, 5, val);
                                 break;
                             case kHIDUsage_GD_Slider:
                                 TRACE("kIOHIDElementTypeInput_Misc / kHIDUsage_GD_Slider\n");
-                                wine_obj = 6 + slider_idx;
-                                oldVal = device->generic.js.rglSlider[slider_idx];
-                                device->generic.js.rglSlider[slider_idx] = newVal;
+                                win32_funcs->joystick_queue_event(&device->generic, DIDFT_ABSAXIS, 6 + slider_idx, val);
                                 slider_idx ++;
                                 break;
                             }
-                            TRACE("valueRef %s val %d oldVal %d newVal %d\n", debugstr_cf(valueRef), val, oldVal, newVal);
-                            if ((wine_obj != -1) && (oldVal != newVal))
-                                win32_funcs->joystick_queue_event(&device->generic, DIDFT_ABSAXIS, wine_obj, newVal);
 
                             break;
                         }
-- 
2.28.0

>From de7fa9ed38bb890a261df6e8319cafbbd43eec48 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?R=C3=A9mi=20Bernon?= <rbernon@codeweavers.com>
Date: Mon, 5 Oct 2020 20:58:16 +0200
Subject: [PATCH 34/39] dinput: Update joystick initial state using
 queue_event.

---
 dlls/dinput/device_private.h      |  1 -
 dlls/dinput/joystick.c            | 14 +++++++++++++-
 dlls/dinput/joystick_linuxinput.c | 27 +++++++++++----------------
 dlls/dinput/joystick_private.h    |  2 --
 4 files changed, 24 insertions(+), 20 deletions(-)

diff --git a/dlls/dinput/device_private.h b/dlls/dinput/device_private.h
index ef6bb05108f..0ba20abe68e 100644
--- a/dlls/dinput/device_private.h
+++ b/dlls/dinput/device_private.h
@@ -119,7 +119,6 @@ typedef struct
 } ObjProps;
 
 extern DWORD joystick_map_pov(const POINTL *p) DECLSPEC_HIDDEN;
-extern LONG joystick_map_axis(ObjProps *props, int val) DECLSPEC_HIDDEN;
 
 typedef struct
 {
diff --git a/dlls/dinput/joystick.c b/dlls/dinput/joystick.c
index ac2e53489bb..f226fa944e7 100644
--- a/dlls/dinput/joystick.c
+++ b/dlls/dinput/joystick.c
@@ -339,6 +339,8 @@ static BOOL is_xinput_device(const DIDEVCAPS *devcaps, WORD vid, WORD pid)
     return (devcaps->dwAxes == 6 && devcaps->dwButtons >= 14);
 }
 
+static LONG joystick_map_axis(ObjProps *props, int val);
+
 /******************************************************************************
   *     SetProperty : change input device properties
   */
@@ -982,7 +984,7 @@ HRESULT WINAPI JoystickWGenericImpl_SetActionMap(LPDIRECTINPUTDEVICE8W iface,
  * Notes:
  *   Dead zone is in % multiplied by a 100 (range 0..10000)
  */
-LONG joystick_map_axis(ObjProps *props, int val)
+static LONG joystick_map_axis(ObjProps *props, int val)
 {
     LONG ret;
     LONG dead_zone = MulDiv( props->lDeadZone, props->lDevMax - props->lDevMin, 10000 );
@@ -1225,6 +1227,16 @@ HRESULT dinput_create_unix_joystick(const struct dinput_device *device, IDirectI
     This->devcaps.dwFlags = DIDC_ATTACHED;
     This->devcaps.dwDevType = This->base.info.dwDevType;
 
+    This->js.lX = 0;
+    This->js.lY = 0;
+    This->js.lZ = 0;
+    This->js.lRx = 0;
+    This->js.lRy = 0;
+    This->js.lRz = 0;
+    This->js.rglSlider[0] = 0;
+    This->js.rglSlider[1] = 0;
+    for (i = 0; i < 4; i++) This->js.rgdwPOV[i] = -1;
+
     if (FAILED(hr = This->unix_funcs->init(This->unix_ptr, props, &prop_count, &has_ff))) goto done;
     memcpy(This->props, props, sizeof(This->props));
 
diff --git a/dlls/dinput/joystick_linuxinput.c b/dlls/dinput/joystick_linuxinput.c
index b4559fffedc..f9fbffc0c0c 100644
--- a/dlls/dinput/joystick_linuxinput.c
+++ b/dlls/dinput/joystick_linuxinput.c
@@ -729,25 +729,20 @@ static HRESULT CDECL unix_joystick_ff_set_gain(struct unix_joystick *ptr, DWORD
  * values on the axes
  */
 #define CENTER_AXIS(a) \
-    (This->joydev->dev_axes_to_di[a] == -1 ? 0 : joystick_map_axis(&This->generic.props[This->joydev->dev_axes_to_di[a]], This->joydev->axes[a].value))
+    if ((axis = This->joydev->dev_axes_to_di[a]) >= 0) \
+        win32_funcs->joystick_queue_event(&This->generic, DIDFT_ABSAXIS, axis, This->joydev->axes[a].value)
 static void CDECL unix_joystick_reset(struct unix_joystick *ptr)
 {
     JoystickImpl *This = impl_from_unix_joystick(ptr);
-    int i;
-
-    /* center the axes */
-    This->generic.js.lX           = CENTER_AXIS(ABS_X);
-    This->generic.js.lY           = CENTER_AXIS(ABS_Y);
-    This->generic.js.lZ           = CENTER_AXIS(ABS_Z);
-    This->generic.js.lRx          = CENTER_AXIS(ABS_RX);
-    This->generic.js.lRy          = CENTER_AXIS(ABS_RY);
-    This->generic.js.lRz          = CENTER_AXIS(ABS_RZ);
-    This->generic.js.rglSlider[0] = CENTER_AXIS(ABS_THROTTLE);
-    This->generic.js.rglSlider[1] = CENTER_AXIS(ABS_RUDDER);
-
-    /* POV center is -1 */
-    for (i = 0; i < 4; i++)
-        This->generic.js.rgdwPOV[i] = -1;
+    int axis;
+    CENTER_AXIS(ABS_X);
+    CENTER_AXIS(ABS_Y);
+    CENTER_AXIS(ABS_Z);
+    CENTER_AXIS(ABS_RX);
+    CENTER_AXIS(ABS_RY);
+    CENTER_AXIS(ABS_RZ);
+    CENTER_AXIS(ABS_THROTTLE);
+    CENTER_AXIS(ABS_RUDDER);
 }
 #undef CENTER_AXIS
 
diff --git a/dlls/dinput/joystick_private.h b/dlls/dinput/joystick_private.h
index 4dee1ae1948..44d8731bdb1 100644
--- a/dlls/dinput/joystick_private.h
+++ b/dlls/dinput/joystick_private.h
@@ -76,8 +76,6 @@ typedef struct JoystickGenericImpl
 
 extern HRESULT dinput_create_unix_joystick(const struct dinput_device *device, IDirectInputImpl *dinput, REFGUID guid, REFIID iid, void **out) DECLSPEC_HIDDEN;
 
-LONG joystick_map_axis(ObjProps *props, int val) DECLSPEC_HIDDEN;
-
 DWORD joystick_map_pov(const POINTL *p) DECLSPEC_HIDDEN;
 
 extern BOOL device_disabled_registry(const WCHAR* name) DECLSPEC_HIDDEN;
-- 
2.28.0

>From 109ecdded8e1736893a07e5e3ac684f47eaef55d Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?R=C3=A9mi=20Bernon?= <rbernon@codeweavers.com>
Date: Tue, 6 Oct 2020 16:16:53 +0200
Subject: [PATCH 35/39] dinput: Use unix vtable and wrapper for joystick
 effects.

---
 dlls/dinput/device_private.h      |   6 -
 dlls/dinput/effect_linuxinput.c   | 247 ++++++++++--------------------
 dlls/dinput/joystick.c            | 200 ++++++++++++++++++++++--
 dlls/dinput/joystick_linuxinput.c |  27 +---
 dlls/dinput/joystick_osx.c        | 169 +++++++-------------
 dlls/dinput/joystick_private.h    |  18 ++-
 6 files changed, 348 insertions(+), 319 deletions(-)

diff --git a/dlls/dinput/device_private.h b/dlls/dinput/device_private.h
index 0ba20abe68e..d6ce489c3e1 100644
--- a/dlls/dinput/device_private.h
+++ b/dlls/dinput/device_private.h
@@ -120,12 +120,6 @@ typedef struct
 
 extern DWORD joystick_map_pov(const POINTL *p) DECLSPEC_HIDDEN;
 
-typedef struct
-{
-    struct list entry;
-    LPDIRECTINPUTEFFECT ref;
-} effect_list_item;
-
 extern const GUID DInput_PIDVID_Product_GUID DECLSPEC_HIDDEN;
 
 /* Various debug tools */
diff --git a/dlls/dinput/effect_linuxinput.c b/dlls/dinput/effect_linuxinput.c
index d5daba6daa1..640b527c4e2 100644
--- a/dlls/dinput/effect_linuxinput.c
+++ b/dlls/dinput/effect_linuxinput.c
@@ -47,24 +47,23 @@
 
 WINE_DEFAULT_DEBUG_CHANNEL(dinput);
 
-static const IDirectInputEffectVtbl LinuxInputEffectVtbl;
 typedef struct LinuxInputEffectImpl LinuxInputEffectImpl;
 struct LinuxInputEffectImpl
 {
-    IDirectInputEffect  IDirectInputEffect_iface;
-    LONG                ref;
-    GUID                guid;
-
+    DWORD               type;
     struct ff_effect    effect; /* Effect data */
     int                 gain;   /* Effect gain */
     BOOL                first_axis_is_x;
     int*                fd;     /* Parent device */
-    struct list        *entry;  /* Entry into the parent's list of effects */
 };
 
-static inline LinuxInputEffectImpl *impl_from_IDirectInputEffect(IDirectInputEffect *iface)
+static inline LinuxInputEffectImpl *impl_from_unix_effect(struct unix_effect *ptr)
+{
+    return (LinuxInputEffectImpl *)ptr;
+}
+static inline struct unix_effect *unix_effect_from_impl(LinuxInputEffectImpl *This)
 {
-    return CONTAINING_RECORD(iface, LinuxInputEffectImpl, IDirectInputEffect_iface);
+    return (struct unix_effect *)This;
 }
 
 static double ff_effect_direction_to_rad(unsigned int dir)
@@ -163,19 +162,9 @@ static void ff_dump_effect(struct ff_effect *effect)
  *      LinuxInputEffectImpl 
  */
 
-static ULONG WINAPI LinuxInputEffectImpl_AddRef(
-	LPDIRECTINPUTEFFECT iface)
+static HRESULT CDECL unix_effect_download(struct unix_effect *ptr)
 {
-    LinuxInputEffectImpl *This = impl_from_IDirectInputEffect(iface);
-    ULONG ref = InterlockedIncrement(&This->ref);
-    TRACE( "(%p) ref %d\n", This, ref );
-    return ref;
-}
-
-static HRESULT WINAPI LinuxInputEffectImpl_Download(
-	LPDIRECTINPUTEFFECT iface)
-{
-    LinuxInputEffectImpl *This = impl_from_IDirectInputEffect(iface);
+    LinuxInputEffectImpl *This = impl_from_unix_effect(ptr);
     int ret, old_effect_id;
 
     TRACE("(this=%p)\n", This);
@@ -209,34 +198,17 @@ static HRESULT WINAPI LinuxInputEffectImpl_Download(
     return ret;
 }
 
-static HRESULT WINAPI LinuxInputEffectImpl_Escape(
-	LPDIRECTINPUTEFFECT iface,
-        LPDIEFFESCAPE pesc)
+static HRESULT CDECL unix_effect_escape(struct unix_effect *ptr, LPDIEFFESCAPE pesc)
 {
     WARN("(this=%p,%p): invalid: no hardware-specific escape codes in this" 
-         " driver!\n", iface, pesc);
-
-    return DI_OK;
-}
-
-static HRESULT WINAPI LinuxInputEffectImpl_GetEffectGuid(
-        LPDIRECTINPUTEFFECT iface,
-	LPGUID pguid)
-{
-    LinuxInputEffectImpl *This = impl_from_IDirectInputEffect(iface);
-
-    TRACE("(this=%p,%p)\n", This, pguid);
-
-    *pguid = This->guid;
+         " driver!\n", ptr, pesc);
 
     return DI_OK;
 }
 
-static HRESULT WINAPI LinuxInputEffectImpl_GetEffectStatus(
-        LPDIRECTINPUTEFFECT iface,
-	LPDWORD pdwFlags)
+static HRESULT CDECL unix_effect_get_status(struct unix_effect *ptr, LPDWORD pdwFlags)
 {
-    LinuxInputEffectImpl *This = impl_from_IDirectInputEffect(iface);
+    LinuxInputEffectImpl *This = impl_from_unix_effect(ptr);
 
     TRACE("(this=%p,%p)\n", This, pdwFlags);
 
@@ -256,13 +228,10 @@ static HRESULT WINAPI LinuxInputEffectImpl_GetEffectStatus(
     return DI_OK;
 }
 
-static HRESULT WINAPI LinuxInputEffectImpl_GetParameters(
-	LPDIRECTINPUTEFFECT iface,
-	LPDIEFFECT peff,
-	DWORD dwFlags)
+static HRESULT CDECL unix_effect_get_parameters(struct unix_effect *ptr, LPDIEFFECT peff, DWORD dwFlags)
 {
     HRESULT diErr = DI_OK;
-    LinuxInputEffectImpl *This = impl_from_IDirectInputEffect(iface);
+    LinuxInputEffectImpl *This = impl_from_unix_effect(ptr);
     TRACE("(this=%p,%p,%d)\n", This, peff, dwFlags);
 
     /* Major conversion factors are:
@@ -412,55 +381,19 @@ static HRESULT WINAPI LinuxInputEffectImpl_GetParameters(
     return diErr;
 }
 
-static HRESULT WINAPI LinuxInputEffectImpl_Initialize(
-        LPDIRECTINPUTEFFECT iface,
-	HINSTANCE hinst,
-	DWORD dwVersion,
-	REFGUID rguid)
-{
-    FIXME("(this=%p,%p,%d,%s): stub!\n",
-	 iface, hinst, dwVersion, debugstr_guid(rguid));
-
-    return DI_OK;
-}
-
-static HRESULT WINAPI LinuxInputEffectImpl_QueryInterface(
-	LPDIRECTINPUTEFFECT iface,
-	REFIID riid,
-	void **ppvObject)
-{
-    LinuxInputEffectImpl *This = impl_from_IDirectInputEffect(iface);
-
-    TRACE("(this=%p,%s,%p)\n", This, debugstr_guid(riid), ppvObject);
-
-    if (IsEqualGUID(&IID_IUnknown, riid) ||
-	IsEqualGUID(&IID_IDirectInputEffect, riid)) {
-	    LinuxInputEffectImpl_AddRef(iface);
-	    *ppvObject = This;
-	    return 0;
-    }
-
-    TRACE("Unsupported interface!\n");
-    return E_FAIL;
-}
-
-static HRESULT WINAPI LinuxInputEffectImpl_Start(
-	LPDIRECTINPUTEFFECT iface,
-	DWORD dwIterations,
-	DWORD dwFlags)
+static HRESULT CDECL unix_effect_start(struct unix_effect *ptr, DWORD dwIterations, DWORD dwFlags)
 {
     struct input_event event;
-    LinuxInputEffectImpl *This = impl_from_IDirectInputEffect(iface);
+    LinuxInputEffectImpl *This = impl_from_unix_effect(ptr);
 
     TRACE("(this=%p,%d,%d)\n", This, dwIterations, dwFlags);
 
     if (!(dwFlags & DIES_NODOWNLOAD)) {
 	/* Download the effect if necessary */
 	if (This->effect.id == -1) {
-	    HRESULT res = LinuxInputEffectImpl_Download(iface);
-	    if (res != DI_OK)
-		return res;
-	}
+            HRESULT res = unix_effect_download(ptr);
+            if (res != DI_OK) return res;
+        }
     }
 
     if (dwFlags & DIES_SOLO) {
@@ -478,19 +411,13 @@ static HRESULT WINAPI LinuxInputEffectImpl_Start(
     return DI_OK;
 }
 
-static HRESULT WINAPI LinuxInputEffectImpl_SetParameters(
-        LPDIRECTINPUTEFFECT iface,
-        LPCDIEFFECT peff,
-        DWORD dwFlags)
+static HRESULT CDECL unix_effect_set_parameters(struct unix_effect *ptr, LPCDIEFFECT peff, DWORD dwFlags)
 {
-    LinuxInputEffectImpl *This = impl_from_IDirectInputEffect(iface);
-    DWORD type = typeFromGUID(&This->guid);
+    LinuxInputEffectImpl *This = impl_from_unix_effect(ptr);
     HRESULT retval = DI_OK;
 
     TRACE("(this=%p,%p,%d)\n", This, peff, dwFlags);
 
-    dump_DIEFFECT(peff, &This->guid, dwFlags);
-
     if (!dwFlags)
         return DI_NOEFFECT;
 
@@ -633,7 +560,7 @@ static HRESULT WINAPI LinuxInputEffectImpl_SetParameters(
         if (!(peff->lpvTypeSpecificParams))
             return DIERR_INVALIDPARAM;
 
-        if (type == DIEFT_PERIODIC)
+        if (This->type == DIEFT_PERIODIC)
         {
             DIPERIODIC *tsp;
             if (peff->cbTypeSpecificParams != sizeof(DIPERIODIC))
@@ -650,14 +577,14 @@ static HRESULT WINAPI LinuxInputEffectImpl_SetParameters(
             else
                 This->effect.u.periodic.period = tsp->dwPeriod / 1000;
         }
-        else if (type == DIEFT_CONSTANTFORCE)
+        else if (This->type == DIEFT_CONSTANTFORCE)
         {
             LPCDICONSTANTFORCE tsp;
             if (peff->cbTypeSpecificParams != sizeof(DICONSTANTFORCE))
                 return DIERR_INVALIDPARAM;
             tsp = peff->lpvTypeSpecificParams;
 	    This->effect.u.constant.level = (max(min(tsp->lMagnitude, 10000), -10000) / 10) * 32;
-	} else if (type == DIEFT_RAMPFORCE) {
+	} else if (This->type == DIEFT_RAMPFORCE) {
             LPCDIRAMPFORCE tsp;
             if (peff->cbTypeSpecificParams != sizeof(DIRAMPFORCE))
                 return DIERR_INVALIDPARAM;
@@ -665,7 +592,7 @@ static HRESULT WINAPI LinuxInputEffectImpl_SetParameters(
 	    This->effect.u.ramp.start_level = (tsp->lStart / 10) * 32;
 	    This->effect.u.ramp.end_level = (tsp->lEnd / 10) * 32;
         }
-        else if (type == DIEFT_CONDITION)
+        else if (This->type == DIEFT_CONDITION)
         {
             DICONDITION *tsp = peff->lpvTypeSpecificParams;
             struct ff_condition_effect *cond = This->effect.u.condition;
@@ -709,27 +636,24 @@ static HRESULT WINAPI LinuxInputEffectImpl_SetParameters(
         }
     }
 
-    if (!(dwFlags & DIEP_NODOWNLOAD))
-	retval = LinuxInputEffectImpl_Download(iface);
+    if (!(dwFlags & DIEP_NODOWNLOAD)) retval = unix_effect_download(ptr);
     if (retval != DI_OK)
 	return DI_DOWNLOADSKIPPED;
 
     if (dwFlags & DIEP_NORESTART)
 	TRACE("DIEP_NORESTART: not handled (we have no control of that).\n");
 
-    if (dwFlags & DIEP_START)
-	retval = LinuxInputEffectImpl_Start(iface, 1, 0);
+    if (dwFlags & DIEP_START) retval = unix_effect_start(ptr, 1, 0);
     if (retval != DI_OK)
 	return retval;
  
     return DI_OK;
-}   
+}
 
-static HRESULT WINAPI LinuxInputEffectImpl_Stop(
-        LPDIRECTINPUTEFFECT iface)
+static HRESULT CDECL unix_effect_stop(struct unix_effect *ptr)
 {
     struct input_event event;
-    LinuxInputEffectImpl *This = impl_from_IDirectInputEffect(iface);
+    LinuxInputEffectImpl *This = impl_from_unix_effect(ptr);
 
     TRACE("(this=%p)\n", This);
 
@@ -742,10 +666,9 @@ static HRESULT WINAPI LinuxInputEffectImpl_Stop(
     return DI_OK;
 }
 
-static HRESULT WINAPI LinuxInputEffectImpl_Unload(
-	LPDIRECTINPUTEFFECT iface)
+static HRESULT CDECL unix_effect_unload(struct unix_effect *ptr)
 {
-    LinuxInputEffectImpl *This = impl_from_IDirectInputEffect(iface);
+    LinuxInputEffectImpl *This = impl_from_unix_effect(ptr);
     TRACE("(this=%p)\n", This);
 
     /* Erase the downloaded effect */
@@ -758,43 +681,56 @@ static HRESULT WINAPI LinuxInputEffectImpl_Unload(
     return DI_OK;
 }
 
-static ULONG WINAPI LinuxInputEffectImpl_Release(LPDIRECTINPUTEFFECT iface)
+static void CDECL unix_effect_destroy(struct unix_effect *ptr)
 {
-    LinuxInputEffectImpl *This = impl_from_IDirectInputEffect(iface);
-    ULONG ref = InterlockedDecrement(&(This->ref));
-
-    TRACE( "(%p) ref %d\n", This, ref );
-
-    if (ref == 0)
-    {
-        LinuxInputEffectImpl_Stop(iface);
-        LinuxInputEffectImpl_Unload(iface);
-        list_remove(This->entry);
-        HeapFree(GetProcessHeap(), 0, LIST_ENTRY(This->entry, effect_list_item, entry));
-        HeapFree(GetProcessHeap(), 0, This);
-    }
-    return ref;
+    unix_effect_stop(ptr);
+    unix_effect_unload(ptr);
+    HeapFree(GetProcessHeap(), 0, ptr);
 }
 
+static const struct unix_effect_vtbl unix_effect_vtbl =
+{
+    unix_effect_get_parameters,
+    unix_effect_set_parameters,
+    unix_effect_start,
+    unix_effect_stop,
+    unix_effect_get_status,
+    unix_effect_download,
+    unix_effect_unload,
+    unix_effect_escape,
+    unix_effect_destroy,
+};
+
 /******************************************************************************
  *      LinuxInputEffect
  */
 
-DECLSPEC_HIDDEN HRESULT linuxinput_create_effect(
-	int* fd,
-	REFGUID rguid,
-        struct list *parent_list_entry,
-	LPDIRECTINPUTEFFECT* peff)
+DECLSPEC_HIDDEN HRESULT linuxinput_create_effect(int *fd, REFGUID rguid, DWORD type, const DIEFFECT *effect, const struct unix_effect_vtbl **vtbl, struct unix_effect **out)
 {
-    LinuxInputEffectImpl* newEffect = HeapAlloc(GetProcessHeap(), 
-	HEAP_ZERO_MEMORY, sizeof(LinuxInputEffectImpl));
-    DWORD type = typeFromGUID(rguid);
+    LinuxInputEffectImpl *newEffect;
+    HRESULT hr;
+
+    switch (type)
+    {
+    case DIEFT_PERIODIC:
+    case DIEFT_CONSTANTFORCE:
+    case DIEFT_RAMPFORCE:
+    case DIEFT_CONDITION:
+        break;
+    case DIEFT_CUSTOMFORCE:
+        FIXME("Custom forces are not supported.\n");
+        return DIERR_INVALIDPARAM;
+    default:
+        FIXME("Unknown force type 0x%x.\n", type);
+        return DIERR_INVALIDPARAM;
+    }
+
+    if (!(newEffect = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*newEffect))))
+        return DIERR_OUTOFMEMORY;
 
-    newEffect->IDirectInputEffect_iface.lpVtbl = &LinuxInputEffectVtbl;
-    newEffect->ref = 1;
-    newEffect->guid = *rguid;
     newEffect->fd = fd;
     newEffect->gain = 0xFFFF;
+    newEffect->type = type;
 
     /* set the type.  this cannot be changed over the effect's life. */
     switch (type) {
@@ -829,26 +765,27 @@ DECLSPEC_HIDDEN HRESULT linuxinput_create_effect(
 		newEffect->effect.type = FF_DAMPER;
 	    }
 	    break;
-	case DIEFT_CUSTOMFORCE:
-	    FIXME("Custom forces are not supported.\n");
-	    HeapFree(GetProcessHeap(), 0, newEffect);
-	    return DIERR_INVALIDPARAM;
 	default:
-            FIXME("Unknown force type 0x%x.\n", type);
-            HeapFree(GetProcessHeap(), 0, newEffect);
-	    return DIERR_INVALIDPARAM;
+            break;
     }
 
     /* mark as non-uploaded */
     newEffect->effect.id = -1;
 
-    newEffect->entry = parent_list_entry;
-
-    *peff = &newEffect->IDirectInputEffect_iface;
+    hr = unix_effect_set_parameters(unix_effect_from_impl(newEffect), effect,
+            DIEP_AXES | DIEP_DIRECTION | DIEP_DURATION | DIEP_ENVELOPE | DIEP_GAIN | DIEP_SAMPLEPERIOD |
+            DIEP_STARTDELAY | DIEP_TRIGGERBUTTON | DIEP_TRIGGERREPEATINTERVAL | DIEP_TYPESPECIFICPARAMS);
+    if (hr != DI_OK && hr != DI_DOWNLOADSKIPPED)
+    {
+        HeapFree(GetProcessHeap(), 0, newEffect);
+        return hr;
+    }
 
     TRACE("Creating linux input system effect (%p) with guid %s\n", 
-	  *peff, _dump_dinput_GUID(rguid));
+	  newEffect, _dump_dinput_GUID(rguid));
 
+    *vtbl = &unix_effect_vtbl;
+    *out = unix_effect_from_impl(newEffect);
     return DI_OK;
 }
 
@@ -886,20 +823,4 @@ DECLSPEC_HIDDEN HRESULT linuxinput_get_info_A(
     return DI_OK;
 }
 
-static const IDirectInputEffectVtbl LinuxInputEffectVtbl = {
-    LinuxInputEffectImpl_QueryInterface,
-    LinuxInputEffectImpl_AddRef,
-    LinuxInputEffectImpl_Release,
-    LinuxInputEffectImpl_Initialize,
-    LinuxInputEffectImpl_GetEffectGuid,
-    LinuxInputEffectImpl_GetParameters,
-    LinuxInputEffectImpl_SetParameters,
-    LinuxInputEffectImpl_Start,
-    LinuxInputEffectImpl_Stop,
-    LinuxInputEffectImpl_GetEffectStatus,
-    LinuxInputEffectImpl_Download,
-    LinuxInputEffectImpl_Unload,
-    LinuxInputEffectImpl_Escape
-};
-
 #endif /* HAVE_STRUCT_FF_EFFECT_DIRECTION */
diff --git a/dlls/dinput/joystick.c b/dlls/dinput/joystick.c
index f226fa944e7..6768ff5b1be 100644
--- a/dlls/dinput/joystick.c
+++ b/dlls/dinput/joystick.c
@@ -61,6 +61,167 @@ const GUID DInput_PIDVID_Product_GUID = { /* device_pidvid-0000-0000-0000-504944
     0x00000000, 0x0000, 0x0000, {0x00, 0x00, 0x50, 0x49, 0x44, 0x56, 0x49, 0x44}
 };
 
+static void dump_DIEFFECT(LPCDIEFFECT eff, REFGUID guid, DWORD dwFlags);
+
+struct dinput_unix_effect
+{
+    IDirectInputEffect IDirectInputEffect_iface;
+    LONG ref;
+    GUID guid;
+    const struct unix_effect_vtbl *unix_funcs;
+    struct unix_effect *unix_ptr;
+    struct list entry;
+};
+
+static inline struct dinput_unix_effect *impl_from_IDirectInputEffect(IDirectInputEffect *iface)
+{
+    return CONTAINING_RECORD(iface, struct dinput_unix_effect, IDirectInputEffect_iface);
+}
+
+static inline IDirectInputEffect *IDirectInputEffect_from_impl(struct dinput_unix_effect *This)
+{
+    return &This->IDirectInputEffect_iface;
+}
+
+static HRESULT STDMETHODCALLTYPE dinput_unix_effect_QueryInterface(IDirectInputEffect *iface, REFIID iid, void **out)
+{
+    struct dinput_unix_effect *This = impl_from_IDirectInputEffect(iface);
+    TRACE("iface %p, iid %s, out %p.\n", iface, debugstr_guid(iid), out);
+
+    if (IsEqualGUID(&IID_IUnknown, iid) || IsEqualGUID(&IID_IDirectInputEffect, iid))
+    {
+        IDirectInputEffect_AddRef(iface);
+        *out = This;
+        return 0;
+    }
+
+    FIXME("Unsupported interface %s!\n", debugstr_guid(iid));
+    return E_FAIL;
+}
+
+static ULONG STDMETHODCALLTYPE dinput_unix_effect_AddRef(IDirectInputEffect *iface)
+{
+    struct dinput_unix_effect *This = impl_from_IDirectInputEffect(iface);
+    ULONG ref = InterlockedIncrement(&This->ref);
+    TRACE("iface %p -> ref %d.\n", iface, ref);
+    return ref;
+}
+
+static ULONG STDMETHODCALLTYPE dinput_unix_effect_Release(IDirectInputEffect *iface)
+{
+    struct dinput_unix_effect *This = impl_from_IDirectInputEffect(iface);
+    ULONG ref = InterlockedDecrement(&(This->ref));
+    TRACE("iface %p -> ref %d\n", iface, ref);
+    if (ref) return ref;
+    This->unix_funcs->destroy(This->unix_ptr);
+    list_remove(&This->entry);
+    HeapFree(GetProcessHeap(), 0, This);
+    return 0;
+}
+
+static HRESULT STDMETHODCALLTYPE dinput_unix_effect_Initialize(IDirectInputEffect *iface, HINSTANCE instance, DWORD version, REFGUID guid)
+{
+    TRACE("iface %p, instance %p, version %#x, guid %s, stub!\n", iface, instance, version, debugstr_guid(guid));
+    return DI_OK;
+}
+
+static HRESULT STDMETHODCALLTYPE dinput_unix_effect_GetEffectGuid(IDirectInputEffect *iface, GUID *guid)
+{
+    struct dinput_unix_effect *This = impl_from_IDirectInputEffect(iface);
+    TRACE("iface %p, guid %p.\n", iface, guid);
+    *guid = This->guid;
+    return DI_OK;
+}
+
+static HRESULT STDMETHODCALLTYPE dinput_unix_effect_GetParameters(IDirectInputEffect *iface, DIEFFECT *effect, DWORD flags)
+{
+    struct dinput_unix_effect *This = impl_from_IDirectInputEffect(iface);
+    TRACE("iface %p, effect %p, flags %#x.\n", iface, effect, flags);
+    return This->unix_funcs->get_parameters(This->unix_ptr, effect, flags);
+}
+
+static HRESULT STDMETHODCALLTYPE dinput_unix_effect_SetParameters(IDirectInputEffect *iface, const DIEFFECT *effect, DWORD flags)
+{
+    struct dinput_unix_effect *This = impl_from_IDirectInputEffect(iface);
+    TRACE("iface %p, effect %p, flags %#x.\n", iface, effect, flags);
+    dump_DIEFFECT(effect, &This->guid, flags);
+    return This->unix_funcs->set_parameters(This->unix_ptr, effect, flags);
+}
+
+static HRESULT STDMETHODCALLTYPE dinput_unix_effect_Start(IDirectInputEffect *iface, DWORD iterations, DWORD flags)
+{
+    struct dinput_unix_effect *This = impl_from_IDirectInputEffect(iface);
+    TRACE("iface %p, iterations %u, flags %#x.\n", iface, iterations, flags);
+    return This->unix_funcs->start(This->unix_ptr, iterations, flags);
+}
+
+static HRESULT STDMETHODCALLTYPE dinput_unix_effect_Stop(IDirectInputEffect *iface)
+{
+    struct dinput_unix_effect *This = impl_from_IDirectInputEffect(iface);
+    TRACE("iface %p.\n", iface);
+    return This->unix_funcs->stop(This->unix_ptr);
+}
+
+static HRESULT STDMETHODCALLTYPE dinput_unix_effect_GetEffectStatus(IDirectInputEffect *iface, DWORD *flags)
+{
+    struct dinput_unix_effect *This = impl_from_IDirectInputEffect(iface);
+    TRACE("iface %p, flags %p.\n", iface, flags);
+    return This->unix_funcs->get_status(This->unix_ptr, flags);
+}
+
+static HRESULT STDMETHODCALLTYPE dinput_unix_effect_Download(IDirectInputEffect *iface)
+{
+    struct dinput_unix_effect *This = impl_from_IDirectInputEffect(iface);
+    TRACE("iface %p.\n", iface);
+    return This->unix_funcs->download(This->unix_ptr);
+}
+
+static HRESULT STDMETHODCALLTYPE dinput_unix_effect_Unload(IDirectInputEffect *iface)
+{
+    struct dinput_unix_effect *This = impl_from_IDirectInputEffect(iface);
+    TRACE("iface %p.\n", iface);
+    return This->unix_funcs->unload(This->unix_ptr);
+}
+
+static HRESULT STDMETHODCALLTYPE dinput_unix_effect_Escape(IDirectInputEffect *iface, DIEFFESCAPE *escape)
+{
+    struct dinput_unix_effect *This = impl_from_IDirectInputEffect(iface);
+    TRACE("iface %p, escape %p.\n", iface, escape);
+    return This->unix_funcs->escape(This->unix_ptr, escape);
+}
+
+static const IDirectInputEffectVtbl dinput_unix_effect_vtbl =
+{
+    /*** IUnknown methods ***/
+    dinput_unix_effect_QueryInterface,
+    dinput_unix_effect_AddRef,
+    dinput_unix_effect_Release,
+    /*** IDirectInputEffect methods ***/
+    dinput_unix_effect_Initialize,
+    dinput_unix_effect_GetEffectGuid,
+    dinput_unix_effect_GetParameters,
+    dinput_unix_effect_SetParameters,
+    dinput_unix_effect_Start,
+    dinput_unix_effect_Stop,
+    dinput_unix_effect_GetEffectStatus,
+    dinput_unix_effect_Download,
+    dinput_unix_effect_Unload,
+    dinput_unix_effect_Escape,
+};
+
+static HRESULT CDECL dinput_unix_effect_alloc(const struct unix_effect_vtbl *unix_funcs, struct unix_effect *unix_ptr, const GUID *guid, IDirectInputEffect **out)
+{
+    struct dinput_unix_effect *This;
+    if (!(This = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*This)))) return DIERR_OUTOFMEMORY;
+    This->IDirectInputEffect_iface.lpVtbl = &dinput_unix_effect_vtbl;
+    This->ref = 1;
+    This->guid = *guid;
+    This->unix_funcs = unix_funcs;
+    This->unix_ptr = unix_ptr;
+    *out = &This->IDirectInputEffect_iface;
+    return DI_OK;
+}
+
 static inline JoystickGenericImpl *impl_from_IDirectInputDevice8W(IDirectInputDevice8W *iface)
 {
     return CONTAINING_RECORD(CONTAINING_RECORD(iface, IDirectInputDeviceImpl, IDirectInputDevice8W_iface), JoystickGenericImpl, base);
@@ -178,7 +339,7 @@ static void _dump_DICUSTOMFORCE(LPCDICUSTOMFORCE frc)
     }
 }
 
-void dump_DIEFFECT(LPCDIEFFECT eff, REFGUID guid, DWORD dwFlags)
+static void dump_DIEFFECT(LPCDIEFFECT eff, REFGUID guid, DWORD dwFlags)
 {
     DWORD type = typeFromGUID(guid);
     unsigned int i;
@@ -799,7 +960,9 @@ HRESULT WINAPI JoystickWGenericImpl_CreateEffect(LPDIRECTINPUTDEVICE8W iface, RE
         LPDIRECTINPUTEFFECT *ppdef, LPUNKNOWN pUnkOuter)
 {
     JoystickGenericImpl *This = impl_from_IDirectInputDevice8W(iface);
-    effect_list_item *item = NULL;
+    struct dinput_unix_effect *unix_effect;
+    const struct unix_effect_vtbl *unix_vtbl;
+    struct unix_effect *unix_ptr = NULL;
     HRESULT hr;
 
     TRACE("(this=%p,%p,%p,%p,%p)\n", This, rguid, lpeff, ppdef, pUnkOuter);
@@ -807,15 +970,18 @@ HRESULT WINAPI JoystickWGenericImpl_CreateEffect(LPDIRECTINPUTDEVICE8W iface, RE
     if (!ppdef) return E_POINTER;
     *ppdef = NULL;
 
+    dump_DIEFFECT(lpeff, rguid, 0);
+
     if (!This->unix_funcs->create_effect) return DIERR_UNSUPPORTED;
-    if (!(item = HeapAlloc(GetProcessHeap(), 0, sizeof(*item)))) return DIERR_OUTOFMEMORY;
-    if (FAILED(hr = This->unix_funcs->create_effect(This->unix_ptr, rguid, lpeff, &item->entry, &item->ref)))
+    if (FAILED(hr = This->unix_funcs->create_effect(This->unix_ptr, rguid, typeFromGUID(rguid), lpeff, &unix_vtbl, &unix_ptr)) ||
+        FAILED(hr = dinput_unix_effect_alloc(unix_vtbl, unix_ptr, rguid, ppdef)))
     {
-        HeapFree(GetProcessHeap(), 0, item);
+        if (*ppdef) IDirectInputEffect_Release(*ppdef);
+        else if (unix_ptr) unix_vtbl->destroy(unix_ptr);
         return hr;
     }
-    list_add_tail(&This->ff_effects, &item->entry);
-    *ppdef = item->ref;
+    unix_effect = impl_from_IDirectInputEffect(*ppdef);
+    list_add_tail(&This->ff_effects, &unix_effect->entry);
     if (pUnkOuter != NULL) FIXME("Interface aggregation not implemented.\n");
     return DI_OK;
 }
@@ -824,14 +990,14 @@ HRESULT WINAPI JoystickWGenericImpl_EnumCreatedEffectObjects(LPDIRECTINPUTDEVICE
         LPDIENUMCREATEDEFFECTOBJECTSCALLBACK lpCallback, LPVOID pvRef, DWORD dwFlags)
 {
     JoystickGenericImpl *This = impl_from_IDirectInputDevice8W(iface);
-    effect_list_item *itr, *ptr;
+    struct dinput_unix_effect *itr, *ptr;
 
     TRACE("(this=%p,%p,%p,%d)\n", This, lpCallback, pvRef, dwFlags);
 
     if (!lpCallback) return DIERR_INVALIDPARAM;
     if (dwFlags != 0) FIXME("Flags specified, but no flags exist yet (DX9)!\n");
-    LIST_FOR_EACH_ENTRY_SAFE(itr, ptr, &This->ff_effects, effect_list_item, entry)
-        (*lpCallback)(itr->ref, pvRef);
+    LIST_FOR_EACH_ENTRY_SAFE(itr, ptr, &This->ff_effects, struct dinput_unix_effect, entry)
+        (*lpCallback)(IDirectInputEffect_from_impl(itr), pvRef);
     return DI_OK;
 }
 
@@ -848,7 +1014,7 @@ HRESULT WINAPI JoystickWGenericImpl_GetForceFeedbackState(LPDIRECTINPUTDEVICE8W
 HRESULT WINAPI JoystickWGenericImpl_SendForceFeedbackCommand(LPDIRECTINPUTDEVICE8W iface, DWORD dwFlags)
 {
     JoystickGenericImpl *This = impl_from_IDirectInputDevice8W(iface);
-    effect_list_item *itr;
+    struct dinput_unix_effect *itr;
 
     TRACE("(this=%p,%d)\n", This, dwFlags);
 
@@ -857,14 +1023,14 @@ HRESULT WINAPI JoystickWGenericImpl_SendForceFeedbackCommand(LPDIRECTINPUTDEVICE
     switch (dwFlags)
     {
     case DISFFC_STOPALL:
-        LIST_FOR_EACH_ENTRY(itr, &This->ff_effects, effect_list_item, entry)
-            IDirectInputEffect_Stop(itr->ref);
+        LIST_FOR_EACH_ENTRY(itr, &This->ff_effects, struct dinput_unix_effect, entry)
+            IDirectInputEffect_Stop(IDirectInputEffect_from_impl(itr));
         break;
     case DISFFC_RESET:
-        LIST_FOR_EACH_ENTRY(itr, &This->ff_effects, effect_list_item, entry)
+        LIST_FOR_EACH_ENTRY(itr, &This->ff_effects, struct dinput_unix_effect, entry)
         {
-            IDirectInputEffect_Stop(itr->ref);
-            IDirectInputEffect_Unload(itr->ref);
+            IDirectInputEffect_Stop(IDirectInputEffect_from_impl(itr));
+            IDirectInputEffect_Unload(IDirectInputEffect_from_impl(itr));
         }
         break;
     default:
@@ -1204,6 +1370,8 @@ HRESULT dinput_create_unix_joystick(const struct dinput_device *device, IDirectI
 
     if (FAILED(hr = device->create_unix_joystick(dinput, guid, &This)))
         return hr;
+    list_init(&This->ff_effects);
+
     if (This->unix_funcs->get_mapping)
     {
         This->unix_funcs->get_mapping(This->unix_ptr, &default_axis_count, &default_axes_map);
diff --git a/dlls/dinput/joystick_linuxinput.c b/dlls/dinput/joystick_linuxinput.c
index f9fbffc0c0c..8ed22d5bcfc 100644
--- a/dlls/dinput/joystick_linuxinput.c
+++ b/dlls/dinput/joystick_linuxinput.c
@@ -87,7 +87,7 @@ struct wine_input_absinfo {
 };
 
 /* implemented in effect_linuxinput.c */
-HRESULT linuxinput_create_effect(int* fd, REFGUID rguid, struct list *parent_list_entry, LPDIRECTINPUTEFFECT* peff);
+HRESULT linuxinput_create_effect(int *fd, REFGUID rguid, DWORD type, const DIEFFECT *effect, const struct unix_effect_vtbl **vtbl, struct unix_effect **out);
 HRESULT linuxinput_get_info_A(int fd, REFGUID rguid, LPDIEFFECTINFOA info);
 
 typedef struct JoystickImpl JoystickImpl;
@@ -161,8 +161,8 @@ static HRESULT CDECL unix_joystick_ff_send_cmd(struct unix_joystick *ptr, DWORD
 
 static HRESULT CDECL unix_joystick_list_effects(struct unix_joystick *ptr, DWORD type, const GUID **guids, DWORD size, DWORD *count);
 static HRESULT CDECL unix_joystick_get_effect_info(struct unix_joystick *ptr, REFGUID guid, LPDIEFFECTINFOA diei);
-static HRESULT CDECL unix_joystick_create_effect(struct unix_joystick *ptr, REFGUID guid, const DIEFFECT *effect,
-        struct list *entry, IDirectInputEffect **out);
+static HRESULT CDECL unix_joystick_create_effect(struct unix_joystick *ptr, REFGUID guid, DWORD type, const DIEFFECT *effect,
+        const struct unix_effect_vtbl **vtbl, struct unix_effect **out);
 
 static HRESULT CDECL unix_joystick_init(struct unix_joystick *ptr, ObjProps *props, int *prop_count, BOOL *has_ff);
 static void CDECL unix_joystick_reset(struct unix_joystick *ptr);
@@ -557,7 +557,6 @@ static HRESULT CDECL unix_joystick_init(struct unix_joystick *ptr, ObjProps *pro
     JoystickImpl *This = impl_from_unix_joystick(ptr);
     int i, idx = 0, wine_obj;
 
-    list_init(&This->generic.ff_effects);
 #ifdef HAVE_STRUCT_FF_EFFECT_DIRECTION
     This->ff_state = FF_STATUS_STOPPED;
 #endif
@@ -820,34 +819,22 @@ static void CDECL unix_joystick_poll(struct unix_joystick *ptr)
 /****************************************************************************** 
   *	CreateEffect - Create a new FF effect with the specified params
   */
-static HRESULT CDECL unix_joystick_create_effect(struct unix_joystick *ptr, REFGUID guid, const DIEFFECT *effect,
-        struct list *entry, IDirectInputEffect **out)
+static HRESULT CDECL unix_joystick_create_effect(struct unix_joystick *ptr, REFGUID guid, DWORD type, const DIEFFECT *effect,
+        const struct unix_effect_vtbl **vtbl, struct unix_effect **out)
 {
     HRESULT retval = DI_OK;
     JoystickImpl* This = impl_from_unix_joystick(ptr);
-    TRACE("(this=%p,%p,%p,%p,%p)\n", This, guid, effect, entry, out);
+    TRACE("(this=%p,%p,%p,%p)\n", This, guid, effect, out);
 
-    *out = NULL;
     if (!This->joydev->has_ff)
     {
         TRACE("No force feedback support\n");
         return DIERR_UNSUPPORTED;
     }
 
-    retval = linuxinput_create_effect(&This->joyfd, guid, entry, out);
+    retval = linuxinput_create_effect(&This->joyfd, guid, type, effect, vtbl, out);
     if (retval != DI_OK) return retval;
 
-    if (effect != NULL)
-    {
-        retval = IDirectInputEffect_SetParameters(*out, effect,
-            DIEP_AXES | DIEP_DIRECTION | DIEP_DURATION | DIEP_ENVELOPE |
-            DIEP_GAIN | DIEP_SAMPLEPERIOD | DIEP_STARTDELAY | DIEP_TRIGGERBUTTON |
-            DIEP_TRIGGERREPEATINTERVAL | DIEP_TYPESPECIFICPARAMS);
-
-        if (retval != DI_OK && retval != DI_DOWNLOADSKIPPED)
-            return retval;
-    }
-
     return DI_OK;
 }
 
diff --git a/dlls/dinput/joystick_osx.c b/dlls/dinput/joystick_osx.c
index 5aebf2d570b..6fad4d3fe52 100644
--- a/dlls/dinput/joystick_osx.c
+++ b/dlls/dinput/joystick_osx.c
@@ -124,22 +124,18 @@ static inline JoystickImpl *impl_from_unix_joystick(struct unix_joystick *ptr)
 }
 
 typedef struct _EffectImpl {
-    IDirectInputEffect IDirectInputEffect_iface;
-    LONG ref;
-
     JoystickImpl *device;
     FFEffectObjectReference effect;
-    GUID guid;
-
-    struct list entry;
 } EffectImpl;
 
-static EffectImpl *impl_from_IDirectInputEffect(IDirectInputEffect *iface)
+static inline EffectImpl *impl_from_unix_effect(struct unix_effect *ptr)
 {
-    return CONTAINING_RECORD(iface, EffectImpl, IDirectInputEffect_iface);
+    return (EffectImpl *)ptr;
+}
+static inline struct unix_effect *unix_effect_from_impl(EffectImpl *This)
+{
+    return (struct unix_effect *)This;
 }
-
-static const IDirectInputEffectVtbl EffectVtbl;
 
 static const GUID DInput_Wine_OsX_Joystick_GUID = { /* 59CAD8F6-E617-41E2-8EB7-47B23EEEDC5A */
   0x59CAD8F6, 0xE617, 0x41E2, {0x8E, 0xB7, 0x47, 0xB2, 0x3E, 0xEE, 0xDC, 0x5A}
@@ -938,8 +934,8 @@ static HRESULT CDECL unix_joystick_ff_set_autocenter(struct unix_joystick *ptr,
 static HRESULT CDECL unix_joystick_ff_set_gain(struct unix_joystick *ptr, DWORD value);
 static HRESULT CDECL unix_joystick_ff_send_cmd(struct unix_joystick *ptr, DWORD flags);
 
-static HRESULT CDECL unix_joystick_create_effect(struct unix_joystick *ptr, REFGUID guid, const DIEFFECT *params,
-        struct list *entry, IDirectInputEffect **out);
+static HRESULT CDECL unix_joystick_create_effect(struct unix_joystick *ptr, REFGUID guid, DWORD type, const DIEFFECT *params,
+        const struct unix_effect_vtbl **vtbl, struct unix_effect **out);
 
 static HRESULT CDECL unix_joystick_init(struct unix_joystick *ptr, ObjProps *props, int *prop_count, BOOL *has_ff);
 
@@ -960,6 +956,29 @@ static const struct unix_joystick_vtbl unix_joystick_vtbl =
     unix_joystick_poll,
 };
 
+static HRESULT CDECL unix_effect_get_parameters(struct unix_effect *ptr, DIEFFECT *effect, DWORD flags);
+static HRESULT CDECL unix_effect_set_parameters(struct unix_effect *ptr, const DIEFFECT *effect, DWORD flags);
+static HRESULT CDECL unix_effect_start(struct unix_effect *ptr, DWORD iterations, DWORD flags);
+static HRESULT CDECL unix_effect_stop(struct unix_effect *ptr);
+static HRESULT CDECL unix_effect_get_status(struct unix_effect *ptr, DWORD *flags);
+static HRESULT CDECL unix_effect_download(struct unix_effect *ptr);
+static HRESULT CDECL unix_effect_unload(struct unix_effect *ptr);
+static HRESULT CDECL unix_effect_escape(struct unix_effect *ptr, DIEFFESCAPE *escape);
+static void CDECL unix_effect_destroy(struct unix_effect *ptr);
+
+static const struct unix_effect_vtbl unix_effect_vtbl =
+{
+    unix_effect_get_parameters,
+    unix_effect_set_parameters,
+    unix_effect_start,
+    unix_effect_stop,
+    unix_effect_get_status,
+    unix_effect_download,
+    unix_effect_unload,
+    unix_effect_escape,
+    unix_effect_destroy,
+};
+
 static INT find_joystick_devices(void)
 {
     static INT joystick_devices_count = -1;
@@ -1146,7 +1165,6 @@ static HRESULT CDECL unix_joystick_init(struct unix_joystick *ptr, ObjProps *pro
     get_osx_device_name(This->id, name, MAX_PATH);
     TRACE("Name %s\n",name);
 
-    list_init(&This->generic.ff_effects);
     if (get_ff(device, &This->ff) == S_OK)
     {
         *has_ff = TRUE;
@@ -1236,26 +1254,21 @@ static CFUUIDRef effect_win_to_mac(const GUID *effect)
     return 0;
 }
 
-static HRESULT CDECL unix_joystick_create_effect(struct unix_joystick *ptr, REFGUID guid, const DIEFFECT *params,
-        struct list *entry, IDirectInputEffect **out)
+static HRESULT CDECL unix_joystick_create_effect(struct unix_joystick *ptr, REFGUID guid, DWORD type, const DIEFFECT *params,
+        const struct unix_effect_vtbl **vtbl, struct unix_effect **out)
 {
     JoystickImpl *This = impl_from_unix_joystick(ptr);
     EffectImpl *effect;
     HRESULT hr;
 
-    TRACE("(%p)->(%s %p %p %p)\n", This, debugstr_guid(guid), params, entry, out);
-    dump_DIEFFECT(params, guid, 0);
+    TRACE("(%p)->(%s %p %p)\n", This, debugstr_guid(guid), params, out);
 
     if(!This->ff){
         TRACE("No force feedback support\n");
-        *out = NULL;
         return DIERR_UNSUPPORTED;
     }
 
-    effect = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*This));
-    effect->IDirectInputEffect_iface.lpVtbl = &EffectVtbl;
-    effect->ref = 1;
-    effect->guid = *guid;
+    if (!(effect = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*effect)))) return DIERR_OUTOFMEMORY;
     effect->device = This;
 
     /* Mac's FFEFFECT and Win's DIEFFECT are binary identical. */
@@ -1267,10 +1280,10 @@ static HRESULT CDECL unix_joystick_create_effect(struct unix_joystick *ptr, REFG
         return hr;
     }
 
-    *out = &effect->IDirectInputEffect_iface;
-
     TRACE("allocated effect: %p\n", effect);
 
+    *vtbl = &unix_effect_vtbl;
+    *out = unix_effect_from_impl(effect);
     return S_OK;
 }
 
@@ -1337,137 +1350,69 @@ static const IDirectInputDevice8WVtbl JoystickWvt =
     IDirectInputDevice8WImpl_GetImageInfo
 };
 
-static HRESULT WINAPI effect_QueryInterface(IDirectInputEffect *iface,
-        const GUID *guid, void **out)
-{
-    EffectImpl *This = impl_from_IDirectInputEffect(iface);
-
-    TRACE("%p %s %p\n", This, debugstr_guid(guid), out);
-
-    if(IsEqualIID(guid, &IID_IUnknown) || IsEqualIID(guid, &IID_IDirectInputEffect)){
-        *out = iface;
-        IDirectInputEffect_AddRef(iface);
-        return S_OK;
-    }
-
-    return E_NOINTERFACE;
-}
-
-static ULONG WINAPI effect_AddRef(IDirectInputEffect *iface)
-{
-    EffectImpl *This = impl_from_IDirectInputEffect(iface);
-    ULONG ref = InterlockedIncrement(&This->ref);
-    TRACE("%p, ref is now: %u\n", This, ref);
-    return ref;
-}
-
-static ULONG WINAPI effect_Release(IDirectInputEffect *iface)
-{
-    EffectImpl *This = impl_from_IDirectInputEffect(iface);
-    ULONG ref = InterlockedDecrement(&This->ref);
-    TRACE("%p, ref is now: %u\n", This, ref);
-
-    if(!ref){
-        list_remove(&This->entry);
-        FFDeviceReleaseEffect(This->device->ff, This->effect);
-        HeapFree(GetProcessHeap(), 0, This);
-    }
-
-    return ref;
-}
-
-static HRESULT WINAPI effect_Initialize(IDirectInputEffect *iface, HINSTANCE hinst,
-        DWORD version, const GUID *guid)
-{
-    EffectImpl *This = impl_from_IDirectInputEffect(iface);
-    TRACE("%p %p 0x%x, %s\n", This, hinst, version, debugstr_guid(guid));
-    return S_OK;
-}
-
-static HRESULT WINAPI effect_GetEffectGuid(IDirectInputEffect *iface, GUID *out)
+static void CDECL unix_effect_destroy(struct unix_effect *ptr)
 {
-    EffectImpl *This = impl_from_IDirectInputEffect(iface);
-    TRACE("%p %p\n", This, out);
-    *out = This->guid;
-    return S_OK;
+    EffectImpl *This = impl_from_unix_effect(ptr);
+    FFDeviceReleaseEffect(This->device->ff, This->effect);
+    HeapFree(GetProcessHeap(), 0, This);
 }
 
-static HRESULT WINAPI effect_GetParameters(IDirectInputEffect *iface,
-        DIEFFECT *effect, DWORD flags)
+static HRESULT CDECL unix_effect_get_parameters(struct unix_effect *ptr, DIEFFECT *effect, DWORD flags)
 {
-    EffectImpl *This = impl_from_IDirectInputEffect(iface);
+    EffectImpl *This = impl_from_unix_effect(ptr);
     TRACE("%p %p 0x%x\n", This, effect, flags);
     return osx_to_win32_hresult(FFEffectGetParameters(This->effect, (FFEFFECT*)effect, flags));
 }
 
-static HRESULT WINAPI effect_SetParameters(IDirectInputEffect *iface,
-        const DIEFFECT *effect, DWORD flags)
+static HRESULT CDECL unix_effect_set_parameters(struct unix_effect *ptr, const DIEFFECT *effect, DWORD flags)
 {
-    EffectImpl *This = impl_from_IDirectInputEffect(iface);
+    EffectImpl *This = impl_from_unix_effect(ptr);
     TRACE("%p %p 0x%x\n", This, effect, flags);
-    dump_DIEFFECT(effect, &This->guid, flags);
     return osx_to_win32_hresult(FFEffectSetParameters(This->effect, (FFEFFECT*)effect, flags));
 }
 
-static HRESULT WINAPI effect_Start(IDirectInputEffect *iface, DWORD iterations,
-        DWORD flags)
+static HRESULT CDECL unix_effect_start(struct unix_effect *ptr, DWORD iterations, DWORD flags)
 {
-    EffectImpl *This = impl_from_IDirectInputEffect(iface);
+    EffectImpl *This = impl_from_unix_effect(ptr);
     TRACE("%p 0x%x 0x%x\n", This, iterations, flags);
     return osx_to_win32_hresult(FFEffectStart(This->effect, iterations, flags));
 }
 
-static HRESULT WINAPI effect_Stop(IDirectInputEffect *iface)
+static HRESULT CDECL unix_effect_stop(struct unix_effect *ptr)
 {
-    EffectImpl *This = impl_from_IDirectInputEffect(iface);
+    EffectImpl *This = impl_from_unix_effect(ptr);
     TRACE("%p\n", This);
     return osx_to_win32_hresult(FFEffectStop(This->effect));
 }
 
-static HRESULT WINAPI effect_GetEffectStatus(IDirectInputEffect *iface, DWORD *flags)
+static HRESULT CDECL unix_effect_get_status(struct unix_effect *ptr, DWORD *flags)
 {
-    EffectImpl *This = impl_from_IDirectInputEffect(iface);
+    EffectImpl *This = impl_from_unix_effect(ptr);
     TRACE("%p %p\n", This, flags);
     return osx_to_win32_hresult(FFEffectGetEffectStatus(This->effect, (UInt32*)flags));
 }
 
-static HRESULT WINAPI effect_Download(IDirectInputEffect *iface)
+static HRESULT CDECL unix_effect_download(struct unix_effect *ptr)
 {
-    EffectImpl *This = impl_from_IDirectInputEffect(iface);
+    EffectImpl *This = impl_from_unix_effect(ptr);
     TRACE("%p\n", This);
     return osx_to_win32_hresult(FFEffectDownload(This->effect));
 }
 
-static HRESULT WINAPI effect_Unload(IDirectInputEffect *iface)
+static HRESULT CDECL unix_effect_unload(struct unix_effect *ptr)
 {
-    EffectImpl *This = impl_from_IDirectInputEffect(iface);
+    EffectImpl *This = impl_from_unix_effect(ptr);
     TRACE("%p\n", This);
     return osx_to_win32_hresult(FFEffectUnload(This->effect));
 }
 
-static HRESULT WINAPI effect_Escape(IDirectInputEffect *iface, DIEFFESCAPE *escape)
+static HRESULT CDECL unix_effect_escape(struct unix_effect *ptr, DIEFFESCAPE *escape)
 {
-    EffectImpl *This = impl_from_IDirectInputEffect(iface);
+    EffectImpl *This = impl_from_unix_effect(ptr);
     TRACE("%p %p\n", This, escape);
     return osx_to_win32_hresult(FFEffectEscape(This->effect, (FFEFFESCAPE*)escape));
 }
 
-static const IDirectInputEffectVtbl EffectVtbl = {
-    effect_QueryInterface,
-    effect_AddRef,
-    effect_Release,
-    effect_Initialize,
-    effect_GetEffectGuid,
-    effect_GetParameters,
-    effect_SetParameters,
-    effect_Start,
-    effect_Stop,
-    effect_GetEffectStatus,
-    effect_Download,
-    effect_Unload,
-    effect_Escape
-};
-
 #else /* HAVE_IOHIDMANAGERCREATE */
 
 const struct dinput_device joystick_osx_device = {
diff --git a/dlls/dinput/joystick_private.h b/dlls/dinput/joystick_private.h
index 44d8731bdb1..4e5b3eaa245 100644
--- a/dlls/dinput/joystick_private.h
+++ b/dlls/dinput/joystick_private.h
@@ -33,6 +33,21 @@
 #define MAX_PROPS 164
 struct JoystickGenericImpl;
 
+struct unix_effect;
+
+struct unix_effect_vtbl
+{
+    HRESULT (CDECL *get_parameters)(struct unix_effect *ptr, DIEFFECT *effect, DWORD flags);
+    HRESULT (CDECL *set_parameters)(struct unix_effect *ptr, const DIEFFECT *effect, DWORD flags);
+    HRESULT (CDECL *start)(struct unix_effect *ptr, DWORD iterations, DWORD flags);
+    HRESULT (CDECL *stop)(struct unix_effect *ptr);
+    HRESULT (CDECL *get_status)(struct unix_effect *ptr, DWORD *flags);
+    HRESULT (CDECL *download)(struct unix_effect *ptr);
+    HRESULT (CDECL *unload)(struct unix_effect *ptr);
+    HRESULT (CDECL *escape)(struct unix_effect *ptr, DIEFFESCAPE *escape);
+    void (CDECL *destroy)(struct unix_effect *ptr);
+};
+
 struct unix_joystick;
 
 struct unix_joystick_vtbl
@@ -52,7 +67,7 @@ struct unix_joystick_vtbl
 
     HRESULT (CDECL *list_effects)(struct unix_joystick *ptr, DWORD type, const GUID **guids, DWORD size, DWORD *count);
     HRESULT (CDECL *get_effect_info)(struct unix_joystick *ptr, REFGUID guid, DIEFFECTINFOA *diei);
-    HRESULT (CDECL *create_effect)(struct unix_joystick *ptr, REFGUID guid, const DIEFFECT *effect, struct list *entry, IDirectInputEffect **out);
+    HRESULT (CDECL *create_effect)(struct unix_joystick *ptr, REFGUID guid, DWORD type, const DIEFFECT *effect, const struct unix_effect_vtbl **vtbl, struct unix_effect **out);
 
     void (CDECL *poll)(struct unix_joystick *ptr);
 };
@@ -120,6 +135,5 @@ HRESULT WINAPI JoystickWGenericImpl_BuildActionMap(LPDIRECTINPUTDEVICE8W iface,
 HRESULT WINAPI JoystickWGenericImpl_SetActionMap(LPDIRECTINPUTDEVICE8W iface, LPDIACTIONFORMATW lpdiaf, LPCWSTR lpszUserName, DWORD dwFlags) DECLSPEC_HIDDEN;
 
 DWORD typeFromGUID(REFGUID guid) DECLSPEC_HIDDEN;
-void dump_DIEFFECT(LPCDIEFFECT eff, REFGUID guid, DWORD dwFlags) DECLSPEC_HIDDEN;
 
 #endif /* __WINE_DLLS_DINPUT_JOYSTICK_PRIVATE_H */
-- 
2.28.0

>From 2b8c25d5d2049cd167a940cee98f27185c74f56e Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?R=C3=A9mi=20Bernon?= <rbernon@codeweavers.com>
Date: Tue, 6 Oct 2020 16:18:11 +0200
Subject: [PATCH 36/39] dinput: Create unix joystick data separately from
 generic.

---
 dlls/dinput/ansi.c                |   2 +-
 dlls/dinput/device_private.h      |   1 +
 dlls/dinput/dinput_private.h      |   5 +-
 dlls/dinput/joystick.c            | 123 ++++++++++++++++++++++++------
 dlls/dinput/joystick_linux.c      | 114 +++++++--------------------
 dlls/dinput/joystick_linuxinput.c | 120 ++++++++---------------------
 dlls/dinput/joystick_osx.c        | 106 ++++++++-----------------
 dlls/dinput/joystick_private.h    |  58 +-------------
 8 files changed, 201 insertions(+), 328 deletions(-)

diff --git a/dlls/dinput/ansi.c b/dlls/dinput/ansi.c
index 81ac24f4d26..da5c52dd3f8 100644
--- a/dlls/dinput/ansi.c
+++ b/dlls/dinput/ansi.c
@@ -103,7 +103,7 @@ static void dideviceinstance_wtoa(const DIDEVICEINSTANCEW *didiw, DIDEVICEINSTAN
     didia->wUsage = didiw->wUsage;
 }
 
-static void dideviceinstance_atow(const DIDEVICEINSTANCEA *didia, DIDEVICEINSTANCEW *didiw)
+void dideviceinstance_atow(const DIDEVICEINSTANCEA *didia, DIDEVICEINSTANCEW *didiw)
 {
     didiw->guidInstance = didia->guidInstance;
     didiw->guidProduct = didia->guidProduct;
diff --git a/dlls/dinput/device_private.h b/dlls/dinput/device_private.h
index d6ce489c3e1..c244550e105 100644
--- a/dlls/dinput/device_private.h
+++ b/dlls/dinput/device_private.h
@@ -94,6 +94,7 @@ extern const IDirectInputDevice8AVtbl direct_input_device_a_vtbl DECLSPEC_HIDDEN
 
 extern HRESULT direct_input_device_alloc(SIZE_T size, const IDirectInputDevice8WVtbl *vtbl, const GUID *guid, WORD vid,
         WORD pid, WORD iid, const DIDEVICEINSTANCEW *info, IDirectInputImpl *dinput, void **out) DECLSPEC_HIDDEN;
+extern void dideviceinstance_atow(const DIDEVICEINSTANCEA *didia, DIDEVICEINSTANCEW *didiw) DECLSPEC_HIDDEN;
 
 extern BOOL get_app_key(HKEY*, HKEY*) DECLSPEC_HIDDEN;
 extern DWORD get_config_key(HKEY, HKEY, const char*, char*, DWORD) DECLSPEC_HIDDEN;
diff --git a/dlls/dinput/dinput_private.h b/dlls/dinput/dinput_private.h
index 41819fbd425..99cc3ce4a1c 100644
--- a/dlls/dinput/dinput_private.h
+++ b/dlls/dinput/dinput_private.h
@@ -55,13 +55,16 @@ extern const IDirectInput8AVtbl direct_input_8_a_vtbl DECLSPEC_HIDDEN;
 typedef struct IDirectInputDeviceImpl IDirectInputDeviceImpl;
 typedef struct JoystickGenericImpl JoystickGenericImpl;
 
+struct unix_joystick_vtbl;
+struct unix_joystick;
+
 /* Function called by all devices that Wine supports */
 struct dinput_device {
     const char *name;
     HRESULT (*enum_deviceA)(DWORD dwDevType, DWORD dwFlags, LPDIDEVICEINSTANCEA lpddi, DWORD version, int id);
     HRESULT (*enum_deviceW)(DWORD dwDevType, DWORD dwFlags, LPDIDEVICEINSTANCEW lpddi, DWORD version, int id);
     HRESULT (*create_device)(IDirectInputImpl *dinput, REFGUID rguid, IDirectInputDeviceImpl **out);
-    HRESULT (*create_unix_joystick)(IDirectInputImpl *dinput, REFGUID rguid, JoystickGenericImpl **out);
+    HRESULT (*create_unix_joystick)(REFGUID guid, DWORD version, const struct unix_joystick_vtbl **vtbl, struct unix_joystick **ptr, WORD *vid, WORD *pid, WORD *iid, DIDEVICEINSTANCEA *info);
 };
 
 typedef struct JoystickGenericImpl JoystickGenericImpl;
diff --git a/dlls/dinput/joystick.c b/dlls/dinput/joystick.c
index 6768ff5b1be..2e28c0cacee 100644
--- a/dlls/dinput/joystick.c
+++ b/dlls/dinput/joystick.c
@@ -222,6 +222,23 @@ static HRESULT CDECL dinput_unix_effect_alloc(const struct unix_effect_vtbl *uni
     return DI_OK;
 }
 
+typedef struct JoystickGenericImpl
+{
+    struct IDirectInputDeviceImpl base;
+    const struct unix_joystick_vtbl *unix_funcs;
+    struct unix_joystick *unix_ptr;
+
+    ObjProps    props[MAX_PROPS];
+    DIDEVCAPS   devcaps;
+    DIJOYSTATE2 js;     /* wine data */
+    int        *axis_map;               /* User axes remapping */
+    LONG        deadzone;               /* Default dead-zone */
+
+    DWORD ff_autocenter;
+    DWORD ff_gain;
+    struct list ff_effects;
+} JoystickGenericImpl;
+
 static inline JoystickGenericImpl *impl_from_IDirectInputDevice8W(IDirectInputDevice8W *iface)
 {
     return CONTAINING_RECORD(CONTAINING_RECORD(iface, IDirectInputDeviceImpl, IDirectInputDevice8W_iface), JoystickGenericImpl, base);
@@ -505,7 +522,7 @@ static LONG joystick_map_axis(ObjProps *props, int val);
 /******************************************************************************
   *     SetProperty : change input device properties
   */
-HRESULT WINAPI JoystickWGenericImpl_SetProperty(LPDIRECTINPUTDEVICE8W iface, REFGUID rguid, LPCDIPROPHEADER ph)
+static HRESULT WINAPI JoystickWGenericImpl_SetProperty(LPDIRECTINPUTDEVICE8W iface, REFGUID rguid, LPCDIPROPHEADER ph)
 {
     JoystickGenericImpl *This = impl_from_IDirectInputDevice8W(iface);
     DWORD i;
@@ -656,7 +673,7 @@ HRESULT WINAPI JoystickWGenericImpl_SetProperty(LPDIRECTINPUTDEVICE8W iface, REF
     return DI_OK;
 }
 
-HRESULT WINAPI JoystickWGenericImpl_Acquire(LPDIRECTINPUTDEVICE8W iface)
+static HRESULT WINAPI JoystickWGenericImpl_Acquire(LPDIRECTINPUTDEVICE8W iface)
 {
     JoystickGenericImpl *This = impl_from_IDirectInputDevice8W(iface);
     HRESULT hr;
@@ -670,7 +687,7 @@ HRESULT WINAPI JoystickWGenericImpl_Acquire(LPDIRECTINPUTDEVICE8W iface)
     return hr;
 }
 
-HRESULT WINAPI JoystickWGenericImpl_Unacquire(LPDIRECTINPUTDEVICE8W iface)
+static HRESULT WINAPI JoystickWGenericImpl_Unacquire(LPDIRECTINPUTDEVICE8W iface)
 {
     JoystickGenericImpl *This = impl_from_IDirectInputDevice8W(iface);
     HRESULT hr;
@@ -730,7 +747,17 @@ static void _dump_DIDEVCAPS(const DIDEVCAPS *lpDIDevCaps)
 }
 #undef DEBUG_TYPE
 
-HRESULT WINAPI JoystickWGenericImpl_GetCapabilities(LPDIRECTINPUTDEVICE8W iface, LPDIDEVCAPS lpDIDevCaps)
+static ULONG WINAPI JoystickWGenericImpl_Release(LPDIRECTINPUTDEVICE8W iface)
+{
+    JoystickGenericImpl *This = impl_from_IDirectInputDevice8W(iface);
+    const struct unix_joystick_vtbl *unix_funcs = This->unix_funcs;
+    struct unix_joystick *unix_ptr = This->unix_ptr;
+    ULONG ref = IDirectInputDevice2WImpl_Release(iface);
+    if (!ref) unix_funcs->destroy(unix_ptr);
+    return ref;
+}
+
+static HRESULT WINAPI JoystickWGenericImpl_GetCapabilities(LPDIRECTINPUTDEVICE8W iface, LPDIDEVCAPS lpDIDevCaps)
 {
     JoystickGenericImpl *This = impl_from_IDirectInputDevice8W(iface);
     int size;
@@ -761,8 +788,8 @@ HRESULT WINAPI JoystickWGenericImpl_GetCapabilities(LPDIRECTINPUTDEVICE8W iface,
 /******************************************************************************
   *     GetObjectInfo : get object info
   */
-HRESULT WINAPI JoystickWGenericImpl_GetObjectInfo(LPDIRECTINPUTDEVICE8W iface,
-        LPDIDEVICEOBJECTINSTANCEW pdidoi, DWORD dwObj, DWORD dwHow)
+static HRESULT WINAPI JoystickWGenericImpl_GetObjectInfo(LPDIRECTINPUTDEVICE8W iface, LPDIDEVICEOBJECTINSTANCEW pdidoi,
+        DWORD dwObj, DWORD dwHow)
 {
     static const WCHAR axisW[] = {'A','x','i','s',' ','%','d',0};
     static const WCHAR povW[] = {'P','O','V',' ','%','d',0};
@@ -787,7 +814,7 @@ HRESULT WINAPI JoystickWGenericImpl_GetObjectInfo(LPDIRECTINPUTDEVICE8W iface,
 /******************************************************************************
   *     GetProperty : get input device properties
   */
-HRESULT WINAPI JoystickWGenericImpl_GetProperty(LPDIRECTINPUTDEVICE8W iface, REFGUID rguid, LPDIPROPHEADER pdiph)
+static HRESULT WINAPI JoystickWGenericImpl_GetProperty(LPDIRECTINPUTDEVICE8W iface, REFGUID rguid, LPDIPROPHEADER pdiph)
 {
     JoystickGenericImpl *This = impl_from_IDirectInputDevice8W(iface);
 
@@ -906,7 +933,7 @@ HRESULT WINAPI JoystickWGenericImpl_GetProperty(LPDIRECTINPUTDEVICE8W iface, REF
     return DI_OK;
 }
 
-HRESULT WINAPI JoystickWGenericImpl_EnumEffects(LPDIRECTINPUTDEVICE8W iface, LPDIENUMEFFECTSCALLBACKW lpCallback,
+static HRESULT WINAPI JoystickWGenericImpl_EnumEffects(LPDIRECTINPUTDEVICE8W iface, LPDIENUMEFFECTSCALLBACKW lpCallback,
         LPVOID pvRef, DWORD dwEffType)
 {
     JoystickGenericImpl *This = impl_from_IDirectInputDevice8W(iface);
@@ -944,7 +971,7 @@ static void dieffectinfo_atow(const DIEFFECTINFOA *dieia, DIEFFECTINFOW *dieiw)
     MultiByteToWideChar(CP_ACP, 0, dieia->tszName, -1, dieiw->tszName, sizeof(dieiw->tszName));
 }
 
-HRESULT WINAPI JoystickWGenericImpl_GetEffectInfo(LPDIRECTINPUTDEVICE8W iface, LPDIEFFECTINFOW diei, REFGUID rguid)
+static HRESULT WINAPI JoystickWGenericImpl_GetEffectInfo(LPDIRECTINPUTDEVICE8W iface, DIEFFECTINFOW *diei, REFGUID rguid)
 {
     JoystickGenericImpl *This = impl_from_IDirectInputDevice8W(iface);
     DIEFFECTINFOA dieia = {sizeof(dieia)};
@@ -956,7 +983,7 @@ HRESULT WINAPI JoystickWGenericImpl_GetEffectInfo(LPDIRECTINPUTDEVICE8W iface, L
     return hr;
 }
 
-HRESULT WINAPI JoystickWGenericImpl_CreateEffect(LPDIRECTINPUTDEVICE8W iface, REFGUID rguid, LPCDIEFFECT lpeff,
+static HRESULT WINAPI JoystickWGenericImpl_CreateEffect(LPDIRECTINPUTDEVICE8W iface, REFGUID rguid, LPCDIEFFECT lpeff,
         LPDIRECTINPUTEFFECT *ppdef, LPUNKNOWN pUnkOuter)
 {
     JoystickGenericImpl *This = impl_from_IDirectInputDevice8W(iface);
@@ -986,7 +1013,7 @@ HRESULT WINAPI JoystickWGenericImpl_CreateEffect(LPDIRECTINPUTDEVICE8W iface, RE
     return DI_OK;
 }
 
-HRESULT WINAPI JoystickWGenericImpl_EnumCreatedEffectObjects(LPDIRECTINPUTDEVICE8W iface,
+static HRESULT WINAPI JoystickWGenericImpl_EnumCreatedEffectObjects(LPDIRECTINPUTDEVICE8W iface,
         LPDIENUMCREATEDEFFECTOBJECTSCALLBACK lpCallback, LPVOID pvRef, DWORD dwFlags)
 {
     JoystickGenericImpl *This = impl_from_IDirectInputDevice8W(iface);
@@ -1001,7 +1028,7 @@ HRESULT WINAPI JoystickWGenericImpl_EnumCreatedEffectObjects(LPDIRECTINPUTDEVICE
     return DI_OK;
 }
 
-HRESULT WINAPI JoystickWGenericImpl_GetForceFeedbackState(LPDIRECTINPUTDEVICE8W iface, LPDWORD pdwOut)
+static HRESULT WINAPI JoystickWGenericImpl_GetForceFeedbackState(LPDIRECTINPUTDEVICE8W iface, LPDWORD pdwOut)
 {
     JoystickGenericImpl *This = impl_from_IDirectInputDevice8W(iface);
 
@@ -1011,7 +1038,7 @@ HRESULT WINAPI JoystickWGenericImpl_GetForceFeedbackState(LPDIRECTINPUTDEVICE8W
     return This->unix_funcs->ff_get_state(This->unix_ptr, pdwOut);
 }
 
-HRESULT WINAPI JoystickWGenericImpl_SendForceFeedbackCommand(LPDIRECTINPUTDEVICE8W iface, DWORD dwFlags)
+static HRESULT WINAPI JoystickWGenericImpl_SendForceFeedbackCommand(LPDIRECTINPUTDEVICE8W iface, DWORD dwFlags)
 {
     JoystickGenericImpl *This = impl_from_IDirectInputDevice8W(iface);
     struct dinput_unix_effect *itr;
@@ -1041,7 +1068,7 @@ HRESULT WINAPI JoystickWGenericImpl_SendForceFeedbackCommand(LPDIRECTINPUTDEVICE
     return This->unix_funcs->ff_send_cmd(This->unix_ptr, dwFlags);
 }
 
-HRESULT WINAPI JoystickWGenericImpl_Poll(LPDIRECTINPUTDEVICE8W iface)
+static HRESULT WINAPI JoystickWGenericImpl_Poll(LPDIRECTINPUTDEVICE8W iface)
 {
     JoystickGenericImpl *This = impl_from_IDirectInputDevice8W(iface);
 
@@ -1060,7 +1087,7 @@ HRESULT WINAPI JoystickWGenericImpl_Poll(LPDIRECTINPUTDEVICE8W iface)
   *     GetDeviceState : returns the "state" of the joystick.
   *
   */
-HRESULT WINAPI JoystickWGenericImpl_GetDeviceState(LPDIRECTINPUTDEVICE8W iface, DWORD len, LPVOID ptr)
+static HRESULT WINAPI JoystickWGenericImpl_GetDeviceState(LPDIRECTINPUTDEVICE8W iface, DWORD len, LPVOID ptr)
 {
     JoystickGenericImpl *This = impl_from_IDirectInputDevice8W(iface);
 
@@ -1080,10 +1107,8 @@ HRESULT WINAPI JoystickWGenericImpl_GetDeviceState(LPDIRECTINPUTDEVICE8W iface,
     return DI_OK;
 }
 
-HRESULT WINAPI JoystickWGenericImpl_BuildActionMap(LPDIRECTINPUTDEVICE8W iface,
-                                                   LPDIACTIONFORMATW lpdiaf,
-                                                   LPCWSTR lpszUserName,
-                                                   DWORD dwFlags)
+static HRESULT WINAPI JoystickWGenericImpl_BuildActionMap(LPDIRECTINPUTDEVICE8W iface, LPDIACTIONFORMATW lpdiaf,
+        LPCWSTR lpszUserName, DWORD dwFlags)
 {
     static const DWORD object_types[] = { DIDFT_AXIS, DIDFT_BUTTON };
     static const DWORD type_map[] = { DIDFT_RELAXIS, DIDFT_PSHBUTTON };
@@ -1132,10 +1157,8 @@ HRESULT WINAPI JoystickWGenericImpl_BuildActionMap(LPDIRECTINPUTDEVICE8W iface,
     return IDirectInputDevice8WImpl_BuildActionMap(iface, lpdiaf, lpszUserName, dwFlags);
 }
 
-HRESULT WINAPI JoystickWGenericImpl_SetActionMap(LPDIRECTINPUTDEVICE8W iface,
-                                                 LPDIACTIONFORMATW lpdiaf,
-                                                 LPCWSTR lpszUserName,
-                                                 DWORD dwFlags)
+static HRESULT WINAPI JoystickWGenericImpl_SetActionMap(LPDIRECTINPUTDEVICE8W iface, LPDIACTIONFORMATW lpdiaf,
+        LPCWSTR lpszUserName, DWORD dwFlags)
 {
     JoystickGenericImpl *This = impl_from_IDirectInputDevice8W(iface);
 
@@ -1356,20 +1379,70 @@ static HRESULT setup_dinput_options(JoystickGenericImpl *This, int default_axis_
     return DI_OK;
 }
 
+static const IDirectInputDevice8WVtbl dinput_joystick_w_vtbl =
+{
+    IDirectInputDevice2WImpl_QueryInterface,
+    IDirectInputDevice2WImpl_AddRef,
+    JoystickWGenericImpl_Release,
+    JoystickWGenericImpl_GetCapabilities,
+    IDirectInputDevice2WImpl_EnumObjects,
+    JoystickWGenericImpl_GetProperty,
+    JoystickWGenericImpl_SetProperty,
+    JoystickWGenericImpl_Acquire,
+    JoystickWGenericImpl_Unacquire,
+    JoystickWGenericImpl_GetDeviceState,
+    IDirectInputDevice2WImpl_GetDeviceData,
+    IDirectInputDevice2WImpl_SetDataFormat,
+    IDirectInputDevice2WImpl_SetEventNotification,
+    IDirectInputDevice2WImpl_SetCooperativeLevel,
+    JoystickWGenericImpl_GetObjectInfo,
+    IDirectInputDevice2WImpl_GetDeviceInfo,
+    IDirectInputDevice2WImpl_RunControlPanel,
+    IDirectInputDevice2WImpl_Initialize,
+    JoystickWGenericImpl_CreateEffect,
+    JoystickWGenericImpl_EnumEffects,
+    JoystickWGenericImpl_GetEffectInfo,
+    JoystickWGenericImpl_GetForceFeedbackState,
+    JoystickWGenericImpl_SendForceFeedbackCommand,
+    JoystickWGenericImpl_EnumCreatedEffectObjects,
+    IDirectInputDevice2WImpl_Escape,
+    JoystickWGenericImpl_Poll,
+    IDirectInputDevice2WImpl_SendDeviceData,
+    IDirectInputDevice7WImpl_EnumEffectsInFile,
+    IDirectInputDevice7WImpl_WriteEffectToFile,
+    JoystickWGenericImpl_BuildActionMap,
+    JoystickWGenericImpl_SetActionMap,
+    IDirectInputDevice8WImpl_GetImageInfo
+};
+
 HRESULT dinput_create_unix_joystick(const struct dinput_device *device, IDirectInputImpl *dinput, REFGUID guid, REFIID iid, void **out)
 {
+    DIDEVICEINSTANCEW didiw = {sizeof(didiw)};
+    DIDEVICEINSTANCEA didia = {sizeof(didia)};
+    const struct unix_joystick_vtbl *unix_funcs;
+    struct unix_joystick *unix_ptr;
     JoystickGenericImpl *This;
     ObjProps props[MAX_PROPS];
     DIOBJECTDATAFORMAT *odf = NULL;
     DIDATAFORMAT *df = NULL;
     HRESULT hr;
+    WORD pid, vid, index;
     const int *default_axes_map;
     int i, j, default_axis_count, prop_count;
     WORD idx, type;
     BOOL has_ff = FALSE;
 
-    if (FAILED(hr = device->create_unix_joystick(dinput, guid, &This)))
+    *out = NULL;
+    if (FAILED(hr = device->create_unix_joystick(guid, dinput->dwVersion, &unix_funcs, &unix_ptr, &vid, &pid, &index, &didia))) return hr;
+    dideviceinstance_atow(&didia, &didiw);
+    if (FAILED(hr = direct_input_device_alloc(sizeof(JoystickGenericImpl), &dinput_joystick_w_vtbl, guid, vid, pid, index, &didiw, dinput, (void **)&This)))
+    {
+        unix_funcs->destroy(unix_ptr);
         return hr;
+    }
+    This->base.crit.DebugInfo->Spare[0] = (DWORD_PTR)(__FILE__ ": JoystickGenericImpl*->base.crit");
+    This->unix_funcs = unix_funcs;
+    This->unix_ptr = unix_ptr;
     list_init(&This->ff_effects);
 
     if (This->unix_funcs->get_mapping)
@@ -1405,7 +1478,7 @@ HRESULT dinput_create_unix_joystick(const struct dinput_device *device, IDirectI
     This->js.rglSlider[1] = 0;
     for (i = 0; i < 4; i++) This->js.rgdwPOV[i] = -1;
 
-    if (FAILED(hr = This->unix_funcs->init(This->unix_ptr, props, &prop_count, &has_ff))) goto done;
+    if (FAILED(hr = This->unix_funcs->init(This->unix_ptr, This, props, &prop_count, &has_ff))) goto done;
     memcpy(This->props, props, sizeof(This->props));
 
     if (!(df = HeapAlloc(GetProcessHeap(), 0, c_dfDIJoystick2.dwSize))) goto done;
diff --git a/dlls/dinput/joystick_linux.c b/dlls/dinput/joystick_linux.c
index 8ca6deb90b6..a9c57e136de 100644
--- a/dlls/dinput/joystick_linux.c
+++ b/dlls/dinput/joystick_linux.c
@@ -92,10 +92,9 @@ struct JoyDev
 };
 
 typedef struct JoystickImpl JoystickImpl;
-static const IDirectInputDevice8WVtbl JoystickWvt;
 struct JoystickImpl
 {
-        struct JoystickGenericImpl generic;
+        struct JoystickGenericImpl *generic;
 
         struct JoyDev                  *joydev;
 
@@ -130,12 +129,14 @@ static void CDECL unix_joystick_poll(struct unix_joystick *ptr);
 static HRESULT CDECL unix_joystick_acquire(struct unix_joystick *ptr);
 static HRESULT CDECL unix_joystick_unacquire(struct unix_joystick *ptr);
 
-static HRESULT CDECL unix_joystick_init(struct unix_joystick *ptr, ObjProps *props, int *prop_count, BOOL *has_ff);
+static HRESULT CDECL unix_joystick_init(struct unix_joystick *ptr, JoystickGenericImpl *generic, ObjProps *props, int *prop_count, BOOL *has_ff);
+static void CDECL unix_joystick_destroy(struct unix_joystick *ptr);
 static void CDECL unix_joystick_get_mapping(struct unix_joystick *ptr, int *axis_count, const int **axes_map);
 
 static const struct unix_joystick_vtbl unix_joystick_vtbl =
 {
     unix_joystick_init,
+    unix_joystick_destroy,
     NULL,
     unix_joystick_get_mapping,
     unix_joystick_acquire,
@@ -363,7 +364,7 @@ static INT find_joystick_devices(void)
     return joystick_devices_count;
 }
 
-static void fill_joystick_dideviceinstanceW(LPDIDEVICEINSTANCEW lpddi, DWORD version, int id)
+static void fill_joystick_dideviceinstanceA(LPDIDEVICEINSTANCEA lpddi, DWORD version, int id)
 {
     DWORD dwSize = lpddi->dwSize;
 
@@ -389,32 +390,9 @@ static void fill_joystick_dideviceinstanceW(LPDIDEVICEINSTANCEW lpddi, DWORD ver
             lpddi->wUsage = 0x05; /* Game Pad */
     }
 
-    MultiByteToWideChar(CP_ACP, 0, joystick_devices[id].name, -1, lpddi->tszInstanceName, MAX_PATH);
-    MultiByteToWideChar(CP_ACP, 0, joystick_devices[id].name, -1, lpddi->tszProductName, MAX_PATH);
-    lpddi->guidFFDriver = GUID_NULL;
-}
-
-static void fill_joystick_dideviceinstanceA(LPDIDEVICEINSTANCEA lpddi, DWORD version, int id)
-{
-    DIDEVICEINSTANCEW lpddiW;
-    DWORD dwSize = lpddi->dwSize;
-
-    lpddiW.dwSize = sizeof(lpddiW);
-    fill_joystick_dideviceinstanceW(&lpddiW, version, id);
-
-    TRACE("%d %p\n", dwSize, lpddi);
-    memset(lpddi, 0, dwSize);
-
-    /* Convert W->A */
-    lpddi->dwSize = dwSize;
-    lpddi->guidInstance = lpddiW.guidInstance;
-    lpddi->guidProduct = lpddiW.guidProduct;
-    lpddi->dwDevType = lpddiW.dwDevType;
     strcpy(lpddi->tszInstanceName, joystick_devices[id].name);
     strcpy(lpddi->tszProductName,  joystick_devices[id].name);
-    lpddi->guidFFDriver = lpddiW.guidFFDriver;
-    lpddi->wUsagePage = lpddiW.wUsagePage;
-    lpddi->wUsage = lpddiW.wUsage;
+    lpddi->guidFFDriver = GUID_NULL;
 }
 
 static HRESULT joydev_enum_deviceA(DWORD dwDevType, DWORD dwFlags, LPDIDEVICEINSTANCEA lpddi, DWORD version, int id)
@@ -466,36 +444,30 @@ static unsigned short get_joystick_index(REFGUID guid)
     return MAX_JOYSTICKS;
 }
 
-static HRESULT joydev_create_unix_joystick(IDirectInputImpl *dinput, REFGUID guid, JoystickGenericImpl **out)
+static HRESULT joydev_create_unix_joystick(REFGUID guid, DWORD version, const struct unix_joystick_vtbl **vtbl, struct unix_joystick **ptr, WORD *vid, WORD *pid, WORD *iid, DIDEVICEINSTANCEA *info)
 {
     struct JoyDev *joydev;
-    DIDEVICEINSTANCEW didi = {sizeof(didi)};
     JoystickImpl *newDevice;
-    HRESULT hr;
     DWORD index;
 
-    TRACE("%p %s %p\n", dinput, debugstr_guid(guid), out);
-
     find_joystick_devices();
 
-    *out = NULL;
     if ((index = get_joystick_index(guid)) >= MAX_JOYSTICKS || !joystick_devices_count || index >= joystick_devices_count)
         return DIERR_DEVICENOTREG;
     joydev = &joystick_devices[index];
 
-    fill_joystick_dideviceinstanceW(&didi, dinput->dwVersion, index);
-
-    if (FAILED(hr = direct_input_device_alloc(sizeof(JoystickImpl), &JoystickWvt, guid, joydev->vendor_id,
-                       joydev->product_id, index, &didi, dinput, (void **)&newDevice)))
-        return hr;
-    newDevice->generic.base.crit.DebugInfo->Spare[0] = (DWORD_PTR)(__FILE__ ": JoystickImpl*->generic.base.crit");
-    newDevice->generic.unix_funcs = &unix_joystick_vtbl;
-    newDevice->generic.unix_ptr = unix_joystick_from_impl(newDevice);
+    fill_joystick_dideviceinstanceA(info, version, index);
 
+    if (!(newDevice = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*newDevice)))) return DIERR_OUTOFMEMORY;
     newDevice->joydev = joydev;
     newDevice->joyfd = -1;
 
-    *out = &newDevice->generic;
+    *vid = joydev->vendor_id;
+    *pid = joydev->product_id;
+    *iid = index;
+    *vtbl = &unix_joystick_vtbl;
+    *ptr = unix_joystick_from_impl(newDevice);
+
     return DI_OK;
 }
 
@@ -506,16 +478,18 @@ static void CDECL unix_joystick_get_mapping(struct unix_joystick *ptr, int *axis
     *axes_map = This->joydev->axes_map;
 }
 
-static HRESULT CDECL unix_joystick_init(struct unix_joystick *ptr, ObjProps *props, int *prop_count, BOOL *has_ff)
+static HRESULT CDECL unix_joystick_init(struct unix_joystick *ptr, JoystickGenericImpl *generic, ObjProps *props, int *prop_count, BOOL *has_ff)
 {
     JoystickImpl *This = impl_from_unix_joystick(ptr);
     int i, idx = 0, wine_obj;
 
+    This->generic = generic;
+
     for (i = 0; i < This->joydev->axis_count; i++)
     {
         if ((idx = This->joydev->axes_map[i]) >= 0)
         {
-            wine_obj = win32_funcs->joystick_get_axis(&This->generic, i);
+            wine_obj = win32_funcs->joystick_get_axis(This->generic, i);
             if (wine_obj < 0) props[idx].dwType = 0;
             else if (wine_obj < 8) props[idx].dwType = DIDFT_MAKEINSTANCE(wine_obj) | DIDFT_ABSAXIS;
             else props[idx].dwType = DIDFT_MAKEINSTANCE(wine_obj - 8) | DIDFT_POV;
@@ -529,6 +503,12 @@ static HRESULT CDECL unix_joystick_init(struct unix_joystick *ptr, ObjProps *pro
     return DI_OK;
 }
 
+static void CDECL unix_joystick_destroy(struct unix_joystick *ptr)
+{
+    JoystickImpl *This = impl_from_unix_joystick(ptr);
+    HeapFree(GetProcessHeap(), 0, This);
+}
+
 #undef MAX_JOYSTICKS
 
 const struct dinput_device joystick_linux_device = {
@@ -606,60 +586,24 @@ static void CDECL unix_joystick_poll(struct unix_joystick *ptr)
         TRACE("js_event: type 0x%x, number %d, value %d\n",
               jse.type,jse.number,jse.value);
         if (jse.type & JS_EVENT_BUTTON)
-            win32_funcs->joystick_queue_event(&This->generic, DIDFT_PSHBUTTON, jse.number, jse.value ? 0x80 : 0x00);
+            win32_funcs->joystick_queue_event(This->generic, DIDFT_PSHBUTTON, jse.number, jse.value ? 0x80 : 0x00);
         else if (jse.type & JS_EVENT_AXIS)
         {
-            int axis = win32_funcs->joystick_get_axis(&This->generic, jse.number);
+            int axis = win32_funcs->joystick_get_axis(This->generic, jse.number);
             if (axis < 0) return;
             TRACE("changing axis %d => %d\n", jse.number, axis);
-            if (axis >= 0 && axis < 8) win32_funcs->joystick_queue_event(&This->generic, DIDFT_ABSAXIS, axis, jse.value);
+            if (axis >= 0 && axis < 8) win32_funcs->joystick_queue_event(This->generic, DIDFT_ABSAXIS, axis, jse.value);
             else if (axis >= 8 && axis < 12)
             {
                 if (jse.number % 2) This->povs[axis - 8].y = jse.value;
                 else This->povs[axis - 8].x = jse.value;
-                win32_funcs->joystick_queue_event(&This->generic, DIDFT_POV, axis - 8, joystick_map_pov(&This->povs[axis - 8]));
+                win32_funcs->joystick_queue_event(This->generic, DIDFT_POV, axis - 8, joystick_map_pov(&This->povs[axis - 8]));
             }
             else WARN("axis %d not supported\n", axis);
         }
     }
 }
 
-static const IDirectInputDevice8WVtbl JoystickWvt =
-{
-    IDirectInputDevice2WImpl_QueryInterface,
-    IDirectInputDevice2WImpl_AddRef,
-    IDirectInputDevice2WImpl_Release,
-    JoystickWGenericImpl_GetCapabilities,
-    IDirectInputDevice2WImpl_EnumObjects,
-    JoystickWGenericImpl_GetProperty,
-    JoystickWGenericImpl_SetProperty,
-    JoystickWGenericImpl_Acquire,
-    JoystickWGenericImpl_Unacquire,
-    JoystickWGenericImpl_GetDeviceState,
-    IDirectInputDevice2WImpl_GetDeviceData,
-    IDirectInputDevice2WImpl_SetDataFormat,
-    IDirectInputDevice2WImpl_SetEventNotification,
-    IDirectInputDevice2WImpl_SetCooperativeLevel,
-    JoystickWGenericImpl_GetObjectInfo,
-    IDirectInputDevice2WImpl_GetDeviceInfo,
-    IDirectInputDevice2WImpl_RunControlPanel,
-    IDirectInputDevice2WImpl_Initialize,
-    IDirectInputDevice2WImpl_CreateEffect,
-    IDirectInputDevice2WImpl_EnumEffects,
-    IDirectInputDevice2WImpl_GetEffectInfo,
-    IDirectInputDevice2WImpl_GetForceFeedbackState,
-    IDirectInputDevice2WImpl_SendForceFeedbackCommand,
-    IDirectInputDevice2WImpl_EnumCreatedEffectObjects,
-    IDirectInputDevice2WImpl_Escape,
-    JoystickWGenericImpl_Poll,
-    IDirectInputDevice2WImpl_SendDeviceData,
-    IDirectInputDevice7WImpl_EnumEffectsInFile,
-    IDirectInputDevice7WImpl_WriteEffectToFile,
-    JoystickWGenericImpl_BuildActionMap,
-    JoystickWGenericImpl_SetActionMap,
-    IDirectInputDevice8WImpl_GetImageInfo
-};
-
 #else  /* HAVE_LINUX_22_JOYSTICK_API */
 
 const struct dinput_device joystick_linux_device = {
diff --git a/dlls/dinput/joystick_linuxinput.c b/dlls/dinput/joystick_linuxinput.c
index 8ed22d5bcfc..7c9fdba9418 100644
--- a/dlls/dinput/joystick_linuxinput.c
+++ b/dlls/dinput/joystick_linuxinput.c
@@ -91,7 +91,6 @@ HRESULT linuxinput_create_effect(int *fd, REFGUID rguid, DWORD type, const DIEFF
 HRESULT linuxinput_get_info_A(int fd, REFGUID rguid, LPDIEFFECTINFOA info);
 
 typedef struct JoystickImpl JoystickImpl;
-static const IDirectInputDevice8WVtbl JoystickWvt;
 
 struct JoyDev {
 	char *device;
@@ -124,7 +123,7 @@ struct JoyDev {
 
 struct JoystickImpl
 {
-        struct JoystickGenericImpl      generic;
+        struct JoystickGenericImpl     *generic;
         struct JoyDev                  *joydev;
 
 	/* joystick private */
@@ -164,13 +163,15 @@ static HRESULT CDECL unix_joystick_get_effect_info(struct unix_joystick *ptr, RE
 static HRESULT CDECL unix_joystick_create_effect(struct unix_joystick *ptr, REFGUID guid, DWORD type, const DIEFFECT *effect,
         const struct unix_effect_vtbl **vtbl, struct unix_effect **out);
 
-static HRESULT CDECL unix_joystick_init(struct unix_joystick *ptr, ObjProps *props, int *prop_count, BOOL *has_ff);
+static HRESULT CDECL unix_joystick_init(struct unix_joystick *ptr, JoystickGenericImpl *generic, ObjProps *props, int *prop_count, BOOL *has_ff);
+static void CDECL unix_joystick_destroy(struct unix_joystick *ptr);
 static void CDECL unix_joystick_reset(struct unix_joystick *ptr);
 static void CDECL unix_joystick_get_mapping(struct unix_joystick *ptr, int *axis_count, const int **axes_map);
 
 static const struct unix_joystick_vtbl unix_joystick_vtbl =
 {
     unix_joystick_init,
+    unix_joystick_destroy,
     unix_joystick_reset,
     unix_joystick_get_mapping,
     unix_joystick_acquire,
@@ -415,7 +416,7 @@ static void find_joydevs(void)
     }
 }
 
-static void fill_joystick_dideviceinstanceW(LPDIDEVICEINSTANCEW lpddi, DWORD version, int id)
+static void fill_joystick_dideviceinstanceA(LPDIDEVICEINSTANCEA lpddi, DWORD version, int id)
 {
     DWORD dwSize = lpddi->dwSize;
 
@@ -440,31 +441,8 @@ static void fill_joystick_dideviceinstanceW(LPDIDEVICEINSTANCEW lpddi, DWORD ver
             lpddi->wUsage = 0x05; /* Game Pad */
     }
 
-    MultiByteToWideChar(CP_ACP, 0, joydevs[id].name, -1, lpddi->tszInstanceName, MAX_PATH);
-    MultiByteToWideChar(CP_ACP, 0, joydevs[id].name, -1, lpddi->tszProductName, MAX_PATH);
-}
-
-static void fill_joystick_dideviceinstanceA(LPDIDEVICEINSTANCEA lpddi, DWORD version, int id)
-{
-    DIDEVICEINSTANCEW lpddiW;
-    DWORD dwSize = lpddi->dwSize;
-
-    lpddiW.dwSize = sizeof(lpddiW);
-    fill_joystick_dideviceinstanceW(&lpddiW, version, id);
-
-    TRACE("%d %p\n", dwSize, lpddi);
-    memset(lpddi, 0, dwSize);
-
-    /* Convert W->A */
-    lpddi->dwSize = dwSize;
-    lpddi->guidInstance = lpddiW.guidInstance;
-    lpddi->guidProduct = lpddiW.guidProduct;
-    lpddi->dwDevType = lpddiW.dwDevType;
     lstrcpynA(lpddi->tszInstanceName, joydevs[id].name, MAX_PATH);
     lstrcpynA(lpddi->tszProductName,  joydevs[id].name, MAX_PATH);
-    lpddi->guidFFDriver = lpddiW.guidFFDriver;
-    lpddi->wUsagePage = lpddiW.wUsagePage;
-    lpddi->wUsage = lpddiW.wUsage;
 }
 
 static HRESULT joydev_enum_deviceA(DWORD dwDevType, DWORD dwFlags, LPDIDEVICEINSTANCEA lpddi, DWORD version, int id)
@@ -512,36 +490,30 @@ static unsigned short get_joystick_index(REFGUID guid)
     return MAX_JOYDEV;
 }
 
-static HRESULT joydev_create_unix_joystick(IDirectInputImpl *dinput, REFGUID guid, JoystickGenericImpl **out)
+static HRESULT joydev_create_unix_joystick(REFGUID guid, DWORD version, const struct unix_joystick_vtbl **vtbl, struct unix_joystick **ptr, WORD *vid, WORD *pid, WORD *iid, DIDEVICEINSTANCEA *info)
 {
     struct JoyDev *joydev;
-    DIDEVICEINSTANCEW didi = {sizeof(didi)};
     JoystickImpl *newDevice;
-    HRESULT hr;
     int index;
 
-    TRACE("%p %s %p\n", dinput, debugstr_guid(guid), out);
-
     find_joydevs();
 
-    *out = NULL;
     if ((index = get_joystick_index(guid)) >= MAX_JOYDEV || !have_joydevs || index >= have_joydevs)
         return DIERR_DEVICENOTREG;
     joydev = &joydevs[index];
 
-    fill_joystick_dideviceinstanceW(&didi, dinput->dwVersion, index);
-
-    if (FAILED(hr = direct_input_device_alloc(sizeof(JoystickImpl), &JoystickWvt, guid, joydev->vendor_id,
-                       joydev->product_id, index, &didi, dinput, (void **)&newDevice)))
-        return hr;
-    newDevice->generic.base.crit.DebugInfo->Spare[0] = (DWORD_PTR)(__FILE__ ": JoystickImpl*->base.crit");
-    newDevice->generic.unix_funcs = &unix_joystick_vtbl;
-    newDevice->generic.unix_ptr = unix_joystick_from_impl(newDevice);
+    fill_joystick_dideviceinstanceA(info, version, index);
 
+    if (!(newDevice = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*newDevice)))) return DIERR_OUTOFMEMORY;
     newDevice->joyfd       = -1;
     newDevice->joydev = joydev;
 
-    *out = &newDevice->generic;
+    *vid = joydev->vendor_id;
+    *pid = joydev->product_id;
+    *iid = index;
+    *vtbl = &unix_joystick_vtbl;
+    *ptr = unix_joystick_from_impl(newDevice);
+
     return DI_OK;
 }
 
@@ -552,11 +524,13 @@ static void CDECL unix_joystick_get_mapping(struct unix_joystick *ptr, int *axis
     *axes_map = This->joydev->axes_map;
 }
 
-static HRESULT CDECL unix_joystick_init(struct unix_joystick *ptr, ObjProps *props, int *prop_count, BOOL *has_ff)
+static HRESULT CDECL unix_joystick_init(struct unix_joystick *ptr, JoystickGenericImpl *generic, ObjProps *props, int *prop_count, BOOL *has_ff)
 {
     JoystickImpl *This = impl_from_unix_joystick(ptr);
     int i, idx = 0, wine_obj;
 
+    This->generic = generic;
+
 #ifdef HAVE_STRUCT_FF_EFFECT_DIRECTION
     This->ff_state = FF_STATUS_STOPPED;
 #endif
@@ -574,7 +548,7 @@ static HRESULT CDECL unix_joystick_init(struct unix_joystick *ptr, ObjProps *pro
             props[idx].lDevMin = This->joydev->axes[i].minimum;
             props[idx].lDevMax = This->joydev->axes[i].maximum;
 
-            wine_obj = win32_funcs->joystick_get_axis(&This->generic, idx);
+            wine_obj = win32_funcs->joystick_get_axis(This->generic, idx);
             if (wine_obj < 0) props[idx].dwType = 0;
             else if (wine_obj < 8) props[idx].dwType = DIDFT_MAKEINSTANCE(wine_obj) | DIDFT_ABSAXIS;
             else props[idx].dwType = DIDFT_MAKEINSTANCE(wine_obj - 8) | DIDFT_POV;
@@ -590,7 +564,7 @@ static HRESULT CDECL unix_joystick_init(struct unix_joystick *ptr, ObjProps *pro
             props[idx].lDevMin = This->joydev->axes[ABS_HAT0X + i * 2].minimum;
             props[idx].lDevMax = This->joydev->axes[ABS_HAT0X + i * 2].maximum;
 
-            wine_obj = win32_funcs->joystick_get_axis(&This->generic, idx);
+            wine_obj = win32_funcs->joystick_get_axis(This->generic, idx);
             if (wine_obj < 0) props[idx].dwType = 0;
             else if (wine_obj < 8) props[idx].dwType = DIDFT_MAKEINSTANCE(wine_obj) | DIDFT_ABSAXIS;
             else props[idx].dwType = DIDFT_MAKEINSTANCE(wine_obj - 8) | DIDFT_POV;
@@ -601,7 +575,7 @@ static HRESULT CDECL unix_joystick_init(struct unix_joystick *ptr, ObjProps *pro
             props[idx].lDevMin = This->joydev->axes[ABS_HAT0Y + i * 2].minimum;
             props[idx].lDevMax = This->joydev->axes[ABS_HAT0Y + i * 2].maximum;
 
-            wine_obj = win32_funcs->joystick_get_axis(&This->generic, idx);
+            wine_obj = win32_funcs->joystick_get_axis(This->generic, idx);
             if (wine_obj < 0) props[idx].dwType = 0;
             else if (wine_obj < 8) props[idx].dwType = DIDFT_MAKEINSTANCE(wine_obj) | DIDFT_ABSAXIS;
             else props[idx].dwType = DIDFT_MAKEINSTANCE(wine_obj - 8) | DIDFT_POV;
@@ -616,6 +590,12 @@ static HRESULT CDECL unix_joystick_init(struct unix_joystick *ptr, ObjProps *pro
     return DI_OK;
 }
 
+static void CDECL unix_joystick_destroy(struct unix_joystick *ptr)
+{
+    JoystickImpl *This = impl_from_unix_joystick(ptr);
+    HeapFree(GetProcessHeap(), 0, This);
+}
+
 const struct dinput_device joystick_linuxinput_device = {
   "Wine Linux-input joystick driver",
   joydev_enum_deviceA,
@@ -713,7 +693,7 @@ static HRESULT CDECL unix_joystick_ff_set_gain(struct unix_joystick *ptr, DWORD
     struct input_event event;
 
     This->ff_gain = MulDiv(value, 0xFFFF, 10000);
-    if (!This->generic.base.acquired) return DI_OK;
+    if (This->joyfd == -1) return DI_OK;
 
     event.type = EV_FF;
     event.code = FF_GAIN;
@@ -729,7 +709,7 @@ static HRESULT CDECL unix_joystick_ff_set_gain(struct unix_joystick *ptr, DWORD
  */
 #define CENTER_AXIS(a) \
     if ((axis = This->joydev->dev_axes_to_di[a]) >= 0) \
-        win32_funcs->joystick_queue_event(&This->generic, DIDFT_ABSAXIS, axis, This->joydev->axes[a].value)
+        win32_funcs->joystick_queue_event(This->generic, DIDFT_ABSAXIS, axis, This->joydev->axes[a].value)
 static void CDECL unix_joystick_reset(struct unix_joystick *ptr)
 {
     JoystickImpl *This = impl_from_unix_joystick(ptr);
@@ -773,22 +753,22 @@ static void CDECL unix_joystick_poll(struct unix_joystick *ptr)
         {
             int btn = This->joydev->buttons[ie.code];
             TRACE("(%p) %d -> %d\n", This, ie.code, btn);
-            if (btn & 0x80) win32_funcs->joystick_queue_event(&This->generic, DIDFT_PSHBUTTON, btn & 0x7f, ie.value ? 0x80 : 0x00);
+            if (btn & 0x80) win32_funcs->joystick_queue_event(This->generic, DIDFT_PSHBUTTON, btn & 0x7f, ie.value ? 0x80 : 0x00);
             break;
         }
 	case EV_ABS:
         {
             int axis = This->joydev->dev_axes_to_di[ie.code];
             if (axis < 0) break;
-            axis = win32_funcs->joystick_get_axis(&This->generic, axis);
+            axis = win32_funcs->joystick_get_axis(This->generic, axis);
             if (axis < 0) break;
 
-            if (axis >= 0 && axis < 8) win32_funcs->joystick_queue_event(&This->generic, DIDFT_ABSAXIS, axis, ie.value);
+            if (axis >= 0 && axis < 8) win32_funcs->joystick_queue_event(This->generic, DIDFT_ABSAXIS, axis, ie.value);
             else if (axis >= 8 && axis < 12)
             {
                 if (ie.code % 2) This->povs[axis - 8].y = ie.value;
                 else This->povs[axis - 8].x = ie.value;
-                win32_funcs->joystick_queue_event(&This->generic, DIDFT_POV, axis - 8, joystick_map_pov(&This->povs[axis - 8]));
+                win32_funcs->joystick_queue_event(This->generic, DIDFT_POV, axis - 8, joystick_map_pov(&This->povs[axis - 8]));
             }
             else FIXME("unhandled joystick axis event (code %d, value %d)\n", ie.code, ie.value);
 
@@ -977,42 +957,6 @@ static HRESULT CDECL unix_joystick_ff_send_cmd(struct unix_joystick *ptr, DWORD
 #endif
 }
 
-static const IDirectInputDevice8WVtbl JoystickWvt =
-{
-    IDirectInputDevice2WImpl_QueryInterface,
-    IDirectInputDevice2WImpl_AddRef,
-    IDirectInputDevice2WImpl_Release,
-    JoystickWGenericImpl_GetCapabilities,
-    IDirectInputDevice2WImpl_EnumObjects,
-    JoystickWGenericImpl_GetProperty,
-    JoystickWGenericImpl_SetProperty,
-    JoystickWGenericImpl_Acquire,
-    JoystickWGenericImpl_Unacquire,
-    JoystickWGenericImpl_GetDeviceState,
-    IDirectInputDevice2WImpl_GetDeviceData,
-    IDirectInputDevice2WImpl_SetDataFormat,
-    IDirectInputDevice2WImpl_SetEventNotification,
-    IDirectInputDevice2WImpl_SetCooperativeLevel,
-    JoystickWGenericImpl_GetObjectInfo,
-    IDirectInputDevice2WImpl_GetDeviceInfo,
-    IDirectInputDevice2WImpl_RunControlPanel,
-    IDirectInputDevice2WImpl_Initialize,
-    JoystickWGenericImpl_CreateEffect,
-    JoystickWGenericImpl_EnumEffects,
-    JoystickWGenericImpl_GetEffectInfo,
-    JoystickWGenericImpl_GetForceFeedbackState,
-    JoystickWGenericImpl_SendForceFeedbackCommand,
-    JoystickWGenericImpl_EnumCreatedEffectObjects,
-    IDirectInputDevice2WImpl_Escape,
-    JoystickWGenericImpl_Poll,
-    IDirectInputDevice2WImpl_SendDeviceData,
-    IDirectInputDevice7WImpl_EnumEffectsInFile,
-    IDirectInputDevice7WImpl_WriteEffectToFile,
-    JoystickWGenericImpl_BuildActionMap,
-    JoystickWGenericImpl_SetActionMap,
-    IDirectInputDevice8WImpl_GetImageInfo
-};
-
 #else  /* HAS_PROPER_HEADER */
 
 const struct dinput_device joystick_linuxinput_device = {
diff --git a/dlls/dinput/joystick_osx.c b/dlls/dinput/joystick_osx.c
index 6fad4d3fe52..cb5f3ca1fc5 100644
--- a/dlls/dinput/joystick_osx.c
+++ b/dlls/dinput/joystick_osx.c
@@ -101,11 +101,10 @@ extern const struct win32_funcs *win32_funcs DECLSPEC_HIDDEN;
 static CFMutableArrayRef device_main_elements = NULL;
 
 typedef struct JoystickImpl JoystickImpl;
-static const IDirectInputDevice8WVtbl JoystickWvt;
 
 struct JoystickImpl
 {
-    struct JoystickGenericImpl generic;
+    struct JoystickGenericImpl *generic;
 
     /* osx private */
     int                    id;
@@ -845,7 +844,7 @@ static void CDECL unix_joystick_poll(struct unix_joystick *ptr)
                         if (valueRef == NULL)
                             return;
                         val = IOHIDValueGetIntegerValue(valueRef);
-                        win32_funcs->joystick_queue_event(&device->generic, DIDFT_PSHBUTTON, button_idx, val ? 0x80 : 0x0);
+                        win32_funcs->joystick_queue_event(device->generic, DIDFT_PSHBUTTON, button_idx, val ? 0x80 : 0x0);
                         button_idx ++;
                     }
                     break;
@@ -865,7 +864,7 @@ static void CDECL unix_joystick_poll(struct unix_joystick *ptr)
                             val = IOHIDValueGetIntegerValue(valueRef);
                             if (val >= 8) val = -1;
                             else val = val * 4500;
-                            win32_funcs->joystick_queue_event(&device->generic, DIDFT_POV, pov_idx, val);
+                            win32_funcs->joystick_queue_event(device->generic, DIDFT_POV, pov_idx, val);
                             pov_idx ++;
                             break;
                         }
@@ -887,31 +886,31 @@ static void CDECL unix_joystick_poll(struct unix_joystick *ptr)
                             {
                             case kHIDUsage_GD_X:
                                 TRACE("kIOHIDElementTypeInput_Misc / kHIDUsage_GD_X\n");
-                                win32_funcs->joystick_queue_event(&device->generic, DIDFT_ABSAXIS, 0, val);
+                                win32_funcs->joystick_queue_event(device->generic, DIDFT_ABSAXIS, 0, val);
                                 break;
                             case kHIDUsage_GD_Y:
                                 TRACE("kIOHIDElementTypeInput_Misc / kHIDUsage_GD_Y\n");
-                                win32_funcs->joystick_queue_event(&device->generic, DIDFT_ABSAXIS, 1, val);
+                                win32_funcs->joystick_queue_event(device->generic, DIDFT_ABSAXIS, 1, val);
                                 break;
                             case kHIDUsage_GD_Z:
                                 TRACE("kIOHIDElementTypeInput_Misc / kHIDUsage_GD_Z\n");
-                                win32_funcs->joystick_queue_event(&device->generic, DIDFT_ABSAXIS, 2, val);
+                                win32_funcs->joystick_queue_event(device->generic, DIDFT_ABSAXIS, 2, val);
                                 break;
                             case kHIDUsage_GD_Rx:
                                 TRACE("kIOHIDElementTypeInput_Misc / kHIDUsage_GD_Rx\n");
-                                win32_funcs->joystick_queue_event(&device->generic, DIDFT_ABSAXIS, 3, val);
+                                win32_funcs->joystick_queue_event(device->generic, DIDFT_ABSAXIS, 3, val);
                                 break;
                             case kHIDUsage_GD_Ry:
                                 TRACE("kIOHIDElementTypeInput_Misc / kHIDUsage_GD_Ry\n");
-                                win32_funcs->joystick_queue_event(&device->generic, DIDFT_ABSAXIS, 4, val);
+                                win32_funcs->joystick_queue_event(device->generic, DIDFT_ABSAXIS, 4, val);
                                 break;
                             case kHIDUsage_GD_Rz:
                                 TRACE("kIOHIDElementTypeInput_Misc / kHIDUsage_GD_Rz\n");
-                                win32_funcs->joystick_queue_event(&device->generic, DIDFT_ABSAXIS, 5, val);
+                                win32_funcs->joystick_queue_event(device->generic, DIDFT_ABSAXIS, 5, val);
                                 break;
                             case kHIDUsage_GD_Slider:
                                 TRACE("kIOHIDElementTypeInput_Misc / kHIDUsage_GD_Slider\n");
-                                win32_funcs->joystick_queue_event(&device->generic, DIDFT_ABSAXIS, 6 + slider_idx, val);
+                                win32_funcs->joystick_queue_event(device->generic, DIDFT_ABSAXIS, 6 + slider_idx, val);
                                 slider_idx ++;
                                 break;
                             }
@@ -937,11 +936,13 @@ static HRESULT CDECL unix_joystick_ff_send_cmd(struct unix_joystick *ptr, DWORD
 static HRESULT CDECL unix_joystick_create_effect(struct unix_joystick *ptr, REFGUID guid, DWORD type, const DIEFFECT *params,
         const struct unix_effect_vtbl **vtbl, struct unix_effect **out);
 
-static HRESULT CDECL unix_joystick_init(struct unix_joystick *ptr, ObjProps *props, int *prop_count, BOOL *has_ff);
+static HRESULT CDECL unix_joystick_init(struct unix_joystick *ptr, JoystickGenericImpl *generic, ObjProps *props, int *prop_count, BOOL *has_ff);
+static void CDECL unix_joystick_destroy(struct unix_joystick *ptr);
 
 static const struct unix_joystick_vtbl unix_joystick_vtbl =
 {
     unix_joystick_init,
+    unix_joystick_destroy,
     NULL,
     NULL,
     NULL,
@@ -1070,10 +1071,8 @@ static BOOL osx_axis_has_ff(FFCAPABILITIES *ffcaps, UInt8 axis)
     return FALSE;
 }
 
-static void fill_joystick_dideviceinstanceW(LPDIDEVICEINSTANCEW didi, IOHIDDeviceRef device, DWORD version, int index, const char *name)
+static void fill_joystick_dideviceinstanceA(LPDIDEVICEINSTANCEA didi, IOHIDDeviceRef device, DWORD version, int index, const char *name)
 {
-    char buffer[MAX_PATH];
-
     didi->guidInstance = DInput_Wine_OsX_Joystick_GUID;
     didi->guidInstance.Data3 = index;
     didi->guidProduct = DInput_PIDVID_Product_GUID;
@@ -1081,9 +1080,8 @@ static void fill_joystick_dideviceinstanceW(LPDIDEVICEINSTANCEW didi, IOHIDDevic
     if (version >= 0x0800) didi->dwDevType = DI8DEVTYPE_JOYSTICK | (DI8DEVTYPEJOYSTICK_STANDARD << 8);
     else didi->dwDevType = DIDEVTYPE_JOYSTICK | (DIDEVTYPEJOYSTICK_TRADITIONAL << 8);
 
-    snprintf(buffer, sizeof(buffer), "Joystick %d", index);
-    MultiByteToWideChar(CP_ACP, 0, buffer, -1, didi->tszInstanceName, MAX_PATH);
-    MultiByteToWideChar(CP_ACP, 0, name, -1, didi->tszProductName, MAX_PATH);
+    snprintf(didi->tszInstanceName, sizeof(didi->tszInstanceName), "Joystick %d", index);
+    lstrcpynA(didi->tszProductName,  name, MAX_PATH);
 
     didi->guidFFDriver = GUID_NULL;
     didi->wUsagePage = 0;
@@ -1110,19 +1108,13 @@ static unsigned short get_joystick_index(REFGUID guid)
     return 0xffff;
 }
 
-static HRESULT joydev_create_unix_joystick(IDirectInputImpl *dinput, REFGUID guid, JoystickGenericImpl **out)
+static HRESULT joydev_create_unix_joystick(REFGUID guid, DWORD version, const struct unix_joystick_vtbl **vtbl, struct unix_joystick **ptr, WORD *vid, WORD *pid, WORD *iid, DIDEVICEINSTANCEA *info)
 {
-    DIDEVICEINSTANCEW didi = {sizeof(didi)};
     IOHIDDeviceRef device;
     JoystickImpl* newDevice;
     char name[MAX_PATH];
     unsigned short index;
     int joystick_devices_count;
-    WORD vendor_id, product_id;
-
-    TRACE("%p %s %p\n", dinput, debugstr_guid(guid), out);
-
-    *out = NULL;
 
     if ((joystick_devices_count = find_joystick_devices()) == 0) return DIERR_DEVICENOTREG;
 
@@ -1131,25 +1123,22 @@ static HRESULT joydev_create_unix_joystick(IDirectInputImpl *dinput, REFGUID gui
 
     device = get_device_ref(index);
     get_osx_device_name(index, name, MAX_PATH);
-    vendor_id = get_device_property_long(device, CFSTR(kIOHIDVendorIDKey));
-    product_id = get_device_property_long(device, CFSTR(kIOHIDProductIDKey));
 
-    fill_joystick_dideviceinstanceW(&didi, device, dinput->dwVersion, index, name);
-
-    if (FAILED(hr = direct_input_device_alloc(sizeof(JoystickImpl), &JoystickWvt, guid, vendor_id, product_id, index,
-                       &didi, dinput, (void **)&newDevice)))
-        return hr;
-    newDevice->generic.base.crit.DebugInfo->Spare[0] = (DWORD_PTR)(__FILE__ ": JoystickImpl*->generic.base.crit");
-    newDevice->generic.unix_funcs = &unix_joystick_vtbl;
-    newDevice->generic.unix_ptr = unix_joystick_from_impl(newDevice);
+    fill_joystick_dideviceinstanceA(info, device, version, index, name);
 
+    if (!(newDevice = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*newDevice)))) return DIERR_OUTOFMEMORY;
     newDevice->id = index;
 
-    *out = &newDevice->generic;
+    *vid = get_device_property_long(device, CFSTR(kIOHIDVendorIDKey));
+    *pid = get_device_property_long(device, CFSTR(kIOHIDProductIDKey));
+    *iid = index;
+    *vtbl = &unix_joystick_vtbl;
+    *ptr = unix_joystick_from_impl(newDevice);
+
     return DI_OK;
 }
 
-static HRESULT CDECL unix_joystick_init(struct unix_joystick *ptr, ObjProps *props, int *prop_count, BOOL *has_ff)
+static HRESULT CDECL unix_joystick_init(struct unix_joystick *ptr, JoystickGenericImpl *generic, ObjProps *props, int *prop_count, BOOL *has_ff)
 {
     JoystickImpl *This = impl_from_unix_joystick(ptr);
     IOHIDDeviceRef device;
@@ -1160,6 +1149,7 @@ static HRESULT CDECL unix_joystick_init(struct unix_joystick *ptr, ObjProps *pro
     int axis_map[8]; /* max axes */
 
     device = get_device_ref(This->id);
+    This->generic = generic;
 
     /* get the device name */
     get_osx_device_name(This->id, name, MAX_PATH);
@@ -1206,6 +1196,12 @@ static HRESULT CDECL unix_joystick_init(struct unix_joystick *ptr, ObjProps *pro
     return DI_OK;
 }
 
+static void CDECL unix_joystick_destroy(struct unix_joystick *ptr)
+{
+    JoystickImpl *This = impl_from_unix_joystick(ptr);
+    HeapFree(GetProcessHeap(), 0, This);
+}
+
 static HRESULT CDECL unix_joystick_ff_set_autocenter(struct unix_joystick *ptr, DWORD value)
 {
     JoystickImpl *This = impl_from_unix_joystick(ptr);
@@ -1314,42 +1310,6 @@ const struct dinput_device joystick_osx_device = {
   joydev_create_unix_joystick
 };
 
-static const IDirectInputDevice8WVtbl JoystickWvt =
-{
-    IDirectInputDevice2WImpl_QueryInterface,
-    IDirectInputDevice2WImpl_AddRef,
-    IDirectInputDevice2WImpl_Release,
-    JoystickWGenericImpl_GetCapabilities,
-    IDirectInputDevice2WImpl_EnumObjects,
-    JoystickWGenericImpl_GetProperty,
-    JoystickWGenericImpl_SetProperty,
-    IDirectInputDevice2WImpl_Acquire,
-    IDirectInputDevice2WImpl_Unacquire,
-    JoystickWGenericImpl_GetDeviceState,
-    IDirectInputDevice2WImpl_GetDeviceData,
-    IDirectInputDevice2WImpl_SetDataFormat,
-    IDirectInputDevice2WImpl_SetEventNotification,
-    IDirectInputDevice2WImpl_SetCooperativeLevel,
-    JoystickWGenericImpl_GetObjectInfo,
-    IDirectInputDevice2WImpl_GetDeviceInfo,
-    IDirectInputDevice2WImpl_RunControlPanel,
-    IDirectInputDevice2WImpl_Initialize,
-    JoystickWGenericImpl_CreateEffect,
-    IDirectInputDevice2WImpl_EnumEffects,
-    IDirectInputDevice2WImpl_GetEffectInfo,
-    IDirectInputDevice2WImpl_GetForceFeedbackState,
-    JoystickWGenericImpl_SendForceFeedbackCommand,
-    JoystickWGenericImpl_EnumCreatedEffectObjects,
-    IDirectInputDevice2WImpl_Escape,
-    JoystickWGenericImpl_Poll,
-    IDirectInputDevice2WImpl_SendDeviceData,
-    IDirectInputDevice7WImpl_EnumEffectsInFile,
-    IDirectInputDevice7WImpl_WriteEffectToFile,
-    JoystickWGenericImpl_BuildActionMap,
-    JoystickWGenericImpl_SetActionMap,
-    IDirectInputDevice8WImpl_GetImageInfo
-};
-
 static void CDECL unix_effect_destroy(struct unix_effect *ptr)
 {
     EffectImpl *This = impl_from_unix_effect(ptr);
diff --git a/dlls/dinput/joystick_private.h b/dlls/dinput/joystick_private.h
index 4e5b3eaa245..34f2260173b 100644
--- a/dlls/dinput/joystick_private.h
+++ b/dlls/dinput/joystick_private.h
@@ -31,7 +31,7 @@
 
 /* Number of objects in the default data format */
 #define MAX_PROPS 164
-struct JoystickGenericImpl;
+typedef struct JoystickGenericImpl JoystickGenericImpl;
 
 struct unix_effect;
 
@@ -52,7 +52,8 @@ struct unix_joystick;
 
 struct unix_joystick_vtbl
 {
-    HRESULT (CDECL *init)(struct unix_joystick *ptr, ObjProps *props, int *prop_count, BOOL *has_ff);
+    HRESULT (CDECL *init)(struct unix_joystick *ptr, JoystickGenericImpl *generic, ObjProps *props, int *prop_count, BOOL *has_ff);
+    void (CDECL *destroy)(struct unix_joystick *ptr);
     void (CDECL *reset)(struct unix_joystick *ptr);
 
     void (CDECL *get_mapping)(struct unix_joystick *ptr, int *axis_count, const int **axes_map);
@@ -72,23 +73,6 @@ struct unix_joystick_vtbl
     void (CDECL *poll)(struct unix_joystick *ptr);
 };
 
-typedef struct JoystickGenericImpl
-{
-    struct IDirectInputDeviceImpl base;
-    const struct unix_joystick_vtbl *unix_funcs;
-    struct unix_joystick *unix_ptr;
-
-    ObjProps    props[MAX_PROPS];
-    DIDEVCAPS   devcaps;
-    DIJOYSTATE2 js;     /* wine data */
-    int        *axis_map;               /* User axes remapping */
-    LONG        deadzone;               /* Default dead-zone */
-
-    DWORD ff_autocenter;
-    DWORD ff_gain;
-    struct list ff_effects;
-} JoystickGenericImpl;
-
 extern HRESULT dinput_create_unix_joystick(const struct dinput_device *device, IDirectInputImpl *dinput, REFGUID guid, REFIID iid, void **out) DECLSPEC_HIDDEN;
 
 DWORD joystick_map_pov(const POINTL *p) DECLSPEC_HIDDEN;
@@ -98,42 +82,6 @@ extern BOOL device_disabled_registry(const WCHAR* name) DECLSPEC_HIDDEN;
 extern int CDECL dinput_unix_joystick_get_axis(JoystickGenericImpl *This, int index) DECLSPEC_HIDDEN;
 extern void CDECL dinput_unix_joystick_queue_event(JoystickGenericImpl *This, WORD type, int index, DWORD data) DECLSPEC_HIDDEN;
 
-HRESULT WINAPI JoystickWGenericImpl_GetObjectInfo(LPDIRECTINPUTDEVICE8W iface,
-        LPDIDEVICEOBJECTINSTANCEW pdidoi, DWORD dwObj, DWORD dwHow) DECLSPEC_HIDDEN;
-
-HRESULT WINAPI JoystickWGenericImpl_GetProperty(LPDIRECTINPUTDEVICE8W iface, REFGUID rguid, LPDIPROPHEADER pdiph) DECLSPEC_HIDDEN;
-
-HRESULT WINAPI JoystickWGenericImpl_GetCapabilities(LPDIRECTINPUTDEVICE8W iface, LPDIDEVCAPS lpDIDevCaps) DECLSPEC_HIDDEN;
-
-HRESULT WINAPI JoystickWGenericImpl_SetProperty(LPDIRECTINPUTDEVICE8W iface, REFGUID rguid, LPCDIPROPHEADER ph) DECLSPEC_HIDDEN;
-
-HRESULT WINAPI JoystickWGenericImpl_Acquire(LPDIRECTINPUTDEVICE8W iface) DECLSPEC_HIDDEN;
-
-HRESULT WINAPI JoystickWGenericImpl_Unacquire(LPDIRECTINPUTDEVICE8W iface) DECLSPEC_HIDDEN;
-
-HRESULT WINAPI JoystickWGenericImpl_GetEffectInfo(LPDIRECTINPUTDEVICE8W iface, LPDIEFFECTINFOW pdei, REFGUID rguid) DECLSPEC_HIDDEN;
-
-HRESULT WINAPI JoystickWGenericImpl_EnumEffects(LPDIRECTINPUTDEVICE8W iface, LPDIENUMEFFECTSCALLBACKW lpCallback,
-        LPVOID pvRef, DWORD dwEffType) DECLSPEC_HIDDEN;
-
-HRESULT WINAPI JoystickWGenericImpl_CreateEffect(LPDIRECTINPUTDEVICE8W iface, REFGUID rguid, LPCDIEFFECT lpeff,
-        LPDIRECTINPUTEFFECT *ppdef, LPUNKNOWN pUnkOuter) DECLSPEC_HIDDEN;
-
-HRESULT WINAPI JoystickWGenericImpl_EnumCreatedEffectObjects(LPDIRECTINPUTDEVICE8W iface,
-        LPDIENUMCREATEDEFFECTOBJECTSCALLBACK lpCallback, LPVOID pvRef, DWORD dwFlags) DECLSPEC_HIDDEN;
-
-HRESULT WINAPI JoystickWGenericImpl_GetForceFeedbackState(LPDIRECTINPUTDEVICE8W iface, LPDWORD pdwOut) DECLSPEC_HIDDEN;
-
-HRESULT WINAPI JoystickWGenericImpl_SendForceFeedbackCommand(LPDIRECTINPUTDEVICE8W iface, DWORD dwFlags) DECLSPEC_HIDDEN;
-
-HRESULT WINAPI JoystickWGenericImpl_Poll(LPDIRECTINPUTDEVICE8W iface) DECLSPEC_HIDDEN;
-
-HRESULT WINAPI JoystickWGenericImpl_GetDeviceState(LPDIRECTINPUTDEVICE8W iface, DWORD len, LPVOID ptr) DECLSPEC_HIDDEN;
-
-HRESULT WINAPI JoystickWGenericImpl_BuildActionMap(LPDIRECTINPUTDEVICE8W iface, LPDIACTIONFORMATW lpdiaf, LPCWSTR lpszUserName, DWORD dwFlags) DECLSPEC_HIDDEN;
-
-HRESULT WINAPI JoystickWGenericImpl_SetActionMap(LPDIRECTINPUTDEVICE8W iface, LPDIACTIONFORMATW lpdiaf, LPCWSTR lpszUserName, DWORD dwFlags) DECLSPEC_HIDDEN;
-
 DWORD typeFromGUID(REFGUID guid) DECLSPEC_HIDDEN;
 
 #endif /* __WINE_DLLS_DINPUT_JOYSTICK_PRIVATE_H */
-- 
2.28.0

>From f27e6ba6394ef16ea69c8a5fbef854b1cc37ff39 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?R=C3=A9mi=20Bernon?= <rbernon@codeweavers.com>
Date: Mon, 5 Oct 2020 12:44:48 +0200
Subject: [PATCH 37/39] dinput: Introduce unix_funcs to enumerate unix devices.

---
 dlls/dinput/dinput_main.c         | 30 +++++++++++++++++++++++++++++-
 dlls/dinput/dinput_private.h      | 13 +++++++++----
 dlls/dinput/joystick_linux.c      |  4 ++--
 dlls/dinput/joystick_linuxinput.c |  4 ++--
 dlls/dinput/joystick_osx.c        |  4 ++--
 dlls/dinput/keyboard.c            |  6 +++---
 dlls/dinput/mouse.c               |  4 ++--
 7 files changed, 49 insertions(+), 16 deletions(-)

diff --git a/dlls/dinput/dinput_main.c b/dlls/dinput/dinput_main.c
index 66a65b7b55e..a7341171bcc 100644
--- a/dlls/dinput/dinput_main.c
+++ b/dlls/dinput/dinput_main.c
@@ -75,10 +75,15 @@ static inline IDirectInputDeviceImpl *impl_from_IDirectInputDevice8W(IDirectInpu
     return CONTAINING_RECORD(iface, IDirectInputDeviceImpl, IDirectInputDevice8W_iface);
 }
 
-static const struct dinput_device *dinput_devices[] =
+static const struct dinput_device *dinput_devices[32] =
 {
     &mouse_device,
     &keyboard_device,
+    NULL,
+};
+
+static const struct dinput_device *unix_devices[] =
+{
     &joystick_linuxinput_device,
     &joystick_linux_device,
     &joystick_osx_device
@@ -92,6 +97,20 @@ const struct win32_funcs win32_entry =
 
 const struct win32_funcs *win32_funcs = &win32_entry;
 
+static HRESULT CDECL unix_get_dinput_device(unsigned int index, const struct dinput_device **out)
+{
+    if (index >= ARRAY_SIZE(unix_devices)) return E_FAIL;
+    *out = unix_devices[index];
+    return DI_OK;
+}
+
+const struct unix_funcs unix_entry =
+{
+    unix_get_dinput_device
+};
+
+static const struct unix_funcs *unix_funcs = &unix_entry;
+
 HINSTANCE DINPUT_instance;
 
 static const WCHAR di_em_win_w[] = {'D','I','E','m','W','i','n',0};
@@ -391,6 +410,7 @@ static HRESULT WINAPI IDirectInputWImpl_EnumDevices(
         return DIERR_NOTINITIALIZED;
 
     for (i = 0; i < ARRAY_SIZE(dinput_devices); i++) {
+        if (!dinput_devices[i]) break;
         for (j = 0, r = S_OK; SUCCEEDED(r); j++) {
             devInstance.dwSize = sizeof(devInstance);
             TRACE("  - checking device %u ('%s')\n", i, dinput_devices[i]->name);
@@ -676,6 +696,7 @@ static HRESULT WINAPI IDirectInput7WImpl_CreateDeviceEx(LPDIRECTINPUT7W iface, R
     /* Loop on all the devices to see if anyone matches the given GUID */
     for (i = 0; i < ARRAY_SIZE(dinput_devices); i++)
     {
+        if (!dinput_devices[i]) break;
         if (SUCCEEDED(hr = dinput_create_device(dinput_devices[i], This, rguid, riid, pvOut))) return hr;
     }
 
@@ -828,6 +849,7 @@ static HRESULT WINAPI IDirectInput8WImpl_EnumDevicesBySemantics(
     for (i = 0; i < ARRAY_SIZE(dinput_devices); i++)
     {
         HRESULT enumSuccess;
+        if (!dinput_devices[i]) break;
         for (j = 0, enumSuccess = S_OK; SUCCEEDED(enumSuccess); j++)
         {
             TRACE(" - checking device %u ('%s')\n", i, dinput_devices[i]->name);
@@ -1000,6 +1022,7 @@ static HRESULT WINAPI JoyConfig8Impl_GetConfig(IDirectInputJoyConfig8 *iface, UI
     /* Enumerate all joysticks in order */
     for (i = 0; i < ARRAY_SIZE(dinput_devices); i++)
     {
+        if (!dinput_devices[i]) break;
         for (j = 0, r = S_OK; SUCCEEDED(r); j++)
         {
             DIDEVICEINSTANCEW dev;
@@ -1501,12 +1524,17 @@ void check_dinput_events(void)
 
 BOOL WINAPI DllMain( HINSTANCE inst, DWORD reason, LPVOID reserved)
 {
+    unsigned int i = 0;
+    const struct dinput_device **device = dinput_devices, **device_last = dinput_devices + ARRAY_SIZE(dinput_devices) - 1;
     switch(reason)
     {
       case DLL_PROCESS_ATTACH:
         DisableThreadLibraryCalls(inst);
         DINPUT_instance = inst;
         register_di_em_win_class();
+        while (device < device_last && *device) device++;
+        while (device < device_last && SUCCEEDED(unix_funcs->get_dinput_device(i++, device))) device++;
+        *device = NULL;
         break;
       case DLL_PROCESS_DETACH:
         if (reserved) break;
diff --git a/dlls/dinput/dinput_private.h b/dlls/dinput/dinput_private.h
index 99cc3ce4a1c..22cad3d02cc 100644
--- a/dlls/dinput/dinput_private.h
+++ b/dlls/dinput/dinput_private.h
@@ -61,10 +61,15 @@ struct unix_joystick;
 /* Function called by all devices that Wine supports */
 struct dinput_device {
     const char *name;
-    HRESULT (*enum_deviceA)(DWORD dwDevType, DWORD dwFlags, LPDIDEVICEINSTANCEA lpddi, DWORD version, int id);
-    HRESULT (*enum_deviceW)(DWORD dwDevType, DWORD dwFlags, LPDIDEVICEINSTANCEW lpddi, DWORD version, int id);
-    HRESULT (*create_device)(IDirectInputImpl *dinput, REFGUID rguid, IDirectInputDeviceImpl **out);
-    HRESULT (*create_unix_joystick)(REFGUID guid, DWORD version, const struct unix_joystick_vtbl **vtbl, struct unix_joystick **ptr, WORD *vid, WORD *pid, WORD *iid, DIDEVICEINSTANCEA *info);
+    HRESULT (CDECL *enum_deviceA)(DWORD dwDevType, DWORD dwFlags, LPDIDEVICEINSTANCEA lpddi, DWORD version, int id);
+    HRESULT (CDECL *enum_deviceW)(DWORD dwDevType, DWORD dwFlags, LPDIDEVICEINSTANCEW lpddi, DWORD version, int id);
+    HRESULT (CDECL *create_device)(IDirectInputImpl *dinput, REFGUID rguid, IDirectInputDeviceImpl **out);
+    HRESULT (CDECL *create_unix_joystick)(REFGUID guid, DWORD version, const struct unix_joystick_vtbl **vtbl, struct unix_joystick **ptr, WORD *vid, WORD *pid, WORD *iid, DIDEVICEINSTANCEA *info);
+};
+
+struct unix_funcs
+{
+    HRESULT (CDECL *get_dinput_device)(unsigned int index, const struct dinput_device **out);
 };
 
 typedef struct JoystickGenericImpl JoystickGenericImpl;
diff --git a/dlls/dinput/joystick_linux.c b/dlls/dinput/joystick_linux.c
index a9c57e136de..c5194720e4c 100644
--- a/dlls/dinput/joystick_linux.c
+++ b/dlls/dinput/joystick_linux.c
@@ -395,7 +395,7 @@ static void fill_joystick_dideviceinstanceA(LPDIDEVICEINSTANCEA lpddi, DWORD ver
     lpddi->guidFFDriver = GUID_NULL;
 }
 
-static HRESULT joydev_enum_deviceA(DWORD dwDevType, DWORD dwFlags, LPDIDEVICEINSTANCEA lpddi, DWORD version, int id)
+static HRESULT CDECL joydev_enum_deviceA(DWORD dwDevType, DWORD dwFlags, LPDIDEVICEINSTANCEA lpddi, DWORD version, int id)
 {
     int fd = -1;
 
@@ -444,7 +444,7 @@ static unsigned short get_joystick_index(REFGUID guid)
     return MAX_JOYSTICKS;
 }
 
-static HRESULT joydev_create_unix_joystick(REFGUID guid, DWORD version, const struct unix_joystick_vtbl **vtbl, struct unix_joystick **ptr, WORD *vid, WORD *pid, WORD *iid, DIDEVICEINSTANCEA *info)
+static HRESULT CDECL joydev_create_unix_joystick(REFGUID guid, DWORD version, const struct unix_joystick_vtbl **vtbl, struct unix_joystick **ptr, WORD *vid, WORD *pid, WORD *iid, DIDEVICEINSTANCEA *info)
 {
     struct JoyDev *joydev;
     JoystickImpl *newDevice;
diff --git a/dlls/dinput/joystick_linuxinput.c b/dlls/dinput/joystick_linuxinput.c
index 7c9fdba9418..1e72dd59339 100644
--- a/dlls/dinput/joystick_linuxinput.c
+++ b/dlls/dinput/joystick_linuxinput.c
@@ -445,7 +445,7 @@ static void fill_joystick_dideviceinstanceA(LPDIDEVICEINSTANCEA lpddi, DWORD ver
     lstrcpynA(lpddi->tszProductName,  joydevs[id].name, MAX_PATH);
 }
 
-static HRESULT joydev_enum_deviceA(DWORD dwDevType, DWORD dwFlags, LPDIDEVICEINSTANCEA lpddi, DWORD version, int id)
+static HRESULT CDECL joydev_enum_deviceA(DWORD dwDevType, DWORD dwFlags, LPDIDEVICEINSTANCEA lpddi, DWORD version, int id)
 {
   find_joydevs();
 
@@ -490,7 +490,7 @@ static unsigned short get_joystick_index(REFGUID guid)
     return MAX_JOYDEV;
 }
 
-static HRESULT joydev_create_unix_joystick(REFGUID guid, DWORD version, const struct unix_joystick_vtbl **vtbl, struct unix_joystick **ptr, WORD *vid, WORD *pid, WORD *iid, DIDEVICEINSTANCEA *info)
+static HRESULT CDECL joydev_create_unix_joystick(REFGUID guid, DWORD version, const struct unix_joystick_vtbl **vtbl, struct unix_joystick **ptr, WORD *vid, WORD *pid, WORD *iid, DIDEVICEINSTANCEA *info)
 {
     struct JoyDev *joydev;
     JoystickImpl *newDevice;
diff --git a/dlls/dinput/joystick_osx.c b/dlls/dinput/joystick_osx.c
index cb5f3ca1fc5..ff11e8514a0 100644
--- a/dlls/dinput/joystick_osx.c
+++ b/dlls/dinput/joystick_osx.c
@@ -1001,7 +1001,7 @@ static DWORD make_vid_pid(IOHIDDeviceRef device)
     return MAKELONG(vendID, prodID);
 }
 
-static HRESULT joydev_enum_deviceA(DWORD dwDevType, DWORD dwFlags, LPDIDEVICEINSTANCEA lpddi, DWORD version, int id)
+static HRESULT CDECL joydev_enum_deviceA(DWORD dwDevType, DWORD dwFlags, LPDIDEVICEINSTANCEA lpddi, DWORD version, int id)
 {
     IOHIDDeviceRef device;
     BOOL is_joystick;
@@ -1108,7 +1108,7 @@ static unsigned short get_joystick_index(REFGUID guid)
     return 0xffff;
 }
 
-static HRESULT joydev_create_unix_joystick(REFGUID guid, DWORD version, const struct unix_joystick_vtbl **vtbl, struct unix_joystick **ptr, WORD *vid, WORD *pid, WORD *iid, DIDEVICEINSTANCEA *info)
+static HRESULT CDECL joydev_create_unix_joystick(REFGUID guid, DWORD version, const struct unix_joystick_vtbl **vtbl, struct unix_joystick **ptr, WORD *vid, WORD *pid, WORD *iid, DIDEVICEINSTANCEA *info)
 {
     IOHIDDeviceRef device;
     JoystickImpl* newDevice;
diff --git a/dlls/dinput/keyboard.c b/dlls/dinput/keyboard.c
index b257f2b51c1..c3dc8b9319f 100644
--- a/dlls/dinput/keyboard.c
+++ b/dlls/dinput/keyboard.c
@@ -172,8 +172,8 @@ static void fill_keyboard_dideviceinstanceW(LPDIDEVICEINSTANCEW lpddi, DWORD ver
 
     memcpy(lpddi, &ddi, (dwSize < sizeof(ddi) ? dwSize : sizeof(ddi)));
 }
- 
-static HRESULT keyboarddev_enum_deviceW(DWORD dwDevType, DWORD dwFlags, LPDIDEVICEINSTANCEW lpddi, DWORD version, int id)
+
+static HRESULT CDECL keyboarddev_enum_deviceW(DWORD dwDevType, DWORD dwFlags, LPDIDEVICEINSTANCEW lpddi, DWORD version, int id)
 {
   if (id != 0)
     return E_FAIL;
@@ -238,7 +238,7 @@ failed:
     return NULL;
 }
 
-static HRESULT keyboarddev_create_device(IDirectInputImpl *dinput, REFGUID guid, IDirectInputDeviceImpl **out)
+static HRESULT CDECL keyboarddev_create_device(IDirectInputImpl *dinput, REFGUID guid, IDirectInputDeviceImpl **out)
 {
     TRACE("%p %s %p\n", dinput, debugstr_guid(guid), out);
     *out = NULL;
diff --git a/dlls/dinput/mouse.c b/dlls/dinput/mouse.c
index c436bf5032a..afaa7d14c8e 100644
--- a/dlls/dinput/mouse.c
+++ b/dlls/dinput/mouse.c
@@ -117,7 +117,7 @@ static void fill_mouse_dideviceinstanceW(LPDIDEVICEINSTANCEW lpddi, DWORD versio
     memcpy(lpddi, &ddi, (dwSize < sizeof(ddi) ? dwSize : sizeof(ddi)));
 }
 
-static HRESULT mousedev_enum_deviceW(DWORD dwDevType, DWORD dwFlags, LPDIDEVICEINSTANCEW lpddi, DWORD version, int id)
+static HRESULT CDECL mousedev_enum_deviceW(DWORD dwDevType, DWORD dwFlags, LPDIDEVICEINSTANCEW lpddi, DWORD version, int id)
 {
     if (id != 0)
         return E_FAIL;
@@ -196,7 +196,7 @@ failed:
     return NULL;
 }
 
-static HRESULT mousedev_create_device(IDirectInputImpl *dinput, REFGUID guid, IDirectInputDeviceImpl **out)
+static HRESULT CDECL mousedev_create_device(IDirectInputImpl *dinput, REFGUID guid, IDirectInputDeviceImpl **out)
 {
     TRACE("%p %s %p\n", dinput, debugstr_guid(guid), out);
     *out = NULL;
-- 
2.28.0

>From 999458082bb1bdbfc47e1448db7b681c4ca7d2ce Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?R=C3=A9mi=20Bernon?= <rbernon@codeweavers.com>
Date: Tue, 6 Oct 2020 14:17:10 +0200
Subject: [PATCH 38/39] dinput: Split unix joysticks to a separate unix lib.

---
 dlls/dinput/Makefile.in           |   3 +-
 dlls/dinput/device_private.h      |   2 -
 dlls/dinput/dinput_main.c         |  41 ++----
 dlls/dinput/dinput_private.h      |   3 +-
 dlls/dinput/effect_linuxinput.c   |  14 ++-
 dlls/dinput/joystick.c            |  28 -----
 dlls/dinput/joystick_linux.c      |  13 +-
 dlls/dinput/joystick_linuxinput.c |  17 ++-
 dlls/dinput/joystick_osx.c        |  15 ++-
 dlls/dinput/joystick_private.h    |   4 +-
 dlls/dinput/unixlib.c             | 202 ++++++++++++++++++++++++++++++
 dlls/dinput/unixlib_private.h     |  38 ++++++
 dlls/dinput8/Makefile.in          |   3 +-
 13 files changed, 300 insertions(+), 83 deletions(-)
 create mode 100644 dlls/dinput/unixlib.c
 create mode 100644 dlls/dinput/unixlib_private.h

diff --git a/dlls/dinput/Makefile.in b/dlls/dinput/Makefile.in
index a22c8a72180..5268ce4c3b7 100644
--- a/dlls/dinput/Makefile.in
+++ b/dlls/dinput/Makefile.in
@@ -16,7 +16,8 @@ C_SRCS = \
 	joystick_linuxinput.c \
 	joystick_osx.c \
 	keyboard.c \
-	mouse.c
+	mouse.c \
+	unixlib.c
 
 IDL_SRCS = dinput_classes.idl
 
diff --git a/dlls/dinput/device_private.h b/dlls/dinput/device_private.h
index c244550e105..5611d57e99f 100644
--- a/dlls/dinput/device_private.h
+++ b/dlls/dinput/device_private.h
@@ -119,8 +119,6 @@ typedef struct
     DWORD dwFlags;
 } ObjProps;
 
-extern DWORD joystick_map_pov(const POINTL *p) DECLSPEC_HIDDEN;
-
 extern const GUID DInput_PIDVID_Product_GUID DECLSPEC_HIDDEN;
 
 /* Various debug tools */
diff --git a/dlls/dinput/dinput_main.c b/dlls/dinput/dinput_main.c
index a7341171bcc..05763d0b3f4 100644
--- a/dlls/dinput/dinput_main.c
+++ b/dlls/dinput/dinput_main.c
@@ -38,21 +38,26 @@
 #define COBJMACROS
 #define NONAMELESSUNION
 
-#include "wine/debug.h"
-#include "wine/unicode.h"
-#include "wine/asm.h"
+#include "ntstatus.h"
+#define WIN32_NO_STATUS
 #include "windef.h"
 #include "winbase.h"
 #include "winuser.h"
 #include "winerror.h"
+#include "winternl.h"
 #include "objbase.h"
 #include "rpcproxy.h"
 #include "initguid.h"
 #include "devguid.h"
+#include "dinputd.h"
+
+#include "wine/debug.h"
+#include "wine/unicode.h"
+#include "wine/asm.h"
+
 #include "dinput_private.h"
 #include "device_private.h"
 #include "joystick_private.h"
-#include "dinputd.h"
 
 WINE_DEFAULT_DEBUG_CHANNEL(dinput);
 
@@ -82,35 +87,14 @@ static const struct dinput_device *dinput_devices[32] =
     NULL,
 };
 
-static const struct dinput_device *unix_devices[] =
-{
-    &joystick_linuxinput_device,
-    &joystick_linux_device,
-    &joystick_osx_device
-};
+static const struct unix_funcs *unix_funcs;
 
-const struct win32_funcs win32_entry =
+static const struct win32_funcs win32_funcs =
 {
     dinput_unix_joystick_get_axis,
-    dinput_unix_joystick_queue_event
-};
-
-const struct win32_funcs *win32_funcs = &win32_entry;
-
-static HRESULT CDECL unix_get_dinput_device(unsigned int index, const struct dinput_device **out)
-{
-    if (index >= ARRAY_SIZE(unix_devices)) return E_FAIL;
-    *out = unix_devices[index];
-    return DI_OK;
-}
-
-const struct unix_funcs unix_entry =
-{
-    unix_get_dinput_device
+    dinput_unix_joystick_queue_event,
 };
 
-static const struct unix_funcs *unix_funcs = &unix_entry;
-
 HINSTANCE DINPUT_instance;
 
 static const WCHAR di_em_win_w[] = {'D','I','E','m','W','i','n',0};
@@ -1526,6 +1510,7 @@ BOOL WINAPI DllMain( HINSTANCE inst, DWORD reason, LPVOID reserved)
 {
     unsigned int i = 0;
     const struct dinput_device **device = dinput_devices, **device_last = dinput_devices + ARRAY_SIZE(dinput_devices) - 1;
+    if (__wine_init_unix_lib(inst, reason, &win32_funcs, &unix_funcs)) return FALSE;
     switch(reason)
     {
       case DLL_PROCESS_ATTACH:
diff --git a/dlls/dinput/dinput_private.h b/dlls/dinput/dinput_private.h
index 22cad3d02cc..030d7f3ead1 100644
--- a/dlls/dinput/dinput_private.h
+++ b/dlls/dinput/dinput_private.h
@@ -25,7 +25,9 @@
 #include "winbase.h"
 #include "dinput.h"
 #include "dinputd.h"
+
 #include "wine/list.h"
+#include "wine/debug.h"
 
 extern HINSTANCE DINPUT_instance;
 
@@ -109,7 +111,6 @@ extern void check_dinput_events(void) DECLSPEC_HIDDEN;
 extern HRESULT _configure_devices(IDirectInput8W *iface, LPDICONFIGUREDEVICESCALLBACK lpdiCallback, LPDICONFIGUREDEVICESPARAMSW lpdiCDParams, DWORD dwFlags, LPVOID pvRefData) DECLSPEC_HIDDEN;
 
 extern WCHAR* get_mapping_path(const WCHAR *device, const WCHAR *username) DECLSPEC_HIDDEN;
-extern DWORD get_device_type(DWORD version, BOOL is_joystick) DECLSPEC_HIDDEN;
 
 #define IS_DIPROP(x)    (((ULONG_PTR)(x) >> 16) == 0)
 
diff --git a/dlls/dinput/effect_linuxinput.c b/dlls/dinput/effect_linuxinput.c
index 640b527c4e2..dcd4f5be1e0 100644
--- a/dlls/dinput/effect_linuxinput.c
+++ b/dlls/dinput/effect_linuxinput.c
@@ -19,7 +19,12 @@
  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
  */
 
+#if 0
+#pragma makedep unix
+#endif
+
 #include "config.h"
+#include "wine/port.h"
 
 #ifdef HAVE_STRUCT_FF_EFFECT_DIRECTION
 
@@ -44,6 +49,7 @@
 
 #include "device_private.h"
 #include "joystick_private.h"
+#include "unixlib_private.h"
 
 WINE_DEFAULT_DEBUG_CHANNEL(dinput);
 
@@ -685,7 +691,7 @@ static void CDECL unix_effect_destroy(struct unix_effect *ptr)
 {
     unix_effect_stop(ptr);
     unix_effect_unload(ptr);
-    HeapFree(GetProcessHeap(), 0, ptr);
+    free(ptr);
 }
 
 static const struct unix_effect_vtbl unix_effect_vtbl =
@@ -725,7 +731,7 @@ DECLSPEC_HIDDEN HRESULT linuxinput_create_effect(int *fd, REFGUID rguid, DWORD t
         return DIERR_INVALIDPARAM;
     }
 
-    if (!(newEffect = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*newEffect))))
+    if (!(newEffect = calloc(1, sizeof(*newEffect))))
         return DIERR_OUTOFMEMORY;
 
     newEffect->fd = fd;
@@ -777,7 +783,7 @@ DECLSPEC_HIDDEN HRESULT linuxinput_create_effect(int *fd, REFGUID rguid, DWORD t
             DIEP_STARTDELAY | DIEP_TRIGGERBUTTON | DIEP_TRIGGERREPEATINTERVAL | DIEP_TYPESPECIFICPARAMS);
     if (hr != DI_OK && hr != DI_DOWNLOADSKIPPED)
     {
-        HeapFree(GetProcessHeap(), 0, newEffect);
+        free(newEffect);
         return hr;
     }
 
@@ -796,7 +802,7 @@ DECLSPEC_HIDDEN HRESULT linuxinput_get_info_A(
 {
     DWORD type = typeFromGUID(rguid);
 
-    TRACE("(%d, %s, %p) type=%d\n", fd, _dump_dinput_GUID(rguid), info, type);
+    TRACE("(%d, %s, %p) type=%d\n", fd, debugstr_guid(rguid), info, type);
 
     if (!info) return E_POINTER;
 
diff --git a/dlls/dinput/joystick.c b/dlls/dinput/joystick.c
index 2e28c0cacee..66ce63eb8e9 100644
--- a/dlls/dinput/joystick.c
+++ b/dlls/dinput/joystick.c
@@ -273,16 +273,6 @@ DWORD typeFromGUID(REFGUID guid)
     }
 }
 
-DWORD get_device_type(DWORD version, BOOL is_joystick)
-{
-    if (is_joystick)
-        return version >= 0x0800 ? DI8DEVTYPE_JOYSTICK | (DI8DEVTYPEJOYSTICK_STANDARD << 8) :
-                    DIDEVTYPE_JOYSTICK | (DIDEVTYPEJOYSTICK_TRADITIONAL << 8);
-
-    return version >= 0x0800 ? DI8DEVTYPE_GAMEPAD | (DI8DEVTYPEJOYSTICK_STANDARD << 8) :
-                DIDEVTYPE_JOYSTICK | (DIDEVTYPEJOYSTICK_GAMEPAD << 8);
-}
-
 static void _dump_DIEFFECT_flags(DWORD dwFlags)
 {
     if (TRACE_ON(dinput)) {
@@ -1204,24 +1194,6 @@ static LONG joystick_map_axis(ObjProps *props, int val)
     return ret;
 }
 
-/*
- * Maps POV x & y event values to a DX "clock" position:
- *         0
- *   31500    4500
- * 27000  -1    9000
- *   22500   13500
- *       18000
- */
-DWORD joystick_map_pov(const POINTL *p)
-{
-    if (p->x > 0)
-        return p->y < 0 ?  4500 : !p->y ?  9000 : 13500;
-    else if (p->x < 0)
-        return p->y < 0 ? 31500 : !p->y ? 27000 : 22500;
-    else
-        return p->y < 0 ?     0 : !p->y ?    -1 : 18000;
-}
-
 /*
  * Setup the dinput options.
  */
diff --git a/dlls/dinput/joystick_linux.c b/dlls/dinput/joystick_linux.c
index c5194720e4c..0e7bcef352a 100644
--- a/dlls/dinput/joystick_linux.c
+++ b/dlls/dinput/joystick_linux.c
@@ -25,6 +25,10 @@
  *	force feedback
  */
 
+#if 0
+#pragma makedep unix
+#endif
+
 #include "config.h"
 #include "wine/port.h"
 
@@ -65,6 +69,7 @@
 #include "dinput_private.h"
 #include "device_private.h"
 #include "joystick_private.h"
+#include "unixlib_private.h"
 
 #ifdef HAVE_LINUX_22_JOYSTICK_API
 
@@ -348,9 +353,9 @@ static INT find_joystick_devices(void)
         close(fd);
 
         if (!joystick_devices_count)
-            new_joydevs = HeapAlloc(GetProcessHeap(), 0, sizeof(struct JoyDev));
+            new_joydevs = malloc(sizeof(struct JoyDev));
         else
-            new_joydevs = HeapReAlloc(GetProcessHeap(), 0, joystick_devices,
+            new_joydevs = realloc(joystick_devices,
                                       (joystick_devices_count + 1) * sizeof(struct JoyDev));
         if (!new_joydevs) continue;
 
@@ -458,7 +463,7 @@ static HRESULT CDECL joydev_create_unix_joystick(REFGUID guid, DWORD version, co
 
     fill_joystick_dideviceinstanceA(info, version, index);
 
-    if (!(newDevice = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*newDevice)))) return DIERR_OUTOFMEMORY;
+    if (!(newDevice = calloc(1, sizeof(*newDevice)))) return DIERR_OUTOFMEMORY;
     newDevice->joydev = joydev;
     newDevice->joyfd = -1;
 
@@ -506,7 +511,7 @@ static HRESULT CDECL unix_joystick_init(struct unix_joystick *ptr, JoystickGener
 static void CDECL unix_joystick_destroy(struct unix_joystick *ptr)
 {
     JoystickImpl *This = impl_from_unix_joystick(ptr);
-    HeapFree(GetProcessHeap(), 0, This);
+    free(This);
 }
 
 #undef MAX_JOYSTICKS
diff --git a/dlls/dinput/joystick_linuxinput.c b/dlls/dinput/joystick_linuxinput.c
index 1e72dd59339..e964a4ca863 100644
--- a/dlls/dinput/joystick_linuxinput.c
+++ b/dlls/dinput/joystick_linuxinput.c
@@ -20,6 +20,10 @@
  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
  */
 
+#if 0
+#pragma makedep unix
+#endif
+
 #include "config.h"
 #include "wine/port.h"
 
@@ -63,6 +67,7 @@
 #include "dinput_private.h"
 #include "device_private.h"
 #include "joystick_private.h"
+#include "unixlib_private.h"
 
 #ifdef HAS_PROPER_HEADER
 
@@ -290,7 +295,7 @@ static void find_joydevs(void)
             test_bit(joydev.keybits, BTN_GEAR_DOWN) ||
             test_bit(joydev.keybits, BTN_DEAD);
 
-        if (!(joydev.device = HeapAlloc(GetProcessHeap(), 0, strlen(buf) + 1)))
+        if (!(joydev.device = malloc(strlen(buf) + 1)))
         {
             close(fd);
             continue;
@@ -299,7 +304,7 @@ static void find_joydevs(void)
 
         buf[MAX_PATH - 1] = 0;
         if (ioctl(fd, EVIOCGNAME(MAX_PATH - 1), buf) != -1 &&
-            (joydev.name = HeapAlloc(GetProcessHeap(), 0, strlen(buf) + strlen(EVDEVDRIVER) + 1)))
+            (joydev.name = malloc(strlen(buf) + strlen(EVDEVDRIVER) + 1)))
         {
             strcpy(joydev.name, buf);
             /* Append driver name */
@@ -399,9 +404,9 @@ static void find_joydevs(void)
         }
 
         if (!have_joydevs)
-            new_joydevs = HeapAlloc(GetProcessHeap(), 0, sizeof(struct JoyDev));
+            new_joydevs = malloc(sizeof(struct JoyDev));
         else
-            new_joydevs = HeapReAlloc(GetProcessHeap(), 0, joydevs, (1 + have_joydevs) * sizeof(struct JoyDev));
+            new_joydevs = realloc(joydevs, (1 + have_joydevs) * sizeof(struct JoyDev));
 
         if (!new_joydevs)
         {
@@ -504,7 +509,7 @@ static HRESULT CDECL joydev_create_unix_joystick(REFGUID guid, DWORD version, co
 
     fill_joystick_dideviceinstanceA(info, version, index);
 
-    if (!(newDevice = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*newDevice)))) return DIERR_OUTOFMEMORY;
+    if (!(newDevice = calloc(1, sizeof(*newDevice)))) return DIERR_OUTOFMEMORY;
     newDevice->joyfd       = -1;
     newDevice->joydev = joydev;
 
@@ -593,7 +598,7 @@ static HRESULT CDECL unix_joystick_init(struct unix_joystick *ptr, JoystickGener
 static void CDECL unix_joystick_destroy(struct unix_joystick *ptr)
 {
     JoystickImpl *This = impl_from_unix_joystick(ptr);
-    HeapFree(GetProcessHeap(), 0, This);
+    free(This);
 }
 
 const struct dinput_device joystick_linuxinput_device = {
diff --git a/dlls/dinput/joystick_osx.c b/dlls/dinput/joystick_osx.c
index ff11e8514a0..406ea715c47 100644
--- a/dlls/dinput/joystick_osx.c
+++ b/dlls/dinput/joystick_osx.c
@@ -20,6 +20,10 @@
  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
  */
 
+#if 0
+#pragma makedep unix
+#endif
+
 #include "config.h"
 #include "wine/port.h"
 
@@ -91,6 +95,7 @@
 #include "dinput_private.h"
 #include "device_private.h"
 #include "joystick_private.h"
+#include "unixlib_private.h"
 
 #ifdef HAVE_IOHIDMANAGERCREATE
 
@@ -1126,7 +1131,7 @@ static HRESULT CDECL joydev_create_unix_joystick(REFGUID guid, DWORD version, co
 
     fill_joystick_dideviceinstanceA(info, device, version, index, name);
 
-    if (!(newDevice = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*newDevice)))) return DIERR_OUTOFMEMORY;
+    if (!(newDevice = calloc(1, sizeof(*newDevice)))) return DIERR_OUTOFMEMORY;
     newDevice->id = index;
 
     *vid = get_device_property_long(device, CFSTR(kIOHIDVendorIDKey));
@@ -1199,7 +1204,7 @@ static HRESULT CDECL unix_joystick_init(struct unix_joystick *ptr, JoystickGener
 static void CDECL unix_joystick_destroy(struct unix_joystick *ptr)
 {
     JoystickImpl *This = impl_from_unix_joystick(ptr);
-    HeapFree(GetProcessHeap(), 0, This);
+    free(This);
 }
 
 static HRESULT CDECL unix_joystick_ff_set_autocenter(struct unix_joystick *ptr, DWORD value)
@@ -1264,7 +1269,7 @@ static HRESULT CDECL unix_joystick_create_effect(struct unix_joystick *ptr, REFG
         return DIERR_UNSUPPORTED;
     }
 
-    if (!(effect = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*effect)))) return DIERR_OUTOFMEMORY;
+    if (!(effect = calloc(1, sizeof(*effect)))) return DIERR_OUTOFMEMORY;
     effect->device = This;
 
     /* Mac's FFEFFECT and Win's DIEFFECT are binary identical. */
@@ -1272,7 +1277,7 @@ static HRESULT CDECL unix_joystick_create_effect(struct unix_joystick *ptr, REFG
                 effect_win_to_mac(guid), (FFEFFECT*)params, &effect->effect));
     if(FAILED(hr)){
         WARN("FFDeviceCreateEffect failed: %08x\n", hr);
-        HeapFree(GetProcessHeap(), 0, effect);
+        free(effect);
         return hr;
     }
 
@@ -1314,7 +1319,7 @@ static void CDECL unix_effect_destroy(struct unix_effect *ptr)
 {
     EffectImpl *This = impl_from_unix_effect(ptr);
     FFDeviceReleaseEffect(This->device->ff, This->effect);
-    HeapFree(GetProcessHeap(), 0, This);
+    free(This);
 }
 
 static HRESULT CDECL unix_effect_get_parameters(struct unix_effect *ptr, DIEFFECT *effect, DWORD flags)
diff --git a/dlls/dinput/joystick_private.h b/dlls/dinput/joystick_private.h
index 34f2260173b..1d331d7fdef 100644
--- a/dlls/dinput/joystick_private.h
+++ b/dlls/dinput/joystick_private.h
@@ -75,13 +75,11 @@ struct unix_joystick_vtbl
 
 extern HRESULT dinput_create_unix_joystick(const struct dinput_device *device, IDirectInputImpl *dinput, REFGUID guid, REFIID iid, void **out) DECLSPEC_HIDDEN;
 
-DWORD joystick_map_pov(const POINTL *p) DECLSPEC_HIDDEN;
-
 extern BOOL device_disabled_registry(const WCHAR* name) DECLSPEC_HIDDEN;
 
 extern int CDECL dinput_unix_joystick_get_axis(JoystickGenericImpl *This, int index) DECLSPEC_HIDDEN;
 extern void CDECL dinput_unix_joystick_queue_event(JoystickGenericImpl *This, WORD type, int index, DWORD data) DECLSPEC_HIDDEN;
 
-DWORD typeFromGUID(REFGUID guid) DECLSPEC_HIDDEN;
+extern DWORD typeFromGUID(REFGUID guid) DECLSPEC_HIDDEN;
 
 #endif /* __WINE_DLLS_DINPUT_JOYSTICK_PRIVATE_H */
diff --git a/dlls/dinput/unixlib.c b/dlls/dinput/unixlib.c
new file mode 100644
index 00000000000..cbf7c9a31d0
--- /dev/null
+++ b/dlls/dinput/unixlib.c
@@ -0,0 +1,202 @@
+/*
+ * Unix library entry points
+ *
+ * Copyright 2020 Rémi Bernon for CodeWeavers
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+#if 0
+#pragma makedep unix
+#endif
+
+#include "config.h"
+#include "wine/port.h"
+
+#include <assert.h>
+#include <stdarg.h>
+#include <string.h>
+#include <stdlib.h>
+
+#include "ntstatus.h"
+#define WIN32_NO_STATUS
+#include "windef.h"
+#include "winternl.h"
+#include "initguid.h"
+
+#include "wine/debug.h"
+
+#include "unixlib_private.h"
+
+WINE_DEFAULT_DEBUG_CHANNEL(dinput);
+
+/* Windows uses this GUID for guidProduct on non-keyboard/mouse devices.
+ * Data1 contains the device VID (low word) and PID (high word).
+ * Data4 ends with the ASCII bytes "PIDVID".
+ */
+DEFINE_GUID(DInput_PIDVID_Product_GUID,0x00000000,0x0000,0x0000,0x00,0x00,0x50,0x49,0x44,0x56,0x49,0x44);
+DEFINE_GUID(GUID_NULL,0,0,0,0,0,0,0,0,0,0,0);
+
+static const struct dinput_device *unix_devices[] =
+{
+    &joystick_linuxinput_device,
+    &joystick_linux_device,
+    &joystick_osx_device
+};
+
+static HRESULT CDECL unix_get_dinput_device(unsigned int index, const struct dinput_device **out)
+{
+    TRACE("index %d, out %p.\n", index, out);
+    if (index >= ARRAY_SIZE(unix_devices)) return E_FAIL;
+    *out = unix_devices[index];
+    return DI_OK;
+}
+
+const struct win32_funcs *win32_funcs;
+const struct unix_funcs unix_funcs =
+{
+    unix_get_dinput_device
+};
+
+NTSTATUS CDECL __wine_init_unix_lib( HMODULE module, DWORD reason, const void *ptr_in, void *ptr_out )
+{
+    TRACE("module %p, reason %d, ptr_in %p, ptr_out %p.\n", module, reason, ptr_in, ptr_out);
+    if (reason != DLL_PROCESS_ATTACH) return STATUS_SUCCESS;
+    win32_funcs = (const struct win32_funcs *)ptr_in;
+    *(const struct unix_funcs **)ptr_out = &unix_funcs;
+    return STATUS_SUCCESS;
+}
+
+const char *_dump_dinput_GUID(const GUID *guid) {
+    unsigned int i;
+    static const struct {
+	const GUID *guid;
+	const char *name;
+    } guids[] = {
+#define FE(x) { &x, #x}
+	FE(GUID_XAxis),
+	FE(GUID_YAxis),
+	FE(GUID_ZAxis),
+	FE(GUID_RxAxis),
+	FE(GUID_RyAxis),
+	FE(GUID_RzAxis),
+	FE(GUID_Slider),
+	FE(GUID_Button),
+	FE(GUID_Key),
+	FE(GUID_POV),
+	FE(GUID_Unknown),
+	FE(GUID_SysMouse),
+	FE(GUID_SysKeyboard),
+	FE(GUID_Joystick),
+	FE(GUID_ConstantForce),
+	FE(GUID_RampForce),
+	FE(GUID_Square),
+	FE(GUID_Sine),
+	FE(GUID_Triangle),
+	FE(GUID_SawtoothUp),
+	FE(GUID_SawtoothDown),
+	FE(GUID_Spring),
+	FE(GUID_Damper),
+	FE(GUID_Inertia),
+	FE(GUID_Friction),
+	FE(GUID_CustomForce)
+#undef FE
+    };
+    if (guid == NULL)
+	return "null GUID";
+    for (i = 0; i < ARRAY_SIZE(guids); i++) {
+	if (IsEqualGUID(guids[i].guid, guid)) {
+	    return guids[i].name;
+	}
+    }
+    return debugstr_guid(guid);
+}
+
+DWORD typeFromGUID(REFGUID guid)
+{
+    if (IsEqualGUID(guid, &GUID_ConstantForce)) {
+        return DIEFT_CONSTANTFORCE;
+    } else if (IsEqualGUID(guid, &GUID_Square)
+            || IsEqualGUID(guid, &GUID_Sine)
+            || IsEqualGUID(guid, &GUID_Triangle)
+            || IsEqualGUID(guid, &GUID_SawtoothUp)
+            || IsEqualGUID(guid, &GUID_SawtoothDown)) {
+        return DIEFT_PERIODIC;
+    } else if (IsEqualGUID(guid, &GUID_RampForce)) {
+        return DIEFT_RAMPFORCE;
+    } else if (IsEqualGUID(guid, &GUID_Spring)
+            || IsEqualGUID(guid, &GUID_Damper)
+            || IsEqualGUID(guid, &GUID_Inertia)
+            || IsEqualGUID(guid, &GUID_Friction)) {
+        return DIEFT_CONDITION;
+    } else if (IsEqualGUID(guid, &GUID_CustomForce)) {
+        return DIEFT_CUSTOMFORCE;
+    } else {
+        WARN("GUID (%s) is not a known force type\n", _dump_dinput_GUID(guid));
+        return 0;
+    }
+}
+
+INT WINAPI MulDiv( INT nMultiplicand, INT nMultiplier, INT nDivisor)
+{
+    LONGLONG ret;
+
+    if (!nDivisor) return -1;
+
+    /* We want to deal with a positive divisor to simplify the logic. */
+    if (nDivisor < 0)
+    {
+      nMultiplicand = - nMultiplicand;
+      nDivisor = -nDivisor;
+    }
+
+    /* If the result is positive, we "add" to round. else, we subtract to round. */
+    if ( ( (nMultiplicand <  0) && (nMultiplier <  0) ) ||
+         ( (nMultiplicand >= 0) && (nMultiplier >= 0) ) )
+      ret = (((LONGLONG)nMultiplicand * nMultiplier) + (nDivisor/2)) / nDivisor;
+    else
+      ret = (((LONGLONG)nMultiplicand * nMultiplier) - (nDivisor/2)) / nDivisor;
+
+    if ((ret > 2147483647) || (ret < -2147483647)) return -1;
+    return ret;
+}
+
+/*
+ * Maps POV x & y event values to a DX "clock" position:
+ *         0
+ *   31500    4500
+ * 27000  -1    9000
+ *   22500   13500
+ *       18000
+ */
+DWORD joystick_map_pov(const POINTL *p)
+{
+    if (p->x > 0)
+        return p->y < 0 ?  4500 : !p->y ?  9000 : 13500;
+    else if (p->x < 0)
+        return p->y < 0 ? 31500 : !p->y ? 27000 : 22500;
+    else
+        return p->y < 0 ?     0 : !p->y ?    -1 : 18000;
+}
+
+DWORD get_device_type(DWORD version, BOOL is_joystick)
+{
+    if (is_joystick)
+        return version >= 0x0800 ? DI8DEVTYPE_JOYSTICK | (DI8DEVTYPEJOYSTICK_STANDARD << 8) :
+                    DIDEVTYPE_JOYSTICK | (DIDEVTYPEJOYSTICK_TRADITIONAL << 8);
+
+    return version >= 0x0800 ? DI8DEVTYPE_GAMEPAD | (DI8DEVTYPEJOYSTICK_STANDARD << 8) :
+                DIDEVTYPE_JOYSTICK | (DIDEVTYPEJOYSTICK_GAMEPAD << 8);
+}
diff --git a/dlls/dinput/unixlib_private.h b/dlls/dinput/unixlib_private.h
new file mode 100644
index 00000000000..f330896d685
--- /dev/null
+++ b/dlls/dinput/unixlib_private.h
@@ -0,0 +1,38 @@
+/*
+ * Copyright 2020, Rémi Bernon for CodeWeavers
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+#ifndef __WINE_DLLS_DINPUT_UNIXLIB_PRIVATE_H
+#define __WINE_DLLS_DINPUT_UNIXLIB_PRIVATE_H
+
+#include <stdarg.h>
+
+#include "windef.h"
+#include "winbase.h"
+#include "dinput.h"
+#include "wine/list.h"
+#include "wine/unicode.h"
+
+#include "dinput_private.h"
+#include "device_private.h"
+
+extern INT WINAPI MulDiv(INT nMultiplicand, INT nMultiplier, INT nDivisor) DECLSPEC_HIDDEN;
+extern DWORD joystick_map_pov(const POINTL *p) DECLSPEC_HIDDEN;
+extern DWORD typeFromGUID(REFGUID guid) DECLSPEC_HIDDEN;
+extern DWORD get_device_type(DWORD version, BOOL is_joystick) DECLSPEC_HIDDEN;
+
+#endif /* __WINE_DLLS_DINPUT_UNIXLIB_PRIVATE_H */
diff --git a/dlls/dinput8/Makefile.in b/dlls/dinput8/Makefile.in
index 35b3bfb75f5..774f8e0f20a 100644
--- a/dlls/dinput8/Makefile.in
+++ b/dlls/dinput8/Makefile.in
@@ -17,7 +17,8 @@ C_SRCS = \
 	joystick_linuxinput.c \
 	joystick_osx.c \
 	keyboard.c \
-	mouse.c
+	mouse.c \
+	unixlib.c
 
 IDL_SRCS = dinput8.idl
 
-- 
2.28.0

>From 6a812ff779fd3fe94245a151b10a677159586b14 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?R=C3=A9mi=20Bernon?= <rbernon@codeweavers.com>
Date: Mon, 5 Oct 2020 12:44:48 +0200
Subject: [PATCH 39/39] dinput: Build with msvcrt.

---
 dlls/dinput/Makefile.in        |  2 ++
 dlls/dinput/config.c           |  1 -
 dlls/dinput/device.c           | 20 +++++++++++---------
 dlls/dinput/dinput_main.c      |  2 --
 dlls/dinput/joystick.c         | 14 +++++++-------
 dlls/dinput/joystick_private.h |  3 ++-
 dlls/dinput/keyboard.c         |  7 ++-----
 dlls/dinput/mouse.c            | 13 +++++--------
 dlls/dinput8/Makefile.in       |  3 +++
 9 files changed, 32 insertions(+), 33 deletions(-)

diff --git a/dlls/dinput/Makefile.in b/dlls/dinput/Makefile.in
index 5268ce4c3b7..0fb463ab1ff 100644
--- a/dlls/dinput/Makefile.in
+++ b/dlls/dinput/Makefile.in
@@ -4,6 +4,8 @@ IMPORTS   = dinput dxguid uuid comctl32 ole32 user32 advapi32
 EXTRADEFS = -DDIRECTINPUT_VERSION=0x0700
 EXTRALIBS = $(IOKIT_LIBS) $(FORCEFEEDBACK_LIBS)
 
+EXTRADLLFLAGS = -mno-cygwin
+
 C_SRCS = \
 	ansi.c \
 	config.c \
diff --git a/dlls/dinput/config.c b/dlls/dinput/config.c
index bf448985893..45cd0d63349 100644
--- a/dlls/dinput/config.c
+++ b/dlls/dinput/config.c
@@ -18,7 +18,6 @@
 
 #define NONAMELESSUNION
 
-#include "wine/unicode.h"
 #include "objbase.h"
 #include "dinput_private.h"
 #include "device_private.h"
diff --git a/dlls/dinput/device.c b/dlls/dinput/device.c
index 9f3e5af836e..5564de1ad5f 100644
--- a/dlls/dinput/device.c
+++ b/dlls/dinput/device.c
@@ -24,19 +24,21 @@
 
    It also contains all the helper functions.
 */
-#include "config.h"
 
 #include <stdarg.h>
 #include <string.h>
 #include <assert.h>
-#include "wine/debug.h"
-#include "wine/unicode.h"
+
 #include "windef.h"
 #include "winbase.h"
+#include "winnls.h"
 #include "winreg.h"
 #include "winuser.h"
 #include "winerror.h"
 #include "dinput.h"
+
+#include "wine/debug.h"
+
 #include "device_private.h"
 #include "dinput_private.h"
 #include "joystick_private.h"
@@ -660,10 +662,10 @@ static HKEY get_mapping_key(const WCHAR *device, const WCHAR *username, const WC
         'M','a','p','p','i','n','g','s','\\','%','s','\\','%','s','\\','%','s','\0'};
     HKEY hkey;
     WCHAR *keyname;
+    SIZE_T len = lstrlenW(subkey) + lstrlenW(username) + lstrlenW(device) + lstrlenW(guid);
 
-    keyname = HeapAlloc(GetProcessHeap(), 0,
-        sizeof(WCHAR) * (lstrlenW(subkey) + strlenW(username) + strlenW(device) + strlenW(guid)));
-    sprintfW(keyname, subkey, username, device, guid);
+    keyname = HeapAlloc(GetProcessHeap(), 0, sizeof(WCHAR) * len);
+    swprintf(keyname, len, subkey, username, device, guid);
 
     /* The key used is HKCU\Software\Wine\DirectInput\Mappings\[username]\[device]\[mapping_guid] */
     if (RegCreateKeyW(HKEY_CURRENT_USER, keyname, &hkey))
@@ -706,8 +708,8 @@ static HRESULT save_mapping_settings(IDirectInputDevice8W *iface, LPDIACTIONFORM
         if (IsEqualGUID(&didev.guidInstance, &lpdiaf->rgoAction[i].guidInstance) &&
             lpdiaf->rgoAction[i].dwHow != DIAH_UNMAPPED)
         {
-             sprintfW(label, format, lpdiaf->rgoAction[i].dwSemantic);
-             RegSetValueExW(hkey, label, 0, REG_DWORD, (const BYTE*) &lpdiaf->rgoAction[i].dwObjID, sizeof(DWORD));
+            swprintf(label, ARRAY_SIZE(label), format, lpdiaf->rgoAction[i].dwSemantic);
+            RegSetValueExW(hkey, label, 0, REG_DWORD, (const BYTE *)&lpdiaf->rgoAction[i].dwObjID, sizeof(DWORD));
         }
     }
 
@@ -745,7 +747,7 @@ static BOOL load_mapping_settings(IDirectInputDeviceImpl *This, LPDIACTIONFORMAT
         DWORD id, size = sizeof(DWORD);
         WCHAR label[9];
 
-        sprintfW(label, format, lpdiaf->rgoAction[i].dwSemantic);
+        swprintf(label, ARRAY_SIZE(label), format, lpdiaf->rgoAction[i].dwSemantic);
 
         if (!RegQueryValueExW(hkey, label, 0, NULL, (LPBYTE) &id, &size))
         {
diff --git a/dlls/dinput/dinput_main.c b/dlls/dinput/dinput_main.c
index 05763d0b3f4..498e60e55b2 100644
--- a/dlls/dinput/dinput_main.c
+++ b/dlls/dinput/dinput_main.c
@@ -30,7 +30,6 @@
  * - Fallout : works great in X and DGA mode
  */
 
-#include "config.h"
 #include <assert.h>
 #include <stdarg.h>
 #include <string.h>
@@ -52,7 +51,6 @@
 #include "dinputd.h"
 
 #include "wine/debug.h"
-#include "wine/unicode.h"
 #include "wine/asm.h"
 
 #include "dinput_private.h"
diff --git a/dlls/dinput/joystick.c b/dlls/dinput/joystick.c
index 66ce63eb8e9..44732df0f2f 100644
--- a/dlls/dinput/joystick.c
+++ b/dlls/dinput/joystick.c
@@ -482,7 +482,7 @@ BOOL device_disabled_registry(const WCHAR* name)
 
     /* Look for the "controllername"="disabled" key */
     if (!get_config_key_w(hkey, appkey, name, buffer, sizeof(buffer)))
-        if (!strcmpW(disabled_str, buffer))
+        if (!lstrcmpW(disabled_str, buffer))
         {
             TRACE("Disabling joystick '%s' based on registry key.\n", debugstr_w(name));
             do_disable = TRUE;
@@ -790,12 +790,12 @@ static HRESULT WINAPI JoystickWGenericImpl_GetObjectInfo(LPDIRECTINPUTDEVICE8W i
     if (res != DI_OK) return res;
 
     if (pdidoi->dwType & DIDFT_AXIS) {
-        sprintfW(pdidoi->tszName, axisW, DIDFT_GETINSTANCE(pdidoi->dwType));
+        swprintf(pdidoi->tszName, MAX_PATH, axisW, DIDFT_GETINSTANCE(pdidoi->dwType));
         pdidoi->dwFlags |= DIDOI_ASPECTPOSITION;
-    } else if (pdidoi->dwType & DIDFT_POV)
-        sprintfW(pdidoi->tszName, povW, DIDFT_GETINSTANCE(pdidoi->dwType));
+    }
+    else if (pdidoi->dwType & DIDFT_POV) swprintf(pdidoi->tszName, MAX_PATH, povW, DIDFT_GETINSTANCE(pdidoi->dwType));
     else if (pdidoi->dwType & DIDFT_BUTTON)
-        sprintfW(pdidoi->tszName, buttonW, DIDFT_GETINSTANCE(pdidoi->dwType));
+        swprintf(pdidoi->tszName, MAX_PATH, buttonW, DIDFT_GETINSTANCE(pdidoi->dwType));
 
     _dump_OBJECTINSTANCEW(pdidoi);
     return res;
@@ -893,8 +893,8 @@ static HRESULT WINAPI JoystickWGenericImpl_GetProperty(LPDIRECTINPUTDEVICE8W ifa
             if (!This->base.vendor_id || !This->base.product_id) return DIERR_UNSUPPORTED;
             is_gamepad = is_xinput_device(&This->devcaps, This->base.vendor_id, This->base.product_id);
             pd->guidClass = GUID_DEVCLASS_HIDCLASS;
-            sprintfW(pd->wszPath, formatW, This->base.vendor_id, This->base.product_id, is_gamepad ? igW : miW,
-                    This->base.instance_id);
+            swprintf(pd->wszPath, MAX_PATH, formatW, This->base.vendor_id, This->base.product_id,
+                    is_gamepad ? igW : miW, This->base.instance_id);
 
             TRACE("guidandpath(%s, %s): returning fake path\n", debugstr_guid(&pd->guidClass), debugstr_w(pd->wszPath));
             return DI_OK;
diff --git a/dlls/dinput/joystick_private.h b/dlls/dinput/joystick_private.h
index 1d331d7fdef..92288224496 100644
--- a/dlls/dinput/joystick_private.h
+++ b/dlls/dinput/joystick_private.h
@@ -24,8 +24,9 @@
 #include "windef.h"
 #include "winbase.h"
 #include "dinput.h"
+
 #include "wine/list.h"
-#include "wine/unicode.h"
+
 #include "dinput_private.h"
 #include "device_private.h"
 
diff --git a/dlls/dinput/keyboard.c b/dlls/dinput/keyboard.c
index c3dc8b9319f..88ecb4a2c49 100644
--- a/dlls/dinput/keyboard.c
+++ b/dlls/dinput/keyboard.c
@@ -20,9 +20,6 @@
  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
  */
 
-#include "config.h"
-#include "wine/port.h"
-
 #include <stdarg.h>
 #include <string.h>
 #include "windef.h"
@@ -31,10 +28,10 @@
 #include "winerror.h"
 #include "dinput.h"
 
+#include "wine/debug.h"
+
 #include "dinput_private.h"
 #include "device_private.h"
-#include "wine/debug.h"
-#include "wine/unicode.h"
 
 WINE_DEFAULT_DEBUG_CHANNEL(dinput);
 
diff --git a/dlls/dinput/mouse.c b/dlls/dinput/mouse.c
index afaa7d14c8e..3d06d7fff56 100644
--- a/dlls/dinput/mouse.c
+++ b/dlls/dinput/mouse.c
@@ -19,9 +19,6 @@
  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
  */
 
-#include "config.h"
-#include "wine/port.h"
-
 #include <stdarg.h>
 #include <string.h>
 
@@ -34,10 +31,10 @@
 #include "winreg.h"
 #include "dinput.h"
 
+#include "wine/debug.h"
+
 #include "dinput_private.h"
 #include "device_private.h"
-#include "wine/debug.h"
-#include "wine/unicode.h"
 
 WINE_DEFAULT_DEBUG_CHANNEL(dinput);
 
@@ -683,9 +680,9 @@ static HRESULT WINAPI SysMouseWImpl_GetObjectInfo(LPDIRECTINPUTDEVICE8W iface,
     res = IDirectInputDevice2WImpl_GetObjectInfo(iface, pdidoi, dwObj, dwHow);
     if (res != DI_OK) return res;
 
-    if      (IsEqualGUID(&pdidoi->guidType, &GUID_XAxis)) strcpyW(pdidoi->tszName, x_axisW);
-    else if (IsEqualGUID(&pdidoi->guidType, &GUID_YAxis)) strcpyW(pdidoi->tszName, y_axisW);
-    else if (IsEqualGUID(&pdidoi->guidType, &GUID_ZAxis)) strcpyW(pdidoi->tszName, wheelW);
+    if (IsEqualGUID(&pdidoi->guidType, &GUID_XAxis)) lstrcpyW(pdidoi->tszName, x_axisW);
+    else if (IsEqualGUID(&pdidoi->guidType, &GUID_YAxis)) lstrcpyW(pdidoi->tszName, y_axisW);
+    else if (IsEqualGUID(&pdidoi->guidType, &GUID_ZAxis)) lstrcpyW(pdidoi->tszName, wheelW);
     else if (pdidoi->dwType & DIDFT_BUTTON)
         wsprintfW(pdidoi->tszName, buttonW, DIDFT_GETINSTANCE(pdidoi->dwType) - 3);
 
diff --git a/dlls/dinput8/Makefile.in b/dlls/dinput8/Makefile.in
index 774f8e0f20a..a71987b0cee 100644
--- a/dlls/dinput8/Makefile.in
+++ b/dlls/dinput8/Makefile.in
@@ -3,6 +3,9 @@ IMPORTLIB = dinput8
 IMPORTS   = dinput8 dxguid uuid comctl32 ole32 user32 advapi32
 EXTRADEFS = -DDIRECTINPUT_VERSION=0x0800
 EXTRALIBS = $(IOKIT_LIBS) $(FORCEFEEDBACK_LIBS)
+
+EXTRADLLFLAGS = -mno-cygwin
+
 PARENTSRC = ../dinput
 
 C_SRCS = \
-- 
2.28.0

