[v3 2/2] dinput: Handle username in EnumDevicesBySemantics.
Andrew Eikum
aeikum at codeweavers.com
Fri Mar 3 10:50:19 CST 2017
Signed-off-by: Andrew Eikum <aeikum at codeweavers.com>
On Thu, Mar 02, 2017 at 08:51:41PM +0200, Jetro Jormalainen wrote:
> EnumDevicesBySemantics enums only devices with given username when
> DIEDBSFL_THISUSER is set and only unowned devices when
> DIEDBSFL_AVAILABLEDEVICES is set.
>
> v2: Fixed problems noted by Andrew Eikum.
> v3: Combined test for username in EnumDevicesBySemantics from previous
> 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/dinput_main.c | 111 ++++++++++++++++++++++++++++++++++++++------
> dlls/dinput8/tests/dinput.c | 11 ++++-
> 2 files changed, 105 insertions(+), 17 deletions(-)
>
> diff --git a/dlls/dinput/dinput_main.c b/dlls/dinput/dinput_main.c
> index 2bf9f38ba4..a59217472c 100644
> --- a/dlls/dinput/dinput_main.c
> +++ b/dlls/dinput/dinput_main.c
> @@ -923,6 +923,47 @@ static HRESULT WINAPI IDirectInput8WImpl_FindDevice(LPDIRECTINPUT8W iface, REFGU
> return IDirectInput2WImpl_FindDevice( &This->IDirectInput7W_iface, rguid, pszName, pguidInstance );
> }
>
> +static BOOL should_enumerate_device(const WCHAR *username, DWORD dwFlags,
> + struct list *device_players, REFGUID guid)
> +{
> + BOOL should_enumerate = TRUE;
> + struct DevicePlayer *device_player;
> +
> + /* Check if user owns this device */
> + if (dwFlags & DIEDBSFL_THISUSER && username && *username)
> + {
> + should_enumerate = FALSE;
> + LIST_FOR_EACH_ENTRY(device_player, device_players, struct DevicePlayer, entry)
> + {
> + if (IsEqualGUID(&device_player->instance_guid, guid))
> + {
> + if (*device_player->username && !lstrcmpW(username, device_player->username))
> + return TRUE; /* Device username matches */
> + break;
> + }
> + }
> + }
> +
> + /* Check if this device is not owned by anyone */
> + if (dwFlags & DIEDBSFL_AVAILABLEDEVICES) {
> + BOOL found = FALSE;
> + should_enumerate = FALSE;
> + LIST_FOR_EACH_ENTRY(device_player, device_players, struct DevicePlayer, entry)
> + {
> + if (IsEqualGUID(&device_player->instance_guid, guid))
> + {
> + if (*device_player->username)
> + found = TRUE;
> + break;
> + }
> + }
> + if (!found)
> + return TRUE; /* Device does not have a username */
> + }
> +
> + return should_enumerate;
> +}
> +
> static HRESULT WINAPI IDirectInput8AImpl_EnumDevicesBySemantics(
> LPDIRECTINPUT8A iface, LPCSTR ptszUserName, LPDIACTIONFORMATA lpdiActionFormat,
> LPDIENUMDEVICESBYSEMANTICSCBA lpCallback,
> @@ -939,6 +980,7 @@ static HRESULT WINAPI IDirectInput8AImpl_EnumDevicesBySemantics(
> int device_count = 0;
> int remain;
> DIDEVICEINSTANCEA *didevis = 0;
> + WCHAR *username_w = 0;
>
> FIXME("(this=%p,%s,%p,%p,%p,%04x): semi-stub\n", This, debugstr_a(ptszUserName), lpdiActionFormat,
> lpCallback, pvRef, dwFlags);
> @@ -955,6 +997,14 @@ static HRESULT WINAPI IDirectInput8AImpl_EnumDevicesBySemantics(
>
> didevi.dwSize = sizeof(didevi);
>
> + if (ptszUserName)
> + {
> + int len = MultiByteToWideChar(CP_ACP, 0, ptszUserName, -1, 0, 0);
> +
> + username_w = HeapAlloc(GetProcessHeap(), 0, sizeof(WCHAR)*len);
> + MultiByteToWideChar(CP_ACP, 0, ptszUserName, -1, username_w, len);
> + }
> +
> /* Enumerate all the joysticks */
> for (i = 0; i < NB_DINPUT_DEVICES; i++)
> {
> @@ -968,7 +1018,8 @@ static HRESULT WINAPI IDirectInput8AImpl_EnumDevicesBySemantics(
>
> /* Default behavior is to enumerate attached game controllers */
> enumSuccess = dinput_devices[i]->enum_deviceA(DI8DEVCLASS_GAMECTRL, DIEDFL_ATTACHEDONLY | dwFlags, &didevi, This->dwVersion, j);
> - if (enumSuccess == S_OK)
> + if (enumSuccess == S_OK &&
> + should_enumerate_device(username_w, dwFlags, &This->device_players, &didevi.guidInstance))
> {
> if (device_count++)
> didevis = HeapReAlloc(GetProcessHeap(), 0, didevis, sizeof(DIDEVICEINSTANCEA)*device_count);
> @@ -980,8 +1031,15 @@ static HRESULT WINAPI IDirectInput8AImpl_EnumDevicesBySemantics(
> }
>
> remain = device_count;
> + /* Add keyboard and mouse to remaining device count */
> if (!(dwFlags & DIEDBSFL_FORCEFEEDBACK))
> - remain += sizeof(guids)/sizeof(guids[0]);
> + {
> + for (i = 0; i < sizeof(guids) / sizeof(guids[0]); i++)
> + {
> + if (should_enumerate_device(username_w, dwFlags, &This->device_players, guids[i]))
> + remain++;
> + }
> + }
>
> for (i = 0; i < device_count; i++)
> {
> @@ -991,26 +1049,38 @@ static HRESULT WINAPI IDirectInput8AImpl_EnumDevicesBySemantics(
> if (lpCallback(&didevis[i], lpdid, callbackFlags, --remain, pvRef) == DIENUM_STOP)
> {
> HeapFree(GetProcessHeap(), 0, didevis);
> + HeapFree(GetProcessHeap(), 0, username_w);
> return DI_OK;
> }
> }
>
> HeapFree(GetProcessHeap(), 0, didevis);
>
> - if (dwFlags & DIEDBSFL_FORCEFEEDBACK) return DI_OK;
> + if (dwFlags & DIEDBSFL_FORCEFEEDBACK)
> + {
> + HeapFree(GetProcessHeap(), 0, username_w);
> + return DI_OK;
> + }
>
> /* Enumerate keyboard and mouse */
> for(i=0; i < sizeof(guids)/sizeof(guids[0]); i++)
> {
> - callbackFlags = diactionformat_priorityA(lpdiActionFormat, actionMasks[i]);
> + if (should_enumerate_device(username_w, dwFlags, &This->device_players, guids[i]))
> + {
> + callbackFlags = diactionformat_priorityA(lpdiActionFormat, actionMasks[i]);
>
> - IDirectInput_CreateDevice(iface, guids[i], &lpdid, NULL);
> - IDirectInputDevice_GetDeviceInfo(lpdid, &didevi);
> + IDirectInput_CreateDevice(iface, guids[i], &lpdid, NULL);
> + IDirectInputDevice_GetDeviceInfo(lpdid, &didevi);
>
> - if (lpCallback(&didevi, lpdid, callbackFlags, sizeof(guids)/sizeof(guids[0]) - (i+1), pvRef) == DIENUM_STOP)
> - return DI_OK;
> + if (lpCallback(&didevi, lpdid, callbackFlags, --remain, pvRef) == DIENUM_STOP)
> + {
> + HeapFree(GetProcessHeap(), 0, username_w);
> + return DI_OK;
> + }
> + }
> }
>
> + HeapFree(GetProcessHeap(), 0, username_w);
> return DI_OK;
> }
>
> @@ -1049,7 +1119,8 @@ static HRESULT WINAPI IDirectInput8WImpl_EnumDevicesBySemantics(
>
> /* Default behavior is to enumerate attached game controllers */
> enumSuccess = dinput_devices[i]->enum_deviceW(DI8DEVCLASS_GAMECTRL, DIEDFL_ATTACHEDONLY | dwFlags, &didevi, This->dwVersion, j);
> - if (enumSuccess == S_OK)
> + if (enumSuccess == S_OK &&
> + should_enumerate_device(ptszUserName, dwFlags, &This->device_players, &didevi.guidInstance))
> {
> if (device_count++)
> didevis = HeapReAlloc(GetProcessHeap(), 0, didevis, sizeof(DIDEVICEINSTANCEW)*device_count);
> @@ -1061,8 +1132,15 @@ static HRESULT WINAPI IDirectInput8WImpl_EnumDevicesBySemantics(
> }
>
> remain = device_count;
> + /* Add keyboard and mouse to remaining device count */
> if (!(dwFlags & DIEDBSFL_FORCEFEEDBACK))
> - remain += sizeof(guids)/sizeof(guids[0]);
> + {
> + for (i = 0; i < sizeof(guids) / sizeof(guids[0]); i++)
> + {
> + if (should_enumerate_device(ptszUserName, dwFlags, &This->device_players, guids[i]))
> + remain++;
> + }
> + }
>
> for (i = 0; i < device_count; i++)
> {
> @@ -1083,13 +1161,16 @@ static HRESULT WINAPI IDirectInput8WImpl_EnumDevicesBySemantics(
> /* Enumerate keyboard and mouse */
> for(i=0; i < sizeof(guids)/sizeof(guids[0]); i++)
> {
> - callbackFlags = diactionformat_priorityW(lpdiActionFormat, actionMasks[i]);
> + if (should_enumerate_device(ptszUserName, dwFlags, &This->device_players, guids[i]))
> + {
> + callbackFlags = diactionformat_priorityW(lpdiActionFormat, actionMasks[i]);
>
> - IDirectInput_CreateDevice(iface, guids[i], &lpdid, NULL);
> - IDirectInputDevice_GetDeviceInfo(lpdid, &didevi);
> + IDirectInput_CreateDevice(iface, guids[i], &lpdid, NULL);
> + IDirectInputDevice_GetDeviceInfo(lpdid, &didevi);
>
> - if (lpCallback(&didevi, lpdid, callbackFlags, sizeof(guids)/sizeof(guids[0]) - (i+1), pvRef) == DIENUM_STOP)
> - return DI_OK;
> + if (lpCallback(&didevi, lpdid, callbackFlags, --remain, pvRef) == DIENUM_STOP)
> + return DI_OK;
> + }
> }
>
> return DI_OK;
> diff --git a/dlls/dinput8/tests/dinput.c b/dlls/dinput8/tests/dinput.c
> index 18f3001596..e16542ab13 100644
> --- a/dlls/dinput8/tests/dinput.c
> +++ b/dlls/dinput8/tests/dinput.c
> @@ -562,6 +562,13 @@ static void test_EnumDevicesBySemantics(void)
> /* Keep the device total */
> device_total = data.device_count;
>
> + /* There should be no devices for any user. No device should be enumerated with DIEDBSFL_THISUSER.
> + MSDN defines that all unowned devices are also enumerated but this doesn't seem to be happening. */
> + data.device_count = 0;
> + hr = IDirectInput8_EnumDevicesBySemantics(pDI, "Sh4d0w M4g3", &diaf, enum_semantics_callback, &data, DIEDBSFL_THISUSER);
> + ok (SUCCEEDED(hr), "EnumDevicesBySemantics failed hr=%08x\n", hr);
> + ok (data.device_count == 0, "No devices should be assigned for this user assigned=%d\n", data.device_count);
> +
> /* This enumeration builds and sets the action map for all devices with a NULL username */
> hr = IDirectInput8_EnumDevicesBySemantics(pDI, NULL, &diaf, set_action_map_callback, &data, DIEDBSFL_ATTACHEDONLY);
> ok (SUCCEEDED(hr), "EnumDevicesBySemantics failed: hr=%08x\n", hr);
> @@ -570,7 +577,7 @@ static void test_EnumDevicesBySemantics(void)
> data.device_count = 0;
> hr = IDirectInput8_EnumDevicesBySemantics(pDI, NULL, &diaf, enum_semantics_callback, &data, DIEDBSFL_AVAILABLEDEVICES);
> ok (SUCCEEDED(hr), "EnumDevicesBySemantics failed hr=%08x\n", hr);
> - todo_wine ok (data.device_count == 0, "No device should be available after action mapping available=%d\n", data.device_count);
> + ok (data.device_count == 0, "No device should be available after action mapping available=%d\n", data.device_count);
>
> /* Now we'll give all the devices to a specific user */
> data.username = "Sh4d0w M4g3";
> @@ -593,7 +600,7 @@ static void test_EnumDevicesBySemantics(void)
> data.device_count = 0;
> hr = IDirectInput8_EnumDevicesBySemantics(pDI, "Ninja Brian", &diaf, enum_semantics_callback, &data, DIEDBSFL_THISUSER);
> ok (SUCCEEDED(hr), "EnumDevicesBySemantics failed hr=%08x\n", hr);
> - todo_wine ok (data.device_count == 0, "This user should own no devices owned=%d\n", data.device_count);
> + ok (data.device_count == 0, "This user should own no devices owned=%d\n", data.device_count);
>
> /* Sh4d0w M4g3 has ownership of all devices */
> data.device_count = 0;
> --
> 2.11.0
>
>
>
More information about the wine-patches
mailing list