diff --git a/patches/patchinstall.sh b/patches/patchinstall.sh
index 25924f24..e6414a3d 100755
--- a/patches/patchinstall.sh
+++ b/patches/patchinstall.sh
@@ -1451,11 +1451,18 @@ if test "$enable_wineboot_ProxySettings" -eq 1; then
 	enable_wineboot_drivers_etc_Stubs=1
 fi
 
-if test "$enable_windows_media_speech_dll" -eq 1; then
-	if test "$enable_windows_gaming_input_dll" -gt 1; then
-		abort "Patchset windows.gaming.input-dll disabled, but windows.media.speech.dll depends on that."
+if test "$enable_windows_gaming_input_dll" -eq 1; then
+	if test "$enable_windows_media_speech_dll" -gt 1; then
+		abort "Patchset windows.media.speech.dll disabled, but windows.gaming.input-dll depends on that."
 	fi
-	enable_windows_gaming_input_dll=1
+	enable_windows_media_speech_dll=1
+fi
+
+if test "$enable_windows_media_speech_dll" -eq 1; then
+	if test "$enable_widl_winrt_support" -gt 1; then
+		abort "Patchset widl-winrt-support disabled, but windows.media.speech.dll depends on that."
+	fi
+	enable_widl_winrt_support=1
 fi
 
 if test "$enable_uxtheme_GTK_Theming" -eq 1; then
@@ -4356,26 +4363,10 @@ if test "$enable_widl_winrt_support" -eq 1; then
 	patch_apply widl-winrt-support/0028-include-Add-IVectorView-HSTRING-declaration-to-windo.patch
 fi
 
-# Patchset windows.gaming.input-dll
-# |
-# | This patchset fixes the following Wine bugs:
-# |   *	[#49756] windows.gaming.input: New DLL
-# |
-# | Modified files:
-# |   *	configure.ac, dlls/windows.gaming.input.dll/Makefile.in, dlls/windows.gaming.input.dll/windows.gaming.input.spec,
-# | 	dlls/windows.gaming.input.dll/windows.gaming.input_main.c, loader/wine.inf.in
-# |
-if test "$enable_windows_gaming_input_dll" -eq 1; then
-	patch_apply windows.gaming.input-dll/0001-windows.gaming.input-Add-stub-dll.patch
-	patch_apply windows.gaming.input-dll/0002-windows.gaming.input-Implement-IActivationFactory-st.patch
-	patch_apply windows.gaming.input-dll/0003-windows.gaming.input-Implement-IGamepadStatics-stubs.patch
-	patch_apply windows.gaming.input-dll/0004-windows.gaming.input-Implement-IRawGameControllerSta.patch
-fi
-
 # Patchset windows.media.speech.dll
 # |
 # | This patchset has the following (direct or indirect) dependencies:
-# |   *	windows.gaming.input-dll
+# |   *	widl-winrt-support
 # |
 # | This patchset fixes the following Wine bugs:
 # |   *	[#49740] windows.media.speech: New DLL
@@ -4391,6 +4382,32 @@ if test "$enable_windows_media_speech_dll" -eq 1; then
 	patch_apply windows.media.speech.dll/0004-windows.media.speech-Fake-empty-IInstalledVoicesStat.patch
 fi
 
+# Patchset windows.gaming.input-dll
+# |
+# | This patchset has the following (direct or indirect) dependencies:
+# |   *	widl-winrt-support, windows.media.speech.dll
+# |
+# | This patchset fixes the following Wine bugs:
+# |   *	[#49756] windows.gaming.input: New DLL
+# |
+# | Modified files:
+# |   *	configure.ac, dlls/windows.gaming.input.dll/Makefile.in, dlls/windows.gaming.input.dll/windows.gaming.input.spec,
+# | 	dlls/windows.gaming.input.dll/windows.gaming.input_main.c, include/Makefile.in, include/asyncinfo.idl,
+# | 	include/windows.foundation.idl, include/windows.gaming.input.forcefeedback.idl, include/windows.gaming.input.idl,
+# | 	include/windows.system.idl, loader/wine.inf.in
+# |
+if test "$enable_windows_gaming_input_dll" -eq 1; then
+	patch_apply windows.gaming.input-dll/0001-windows.gaming.input-Add-stub-dll.patch
+	patch_apply windows.gaming.input-dll/0002-windows.gaming.input-Implement-IGamepadStatics-stubs.patch
+	patch_apply windows.gaming.input-dll/0003-windows.gaming.input-Implement-IGamepadStatics-Gamep.patch
+	patch_apply windows.gaming.input-dll/0004-windows.gaming.input-Fake-empty-IGamepadStatics-Game.patch
+	patch_apply windows.gaming.input-dll/0005-windows.gaming.input-Fake-IEventHandler_Gamepad-supp.patch
+	patch_apply windows.gaming.input-dll/0006-windows.gaming.input-Implement-IRawGameControllerSta.patch
+	patch_apply windows.gaming.input-dll/0007-windows.gaming.input-Implement-IRawGameControllerSta.patch
+	patch_apply windows.gaming.input-dll/0008-windows.gaming.input-Fake-empty-IRawGameControllerSt.patch
+	patch_apply windows.gaming.input-dll/0009-windows.gaming.input-Fake-IEventHandler_RawGameContr.patch
+fi
+
 # Patchset windowscodecs-GIF_Encoder
 # |
 # | Modified files:
diff --git a/patches/windows.gaming.input-dll/0001-windows.gaming.input-Add-stub-dll.patch b/patches/windows.gaming.input-dll/0001-windows.gaming.input-Add-stub-dll.patch
index ca3adfeb..66a04e25 100644
--- a/patches/windows.gaming.input-dll/0001-windows.gaming.input-Add-stub-dll.patch
+++ b/patches/windows.gaming.input-dll/0001-windows.gaming.input-Add-stub-dll.patch
@@ -1,50 +1,47 @@
-From 42c3691a1a3f4124a819dbde46a41eedc94bb17e Mon Sep 17 00:00:00 2001
+From 0a5e3bf90552df0bbf21ecec922bd91fe8a27a3a Mon Sep 17 00:00:00 2001
 From: =?UTF-8?q?R=C3=A9mi=20Bernon?= <rbernon@codeweavers.com>
-Date: Fri, 21 Aug 2020 08:58:32 +0200
-Subject: [PATCH 1/4] windows.gaming.input: Add stub dll.
-MIME-Version: 1.0
-Content-Type: text/plain; charset=UTF-8
-Content-Transfer-Encoding: 8bit
+Date: Fri, 9 Oct 2020 13:38:18 +0200
+Subject: [PATCH 1/9] windows.gaming.input: Add stub dll.
 
-Signed-off-by: Rémi Bernon <rbernon@codeweavers.com>
 ---
- configure.ac                                  |  1 +
- dlls/windows.gaming.input.dll/Makefile.in     |  7 +++
- .../windows.gaming.input.spec                 |  3 ++
- .../windows.gaming.input_main.c               | 54 +++++++++++++++++++
- 4 files changed, 65 insertions(+)
+ configure.ac                                  |   1 +
+ dlls/windows.gaming.input.dll/Makefile.in     |   5 +
+ .../windows.gaming.input.spec                 |   3 +
+ .../windows.gaming.input_main.c               | 140 ++++++++++++++++++
+ include/Makefile.in                           |   1 +
+ include/windows.gaming.input.idl              |  24 +++
+ 6 files changed, 174 insertions(+)
  create mode 100644 dlls/windows.gaming.input.dll/Makefile.in
  create mode 100644 dlls/windows.gaming.input.dll/windows.gaming.input.spec
  create mode 100644 dlls/windows.gaming.input.dll/windows.gaming.input_main.c
+ create mode 100644 include/windows.gaming.input.idl
 
 diff --git a/configure.ac b/configure.ac
-index 61142f73e6..82fc6817be 100644
+index a8649a2e40b..3e717d5191f 100644
 --- a/configure.ac
 +++ b/configure.ac
-@@ -3837,6 +3837,7 @@ WINE_CONFIG_MAKEFILE(dlls/win32s16.dll16,enable_win16)
+@@ -3822,6 +3822,7 @@ WINE_CONFIG_MAKEFILE(dlls/win32s16.dll16,enable_win16)
  WINE_CONFIG_MAKEFILE(dlls/win87em.dll16,enable_win16)
  WINE_CONFIG_MAKEFILE(dlls/winaspi.dll16,enable_win16)
  WINE_CONFIG_MAKEFILE(dlls/windebug.dll16,enable_win16)
 +WINE_CONFIG_MAKEFILE(dlls/windows.gaming.input.dll)
+ WINE_CONFIG_MAKEFILE(dlls/windows.media.speech.dll)
  WINE_CONFIG_MAKEFILE(dlls/windowscodecs)
  WINE_CONFIG_MAKEFILE(dlls/windowscodecs/tests)
- WINE_CONFIG_MAKEFILE(dlls/windowscodecsext)
 diff --git a/dlls/windows.gaming.input.dll/Makefile.in b/dlls/windows.gaming.input.dll/Makefile.in
 new file mode 100644
-index 0000000000..782d81ad34
+index 00000000000..d9478342294
 --- /dev/null
 +++ b/dlls/windows.gaming.input.dll/Makefile.in
-@@ -0,0 +1,7 @@
-+MODULE    = windows.gaming.input.dll
-+IMPORTS   = combase uuid
-+
+@@ -0,0 +1,5 @@
++MODULE = windows.gaming.input.dll
++IMPORTS = combase uuid
 +EXTRADLLFLAGS = -mno-cygwin
-+
 +C_SRCS = \
 +	windows.gaming.input_main.c
 diff --git a/dlls/windows.gaming.input.dll/windows.gaming.input.spec b/dlls/windows.gaming.input.dll/windows.gaming.input.spec
 new file mode 100644
-index 0000000000..20a8bfa98e
+index 00000000000..20a8bfa98ea
 --- /dev/null
 +++ b/dlls/windows.gaming.input.dll/windows.gaming.input.spec
 @@ -0,0 +1,3 @@
@@ -53,10 +50,10 @@ index 0000000000..20a8bfa98e
 +@ stdcall -private DllGetClassObject(ptr ptr ptr)
 diff --git a/dlls/windows.gaming.input.dll/windows.gaming.input_main.c b/dlls/windows.gaming.input.dll/windows.gaming.input_main.c
 new file mode 100644
-index 0000000000..3c12a83e6b
+index 00000000000..2b6abc4dd84
 --- /dev/null
 +++ b/dlls/windows.gaming.input.dll/windows.gaming.input_main.c
-@@ -0,0 +1,54 @@
+@@ -0,0 +1,140 @@
 +#include <stdarg.h>
 +
 +#define COBJMACROS
@@ -64,9 +61,13 @@ index 0000000000..3c12a83e6b
 +#include "winbase.h"
 +#include "winstring.h"
 +#include "wine/debug.h"
-+#include "activation.h"
 +#include "objbase.h"
++
 +#include "initguid.h"
++#include "activation.h"
++
++#include "windows.foundation.h"
++#include "windows.gaming.input.h"
 +
 +WINE_DEFAULT_DEBUG_CHANNEL(input);
 +
@@ -79,38 +80,162 @@ index 0000000000..3c12a83e6b
 +    return wine_dbgstr_wn(str, len);
 +}
 +
-+BOOL WINAPI DllMain(HINSTANCE instance, DWORD reason, void *reserved)
++struct windows_gaming_input
 +{
-+    TRACE("(%p, %u, %p)\n", instance, reason, reserved);
++    IActivationFactory IActivationFactory_iface;
++    LONG ref;
++};
 +
-+    switch (reason)
++static inline struct windows_gaming_input *impl_from_IActivationFactory(IActivationFactory *iface)
++{
++    return CONTAINING_RECORD(iface, struct windows_gaming_input, IActivationFactory_iface);
++}
++
++static HRESULT STDMETHODCALLTYPE windows_gaming_input_QueryInterface(
++        IActivationFactory *iface, REFIID iid, void **out)
++{
++    struct windows_gaming_input *impl = impl_from_IActivationFactory(iface);
++    TRACE("iface %p, iid %s, out %p stub!\n", iface, debugstr_guid(iid), out);
++
++    if (IsEqualGUID(iid, &IID_IUnknown) ||
++        IsEqualGUID(iid, &IID_IInspectable) ||
++        IsEqualGUID(iid, &IID_IActivationFactory))
 +    {
-+    case DLL_WINE_PREATTACH:
-+        return FALSE;    /* prefer native version */
-+    case DLL_PROCESS_ATTACH:
-+        DisableThreadLibraryCalls(instance);
-+        break;
++        IUnknown_AddRef(iface);
++        *out = &impl->IActivationFactory_iface;
++        return S_OK;
 +    }
 +
-+    return TRUE;
++    FIXME("%s not implemented, returning E_NOINTERFACE.\n", debugstr_guid(iid));
++    *out = NULL;
++    return E_NOINTERFACE;
 +}
 +
++static ULONG STDMETHODCALLTYPE windows_gaming_input_AddRef(
++        IActivationFactory *iface)
++{
++    struct windows_gaming_input *impl = impl_from_IActivationFactory(iface);
++    ULONG ref = InterlockedIncrement(&impl->ref);
++    TRACE("iface %p, ref %u.\n", iface, ref);
++    return ref;
++}
++
++static ULONG STDMETHODCALLTYPE windows_gaming_input_Release(
++        IActivationFactory *iface)
++{
++    struct windows_gaming_input *impl = impl_from_IActivationFactory(iface);
++    ULONG ref = InterlockedDecrement(&impl->ref);
++    TRACE("iface %p, ref %u.\n", iface, ref);
++    return ref;
++}
++
++static HRESULT STDMETHODCALLTYPE windows_gaming_input_GetIids(
++        IActivationFactory *iface, ULONG *iid_count, IID **iids)
++{
++    FIXME("iface %p, iid_count %p, iids %p stub!\n", iface, iid_count, iids);
++    return E_NOTIMPL;
++}
++
++static HRESULT STDMETHODCALLTYPE windows_gaming_input_GetRuntimeClassName(
++        IActivationFactory *iface, HSTRING *class_name)
++{
++    FIXME("iface %p, class_name %p stub!\n", iface, class_name);
++    return E_NOTIMPL;
++}
++
++static HRESULT STDMETHODCALLTYPE windows_gaming_input_GetTrustLevel(
++        IActivationFactory *iface, TrustLevel *trust_level)
++{
++    FIXME("iface %p, trust_level %p stub!\n", iface, trust_level);
++    return E_NOTIMPL;
++}
++
++static HRESULT STDMETHODCALLTYPE windows_gaming_input_ActivateInstance(
++        IActivationFactory *iface, IInspectable **instance)
++{
++    FIXME("iface %p, instance %p stub!\n", iface, instance);
++    return E_NOTIMPL;
++}
++
++static const struct IActivationFactoryVtbl activation_factory_vtbl =
++{
++    windows_gaming_input_QueryInterface,
++    windows_gaming_input_AddRef,
++    windows_gaming_input_Release,
++    /* IInspectable methods */
++    windows_gaming_input_GetIids,
++    windows_gaming_input_GetRuntimeClassName,
++    windows_gaming_input_GetTrustLevel,
++    /* IActivationFactory methods */
++    windows_gaming_input_ActivateInstance,
++};
++
++static struct windows_gaming_input windows_gaming_input =
++{
++    {&activation_factory_vtbl},
++    0
++};
++
 +HRESULT WINAPI DllCanUnloadNow(void)
 +{
 +    return S_FALSE;
 +}
 +
-+HRESULT WINAPI DllGetClassObject(REFCLSID clsid, REFIID riid, LPVOID *object)
++HRESULT WINAPI DllGetClassObject(REFCLSID clsid, REFIID riid, void **out)
 +{
-+    FIXME("clsid %s, riid %s, object %p stub!\n", debugstr_guid(clsid), debugstr_guid(riid), object);
++    FIXME("clsid %s, riid %s, out %p stub!\n", debugstr_guid(clsid), debugstr_guid(riid), out);
 +    return CLASS_E_CLASSNOTAVAILABLE;
 +}
 +
 +HRESULT WINAPI DllGetActivationFactory(HSTRING classid, IActivationFactory **factory)
 +{
-+    FIXME("classid %s, factory %p stub!\n", debugstr_hstring(classid), factory);
-+    return E_NOINTERFACE;
++    TRACE("classid %s, factory %p.\n", debugstr_hstring(classid), factory);
++    *factory = &windows_gaming_input.IActivationFactory_iface;
++    IUnknown_AddRef(*factory);
++    return S_OK;
 +}
+diff --git a/include/Makefile.in b/include/Makefile.in
+index 91297753b12..8ae1091b8b7 100644
+--- a/include/Makefile.in
++++ b/include/Makefile.in
+@@ -735,6 +735,7 @@ SOURCES = \
+ 	windef.h \
+ 	windns.h \
+ 	windows.foundation.idl \
++	windows.gaming.input.idl \
+ 	windows.media.speechsynthesis.idl \
+ 	windows.h \
+ 	windowscontracts.idl \
+diff --git a/include/windows.gaming.input.idl b/include/windows.gaming.input.idl
+new file mode 100644
+index 00000000000..575f34ccb58
+--- /dev/null
++++ b/include/windows.gaming.input.idl
+@@ -0,0 +1,24 @@
++/*
++ * 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
++ */
++
++#ifdef __WIDL__
++#pragma winrt ns_prefix
++#endif
++
++import "inspectable.idl";
++import "windows.foundation.idl";
 -- 
 2.28.0
 
diff --git a/patches/windows.gaming.input-dll/0002-windows.gaming.input-Implement-IActivationFactory-st.patch b/patches/windows.gaming.input-dll/0002-windows.gaming.input-Implement-IActivationFactory-st.patch
deleted file mode 100644
index 2c21ed1b..00000000
--- a/patches/windows.gaming.input-dll/0002-windows.gaming.input-Implement-IActivationFactory-st.patch
+++ /dev/null
@@ -1,122 +0,0 @@
-From 46168d502a9677f29960fdd3f5bbacf1f35f0f6e Mon Sep 17 00:00:00 2001
-From: =?UTF-8?q?R=C3=A9mi=20Bernon?= <rbernon@codeweavers.com>
-Date: Fri, 21 Aug 2020 08:58:33 +0200
-Subject: [PATCH 2/4] windows.gaming.input: Implement IActivationFactory stubs.
-MIME-Version: 1.0
-Content-Type: text/plain; charset=UTF-8
-Content-Transfer-Encoding: 8bit
-
-Signed-off-by: Rémi Bernon <rbernon@codeweavers.com>
----
- .../windows.gaming.input_main.c               | 90 ++++++++++++++++++-
- 1 file changed, 88 insertions(+), 2 deletions(-)
-
-diff --git a/dlls/windows.gaming.input.dll/windows.gaming.input_main.c b/dlls/windows.gaming.input.dll/windows.gaming.input_main.c
-index 3c12a83e6b..f345fbffb5 100644
---- a/dlls/windows.gaming.input.dll/windows.gaming.input_main.c
-+++ b/dlls/windows.gaming.input.dll/windows.gaming.input_main.c
-@@ -20,6 +20,90 @@ static const char *debugstr_hstring(HSTRING hstr)
-     return wine_dbgstr_wn(str, len);
- }
- 
-+struct windows_gaming_input
-+{
-+    IActivationFactory IActivationFactory_iface;
-+    LONG refcount;
-+};
-+
-+static inline struct windows_gaming_input *impl_from_IActivationFactory(IActivationFactory *iface)
-+{
-+    return CONTAINING_RECORD(iface, struct windows_gaming_input, IActivationFactory_iface);
-+}
-+
-+static HRESULT STDMETHODCALLTYPE windows_gaming_input_QueryInterface(
-+        IActivationFactory *iface, REFIID iid, void **object)
-+{
-+    TRACE("iface %p, iid %s, object %p stub!\n", iface, debugstr_guid(iid), object);
-+    *object = NULL;
-+    return E_NOINTERFACE;
-+}
-+
-+static ULONG STDMETHODCALLTYPE windows_gaming_input_AddRef(
-+        IActivationFactory *iface)
-+{
-+    struct windows_gaming_input *impl = impl_from_IActivationFactory(iface);
-+    ULONG rc = InterlockedIncrement(&impl->refcount);
-+    TRACE("%p increasing refcount to %u.\n", impl, rc);
-+    return rc;
-+}
-+
-+static ULONG STDMETHODCALLTYPE windows_gaming_input_Release(
-+        IActivationFactory *iface)
-+{
-+    struct windows_gaming_input *impl = impl_from_IActivationFactory(iface);
-+    ULONG rc = InterlockedDecrement(&impl->refcount);
-+    TRACE("%p decreasing refcount to %u.\n", impl, rc);
-+    return rc;
-+}
-+
-+static HRESULT STDMETHODCALLTYPE windows_gaming_input_GetIids(
-+        IActivationFactory *iface, ULONG *iid_count, IID **iids)
-+{
-+    FIXME("iface %p, iid_count %p, iids %p stub!\n", iface, iid_count, iids);
-+    return E_NOTIMPL;
-+}
-+
-+static HRESULT STDMETHODCALLTYPE windows_gaming_input_GetRuntimeClassName(
-+        IActivationFactory *iface, HSTRING *class_name)
-+{
-+    FIXME("iface %p, class_name %p stub!\n", iface, class_name);
-+    return E_NOTIMPL;
-+}
-+
-+static HRESULT STDMETHODCALLTYPE windows_gaming_input_GetTrustLevel(
-+        IActivationFactory *iface, TrustLevel *trust_level)
-+{
-+    FIXME("iface %p, trust_level %p stub!\n", iface, trust_level);
-+    return E_NOTIMPL;
-+}
-+
-+static HRESULT STDMETHODCALLTYPE windows_gaming_input_ActivateInstance(
-+        IActivationFactory *iface, IInspectable **instance)
-+{
-+    FIXME("iface %p, instance %p stub!\n", iface, instance);
-+    return E_NOTIMPL;
-+}
-+
-+static const struct IActivationFactoryVtbl activation_factory_vtbl =
-+{
-+    windows_gaming_input_QueryInterface,
-+    windows_gaming_input_AddRef,
-+    windows_gaming_input_Release,
-+    /* IInspectable methods */
-+    windows_gaming_input_GetIids,
-+    windows_gaming_input_GetRuntimeClassName,
-+    windows_gaming_input_GetTrustLevel,
-+    /* IActivationFactory methods */
-+    windows_gaming_input_ActivateInstance,
-+};
-+
-+static struct windows_gaming_input windows_gaming_input =
-+{
-+    {&activation_factory_vtbl},
-+    0
-+};
-+
- BOOL WINAPI DllMain(HINSTANCE instance, DWORD reason, void *reserved)
- {
-     TRACE("(%p, %u, %p)\n", instance, reason, reserved);
-@@ -49,6 +133,8 @@ HRESULT WINAPI DllGetClassObject(REFCLSID clsid, REFIID riid, LPVOID *object)
- 
- HRESULT WINAPI DllGetActivationFactory(HSTRING classid, IActivationFactory **factory)
- {
--    FIXME("classid %s, factory %p stub!\n", debugstr_hstring(classid), factory);
--    return E_NOINTERFACE;
-+    TRACE("classid %s, factory %p.\n", debugstr_hstring(classid), factory);
-+    *factory = &windows_gaming_input.IActivationFactory_iface;
-+    IUnknown_AddRef(*factory);
-+    return S_OK;
- }
--- 
-2.28.0
-
diff --git a/patches/windows.gaming.input-dll/0002-windows.gaming.input-Implement-IGamepadStatics-stubs.patch b/patches/windows.gaming.input-dll/0002-windows.gaming.input-Implement-IGamepadStatics-stubs.patch
new file mode 100644
index 00000000..51491bab
--- /dev/null
+++ b/patches/windows.gaming.input-dll/0002-windows.gaming.input-Implement-IGamepadStatics-stubs.patch
@@ -0,0 +1,358 @@
+From b24e0e059c1734c3a9d287d0be1450c2b29cc259 Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?R=C3=A9mi=20Bernon?= <rbernon@codeweavers.com>
+Date: Mon, 12 Oct 2020 12:50:32 +0200
+Subject: [PATCH 2/9] windows.gaming.input: Implement IGamepadStatics stubs.
+
+---
+ .../windows.gaming.input_main.c               | 127 +++++++++++++++++
+ include/windows.foundation.idl                |  11 ++
+ include/windows.gaming.input.idl              | 128 ++++++++++++++++++
+ loader/wine.inf.in                            |   1 +
+ 4 files changed, 267 insertions(+)
+
+diff --git a/dlls/windows.gaming.input.dll/windows.gaming.input_main.c b/dlls/windows.gaming.input.dll/windows.gaming.input_main.c
+index 2b6abc4dd84..33c260b27b3 100644
+--- a/dlls/windows.gaming.input.dll/windows.gaming.input_main.c
++++ b/dlls/windows.gaming.input.dll/windows.gaming.input_main.c
+@@ -10,6 +10,10 @@
+ #include "initguid.h"
+ #include "activation.h"
+ 
++#define WIDL_USING_IVECTORVIEW_1_WINDOWS_GAMING_INPUT_GAMEPAD
++#define WIDL_USING_IEVENTHANDLER_1_WINDOWS_GAMING_INPUT_GAMEPAD
++#define WIDL_USING_WINDOWS_GAMING_INPUT_IGAMEPAD
++#define WIDL_USING_WINDOWS_GAMING_INPUT_IGAMEPADSTATICS
+ #include "windows.foundation.h"
+ #include "windows.gaming.input.h"
+ 
+@@ -27,6 +31,7 @@ static const char *debugstr_hstring(HSTRING hstr)
+ struct windows_gaming_input
+ {
+     IActivationFactory IActivationFactory_iface;
++    IGamepadStatics IGamepadStatics_iface;
+     LONG ref;
+ };
+ 
+@@ -35,6 +40,120 @@ static inline struct windows_gaming_input *impl_from_IActivationFactory(IActivat
+     return CONTAINING_RECORD(iface, struct windows_gaming_input, IActivationFactory_iface);
+ }
+ 
++static inline struct windows_gaming_input *impl_from_IGamepadStatics(IGamepadStatics *iface)
++{
++    return CONTAINING_RECORD(iface, struct windows_gaming_input, IGamepadStatics_iface);
++}
++
++static HRESULT STDMETHODCALLTYPE gamepad_statics_QueryInterface(
++        IGamepadStatics *iface, REFIID iid, void **out)
++{
++    TRACE("iface %p, iid %s, out %p stub!\n", iface, debugstr_guid(iid), out);
++
++    if (IsEqualGUID(iid, &IID_IAgileObject))
++    {
++        IUnknown_AddRef(iface);
++        *out = iface;
++        return S_OK;
++    }
++
++    WARN("%s not implemented, returning E_NOINTERFACE.\n", debugstr_guid(iid));
++    *out = NULL;
++    return E_NOINTERFACE;
++}
++
++static ULONG STDMETHODCALLTYPE gamepad_statics_AddRef(
++        IGamepadStatics *iface)
++{
++    struct windows_gaming_input *impl = impl_from_IGamepadStatics(iface);
++    ULONG ref = InterlockedIncrement(&impl->ref);
++    TRACE("iface %p, ref %u.\n", iface, ref);
++    return ref;
++}
++
++static ULONG STDMETHODCALLTYPE gamepad_statics_Release(
++        IGamepadStatics *iface)
++{
++    struct windows_gaming_input *impl = impl_from_IGamepadStatics(iface);
++    ULONG ref = InterlockedDecrement(&impl->ref);
++    TRACE("iface %p, ref %u.\n", iface, ref);
++    return ref;
++}
++
++static HRESULT STDMETHODCALLTYPE gamepad_statics_GetIids(
++        IGamepadStatics *iface, ULONG *iid_count, IID **iids)
++{
++    FIXME("iface %p, iid_count %p, iids %p stub!\n", iface, iid_count, iids);
++    return E_NOTIMPL;
++}
++
++static HRESULT STDMETHODCALLTYPE gamepad_statics_GetRuntimeClassName(
++        IGamepadStatics *iface, HSTRING *class_name)
++{
++    FIXME("iface %p, class_name %p stub!\n", iface, class_name);
++    return E_NOTIMPL;
++}
++
++static HRESULT STDMETHODCALLTYPE gamepad_statics_GetTrustLevel(
++        IGamepadStatics *iface, TrustLevel *trust_level)
++{
++    FIXME("iface %p, trust_level %p stub!\n", iface, trust_level);
++    return E_NOTIMPL;
++}
++
++static HRESULT STDMETHODCALLTYPE gamepad_statics_add_GamepadAdded(
++    IGamepadStatics *iface, IEventHandler_Gamepad *value, EventRegistrationToken* token)
++{
++    FIXME("iface %p, value %p, token %p stub!\n", iface, value, token);
++    return E_NOTIMPL;
++}
++
++static HRESULT STDMETHODCALLTYPE gamepad_statics_remove_GamepadAdded(
++    IGamepadStatics *iface, EventRegistrationToken token)
++{
++    FIXME("iface %p, token %#I64x stub!\n", iface, token.value);
++    return E_NOTIMPL;
++}
++
++static HRESULT STDMETHODCALLTYPE gamepad_statics_add_GamepadRemoved(
++    IGamepadStatics *iface, IEventHandler_Gamepad *value, EventRegistrationToken* token)
++{
++    FIXME("iface %p, value %p, token %p stub!\n", iface, value, token);
++    return E_NOTIMPL;
++}
++
++static HRESULT STDMETHODCALLTYPE gamepad_statics_remove_GamepadRemoved(
++    IGamepadStatics *iface, EventRegistrationToken token)
++{
++    FIXME("iface %p, token %#I64x stub!\n", iface, token.value);
++    return E_NOTIMPL;
++}
++
++static HRESULT STDMETHODCALLTYPE gamepad_statics_get_Gamepads(
++    IGamepadStatics *iface, IVectorView_Gamepad **value)
++{
++    struct windows_gaming_input *impl = impl_from_IGamepadStatics(iface);
++    FIXME("iface %p, value %p stub!\n", iface, value);
++    return E_NOTIMPL;
++}
++
++static const struct IGamepadStaticsVtbl gamepad_statics_vtbl =
++{
++    gamepad_statics_QueryInterface,
++    gamepad_statics_AddRef,
++    gamepad_statics_Release,
++    /* IInspectable methods */
++    gamepad_statics_GetIids,
++    gamepad_statics_GetRuntimeClassName,
++    gamepad_statics_GetTrustLevel,
++    /* IGamepadStatics methods */
++    gamepad_statics_add_GamepadAdded,
++    gamepad_statics_remove_GamepadAdded,
++    gamepad_statics_add_GamepadRemoved,
++    gamepad_statics_remove_GamepadRemoved,
++    gamepad_statics_get_Gamepads,
++};
++
+ static HRESULT STDMETHODCALLTYPE windows_gaming_input_QueryInterface(
+         IActivationFactory *iface, REFIID iid, void **out)
+ {
+@@ -50,6 +169,13 @@ static HRESULT STDMETHODCALLTYPE windows_gaming_input_QueryInterface(
+         return S_OK;
+     }
+ 
++    if (IsEqualGUID(iid, &IID_IGamepadStatics))
++    {
++        IUnknown_AddRef(iface);
++        *out = &impl->IGamepadStatics_iface;
++        return S_OK;
++    }
++
+     FIXME("%s not implemented, returning E_NOINTERFACE.\n", debugstr_guid(iid));
+     *out = NULL;
+     return E_NOINTERFACE;
+@@ -117,6 +243,7 @@ static const struct IActivationFactoryVtbl activation_factory_vtbl =
+ static struct windows_gaming_input windows_gaming_input =
+ {
+     {&activation_factory_vtbl},
++    {&gamepad_statics_vtbl},
+     0
+ };
+ 
+diff --git a/include/windows.foundation.idl b/include/windows.foundation.idl
+index 9b9b40897be..dd613b68b00 100644
+--- a/include/windows.foundation.idl
++++ b/include/windows.foundation.idl
+@@ -26,6 +26,11 @@ import "windowscontracts.idl";
+ /* import "eventtoken.idl"; */
+ /* import "ivectorchangedeventargs.idl"; */
+ 
++typedef struct EventRegistrationToken
++{
++    __int64 value;
++} EventRegistrationToken;
++
+ namespace Windows {
+     namespace Foundation {
+         [contract(Windows.Foundation.FoundationContract, 1.0)]
+@@ -119,6 +124,12 @@ namespace Windows {
+         ]
+         delegate void EventHandler<T>([in] IInspectable *sender, [in] T args);
+ 
++        [
++            contract(Windows.Foundation.FoundationContract, 1.0),
++            uuid(9de1c534-6ae1-11e0-84e1-18a905bcc53f)
++        ]
++        delegate void TypedEventHandler<TSender, TResult>([in] TSender sender, [in] TResult args);
++
+         namespace Collections
+         {
+             [
+diff --git a/include/windows.gaming.input.idl b/include/windows.gaming.input.idl
+index 575f34ccb58..b5af4e24a66 100644
+--- a/include/windows.gaming.input.idl
++++ b/include/windows.gaming.input.idl
+@@ -22,3 +22,131 @@
+ 
+ import "inspectable.idl";
+ import "windows.foundation.idl";
++
++namespace Windows {
++    namespace Gaming {
++        namespace Input {
++            typedef enum GamepadButtons GamepadButtons;
++            typedef struct GamepadReading GamepadReading;
++            typedef struct GamepadVibration GamepadVibration;
++            interface IGameController;
++            interface IGameControllerBatteryInfo;
++            interface IGamepad;
++            interface IGamepad2;
++            interface IGamepadStatics;
++            interface IGamepadStatics2;
++            runtimeclass Gamepad;
++        }
++    }
++}
++
++namespace Windows {
++    namespace Gaming {
++        namespace Input {
++            declare {
++                interface Windows.Foundation.EventHandler<Windows.Gaming.Input.Gamepad*>;
++                interface Windows.Foundation.Collections.IVectorView<Gamepad*>;
++            }
++        }
++    }
++}
++
++namespace Windows {
++    namespace Gaming {
++        namespace Input {
++            [
++                contract(Windows.Foundation.UniversalApiContract, 1.0),
++                flags
++            ]
++            enum GamepadButtons
++            {
++                None = 0x0,
++                Menu = 0x1,
++                View = 0x2,
++                A = 0x4,
++                B = 0x8,
++                X = 0x10,
++                Y = 0x20,
++                DPadUp = 0x40,
++                DPadDown = 0x80,
++                DPadLeft = 0x100,
++                DPadRight = 0x200,
++                LeftShoulder = 0x400,
++                RightShoulder = 0x800,
++                LeftThumbstick = 0x1000,
++                RightThumbstick = 0x2000,
++                [contract(Windows.Foundation.UniversalApiContract, 3.0)]
++                Paddle1 = 0x4000,
++                [contract(Windows.Foundation.UniversalApiContract, 3.0)]
++                Paddle2 = 0x8000,
++                [contract(Windows.Foundation.UniversalApiContract, 3.0)]
++                Paddle3 = 0x10000,
++                [contract(Windows.Foundation.UniversalApiContract, 3.0)]
++                Paddle4 = 0x20000
++            };
++
++            [contract(Windows.Foundation.UniversalApiContract, 1.0)]
++            struct GamepadReading
++            {
++                UINT64 Timestamp;
++                Windows.Gaming.Input.GamepadButtons Buttons;
++                DOUBLE LeftTrigger;
++                DOUBLE RightTrigger;
++                DOUBLE LeftThumbstickX;
++                DOUBLE LeftThumbstickY;
++                DOUBLE RightThumbstickX;
++                DOUBLE RightThumbstickY;
++            };
++
++            [contract(Windows.Foundation.UniversalApiContract, 1.0)]
++            struct GamepadVibration
++            {
++                DOUBLE LeftMotor;
++                DOUBLE RightMotor;
++                DOUBLE LeftTrigger;
++                DOUBLE RightTrigger;
++            };
++
++            [
++                contract(Windows.Foundation.UniversalApiContract, 1.0),
++                exclusiveto(Windows.Gaming.Input.Gamepad),
++                uuid(bc7bb43c-0a69-3903-9e9d-a50f86a45de5)
++            ]
++            interface IGamepad : IInspectable
++                requires Windows.Gaming.Input.IGameController
++            {
++                [propget] HRESULT Vibration([out, retval] Windows.Gaming.Input.GamepadVibration* value);
++                [propput] HRESULT Vibration([in] Windows.Gaming.Input.GamepadVibration value);
++                HRESULT GetCurrentReading([out, retval] Windows.Gaming.Input.GamepadReading* value);
++            }
++
++            [
++                object,
++                uuid(8bbce529-d49c-39e9-9560-e47dde96b7c8)
++            ]
++            interface IGamepadStatics : IInspectable
++            {
++                [eventadd] HRESULT GamepadAdded([in] Windows.Foundation.EventHandler<Gamepad*> *value, [out, retval] EventRegistrationToken* token);
++                [eventremove] HRESULT GamepadAdded([in] EventRegistrationToken token);
++                [eventadd] HRESULT GamepadRemoved([in] Windows.Foundation.EventHandler<Gamepad*> *value, [out, retval] EventRegistrationToken* token);
++                [eventremove] HRESULT GamepadRemoved([in] EventRegistrationToken token);
++                [propget] HRESULT Gamepads([out, retval] Windows.Foundation.Collections.IVectorView<Gamepad*> **value);
++            }
++
++            [
++                contract(Windows.Foundation.UniversalApiContract, 1.0),
++                marshaling_behavior(agile),
++                static(Windows.Gaming.Input.IGamepadStatics, Windows.Foundation.UniversalApiContract, 1.0),
++                static(Windows.Gaming.Input.IGamepadStatics2, Windows.Foundation.UniversalApiContract, 4.0),
++                threading(both)
++            ]
++            runtimeclass Gamepad
++            {
++                [default] interface Windows.Gaming.Input.IGamepad;
++                interface Windows.Gaming.Input.IGameController;
++                [contract(Windows.Foundation.UniversalApiContract, 3.0)] interface Windows.Gaming.Input.IGamepad2;
++                [contract(Windows.Foundation.UniversalApiContract, 4.0)] interface Windows.Gaming.Input.IGameControllerBatteryInfo;
++            }
++        }
++    }
++}
+diff --git a/loader/wine.inf.in b/loader/wine.inf.in
+index 157b146a857..9d738859b81 100644
+--- a/loader/wine.inf.in
++++ b/loader/wine.inf.in
+@@ -713,6 +713,7 @@ HKLM,%MciExtStr%,"wmx",,"MPEGVideo"
+ HKLM,%MciExtStr%,"wvx",,"MPEGVideo"
+ 
+ [Misc]
++HKLM,Software\Microsoft\WindowsRuntime\ActivatableClassId\Windows.Gaming.Input.Gamepad,"DllPath",2,"Windows.Gaming.Input.dll"
+ HKLM,Software\Microsoft\WindowsRuntime\ActivatableClassId\Windows.Media.SpeechSynthesis.SpeechSynthesizer,"DllPath",2,"Windows.Media.Speech.dll"
+ HKLM,Software\Borland\Database Engine\Settings\SYSTEM\INIT,SHAREDMEMLOCATION,,9000
+ HKLM,Software\Clients\Mail,,2,"Native Mail Client"
+-- 
+2.28.0
+
diff --git a/patches/windows.gaming.input-dll/0003-windows.gaming.input-Implement-IGamepadStatics-Gamep.patch b/patches/windows.gaming.input-dll/0003-windows.gaming.input-Implement-IGamepadStatics-Gamep.patch
new file mode 100644
index 00000000..153c17d0
--- /dev/null
+++ b/patches/windows.gaming.input-dll/0003-windows.gaming.input-Implement-IGamepadStatics-Gamep.patch
@@ -0,0 +1,157 @@
+From 39cabcb0a109f9705740120186858defe1c1cf2c Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?R=C3=A9mi=20Bernon?= <rbernon@codeweavers.com>
+Date: Tue, 13 Oct 2020 17:58:14 +0200
+Subject: [PATCH 3/9] windows.gaming.input: Implement IGamepadStatics::Gamepads
+ stubs.
+
+---
+ .../windows.gaming.input_main.c               | 112 +++++++++++++++++-
+ 1 file changed, 111 insertions(+), 1 deletion(-)
+
+diff --git a/dlls/windows.gaming.input.dll/windows.gaming.input_main.c b/dlls/windows.gaming.input.dll/windows.gaming.input_main.c
+index 33c260b27b3..a7d9a89244b 100644
+--- a/dlls/windows.gaming.input.dll/windows.gaming.input_main.c
++++ b/dlls/windows.gaming.input.dll/windows.gaming.input_main.c
+@@ -32,6 +32,7 @@ struct windows_gaming_input
+ {
+     IActivationFactory IActivationFactory_iface;
+     IGamepadStatics IGamepadStatics_iface;
++    IVectorView_Gamepad IVectorView_Gamepad_iface;
+     LONG ref;
+ };
+ 
+@@ -45,6 +46,113 @@ static inline struct windows_gaming_input *impl_from_IGamepadStatics(IGamepadSta
+     return CONTAINING_RECORD(iface, struct windows_gaming_input, IGamepadStatics_iface);
+ }
+ 
++static inline struct windows_gaming_input *impl_from_IVectorView_Gamepad(IVectorView_Gamepad *iface)
++{
++    return CONTAINING_RECORD(iface, struct windows_gaming_input, IVectorView_Gamepad_iface);
++}
++
++static HRESULT STDMETHODCALLTYPE vector_view_gamepad_QueryInterface(
++        IVectorView_Gamepad *iface, REFIID iid, void **out)
++{
++    TRACE("iface %p, iid %s, out %p stub!\n", iface, debugstr_guid(iid), out);
++
++    if (IsEqualGUID(iid, &IID_IUnknown) ||
++        IsEqualGUID(iid, &IID_IInspectable) ||
++        IsEqualGUID(iid, &IID_IVectorView_Gamepad))
++    {
++        IUnknown_AddRef(iface);
++        *out = iface;
++        return S_OK;
++    }
++
++    WARN("%s not implemented, returning E_NOINTERFACE.\n", debugstr_guid(iid));
++    *out = NULL;
++    return E_NOINTERFACE;
++}
++
++static ULONG STDMETHODCALLTYPE vector_view_gamepad_AddRef(
++        IVectorView_Gamepad *iface)
++{
++    struct windows_gaming_input *impl = impl_from_IVectorView_Gamepad(iface);
++    ULONG ref = InterlockedIncrement(&impl->ref);
++    TRACE("iface %p, ref %u.\n", iface, ref);
++    return ref;
++}
++
++static ULONG STDMETHODCALLTYPE vector_view_gamepad_Release(
++        IVectorView_Gamepad *iface)
++{
++    struct windows_gaming_input *impl = impl_from_IVectorView_Gamepad(iface);
++    ULONG ref = InterlockedDecrement(&impl->ref);
++    TRACE("iface %p, ref %u.\n", iface, ref);
++    return ref;
++}
++
++static HRESULT STDMETHODCALLTYPE vector_view_gamepad_GetIids(
++        IVectorView_Gamepad *iface, ULONG *iid_count, IID **iids)
++{
++    FIXME("iface %p, iid_count %p, iids %p stub!\n", iface, iid_count, iids);
++    return E_NOTIMPL;
++}
++
++static HRESULT STDMETHODCALLTYPE vector_view_gamepad_GetRuntimeClassName(
++        IVectorView_Gamepad *iface, HSTRING *class_name)
++{
++    FIXME("iface %p, class_name %p stub!\n", iface, class_name);
++    return E_NOTIMPL;
++}
++
++static HRESULT STDMETHODCALLTYPE vector_view_gamepad_GetTrustLevel(
++        IVectorView_Gamepad *iface, TrustLevel *trust_level)
++{
++    FIXME("iface %p, trust_level %p stub!\n", iface, trust_level);
++    return E_NOTIMPL;
++}
++
++static HRESULT STDMETHODCALLTYPE vector_view_gamepad_GetAt(
++    IVectorView_Gamepad *iface, ULONG index, IGamepad **value)
++{
++    FIXME("iface %p, index %#x, value %p stub!\n", iface, index, value);
++    return E_NOTIMPL;
++}
++
++static HRESULT STDMETHODCALLTYPE vector_view_gamepad_get_Size(
++    IVectorView_Gamepad *iface, ULONG *value)
++{
++    FIXME("iface %p, value %p stub!\n", iface, value);
++    return E_NOTIMPL;
++}
++
++static HRESULT STDMETHODCALLTYPE vector_view_gamepad_IndexOf(
++    IVectorView_Gamepad *iface, IGamepad *element, ULONG *index, BOOLEAN *value)
++{
++    FIXME("iface %p, element %p, index %p, value %p stub!\n", iface, element, index, value);
++    return E_NOTIMPL;
++}
++
++static HRESULT STDMETHODCALLTYPE vector_view_gamepad_GetMany(
++    IVectorView_Gamepad *iface, ULONG start_index, IGamepad **items, UINT *value)
++{
++    FIXME("iface %p, start_index %#x, items %p, value %p stub!\n", iface, start_index, items, value);
++    return E_NOTIMPL;
++}
++
++static const struct IVectorView_GamepadVtbl vector_view_gamepad_vtbl =
++{
++    vector_view_gamepad_QueryInterface,
++    vector_view_gamepad_AddRef,
++    vector_view_gamepad_Release,
++    /* IInspectable methods */
++    vector_view_gamepad_GetIids,
++    vector_view_gamepad_GetRuntimeClassName,
++    vector_view_gamepad_GetTrustLevel,
++    /* IVectorView<Gamepad> methods */
++    vector_view_gamepad_GetAt,
++    vector_view_gamepad_get_Size,
++    vector_view_gamepad_IndexOf,
++    vector_view_gamepad_GetMany,
++};
++
+ static HRESULT STDMETHODCALLTYPE gamepad_statics_QueryInterface(
+         IGamepadStatics *iface, REFIID iid, void **out)
+ {
+@@ -134,7 +242,8 @@ static HRESULT STDMETHODCALLTYPE gamepad_statics_get_Gamepads(
+ {
+     struct windows_gaming_input *impl = impl_from_IGamepadStatics(iface);
+     FIXME("iface %p, value %p stub!\n", iface, value);
+-    return E_NOTIMPL;
++    *value = &impl->IVectorView_Gamepad_iface;
++    return S_OK;
+ }
+ 
+ static const struct IGamepadStaticsVtbl gamepad_statics_vtbl =
+@@ -244,6 +353,7 @@ static struct windows_gaming_input windows_gaming_input =
+ {
+     {&activation_factory_vtbl},
+     {&gamepad_statics_vtbl},
++    {&vector_view_gamepad_vtbl},
+     0
+ };
+ 
+-- 
+2.28.0
+
diff --git a/patches/windows.gaming.input-dll/0003-windows.gaming.input-Implement-IGamepadStatics-stubs.patch b/patches/windows.gaming.input-dll/0003-windows.gaming.input-Implement-IGamepadStatics-stubs.patch
deleted file mode 100644
index c4a063a1..00000000
--- a/patches/windows.gaming.input-dll/0003-windows.gaming.input-Implement-IGamepadStatics-stubs.patch
+++ /dev/null
@@ -1,419 +0,0 @@
-From ba450b20147db9af677e2388c7b3b43995967ce8 Mon Sep 17 00:00:00 2001
-From: =?UTF-8?q?R=C3=A9mi=20Bernon?= <rbernon@codeweavers.com>
-Date: Fri, 21 Aug 2020 08:58:34 +0200
-Subject: [PATCH] windows.gaming.input: Implement IGamepadStatics stubs.
-MIME-Version: 1.0
-Content-Type: text/plain; charset=UTF-8
-Content-Transfer-Encoding: 8bit
-
-Signed-off-by: Rémi Bernon <rbernon@codeweavers.com>
----
- .../windows.gaming.input_main.c               | 358 ++++++++++++++++++
- loader/wine.inf.in                            |   1 +
- 3 files changed, 370 insertions(+)
-
-diff --git a/dlls/windows.gaming.input.dll/windows.gaming.input_main.c b/dlls/windows.gaming.input.dll/windows.gaming.input_main.c
-index f345fbffb50..44ad92980e5 100644
---- a/dlls/windows.gaming.input.dll/windows.gaming.input_main.c
-+++ b/dlls/windows.gaming.input.dll/windows.gaming.input_main.c
-@@ -20,9 +20,140 @@ static const char *debugstr_hstring(HSTRING hstr)
-     return wine_dbgstr_wn(str, len);
- }
- 
-+DEFINE_GUID(IID_IGamepadStatics,0x8bbce529,0xd49c,0x39e9,0x95,0x60,0xe4,0x7d,0xde,0x96,0xb7,0xc8);
-+
-+typedef struct EventRegistrationToken
-+{
-+  __int64 value;
-+} EventRegistrationToken;
-+
-+typedef struct IVectorView IVectorView;
-+
-+typedef struct IVectorViewVtbl
-+{
-+    /*** IUnknown methods ***/
-+    HRESULT (STDMETHODCALLTYPE *QueryInterface)(
-+        IVectorView *This,
-+        REFIID riid,
-+        void **ppvObject);
-+
-+    ULONG (STDMETHODCALLTYPE *AddRef)(
-+        IVectorView *This);
-+
-+    ULONG (STDMETHODCALLTYPE *Release)(
-+        IVectorView *This);
-+
-+    /*** IInspectable methods ***/
-+    HRESULT (STDMETHODCALLTYPE *GetIids)(
-+        IVectorView *This,
-+        ULONG *iidCount,
-+        IID **iids);
-+
-+    HRESULT (STDMETHODCALLTYPE *GetRuntimeClassName)(
-+        IVectorView *This,
-+        HSTRING *className);
-+
-+    HRESULT (STDMETHODCALLTYPE *GetTrustLevel)(
-+        IVectorView *This,
-+        TrustLevel *trustLevel);
-+
-+    /*** IVectorView<T> methods ***/
-+    HRESULT (STDMETHODCALLTYPE *GetAt)(
-+        IVectorView *This,
-+        ULONG index,
-+        /* T */ void *out_value);
-+
-+    HRESULT (STDMETHODCALLTYPE *get_Size)(
-+        IVectorView *This,
-+        ULONG *out_value);
-+
-+    HRESULT (STDMETHODCALLTYPE *IndexOf)(
-+        IVectorView *This,
-+        /* T */ void *value,
-+        ULONG *index,
-+        BOOLEAN *out_value);
-+
-+    HRESULT (STDMETHODCALLTYPE *GetMany)(
-+        IVectorView *This,
-+        ULONG start_index,
-+        /* T[] */ void **items,
-+        UINT *out_value);
-+} IVectorViewVtbl;
-+
-+struct IVectorView
-+{
-+    CONST_VTBL IVectorViewVtbl* lpVtbl;
-+};
-+
-+typedef struct IGamepadStatics IGamepadStatics;
-+
-+typedef struct IGamepadStaticsVtbl
-+{
-+    BEGIN_INTERFACE
-+
-+    /*** IUnknown methods ***/
-+    HRESULT (STDMETHODCALLTYPE *QueryInterface)(
-+        IGamepadStatics *This,
-+        REFIID riid,
-+        void **ppvObject);
-+
-+    ULONG (STDMETHODCALLTYPE *AddRef)(
-+        IGamepadStatics *This);
-+
-+    ULONG (STDMETHODCALLTYPE *Release)(
-+        IGamepadStatics *This);
-+
-+    /*** IInspectable methods ***/
-+    HRESULT (STDMETHODCALLTYPE *GetIids)(
-+        IGamepadStatics *This,
-+        ULONG *iidCount,
-+        IID **iids);
-+
-+    HRESULT (STDMETHODCALLTYPE *GetRuntimeClassName)(
-+        IGamepadStatics *This,
-+        HSTRING *className);
-+
-+    HRESULT (STDMETHODCALLTYPE *GetTrustLevel)(
-+        IGamepadStatics *This,
-+        TrustLevel *trustLevel);
-+
-+    /*** IGamepadStatics methods ***/
-+    HRESULT (STDMETHODCALLTYPE *eventadd_GamepadAdded)(
-+        IGamepadStatics *This,
-+        /* Windows.Foundation.EventHandler<Windows.Gaming.Input.Gamepad*> */
-+        void *value,
-+        EventRegistrationToken* token);
-+    HRESULT (STDMETHODCALLTYPE *eventremove_GamepadAdded)(
-+        IGamepadStatics *This,
-+        EventRegistrationToken token);
-+
-+    HRESULT (STDMETHODCALLTYPE *eventadd_GamepadRemoved)(
-+        IGamepadStatics *This,
-+        /* Windows.Foundation.EventHandler<Windows.Gaming.Input.Gamepad*> */
-+        void *value,
-+        EventRegistrationToken* token);
-+    HRESULT (STDMETHODCALLTYPE *eventremove_GamepadRemoved)(
-+        IGamepadStatics *This,
-+        EventRegistrationToken token);
-+
-+    HRESULT (STDMETHODCALLTYPE *get_Gamepads)(
-+        IGamepadStatics *This,
-+        /* Windows.Foundation.Collections.IVectorView<Windows.Gaming.Input.Gamepad*>* */
-+        void **value);
-+
-+    END_INTERFACE
-+} IGamepadStaticsVtbl;
-+
-+struct IGamepadStatics
-+{
-+    CONST_VTBL IGamepadStaticsVtbl* lpVtbl;
-+};
-+
- struct windows_gaming_input
- {
-     IActivationFactory IActivationFactory_iface;
-+    IGamepadStatics IGamepadStatics_iface;
-+    IVectorView IVectorView_iface;
-     LONG refcount;
- };
- 
-@@ -31,10 +162,235 @@ static inline struct windows_gaming_input *impl_from_IActivationFactory(IActivat
-     return CONTAINING_RECORD(iface, struct windows_gaming_input, IActivationFactory_iface);
- }
- 
-+static inline struct windows_gaming_input *impl_from_IGamepadStatics(IGamepadStatics *iface)
-+{
-+    return CONTAINING_RECORD(iface, struct windows_gaming_input, IGamepadStatics_iface);
-+}
-+
-+static inline struct windows_gaming_input *impl_from_IVectorView(IVectorView *iface)
-+{
-+    return CONTAINING_RECORD(iface, struct windows_gaming_input, IVectorView_iface);
-+}
-+
-+static HRESULT STDMETHODCALLTYPE vector_view_QueryInterface(
-+        IVectorView *iface, REFIID iid, void **object)
-+{
-+    TRACE("iface %p, iid %s, object %p stub!\n", iface, debugstr_guid(iid), object);
-+    WARN("%s not implemented, returning E_NOINTERFACE.\n", debugstr_guid(iid));
-+    *object = NULL;
-+    return E_NOINTERFACE;
-+}
-+
-+static ULONG STDMETHODCALLTYPE vector_view_AddRef(
-+        IVectorView *iface)
-+{
-+    struct windows_gaming_input *impl = impl_from_IVectorView(iface);
-+    ULONG rc = InterlockedIncrement(&impl->refcount);
-+    TRACE("%p increasing refcount to %u.\n", impl, rc);
-+    return rc;
-+}
-+
-+static ULONG STDMETHODCALLTYPE vector_view_Release(
-+        IVectorView *iface)
-+{
-+    struct windows_gaming_input *impl = impl_from_IVectorView(iface);
-+    ULONG rc = InterlockedDecrement(&impl->refcount);
-+    TRACE("%p decreasing refcount to %u.\n", impl, rc);
-+    return rc;
-+}
-+
-+static HRESULT STDMETHODCALLTYPE vector_view_GetIids(
-+        IVectorView *iface, ULONG *iid_count, IID **iids)
-+{
-+    FIXME("iface %p, iid_count %p, iids %p stub!\n", iface, iid_count, iids);
-+    return E_NOTIMPL;
-+}
-+
-+static HRESULT STDMETHODCALLTYPE vector_view_GetRuntimeClassName(
-+        IVectorView *iface, HSTRING *class_name)
-+{
-+    FIXME("iface %p, class_name %p stub!\n", iface, class_name);
-+    return E_NOTIMPL;
-+}
-+
-+static HRESULT STDMETHODCALLTYPE vector_view_GetTrustLevel(
-+        IVectorView *iface, TrustLevel *trust_level)
-+{
-+    FIXME("iface %p, trust_level %p stub!\n", iface, trust_level);
-+    return E_NOTIMPL;
-+}
-+
-+static HRESULT STDMETHODCALLTYPE vector_view_GetAt(
-+    IVectorView *iface, ULONG index, void *out_value)
-+{
-+    FIXME("iface %p, index %#x, out_value %p stub!\n", iface, index, out_value);
-+    return S_OK;
-+}
-+
-+static HRESULT STDMETHODCALLTYPE vector_view_get_Size(
-+    IVectorView *iface, ULONG *out_value)
-+{
-+    FIXME("iface %p, out_value %p stub!\n", iface, out_value);
-+    *out_value = 0;
-+    return S_OK;
-+}
-+
-+static HRESULT STDMETHODCALLTYPE vector_view_IndexOf(
-+    IVectorView *iface, void *value, ULONG *index, BOOLEAN *out_value)
-+{
-+    FIXME("iface %p, value %p, index %p, out_value %p stub!\n", iface, value, index, out_value);
-+    *out_value = FALSE;
-+    return S_OK;
-+}
-+
-+static HRESULT STDMETHODCALLTYPE vector_view_GetMany(
-+    IVectorView *iface, ULONG start_index, void **items, UINT *out_value)
-+{
-+    FIXME("iface %p, start_index %#x, items %p, out_value %p stub!\n", iface, start_index, items, out_value);
-+    *out_value = 0;
-+    return S_OK;
-+}
-+
-+static const struct IVectorViewVtbl vector_view_vtbl =
-+{
-+    vector_view_QueryInterface,
-+    vector_view_AddRef,
-+    vector_view_Release,
-+    /* IInspectable methods */
-+    vector_view_GetIids,
-+    vector_view_GetRuntimeClassName,
-+    vector_view_GetTrustLevel,
-+    /*** IVectorView<T> methods ***/
-+    vector_view_GetAt,
-+    vector_view_get_Size,
-+    vector_view_IndexOf,
-+    vector_view_GetMany,
-+};
-+
-+static HRESULT STDMETHODCALLTYPE gamepad_statics_QueryInterface(
-+        IGamepadStatics *iface, REFIID iid, void **object)
-+{
-+    TRACE("iface %p, iid %s, object %p stub!\n", iface, debugstr_guid(iid), object);
-+
-+    if (IsEqualGUID(iid, &IID_IAgileObject))
-+    {
-+        IUnknown_AddRef(iface);
-+        *object = iface;
-+        return S_OK;
-+    }
-+
-+    WARN("%s not implemented, returning E_NOINTERFACE.\n", debugstr_guid(iid));
-+    *object = NULL;
-+    return E_NOINTERFACE;
-+}
-+
-+static ULONG STDMETHODCALLTYPE gamepad_statics_AddRef(
-+        IGamepadStatics *iface)
-+{
-+    struct windows_gaming_input *impl = impl_from_IGamepadStatics(iface);
-+    ULONG rc = InterlockedIncrement(&impl->refcount);
-+    TRACE("%p increasing refcount to %u.\n", impl, rc);
-+    return rc;
-+}
-+
-+static ULONG STDMETHODCALLTYPE gamepad_statics_Release(
-+        IGamepadStatics *iface)
-+{
-+    struct windows_gaming_input *impl = impl_from_IGamepadStatics(iface);
-+    ULONG rc = InterlockedDecrement(&impl->refcount);
-+    TRACE("%p decreasing refcount to %u.\n", impl, rc);
-+    return rc;
-+}
-+
-+static HRESULT STDMETHODCALLTYPE gamepad_statics_GetIids(
-+        IGamepadStatics *iface, ULONG *iid_count, IID **iids)
-+{
-+    FIXME("iface %p, iid_count %p, iids %p stub!\n", iface, iid_count, iids);
-+    return E_NOTIMPL;
-+}
-+
-+static HRESULT STDMETHODCALLTYPE gamepad_statics_GetRuntimeClassName(
-+        IGamepadStatics *iface, HSTRING *class_name)
-+{
-+    FIXME("iface %p, class_name %p stub!\n", iface, class_name);
-+    return E_NOTIMPL;
-+}
-+
-+static HRESULT STDMETHODCALLTYPE gamepad_statics_GetTrustLevel(
-+        IGamepadStatics *iface, TrustLevel *trust_level)
-+{
-+    FIXME("iface %p, trust_level %p stub!\n", iface, trust_level);
-+    return E_NOTIMPL;
-+}
-+
-+static HRESULT STDMETHODCALLTYPE gamepad_statics_eventadd_GamepadAdded(
-+    IGamepadStatics *iface, void *value, EventRegistrationToken* token)
-+{
-+    FIXME("iface %p, value %p, token %p stub!\n", iface, value, token);
-+    return S_OK;
-+}
-+
-+static HRESULT STDMETHODCALLTYPE gamepad_statics_eventremove_GamepadAdded(
-+    IGamepadStatics *iface, EventRegistrationToken token)
-+{
-+    FIXME("iface %p, token %#I64x stub!\n", iface, token.value);
-+    return S_OK;
-+}
-+
-+static HRESULT STDMETHODCALLTYPE gamepad_statics_eventadd_GamepadRemoved(
-+    IGamepadStatics *iface, void *value, EventRegistrationToken* token)
-+{
-+    FIXME("iface %p, value %p, token %p stub!\n", iface, value, token);
-+    return S_OK;
-+}
-+
-+static HRESULT STDMETHODCALLTYPE gamepad_statics_eventremove_GamepadRemoved(
-+    IGamepadStatics *iface, EventRegistrationToken token)
-+{
-+    FIXME("iface %p, token %#I64x stub!\n", iface, token.value);
-+    return S_OK;
-+}
-+
-+static HRESULT STDMETHODCALLTYPE gamepad_statics_get_Gamepads(
-+    IGamepadStatics *iface, void **value)
-+{
-+    struct windows_gaming_input *impl = impl_from_IGamepadStatics(iface);
-+    FIXME("iface %p, value %p stub!\n", iface, value);
-+    *value = &impl->IVectorView_iface;
-+    return S_OK;
-+}
-+
-+static const struct IGamepadStaticsVtbl gamepad_statics_vtbl =
-+{
-+    gamepad_statics_QueryInterface,
-+    gamepad_statics_AddRef,
-+    gamepad_statics_Release,
-+    /* IInspectable methods */
-+    gamepad_statics_GetIids,
-+    gamepad_statics_GetRuntimeClassName,
-+    gamepad_statics_GetTrustLevel,
-+    /* IGamepadStatics methods */
-+    gamepad_statics_eventadd_GamepadAdded,
-+    gamepad_statics_eventremove_GamepadAdded,
-+    gamepad_statics_eventadd_GamepadRemoved,
-+    gamepad_statics_eventremove_GamepadRemoved,
-+    gamepad_statics_get_Gamepads,
-+};
-+
- static HRESULT STDMETHODCALLTYPE windows_gaming_input_QueryInterface(
-         IActivationFactory *iface, REFIID iid, void **object)
- {
-+    struct windows_gaming_input *impl = impl_from_IActivationFactory(iface);
-     TRACE("iface %p, iid %s, object %p stub!\n", iface, debugstr_guid(iid), object);
-+
-+    if (IsEqualGUID(iid, &IID_IGamepadStatics))
-+    {
-+        IUnknown_AddRef(iface);
-+        *object = &impl->IGamepadStatics_iface;
-+        return S_OK;
-+    }
-+
-+    WARN("%s not implemented, returning E_NOINTERFACE.\n", debugstr_guid(iid));
-     *object = NULL;
-     return E_NOINTERFACE;
- }
-@@ -101,6 +457,8 @@ static const struct IActivationFactoryVtbl activation_factory_vtbl =
- static struct windows_gaming_input windows_gaming_input =
- {
-     {&activation_factory_vtbl},
-+    {&gamepad_statics_vtbl},
-+    {&vector_view_vtbl},
-     0
- };
- 
-diff --git a/loader/wine.inf.in b/loader/wine.inf.in
-index f1f1563ac53..1d372f457ee 100644
---- a/loader/wine.inf.in
-+++ b/loader/wine.inf.in
-@@ -717,6 +717,7 @@ HKLM,%MciExtStr%,"wmx",,"MPEGVideo"
- HKLM,%MciExtStr%,"wvx",,"MPEGVideo"
- 
- [Misc]
-+HKLM,Software\Microsoft\WindowsRuntime\ActivatableClassId\Windows.Gaming.Input.Gamepad,"DllPath",2,"Windows.Gaming.Input.dll"
- HKLM,Software\Borland\Database Engine\Settings\SYSTEM\INIT,SHAREDMEMLOCATION,,9000
- HKLM,Software\Clients\Mail,,2,"Native Mail Client"
- HKLM,Software\Clients\Mail\Native Mail Client,,2,"Native Mail Client"
--- 
-2.28.0
-
diff --git a/patches/windows.gaming.input-dll/0004-windows.gaming.input-Fake-empty-IGamepadStatics-Game.patch b/patches/windows.gaming.input-dll/0004-windows.gaming.input-Fake-empty-IGamepadStatics-Game.patch
new file mode 100644
index 00000000..7daa2865
--- /dev/null
+++ b/patches/windows.gaming.input-dll/0004-windows.gaming.input-Fake-empty-IGamepadStatics-Game.patch
@@ -0,0 +1,53 @@
+From bedffa28b0137a32106c3c126e842c9469555d98 Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?R=C3=A9mi=20Bernon?= <rbernon@codeweavers.com>
+Date: Tue, 13 Oct 2020 17:59:51 +0200
+Subject: [PATCH 4/9] windows.gaming.input: Fake empty
+ IGamepadStatics::Gamepads vector.
+
+---
+ .../windows.gaming.input_main.c                       | 11 +++++++----
+ 1 file changed, 7 insertions(+), 4 deletions(-)
+
+diff --git a/dlls/windows.gaming.input.dll/windows.gaming.input_main.c b/dlls/windows.gaming.input.dll/windows.gaming.input_main.c
+index a7d9a89244b..7d81e22ddd6 100644
+--- a/dlls/windows.gaming.input.dll/windows.gaming.input_main.c
++++ b/dlls/windows.gaming.input.dll/windows.gaming.input_main.c
+@@ -113,28 +113,31 @@ static HRESULT STDMETHODCALLTYPE vector_view_gamepad_GetAt(
+     IVectorView_Gamepad *iface, ULONG index, IGamepad **value)
+ {
+     FIXME("iface %p, index %#x, value %p stub!\n", iface, index, value);
+-    return E_NOTIMPL;
++    return S_OK;
+ }
+ 
+ static HRESULT STDMETHODCALLTYPE vector_view_gamepad_get_Size(
+     IVectorView_Gamepad *iface, ULONG *value)
+ {
+     FIXME("iface %p, value %p stub!\n", iface, value);
+-    return E_NOTIMPL;
++    *value = 0;
++    return S_OK;
+ }
+ 
+ static HRESULT STDMETHODCALLTYPE vector_view_gamepad_IndexOf(
+     IVectorView_Gamepad *iface, IGamepad *element, ULONG *index, BOOLEAN *value)
+ {
+     FIXME("iface %p, element %p, index %p, value %p stub!\n", iface, element, index, value);
+-    return E_NOTIMPL;
++    *value = FALSE;
++    return S_OK;
+ }
+ 
+ static HRESULT STDMETHODCALLTYPE vector_view_gamepad_GetMany(
+     IVectorView_Gamepad *iface, ULONG start_index, IGamepad **items, UINT *value)
+ {
+     FIXME("iface %p, start_index %#x, items %p, value %p stub!\n", iface, start_index, items, value);
+-    return E_NOTIMPL;
++    *value = 0;
++    return S_OK;
+ }
+ 
+ static const struct IVectorView_GamepadVtbl vector_view_gamepad_vtbl =
+-- 
+2.28.0
+
diff --git a/patches/windows.gaming.input-dll/0004-windows.gaming.input-Implement-IRawGameControllerSta.patch b/patches/windows.gaming.input-dll/0004-windows.gaming.input-Implement-IRawGameControllerSta.patch
deleted file mode 100644
index ecaf34da..00000000
--- a/patches/windows.gaming.input-dll/0004-windows.gaming.input-Implement-IRawGameControllerSta.patch
+++ /dev/null
@@ -1,284 +0,0 @@
-From bf6e0d12e7a2abce3548c069cc8b9bb3486419d6 Mon Sep 17 00:00:00 2001
-From: =?UTF-8?q?R=C3=A9mi=20Bernon?= <rbernon@codeweavers.com>
-Date: Fri, 21 Aug 2020 08:58:35 +0200
-Subject: [PATCH 4/4] windows.gaming.input: Implement IRawGameControllerStatics
- stubs.
-MIME-Version: 1.0
-Content-Type: text/plain; charset=UTF-8
-Content-Transfer-Encoding: 8bit
-
-Signed-off-by: Rémi Bernon <rbernon@codeweavers.com>
----
- .../windows.gaming.input_main.c               | 204 ++++++++++++++++++
- loader/wine.inf.in                            |   1 +
- 2 files changed, 205 insertions(+)
-
-diff --git a/dlls/windows.gaming.input.dll/windows.gaming.input_main.c b/dlls/windows.gaming.input.dll/windows.gaming.input_main.c
-index 44ad92980e..d17aa7ec6a 100644
---- a/dlls/windows.gaming.input.dll/windows.gaming.input_main.c
-+++ b/dlls/windows.gaming.input.dll/windows.gaming.input_main.c
-@@ -21,6 +21,7 @@ static const char *debugstr_hstring(HSTRING hstr)
- }
- 
- DEFINE_GUID(IID_IGamepadStatics,0x8bbce529,0xd49c,0x39e9,0x95,0x60,0xe4,0x7d,0xde,0x96,0xb7,0xc8);
-+DEFINE_GUID(IID_IRawGameControllerStatics,0xeb8d0792,0xe95a,0x4b19,0xaf,0xc7,0x0a,0x59,0xf8,0xbf,0x75,0x9e);
- 
- typedef struct EventRegistrationToken
- {
-@@ -149,10 +150,82 @@ struct IGamepadStatics
-     CONST_VTBL IGamepadStaticsVtbl* lpVtbl;
- };
- 
-+typedef struct IRawGameControllerStatics IRawGameControllerStatics;
-+
-+typedef struct IRawGameControllerStaticsVtbl
-+{
-+    BEGIN_INTERFACE
-+
-+    /*** IUnknown methods ***/
-+    HRESULT (STDMETHODCALLTYPE *QueryInterface)(
-+        IRawGameControllerStatics *This,
-+        REFIID riid,
-+        void **ppvObject);
-+
-+    ULONG (STDMETHODCALLTYPE *AddRef)(
-+        IRawGameControllerStatics *This);
-+
-+    ULONG (STDMETHODCALLTYPE *Release)(
-+        IRawGameControllerStatics *This);
-+
-+    /*** IInspectable methods ***/
-+    HRESULT (STDMETHODCALLTYPE *GetIids)(
-+        IRawGameControllerStatics *This,
-+        ULONG *iidCount,
-+        IID **iids);
-+
-+    HRESULT (STDMETHODCALLTYPE *GetRuntimeClassName)(
-+        IRawGameControllerStatics *This,
-+        HSTRING *className);
-+
-+    HRESULT (STDMETHODCALLTYPE *GetTrustLevel)(
-+        IRawGameControllerStatics *This,
-+        TrustLevel *trustLevel);
-+
-+    /*** IRawGameControllerStatics methods ***/
-+    HRESULT (STDMETHODCALLTYPE *eventadd_RawGameControllerAdded)(
-+        IRawGameControllerStatics *This,
-+        /* Windows.Foundation.EventHandler<Windows.Gaming.Input.RawGameController*> */
-+        void *value,
-+        EventRegistrationToken* token);
-+    HRESULT (STDMETHODCALLTYPE *eventremove_RawGameControllerAdded)(
-+        IRawGameControllerStatics *This,
-+        EventRegistrationToken token);
-+
-+    HRESULT (STDMETHODCALLTYPE *eventadd_RawGameControllerRemoved)(
-+        IRawGameControllerStatics *This,
-+        /* Windows.Foundation.EventHandler<Windows.Gaming.Input.RawGameController*> */
-+        void *value,
-+        EventRegistrationToken* token);
-+    HRESULT (STDMETHODCALLTYPE *eventremove_RawGameControllerRemoved)(
-+        IRawGameControllerStatics *This,
-+        EventRegistrationToken token);
-+
-+    HRESULT (STDMETHODCALLTYPE *get_RawGameControllers)(
-+        IRawGameControllerStatics *This,
-+        /* Windows.Foundation.Collections.IVectorView<Windows.Gaming.Input.RawGameController*>* */
-+        void **value);
-+
-+    HRESULT (STDMETHODCALLTYPE *FromGameController)(
-+        IRawGameControllerStatics *This,
-+        /* Windows.Gaming.Input.IGameController* */
-+        void *game_controller,
-+        /* Windows.Gaming.Input.RawGameController** */
-+        void **value);
-+
-+    END_INTERFACE
-+} IRawGameControllerStaticsVtbl;
-+
-+struct IRawGameControllerStatics
-+{
-+    CONST_VTBL IRawGameControllerStaticsVtbl* lpVtbl;
-+};
-+
- struct windows_gaming_input
- {
-     IActivationFactory IActivationFactory_iface;
-     IGamepadStatics IGamepadStatics_iface;
-+    IRawGameControllerStatics IRawGameControllerStatics_iface;
-     IVectorView IVectorView_iface;
-     LONG refcount;
- };
-@@ -167,6 +240,11 @@ static inline struct windows_gaming_input *impl_from_IGamepadStatics(IGamepadSta
-     return CONTAINING_RECORD(iface, struct windows_gaming_input, IGamepadStatics_iface);
- }
- 
-+static inline struct windows_gaming_input *impl_from_IRawGameControllerStatics(IRawGameControllerStatics *iface)
-+{
-+    return CONTAINING_RECORD(iface, struct windows_gaming_input, IRawGameControllerStatics_iface);
-+}
-+
- static inline struct windows_gaming_input *impl_from_IVectorView(IVectorView *iface)
- {
-     return CONTAINING_RECORD(iface, struct windows_gaming_input, IVectorView_iface);
-@@ -377,6 +455,124 @@ static const struct IGamepadStaticsVtbl gamepad_statics_vtbl =
-     gamepad_statics_get_Gamepads,
- };
- 
-+static HRESULT STDMETHODCALLTYPE raw_game_controller_statics_QueryInterface(
-+        IRawGameControllerStatics *iface, REFIID iid, void **object)
-+{
-+    TRACE("iface %p, iid %s, object %p stub!\n", iface, debugstr_guid(iid), object);
-+
-+    if (IsEqualGUID(iid, &IID_IAgileObject))
-+    {
-+        IUnknown_AddRef(iface);
-+        *object = iface;
-+        return S_OK;
-+    }
-+
-+    WARN("%s not implemented, returning E_NOINTERFACE.\n", debugstr_guid(iid));
-+    *object = NULL;
-+    return E_NOINTERFACE;
-+}
-+
-+static ULONG STDMETHODCALLTYPE raw_game_controller_statics_AddRef(
-+        IRawGameControllerStatics *iface)
-+{
-+    struct windows_gaming_input *impl = impl_from_IRawGameControllerStatics(iface);
-+    ULONG rc = InterlockedIncrement(&impl->refcount);
-+    TRACE("%p increasing refcount to %u.\n", impl, rc);
-+    return rc;
-+}
-+
-+static ULONG STDMETHODCALLTYPE raw_game_controller_statics_Release(
-+        IRawGameControllerStatics *iface)
-+{
-+    struct windows_gaming_input *impl = impl_from_IRawGameControllerStatics(iface);
-+    ULONG rc = InterlockedDecrement(&impl->refcount);
-+    TRACE("%p decreasing refcount to %u.\n", impl, rc);
-+    return rc;
-+}
-+
-+static HRESULT STDMETHODCALLTYPE raw_game_controller_statics_GetIids(
-+        IRawGameControllerStatics *iface, ULONG *iid_count, IID **iids)
-+{
-+    FIXME("iface %p, iid_count %p, iids %p stub!\n", iface, iid_count, iids);
-+    return E_NOTIMPL;
-+}
-+
-+static HRESULT STDMETHODCALLTYPE raw_game_controller_statics_GetRuntimeClassName(
-+        IRawGameControllerStatics *iface, HSTRING *class_name)
-+{
-+    FIXME("iface %p, class_name %p stub!\n", iface, class_name);
-+    return E_NOTIMPL;
-+}
-+
-+static HRESULT STDMETHODCALLTYPE raw_game_controller_statics_GetTrustLevel(
-+        IRawGameControllerStatics *iface, TrustLevel *trust_level)
-+{
-+    FIXME("iface %p, trust_level %p stub!\n", iface, trust_level);
-+    return E_NOTIMPL;
-+}
-+
-+static HRESULT STDMETHODCALLTYPE raw_game_controller_statics_eventadd_RawGameControllerAdded(
-+    IRawGameControllerStatics *iface, void *value, EventRegistrationToken* token)
-+{
-+    FIXME("iface %p, value %p, token %p stub!\n", iface, value, token);
-+    return S_OK;
-+}
-+
-+static HRESULT STDMETHODCALLTYPE raw_game_controller_statics_eventremove_RawGameControllerAdded(
-+    IRawGameControllerStatics *iface, EventRegistrationToken token)
-+{
-+    FIXME("iface %p, token %#I64x stub!\n", iface, token.value);
-+    return S_OK;
-+}
-+
-+static HRESULT STDMETHODCALLTYPE raw_game_controller_statics_eventadd_RawGameControllerRemoved(
-+    IRawGameControllerStatics *iface, void *value, EventRegistrationToken* token)
-+{
-+    FIXME("iface %p, value %p, token %p stub!\n", iface, value, token);
-+    return S_OK;
-+}
-+
-+static HRESULT STDMETHODCALLTYPE raw_game_controller_statics_eventremove_RawGameControllerRemoved(
-+    IRawGameControllerStatics *iface, EventRegistrationToken token)
-+{
-+    FIXME("iface %p, token %#I64x stub!\n", iface, token.value);
-+    return S_OK;
-+}
-+
-+static HRESULT STDMETHODCALLTYPE raw_game_controller_statics_get_RawGameControllers(
-+    IRawGameControllerStatics *iface, void **value)
-+{
-+    struct windows_gaming_input *impl = impl_from_IRawGameControllerStatics(iface);
-+    FIXME("iface %p, value %p stub!\n", iface, value);
-+    *value = &impl->IVectorView_iface;
-+    return S_OK;
-+}
-+
-+static HRESULT STDMETHODCALLTYPE raw_game_controller_statics_FromGameController(
-+    IRawGameControllerStatics *iface, void *game_controller, void **value)
-+{
-+    FIXME("iface %p, game_controller %p, value %p stub!\n", iface, game_controller, value);
-+    return E_NOTIMPL;
-+}
-+
-+static const struct IRawGameControllerStaticsVtbl raw_game_controller_statics_vtbl =
-+{
-+    raw_game_controller_statics_QueryInterface,
-+    raw_game_controller_statics_AddRef,
-+    raw_game_controller_statics_Release,
-+    /* IInspectable methods */
-+    raw_game_controller_statics_GetIids,
-+    raw_game_controller_statics_GetRuntimeClassName,
-+    raw_game_controller_statics_GetTrustLevel,
-+    /* IRawGameControllerStatics methods */
-+    raw_game_controller_statics_eventadd_RawGameControllerAdded,
-+    raw_game_controller_statics_eventremove_RawGameControllerAdded,
-+    raw_game_controller_statics_eventadd_RawGameControllerRemoved,
-+    raw_game_controller_statics_eventremove_RawGameControllerRemoved,
-+    raw_game_controller_statics_get_RawGameControllers,
-+    raw_game_controller_statics_FromGameController,
-+};
-+
- static HRESULT STDMETHODCALLTYPE windows_gaming_input_QueryInterface(
-         IActivationFactory *iface, REFIID iid, void **object)
- {
-@@ -390,6 +586,13 @@ static HRESULT STDMETHODCALLTYPE windows_gaming_input_QueryInterface(
-         return S_OK;
-     }
- 
-+    if (IsEqualGUID(iid, &IID_IRawGameControllerStatics))
-+    {
-+        IUnknown_AddRef(iface);
-+        *object = &impl->IRawGameControllerStatics_iface;
-+        return S_OK;
-+    }
-+
-     WARN("%s not implemented, returning E_NOINTERFACE.\n", debugstr_guid(iid));
-     *object = NULL;
-     return E_NOINTERFACE;
-@@ -458,6 +661,7 @@ static struct windows_gaming_input windows_gaming_input =
- {
-     {&activation_factory_vtbl},
-     {&gamepad_statics_vtbl},
-+    {&raw_game_controller_statics_vtbl},
-     {&vector_view_vtbl},
-     0
- };
-diff --git a/loader/wine.inf.in b/loader/wine.inf.in
-index a5b9e866bd..c7cab25de3 100644
---- a/loader/wine.inf.in
-+++ b/loader/wine.inf.in
-@@ -706,6 +706,7 @@ HKLM,%MciExtStr%,"wvx",,"MPEGVideo"
- 
- [Misc]
- HKLM,Software\Microsoft\WindowsRuntime\ActivatableClassId\Windows.Gaming.Input.Gamepad,"DllPath",2,"Windows.Gaming.Input.dll"
-+HKLM,Software\Microsoft\WindowsRuntime\ActivatableClassId\Windows.Gaming.Input.RawGameController,"DllPath",2,"Windows.Gaming.Input.dll"
- HKLM,Software\Borland\Database Engine\Settings\SYSTEM\INIT,SHAREDMEMLOCATION,,9000
- HKLM,Software\Clients\Mail,,2,"Native Mail Client"
- HKLM,Software\Clients\Mail\Native Mail Client,,2,"Native Mail Client"
--- 
-2.28.0
-
diff --git a/patches/windows.gaming.input-dll/0005-windows.gaming.input-Fake-IEventHandler_Gamepad-supp.patch b/patches/windows.gaming.input-dll/0005-windows.gaming.input-Fake-IEventHandler_Gamepad-supp.patch
new file mode 100644
index 00000000..d0ce359c
--- /dev/null
+++ b/patches/windows.gaming.input-dll/0005-windows.gaming.input-Fake-IEventHandler_Gamepad-supp.patch
@@ -0,0 +1,49 @@
+From 3e2a77be328b8fe724256ffa1ebd5bae72c27a70 Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?R=C3=A9mi=20Bernon?= <rbernon@codeweavers.com>
+Date: Tue, 13 Oct 2020 17:57:05 +0200
+Subject: [PATCH 5/9] windows.gaming.input: Fake IEventHandler_Gamepad support.
+
+---
+ dlls/windows.gaming.input.dll/windows.gaming.input_main.c | 8 ++++----
+ 1 file changed, 4 insertions(+), 4 deletions(-)
+
+diff --git a/dlls/windows.gaming.input.dll/windows.gaming.input_main.c b/dlls/windows.gaming.input.dll/windows.gaming.input_main.c
+index 7d81e22ddd6..dad5a196214 100644
+--- a/dlls/windows.gaming.input.dll/windows.gaming.input_main.c
++++ b/dlls/windows.gaming.input.dll/windows.gaming.input_main.c
+@@ -216,28 +216,28 @@ static HRESULT STDMETHODCALLTYPE gamepad_statics_add_GamepadAdded(
+     IGamepadStatics *iface, IEventHandler_Gamepad *value, EventRegistrationToken* token)
+ {
+     FIXME("iface %p, value %p, token %p stub!\n", iface, value, token);
+-    return E_NOTIMPL;
++    return S_OK;
+ }
+ 
+ static HRESULT STDMETHODCALLTYPE gamepad_statics_remove_GamepadAdded(
+     IGamepadStatics *iface, EventRegistrationToken token)
+ {
+     FIXME("iface %p, token %#I64x stub!\n", iface, token.value);
+-    return E_NOTIMPL;
++    return S_OK;
+ }
+ 
+ static HRESULT STDMETHODCALLTYPE gamepad_statics_add_GamepadRemoved(
+     IGamepadStatics *iface, IEventHandler_Gamepad *value, EventRegistrationToken* token)
+ {
+     FIXME("iface %p, value %p, token %p stub!\n", iface, value, token);
+-    return E_NOTIMPL;
++    return S_OK;
+ }
+ 
+ static HRESULT STDMETHODCALLTYPE gamepad_statics_remove_GamepadRemoved(
+     IGamepadStatics *iface, EventRegistrationToken token)
+ {
+     FIXME("iface %p, token %#I64x stub!\n", iface, token.value);
+-    return E_NOTIMPL;
++    return S_OK;
+ }
+ 
+ static HRESULT STDMETHODCALLTYPE gamepad_statics_get_Gamepads(
+-- 
+2.28.0
+
diff --git a/patches/windows.gaming.input-dll/0006-windows.gaming.input-Implement-IRawGameControllerSta.patch b/patches/windows.gaming.input-dll/0006-windows.gaming.input-Implement-IRawGameControllerSta.patch
new file mode 100644
index 00000000..828b4e2f
--- /dev/null
+++ b/patches/windows.gaming.input-dll/0006-windows.gaming.input-Implement-IRawGameControllerSta.patch
@@ -0,0 +1,807 @@
+From 1f000cd4305f627a8ab8b725581075fa7a3d82ab Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?R=C3=A9mi=20Bernon?= <rbernon@codeweavers.com>
+Date: Mon, 12 Oct 2020 12:50:32 +0200
+Subject: [PATCH 6/9] windows.gaming.input: Implement IRawGameControllerStatics
+ stubs.
+
+---
+ .../windows.gaming.input_main.c               | 142 +++++++++++++
+ include/Makefile.in                           |   3 +
+ include/asyncinfo.idl                         |  45 ++++
+ include/windows.foundation.idl                |  23 ++-
+ .../windows.gaming.input.forcefeedback.idl    | 111 ++++++++++
+ include/windows.gaming.input.idl              | 195 ++++++++++++++++++
+ include/windows.system.idl                    |  70 +++++++
+ loader/wine.inf.in                            |   1 +
+ 8 files changed, 589 insertions(+), 1 deletion(-)
+ create mode 100644 include/asyncinfo.idl
+ create mode 100644 include/windows.gaming.input.forcefeedback.idl
+ create mode 100644 include/windows.system.idl
+
+diff --git a/dlls/windows.gaming.input.dll/windows.gaming.input_main.c b/dlls/windows.gaming.input.dll/windows.gaming.input_main.c
+index dad5a196214..078043b0963 100644
+--- a/dlls/windows.gaming.input.dll/windows.gaming.input_main.c
++++ b/dlls/windows.gaming.input.dll/windows.gaming.input_main.c
+@@ -11,9 +11,15 @@
+ #include "activation.h"
+ 
+ #define WIDL_USING_IVECTORVIEW_1_WINDOWS_GAMING_INPUT_GAMEPAD
++#define WIDL_USING_IVECTORVIEW_1_WINDOWS_GAMING_INPUT_RAWGAMECONTROLLER
+ #define WIDL_USING_IEVENTHANDLER_1_WINDOWS_GAMING_INPUT_GAMEPAD
++#define WIDL_USING_IEVENTHANDLER_1_WINDOWS_GAMING_INPUT_RAWGAMECONTROLLER
+ #define WIDL_USING_WINDOWS_GAMING_INPUT_IGAMEPAD
+ #define WIDL_USING_WINDOWS_GAMING_INPUT_IGAMEPADSTATICS
++#define WIDL_USING_WINDOWS_GAMING_INPUT_IRAWGAMECONTROLLERSTATICS
++#define WIDL_USING_WINDOWS_GAMING_INPUT_IGAMECONTROLLER
++#define WIDL_USING_WINDOWS_GAMING_INPUT_IRAWGAMECONTROLLER
++#define WIDL_USING_WINDOWS_GAMING_INPUT_RAWGAMECONTROLLER
+ #include "windows.foundation.h"
+ #include "windows.gaming.input.h"
+ 
+@@ -32,6 +38,7 @@ struct windows_gaming_input
+ {
+     IActivationFactory IActivationFactory_iface;
+     IGamepadStatics IGamepadStatics_iface;
++    IRawGameControllerStatics IRawGameControllerStatics_iface;
+     IVectorView_Gamepad IVectorView_Gamepad_iface;
+     LONG ref;
+ };
+@@ -46,11 +53,21 @@ static inline struct windows_gaming_input *impl_from_IGamepadStatics(IGamepadSta
+     return CONTAINING_RECORD(iface, struct windows_gaming_input, IGamepadStatics_iface);
+ }
+ 
++static inline struct windows_gaming_input *impl_from_IRawGameControllerStatics(IRawGameControllerStatics *iface)
++{
++    return CONTAINING_RECORD(iface, struct windows_gaming_input, IRawGameControllerStatics_iface);
++}
++
+ static inline struct windows_gaming_input *impl_from_IVectorView_Gamepad(IVectorView_Gamepad *iface)
+ {
+     return CONTAINING_RECORD(iface, struct windows_gaming_input, IVectorView_Gamepad_iface);
+ }
+ 
++static inline struct windows_gaming_input *impl_from_IVectorView_RawGameController(IVectorView_RawGameController *iface)
++{
++    return CONTAINING_RECORD(iface, struct windows_gaming_input, IVectorView_RawGameController_iface);
++}
++
+ static HRESULT STDMETHODCALLTYPE vector_view_gamepad_QueryInterface(
+         IVectorView_Gamepad *iface, REFIID iid, void **out)
+ {
+@@ -266,6 +283,123 @@ static const struct IGamepadStaticsVtbl gamepad_statics_vtbl =
+     gamepad_statics_get_Gamepads,
+ };
+ 
++static HRESULT STDMETHODCALLTYPE raw_game_controller_statics_QueryInterface(
++        IRawGameControllerStatics *iface, REFIID iid, void **out)
++{
++    TRACE("iface %p, iid %s, out %p stub!\n", iface, debugstr_guid(iid), out);
++
++    if (IsEqualGUID(iid, &IID_IAgileObject))
++    {
++        IUnknown_AddRef(iface);
++        *out = iface;
++        return S_OK;
++    }
++
++    WARN("%s not implemented, returning E_NOINTERFACE.\n", debugstr_guid(iid));
++    *out = NULL;
++    return E_NOINTERFACE;
++}
++
++static ULONG STDMETHODCALLTYPE raw_game_controller_statics_AddRef(
++        IRawGameControllerStatics *iface)
++{
++    struct windows_gaming_input *impl = impl_from_IRawGameControllerStatics(iface);
++    ULONG ref = InterlockedIncrement(&impl->ref);
++    TRACE("iface %p, ref %u.\n", iface, ref);
++    return ref;
++}
++
++static ULONG STDMETHODCALLTYPE raw_game_controller_statics_Release(
++        IRawGameControllerStatics *iface)
++{
++    struct windows_gaming_input *impl = impl_from_IRawGameControllerStatics(iface);
++    ULONG ref = InterlockedDecrement(&impl->ref);
++    TRACE("iface %p, ref %u.\n", iface, ref);
++    return ref;
++}
++
++static HRESULT STDMETHODCALLTYPE raw_game_controller_statics_GetIids(
++        IRawGameControllerStatics *iface, ULONG *iid_count, IID **iids)
++{
++    FIXME("iface %p, iid_count %p, iids %p stub!\n", iface, iid_count, iids);
++    return E_NOTIMPL;
++}
++
++static HRESULT STDMETHODCALLTYPE raw_game_controller_statics_GetRuntimeClassName(
++        IRawGameControllerStatics *iface, HSTRING *class_name)
++{
++    FIXME("iface %p, class_name %p stub!\n", iface, class_name);
++    return E_NOTIMPL;
++}
++
++static HRESULT STDMETHODCALLTYPE raw_game_controller_statics_GetTrustLevel(
++        IRawGameControllerStatics *iface, TrustLevel *trust_level)
++{
++    FIXME("iface %p, trust_level %p stub!\n", iface, trust_level);
++    return E_NOTIMPL;
++}
++
++static HRESULT STDMETHODCALLTYPE raw_game_controller_statics_add_RawGameControllerAdded(
++    IRawGameControllerStatics *iface, IEventHandler_RawGameController *value, EventRegistrationToken* token)
++{
++    FIXME("iface %p, value %p, token %p stub!\n", iface, value, token);
++    return E_NOTIMPL;
++}
++
++static HRESULT STDMETHODCALLTYPE raw_game_controller_statics_remove_RawGameControllerAdded(
++    IRawGameControllerStatics *iface, EventRegistrationToken token)
++{
++    FIXME("iface %p, token %#I64x stub!\n", iface, token.value);
++    return E_NOTIMPL;
++}
++
++static HRESULT STDMETHODCALLTYPE raw_game_controller_statics_add_RawGameControllerRemoved(
++    IRawGameControllerStatics *iface, IEventHandler_RawGameController *value, EventRegistrationToken* token)
++{
++    FIXME("iface %p, value %p, token %p stub!\n", iface, value, token);
++    return E_NOTIMPL;
++}
++
++static HRESULT STDMETHODCALLTYPE raw_game_controller_statics_remove_RawGameControllerRemoved(
++    IRawGameControllerStatics *iface, EventRegistrationToken token)
++{
++    FIXME("iface %p, token %#I64x stub!\n", iface, token.value);
++    return E_NOTIMPL;
++}
++
++static HRESULT STDMETHODCALLTYPE raw_game_controller_statics_get_RawGameControllers(
++    IRawGameControllerStatics *iface, IVectorView_RawGameController **value)
++{
++    struct windows_gaming_input *impl = impl_from_IRawGameControllerStatics(iface);
++    FIXME("iface %p, value %p stub!\n", iface, value);
++    return E_NOTIMPL;
++}
++
++static HRESULT STDMETHODCALLTYPE raw_game_controller_statics_FromGameController(
++    IRawGameControllerStatics *iface, IGameController *game_controller, IRawGameController **value)
++{
++    FIXME("iface %p, game_controller %p, value %p stub!\n", iface, game_controller, value);
++    return E_NOTIMPL;
++}
++
++static const struct IRawGameControllerStaticsVtbl raw_game_controller_statics_vtbl =
++{
++    raw_game_controller_statics_QueryInterface,
++    raw_game_controller_statics_AddRef,
++    raw_game_controller_statics_Release,
++    /* IInspectable methods */
++    raw_game_controller_statics_GetIids,
++    raw_game_controller_statics_GetRuntimeClassName,
++    raw_game_controller_statics_GetTrustLevel,
++    /* IRawGameControllerStatics methods */
++    raw_game_controller_statics_add_RawGameControllerAdded,
++    raw_game_controller_statics_remove_RawGameControllerAdded,
++    raw_game_controller_statics_add_RawGameControllerRemoved,
++    raw_game_controller_statics_remove_RawGameControllerRemoved,
++    raw_game_controller_statics_get_RawGameControllers,
++    raw_game_controller_statics_FromGameController,
++};
++
+ static HRESULT STDMETHODCALLTYPE windows_gaming_input_QueryInterface(
+         IActivationFactory *iface, REFIID iid, void **out)
+ {
+@@ -288,6 +422,13 @@ static HRESULT STDMETHODCALLTYPE windows_gaming_input_QueryInterface(
+         return S_OK;
+     }
+ 
++    if (IsEqualGUID(iid, &IID_IRawGameControllerStatics))
++    {
++        IUnknown_AddRef(iface);
++        *out = &impl->IRawGameControllerStatics_iface;
++        return S_OK;
++    }
++
+     FIXME("%s not implemented, returning E_NOINTERFACE.\n", debugstr_guid(iid));
+     *out = NULL;
+     return E_NOINTERFACE;
+@@ -356,6 +497,7 @@ static struct windows_gaming_input windows_gaming_input =
+ {
+     {&activation_factory_vtbl},
+     {&gamepad_statics_vtbl},
++    {&raw_game_controller_statics_vtbl},
+     {&vector_view_gamepad_vtbl},
+     0
+ };
+diff --git a/include/Makefile.in b/include/Makefile.in
+index 8ae1091b8b7..e26eafb7f6a 100644
+--- a/include/Makefile.in
++++ b/include/Makefile.in
+@@ -20,6 +20,7 @@ SOURCES = \
+ 	appmodel.h \
+ 	asferr.h \
+ 	asptlb.idl \
++	asyncinfo.idl \
+ 	asynot.idl \
+ 	asysta.idl \
+ 	atlbase.h \
+@@ -736,7 +737,9 @@ SOURCES = \
+ 	windns.h \
+ 	windows.foundation.idl \
+ 	windows.gaming.input.idl \
++	windows.gaming.input.forcefeedback.idl \
+ 	windows.media.speechsynthesis.idl \
++	windows.system.idl \
+ 	windows.h \
+ 	windowscontracts.idl \
+ 	windowsx.h \
+diff --git a/include/asyncinfo.idl b/include/asyncinfo.idl
+new file mode 100644
+index 00000000000..61784bc65ac
+--- /dev/null
++++ b/include/asyncinfo.idl
+@@ -0,0 +1,45 @@
++/*
++ * 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
++ */
++
++#ifdef __WIDL__
++#pragma winrt ns_prefix
++#endif
++
++import "inspectable.idl";
++
++typedef [v1_enum] enum AsyncStatus
++{
++    Started = 0,
++    Completed, 
++    Canceled, 
++    Error,
++} AsyncStatus;
++
++[
++    object,
++    uuid(00000036-0000-0000-c000-000000000046),
++    pointer_default(unique)
++]
++interface IAsyncInfo : IInspectable
++{
++    [propget] HRESULT Id([out, retval] unsigned __int32 *id);
++    [propget] HRESULT Status([out, retval] AsyncStatus *status);
++    [propget] HRESULT ErrorCode([out, retval] HRESULT *errorCode);
++    HRESULT Cancel();
++    HRESULT Close();
++}
+diff --git a/include/windows.foundation.idl b/include/windows.foundation.idl
+index dd613b68b00..35ce1d68322 100644
+--- a/include/windows.foundation.idl
++++ b/include/windows.foundation.idl
+@@ -21,7 +21,7 @@
+ #endif
+ 
+ import "inspectable.idl";
+-/* import "asyncinfo.idl"; */
++import "asyncinfo.idl";
+ import "windowscontracts.idl";
+ /* import "eventtoken.idl"; */
+ /* import "ivectorchangedeventargs.idl"; */
+@@ -130,6 +130,25 @@ namespace Windows {
+         ]
+         delegate void TypedEventHandler<TSender, TResult>([in] TSender sender, [in] TResult args);
+ 
++        interface IAsyncOperation<TResult>;
++
++        [
++            contract(Windows.Foundation.FoundationContract, 1.0),
++            uuid(fcdcf02c-e5d8-4478-915a-4d90b74b83a5)
++        ]
++        delegate void AsyncOperationCompletedHandler<TResult>([in] IAsyncOperation<TResult> *info, [in] AsyncStatus status);
++
++        [
++            contract(Windows.Foundation.FoundationContract, 1.0),
++            uuid(9fc2b0bb-e446-44e2-aa61-9cab8f636af2)
++        ]
++        interface IAsyncOperation<TResult> : IInspectable
++        {
++            [propput] HRESULT Completed([in] AsyncOperationCompletedHandler<TResult> *handler);
++            [propget] HRESULT Completed([out, retval] AsyncOperationCompletedHandler<TResult> **handler);
++            HRESULT GetResults([out, retval] TResult **results);
++        }
++
+         namespace Collections
+         {
+             [
+@@ -173,6 +192,8 @@ namespace Windows {
+     namespace Foundation {
+         declare {
+             interface Windows.Foundation.Collections.IVectorView<HSTRING>;
++            interface Windows.Foundation.AsyncOperationCompletedHandler<boolean>;
++            interface Windows.Foundation.IAsyncOperation<boolean>;
+         }
+     }
+ }
+diff --git a/include/windows.gaming.input.forcefeedback.idl b/include/windows.gaming.input.forcefeedback.idl
+new file mode 100644
+index 00000000000..fa9da2f7656
+--- /dev/null
++++ b/include/windows.gaming.input.forcefeedback.idl
+@@ -0,0 +1,111 @@
++/*
++ * 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
++ */
++
++#ifdef __WIDL__
++#pragma winrt ns_prefix
++#endif
++
++import "inspectable.idl";
++import "windows.foundation.idl";
++
++namespace Windows {
++    namespace Gaming {
++        namespace Input {
++            namespace ForceFeedback {
++                typedef enum ForceFeedbackEffectAxes ForceFeedbackEffectAxes;
++                typedef enum ForceFeedbackLoadEffectResult ForceFeedbackLoadEffectResult;
++                interface IForceFeedbackEffect;
++                runtimeclass ForceFeedbackMotor;
++            }
++        }
++    }
++}
++
++namespace Windows {
++    namespace Gaming {
++        namespace Input {
++            namespace ForceFeedback {
++                declare {
++                    interface Windows.Foundation.AsyncOperationCompletedHandler<Windows.Gaming.Input.ForceFeedback.ForceFeedbackLoadEffectResult>;
++                    interface Windows.Foundation.IAsyncOperation<Windows.Gaming.Input.ForceFeedback.ForceFeedbackLoadEffectResult>;
++                    interface Windows.Foundation.Collections.IVectorView<Windows.Gaming.Input.ForceFeedback.ForceFeedbackMotor*>;
++                }
++            }
++        }
++    }
++}
++
++namespace Windows {
++    namespace Gaming {
++        namespace Input {
++            namespace ForceFeedback {
++                [
++                    contract(Windows.Foundation.UniversalApiContract, 3.0),
++                    flags
++                ]
++                enum ForceFeedbackEffectAxes
++                {
++                    None = 0x0,
++                    X    = 0x1,
++                    Y    = 0x2,
++                    Z    = 0x4
++                };
++
++                [contract(Windows.Foundation.UniversalApiContract, 3.0)]
++                enum ForceFeedbackLoadEffectResult
++                {
++                    Succeeded          = 0,
++                    EffectStorageFull  = 1,
++                    EffectNotSupported = 2
++                };
++
++                [
++                    contract(Windows.Foundation.UniversalApiContract, 3.0),
++                    exclusiveto(Windows.Gaming.Input.ForceFeedback.ForceFeedbackMotor),
++                    uuid(8d3d417c-a5ea-4516-8026-2b00f74ef6e5)
++                ]
++                interface IForceFeedbackMotor : IInspectable
++                {
++                    [propget] HRESULT AreEffectsPaused([out, retval] boolean* value);
++                    [propget] HRESULT MasterGain([out, retval] DOUBLE* value);
++                    [propput] HRESULT MasterGain([in] DOUBLE value);
++                    [propget] HRESULT IsEnabled([out, retval] boolean* value);
++                    [propget] HRESULT SupportedAxes([out, retval] Windows.Gaming.Input.ForceFeedback.ForceFeedbackEffectAxes* value);
++                    HRESULT LoadEffectAsync([in] Windows.Gaming.Input.ForceFeedback.IForceFeedbackEffect* effect, [out, retval] Windows.Foundation.IAsyncOperation<Windows.Gaming.Input.ForceFeedback.ForceFeedbackLoadEffectResult>** asyncOperation);
++                    HRESULT PauseAllEffects();
++                    HRESULT ResumeAllEffects();
++                    HRESULT StopAllEffects();
++                    HRESULT TryDisableAsync([out, retval] Windows.Foundation.IAsyncOperation<boolean>** asyncOperation);
++                    HRESULT TryEnableAsync([out, retval] Windows.Foundation.IAsyncOperation<boolean>** asyncOperation);
++                    HRESULT TryResetAsync([out, retval] Windows.Foundation.IAsyncOperation<boolean>** asyncOperation);
++                    HRESULT TryUnloadEffectAsync([in] Windows.Gaming.Input.ForceFeedback.IForceFeedbackEffect* effect, [out, retval] Windows.Foundation.IAsyncOperation<boolean>** asyncOperation);
++                }
++
++                [
++                    contract(Windows.Foundation.UniversalApiContract, 3.0),
++                    marshaling_behavior(agile),
++                    threading(both)
++                ]
++                runtimeclass ForceFeedbackMotor
++                {
++                    [default] interface Windows.Gaming.Input.ForceFeedback.IForceFeedbackMotor;
++                }
++            }
++        }
++    }
++}
+diff --git a/include/windows.gaming.input.idl b/include/windows.gaming.input.idl
+index b5af4e24a66..36d4038ed1f 100644
+--- a/include/windows.gaming.input.idl
++++ b/include/windows.gaming.input.idl
+@@ -22,11 +22,16 @@
+ 
+ import "inspectable.idl";
+ import "windows.foundation.idl";
++import "windows.system.idl";
++import "windows.gaming.input.forcefeedback.idl";
+ 
+ namespace Windows {
+     namespace Gaming {
+         namespace Input {
+             typedef enum GamepadButtons GamepadButtons;
++            typedef enum GameControllerButtonLabel GameControllerButtonLabel;
++            typedef enum GameControllerSwitchKind GameControllerSwitchKind;
++            typedef enum GameControllerSwitchPosition GameControllerSwitchPosition;
+             typedef struct GamepadReading GamepadReading;
+             typedef struct GamepadVibration GamepadVibration;
+             interface IGameController;
+@@ -35,7 +40,11 @@ namespace Windows {
+             interface IGamepad2;
+             interface IGamepadStatics;
+             interface IGamepadStatics2;
++            interface IRawGameController;
++            interface IRawGameController2;
+             runtimeclass Gamepad;
++            runtimeclass Headset;
++            runtimeclass RawGameController;
+         }
+     }
+ }
+@@ -45,7 +54,11 @@ namespace Windows {
+         namespace Input {
+             declare {
+                 interface Windows.Foundation.EventHandler<Windows.Gaming.Input.Gamepad*>;
++                interface Windows.Foundation.EventHandler<Windows.Gaming.Input.RawGameController*>;
++                interface Windows.Foundation.TypedEventHandler<Windows.Gaming.Input.IGameController*, Windows.Gaming.Input.Headset*>;
++                interface Windows.Foundation.TypedEventHandler<Windows.Gaming.Input.IGameController*, Windows.System.UserChangedEventArgs*>;
+                 interface Windows.Foundation.Collections.IVectorView<Gamepad*>;
++                interface Windows.Foundation.Collections.IVectorView<Windows.Gaming.Input.RawGameController*>;
+             }
+         }
+     }
+@@ -85,6 +98,102 @@ namespace Windows {
+                 Paddle4 = 0x20000
+             };
+ 
++            [contract(Windows.Foundation.UniversalApiContract, 3.0)]
++            enum GameControllerButtonLabel
++            {
++                None                 = 0,
++                XboxBack             = 1,
++                XboxStart            = 2,
++                XboxMenu             = 3,
++                XboxView             = 4,
++                XboxUp               = 5,
++                XboxDown             = 6,
++                XboxLeft             = 7,
++                XboxRight            = 8,
++                XboxA                = 9,
++                XboxB                = 10,
++                XboxX                = 11,
++                XboxY                = 12,
++                XboxLeftBumper       = 13,
++                XboxLeftTrigger      = 14,
++                XboxLeftStickButton  = 15,
++                XboxRightBumper      = 16,
++                XboxRightTrigger     = 17,
++                XboxRightStickButton = 18,
++                XboxPaddle1          = 19,
++                XboxPaddle2          = 20,
++                XboxPaddle3          = 21,
++                XboxPaddle4          = 22,
++                Mode                 = 23,
++                Select               = 24,
++                Menu                 = 25,
++                View                 = 26,
++                Back                 = 27,
++                Start                = 28,
++                Options              = 29,
++                Share                = 30,
++                Up                   = 31,
++                Down                 = 32,
++                Left                 = 33,
++                Right                = 34,
++                LetterA              = 35,
++                LetterB              = 36,
++                LetterC              = 37,
++                LetterL              = 38,
++                LetterR              = 39,
++                LetterX              = 40,
++                LetterY              = 41,
++                LetterZ              = 42,
++                Cross                = 43,
++                Circle               = 44,
++                Square               = 45,
++                Triangle             = 46,
++                LeftBumper           = 47,
++                LeftTrigger          = 48,
++                LeftStickButton      = 49,
++                Left1                = 50,
++                Left2                = 51,
++                Left3                = 52,
++                RightBumper          = 53,
++                RightTrigger         = 54,
++                RightStickButton     = 55,
++                Right1               = 56,
++                Right2               = 57,
++                Right3               = 58,
++                Paddle1              = 59,
++                Paddle2              = 60,
++                Paddle3              = 61,
++                Paddle4              = 62,
++                Plus                 = 63,
++                Minus                = 64,
++                DownLeftArrow        = 65,
++                DialLeft             = 66,
++                DialRight            = 67,
++                Suspension           = 68
++            };
++
++            [contract(Windows.Foundation.UniversalApiContract, 4.0)]
++            enum GameControllerSwitchKind
++            {
++                TwoWay   = 0,
++                FourWay  = 1,
++                EightWay = 2
++            };
++
++            [contract(Windows.Foundation.UniversalApiContract, 4.0)]
++            enum GameControllerSwitchPosition
++            {
++                Center    = 0,
++                Up        = 1,
++                UpRight   = 2,
++                Right     = 3,
++                DownRight = 4,
++                Down      = 5,
++                DownLeft  = 6,
++                Left      = 7,
++                UpLeft    = 8
++            };
++
+             [contract(Windows.Foundation.UniversalApiContract, 1.0)]
+             struct GamepadReading
+             {
+@@ -107,6 +216,23 @@ namespace Windows {
+                 DOUBLE RightTrigger;
+             };
+ 
++            [
++                contract(Windows.Foundation.UniversalApiContract, 1.0),
++                uuid(1baf6522-5f64-42c5-8267-b9fe2215bfbd)
++            ]
++            interface IGameController : IInspectable
++            {
++                [eventadd] HRESULT HeadsetConnected([in] Windows.Foundation.TypedEventHandler<Windows.Gaming.Input.IGameController*, Windows.Gaming.Input.Headset*>* value, [out, retval] EventRegistrationToken* token);
++                [eventremove] HRESULT HeadsetConnected([in] EventRegistrationToken token);
++                [eventadd] HRESULT HeadsetDisconnected([in] Windows.Foundation.TypedEventHandler<Windows.Gaming.Input.IGameController*, Windows.Gaming.Input.Headset*>* value, [out, retval] EventRegistrationToken* token);
++                [eventremove] HRESULT HeadsetDisconnected([in] EventRegistrationToken token);
++                [eventadd] HRESULT UserChanged([in] Windows.Foundation.TypedEventHandler<Windows.Gaming.Input.IGameController*, Windows.System.UserChangedEventArgs*>* value, [out, retval] EventRegistrationToken* token);
++                [eventremove] HRESULT UserChanged([in] EventRegistrationToken token);
++                [propget] HRESULT Headset([out, retval] Windows.Gaming.Input.Headset** value);
++                [propget] HRESULT IsWireless([out, retval] boolean* value);
++                [propget] HRESULT User([out, retval] Windows.System.User** value);
++            }
++
+             [
+                 contract(Windows.Foundation.UniversalApiContract, 1.0),
+                 exclusiveto(Windows.Gaming.Input.Gamepad),
+@@ -120,6 +246,25 @@ namespace Windows {
+                 HRESULT GetCurrentReading([out, retval] Windows.Gaming.Input.GamepadReading* value);
+             }
+ 
++            [
++                contract(Windows.Foundation.UniversalApiContract, 4.0),
++                exclusiveto(Windows.Gaming.Input.RawGameController),
++                uuid(7cad6d91-a7e1-4f71-9a78-33e9c5dfea62)
++            ]
++            interface IRawGameController : IInspectable
++                requires Windows.Gaming.Input.IGameController
++            {
++                [propget] HRESULT AxisCount([out] [retval] INT32* value);
++                [propget] HRESULT ButtonCount([out] [retval] INT32* value);
++                [propget] HRESULT ForceFeedbackMotors([out] [retval] Windows.Foundation.Collections.IVectorView<Windows.Gaming.Input.ForceFeedback.ForceFeedbackMotor*>** value);
++                [propget] HRESULT HardwareProductId([out] [retval] UINT16* value);
++                [propget] HRESULT HardwareVendorId([out] [retval] UINT16* value);
++                [propget] HRESULT SwitchCount([out] [retval] INT32* value);
++                HRESULT GetButtonLabel([in] INT32 buttonIndex, [out] [retval] Windows.Gaming.Input.GameControllerButtonLabel* value);
++                HRESULT GetCurrentReading([in] UINT32 __buttonArraySize, [out] [size_is(__buttonArraySize)] boolean* buttonArray, [in] UINT32 __switchArraySize, [out] [size_is(__switchArraySize)] Windows.Gaming.Input.GameControllerSwitchPosition* switchArray, [in] UINT32 __axisArraySize, [out] [size_is(__axisArraySize)] DOUBLE* axisArray, [out] [retval] UINT64* timestamp);
++                HRESULT GetSwitchKind([in] INT32 switchIndex, [out] [retval] Windows.Gaming.Input.GameControllerSwitchKind* value);
++            }
++
+             [
+                 object,
+                 uuid(8bbce529-d49c-39e9-9560-e47dde96b7c8)
+@@ -133,6 +278,31 @@ namespace Windows {
+                 [propget] HRESULT Gamepads([out, retval] Windows.Foundation.Collections.IVectorView<Gamepad*> **value);
+             }
+ 
++            [
++                contract(Windows.Foundation.UniversalApiContract, 1.0),
++                exclusiveto(Windows.Gaming.Input.Headset),
++                uuid(3fd156ef-6925-3fa8-9181-029c5223ae3b)
++            ]
++            interface IHeadset : IInspectable
++            {
++                [propget] HRESULT CaptureDeviceId([out, retval] HSTRING* value);
++                [propget] HRESULT RenderDeviceId([out, retval] HSTRING* value);
++            }
++
++            [
++                object,
++                uuid(eb8d0792-e95a-4b19-afc7-0a59f8bf759e)
++            ]
++            interface IRawGameControllerStatics : IInspectable
++            {
++                [eventadd] HRESULT RawGameControllerAdded([in] Windows.Foundation.EventHandler<Windows.Gaming.Input.RawGameController*> *value, [out, retval] EventRegistrationToken* token);
++                [eventremove] HRESULT RawGameControllerAdded([in] EventRegistrationToken token);
++                [eventadd] HRESULT RawGameControllerRemoved([in] Windows.Foundation.EventHandler<Windows.Gaming.Input.RawGameController*> *value, [out, retval] EventRegistrationToken* token);
++                [eventremove] HRESULT RawGameControllerRemoved([in] EventRegistrationToken token);
++                [propget] HRESULT RawGameControllers([out, retval] Windows.Foundation.Collections.IVectorView<Windows.Gaming.Input.RawGameController*> **value);
++                HRESULT FromGameController([in] Windows.Gaming.Input.IGameController *game_controller, [out, retval] Windows.Gaming.Input.RawGameController **value);
++            }
++
+             [
+                 contract(Windows.Foundation.UniversalApiContract, 1.0),
+                 marshaling_behavior(agile),
+@@ -147,6 +317,31 @@ namespace Windows {
+                 [contract(Windows.Foundation.UniversalApiContract, 3.0)] interface Windows.Gaming.Input.IGamepad2;
+                 [contract(Windows.Foundation.UniversalApiContract, 4.0)] interface Windows.Gaming.Input.IGameControllerBatteryInfo;
+             }
++
++            [
++                contract(Windows.Foundation.UniversalApiContract, 1.0),
++                marshaling_behavior(agile),
++                threading(both)
++            ]
++            runtimeclass Headset
++            {
++                [default] interface Windows.Gaming.Input.IHeadset;
++                [contract(Windows.Foundation.UniversalApiContract, 4.0)] interface Windows.Gaming.Input.IGameControllerBatteryInfo;
++            }
++
++            [
++                contract(Windows.Foundation.UniversalApiContract, 4.0),
++                marshaling_behavior(agile),
++                static(Windows.Gaming.Input.IRawGameControllerStatics, Windows.Foundation.UniversalApiContract, 4.0),
++                threading(both)
++            ]
++            runtimeclass RawGameController
++            {
++                [default] interface Windows.Gaming.Input.IRawGameController;
++                interface Windows.Gaming.Input.IGameController;
++                interface Windows.Gaming.Input.IGameControllerBatteryInfo;
++                [contract(Windows.Foundation.UniversalApiContract, 5.0)] interface Windows.Gaming.Input.IRawGameController2;
++            }
+         }
+     }
+ }
+diff --git a/include/windows.system.idl b/include/windows.system.idl
+new file mode 100644
+index 00000000000..824441eaff9
+--- /dev/null
++++ b/include/windows.system.idl
+@@ -0,0 +1,70 @@
++/*
++ * 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
++ */
++
++#ifdef __WIDL__
++#pragma winrt ns_prefix
++#endif
++
++import "inspectable.idl";
++import "windows.foundation.idl";
++
++namespace Windows {
++    namespace System {
++        interface IUser;
++        interface IUserStatics;
++        interface IUserChangedEventArgs;
++        interface IUserChangedEventArgs2;
++        runtimeclass User;
++        runtimeclass UserChangedEventArgs;
++    }
++}
++
++namespace Windows {
++    namespace System {
++        [
++            contract(Windows.Foundation.UniversalApiContract, 1.0),
++            exclusiveto(Windows.System.UserChangedEventArgs),
++            uuid(086459dc-18c6-48db-bc99-724fb9203ccc)
++        ]
++        interface IUserChangedEventArgs : IInspectable
++        {
++            [propget] HRESULT User([out, retval] Windows.System.User** value);
++        }
++
++        [
++            contract(Windows.Foundation.UniversalApiContract, 1.0),
++            marshaling_behavior(agile),
++            static(Windows.System.IUserStatics, Windows.Foundation.UniversalApiContract, 1.0),
++            threading(both),
++        ]
++        runtimeclass User
++        {
++            [default] interface Windows.System.IUser;
++        }
++
++        [
++            contract(Windows.Foundation.UniversalApiContract, 1.0),
++            marshaling_behavior(agile)
++        ]
++        runtimeclass UserChangedEventArgs
++        {
++            [default] interface Windows.System.IUserChangedEventArgs;
++            [contract(Windows.Foundation.UniversalApiContract, 10.0)] interface Windows.System.IUserChangedEventArgs2;
++        }
++    }
++}
+diff --git a/loader/wine.inf.in b/loader/wine.inf.in
+index 9d738859b81..ab18ab97e4c 100644
+--- a/loader/wine.inf.in
++++ b/loader/wine.inf.in
+@@ -714,6 +714,7 @@ HKLM,%MciExtStr%,"wvx",,"MPEGVideo"
+ 
+ [Misc]
+ HKLM,Software\Microsoft\WindowsRuntime\ActivatableClassId\Windows.Gaming.Input.Gamepad,"DllPath",2,"Windows.Gaming.Input.dll"
++HKLM,Software\Microsoft\WindowsRuntime\ActivatableClassId\Windows.Gaming.Input.RawGameController,"DllPath",2,"Windows.Gaming.Input.dll"
+ HKLM,Software\Microsoft\WindowsRuntime\ActivatableClassId\Windows.Media.SpeechSynthesis.SpeechSynthesizer,"DllPath",2,"Windows.Media.Speech.dll"
+ HKLM,Software\Borland\Database Engine\Settings\SYSTEM\INIT,SHAREDMEMLOCATION,,9000
+ HKLM,Software\Clients\Mail,,2,"Native Mail Client"
+-- 
+2.28.0
+
diff --git a/patches/windows.gaming.input-dll/0007-windows.gaming.input-Implement-IRawGameControllerSta.patch b/patches/windows.gaming.input-dll/0007-windows.gaming.input-Implement-IRawGameControllerSta.patch
new file mode 100644
index 00000000..e2a1bf29
--- /dev/null
+++ b/patches/windows.gaming.input-dll/0007-windows.gaming.input-Implement-IRawGameControllerSta.patch
@@ -0,0 +1,152 @@
+From 655ea5abd545db3990caf7c79909cb4993b52cef Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?R=C3=A9mi=20Bernon?= <rbernon@codeweavers.com>
+Date: Tue, 13 Oct 2020 18:02:39 +0200
+Subject: [PATCH 7/9] windows.gaming.input: Implement
+ IRawGameControllerStatics::RawGameControllers stubs.
+
+---
+ .../windows.gaming.input_main.c               | 107 +++++++++++++++++-
+ 1 file changed, 106 insertions(+), 1 deletion(-)
+
+diff --git a/dlls/windows.gaming.input.dll/windows.gaming.input_main.c b/dlls/windows.gaming.input.dll/windows.gaming.input_main.c
+index 078043b0963..c73f08b248d 100644
+--- a/dlls/windows.gaming.input.dll/windows.gaming.input_main.c
++++ b/dlls/windows.gaming.input.dll/windows.gaming.input_main.c
+@@ -40,6 +40,7 @@ struct windows_gaming_input
+     IGamepadStatics IGamepadStatics_iface;
+     IRawGameControllerStatics IRawGameControllerStatics_iface;
+     IVectorView_Gamepad IVectorView_Gamepad_iface;
++    IVectorView_RawGameController IVectorView_RawGameController_iface;
+     LONG ref;
+ };
+ 
+@@ -173,6 +174,108 @@ static const struct IVectorView_GamepadVtbl vector_view_gamepad_vtbl =
+     vector_view_gamepad_GetMany,
+ };
+ 
++static HRESULT STDMETHODCALLTYPE vector_view_raw_game_controller_QueryInterface(
++        IVectorView_RawGameController *iface, REFIID iid, void **out)
++{
++    TRACE("iface %p, iid %s, out %p stub!\n", iface, debugstr_guid(iid), out);
++
++    if (IsEqualGUID(iid, &IID_IUnknown) ||
++        IsEqualGUID(iid, &IID_IInspectable) ||
++        IsEqualGUID(iid, &IID_IVectorView_RawGameController))
++    {
++        IUnknown_AddRef(iface);
++        *out = iface;
++        return S_OK;
++    }
++
++    WARN("%s not implemented, returning E_NOINTERFACE.\n", debugstr_guid(iid));
++    *out = NULL;
++    return E_NOINTERFACE;
++}
++
++static ULONG STDMETHODCALLTYPE vector_view_raw_game_controller_AddRef(
++        IVectorView_RawGameController *iface)
++{
++    struct windows_gaming_input *impl = impl_from_IVectorView_RawGameController(iface);
++    ULONG ref = InterlockedIncrement(&impl->ref);
++    TRACE("iface %p, ref %u.\n", iface, ref);
++    return ref;
++}
++
++static ULONG STDMETHODCALLTYPE vector_view_raw_game_controller_Release(
++        IVectorView_RawGameController *iface)
++{
++    struct windows_gaming_input *impl = impl_from_IVectorView_RawGameController(iface);
++    ULONG ref = InterlockedDecrement(&impl->ref);
++    TRACE("iface %p, ref %u.\n", iface, ref);
++    return ref;
++}
++
++static HRESULT STDMETHODCALLTYPE vector_view_raw_game_controller_GetIids(
++        IVectorView_RawGameController *iface, ULONG *iid_count, IID **iids)
++{
++    FIXME("iface %p, iid_count %p, iids %p stub!\n", iface, iid_count, iids);
++    return E_NOTIMPL;
++}
++
++static HRESULT STDMETHODCALLTYPE vector_view_raw_game_controller_GetRuntimeClassName(
++        IVectorView_RawGameController *iface, HSTRING *class_name)
++{
++    FIXME("iface %p, class_name %p stub!\n", iface, class_name);
++    return E_NOTIMPL;
++}
++
++static HRESULT STDMETHODCALLTYPE vector_view_raw_game_controller_GetTrustLevel(
++        IVectorView_RawGameController *iface, TrustLevel *trust_level)
++{
++    FIXME("iface %p, trust_level %p stub!\n", iface, trust_level);
++    return E_NOTIMPL;
++}
++
++static HRESULT STDMETHODCALLTYPE vector_view_raw_game_controller_GetAt(
++    IVectorView_RawGameController *iface, ULONG index, IRawGameController **value)
++{
++    FIXME("iface %p, index %#x, value %p stub!\n", iface, index, value);
++    return E_NOTIMPL;
++}
++
++static HRESULT STDMETHODCALLTYPE vector_view_raw_game_controller_get_Size(
++    IVectorView_RawGameController *iface, ULONG *value)
++{
++    FIXME("iface %p, value %p stub!\n", iface, value);
++    return E_NOTIMPL;
++}
++
++static HRESULT STDMETHODCALLTYPE vector_view_raw_game_controller_IndexOf(
++    IVectorView_RawGameController *iface, IRawGameController *element, ULONG *index, BOOLEAN *value)
++{
++    FIXME("iface %p, element %p, index %p, value %p stub!\n", iface, element, index, value);
++    return E_NOTIMPL;
++}
++
++static HRESULT STDMETHODCALLTYPE vector_view_raw_game_controller_GetMany(
++    IVectorView_RawGameController *iface, ULONG start_index, IRawGameController **items, UINT *value)
++{
++    FIXME("iface %p, start_index %#x, items %p, value %p stub!\n", iface, start_index, items, value);
++    return E_NOTIMPL;
++}
++
++static const struct IVectorView_RawGameControllerVtbl vector_view_raw_game_controller_vtbl =
++{
++    vector_view_raw_game_controller_QueryInterface,
++    vector_view_raw_game_controller_AddRef,
++    vector_view_raw_game_controller_Release,
++    /* IInspectable methods */
++    vector_view_raw_game_controller_GetIids,
++    vector_view_raw_game_controller_GetRuntimeClassName,
++    vector_view_raw_game_controller_GetTrustLevel,
++    /* IVectorView<RawGameController> methods */
++    vector_view_raw_game_controller_GetAt,
++    vector_view_raw_game_controller_get_Size,
++    vector_view_raw_game_controller_IndexOf,
++    vector_view_raw_game_controller_GetMany,
++};
++
+ static HRESULT STDMETHODCALLTYPE gamepad_statics_QueryInterface(
+         IGamepadStatics *iface, REFIID iid, void **out)
+ {
+@@ -372,7 +475,8 @@ static HRESULT STDMETHODCALLTYPE raw_game_controller_statics_get_RawGameControll
+ {
+     struct windows_gaming_input *impl = impl_from_IRawGameControllerStatics(iface);
+     FIXME("iface %p, value %p stub!\n", iface, value);
+-    return E_NOTIMPL;
++    *value = &impl->IVectorView_RawGameController_iface;
++    return S_OK;
+ }
+ 
+ static HRESULT STDMETHODCALLTYPE raw_game_controller_statics_FromGameController(
+@@ -499,6 +603,7 @@ static struct windows_gaming_input windows_gaming_input =
+     {&gamepad_statics_vtbl},
+     {&raw_game_controller_statics_vtbl},
+     {&vector_view_gamepad_vtbl},
++    {&vector_view_raw_game_controller_vtbl},
+     0
+ };
+ 
+-- 
+2.28.0
+
diff --git a/patches/windows.gaming.input-dll/0008-windows.gaming.input-Fake-empty-IRawGameControllerSt.patch b/patches/windows.gaming.input-dll/0008-windows.gaming.input-Fake-empty-IRawGameControllerSt.patch
new file mode 100644
index 00000000..de657920
--- /dev/null
+++ b/patches/windows.gaming.input-dll/0008-windows.gaming.input-Fake-empty-IRawGameControllerSt.patch
@@ -0,0 +1,53 @@
+From 66d48431b91c17e3f87246e2c2243b2c2b5b30fb Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?R=C3=A9mi=20Bernon?= <rbernon@codeweavers.com>
+Date: Tue, 13 Oct 2020 18:03:24 +0200
+Subject: [PATCH 8/9] windows.gaming.input: Fake empty
+ IRawGameControllerStatics::RawGameControllers vector.
+
+---
+ .../windows.gaming.input_main.c                       | 11 +++++++----
+ 1 file changed, 7 insertions(+), 4 deletions(-)
+
+diff --git a/dlls/windows.gaming.input.dll/windows.gaming.input_main.c b/dlls/windows.gaming.input.dll/windows.gaming.input_main.c
+index c73f08b248d..53f0b7e61fd 100644
+--- a/dlls/windows.gaming.input.dll/windows.gaming.input_main.c
++++ b/dlls/windows.gaming.input.dll/windows.gaming.input_main.c
+@@ -236,28 +236,31 @@ static HRESULT STDMETHODCALLTYPE vector_view_raw_game_controller_GetAt(
+     IVectorView_RawGameController *iface, ULONG index, IRawGameController **value)
+ {
+     FIXME("iface %p, index %#x, value %p stub!\n", iface, index, value);
+-    return E_NOTIMPL;
++    return S_OK;
+ }
+ 
+ static HRESULT STDMETHODCALLTYPE vector_view_raw_game_controller_get_Size(
+     IVectorView_RawGameController *iface, ULONG *value)
+ {
+     FIXME("iface %p, value %p stub!\n", iface, value);
+-    return E_NOTIMPL;
++    *value = 0;
++    return S_OK;
+ }
+ 
+ static HRESULT STDMETHODCALLTYPE vector_view_raw_game_controller_IndexOf(
+     IVectorView_RawGameController *iface, IRawGameController *element, ULONG *index, BOOLEAN *value)
+ {
+     FIXME("iface %p, element %p, index %p, value %p stub!\n", iface, element, index, value);
+-    return E_NOTIMPL;
++    *value = FALSE;
++    return S_OK;
+ }
+ 
+ static HRESULT STDMETHODCALLTYPE vector_view_raw_game_controller_GetMany(
+     IVectorView_RawGameController *iface, ULONG start_index, IRawGameController **items, UINT *value)
+ {
+     FIXME("iface %p, start_index %#x, items %p, value %p stub!\n", iface, start_index, items, value);
+-    return E_NOTIMPL;
++    *value = 0;
++    return S_OK;
+ }
+ 
+ static const struct IVectorView_RawGameControllerVtbl vector_view_raw_game_controller_vtbl =
+-- 
+2.28.0
+
diff --git a/patches/windows.gaming.input-dll/0009-windows.gaming.input-Fake-IEventHandler_RawGameContr.patch b/patches/windows.gaming.input-dll/0009-windows.gaming.input-Fake-IEventHandler_RawGameContr.patch
new file mode 100644
index 00000000..99daccf1
--- /dev/null
+++ b/patches/windows.gaming.input-dll/0009-windows.gaming.input-Fake-IEventHandler_RawGameContr.patch
@@ -0,0 +1,50 @@
+From 47c3fa730f9607b5907747a143cf0458a2a76c35 Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?R=C3=A9mi=20Bernon?= <rbernon@codeweavers.com>
+Date: Tue, 13 Oct 2020 18:03:42 +0200
+Subject: [PATCH 9/9] windows.gaming.input: Fake
+ IEventHandler_RawGameController support.
+
+---
+ dlls/windows.gaming.input.dll/windows.gaming.input_main.c | 8 ++++----
+ 1 file changed, 4 insertions(+), 4 deletions(-)
+
+diff --git a/dlls/windows.gaming.input.dll/windows.gaming.input_main.c b/dlls/windows.gaming.input.dll/windows.gaming.input_main.c
+index 53f0b7e61fd..a9d09d4a446 100644
+--- a/dlls/windows.gaming.input.dll/windows.gaming.input_main.c
++++ b/dlls/windows.gaming.input.dll/windows.gaming.input_main.c
+@@ -449,28 +449,28 @@ static HRESULT STDMETHODCALLTYPE raw_game_controller_statics_add_RawGameControll
+     IRawGameControllerStatics *iface, IEventHandler_RawGameController *value, EventRegistrationToken* token)
+ {
+     FIXME("iface %p, value %p, token %p stub!\n", iface, value, token);
+-    return E_NOTIMPL;
++    return S_OK;
+ }
+ 
+ static HRESULT STDMETHODCALLTYPE raw_game_controller_statics_remove_RawGameControllerAdded(
+     IRawGameControllerStatics *iface, EventRegistrationToken token)
+ {
+     FIXME("iface %p, token %#I64x stub!\n", iface, token.value);
+-    return E_NOTIMPL;
++    return S_OK;
+ }
+ 
+ static HRESULT STDMETHODCALLTYPE raw_game_controller_statics_add_RawGameControllerRemoved(
+     IRawGameControllerStatics *iface, IEventHandler_RawGameController *value, EventRegistrationToken* token)
+ {
+     FIXME("iface %p, value %p, token %p stub!\n", iface, value, token);
+-    return E_NOTIMPL;
++    return S_OK;
+ }
+ 
+ static HRESULT STDMETHODCALLTYPE raw_game_controller_statics_remove_RawGameControllerRemoved(
+     IRawGameControllerStatics *iface, EventRegistrationToken token)
+ {
+     FIXME("iface %p, token %#I64x stub!\n", iface, token.value);
+-    return E_NOTIMPL;
++    return S_OK;
+ }
+ 
+ static HRESULT STDMETHODCALLTYPE raw_game_controller_statics_get_RawGameControllers(
+-- 
+2.28.0
+
diff --git a/patches/windows.gaming.input-dll/definition b/patches/windows.gaming.input-dll/definition
index f79028c8..120b5bff 100644
--- a/patches/windows.gaming.input-dll/definition
+++ b/patches/windows.gaming.input-dll/definition
@@ -5,3 +5,4 @@
 # https://source.winehq.org/patches/data/191192
 # To support Death Stranding
 Fixes: [49756] windows.gaming.input: New DLL
+Depends: windows.media.speech.dll
diff --git a/patches/windows.media.speech.dll/definition b/patches/windows.media.speech.dll/definition
index 44ad32b6..eb60c295 100644
--- a/patches/windows.media.speech.dll/definition
+++ b/patches/windows.media.speech.dll/definition
@@ -1,2 +1,2 @@
 Fixes: [49740] windows.media.speech: New DLL
-Depends: windows.gaming.input-dll
+Depends: widl-winrt-support