dinput: Implement device property DIPROP_USERNAME. (try 3)
Bernhard Übelacker
bernhardu at vr-web.de
Fri Mar 25 16:19:53 CDT 2016
https://bugs.winehq.org/show_bug.cgi?id=39667
Probably same issue as in https://bugs.winehq.org/show_bug.cgi?id=12432 .
(Attached backtrace seems equal.)
Steps to reproduce:
- start launcher
- "Configure Controllers"
- leave dialog with "Cancel"
- crash
MotoGP 3 demo launcher uses ConfigureDevices for the key mapping.
The crash seems to happen because the result of a
GetProperty(DIPROP_USERNAME) is used without checking.
This affects just the launcher. The game starts without problems with
a default key mapping.
2015-11-24 Try 1: https://www.winehq.org/pipermail/wine-patches/2015-December/145000.html
Review 1: https://www.winehq.org/pipermail/wine-devel/2015-December/110679.html
Changes since try 1 done by wine-staging (Sebastian Lackner?):
- Use correct WCHAR size in calls to lstrcpynW.
- Some white space cleanup in surrounding code.
- Change unnecessary complicated case for DIDSAM_NOUSER.
2015-11-29 Wine-staging: https://github.com/wine-compholio/wine-staging/blob/master/patches/dinput-DIPROP_USERNAME/0001-dinput-Implement-device-property-DIPROP_USERNAME.patch
Review 2: https://bugs.winehq.org/show_bug.cgi?id=39667#c3
Changes since wine-staging variant:
- For DIDSAM_NOUSER just terminate string.
- Initialize or copy string, not both.
- Allocate memory with struct IDirectInputDeviceImpl.
Thanks for all reviews.
Signed-off-by: Bernhard Übelacker <bernhardu at vr-web.de>
---
dlls/dinput/device.c | 35 +++++++++++++++++++++++++++++++++++
dlls/dinput/device_private.h | 1 +
dlls/dinput8/tests/device.c | 29 +++++++++++++++++++++++++++--
3 files changed, 63 insertions(+), 2 deletions(-)
diff --git a/dlls/dinput/device.c b/dlls/dinput/device.c
index e525f01..16c89b9 100644
--- a/dlls/dinput/device.c
+++ b/dlls/dinput/device.c
@@ -783,6 +783,7 @@ HRESULT _set_action_map(LPDIRECTINPUTDEVICE8W iface, LPDIACTIONFORMATW lpdiaf, L
DIOBJECTDATAFORMAT *obj_df = NULL;
DIPROPDWORD dp;
DIPROPRANGE dpr;
+ DIPROPSTRING dps;
WCHAR username[MAX_PATH];
DWORD username_size = MAX_PATH;
int i, action = 0, num_actions = 0;
@@ -863,6 +864,16 @@ HRESULT _set_action_map(LPDIRECTINPUTDEVICE8W iface, LPDIACTIONFORMATW lpdiaf, L
else
lstrcpynW(username, lpszUserName, MAX_PATH);
+ dps.diph.dwSize = sizeof(dps);
+ dps.diph.dwHeaderSize = sizeof(DIPROPHEADER);
+ dps.diph.dwObj = 0;
+ dps.diph.dwHow = DIPH_DEVICE;
+ if (dwFlags & DIDSAM_NOUSER)
+ dps.wsz[0] = '\0';
+ else
+ lstrcpynW(dps.wsz, username, sizeof(dps.wsz)/sizeof(WCHAR));
+ IDirectInputDevice8_SetProperty(iface, DIPROP_USERNAME, &dps.diph);
+
/* Save the settings to disk */
save_mapping_settings(iface, lpdiaf, username);
@@ -1251,6 +1262,18 @@ HRESULT WINAPI IDirectInputDevice2WImpl_GetProperty(LPDIRECTINPUTDEVICE8W iface,
TRACE("buffersize = %d\n", pd->dwData);
break;
}
+ case (DWORD_PTR) DIPROP_USERNAME:
+ {
+ LPDIPROPSTRING ps = (LPDIPROPSTRING)pdiph;
+
+ if (pdiph->dwSize != sizeof(DIPROPSTRING)) return DIERR_INVALIDPARAM;
+
+ if (This->username)
+ lstrcpynW(ps->wsz, This->username, sizeof(ps->wsz)/sizeof(WCHAR));
+ else
+ ps->wsz[0] = '\0';
+ break;
+ }
case (DWORD_PTR) DIPROP_VIDPID:
FIXME("DIPROP_VIDPID not implemented\n");
return DIERR_UNSUPPORTED;
@@ -1324,6 +1347,18 @@ HRESULT WINAPI IDirectInputDevice2WImpl_SetProperty(
LeaveCriticalSection(&This->crit);
break;
}
+ case (DWORD_PTR) DIPROP_USERNAME:
+ {
+ LPCDIPROPSTRING ps = (LPCDIPROPSTRING)pdiph;
+
+ if (pdiph->dwSize != sizeof(DIPROPSTRING)) return DIERR_INVALIDPARAM;
+
+ if (ps->wsz)
+ lstrcpynW(This->username, ps->wsz, sizeof(ps->wsz)/sizeof(WCHAR));
+ else
+ This->username[0] = '\0';
+ break;
+ }
default:
WARN("Unknown property %s\n", debugstr_guid(rguid));
return DIERR_UNSUPPORTED;
diff --git a/dlls/dinput/device_private.h b/dlls/dinput/device_private.h
index 52bbec4..c4fbe85 100644
--- a/dlls/dinput/device_private.h
+++ b/dlls/dinput/device_private.h
@@ -81,6 +81,7 @@ struct IDirectInputDeviceImpl
/* Action mapping */
int num_actions; /* number of actions mapped */
ActionMap *action_map; /* array of mappings */
+ WCHAR username[MAX_PATH];
};
extern BOOL get_app_key(HKEY*, HKEY*) DECLSPEC_HIDDEN;
diff --git a/dlls/dinput8/tests/device.c b/dlls/dinput8/tests/device.c
index 6495559..b5e27ad 100644
--- a/dlls/dinput8/tests/device.c
+++ b/dlls/dinput8/tests/device.c
@@ -223,8 +223,8 @@ static BOOL CALLBACK enumeration_callback(const DIDEVICEINSTANCEA *lpddi, IDirec
dps.wsz[0] = '\0';
hr = IDirectInputDevice_GetProperty(lpdid, DIPROP_USERNAME, &dps.diph);
- todo_wine ok (SUCCEEDED(hr), "GetProperty failed hr=%08x\n", hr);
- todo_wine ok (!lstrcmpW(usernameW, dps.wsz), "Username not set correctly expected=%s, got=%s\n", wine_dbgstr_wn(usernameW, -1), wine_dbgstr_wn(dps.wsz, -1));
+ ok (SUCCEEDED(hr), "GetProperty failed hr=%08x\n", hr);
+ ok (!lstrcmpW(usernameW, dps.wsz), "Username not set correctly expected=%s, got=%s\n", wine_dbgstr_wn(usernameW, -1), wine_dbgstr_wn(dps.wsz, -1));
/* Test buffer size */
memset(&dp, 0, sizeof(dp));
@@ -275,6 +275,7 @@ static void test_action_mapping(void)
HINSTANCE hinst = GetModuleHandleA(NULL);
IDirectInput8A *pDI = NULL;
DIACTIONFORMATA af;
+ DIPROPSTRING dps;
struct enum_data data = {pDI, &af, NULL, NULL, NULL, 0};
HWND hwnd;
@@ -342,6 +343,30 @@ static void test_action_mapping(void)
af.dwDataSize = 4 * sizeof(actionMapping) / sizeof(actionMapping[0]);
af.dwNumActions = sizeof(actionMapping) / sizeof(actionMapping[0]);
+
+ /* test DIDSAM_NOUSER */
+ dps.diph.dwSize = sizeof(dps);
+ dps.diph.dwHeaderSize = sizeof(DIPROPHEADER);
+ dps.diph.dwObj = 0;
+ dps.diph.dwHow = DIPH_DEVICE;
+ dps.wsz[0] = '\0';
+
+ hr = IDirectInputDevice_GetProperty(data.keyboard, DIPROP_USERNAME, &dps.diph);
+ ok (SUCCEEDED(hr), "GetProperty failed hr=%08x\n", hr);
+ ok (dps.wsz[0] != 0, "Expected any username, got=%s\n", wine_dbgstr_wn(dps.wsz, -1));
+
+ hr = IDirectInputDevice8_SetActionMap(data.keyboard, data.lpdiaf, NULL, DIDSAM_NOUSER);
+ ok (SUCCEEDED(hr), "SetActionMap failed hr=%08x\n", hr);
+
+ dps.diph.dwSize = sizeof(dps);
+ dps.diph.dwHeaderSize = sizeof(DIPROPHEADER);
+ dps.diph.dwObj = 0;
+ dps.diph.dwHow = DIPH_DEVICE;
+ dps.wsz[0] = '\0';
+
+ hr = IDirectInputDevice_GetProperty(data.keyboard, DIPROP_USERNAME, &dps.diph);
+ ok (SUCCEEDED(hr), "GetProperty failed hr=%08x\n", hr);
+ ok (dps.wsz[0] == 0, "Expected empty username, got=%s\n", wine_dbgstr_wn(dps.wsz, -1));
}
if (data.mouse != NULL)
--
2.1.4
More information about the wine-patches
mailing list