[v3 1/2] dinput: Keep username same between device objects.
Jetro Jormalainen
jje-wine at jv.jetro.fi
Thu Mar 2 12:51:40 CST 2017
v2: Fixed problems noted by Andrew Eikum.
v3: Combined test for username between device objects from previous
test patch.
Tested on Windows 10, Windows XP, Arch Linux and Rally Trophy Demo.
Signed-off-by: Jetro Jormalainen <jje-wine at jv.jetro.fi>
---
dlls/dinput/device.c | 38 +++++++++++++++++++++++++++++++++++---
dlls/dinput/device_private.h | 1 -
dlls/dinput/dinput_main.c | 6 ++++++
dlls/dinput/dinput_private.h | 7 +++++++
dlls/dinput8/tests/device.c | 11 +++++++++++
5 files changed, 59 insertions(+), 4 deletions(-)
diff --git a/dlls/dinput/device.c b/dlls/dinput/device.c
index a9ef2d4a3d..7b83a39d4b 100644
--- a/dlls/dinput/device.c
+++ b/dlls/dinput/device.c
@@ -1308,11 +1308,24 @@ HRESULT WINAPI IDirectInputDevice2WImpl_GetProperty(LPDIRECTINPUTDEVICE8W iface,
case (DWORD_PTR) DIPROP_USERNAME:
{
LPDIPROPSTRING ps = (LPDIPROPSTRING)pdiph;
+ struct DevicePlayer *device_player;
if (pdiph->dwSize != sizeof(DIPROPSTRING)) return DIERR_INVALIDPARAM;
- lstrcpynW(ps->wsz, This->username, sizeof(ps->wsz)/sizeof(WCHAR));
- break;
+ LIST_FOR_EACH_ENTRY(device_player, &This->dinput->device_players,
+ struct DevicePlayer, entry)
+ {
+ if (IsEqualGUID(&device_player->instance_guid, &This->guid))
+ {
+ if (*device_player->username)
+ {
+ lstrcpynW(ps->wsz, device_player->username, sizeof(ps->wsz)/sizeof(WCHAR));
+ return DI_OK;
+ }
+ else break;
+ }
+ }
+ return S_FALSE;
}
case (DWORD_PTR) DIPROP_VIDPID:
FIXME("DIPROP_VIDPID not implemented\n");
@@ -1390,10 +1403,29 @@ HRESULT WINAPI IDirectInputDevice2WImpl_SetProperty(
case (DWORD_PTR) DIPROP_USERNAME:
{
LPCDIPROPSTRING ps = (LPCDIPROPSTRING)pdiph;
+ struct DevicePlayer *device_player;
+ BOOL found = FALSE;
if (pdiph->dwSize != sizeof(DIPROPSTRING)) return DIERR_INVALIDPARAM;
- lstrcpynW(This->username, ps->wsz, sizeof(This->username)/sizeof(WCHAR));
+ LIST_FOR_EACH_ENTRY(device_player, &This->dinput->device_players,
+ struct DevicePlayer, entry)
+ {
+ if (IsEqualGUID(&device_player->instance_guid, &This->guid))
+ {
+ found = TRUE;
+ break;
+ }
+ }
+ if (!found && (device_player =
+ HeapAlloc(GetProcessHeap(), 0, sizeof(struct DevicePlayer))))
+ {
+ list_add_tail(&This->dinput->device_players, &device_player->entry);
+ device_player->instance_guid = This->guid;
+ }
+ if (device_player)
+ lstrcpynW(device_player->username, ps->wsz,
+ sizeof(device_player->username)/sizeof(WCHAR));
break;
}
default:
diff --git a/dlls/dinput/device_private.h b/dlls/dinput/device_private.h
index c4fbe858fe..52bbec4490 100644
--- a/dlls/dinput/device_private.h
+++ b/dlls/dinput/device_private.h
@@ -81,7 +81,6 @@ 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/dinput/dinput_main.c b/dlls/dinput/dinput_main.c
index ab6a2e8787..2bf9f38ba4 100644
--- a/dlls/dinput/dinput_main.c
+++ b/dlls/dinput/dinput_main.c
@@ -577,6 +577,7 @@ static HRESULT initialize_directinput_instance(IDirectInputImpl *This, DWORD dwV
This->crit.DebugInfo->Spare[0] = (DWORD_PTR)(__FILE__ ": IDirectInputImpl*->crit");
list_init( &This->devices_list );
+ list_init( &This->device_players );
/* Add self to the list of the IDirectInputs */
EnterCriticalSection( &dinput_hook_crit );
@@ -599,11 +600,16 @@ static void uninitialize_directinput_instance(IDirectInputImpl *This)
{
if (This->initialized)
{
+ struct DevicePlayer *device_player, *device_player2;
/* Remove self from the list of the IDirectInputs */
EnterCriticalSection( &dinput_hook_crit );
list_remove( &This->entry );
LeaveCriticalSection( &dinput_hook_crit );
+ LIST_FOR_EACH_ENTRY_SAFE( device_player, device_player2,
+ &This->device_players, struct DevicePlayer, entry )
+ HeapFree(GetProcessHeap(), 0, device_player);
+
check_hook_thread();
This->crit.DebugInfo->Spare[0] = 0;
diff --git a/dlls/dinput/dinput_private.h b/dlls/dinput/dinput_private.h
index 176c0e0287..6c93e16e9e 100644
--- a/dlls/dinput/dinput_private.h
+++ b/dlls/dinput/dinput_private.h
@@ -46,6 +46,7 @@ struct IDirectInputImpl
DWORD evsequence; /* unique sequence number for events */
DWORD dwVersion; /* direct input version number */
struct list devices_list; /* list of all created dinput devices */
+ struct list device_players; /* device instance guid to player name */
};
/* Function called by all devices that Wine supports */
@@ -56,6 +57,12 @@ struct dinput_device {
HRESULT (*create_device)(IDirectInputImpl *dinput, REFGUID rguid, REFIID riid, LPVOID *pdev, int unicode);
};
+struct DevicePlayer {
+ GUID instance_guid;
+ WCHAR username[MAX_PATH];
+ struct list entry;
+};
+
extern const struct dinput_device mouse_device DECLSPEC_HIDDEN;
extern const struct dinput_device keyboard_device DECLSPEC_HIDDEN;
extern const struct dinput_device joystick_linux_device DECLSPEC_HIDDEN;
diff --git a/dlls/dinput8/tests/device.c b/dlls/dinput8/tests/device.c
index 6753b73a2d..2b06f624c2 100644
--- a/dlls/dinput8/tests/device.c
+++ b/dlls/dinput8/tests/device.c
@@ -174,6 +174,7 @@ static BOOL CALLBACK enumeration_callback(const DIDEVICEINSTANCEA *lpddi, IDirec
struct enum_data *data = pvRef;
DWORD cnt;
DIDEVICEOBJECTDATA buffer[5];
+ IDirectInputDevice8A *lpdid2;
if (!data) return DIENUM_CONTINUE;
@@ -205,6 +206,10 @@ static BOOL CALLBACK enumeration_callback(const DIDEVICEINSTANCEA *lpddi, IDirec
ok (dwFlags & DIEDBS_MAPPEDPRI1, "Mouse should be mapped as pri1 dwFlags=%08x\n", dwFlags);
}
+ /* Creating second device object to check if it has the same username */
+ hr = IDirectInput_CreateDevice(data->pDI, &lpddi->guidInstance, &lpdid2, NULL);
+ ok(SUCCEEDED(hr), "IDirectInput_CreateDevice() failed: %08x\n", hr);
+
/* Building and setting an action map */
/* It should not use any pre-stored mappings so we use DIDBAM_HWDEFAULTS */
hr = IDirectInputDevice8_BuildActionMap(lpdid, data->lpdiaf, NULL, DIDBAM_HWDEFAULTS);
@@ -231,6 +236,11 @@ static BOOL CALLBACK enumeration_callback(const DIDEVICEINSTANCEA *lpddi, IDirec
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_w(usernameW), wine_dbgstr_w(dps.wsz));
+ dps.wsz[0] = '\0';
+ hr = IDirectInputDevice_GetProperty(lpdid2, DIPROP_USERNAME, &dps.diph);
+ 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_w(usernameW), wine_dbgstr_w(dps.wsz));
+
/* Test buffer size */
memset(&dp, 0, sizeof(dp));
dp.diph.dwSize = sizeof(dp);
@@ -315,6 +325,7 @@ static void test_action_mapping(void)
af.dwBufferSize = 32;
/* This enumeration builds and sets the action map for all devices */
+ data.pDI = pDI;
hr = IDirectInput8_EnumDevicesBySemantics(pDI, 0, &af, enumeration_callback, &data, DIEDBSFL_ATTACHEDONLY);
ok (SUCCEEDED(hr), "EnumDevicesBySemantics failed: hr=%08x\n", hr);
--
2.11.0
More information about the wine-patches
mailing list