From 045f49ecb29e1bc4648e0784688f70a6775d5d95 Mon Sep 17 00:00:00 2001
From: Paul "TBBle" Hampson <Paul.Hampson@Pobox.com>
Date: Sat, 18 Apr 2009 18:08:05 +1000
Subject: [PATCH 1/3] dinput: Seperate mouse and keyboard driver lists

If any mouse or keyboard driver enumerates a device, stop
processing that class of device for enumeration.

According to MSDN, Windows XP only enumerates a single mouse
and a single keyboard (both as the system devices) so ensure
that we only enumerate one mouse or keyboard driver.
---
 dlls/dinput/dinput_main.c |  133 ++++++++++++++++++++++++++++++++++++++++++++-
 1 files changed, 131 insertions(+), 2 deletions(-)

diff --git a/dlls/dinput/dinput_main.c b/dlls/dinput/dinput_main.c
index 9769d74..3986fb2 100644
--- a/dlls/dinput/dinput_main.c
+++ b/dlls/dinput/dinput_main.c
@@ -74,10 +74,23 @@ static inline IDirectInput7W *IDirectInput7W_from_impl( IDirectInputImpl *iface
     return (IDirectInput7W *)(&iface->lpVtbl7w);
 }
 
+/* Mouse type devices */
+static const struct dinput_device *dinput_mice[] =
+{
+    &mouse_device
+};
+#define NB_DINPUT_MICE (sizeof(dinput_mice)/sizeof(dinput_mice[0]))
+
+/* Keyboard type devices */
+static const struct dinput_device *dinput_keyboards[] =
+{
+    &keyboard_device
+};
+#define NB_DINPUT_KEYBOARDS (sizeof(dinput_keyboards)/sizeof(dinput_keyboards[0]))
+
+/* All other dinput devices */
 static const struct dinput_device *dinput_devices[] =
 {
-    &mouse_device,
-    &keyboard_device,
     &joystick_linuxinput_device,
     &joystick_linux_device,
     &joystick_osx_device
@@ -259,6 +272,32 @@ static HRESULT WINAPI IDirectInputAImpl_EnumDevices(
 	  lpCallback, pvRef, dwFlags);
     _dump_EnumDevices_dwFlags(dwFlags);
 
+    for (i = 0; i < NB_DINPUT_MICE; i++) {
+        if (!dinput_mice[i]->enum_deviceA) continue;
+        for (j = 0, r = -1; r != 0; j++) {
+	    devInstance.dwSize = sizeof(devInstance);
+	    TRACE("  - checking device %u ('%s')\n", i, dinput_mice[i]->name);
+	    if ((r = dinput_mice[i]->enum_deviceA(dwDevType, dwFlags, &devInstance, This->dwVersion, j))) {
+	        if (lpCallback(&devInstance,pvRef) == DIENUM_STOP)
+		    return 0;
+	    }
+	}
+	if (j>1) break;
+    }
+
+    for (i = 0; i < NB_DINPUT_KEYBOARDS; i++) {
+        if (!dinput_keyboards[i]->enum_deviceA) continue;
+        for (j = 0, r = -1; r != 0; j++) {
+	    devInstance.dwSize = sizeof(devInstance);
+	    TRACE("  - checking device %u ('%s')\n", i, dinput_keyboards[i]->name);
+	    if ((r = dinput_keyboards[i]->enum_deviceA(dwDevType, dwFlags, &devInstance, This->dwVersion, j))) {
+	        if (lpCallback(&devInstance,pvRef) == DIENUM_STOP)
+		    return 0;
+	    }
+	}
+	if (j>1) break;
+    }
+
     for (i = 0; i < NB_DINPUT_DEVICES; i++) {
         if (!dinput_devices[i]->enum_deviceA) continue;
         for (j = 0, r = -1; r != 0; j++) {
@@ -290,6 +329,32 @@ static HRESULT WINAPI IDirectInputWImpl_EnumDevices(
 	  lpCallback, pvRef, dwFlags);
     _dump_EnumDevices_dwFlags(dwFlags);
 
+    for (i = 0; i < NB_DINPUT_MICE; i++) {
+        if (!dinput_mice[i]->enum_deviceW) continue;
+        for (j = 0, r = -1; r != 0; j++) {
+	    devInstance.dwSize = sizeof(devInstance);
+	    TRACE("  - checking device %u ('%s')\n", i, dinput_mice[i]->name);
+	    if ((r = dinput_mice[i]->enum_deviceW(dwDevType, dwFlags, &devInstance, This->dwVersion, j))) {
+	        if (lpCallback(&devInstance,pvRef) == DIENUM_STOP)
+		    return 0;
+	    }
+	}
+	if (j>1) break;
+    }
+
+    for (i = 0; i < NB_DINPUT_KEYBOARDS; i++) {
+        if (!dinput_keyboards[i]->enum_deviceW) continue;
+        for (j = 0, r = -1; r != 0; j++) {
+	    devInstance.dwSize = sizeof(devInstance);
+	    TRACE("  - checking device %u ('%s')\n", i, dinput_keyboards[i]->name);
+	    if ((r = dinput_keyboards[i]->enum_deviceW(dwDevType, dwFlags, &devInstance, This->dwVersion, j))) {
+	        if (lpCallback(&devInstance,pvRef) == DIENUM_STOP)
+		    return 0;
+	    }
+	}
+	if (j>1) break;
+    }
+
     for (i = 0; i < NB_DINPUT_DEVICES; i++) {
         if (!dinput_devices[i]->enum_deviceW) continue;
         for (j = 0, r = -1; r != 0; j++) {
@@ -489,6 +554,38 @@ static HRESULT WINAPI IDirectInput7AImpl_CreateDeviceEx(LPDIRECTINPUT7A iface, R
   if (!rguid || !pvOut) return E_POINTER;
 
   /* Loop on all the devices to see if anyone matches the given GUID */
+  for (i = 0; i < NB_DINPUT_MICE; i++) {
+    HRESULT ret;
+
+    if (!dinput_mice[i]->create_deviceA) continue;
+    if ((ret = dinput_mice[i]->create_deviceA(This, rguid, riid, (LPDIRECTINPUTDEVICEA*) pvOut)) == DI_OK)
+    {
+      EnterCriticalSection( &This->crit );
+      list_add_tail( &This->devices_list, &(*(IDirectInputDevice2AImpl**)pvOut)->entry );
+      LeaveCriticalSection( &This->crit );
+      return DI_OK;
+    }
+
+    if (ret == DIERR_NOINTERFACE)
+      ret_value = DIERR_NOINTERFACE;
+  }
+
+  for (i = 0; i < NB_DINPUT_KEYBOARDS; i++) {
+    HRESULT ret;
+
+    if (!dinput_keyboards[i]->create_deviceA) continue;
+    if ((ret = dinput_keyboards[i]->create_deviceA(This, rguid, riid, (LPDIRECTINPUTDEVICEA*) pvOut)) == DI_OK)
+    {
+      EnterCriticalSection( &This->crit );
+      list_add_tail( &This->devices_list, &(*(IDirectInputDevice2AImpl**)pvOut)->entry );
+      LeaveCriticalSection( &This->crit );
+      return DI_OK;
+    }
+
+    if (ret == DIERR_NOINTERFACE)
+      ret_value = DIERR_NOINTERFACE;
+  }
+
   for (i = 0; i < NB_DINPUT_DEVICES; i++) {
     HRESULT ret;
 
@@ -525,6 +622,38 @@ static HRESULT WINAPI IDirectInput7WImpl_CreateDeviceEx(LPDIRECTINPUT7W iface, R
   if (!rguid || !pvOut) return E_POINTER;
 
   /* Loop on all the devices to see if anyone matches the given GUID */
+  for (i = 0; i < NB_DINPUT_MICE; i++) {
+    HRESULT ret;
+
+    if (!dinput_mice[i]->create_deviceW) continue;
+    if ((ret = dinput_mice[i]->create_deviceW(This, rguid, riid, (LPDIRECTINPUTDEVICEW*) pvOut)) == DI_OK)
+    {
+      EnterCriticalSection( &This->crit );
+      list_add_tail( &This->devices_list, &(*(IDirectInputDevice2AImpl**)pvOut)->entry );
+      LeaveCriticalSection( &This->crit );
+      return DI_OK;
+    }
+
+    if (ret == DIERR_NOINTERFACE)
+      ret_value = DIERR_NOINTERFACE;
+  }
+
+  for (i = 0; i < NB_DINPUT_KEYBOARDS; i++) {
+    HRESULT ret;
+
+    if (!dinput_keyboards[i]->create_deviceW) continue;
+    if ((ret = dinput_keyboards[i]->create_deviceW(This, rguid, riid, (LPDIRECTINPUTDEVICEW*) pvOut)) == DI_OK)
+    {
+      EnterCriticalSection( &This->crit );
+      list_add_tail( &This->devices_list, &(*(IDirectInputDevice2AImpl**)pvOut)->entry );
+      LeaveCriticalSection( &This->crit );
+      return DI_OK;
+    }
+
+    if (ret == DIERR_NOINTERFACE)
+      ret_value = DIERR_NOINTERFACE;
+  }
+
   for (i = 0; i < NB_DINPUT_DEVICES; i++) {
     HRESULT ret;
 
-- 
1.6.2.2

