[3/6] dinput: SetActionMap saving simple configurations to an .ini file
Lucas Fialho Zawacki
lfzawacki at gmail.com
Sat Oct 22 15:53:22 CDT 2011
From: Lucas Fialho Zawacki <lfzawacki at gmail.com>
Just the action mapping GUID, number of actions and the time the mapping was applied.
The helper function heap_printfW was copied from winemenubuilder.c
---
dlls/dinput/device.c | 99 ++++++++++++++++++++++++++++++++++++++++++
dlls/dinput/dinput_main.c | 45 +++++++++++++++++++
dlls/dinput/dinput_private.h | 4 ++
3 files changed, 148 insertions(+), 0 deletions(-)
diff --git a/dlls/dinput/device.c b/dlls/dinput/device.c
index b72b0d5..056a03d 100644
--- a/dlls/dinput/device.c
+++ b/dlls/dinput/device.c
@@ -598,6 +598,94 @@ static DWORD semantic_to_obj_id(IDirectInputDeviceImpl* This, DWORD dwSemantic)
return type | (0x0000ff00 & (obj_instance << 8));
}
+/*
+ * _write_private_profile_int_W
+ * An utility function to write an integer, with a specified format, to an .ini file.
+ */
+static void _write_private_profile_intW(const char *format, WCHAR* section, WCHAR* key, int value, WCHAR* file)
+{
+ WCHAR* value_str = heap_printfW(format, value);
+ WritePrivateProfileStringW(section, key, value_str, file);
+ HeapFree(GetProcessHeap(), 0, value_str);
+}
+
+/*
+ * _get_mapping_path
+ * For a given username and device name, returns the filename with path of the
+ * mapping settings files.
+ * The caller has to free the returned string.
+ */
+WCHAR* _get_mapping_path(const WCHAR *device, const WCHAR *username)
+{
+ WCHAR path[] = {
+ '%','C','o','m','m','o','n','P','r','o','g','r','a','m','F','i','l','e','s','%','\\',
+ 'D','i','r','e','c','t','X','\\',
+ 'D','i','r','e','c','t','I','n','p','u','t','\\',
+ 'U','s','e','r',' ','M','a','p','s','\0'};
+ WCHAR *expanded_path, *ret;
+ int expanded_path_size;
+
+ expanded_path_size = ExpandEnvironmentStringsW(path, NULL, 0);
+ expanded_path = HeapAlloc(GetProcessHeap(), 0, sizeof(WCHAR)*expanded_path_size);
+ ExpandEnvironmentStringsW(path, expanded_path, expanded_path_size);
+
+ /* The filename is like this: PATH\TO\FILE\USERNAMEX_DEVICEX_0.INI */
+ ret = heap_printfW("%s\\%sX_%sX_0.INI", expanded_path, username, device);
+
+ /* Unallocate */
+ HeapFree(GetProcessHeap(), 0, expanded_path);
+
+ return ret;
+}
+
+static HRESULT _save_mapping_settings(IDirectInputDevice8W *iface, LPDIACTIONFORMATW lpdiaf, LPCWSTR lpszUsername)
+{
+ DIDEVICEINSTANCEW didev;
+ SYSTEMTIME stime;
+ FILETIME ftime;
+ const char* guid_strA;
+ int guid_size;
+
+ WCHAR *map_path, *app_section, *guid_str, *time_high, *time_low;
+ WCHAR mapexists[] = {'M','a','p','E','x','i','s','t','s','\0'};
+ WCHAR numactions[] = {'N','u','m','A','c','t','i','o','n','\0'};
+
+ didev.dwSize = sizeof(didev);
+ IDirectInputDevice8_GetDeviceInfo(iface, &didev);
+
+ map_path = _get_mapping_path(didev.tszInstanceName, lpszUsername);
+
+ /* Guid and Timestamp */
+ guid_strA = debugstr_guid(&lpdiaf->guidActionMap);
+ guid_size = MultiByteToWideChar(CP_ACP, 0, guid_strA, -1, NULL, 0);
+ guid_str = HeapAlloc(GetProcessHeap(), 0, sizeof(WCHAR) * guid_size);
+ MultiByteToWideChar(CP_ACP, 0, guid_strA, -1, guid_str, guid_size);
+
+ GetSystemTime(&stime);
+ SystemTimeToFileTime(&stime, &ftime);
+
+ time_high = heap_printfW("%s.TimestampHigh", guid_str);
+ time_low = heap_printfW("%s.TimestampLow", guid_str);
+
+ _write_private_profile_intW("0x%08x", didev.tszInstanceName, time_high, ftime.dwHighDateTime, map_path);
+ _write_private_profile_intW("0x%08x", didev.tszInstanceName, time_low, ftime.dwLowDateTime, map_path);
+
+ /* Device app section */
+ /* Something like this: [DEVICENAME.Application.GUID.Genre.NUMBER] */
+ app_section = heap_printfW("%s.Application.%s.Genre.%d", didev.tszInstanceName, guid_str, HIBYTE(HIWORD(lpdiaf->dwGenre)));
+
+ _write_private_profile_intW("%d", app_section, mapexists, 1, map_path);
+ _write_private_profile_intW("%d", app_section, numactions, lpdiaf->dwNumActions, map_path);
+
+ /* Unallocate everything */
+ HeapFree(GetProcessHeap(), 0, map_path);
+ HeapFree(GetProcessHeap(), 0, guid_str);
+ HeapFree(GetProcessHeap(), 0, time_high);
+ HeapFree(GetProcessHeap(), 0, time_low);
+
+ return DI_OK;
+}
+
HRESULT _build_action_map(LPDIRECTINPUTDEVICE8W iface, LPDIACTIONFORMATW lpdiaf, LPCWSTR lpszUserName, DWORD dwFlags, DWORD devMask, LPCDIDATAFORMAT df)
{
IDirectInputDeviceImpl *This = impl_from_IDirectInputDevice8W(iface);
@@ -650,6 +738,8 @@ HRESULT _set_action_map(LPDIRECTINPUTDEVICE8W iface, LPDIACTIONFORMATW lpdiaf, L
DIOBJECTDATAFORMAT *obj_df = NULL;
DIPROPDWORD dp;
DIPROPRANGE dpr;
+ WCHAR username[MAX_PATH];
+ DWORD username_size = MAX_PATH;
int i, action = 0, num_actions = 0;
unsigned int offset = 0;
@@ -722,6 +812,15 @@ HRESULT _set_action_map(LPDIRECTINPUTDEVICE8W iface, LPDIACTIONFORMATW lpdiaf, L
IDirectInputDevice8_SetProperty(iface, DIPROP_BUFFERSIZE, &dp.diph);
}
+ /* Retrieve logged user name if necessary */
+ if (lpszUserName == NULL)
+ GetUserNameW(username, &username_size);
+ else
+ lstrcpynW(username, lpszUserName, MAX_PATH);
+
+ /* Save the settings to disk */
+ _save_mapping_settings(iface, lpdiaf, username);
+
return IDirectInputDevice8WImpl_SetActionMap(iface, lpdiaf, lpszUserName, dwFlags);
}
diff --git a/dlls/dinput/dinput_main.c b/dlls/dinput/dinput_main.c
index 373b990..aec0a1e 100644
--- a/dlls/dinput/dinput_main.c
+++ b/dlls/dinput/dinput_main.c
@@ -349,6 +349,51 @@ static DWORD _diactionformat_priorityW(LPDIACTIONFORMATW lpdiaf, DWORD genre)
return priorityFlags;
}
+/*
+ * heap_printfW
+ *
+ * An utility function that acts just like sprintfW, but returns a heap allocated WCHAR string.
+ * To make the code that uses it more readable the format is accepted as a CHAR string, but note
+ * that other strings that are eventually used as parameters should be WCHAR.
+ * The caller has to free the returned string.
+ */
+WCHAR* heap_printfW(const char *format, ...)
+{
+ va_list args;
+ int size = 512*sizeof(WCHAR), format_size;
+ WCHAR *buffer, *ret, *formatW = NULL;
+ int n;
+
+ format_size = MultiByteToWideChar(CP_ACP, 0, format, -1, formatW, 0);
+ formatW = HeapAlloc(GetProcessHeap(), 0, sizeof(WCHAR)*format_size);
+ MultiByteToWideChar(CP_ACP, 0, format, -1, formatW, format_size);
+
+ va_start(args, format);
+ while (1)
+ {
+ buffer = HeapAlloc(GetProcessHeap(), 0, size);
+ if (buffer == NULL)
+ break;
+ n = vsnprintfW(buffer, size, formatW, args);
+ if (n == -1)
+ size *= 2;
+ else if (n >= size)
+ size = n + 1;
+ else
+ break;
+ HeapFree(GetProcessHeap(), 0, buffer);
+ }
+ va_end(args);
+
+ if (buffer == NULL) return NULL;
+ ret = HeapReAlloc(GetProcessHeap(), 0, buffer, sizeof(WCHAR)*(strlenW(buffer)+1) );
+ if (ret == NULL) ret = buffer;
+
+ HeapFree(GetProcessHeap(), 0, formatW);
+
+ return ret;
+}
+
/******************************************************************************
* IDirectInputA_EnumDevices
*/
diff --git a/dlls/dinput/dinput_private.h b/dlls/dinput/dinput_private.h
index 9a5c8ba..ee0fd2e 100644
--- a/dlls/dinput/dinput_private.h
+++ b/dlls/dinput/dinput_private.h
@@ -68,6 +68,10 @@ extern void _copy_diactionformatWtoA(LPDIACTIONFORMATA, LPDIACTIONFORMATW) DECLS
extern HRESULT _configure_devices(IDirectInput8W *iface, LPDICONFIGUREDEVICESCALLBACK lpdiCallback, LPDICONFIGUREDEVICESPARAMSW lpdiCDParams, DWORD dwFlags, LPVOID pvRefData) DECLSPEC_HIDDEN;
+extern WCHAR* heap_printfW(const char *format, ...) DECLSPEC_HIDDEN;
+extern WCHAR* _get_mapping_path(const WCHAR *device, const WCHAR *username) DECLSPEC_HIDDEN;
+
+
#define IS_DIPROP(x) (((ULONG_PTR)(x) >> 16) == 0)
#define DIKEYBOARD_MASK 0x81000000
--
1.7.0.4
More information about the wine-patches
mailing list