[2/4] dinput: Handle username in EnumDevicesBySemantics.
Jetro Jormalainen
jje-wine at jv.jetro.fi
Wed Feb 22 17:22:19 CST 2017
EnumDevicesBySemantics enums only devices with given username when
DIEDBSFL_THISUSER is set and only unowned devices when
DIEDBSFL_AVAILABLEDEVICES is set.
Tested on Windows 10, Windows XP and Arch Linux.
Signed-off-by: Jetro Jormalainen <jje-wine at jv.jetro.fi>
---
dlls/dinput/dinput_main.c | 103 +++++++++++++++++++++++++++++++++++++++-------
1 file changed, 89 insertions(+), 14 deletions(-)
diff --git a/dlls/dinput/dinput_main.c b/dlls/dinput/dinput_main.c
index 2bf9f38ba4..d8a5cadbb7 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 unsigned char should_enumerate_device(const WCHAR *username, DWORD dwFlags,
+ struct list *device_players, REFGUID guid)
+{
+ unsigned char should_enumerate = 1;
+ struct DevicePlayer *device_player;
+
+ /* Check if user owns this device */
+ if (dwFlags & DIEDBSFL_THISUSER && username && strlenW(username))
+ {
+ should_enumerate = 0;
+ LIST_FOR_EACH_ENTRY(device_player, device_players, struct DevicePlayer, entry)
+ {
+ if (IsEqualGUID(&device_player->guid, guid))
+ {
+ if (lstrlenW(device_player->username) && !lstrcmpW(username, device_player->username))
+ return 1; /* Device username matches */
+ break;
+ }
+ }
+ }
+
+ /* Check if this device is not owned by anyone */
+ if (dwFlags & DIEDBSFL_AVAILABLEDEVICES) {
+ unsigned char found = 0;
+ should_enumerate = 0;
+ LIST_FOR_EACH_ENTRY(device_player, device_players, struct DevicePlayer, entry)
+ {
+ if (IsEqualGUID(&device_player->guid, guid))
+ {
+ if (lstrlenW(device_player->username))
+ found = 1;
+ break;
+ }
+ }
+ if (!found)
+ return 1; /* Device does not have an username */
+ }
+
+ return should_enumerate;
+}
+
static HRESULT WINAPI IDirectInput8AImpl_EnumDevicesBySemantics(
LPDIRECTINPUT8A iface, LPCSTR ptszUserName, LPDIACTIONFORMATA lpdiActionFormat,
LPDIENUMDEVICESBYSEMANTICSCBA lpCallback,
@@ -939,6 +980,8 @@ static HRESULT WINAPI IDirectInput8AImpl_EnumDevicesBySemantics(
int device_count = 0;
int remain;
DIDEVICEINSTANCEA *didevis = 0;
+ WCHAR username_w[MAX_PATH];
+ DWORD username_size = MAX_PATH;
FIXME("(this=%p,%s,%p,%p,%p,%04x): semi-stub\n", This, debugstr_a(ptszUserName), lpdiActionFormat,
lpCallback, pvRef, dwFlags);
@@ -955,6 +998,14 @@ static HRESULT WINAPI IDirectInput8AImpl_EnumDevicesBySemantics(
didevi.dwSize = sizeof(didevi);
+ if (ptszUserName)
+ {
+ username_size = MultiByteToWideChar(CP_ACP, 0, ptszUserName, -1, 0, 0);
+ MultiByteToWideChar(CP_ACP, 0, ptszUserName, -1, username_w, username_size);
+ }
+ else
+ username_w[0] = '\0';
+
/* Enumerate all the joysticks */
for (i = 0; i < NB_DINPUT_DEVICES; i++)
{
@@ -968,7 +1019,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 +1032,17 @@ 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++)
{
@@ -1002,13 +1063,16 @@ static HRESULT WINAPI IDirectInput8AImpl_EnumDevicesBySemantics(
/* 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)
+ return DI_OK;
+ }
}
return DI_OK;
@@ -1049,7 +1113,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 +1126,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 +1155,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;
--
2.11.0
More information about the wine-patches
mailing list