#include <string.h>
#include "wine/debug.h"
#include "wine/unicode.h"
+#include "wine/heap.h"
#include "windef.h"
#include "winbase.h"
#include "winreg.h"
return type | (0x0000ff00 & (obj_instance << 8));
}
+static void del_mapping_key(const WCHAR *device, const WCHAR *username, const WCHAR *guid) {
+ static const WCHAR subkey[] = {
+ 'S','o','f','t','w','a','r','e','\\',
+ 'W','i','n','e','\\',
+ 'D','i','r','e','c','t','I','n','p','u','t','\\',
+ 'M','a','p','p','i','n','g','s','\\','%','s','\\','%','s','\\','%','s','\0'};
+ WCHAR *keyname;
+
+ keyname = heap_alloc(sizeof(WCHAR) * (lstrlenW(subkey) + strlenW(username) + strlenW(device) + strlenW(guid)));
+ sprintfW(keyname, subkey, username, device, guid);
+
+ /* Remove old key mappings so there will be no overlapping mappings */
+ RegDeleteKeyW(HKEY_CURRENT_USER, keyname);
+
+ heap_free(keyname);
+}
+
/*
* get_mapping_key
* Retrieves an open registry key to save the mapping, parametrized for an username,
* specific device and specific action mapping guid.
*/
-static HKEY get_mapping_key(const WCHAR *device, const WCHAR *username, const WCHAR *guid)
+static HKEY get_mapping_key(const WCHAR *device, const WCHAR *username, const WCHAR *guid, BOOL create)
{
static const WCHAR subkey[] = {
'S','o','f','t','w','a','r','e','\\',
sprintfW(keyname, subkey, username, device, guid);
/* The key used is HKCU\Software\Wine\DirectInput\Mappings\[username]\[device]\[mapping_guid] */
- if (RegCreateKeyW(HKEY_CURRENT_USER, keyname, &hkey))
- hkey = 0;
+ if (create) {
+ if (RegCreateKeyW(HKEY_CURRENT_USER, keyname, &hkey))
+ hkey = 0;
+ } else if (RegOpenKeyW(HKEY_CURRENT_USER, keyname, &hkey))
+ hkey = 0;
HeapFree(GetProcessHeap(), 0, keyname);
return hkey;
}
-static HRESULT save_mapping_settings(IDirectInputDevice8W *iface, LPDIACTIONFORMATW lpdiaf, LPCWSTR lpszUsername)
+HRESULT save_mapping_settings(IDirectInputDevice8W *iface, LPDIACTIONFORMATW lpdiaf, LPCWSTR lpszUsername)
{
WCHAR *guid_str = NULL;
DIDEVICEINSTANCEW didev;
if (StringFromCLSID(&lpdiaf->guidActionMap, &guid_str) != S_OK)
return DI_SETTINGSNOTSAVED;
- hkey = get_mapping_key(didev.tszInstanceName, lpszUsername, guid_str);
+ del_mapping_key(didev.tszInstanceName, lpszUsername, guid_str);
+
+ hkey = get_mapping_key(didev.tszInstanceName, lpszUsername, guid_str, TRUE);
if (!hkey)
{
return DI_OK;
}
-static BOOL load_mapping_settings(IDirectInputDeviceImpl *This, LPDIACTIONFORMATW lpdiaf, const WCHAR *username)
+BOOL load_mapping_settings(IDirectInputDeviceImpl *This, LPDIACTIONFORMATW lpdiaf, const WCHAR *username)
{
HKEY hkey;
WCHAR *guid_str;
DIDEVICEINSTANCEW didev;
- int i, mapped = 0;
+ int i;
didev.dwSize = sizeof(didev);
IDirectInputDevice8_GetDeviceInfo(&This->IDirectInputDevice8W_iface, &didev);
if (StringFromCLSID(&lpdiaf->guidActionMap, &guid_str) != S_OK)
return FALSE;
- hkey = get_mapping_key(didev.tszInstanceName, username, guid_str);
+ hkey = get_mapping_key(didev.tszInstanceName, username, guid_str, FALSE);
if (!hkey)
{
{
lpdiaf->rgoAction[i].dwObjID = id;
lpdiaf->rgoAction[i].guidInstance = didev.guidInstance;
- lpdiaf->rgoAction[i].dwHow = DIAH_DEFAULT;
- mapped += 1;
+ lpdiaf->rgoAction[i].dwHow = DIAH_USERCONFIG;
+ }
+ else
+ {
+ memset(&lpdiaf->rgoAction[i].guidInstance, 0, sizeof(GUID));
+ lpdiaf->rgoAction[i].dwHow = DIAH_UNMAPPED;
}
+
}
RegCloseKey(hkey);
CoTaskMemFree(guid_str);
- return mapped > 0;
+ /* On Windows BuildActionMap can open empty mapping, so always return TRUE if get_mapping_key is success */
+ return TRUE;
}
HRESULT _build_action_map(LPDIRECTINPUTDEVICE8W iface, LPDIACTIONFORMATW lpdiaf, LPCWSTR lpszUserName, DWORD dwFlags, DWORD devMask, LPCDIDATAFORMAT df)
load_success = load_mapping_settings(This, lpdiaf, username);
}
- if (load_success) return DI_OK;
+ if (load_success) {
+ /* Update dwCRC to track if action format has changed */
+ for (i=0; i < lpdiaf->dwNumActions; i++)
+ {
+ lpdiaf->dwCRC ^= (lpdiaf->rgoAction[i].dwObjID << i * 2) | (lpdiaf->rgoAction[i].dwObjID >> (sizeof(lpdiaf->dwCRC) * 8 - i * 2));
+ lpdiaf->dwCRC ^= (lpdiaf->rgoAction[i].dwSemantic << (i * 2 + 5)) | (lpdiaf->rgoAction[i].dwSemantic >> (sizeof(lpdiaf->dwCRC) * 8 - (i * 2 + 5)));
+ }
+ return DI_OK;
+ }
for (i=0; i < lpdiaf->dwNumActions; i++)
{
- /* Don't touch a user configured action */
- if (lpdiaf->rgoAction[i].dwHow == DIAH_USERCONFIG) continue;
-
if ((lpdiaf->rgoAction[i].dwSemantic & devMask) == devMask)
{
DWORD obj_id = semantic_to_obj_id(This, lpdiaf->rgoAction[i].dwSemantic);
}
}
+ /* Update dwCRC to track if action format has changed */
+ lpdiaf->dwCRC = 0;
+ for (i=0; i < lpdiaf->dwNumActions; i++)
+ {
+ lpdiaf->dwCRC ^= (lpdiaf->rgoAction[i].dwObjID << i * 2) | (lpdiaf->rgoAction[i].dwObjID >> (sizeof(lpdiaf->dwCRC) * 8 - i * 2));
+ lpdiaf->dwCRC ^= (lpdiaf->rgoAction[i].dwSemantic << (i * 2 + 5)) | (lpdiaf->rgoAction[i].dwSemantic >> (sizeof(lpdiaf->dwCRC) * 8 - (i * 2 + 5)));
+ }
+
if (!has_actions) return DI_NOEFFECT;
return IDirectInputDevice8WImpl_BuildActionMap(iface, lpdiaf, lpszUserName, dwFlags);
DIPROPSTRING dps;
WCHAR username[MAX_PATH];
DWORD username_size = MAX_PATH;
+ DWORD new_crc = 0;
int i, action = 0, num_actions = 0;
unsigned int offset = 0;
data_format.dwFlags = DIDF_RELAXIS;
data_format.dwDataSize = lpdiaf->dwDataSize;
+ /* Calculate checksum for actionformat */
+ for (i=0; i < lpdiaf->dwNumActions; i++)
+ {
+ new_crc ^= (lpdiaf->rgoAction[i].dwObjID << i * 2) | (lpdiaf->rgoAction[i].dwObjID >> (sizeof(lpdiaf->dwCRC) * 8 - i * 2));
+ new_crc ^= (lpdiaf->rgoAction[i].dwSemantic << (i * 2 + 5)) | (lpdiaf->rgoAction[i].dwSemantic >> (sizeof(lpdiaf->dwCRC) * 8 - (i * 2 + 5)));
+ }
+
/* Count the actions */
for (i=0; i < lpdiaf->dwNumActions; i++)
- if (IsEqualGUID(&This->guid, &lpdiaf->rgoAction[i].guidInstance))
+ {
+ if (IsEqualGUID(&This->guid, &lpdiaf->rgoAction[i].guidInstance) ||
+ (IsEqualGUID(&IID_NULL, &lpdiaf->rgoAction[i].guidInstance) &&
+ ((lpdiaf->rgoAction[i].dwSemantic & lpdiaf->dwGenre) == lpdiaf->dwGenre ||
+ (lpdiaf->rgoAction[i].dwSemantic & 0xff000000) == 0xff000000 /* Any Axis */) ))
+ {
num_actions++;
+ }
+ }
- if (num_actions == 0) return DI_NOEFFECT;
+ /* Should return DI_NOEFFECT if we dont have any actions and actionformat has not changed */
+ if (num_actions == 0 && lpdiaf->dwCRC == new_crc && !(dwFlags & DIDSAM_FORCESAVE)) return DI_NOEFFECT;
+
+ /* update dwCRC to track if action format has changed */
+ lpdiaf->dwCRC = new_crc;
This->num_actions = num_actions;
action++;
}
+ else if ((lpdiaf->rgoAction[i].dwSemantic & lpdiaf->dwGenre) == lpdiaf->dwGenre ||
+ (lpdiaf->rgoAction[i].dwSemantic & 0xff000000) == 0xff000000 /* Any Axis */)
+ {
+ DWORD obj_id = semantic_to_obj_id(This, lpdiaf->rgoAction[i].dwSemantic);
+ DWORD type = DIDFT_GETTYPE(obj_id);
+ DWORD inst = DIDFT_GETINSTANCE(obj_id);
+ LPDIOBJECTDATAFORMAT obj;
+
+ if (type == DIDFT_PSHBUTTON) type = DIDFT_BUTTON;
+ else if (type == DIDFT_RELAXIS) type = DIDFT_AXIS;
+
+ obj = dataformat_to_odf_by_type(df, inst, type);
+ TRACE("obj %p, inst 0x%08x, type 0x%08x\n", obj, inst, type);
+ if(obj)
+ {
+ memcpy(&obj_df[action], obj, df->dwObjSize);
+
+ This->action_map[action].uAppData = lpdiaf->rgoAction[i].uAppData;
+ This->action_map[action].offset = offset;
+ obj_df[action].dwOfs = offset;
+ offset += (type & DIDFT_BUTTON) ? 1 : 4;
+
+ action++;
+ }
+ }
+ }
+
+ if (action == 0)
+ {
+ HeapFree(GetProcessHeap(), 0, obj_df);
+ return DI_NOEFFECT;
}
+ data_format.dwNumObjs = action;
IDirectInputDevice8_SetDataFormat(iface, &data_format);
IDirectInputDeviceImpl *This = impl_from_IDirectInputDevice8W(iface);
ULONG ref = InterlockedDecrement(&(This->ref));
- TRACE("(%p) releasing from %d\n", This, ref + 1);
+ TRACE("(%p) ref %d\n", This, ref);
if (ref) return ref;
HeapFree(GetProcessHeap(), 0, This);
- return DI_OK;
+ return ref;
}
ULONG WINAPI IDirectInputDevice2AImpl_Release(LPDIRECTINPUTDEVICE8A iface)
{
IDirectInputDeviceImpl *This = impl_from_IDirectInputDevice8W(iface);
- TRACE("(%p this=%p,%s,%p)\n", iface, This, debugstr_guid(riid), ppobj);
+ TRACE("(%p)->(%s,%p)\n", This, debugstr_guid(riid), ppobj);
if (IsEqualGUID(&IID_IUnknown, riid) ||
IsEqualGUID(&IID_IDirectInputDeviceA, riid) ||
IsEqualGUID(&IID_IDirectInputDevice2A, riid) ||
}
WARN("Unsupported interface!\n");
- return E_FAIL;
+ return E_NOINTERFACE;
}
HRESULT WINAPI IDirectInputDevice2AImpl_QueryInterface(LPDIRECTINPUTDEVICE8A iface, REFIID riid, LPVOID *ppobj)
ULONG WINAPI IDirectInputDevice2WImpl_AddRef(LPDIRECTINPUTDEVICE8W iface)
{
IDirectInputDeviceImpl *This = impl_from_IDirectInputDevice8W(iface);
- return InterlockedIncrement(&This->ref);
+ ULONG ref = InterlockedIncrement(&This->ref);
+ TRACE( "(%p) ref %d\n", This, ref );
+ return ref;
}
ULONG WINAPI IDirectInputDevice2AImpl_AddRef(LPDIRECTINPUTDEVICE8A iface)
DIDEVICEOBJECTINSTANCEA ddoi;
int i;
- TRACE("(%p) %p,%p flags:%08x)\n", iface, lpCallback, lpvRef, dwFlags);
+ TRACE("(%p)->(%p,%p flags:%08x)\n", This, lpCallback, lpvRef, dwFlags);
TRACE(" - flags = ");
_dump_EnumObjects_flags(dwFlags);
TRACE("\n");
DIDEVICEOBJECTINSTANCEW ddoi;
int i;
- TRACE("(%p) %p,%p flags:%08x)\n", iface, lpCallback, lpvRef, dwFlags);
+ TRACE("(%p)->(%p,%p flags:%08x)\n", This, lpCallback, lpvRef, dwFlags);
TRACE(" - flags = ");
_dump_EnumObjects_flags(dwFlags);
TRACE("\n");
{
IDirectInputDeviceImpl *This = impl_from_IDirectInputDevice8W(iface);
- TRACE("(%p) %s,%p\n", iface, debugstr_guid(rguid), pdiph);
+ TRACE("(%p)->(%s,%p)\n", This, debugstr_guid(rguid), pdiph);
_dump_DIPROPHEADER(pdiph);
if (!IS_DIPROP(rguid)) return DI_OK;
{
IDirectInputDeviceImpl *This = impl_from_IDirectInputDevice8W(iface);
- TRACE("(%p) %s,%p\n", iface, debugstr_guid(rguid), pdiph);
+ TRACE("(%p)->(%s,%p)\n", This, debugstr_guid(rguid), pdiph);
_dump_DIPROPHEADER(pdiph);
if (!IS_DIPROP(rguid)) return DI_OK;
HRESULT WINAPI IDirectInputDevice2WImpl_RunControlPanel(LPDIRECTINPUTDEVICE8W iface, HWND hwndOwner, DWORD dwFlags)
{
- FIXME("(this=%p,%p,0x%08x): stub!\n", iface, hwndOwner, dwFlags);
+ IDirectInputDeviceImpl *This = impl_from_IDirectInputDevice8W(iface);
+ FIXME("%p)->(%p,0x%08x): stub!\n", This, hwndOwner, dwFlags);
return DI_OK;
}
HRESULT WINAPI IDirectInputDevice2WImpl_Initialize(LPDIRECTINPUTDEVICE8W iface, HINSTANCE hinst, DWORD dwVersion,
REFGUID rguid)
{
- FIXME("(this=%p,%p,%d,%s): stub!\n", iface, hinst, dwVersion, debugstr_guid(rguid));
+ IDirectInputDeviceImpl *This = impl_from_IDirectInputDevice8W(iface);
+ FIXME("(%p)->(%p,%d,%s): stub!\n", This, hinst, dwVersion, debugstr_guid(rguid));
return DI_OK;
}
HRESULT WINAPI IDirectInputDevice2WImpl_CreateEffect(LPDIRECTINPUTDEVICE8W iface, REFGUID rguid, LPCDIEFFECT lpeff,
LPDIRECTINPUTEFFECT *ppdef, LPUNKNOWN pUnkOuter)
{
- FIXME("(this=%p,%s,%p,%p,%p): stub!\n", iface, debugstr_guid(rguid), lpeff, ppdef, pUnkOuter);
+ IDirectInputDeviceImpl *This = impl_from_IDirectInputDevice8W(iface);
+ FIXME("(%p)->(%s,%p,%p,%p): stub!\n", This, debugstr_guid(rguid), lpeff, ppdef, pUnkOuter);
FIXME("not available in the generic implementation\n");
*ppdef = NULL;
LPVOID lpvRef,
DWORD dwFlags)
{
- FIXME("(this=%p,%p,%p,0x%08x): stub!\n",
- iface, lpCallback, lpvRef, dwFlags);
-
+ IDirectInputDeviceImpl *This = impl_from_IDirectInputDevice8A(iface);
+ FIXME("%p)->(%p,%p,0x%08x): stub!\n", This, lpCallback, lpvRef, dwFlags);
+
return DI_OK;
}
LPVOID lpvRef,
DWORD dwFlags)
{
- FIXME("(this=%p,%p,%p,0x%08x): stub!\n",
- iface, lpCallback, lpvRef, dwFlags);
-
+ IDirectInputDeviceImpl *This = impl_from_IDirectInputDevice8W(iface);
+ FIXME("(%p)->(%p,%p,0x%08x): stub!\n", This, lpCallback, lpvRef, dwFlags);
+
return DI_OK;
}
LPDIEFFECTINFOA lpdei,
REFGUID rguid)
{
- FIXME("(this=%p,%p,%s): stub!\n",
- iface, lpdei, debugstr_guid(rguid));
+ IDirectInputDeviceImpl *This = impl_from_IDirectInputDevice8A(iface);
+ FIXME("(%p)->(%p,%s): stub!\n", This, lpdei, debugstr_guid(rguid));
return DI_OK;
}
LPDIEFFECTINFOW lpdei,
REFGUID rguid)
{
- FIXME("(this=%p,%p,%s): stub!\n",
- iface, lpdei, debugstr_guid(rguid));
+ IDirectInputDeviceImpl *This = impl_from_IDirectInputDevice8W(iface);
+ FIXME("(%p)->(%p,%s): stub!\n", This, lpdei, debugstr_guid(rguid));
return DI_OK;
}
HRESULT WINAPI IDirectInputDevice2WImpl_GetForceFeedbackState(LPDIRECTINPUTDEVICE8W iface, LPDWORD pdwOut)
{
- FIXME("(this=%p,%p): stub!\n", iface, pdwOut);
+ IDirectInputDeviceImpl *This = impl_from_IDirectInputDevice8W(iface);
+ FIXME("(%p)->(%p): stub!\n", This, pdwOut);
return DI_OK;
}
HRESULT WINAPI IDirectInputDevice2WImpl_SendForceFeedbackCommand(LPDIRECTINPUTDEVICE8W iface, DWORD dwFlags)
{
- TRACE("(%p) 0x%08x:\n", iface, dwFlags);
+ IDirectInputDeviceImpl *This = impl_from_IDirectInputDevice8W(iface);
+ TRACE("(%p)->(0x%08x)\n", This, dwFlags);
return DI_NOEFFECT;
}
HRESULT WINAPI IDirectInputDevice2WImpl_EnumCreatedEffectObjects(LPDIRECTINPUTDEVICE8W iface,
LPDIENUMCREATEDEFFECTOBJECTSCALLBACK lpCallback, LPVOID lpvRef, DWORD dwFlags)
{
- FIXME("(this=%p,%p,%p,0x%08x): stub!\n", iface, lpCallback, lpvRef, dwFlags);
+ IDirectInputDeviceImpl *This = impl_from_IDirectInputDevice8W(iface);
+ FIXME("(%p)0>(%p,%p,0x%08x): stub!\n", This, lpCallback, lpvRef, dwFlags);
return DI_OK;
}
HRESULT WINAPI IDirectInputDevice2WImpl_Escape(LPDIRECTINPUTDEVICE8W iface, LPDIEFFESCAPE lpDIEEsc)
{
- FIXME("(this=%p,%p): stub!\n", iface, lpDIEEsc);
+ IDirectInputDeviceImpl *This = impl_from_IDirectInputDevice8W(iface);
+ FIXME("(%p)->(%p): stub!\n", This, lpDIEEsc);
return DI_OK;
}
LPCDIDEVICEOBJECTDATA rgdod, LPDWORD pdwInOut,
DWORD dwFlags)
{
- FIXME("(this=%p,0x%08x,%p,%p,0x%08x): stub!\n", iface, cbObjectData, rgdod, pdwInOut, dwFlags);
+ IDirectInputDeviceImpl *This = impl_from_IDirectInputDevice8W(iface);
+ FIXME("(%p)->(0x%08x,%p,%p,0x%08x): stub!\n", This, cbObjectData, rgdod, pdwInOut, dwFlags);
return DI_OK;
}
LPVOID pvRef,
DWORD dwFlags)
{
- FIXME("(%p)->(%s,%p,%p,%08x): stub !\n", iface, lpszFileName, pec, pvRef, dwFlags);
+ IDirectInputDeviceImpl *This = impl_from_IDirectInputDevice8A(iface);
+ FIXME("(%p)->(%s,%p,%p,%08x): stub !\n", This, lpszFileName, pec, pvRef, dwFlags);
return DI_OK;
}
LPVOID pvRef,
DWORD dwFlags)
{
- FIXME("(%p)->(%s,%p,%p,%08x): stub !\n", iface, debugstr_w(lpszFileName), pec, pvRef, dwFlags);
+ IDirectInputDeviceImpl *This = impl_from_IDirectInputDevice8W(iface);
+ FIXME("(%p)->(%s,%p,%p,%08x): stub !\n", This, debugstr_w(lpszFileName), pec, pvRef, dwFlags);
return DI_OK;
}
LPDIFILEEFFECT rgDiFileEft,
DWORD dwFlags)
{
- FIXME("(%p)->(%s,%08x,%p,%08x): stub !\n", iface, lpszFileName, dwEntries, rgDiFileEft, dwFlags);
+ IDirectInputDeviceImpl *This = impl_from_IDirectInputDevice8A(iface);
+ FIXME("(%p)->(%s,%08x,%p,%08x): stub !\n", This, lpszFileName, dwEntries, rgDiFileEft, dwFlags);
return DI_OK;
}
LPDIFILEEFFECT rgDiFileEft,
DWORD dwFlags)
{
- FIXME("(%p)->(%s,%08x,%p,%08x): stub !\n", iface, debugstr_w(lpszFileName), dwEntries, rgDiFileEft, dwFlags);
+ IDirectInputDeviceImpl *This = impl_from_IDirectInputDevice8W(iface);
+ FIXME("(%p)->(%s,%08x,%p,%08x): stub !\n", This, debugstr_w(lpszFileName), dwEntries, rgDiFileEft, dwFlags);
return DI_OK;
}
LPCWSTR lpszUserName,
DWORD dwFlags)
{
- FIXME("(%p)->(%p,%s,%08x): semi-stub !\n", iface, lpdiaf, debugstr_w(lpszUserName), dwFlags);
+ IDirectInputDeviceImpl *This = impl_from_IDirectInputDevice8W(iface);
+ FIXME("(%p)->(%p,%s,%08x): semi-stub !\n", This, lpdiaf, debugstr_w(lpszUserName), dwFlags);
#define X(x) if (dwFlags & x) FIXME("\tdwFlags =|"#x"\n");
X(DIDBAM_DEFAULT)
X(DIDBAM_PRESERVE)
HRESULT WINAPI IDirectInputDevice8AImpl_GetImageInfo(LPDIRECTINPUTDEVICE8A iface,
LPDIDEVICEIMAGEINFOHEADERA lpdiDevImageInfoHeader)
{
- FIXME("(%p)->(%p): stub !\n", iface, lpdiDevImageInfoHeader);
+ IDirectInputDeviceImpl *This = impl_from_IDirectInputDevice8A(iface);
+ FIXME("(%p)->(%p): stub !\n", This, lpdiDevImageInfoHeader);
return DI_OK;
}
HRESULT WINAPI IDirectInputDevice8WImpl_GetImageInfo(LPDIRECTINPUTDEVICE8W iface,
LPDIDEVICEIMAGEINFOHEADERW lpdiDevImageInfoHeader)
{
- FIXME("(%p)->(%p): stub !\n", iface, lpdiDevImageInfoHeader);
+ IDirectInputDeviceImpl *This = impl_from_IDirectInputDevice8W(iface);
+ FIXME("(%p)->(%p): stub !\n", This, lpdiDevImageInfoHeader);
return DI_OK;
}