Hey guys. So last week I finally got a good understanding of dinput as
a whole and nailed some trivial cases of action mapping, the ones with
the keyboard. I'm sending a series of patches so everyone can take a
look before I try commiting them. Please note that these contain a
partial implementation of EnumDevicesBySemantics, BuildActionMap and
SetActionMap, and also they're only the A versions. There are some
tests for EnumDevicesBySemantics. I'm not too sure of how to code the
tests that require user input...

I hope it's not a nuisance to read the code split in 7 files, if you
guys want I can merge it in one big diff.

On a bright note, this patchset results in the input working for these
two games:

* http://appdb.winehq.org/objectManager.php?sClass=application&iId=3678
* http://appdb.winehq.org/objectManager.php?sClass=application&iId=7919

Cheers :)
From 551a2f3bea643add493d50a5580f7c2a3c2f7566 Mon Sep 17 00:00:00 2001
From: Lucas Fialho Zawacki <lfzawa...@gmail.com>
Date: Sat, 28 May 2011 14:56:28 -0300
Subject: dinput8/tests: Organized it a little and added a test for the EnumDevicesBySemantics callback.

---
 dlls/dinput8/tests/device.c |   37 +++++++++++++++++++++++++------------
 1 files changed, 25 insertions(+), 12 deletions(-)

diff --git a/dlls/dinput8/tests/device.c b/dlls/dinput8/tests/device.c
index c18a83a..eca22a9 100644
--- a/dlls/dinput8/tests/device.c
+++ b/dlls/dinput8/tests/device.c
@@ -27,6 +27,23 @@
 #include "initguid.h"
 #include "dinput.h"
 
+/* Dummy GUID */
+static const GUID ACTION_MAPPING_GUID = { 0x1, 0x2, 0x3, { 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb } };
+
+static DIACTION actionMapping[]=
+{
+  /* axis */
+  { 0, 0x01008A01 /* DIAXIS_DRIVINGR_STEER */ ,       0, { "Steer" } },
+  /* button */
+  { 1, 0x01000C01 /* DIBUTTON_DRIVINGR_SHIFTUP */ ,   0, { "Upshift" } },
+  /* keyboard mapping */
+  { 2, DIKEYBOARD_SPACE , 0, { "Missiles" } }
+};
+
+
+/* This will set the number of devices, incrementing it
+   each time a new one is enumerated
+*/
 static BOOL CALLBACK enum_by_semantics(
     LPCDIDEVICEINSTANCE lpddi,
     LPDIRECTINPUTDEVICE8 lpdid,
@@ -34,6 +51,10 @@ static BOOL CALLBACK enum_by_semantics(
     DWORD dwRemaining,
     LPVOID pvRef)
 {
+
+    int *ndevices = pvRef;
+    if (ndevices != NULL) *ndevices += 1;
+
     return DIENUM_CONTINUE;
 }
 
@@ -44,17 +65,7 @@ static void test_action_mapping(void)
     HINSTANCE hinst = GetModuleHandle(NULL);
     LPDIRECTINPUT8 pDI = NULL;
     DIACTIONFORMAT af;
-    /* Dummy GUID */
-    const GUID ACTION_MAPPING_GUID = { 0x1, 0x2, 0x3, { 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb } };
-
-    DIACTION actionMapping[]=
-    {
-      /* axis */
-      { 0, 0x01008A01 /* DIAXIS_DRIVINGR_STEER */ , 0, { "Steer" } },
-
-      /* button */
-      { 1, 0x01000C01 /* DIBUTTON_DRIVINGR_SHIFTUP */ , 0, { "Upshift" } }
-    };
+    int ndevices = 0;
 
     hr = CoCreateInstance(&CLSID_DirectInput8, 0, 1, &IID_IDirectInput8A, (LPVOID*)&pDI);
     if (hr == DIERR_OLDDIRECTINPUTVERSION ||
@@ -86,9 +97,10 @@ static void test_action_mapping(void)
     af.dwGenre = 0x01000000; /* DIVIRTUAL_DRIVING_RACE */
 
     hr = IDirectInput8_EnumDevicesBySemantics(pDI,0, &af,
-        enum_by_semantics, 0, 0);
+        enum_by_semantics, &ndevices, 0);
 
     ok(SUCCEEDED(hr), "EnumDevicesBySemantics failed: hr=%08x\n",hr);
+    todo_wine ok (ndevices > 0, "EnumDevicesBySemantics did not call the callback. hr=%08x ndevices=%d\n", hr, ndevices);
 
     /* The call fails with a zeroed GUID */
     memset(&af.guidActionMap, 0, sizeof(GUID));
@@ -107,3 +119,4 @@ START_TEST(device)
 
     CoUninitialize();
 }
+
-- 
1.7.0.4

From 1829925b178b3c2eb45fe4ea1956a226e6f91628 Mon Sep 17 00:00:00 2001
From: Lucas Fialho Zawacki <lfzawa...@gmail.com>
Date: Sun, 29 May 2011 16:49:45 -0300
Subject: dinput: Implement a simple version of EnumDevicesBySemanticsA which enumerates only the keyboard.

---
 dlls/dinput/dinput_main.c |   46 ++++++++++++++++++++++++++++++++++++++------
 1 files changed, 39 insertions(+), 7 deletions(-)

diff --git a/dlls/dinput/dinput_main.c b/dlls/dinput/dinput_main.c
index d3727bc..2d572bf 100644
--- a/dlls/dinput/dinput_main.c
+++ b/dlls/dinput/dinput_main.c
@@ -120,7 +120,7 @@ static struct list direct_input_list = LIST_INIT( direct_input_list );
  */
 HRESULT WINAPI DirectInputCreateEx(
 	HINSTANCE hinst, DWORD dwVersion, REFIID riid, LPVOID *ppDI,
-	LPUNKNOWN punkOuter) 
+	LPUNKNOWN punkOuter)
 {
     IDirectInputImpl* This;
 
@@ -282,7 +282,7 @@ static HRESULT WINAPI IDirectInputAImpl_EnumDevices(
 	    }
 	}
     }
-    
+
     return 0;
 }
 /******************************************************************************
@@ -290,7 +290,7 @@ static HRESULT WINAPI IDirectInputAImpl_EnumDevices(
  */
 static HRESULT WINAPI IDirectInputWImpl_EnumDevices(
 	LPDIRECTINPUT7W iface, DWORD dwDevType, LPDIENUMDEVICESCALLBACKW lpCallback,
-	LPVOID pvRef, DWORD dwFlags) 
+	LPVOID pvRef, DWORD dwFlags)
 {
     IDirectInputImpl *This = impl_from_IDirectInput7W( iface );
     DIDEVICEINSTANCEW devInstance;
@@ -313,7 +313,7 @@ static HRESULT WINAPI IDirectInputWImpl_EnumDevices(
 	    }
 	}
     }
-    
+
     return 0;
 }
 
@@ -416,7 +416,7 @@ static HRESULT WINAPI IDirectInputWImpl_QueryInterface(LPDIRECTINPUT7W iface, RE
 
 static HRESULT WINAPI IDirectInputAImpl_Initialize(LPDIRECTINPUT7A iface, HINSTANCE hinst, DWORD x) {
 	TRACE("(this=%p,%p,%x)\n",iface, hinst, x);
-	
+
 	/* Initialize can return: DIERR_BETADIRECTINPUTVERSION, DIERR_OLDDIRECTINPUTVERSION and DI_OK.
 	 * Since we already initialized the device, return DI_OK. In the past we returned DIERR_ALREADYINITIALIZED
 	 * which broke applications like Tomb Raider Legend because it isn't a legal return value.
@@ -674,6 +674,9 @@ static HRESULT WINAPI IDirectInput8WImpl_FindDevice(LPDIRECTINPUT8W iface, REFGU
     return IDirectInput2WImpl_FindDevice( &This->IDirectInput7W_iface, rguid, pszName, pguidInstance );
 }
 
+/***********************************************************************
+ *		EnumDevicesBySemanticsA
+ */
 static HRESULT WINAPI IDirectInput8AImpl_EnumDevicesBySemantics(
       LPDIRECTINPUT8A iface, LPCSTR ptszUserName, LPDIACTIONFORMATA lpdiActionFormat,
       LPDIENUMDEVICESBYSEMANTICSCBA lpCallback,
@@ -681,8 +684,13 @@ static HRESULT WINAPI IDirectInput8AImpl_EnumDevicesBySemantics(
 )
 {
     IDirectInputImpl *This = impl_from_IDirectInput8A( iface );
+    DIDEVICEINSTANCEA devinst;
+    LPDIRECTINPUTDEVICE8A lpdidev;
+    unsigned int i;
+    int j, r;
+    int hasFormat = 0;
 
-    FIXME("(this=%p,%s,%p,%p,%p,%04x): stub\n", This, ptszUserName, lpdiActionFormat,
+    TRACE("(this=%p,%s,%p,%p,%p,%04x): stub\n", This, ptszUserName, lpdiActionFormat,
           lpCallback, pvRef, dwFlags);
 #define X(x) if (dwFlags & x) FIXME("\tdwFlags |= "#x"\n");
 	X(DIEDBSFL_ATTACHEDONLY)
@@ -695,6 +703,29 @@ static HRESULT WINAPI IDirectInput8AImpl_EnumDevicesBySemantics(
 
     _dump_diactionformatA(lpdiActionFormat);
 
+    devinst.dwSize = sizeof(devinst);
+    /* mimicking what EnumDevices does and calling the callback function */
+    for (i = 0; i < NB_DINPUT_DEVICES; i++) {
+        if (!dinput_devices[i]->enum_deviceA) continue;
+        for (j = 0, r = -1; r != 0; j++) {
+
+        TRACE("  - checking device %u ('%s')\n", i, dinput_devices[i]->name);
+        if ((r = dinput_devices[i]->enum_deviceA(DI8DEVCLASS_ALL, dwFlags, &devinst, This->dwVersion, j))) {
+            /* note that we have to create the device and set it's data format */
+            if ( GET_DIDEVICE_TYPE(devinst.dwDevType) == DI8DEVTYPE_KEYBOARD ) {
+                IDirectInput_CreateDevice(iface,&devinst.guidInstance, &lpdidev, NULL);
+                IDirectInputDevice_SetDataFormat(lpdidev,&c_dfDIKeyboard);
+                hasFormat = 1;
+            }
+            /* only enumerate keyboard */
+            if (!hasFormat) continue;
+
+            if  (lpCallback(&devinst, lpdidev, 0 , 0, pvRef) == DIENUM_STOP)
+                return DI_OK;
+        }
+        }
+    }
+
     return DI_OK;
 }
 
@@ -841,7 +872,7 @@ static HRESULT WINAPI DICF_CreateInstance(
 		return DirectInputCreateEx(0,0,riid,ppobj,pOuter);
 	}
 
-	FIXME("(%p,%p,%s,%p) Interface not found!\n",This,pOuter,debugstr_guid(riid),ppobj);	
+	FIXME("(%p,%p,%s,%p) Interface not found!\n",This,pOuter,debugstr_guid(riid),ppobj);
 	return E_NOINTERFACE;
 }
 
@@ -1121,3 +1152,4 @@ void check_dinput_hooks(LPDIRECTINPUTDEVICE8W iface)
 
     LeaveCriticalSection(&dinput_hook_crit);
 }
+
-- 
1.7.0.4

From 97459e68a1247854301f7ef05584c6e860ad1b59 Mon Sep 17 00:00:00 2001
From: Lucas Fialho Zawacki <lfzawa...@gmail.com>
Date: Sun, 29 May 2011 16:50:22 -0300
Subject: dinput8/tests: Testing if EnumDevicesBySemantics sets the device buffer size according to the DIACTIONFORMAT.

---
 dlls/dinput8/tests/device.c |   18 ++++++++++++++++--
 1 files changed, 16 insertions(+), 2 deletions(-)

diff --git a/dlls/dinput8/tests/device.c b/dlls/dinput8/tests/device.c
index eca22a9..dab298c 100644
--- a/dlls/dinput8/tests/device.c
+++ b/dlls/dinput8/tests/device.c
@@ -51,10 +51,23 @@ static BOOL CALLBACK enum_by_semantics(
     DWORD dwRemaining,
     LPVOID pvRef)
 {
-
+    HRESULT hr;
+    DIPROPDWORD dipdw;
     int *ndevices = pvRef;
+
     if (ndevices != NULL) *ndevices += 1;
 
+    /* test the buffer size */
+    dipdw.diph.dwSize       = sizeof(DIPROPDWORD);
+    hr = IDirectInputDevice_GetProperty(lpdid, DIPROP_BUFFERSIZE, &dipdw.diph);
+    ok (SUCCEEDED(hr), "IDirectInputDevice_GetProperty failed hr=%08x\n",hr);
+
+    if ( SUCCEEDED(hr) ) {
+        todo_wine ok ( dipdw.dwData == 32,
+        "EnumDevicesBySemantics must set the buffer size, buffersize=%d\n",
+        dipdw.dwData);
+    }
+
     return DIENUM_CONTINUE;
 }
 
@@ -94,13 +107,14 @@ static void test_action_mapping(void)
     af.dwNumActions = sizeof(actionMapping) / sizeof(actionMapping[0]);
     af.rgoAction = actionMapping;
     af.guidActionMap = ACTION_MAPPING_GUID;
+    af.dwBufferSize = 32;
     af.dwGenre = 0x01000000; /* DIVIRTUAL_DRIVING_RACE */
 
     hr = IDirectInput8_EnumDevicesBySemantics(pDI,0, &af,
         enum_by_semantics, &ndevices, 0);
 
     ok(SUCCEEDED(hr), "EnumDevicesBySemantics failed: hr=%08x\n",hr);
-    todo_wine ok (ndevices > 0, "EnumDevicesBySemantics did not call the callback. hr=%08x ndevices=%d\n", hr, ndevices);
+    ok(ndevices > 0, "EnumDevicesBySemantics did not call the callback. hr=%08x ndevices=%d\n", hr, ndevices);
 
     /* The call fails with a zeroed GUID */
     memset(&af.guidActionMap, 0, sizeof(GUID));
-- 
1.7.0.4

From 33b8103cd04a028cd191c39fa58f56f307601b21 Mon Sep 17 00:00:00 2001
From: Lucas Fialho Zawacki <lfzawa...@gmail.com>
Date: Sun, 29 May 2011 16:55:46 -0300
Subject: dinput: EnumDevicesBySemantics now sets the device buffer according to the DIACTIONFORMAT structure

---
 dlls/dinput/dinput_main.c   |    9 +++++++++
 dlls/dinput8/tests/device.c |    2 +-
 2 files changed, 10 insertions(+), 1 deletions(-)

diff --git a/dlls/dinput/dinput_main.c b/dlls/dinput/dinput_main.c
index 2d572bf..debf060 100644
--- a/dlls/dinput/dinput_main.c
+++ b/dlls/dinput/dinput_main.c
@@ -686,6 +686,7 @@ static HRESULT WINAPI IDirectInput8AImpl_EnumDevicesBySemantics(
     IDirectInputImpl *This = impl_from_IDirectInput8A( iface );
     DIDEVICEINSTANCEA devinst;
     LPDIRECTINPUTDEVICE8A lpdidev;
+    DIPROPDWORD dipdw; /* to set the buffer */
     unsigned int i;
     int j, r;
     int hasFormat = 0;
@@ -720,6 +721,14 @@ static HRESULT WINAPI IDirectInput8AImpl_EnumDevicesBySemantics(
             /* only enumerate keyboard */
             if (!hasFormat) continue;
 
+            /* set the buffer */
+            if (lpdiActionFormat->dwBufferSize > 0) {
+                IDirectInputDevice_Unacquire(lpdidev);
+                dipdw.diph.dwSize = sizeof(DIPROPDWORD);
+                dipdw.dwData = lpdiActionFormat->dwBufferSize;
+                IDirectInputDevice_SetProperty(lpdidev,DIPROP_BUFFERSIZE,&dipdw.diph);
+            }
+
             if  (lpCallback(&devinst, lpdidev, 0 , 0, pvRef) == DIENUM_STOP)
                 return DI_OK;
         }
diff --git a/dlls/dinput8/tests/device.c b/dlls/dinput8/tests/device.c
index dab298c..70e5498 100644
--- a/dlls/dinput8/tests/device.c
+++ b/dlls/dinput8/tests/device.c
@@ -63,7 +63,7 @@ static BOOL CALLBACK enum_by_semantics(
     ok (SUCCEEDED(hr), "IDirectInputDevice_GetProperty failed hr=%08x\n",hr);
 
     if ( SUCCEEDED(hr) ) {
-        todo_wine ok ( dipdw.dwData == 32,
+        ok ( dipdw.dwData == 32,
         "EnumDevicesBySemantics must set the buffer size, buffersize=%d\n",
         dipdw.dwData);
     }
-- 
1.7.0.4

From 67b5ac926ec3107df70a8b018191a9b209eb22b8 Mon Sep 17 00:00:00 2001
From: Lucas Fialho Zawacki <lfzawa...@gmail.com>
Date: Sun, 29 May 2011 18:48:29 -0300
Subject: dinput: Implemented SetActionMapA. Added an array of action mappings to the wine's dinput device

---
 dlls/dinput/device.c         |   64 +++++++++++++++++++++++++----------------
 dlls/dinput/device_private.h |    9 +++++-
 2 files changed, 47 insertions(+), 26 deletions(-)

diff --git a/dlls/dinput/device.c b/dlls/dinput/device.c
index 397e70e..90ede33 100644
--- a/dlls/dinput/device.c
+++ b/dlls/dinput/device.c
@@ -100,7 +100,7 @@ static void _dump_EnumObjects_flags(DWORD dwFlags) {
 	    FE(DIDFT_TGLBUTTON),
 	    FE(DIDFT_POV),
 	    FE(DIDFT_COLLECTION),
-	    FE(DIDFT_NODATA),	    
+	    FE(DIDFT_NODATA),
 	    FE(DIDFT_FFACTUATOR),
 	    FE(DIDFT_FFEFFECTTRIGGER),
 	    FE(DIDFT_OUTPUT),
@@ -221,7 +221,7 @@ void _dump_DIDATAFORMAT(const DIDATAFORMAT *df) {
     TRACE(")\n");
     TRACE("  - dwDataSize: %d\n", df->dwDataSize);
     TRACE("  - dwNumObjs: %d\n", df->dwNumObjs);
-    
+
     for (i = 0; i < df->dwNumObjs; i++) {
 	TRACE("  - Object %d:\n", i);
 	TRACE("      * GUID: %s ('%s')\n", debugstr_guid(df->rgodf[i].pguid), _dump_dinput_GUID(df->rgodf[i].pguid));
@@ -326,19 +326,19 @@ void fill_DataFormat(void *out, DWORD size, const void *in, const DataFormat *df
 			      df->dt[i].offset_out, df->dt[i].value);
 			*(out_c + df->dt[i].offset_out) = (char) df->dt[i].value;
 			break;
-			
+
 		    case 2:
 			TRACE("Copying (s) to %d default value %d\n",
 			      df->dt[i].offset_out, df->dt[i].value);
 			*((short *) (out_c + df->dt[i].offset_out)) = (short) df->dt[i].value;
 			break;
-			
+
 		    case 4:
 			TRACE("Copying (i) to %d default value %d\n",
 			      df->dt[i].offset_out, df->dt[i].value);
 			*((int *) (out_c + df->dt[i].offset_out)) = df->dt[i].value;
 			break;
-			
+
 		    default:
 			memset((out_c + df->dt[i].offset_out), 0, df->dt[i].size);
 			break;
@@ -388,7 +388,7 @@ static HRESULT create_DataFormat(LPCDIDATAFORMAT asked_format, DataFormat *forma
     memcpy(format->user_df, asked_format, asked_format->dwSize);
 
     TRACE("Creating DataTransform :\n");
-    
+
     for (i = 0; i < format->wine_df->dwNumObjs; i++)
     {
         format->offsets[i] = -1;
@@ -396,7 +396,7 @@ static HRESULT create_DataFormat(LPCDIDATAFORMAT asked_format, DataFormat *forma
 	for (j = 0; j < asked_format->dwNumObjs; j++) {
 	    if (done[j] == 1)
 		continue;
-	    
+
 	    if (/* Check if the application either requests any GUID and if not, it if matches
 		 * the GUID of the Wine object.
 		 */
@@ -415,7 +415,7 @@ static HRESULT create_DataFormat(LPCDIDATAFORMAT asked_format, DataFormat *forma
                  DIDFT_GETTYPE(asked_format->rgodf[j].dwType) & format->wine_df->rgodf[i].dwType))
             {
 		done[j] = 1;
-		
+
 		TRACE("Matching :\n");
 		TRACE("   - Asked (%d) :\n", j);
 		TRACE("       * GUID: %s ('%s')\n",
@@ -424,7 +424,7 @@ static HRESULT create_DataFormat(LPCDIDATAFORMAT asked_format, DataFormat *forma
                 TRACE("       * Offset: %3d\n", asked_format->rgodf[j].dwOfs);
                 TRACE("       * dwType: %08x\n", asked_format->rgodf[j].dwType);
 		TRACE("         "); _dump_EnumObjects_flags(asked_format->rgodf[j].dwType); TRACE("\n");
-		
+
 		TRACE("   - Wine  (%d) :\n", i);
 		TRACE("       * GUID: %s ('%s')\n",
                       debugstr_guid(format->wine_df->rgodf[i].pguid),
@@ -432,7 +432,7 @@ static HRESULT create_DataFormat(LPCDIDATAFORMAT asked_format, DataFormat *forma
                 TRACE("       * Offset: %3d\n", format->wine_df->rgodf[i].dwOfs);
                 TRACE("       * dwType: %08x\n", format->wine_df->rgodf[i].dwType);
                 TRACE("         "); _dump_EnumObjects_flags(format->wine_df->rgodf[i].dwType); TRACE("\n");
-		
+
                 if (format->wine_df->rgodf[i].dwType & DIDFT_BUTTON)
 		    dt[index].size = sizeof(BYTE);
 		else
@@ -442,10 +442,10 @@ static HRESULT create_DataFormat(LPCDIDATAFORMAT asked_format, DataFormat *forma
                 format->offsets[i]   = asked_format->rgodf[j].dwOfs;
 		dt[index].value = 0;
                 next = next + dt[index].size;
-		
+
                 if (format->wine_df->rgodf[i].dwOfs != dt[index].offset_out)
 		    same = 0;
-		
+
 		index++;
 		break;
 	    }
@@ -462,7 +462,7 @@ static HRESULT create_DataFormat(LPCDIDATAFORMAT asked_format, DataFormat *forma
             TRACE("       * Offset: %3d\n", asked_format->rgodf[j].dwOfs);
             TRACE("       * dwType: %08x\n", asked_format->rgodf[j].dwType);
 	    TRACE("         "); _dump_EnumObjects_flags(asked_format->rgodf[j].dwType); TRACE("\n");
-	    
+
 	    if (asked_format->rgodf[j].dwType & DIDFT_BUTTON)
 		dt[index].size = sizeof(BYTE);
 	    else
@@ -478,7 +478,7 @@ static HRESULT create_DataFormat(LPCDIDATAFORMAT asked_format, DataFormat *forma
 	    same = 0;
 	}
     }
-    
+
     format->internal_format_size = format->wine_df->dwDataSize;
     format->size = index;
     if (same) {
@@ -1191,7 +1191,7 @@ HRESULT WINAPI IDirectInputDevice2AImpl_EnumEffects(
 {
     FIXME("(this=%p,%p,%p,0x%08x): stub!\n",
 	  iface, lpCallback, lpvRef, dwFlags);
-    
+
     return DI_OK;
 }
 
@@ -1203,7 +1203,7 @@ HRESULT WINAPI IDirectInputDevice2WImpl_EnumEffects(
 {
     FIXME("(this=%p,%p,%p,0x%08x): stub!\n",
 	  iface, lpCallback, lpvRef, dwFlags);
-    
+
     return DI_OK;
 }
 
@@ -1317,7 +1317,7 @@ HRESULT WINAPI IDirectInputDevice7AImpl_EnumEffectsInFile(LPDIRECTINPUTDEVICE8A
 							  DWORD dwFlags)
 {
     FIXME("(%p)->(%s,%p,%p,%08x): stub !\n", iface, lpszFileName, pec, pvRef, dwFlags);
-    
+
     return DI_OK;
 }
 
@@ -1328,7 +1328,7 @@ HRESULT WINAPI IDirectInputDevice7WImpl_EnumEffectsInFile(LPDIRECTINPUTDEVICE8W
 							  DWORD dwFlags)
 {
     FIXME("(%p)->(%s,%p,%p,%08x): stub !\n", iface, debugstr_w(lpszFileName), pec, pvRef, dwFlags);
-    
+
     return DI_OK;
 }
 
@@ -1339,7 +1339,7 @@ HRESULT WINAPI IDirectInputDevice7AImpl_WriteEffectToFile(LPDIRECTINPUTDEVICE8A
 							  DWORD dwFlags)
 {
     FIXME("(%p)->(%s,%08x,%p,%08x): stub !\n", iface, lpszFileName, dwEntries, rgDiFileEft, dwFlags);
-    
+
     return DI_OK;
 }
 
@@ -1350,7 +1350,7 @@ HRESULT WINAPI IDirectInputDevice7WImpl_WriteEffectToFile(LPDIRECTINPUTDEVICE8W
 							  DWORD dwFlags)
 {
     FIXME("(%p)->(%s,%08x,%p,%08x): stub !\n", iface, debugstr_w(lpszFileName), dwEntries, rgDiFileEft, dwFlags);
-    
+
     return DI_OK;
 }
 
@@ -1382,7 +1382,7 @@ HRESULT WINAPI IDirectInputDevice8WImpl_BuildActionMap(LPDIRECTINPUTDEVICE8W ifa
 	X(DIDBAM_INITIALIZE)
 	X(DIDBAM_HWDEFAULTS)
 #undef X
-  
+
     return DI_OK;
 }
 
@@ -1391,8 +1391,21 @@ HRESULT WINAPI IDirectInputDevice8AImpl_SetActionMap(LPDIRECTINPUTDEVICE8A iface
 						     LPCSTR lpszUserName,
 						     DWORD dwFlags)
 {
+    IDirectInputDeviceImpl *This = impl_from_IDirectInputDevice8A(iface);
+    int i;
+
+    This->use_actionmap = 1;
+
+    /* search for actions for this device and apply them */
+    for (i=0; i < lpdiaf->dwNumActions; i++) {
+        if (IsEqualGUID( &lpdiaf->rgoAction[i].guidInstance, &This->guid ) ) {
+            int actionIndex = DIDFT_GETINSTANCE(lpdiaf->rgoAction[i].dwObjID);
+            This->actionmap[actionIndex] = lpdiaf->rgoAction[i].uAppData;
+        }
+    }
+
     FIXME("(%p)->(%p,%s,%08x): stub !\n", iface, lpdiaf, lpszUserName, dwFlags);
-    
+
     return DI_OK;
 }
 
@@ -1402,7 +1415,7 @@ HRESULT WINAPI IDirectInputDevice8WImpl_SetActionMap(LPDIRECTINPUTDEVICE8W iface
 						     DWORD dwFlags)
 {
     FIXME("(%p)->(%p,%s,%08x): stub !\n", iface, lpdiaf, debugstr_w(lpszUserName), dwFlags);
-    
+
     return DI_OK;
 }
 
@@ -1410,7 +1423,7 @@ HRESULT WINAPI IDirectInputDevice8AImpl_GetImageInfo(LPDIRECTINPUTDEVICE8A iface
 						     LPDIDEVICEIMAGEINFOHEADERA lpdiDevImageInfoHeader)
 {
     FIXME("(%p)->(%p): stub !\n", iface, lpdiDevImageInfoHeader);
-    
+
     return DI_OK;
 }
 
@@ -1418,6 +1431,7 @@ HRESULT WINAPI IDirectInputDevice8WImpl_GetImageInfo(LPDIRECTINPUTDEVICE8W iface
 						     LPDIDEVICEIMAGEINFOHEADERW lpdiDevImageInfoHeader)
 {
     FIXME("(%p)->(%p): stub !\n", iface, lpdiDevImageInfoHeader);
-    
+
     return DI_OK;
 }
+
diff --git a/dlls/dinput/device_private.h b/dlls/dinput/device_private.h
index f254d7f..b399d59 100644
--- a/dlls/dinput/device_private.h
+++ b/dlls/dinput/device_private.h
@@ -28,6 +28,8 @@
 #include "wine/list.h"
 #include "dinput_private.h"
 
+#define MAX_DEVICE_OBJECTS 256
+
 typedef struct
 {
     int size;
@@ -71,6 +73,10 @@ struct IDirectInputDeviceImpl
     BOOL                        overflow;    /* return DI_BUFFEROVERFLOW in 'GetDeviceData' */
 
     DataFormat                  data_format; /* user data format and wine to user format converter */
+
+    int                         use_actionmap;
+    /* each app data is indexed by the device ObjID */
+    DWORD                       actionmap[MAX_DEVICE_OBJECTS];
 };
 
 extern BOOL get_app_key(HKEY*, HKEY*) DECLSPEC_HIDDEN;
@@ -150,7 +156,7 @@ extern HRESULT WINAPI IDirectInputDevice2AImpl_GetObjectInfo(
 	LPDIDEVICEOBJECTINSTANCEA pdidoi,
 	DWORD dwObj,
 	DWORD dwHow)  DECLSPEC_HIDDEN;
-extern HRESULT WINAPI IDirectInputDevice2WImpl_GetObjectInfo(LPDIRECTINPUTDEVICE8W iface, 
+extern HRESULT WINAPI IDirectInputDevice2WImpl_GetObjectInfo(LPDIRECTINPUTDEVICE8W iface,
 							     LPDIDEVICEOBJECTINSTANCEW pdidoi,
 							     DWORD dwObj,
 							     DWORD dwHow) DECLSPEC_HIDDEN;
@@ -246,3 +252,4 @@ extern HRESULT WINAPI IDirectInputDevice8WImpl_GetImageInfo(LPDIRECTINPUTDEVICE8
 							    LPDIDEVICEIMAGEINFOHEADERW lpdiDevImageInfoHeader) DECLSPEC_HIDDEN;
 
 #endif /* __WINE_DLLS_DINPUT_DINPUTDEVICE_PRIVATE_H */
+
-- 
1.7.0.4

From 5b668ce7a929c34491fd478eefd50730e9a1c4ca Mon Sep 17 00:00:00 2001
From: Lucas Fialho Zawacki <lfzawa...@gmail.com>
Date: Sun, 29 May 2011 18:55:56 -0300
Subject: dinput: queue_event function now sets the uAppData member if the device is using action mapping

---
 dlls/dinput/device.c |    4 ++++
 1 files changed, 4 insertions(+), 0 deletions(-)

diff --git a/dlls/dinput/device.c b/dlls/dinput/device.c
index 90ede33..a979fff 100644
--- a/dlls/dinput/device.c
+++ b/dlls/dinput/device.c
@@ -576,6 +576,10 @@ void queue_event(LPDIRECTINPUTDEVICE8A iface, int inst_id, DWORD data, DWORD tim
     This->data_queue[This->queue_head].dwData      = data;
     This->data_queue[This->queue_head].dwTimeStamp = time;
     This->data_queue[This->queue_head].dwSequence  = seq;
+    if (This->use_actionmap) {
+        This->data_queue[This->queue_head].uAppData = This->actionmap[ofs];
+    }
+
     This->queue_head = next_pos;
     /* Send event if asked */
 }
-- 
1.7.0.4

From 943df09d16501c88a6a0a9bdf675b8514f268b68 Mon Sep 17 00:00:00 2001
From: Lucas Fialho Zawacki <lfzawa...@gmail.com>
Date: Sun, 29 May 2011 19:01:29 -0300
Subject: dinput: Implemented BuildActionMapA for all the DIACTION that map actions to DIKEYBOARD_* constants.

---
 dlls/dinput/device.c |   23 +++++++++++++++++++++++
 1 files changed, 23 insertions(+), 0 deletions(-)

diff --git a/dlls/dinput/device.c b/dlls/dinput/device.c
index a979fff..19a64f7 100644
--- a/dlls/dinput/device.c
+++ b/dlls/dinput/device.c
@@ -1358,11 +1358,34 @@ HRESULT WINAPI IDirectInputDevice7WImpl_WriteEffectToFile(LPDIRECTINPUTDEVICE8W
     return DI_OK;
 }
 
+/******************************************************************************
+ *	BuildActionMap
+ *  This sets an objID and a GUID for each DIACTION in the DIACTIONFORMAT that
+ *  should be mapped to this device.
+ */
 HRESULT WINAPI IDirectInputDevice8AImpl_BuildActionMap(LPDIRECTINPUTDEVICE8A iface,
 						       LPDIACTIONFORMATA lpdiaf,
 						       LPCSTR lpszUserName,
 						       DWORD dwFlags)
 {
+    IDirectInputDeviceImpl *This = impl_from_IDirectInputDevice8A(iface);
+    int i;
+
+/* dwSemantic=810004df is dwObjID=0xdf04 */
+#define SEMANTIC_TO_OBJID(s) (0x0000ffff & ( ((s) << 8) | ((s) >> 8) ))
+
+    if ( IsEqualGUID(&This->guid, &GUID_SysKeyboard) ) {
+        for (i=0; i < lpdiaf->dwNumActions; i++) {
+            if ( HIWORD(lpdiaf->rgoAction[i].dwSemantic) == 0x8100) { /* DIKEYBOARD_* constant */
+                lpdiaf->rgoAction[i].dwObjID = SEMANTIC_TO_OBJID(lpdiaf->rgoAction[i].dwSemantic);
+                lpdiaf->rgoAction[i].guidInstance = This->guid;
+                lpdiaf->rgoAction[i].dwHow |= DIAH_USERCONFIG; /* set it as configured by the user */
+            }
+        }
+    }
+
+#undef SEMANTIC_TO_OBJID
+
     FIXME("(%p)->(%p,%s,%08x): stub !\n", iface, lpdiaf, lpszUserName, dwFlags);
 #define X(x) if (dwFlags & x) FIXME("\tdwFlags =|"#x"\n");
 	X(DIDBAM_DEFAULT)
-- 
1.7.0.4



Reply via email to