static void test_action_mapping(void) { HRESULT hr; HINSTANCE hinst = GetModuleHandleA(NULL); IDirectInput8A *pDI = NULL; DIACTIONFORMATA af; DIPROPSTRING dps; struct enum_data data = {pDI, &af, NULL, NULL, NULL, 0}; HWND hwnd; hr = CoCreateInstance(&CLSID_DirectInput8, 0, CLSCTX_INPROC_SERVER, &IID_IDirectInput8A, (LPVOID*)&pDI); if (hr == DIERR_OLDDIRECTINPUTVERSION || hr == DIERR_BETADIRECTINPUTVERSION || hr == REGDB_E_CLASSNOTREG) { win_skip("ActionMapping requires dinput8\n"); return; } ok(SUCCEEDED(hr), "DirectInput8 Create failed: hr=%08x\n", hr); if (FAILED(hr)) return; hr = IDirectInput8_Initialize(pDI,hinst, DIRECTINPUT_VERSION); if (hr == DIERR_OLDDIRECTINPUTVERSION || hr == DIERR_BETADIRECTINPUTVERSION) { win_skip("ActionMapping requires dinput8\n"); return; } ok(SUCCEEDED(hr), "DirectInput8 Initialize failed: hr=%08x\n", hr); if (FAILED(hr)) return; memset (&af, 0, sizeof(af)); af.dwSize = sizeof(af); af.dwActionSize = sizeof(DIACTIONA); af.dwDataSize = 4 * ARRAY_SIZE(actionMapping); af.dwNumActions = ARRAY_SIZE(actionMapping); af.rgoAction = actionMapping; af.guidActionMap = ACTION_MAPPING_GUID; af.dwGenre = 0x01000000; /* DIVIRTUAL_DRIVING_RACE */ 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); /* Repeat tests with a non NULL user */ data.username = "******"; hr = IDirectInput8_EnumDevicesBySemantics(pDI, NULL, &af, enumeration_callback, &data, DIEDBSFL_ATTACHEDONLY); ok (SUCCEEDED(hr), "EnumDevicesBySemantics failed: hr=%08x\n", hr); hwnd = CreateWindowExA(WS_EX_TOPMOST, "static", "dinput", WS_POPUP | WS_VISIBLE, 0, 0, 100, 100, NULL, NULL, NULL, NULL); ok(hwnd != NULL, "failed to create window\n"); SetCursorPos(50, 50); if (data.keyboard != NULL) { /* Test keyboard BuildActionMap */ test_build_action_map(data.keyboard, data.lpdiaf, DITEST_KEYBOARDSPACE, DIDFT_PSHBUTTON, DIK_SPACE); /* Test keyboard input */ test_device_input(data.keyboard, INPUT_KEYBOARD, VK_SPACE, 2); /* Test BuildActionMap with no suitable actions for a device */ IDirectInputDevice_Unacquire(data.keyboard); af.dwDataSize = 4 * DITEST_KEYBOARDSPACE; af.dwNumActions = DITEST_KEYBOARDSPACE; hr = IDirectInputDevice8_BuildActionMap(data.keyboard, data.lpdiaf, NULL, DIDBAM_HWDEFAULTS); ok (hr == DI_NOEFFECT, "BuildActionMap should have no effect with no actions hr=%08x\n", hr); hr = IDirectInputDevice8_SetActionMap(data.keyboard, data.lpdiaf, NULL, 0); ok (hr == DI_NOEFFECT, "SetActionMap should have no effect with no actions to map hr=%08x\n", hr); af.dwDataSize = 4 * ARRAY_SIZE(actionMapping); af.dwNumActions = ARRAY_SIZE(actionMapping); /* 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_w(dps.wsz)); 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_w(dps.wsz)); } if (data.mouse != NULL) { /* Test mouse BuildActionMap */ test_build_action_map(data.mouse, data.lpdiaf, DITEST_MOUSEBUTTON0, DIDFT_PSHBUTTON, 0x03); test_build_action_map(data.mouse, data.lpdiaf, DITEST_YAXIS, DIDFT_RELAXIS, 0x01); test_device_input(data.mouse, INPUT_MOUSE, MOUSEEVENTF_LEFTDOWN, 3); } DestroyWindow(hwnd); }
static void test_EnumDevicesBySemantics(void) { IDirectInput8A *pDI; HRESULT hr; DIACTIONFORMATA diaf; const GUID ACTION_MAPPING_GUID = { 0x1, 0x2, 0x3, { 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb } }; struct enum_semantics_test data = { 0, 0, FALSE, FALSE, &diaf, NULL }; int device_total = 0; hr = DirectInput8Create(hInstance, DIRECTINPUT_VERSION, &IID_IDirectInput8A, (void **)&pDI, NULL); if (FAILED(hr)) { win_skip("Failed to instantiate a IDirectInputA instance: 0x%08x\n", hr); return; } memset (&diaf, 0, sizeof(diaf)); diaf.dwSize = sizeof(diaf); diaf.dwActionSize = sizeof(DIACTIONA); diaf.dwNumActions = ARRAY_SIZE(actionMapping); diaf.dwDataSize = 4 * diaf.dwNumActions; diaf.rgoAction = actionMapping; diaf.guidActionMap = ACTION_MAPPING_GUID; diaf.dwGenre = 0x01000000; /* DIVIRTUAL_DRIVING_RACE */ diaf.dwBufferSize = 32; /* Test enumerating all attached and installed devices */ data.keyboard = FALSE; data.mouse = FALSE; data.device_count = 0; hr = IDirectInput8_EnumDevicesBySemantics(pDI, NULL, &diaf, enum_semantics_callback, &data, DIEDBSFL_ATTACHEDONLY); ok (data.device_count > 0, "EnumDevicesBySemantics did not call the callback hr=%08x\n", hr); ok (data.keyboard, "EnumDevicesBySemantics should enumerate the keyboard\n"); ok (data.mouse, "EnumDevicesBySemantics should enumerate the mouse\n"); /* Enumerate Force feedback devices. We should get no mouse nor keyboard */ data.keyboard = FALSE; data.mouse = FALSE; data.device_count = 0; hr = IDirectInput8_EnumDevicesBySemantics(pDI, NULL, &diaf, enum_semantics_callback, &data, DIEDBSFL_FORCEFEEDBACK); ok (SUCCEEDED(hr), "EnumDevicesBySemantics failed hr=%08x\n", hr); ok (!data.keyboard, "Keyboard should not be enumerated when asking for forcefeedback\n"); ok (!data.mouse, "Mouse should not be enumerated when asking for forcefeedback\n"); /* Enumerate available devices. That is devices not owned by any user. Before setting the action map for all devices we still have them available. */ 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); ok (data.device_count > 0, "There should be devices available before action mapping available=%d\n", data.device_count); /* 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); /* After a successful action mapping we should have no devices available */ 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); 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 = "******"; hr = IDirectInput8_EnumDevicesBySemantics(pDI, NULL, &diaf, set_action_map_callback, &data, DIEDBSFL_ATTACHEDONLY); ok (SUCCEEDED(hr), "EnumDevicesBySemantics failed: hr=%08x\n", hr); /* Testing with the default user, DIEDBSFL_THISUSER has no effect */ data.device_count = 0; hr = IDirectInput8_EnumDevicesBySemantics(pDI, NULL, &diaf, enum_semantics_callback, &data, DIEDBSFL_THISUSER); ok (SUCCEEDED(hr), "EnumDevicesBySemantics failed hr=%08x\n", hr); ok (data.device_count == device_total, "THISUSER has no effect with NULL username owned=%d, expected=%d\n", data.device_count, device_total); /* Using an empty user string is the same as passing NULL, DIEDBSFL_THISUSER has no effect */ data.device_count = 0; hr = IDirectInput8_EnumDevicesBySemantics(pDI, "", &diaf, enum_semantics_callback, &data, DIEDBSFL_THISUSER); ok (SUCCEEDED(hr), "EnumDevicesBySemantics failed hr=%08x\n", hr); ok (data.device_count == device_total, "THISUSER has no effect with \"\" as username owned=%d, expected=%d\n", data.device_count, device_total); /* Testing with a user with no ownership of the devices */ 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); 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; 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 == device_total, "This user should own %d devices owned=%d\n", device_total, data.device_count); /* The call fails with a zeroed GUID */ memset(&diaf.guidActionMap, 0, sizeof(GUID)); data.device_count = 0; hr = IDirectInput8_EnumDevicesBySemantics(pDI, NULL, &diaf, enum_semantics_callback, NULL, 0); todo_wine ok(FAILED(hr), "EnumDevicesBySemantics succeeded with invalid GUID hr=%08x\n", hr); IDirectInput8_Release(pDI); }