mfplat: Read queue subscriber within the critical section.
[wine/zf.git] / dlls / dinput8 / tests / device.c
blob3e6da23b4abefebc8a4516a8f012f95b53f8ba1c
1 /*
2 * Copyright (c) 2011 Lucas Fialho Zawacki
3 * Copyright (c) 2006 Vitaliy Margolen
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Lesser General Public
7 * License as published by the Free Software Foundation; either
8 * version 2.1 of the License, or (at your option) any later version.
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Lesser General Public License for more details.
15 * You should have received a copy of the GNU Lesser General Public
16 * License along with this library; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
20 #define DIRECTINPUT_VERSION 0x0800
22 #define COBJMACROS
23 #include <windows.h>
25 #include "wine/test.h"
26 #include "windef.h"
27 #include "dinput.h"
29 struct enum_data {
30 IDirectInput8A *pDI;
31 DIACTIONFORMATA *lpdiaf;
32 IDirectInputDevice8A *keyboard;
33 IDirectInputDevice8A *mouse;
34 const char* username;
35 int ndevices;
38 /* Dummy GUID */
39 static const GUID ACTION_MAPPING_GUID = { 0x1, 0x2, 0x3, { 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb } };
41 enum {
42 DITEST_AXIS,
43 DITEST_BUTTON,
44 DITEST_KEYBOARDSPACE,
45 DITEST_MOUSEBUTTON0,
46 DITEST_YAXIS
49 static DIACTIONA actionMapping[]=
51 /* axis */
52 { 0, 0x01008A01 /* DIAXIS_DRIVINGR_STEER */, 0, { "Steer.\0" } },
53 /* button */
54 { 1, 0x01000C01 /* DIBUTTON_DRIVINGR_SHIFTUP */, 0, { "Upshift.\0" } },
55 /* keyboard key */
56 { 2, DIKEYBOARD_SPACE, 0, { "Missile.\0" } },
57 /* mouse button */
58 { 3, DIMOUSE_BUTTON0, 0, { "Select\0" } },
59 /* mouse axis */
60 { 4, DIMOUSE_YAXIS, 0, { "Y Axis\0" } }
62 /* By placing the memory pointed to by lptszActionName right before memory with PAGE_NOACCESS
63 * one can find out that the regular ansi string termination is not respected by EnumDevicesBySemantics.
64 * Adding a double termination, making it a valid wide string termination, made the test succeed.
65 * Therefore it looks like ansi version of EnumDevicesBySemantics forwards the string to
66 * the wide variant without conversation. */
68 static void flush_events(void)
70 int diff = 200;
71 int min_timeout = 100;
72 DWORD time = GetTickCount() + diff;
74 while (diff > 0)
76 if (MsgWaitForMultipleObjects(0, NULL, FALSE, min_timeout, QS_ALLINPUT) == WAIT_TIMEOUT)
77 break;
78 diff = time - GetTickCount();
79 min_timeout = 50;
83 static void test_device_input(IDirectInputDevice8A *lpdid, DWORD event_type, DWORD event, UINT_PTR expected)
85 HRESULT hr;
86 DIDEVICEOBJECTDATA obj_data;
87 DWORD data_size = 1;
88 int i;
90 hr = IDirectInputDevice8_Acquire(lpdid);
91 ok (SUCCEEDED(hr), "Failed to acquire device hr=%08x\n", hr);
93 if (event_type == INPUT_KEYBOARD)
94 keybd_event(event, MapVirtualKeyA(event, MAPVK_VK_TO_VSC), 0, 0);
96 if (event_type == INPUT_MOUSE)
97 mouse_event( event, 0, 0, 0, 0);
99 flush_events();
100 IDirectInputDevice8_Poll(lpdid);
101 hr = IDirectInputDevice8_GetDeviceData(lpdid, sizeof(obj_data), &obj_data, &data_size, 0);
103 if (data_size != 1)
105 win_skip("We're not able to inject input into Windows dinput8 with events\n");
106 IDirectInputDevice_Unacquire(lpdid);
107 return;
110 ok (obj_data.uAppData == expected, "Retrieval of action failed uAppData=%lu expected=%lu\n", obj_data.uAppData, expected);
112 /* Check for buffer overflow */
113 for (i = 0; i < 17; i++)
114 if (event_type == INPUT_KEYBOARD)
116 keybd_event( VK_SPACE, DIK_SPACE, 0, 0);
117 keybd_event( VK_SPACE, DIK_SPACE, KEYEVENTF_KEYUP, 0);
119 else if (event_type == INPUT_MOUSE)
121 mouse_event(MOUSEEVENTF_LEFTDOWN, 1, 1, 0, 0);
122 mouse_event(MOUSEEVENTF_LEFTUP, 1, 1, 0, 0);
125 flush_events();
126 IDirectInputDevice8_Poll(lpdid);
128 data_size = 1;
129 hr = IDirectInputDevice8_GetDeviceData(lpdid, sizeof(obj_data), &obj_data, &data_size, 0);
130 ok(hr == DI_BUFFEROVERFLOW, "GetDeviceData() failed: %08x\n", hr);
131 data_size = 1;
132 hr = IDirectInputDevice8_GetDeviceData(lpdid, sizeof(obj_data), &obj_data, &data_size, 0);
133 ok(hr == DI_OK && data_size == 1, "GetDeviceData() failed: %08x cnt:%d\n", hr, data_size);
135 /* drain device's queue */
136 while (data_size == 1)
138 hr = IDirectInputDevice8_GetDeviceData(lpdid, sizeof(obj_data), &obj_data, &data_size, 0);
139 ok(hr == DI_OK, "GetDeviceData() failed: %08x cnt:%d\n", hr, data_size);
140 if (hr != DI_OK) break;
143 IDirectInputDevice_Unacquire(lpdid);
146 static void test_build_action_map(IDirectInputDevice8A *lpdid, DIACTIONFORMATA *lpdiaf,
147 int action_index, DWORD expected_type, DWORD expected_inst)
149 HRESULT hr;
150 DIACTIONA *actions;
151 DWORD instance, type, how;
152 GUID assigned_to;
153 DIDEVICEINSTANCEA ddi;
155 ddi.dwSize = sizeof(ddi);
156 IDirectInputDevice_GetDeviceInfo(lpdid, &ddi);
158 hr = IDirectInputDevice8_BuildActionMap(lpdid, lpdiaf, NULL, DIDBAM_HWDEFAULTS);
159 ok (SUCCEEDED(hr), "BuildActionMap failed hr=%08x\n", hr);
161 actions = lpdiaf->rgoAction;
162 instance = DIDFT_GETINSTANCE(actions[action_index].dwObjID);
163 type = DIDFT_GETTYPE(actions[action_index].dwObjID);
164 how = actions[action_index].dwHow;
165 assigned_to = actions[action_index].guidInstance;
167 ok (how == DIAH_USERCONFIG || how == DIAH_DEFAULT, "Action was not set dwHow=%08x\n", how);
168 ok (instance == expected_inst, "Action not mapped correctly instance=%08x expected=%08x\n", instance, expected_inst);
169 ok (type == expected_type, "Action type not mapped correctly type=%08x expected=%08x\n", type, expected_type);
170 ok (IsEqualGUID(&assigned_to, &ddi.guidInstance), "Action and device GUID do not match action=%d\n", action_index);
173 static BOOL CALLBACK enumeration_callback(const DIDEVICEINSTANCEA *lpddi, IDirectInputDevice8A *lpdid,
174 DWORD dwFlags, DWORD dwRemaining, LPVOID pvRef)
176 HRESULT hr;
177 DIPROPDWORD dp;
178 DIPROPRANGE dpr;
179 DIPROPSTRING dps;
180 WCHAR usernameW[MAX_PATH];
181 DWORD username_size = MAX_PATH;
182 struct enum_data *data = pvRef;
183 DWORD cnt;
184 DIDEVICEOBJECTDATA buffer[5];
185 IDirectInputDevice8A *lpdid2;
187 if (!data) return DIENUM_CONTINUE;
189 data->ndevices++;
191 /* Convert username to WCHAR */
192 if (data->username != NULL)
194 username_size = MultiByteToWideChar(CP_ACP, 0, data->username, -1, usernameW, 0);
195 MultiByteToWideChar(CP_ACP, 0, data->username, -1, usernameW, username_size);
197 else
198 GetUserNameW(usernameW, &username_size);
200 /* collect the mouse and keyboard */
201 if (IsEqualGUID(&lpddi->guidInstance, &GUID_SysKeyboard))
203 IDirectInputDevice_AddRef(lpdid);
204 data->keyboard = lpdid;
206 ok (dwFlags & DIEDBS_MAPPEDPRI1, "Keyboard should be mapped as pri1 dwFlags=%08x\n", dwFlags);
209 if (IsEqualGUID(&lpddi->guidInstance, &GUID_SysMouse))
211 IDirectInputDevice_AddRef(lpdid);
212 data->mouse = lpdid;
214 ok (dwFlags & DIEDBS_MAPPEDPRI1, "Mouse should be mapped as pri1 dwFlags=%08x\n", dwFlags);
217 /* Creating second device object to check if it has the same username */
218 hr = IDirectInput_CreateDevice(data->pDI, &lpddi->guidInstance, &lpdid2, NULL);
219 ok(SUCCEEDED(hr), "IDirectInput_CreateDevice() failed: %08x\n", hr);
221 /* Building and setting an action map */
222 /* It should not use any pre-stored mappings so we use DIDBAM_HWDEFAULTS */
223 hr = IDirectInputDevice8_BuildActionMap(lpdid, data->lpdiaf, NULL, DIDBAM_HWDEFAULTS);
224 ok (SUCCEEDED(hr), "BuildActionMap failed hr=%08x\n", hr);
226 /* Device has no data format and thus can't be acquired */
227 hr = IDirectInputDevice8_Acquire(lpdid);
228 ok (hr == DIERR_INVALIDPARAM, "Device was acquired before SetActionMap hr=%08x\n", hr);
230 hr = IDirectInputDevice8_SetActionMap(lpdid, data->lpdiaf, data->username, 0);
231 ok (SUCCEEDED(hr), "SetActionMap failed hr=%08x\n", hr);
233 /* Some joysticks may have no suitable actions and thus should not be tested */
234 if (hr == DI_NOEFFECT) return DIENUM_CONTINUE;
236 /* Test username after SetActionMap */
237 dps.diph.dwSize = sizeof(dps);
238 dps.diph.dwHeaderSize = sizeof(DIPROPHEADER);
239 dps.diph.dwObj = 0;
240 dps.diph.dwHow = DIPH_DEVICE;
241 dps.wsz[0] = '\0';
243 hr = IDirectInputDevice_GetProperty(lpdid, DIPROP_USERNAME, &dps.diph);
244 ok (SUCCEEDED(hr), "GetProperty failed hr=%08x\n", hr);
245 ok (!lstrcmpW(usernameW, dps.wsz), "Username not set correctly expected=%s, got=%s\n", wine_dbgstr_w(usernameW), wine_dbgstr_w(dps.wsz));
247 dps.wsz[0] = '\0';
248 hr = IDirectInputDevice_GetProperty(lpdid2, DIPROP_USERNAME, &dps.diph);
249 ok (SUCCEEDED(hr), "GetProperty failed hr=%08x\n", hr);
250 ok (!lstrcmpW(usernameW, dps.wsz), "Username not set correctly expected=%s, got=%s\n", wine_dbgstr_w(usernameW), wine_dbgstr_w(dps.wsz));
252 /* Test buffer size */
253 memset(&dp, 0, sizeof(dp));
254 dp.diph.dwSize = sizeof(dp);
255 dp.diph.dwHeaderSize = sizeof(DIPROPHEADER);
256 dp.diph.dwHow = DIPH_DEVICE;
258 hr = IDirectInputDevice_GetProperty(lpdid, DIPROP_BUFFERSIZE, &dp.diph);
259 ok (SUCCEEDED(hr), "GetProperty failed hr=%08x\n", hr);
260 ok (dp.dwData == data->lpdiaf->dwBufferSize, "SetActionMap must set the buffer, buffersize=%d\n", dp.dwData);
262 cnt = 1;
263 hr = IDirectInputDevice_GetDeviceData(lpdid, sizeof(buffer[0]), buffer, &cnt, 0);
264 ok(hr == DIERR_NOTACQUIRED, "GetDeviceData() failed hr=%08x\n", hr);
266 /* Test axis range */
267 memset(&dpr, 0, sizeof(dpr));
268 dpr.diph.dwSize = sizeof(dpr);
269 dpr.diph.dwHeaderSize = sizeof(DIPROPHEADER);
270 dpr.diph.dwHow = DIPH_DEVICE;
272 hr = IDirectInputDevice_GetProperty(lpdid, DIPROP_RANGE, &dpr.diph);
273 /* Only test if device supports the range property */
274 if (SUCCEEDED(hr))
276 ok (dpr.lMin == data->lpdiaf->lAxisMin, "SetActionMap must set the min axis range expected=%d got=%d\n", data->lpdiaf->lAxisMin, dpr.lMin);
277 ok (dpr.lMax == data->lpdiaf->lAxisMax, "SetActionMap must set the max axis range expected=%d got=%d\n", data->lpdiaf->lAxisMax, dpr.lMax);
280 /* SetActionMap has set the data format so now it should work */
281 hr = IDirectInputDevice8_Acquire(lpdid);
282 ok (SUCCEEDED(hr), "Acquire failed hr=%08x\n", hr);
284 cnt = 1;
285 hr = IDirectInputDevice_GetDeviceData(lpdid, sizeof(buffer[0]), buffer, &cnt, 0);
286 ok(hr == DI_OK, "GetDeviceData() failed hr=%08x\n", hr);
288 /* SetActionMap should not work on an acquired device */
289 hr = IDirectInputDevice8_SetActionMap(lpdid, data->lpdiaf, NULL, 0);
290 ok (hr == DIERR_ACQUIRED, "SetActionMap succeeded with an acquired device hr=%08x\n", hr);
292 IDirectInputDevice_Release(lpdid2);
294 return DIENUM_CONTINUE;
297 static void test_appdata_property_vs_map(struct enum_data *data)
299 HRESULT hr;
300 DIPROPPOINTER dp;
302 dp.diph.dwSize = sizeof(dp);
303 dp.diph.dwHeaderSize = sizeof(DIPROPHEADER);
304 dp.diph.dwHow = DIPH_BYID;
305 dp.diph.dwObj = DIDFT_MAKEINSTANCE(DIK_SPACE) | DIDFT_PSHBUTTON;
306 dp.uData = 10;
307 hr = IDirectInputDevice8_SetProperty(data->keyboard, DIPROP_APPDATA, &(dp.diph));
308 ok(SUCCEEDED(hr), "IDirectInputDevice8_SetProperty failed hr=%08x\n", hr);
310 test_device_input(data->keyboard, INPUT_KEYBOARD, VK_SPACE, 10);
312 dp.diph.dwHow = DIPH_BYID;
313 dp.diph.dwObj = DIDFT_MAKEINSTANCE(DIK_V) | DIDFT_PSHBUTTON;
314 dp.uData = 11;
315 hr = IDirectInputDevice8_SetProperty(data->keyboard, DIPROP_APPDATA, &(dp.diph));
316 ok(hr == DIERR_OBJECTNOTFOUND, "IDirectInputDevice8_SetProperty should not find key that's not in the action map hr=%08x\n", hr);
318 /* setting format should reset action map */
319 hr = IDirectInputDevice8_SetDataFormat(data->keyboard, &c_dfDIKeyboard);
320 ok(SUCCEEDED(hr), "SetDataFormat failed: %08x\n", hr);
322 test_device_input(data->keyboard, INPUT_KEYBOARD, VK_SPACE, -1);
324 dp.diph.dwHow = DIPH_BYID;
325 dp.diph.dwObj = DIDFT_MAKEINSTANCE(DIK_V) | DIDFT_PSHBUTTON;
326 dp.uData = 11;
327 hr = IDirectInputDevice8_SetProperty(data->keyboard, DIPROP_APPDATA, &(dp.diph));
328 ok(SUCCEEDED(hr), "IDirectInputDevice8_SetProperty failed hr=%08x\n", hr);
330 test_device_input(data->keyboard, INPUT_KEYBOARD, 'V', 11);
332 /* back to action map */
333 hr = IDirectInputDevice8_SetActionMap(data->keyboard, data->lpdiaf, NULL, 0);
334 ok(SUCCEEDED(hr), "SetActionMap failed hr=%08x\n", hr);
336 test_device_input(data->keyboard, INPUT_KEYBOARD, VK_SPACE, 2);
339 static void test_action_mapping(void)
341 HRESULT hr;
342 HINSTANCE hinst = GetModuleHandleA(NULL);
343 IDirectInput8A *pDI = NULL;
344 DIACTIONFORMATA af;
345 DIPROPSTRING dps;
346 struct enum_data data = {pDI, &af, NULL, NULL, NULL, 0};
347 HWND hwnd;
349 hr = CoCreateInstance(&CLSID_DirectInput8, 0, CLSCTX_INPROC_SERVER, &IID_IDirectInput8A, (LPVOID*)&pDI);
350 if (hr == DIERR_OLDDIRECTINPUTVERSION ||
351 hr == DIERR_BETADIRECTINPUTVERSION ||
352 hr == REGDB_E_CLASSNOTREG)
354 win_skip("ActionMapping requires dinput8\n");
355 return;
357 ok(SUCCEEDED(hr), "DirectInput8 Create failed: hr=%08x\n", hr);
358 if (FAILED(hr)) return;
360 hr = IDirectInput8_Initialize(pDI,hinst, DIRECTINPUT_VERSION);
361 if (hr == DIERR_OLDDIRECTINPUTVERSION || hr == DIERR_BETADIRECTINPUTVERSION)
363 win_skip("ActionMapping requires dinput8\n");
364 return;
366 ok(SUCCEEDED(hr), "DirectInput8 Initialize failed: hr=%08x\n", hr);
367 if (FAILED(hr)) return;
369 memset (&af, 0, sizeof(af));
370 af.dwSize = sizeof(af);
371 af.dwActionSize = sizeof(DIACTIONA);
372 af.dwDataSize = 4 * ARRAY_SIZE(actionMapping);
373 af.dwNumActions = ARRAY_SIZE(actionMapping);
374 af.rgoAction = actionMapping;
375 af.guidActionMap = ACTION_MAPPING_GUID;
376 af.dwGenre = 0x01000000; /* DIVIRTUAL_DRIVING_RACE */
377 af.dwBufferSize = 32;
379 /* This enumeration builds and sets the action map for all devices */
380 data.pDI = pDI;
381 hr = IDirectInput8_EnumDevicesBySemantics(pDI, 0, &af, enumeration_callback, &data, DIEDBSFL_ATTACHEDONLY);
382 ok (SUCCEEDED(hr), "EnumDevicesBySemantics failed: hr=%08x\n", hr);
384 if (data.keyboard)
385 IDirectInputDevice_Release(data.keyboard);
387 if (data.mouse)
388 IDirectInputDevice_Release(data.mouse);
390 /* Repeat tests with a non NULL user */
391 data.username = "Ninja Brian";
392 hr = IDirectInput8_EnumDevicesBySemantics(pDI, NULL, &af, enumeration_callback, &data, DIEDBSFL_ATTACHEDONLY);
393 ok (SUCCEEDED(hr), "EnumDevicesBySemantics failed: hr=%08x\n", hr);
395 hwnd = CreateWindowExA(WS_EX_TOPMOST, "static", "dinput",
396 WS_POPUP | WS_VISIBLE, 0, 0, 100, 100, NULL, NULL, NULL, NULL);
397 ok(hwnd != NULL, "failed to create window\n");
398 SetCursorPos(50, 50);
400 if (data.keyboard != NULL)
402 /* Test keyboard BuildActionMap */
403 test_build_action_map(data.keyboard, data.lpdiaf, DITEST_KEYBOARDSPACE, DIDFT_PSHBUTTON, DIK_SPACE);
404 /* Test keyboard input */
405 test_device_input(data.keyboard, INPUT_KEYBOARD, VK_SPACE, 2);
407 /* setting format should reset action map */
408 hr = IDirectInputDevice8_SetDataFormat(data.keyboard, &c_dfDIKeyboard);
409 ok (SUCCEEDED(hr), "IDirectInputDevice8_SetDataFormat failed: %08x\n", hr);
411 test_device_input(data.keyboard, INPUT_KEYBOARD, VK_SPACE, -1);
413 /* back to action map */
414 hr = IDirectInputDevice8_SetActionMap(data.keyboard, data.lpdiaf, NULL, 0);
415 ok (SUCCEEDED(hr), "SetActionMap should succeed hr=%08x\n", hr);
417 test_device_input(data.keyboard, INPUT_KEYBOARD, VK_SPACE, 2);
419 test_appdata_property_vs_map(&data);
421 /* Test BuildActionMap with no suitable actions for a device */
422 IDirectInputDevice_Unacquire(data.keyboard);
423 af.dwDataSize = 4 * DITEST_KEYBOARDSPACE;
424 af.dwNumActions = DITEST_KEYBOARDSPACE;
426 hr = IDirectInputDevice8_BuildActionMap(data.keyboard, data.lpdiaf, NULL, DIDBAM_HWDEFAULTS);
427 ok (hr == DI_NOEFFECT, "BuildActionMap should have no effect with no actions hr=%08x\n", hr);
429 hr = IDirectInputDevice8_SetActionMap(data.keyboard, data.lpdiaf, NULL, 0);
430 ok (hr == DI_NOEFFECT, "SetActionMap should have no effect with no actions to map hr=%08x\n", hr);
432 af.dwDataSize = 4 * ARRAY_SIZE(actionMapping);
433 af.dwNumActions = ARRAY_SIZE(actionMapping);
435 /* test DIDSAM_NOUSER */
436 dps.diph.dwSize = sizeof(dps);
437 dps.diph.dwHeaderSize = sizeof(DIPROPHEADER);
438 dps.diph.dwObj = 0;
439 dps.diph.dwHow = DIPH_DEVICE;
440 dps.wsz[0] = '\0';
442 hr = IDirectInputDevice_GetProperty(data.keyboard, DIPROP_USERNAME, &dps.diph);
443 ok (SUCCEEDED(hr), "GetProperty failed hr=%08x\n", hr);
444 ok (dps.wsz[0] != 0, "Expected any username, got=%s\n", wine_dbgstr_w(dps.wsz));
446 hr = IDirectInputDevice8_SetActionMap(data.keyboard, data.lpdiaf, NULL, DIDSAM_NOUSER);
447 ok (SUCCEEDED(hr), "SetActionMap failed hr=%08x\n", hr);
449 dps.diph.dwSize = sizeof(dps);
450 dps.diph.dwHeaderSize = sizeof(DIPROPHEADER);
451 dps.diph.dwObj = 0;
452 dps.diph.dwHow = DIPH_DEVICE;
453 dps.wsz[0] = '\0';
455 hr = IDirectInputDevice_GetProperty(data.keyboard, DIPROP_USERNAME, &dps.diph);
456 ok (SUCCEEDED(hr), "GetProperty failed hr=%08x\n", hr);
457 ok (dps.wsz[0] == 0, "Expected empty username, got=%s\n", wine_dbgstr_w(dps.wsz));
459 IDirectInputDevice_Release(data.keyboard);
462 if (data.mouse != NULL)
464 /* Test mouse BuildActionMap */
465 test_build_action_map(data.mouse, data.lpdiaf, DITEST_MOUSEBUTTON0, DIDFT_PSHBUTTON, 0x03);
466 test_build_action_map(data.mouse, data.lpdiaf, DITEST_YAXIS, DIDFT_RELAXIS, 0x01);
468 test_device_input(data.mouse, INPUT_MOUSE, MOUSEEVENTF_LEFTDOWN, 3);
470 IDirectInputDevice_Release(data.mouse);
473 DestroyWindow(hwnd);
474 IDirectInput_Release(pDI);
477 static void test_save_settings(void)
479 HRESULT hr;
480 HINSTANCE hinst = GetModuleHandleA(NULL);
481 IDirectInput8A *pDI = NULL;
482 DIACTIONFORMATA af;
483 IDirectInputDevice8A *pKey;
485 static const GUID mapping_guid = { 0xcafecafe, 0x2, 0x3, { 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb } };
486 static const GUID other_guid = { 0xcafe, 0xcafe, 0x3, { 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb } };
488 static DIACTIONA actions[] = {
489 { 0, DIKEYBOARD_A , 0, { "Blam" } },
490 { 1, DIKEYBOARD_B , 0, { "Kapow"} }
492 static const DWORD results[] = {
493 DIDFT_MAKEINSTANCE(DIK_A) | DIDFT_PSHBUTTON,
494 DIDFT_MAKEINSTANCE(DIK_B) | DIDFT_PSHBUTTON
496 static const DWORD other_results[] = {
497 DIDFT_MAKEINSTANCE(DIK_C) | DIDFT_PSHBUTTON,
498 DIDFT_MAKEINSTANCE(DIK_D) | DIDFT_PSHBUTTON
501 hr = CoCreateInstance(&CLSID_DirectInput8, 0, CLSCTX_INPROC_SERVER, &IID_IDirectInput8A, (LPVOID*)&pDI);
502 if (hr == DIERR_OLDDIRECTINPUTVERSION ||
503 hr == DIERR_BETADIRECTINPUTVERSION ||
504 hr == REGDB_E_CLASSNOTREG)
506 win_skip("ActionMapping requires dinput8\n");
507 return;
509 ok (SUCCEEDED(hr), "DirectInput8 Create failed: hr=%08x\n", hr);
510 if (FAILED(hr)) return;
512 hr = IDirectInput8_Initialize(pDI,hinst, DIRECTINPUT_VERSION);
513 if (hr == DIERR_OLDDIRECTINPUTVERSION || hr == DIERR_BETADIRECTINPUTVERSION)
515 win_skip("ActionMapping requires dinput8\n");
516 return;
518 ok (SUCCEEDED(hr), "DirectInput8 Initialize failed: hr=%08x\n", hr);
519 if (FAILED(hr)) return;
521 hr = IDirectInput_CreateDevice(pDI, &GUID_SysKeyboard, &pKey, NULL);
522 ok (SUCCEEDED(hr), "IDirectInput_Create device failed hr: 0x%08x\n", hr);
523 if (FAILED(hr)) return;
525 memset (&af, 0, sizeof(af));
526 af.dwSize = sizeof(af);
527 af.dwActionSize = sizeof(DIACTIONA);
528 af.dwDataSize = 4 * ARRAY_SIZE(actions);
529 af.dwNumActions = ARRAY_SIZE(actions);
530 af.rgoAction = actions;
531 af.guidActionMap = mapping_guid;
532 af.dwGenre = 0x01000000; /* DIVIRTUAL_DRIVING_RACE */
533 af.dwBufferSize = 32;
535 /* Easy case. Ask for default mapping, save, ask for previous map and read it back */
536 hr = IDirectInputDevice8_BuildActionMap(pKey, &af, NULL, DIDBAM_HWDEFAULTS);
537 ok (SUCCEEDED(hr), "BuildActionMap failed hr=%08x\n", hr);
538 ok (results[0] == af.rgoAction[0].dwObjID,
539 "Mapped incorrectly expected: 0x%08x got: 0x%08x\n", results[0], af.rgoAction[0].dwObjID);
541 ok (results[1] == af.rgoAction[1].dwObjID,
542 "Mapped incorrectly expected: 0x%08x got: 0x%08x\n", results[1], af.rgoAction[1].dwObjID);
544 hr = IDirectInputDevice8_SetActionMap(pKey, &af, NULL, DIDSAM_FORCESAVE);
545 ok (SUCCEEDED(hr), "SetActionMap failed hr=%08x\n", hr);
547 if (hr == DI_SETTINGSNOTSAVED)
549 skip ("Can't test saving settings if SetActionMap returns DI_SETTINGSNOTSAVED\n");
550 return;
553 af.rgoAction[0].dwObjID = 0;
554 af.rgoAction[1].dwObjID = 0;
555 memset(&af.rgoAction[0].guidInstance, 0, sizeof(GUID));
556 memset(&af.rgoAction[1].guidInstance, 0, sizeof(GUID));
558 hr = IDirectInputDevice8_BuildActionMap(pKey, &af, NULL, 0);
559 ok (SUCCEEDED(hr), "BuildActionMap failed hr=%08x\n", hr);
561 ok (results[0] == af.rgoAction[0].dwObjID,
562 "Mapped incorrectly expected: 0x%08x got: 0x%08x\n", results[0], af.rgoAction[0].dwObjID);
563 ok (IsEqualGUID(&GUID_SysKeyboard, &af.rgoAction[0].guidInstance), "Action should be mapped to keyboard\n");
565 ok (results[1] == af.rgoAction[1].dwObjID,
566 "Mapped incorrectly expected: 0x%08x got: 0x%08x\n", results[1], af.rgoAction[1].dwObjID);
567 ok (IsEqualGUID(&GUID_SysKeyboard, &af.rgoAction[1].guidInstance), "Action should be mapped to keyboard\n");
569 /* Test that a different action map with no pre-stored settings, in spite of the flags,
570 does not try to load mappings and instead applies the default mapping */
571 af.guidActionMap = other_guid;
573 af.rgoAction[0].dwObjID = 0;
574 af.rgoAction[1].dwObjID = 0;
575 memset(&af.rgoAction[0].guidInstance, 0, sizeof(GUID));
576 memset(&af.rgoAction[1].guidInstance, 0, sizeof(GUID));
578 hr = IDirectInputDevice8_BuildActionMap(pKey, &af, NULL, 0);
579 ok (SUCCEEDED(hr), "BuildActionMap failed hr=%08x\n", hr);
581 ok (results[0] == af.rgoAction[0].dwObjID,
582 "Mapped incorrectly expected: 0x%08x got: 0x%08x\n", results[0], af.rgoAction[0].dwObjID);
583 ok (IsEqualGUID(&GUID_SysKeyboard, &af.rgoAction[0].guidInstance), "Action should be mapped to keyboard\n");
585 ok (results[1] == af.rgoAction[1].dwObjID,
586 "Mapped incorrectly expected: 0x%08x got: 0x%08x\n", results[1], af.rgoAction[1].dwObjID);
587 ok (IsEqualGUID(&GUID_SysKeyboard, &af.rgoAction[1].guidInstance), "Action should be mapped to keyboard\n");
589 af.guidActionMap = mapping_guid;
590 /* Hard case. Customized mapping, save, ask for previous map and read it back */
591 af.rgoAction[0].dwObjID = other_results[0];
592 af.rgoAction[0].dwHow = DIAH_USERCONFIG;
593 af.rgoAction[0].guidInstance = GUID_SysKeyboard;
594 af.rgoAction[1].dwObjID = other_results[1];
595 af.rgoAction[1].dwHow = DIAH_USERCONFIG;
596 af.rgoAction[1].guidInstance = GUID_SysKeyboard;
598 hr = IDirectInputDevice8_SetActionMap(pKey, &af, NULL, DIDSAM_FORCESAVE);
599 ok (SUCCEEDED(hr), "SetActionMap failed hr=%08x\n", hr);
601 if (hr == DI_SETTINGSNOTSAVED)
603 skip ("Can't test saving settings if SetActionMap returns DI_SETTINGSNOTSAVED\n");
604 return;
607 af.rgoAction[0].dwObjID = 0;
608 af.rgoAction[1].dwObjID = 0;
609 memset(&af.rgoAction[0].guidInstance, 0, sizeof(GUID));
610 memset(&af.rgoAction[1].guidInstance, 0, sizeof(GUID));
612 hr = IDirectInputDevice8_BuildActionMap(pKey, &af, NULL, 0);
613 ok (SUCCEEDED(hr), "BuildActionMap failed hr=%08x\n", hr);
615 ok (other_results[0] == af.rgoAction[0].dwObjID,
616 "Mapped incorrectly expected: 0x%08x got: 0x%08x\n", other_results[0], af.rgoAction[0].dwObjID);
617 ok (IsEqualGUID(&GUID_SysKeyboard, &af.rgoAction[0].guidInstance), "Action should be mapped to keyboard\n");
619 ok (other_results[1] == af.rgoAction[1].dwObjID,
620 "Mapped incorrectly expected: 0x%08x got: 0x%08x\n", other_results[1], af.rgoAction[1].dwObjID);
621 ok (IsEqualGUID(&GUID_SysKeyboard, &af.rgoAction[1].guidInstance), "Action should be mapped to keyboard\n");
623 IDirectInputDevice_Release(pKey);
624 IDirectInput_Release(pDI);
627 static void test_mouse_keyboard(void)
629 HRESULT hr;
630 HWND hwnd, di_hwnd = INVALID_HANDLE_VALUE;
631 IDirectInput8A *di = NULL;
632 IDirectInputDevice8A *di_mouse, *di_keyboard;
633 UINT raw_devices_count;
634 RAWINPUTDEVICE raw_devices[3];
636 hwnd = CreateWindowExA(WS_EX_TOPMOST, "static", "dinput", WS_POPUP | WS_VISIBLE, 0, 0, 100, 100, NULL, NULL, NULL, NULL);
637 ok(hwnd != NULL, "CreateWindowExA failed\n");
639 hr = CoCreateInstance(&CLSID_DirectInput8, 0, CLSCTX_INPROC_SERVER, &IID_IDirectInput8A, (LPVOID*)&di);
640 if (hr == DIERR_OLDDIRECTINPUTVERSION ||
641 hr == DIERR_BETADIRECTINPUTVERSION ||
642 hr == REGDB_E_CLASSNOTREG)
644 win_skip("test_mouse_keyboard requires dinput8\n");
645 return;
647 ok(SUCCEEDED(hr), "DirectInput8Create failed: %08x\n", hr);
649 hr = IDirectInput8_Initialize(di, GetModuleHandleA(NULL), DIRECTINPUT_VERSION);
650 if (hr == DIERR_OLDDIRECTINPUTVERSION || hr == DIERR_BETADIRECTINPUTVERSION)
652 win_skip("test_mouse_keyboard requires dinput8\n");
653 return;
655 ok(SUCCEEDED(hr), "IDirectInput8_Initialize failed: %08x\n", hr);
657 hr = IDirectInput8_CreateDevice(di, &GUID_SysMouse, &di_mouse, NULL);
658 ok(SUCCEEDED(hr), "IDirectInput8_CreateDevice failed: %08x\n", hr);
659 hr = IDirectInputDevice8_SetDataFormat(di_mouse, &c_dfDIMouse);
660 ok(SUCCEEDED(hr), "IDirectInputDevice8_SetDataFormat failed: %08x\n", hr);
662 hr = IDirectInput8_CreateDevice(di, &GUID_SysKeyboard, &di_keyboard, NULL);
663 ok(SUCCEEDED(hr), "IDirectInput8_CreateDevice failed: %08x\n", hr);
664 hr = IDirectInputDevice8_SetDataFormat(di_keyboard, &c_dfDIKeyboard);
665 ok(SUCCEEDED(hr), "IDirectInputDevice8_SetDataFormat failed: %08x\n", hr);
667 raw_devices_count = ARRAY_SIZE(raw_devices);
668 GetRegisteredRawInputDevices(NULL, &raw_devices_count, sizeof(RAWINPUTDEVICE));
669 ok(raw_devices_count == 0, "Unexpected raw devices registered: %d\n", raw_devices_count);
671 hr = IDirectInputDevice8_Acquire(di_keyboard);
672 ok(SUCCEEDED(hr), "IDirectInputDevice8_Acquire failed: %08x\n", hr);
673 raw_devices_count = ARRAY_SIZE(raw_devices);
674 memset(raw_devices, 0, sizeof(raw_devices));
675 hr = GetRegisteredRawInputDevices(raw_devices, &raw_devices_count, sizeof(RAWINPUTDEVICE));
676 todo_wine
677 ok(hr == 1, "GetRegisteredRawInputDevices returned %d, raw_devices_count: %d\n", hr, raw_devices_count);
678 todo_wine
679 ok(raw_devices[0].usUsagePage == 1, "Unexpected raw device usage page: %x\n", raw_devices[0].usUsagePage);
680 todo_wine
681 ok(raw_devices[0].usUsage == 6, "Unexpected raw device usage: %x\n", raw_devices[0].usUsage);
682 todo_wine
683 ok(raw_devices[0].dwFlags == RIDEV_INPUTSINK, "Unexpected raw device flags: %x\n", raw_devices[0].dwFlags);
684 todo_wine
685 ok(raw_devices[0].hwndTarget != NULL, "Unexpected raw device target: %p\n", raw_devices[0].hwndTarget);
686 hr = IDirectInputDevice8_Unacquire(di_keyboard);
687 ok(SUCCEEDED(hr), "IDirectInputDevice8_Acquire failed: %08x\n", hr);
688 raw_devices_count = ARRAY_SIZE(raw_devices);
689 GetRegisteredRawInputDevices(NULL, &raw_devices_count, sizeof(RAWINPUTDEVICE));
690 ok(raw_devices_count == 0, "Unexpected raw devices registered: %d\n", raw_devices_count);
692 if (raw_devices[0].hwndTarget != NULL)
694 WCHAR str[16];
695 int i;
697 di_hwnd = raw_devices[0].hwndTarget;
698 i = GetClassNameW(di_hwnd, str, ARRAY_SIZE(str));
699 ok(i == lstrlenW(L"DIEmWin"), "GetClassName returned incorrect length\n");
700 ok(!lstrcmpW(L"DIEmWin", str), "GetClassName returned incorrect name for this window's class\n");
702 i = GetWindowTextW(di_hwnd, str, ARRAY_SIZE(str));
703 ok(i == lstrlenW(L"DIEmWin"), "GetClassName returned incorrect length\n");
704 ok(!lstrcmpW(L"DIEmWin", str), "GetClassName returned incorrect name for this window's class\n");
707 hr = IDirectInputDevice8_Acquire(di_mouse);
708 ok(SUCCEEDED(hr), "IDirectInputDevice8_Acquire failed: %08x\n", hr);
709 raw_devices_count = ARRAY_SIZE(raw_devices);
710 memset(raw_devices, 0, sizeof(raw_devices));
711 hr = GetRegisteredRawInputDevices(raw_devices, &raw_devices_count, sizeof(RAWINPUTDEVICE));
712 ok(hr == 1, "GetRegisteredRawInputDevices returned %d, raw_devices_count: %d\n", hr, raw_devices_count);
713 ok(raw_devices[0].usUsagePage == 1, "Unexpected raw device usage page: %x\n", raw_devices[0].usUsagePage);
714 ok(raw_devices[0].usUsage == 2, "Unexpected raw device usage: %x\n", raw_devices[0].usUsage);
715 ok(raw_devices[0].dwFlags == RIDEV_INPUTSINK, "Unexpected raw device flags: %x\n", raw_devices[0].dwFlags);
716 todo_wine
717 ok(raw_devices[0].hwndTarget == di_hwnd, "Unexpected raw device target: %p\n", raw_devices[0].hwndTarget);
718 hr = IDirectInputDevice8_Unacquire(di_mouse);
719 ok(SUCCEEDED(hr), "IDirectInputDevice8_Acquire failed: %08x\n", hr);
720 raw_devices_count = ARRAY_SIZE(raw_devices);
721 GetRegisteredRawInputDevices(NULL, &raw_devices_count, sizeof(RAWINPUTDEVICE));
722 ok(raw_devices_count == 0, "Unexpected raw devices registered: %d\n", raw_devices_count);
724 if (raw_devices[0].hwndTarget != NULL)
725 di_hwnd = raw_devices[0].hwndTarget;
727 /* expect dinput8 to take over any activated raw input devices */
728 raw_devices[0].usUsagePage = 0x01;
729 raw_devices[0].usUsage = 0x05;
730 raw_devices[0].dwFlags = 0;
731 raw_devices[0].hwndTarget = hwnd;
732 raw_devices[1].usUsagePage = 0x01;
733 raw_devices[1].usUsage = 0x06;
734 raw_devices[1].dwFlags = 0;
735 raw_devices[1].hwndTarget = hwnd;
736 raw_devices[2].usUsagePage = 0x01;
737 raw_devices[2].usUsage = 0x02;
738 raw_devices[2].dwFlags = 0;
739 raw_devices[2].hwndTarget = hwnd;
740 raw_devices_count = ARRAY_SIZE(raw_devices);
741 hr = RegisterRawInputDevices(raw_devices, raw_devices_count, sizeof(RAWINPUTDEVICE));
742 ok(hr == TRUE, "RegisterRawInputDevices failed\n");
744 hr = IDirectInputDevice8_Acquire(di_keyboard);
745 ok(SUCCEEDED(hr), "IDirectInputDevice8_Acquire failed: %08x\n", hr);
746 hr = IDirectInputDevice8_Acquire(di_mouse);
747 ok(SUCCEEDED(hr), "IDirectInputDevice8_Acquire failed: %08x\n", hr);
748 raw_devices_count = ARRAY_SIZE(raw_devices);
749 memset(raw_devices, 0, sizeof(raw_devices));
750 hr = GetRegisteredRawInputDevices(raw_devices, &raw_devices_count, sizeof(RAWINPUTDEVICE));
751 ok(hr == 3, "GetRegisteredRawInputDevices returned %d, raw_devices_count: %d\n", hr, raw_devices_count);
752 ok(raw_devices[0].usUsagePage == 1, "Unexpected raw device usage page: %x\n", raw_devices[0].usUsagePage);
753 ok(raw_devices[0].usUsage == 2, "Unexpected raw device usage: %x\n", raw_devices[0].usUsage);
754 ok(raw_devices[0].dwFlags == RIDEV_INPUTSINK, "Unexpected raw device flags: %x\n", raw_devices[0].dwFlags);
755 ok(raw_devices[0].hwndTarget == di_hwnd, "Unexpected raw device target: %p\n", raw_devices[0].hwndTarget);
756 ok(raw_devices[1].usUsagePage == 1, "Unexpected raw device usage page: %x\n", raw_devices[1].usUsagePage);
757 ok(raw_devices[1].usUsage == 5, "Unexpected raw device usage: %x\n", raw_devices[1].usUsage);
758 ok(raw_devices[1].dwFlags == 0, "Unexpected raw device flags: %x\n", raw_devices[1].dwFlags);
759 ok(raw_devices[1].hwndTarget == hwnd, "Unexpected raw device target: %p\n", raw_devices[1].hwndTarget);
760 ok(raw_devices[2].usUsagePage == 1, "Unexpected raw device usage page: %x\n", raw_devices[1].usUsagePage);
761 ok(raw_devices[2].usUsage == 6, "Unexpected raw device usage: %x\n", raw_devices[1].usUsage);
762 todo_wine
763 ok(raw_devices[2].dwFlags == RIDEV_INPUTSINK, "Unexpected raw device flags: %x\n", raw_devices[1].dwFlags);
764 todo_wine
765 ok(raw_devices[2].hwndTarget == di_hwnd, "Unexpected raw device target: %p\n", raw_devices[1].hwndTarget);
766 hr = IDirectInputDevice8_Unacquire(di_keyboard);
767 ok(SUCCEEDED(hr), "IDirectInputDevice8_Acquire failed: %08x\n", hr);
768 hr = IDirectInputDevice8_Unacquire(di_mouse);
769 ok(SUCCEEDED(hr), "IDirectInputDevice8_Acquire failed: %08x\n", hr);
770 raw_devices_count = ARRAY_SIZE(raw_devices);
771 GetRegisteredRawInputDevices(NULL, &raw_devices_count, sizeof(RAWINPUTDEVICE));
772 todo_wine
773 ok(raw_devices_count == 1, "Unexpected raw devices registered: %d\n", raw_devices_count);
775 IDirectInputDevice8_SetCooperativeLevel(di_mouse, hwnd, DISCL_FOREGROUND|DISCL_EXCLUSIVE);
776 IDirectInputDevice8_SetCooperativeLevel(di_keyboard, hwnd, DISCL_FOREGROUND|DISCL_EXCLUSIVE);
778 hr = IDirectInputDevice8_Acquire(di_keyboard);
779 ok(SUCCEEDED(hr), "IDirectInputDevice8_Acquire failed: %08x\n", hr);
780 hr = IDirectInputDevice8_Acquire(di_mouse);
781 ok(SUCCEEDED(hr), "IDirectInputDevice8_Acquire failed: %08x\n", hr);
782 raw_devices_count = ARRAY_SIZE(raw_devices);
783 memset(raw_devices, 0, sizeof(raw_devices));
784 hr = GetRegisteredRawInputDevices(raw_devices, &raw_devices_count, sizeof(RAWINPUTDEVICE));
785 ok(hr == 3, "GetRegisteredRawInputDevices returned %d, raw_devices_count: %d\n", hr, raw_devices_count);
786 ok(raw_devices[0].dwFlags == (RIDEV_CAPTUREMOUSE|RIDEV_NOLEGACY), "Unexpected raw device flags: %x\n", raw_devices[0].dwFlags);
787 todo_wine
788 ok(raw_devices[2].dwFlags == (RIDEV_NOHOTKEYS|RIDEV_NOLEGACY), "Unexpected raw device flags: %x\n", raw_devices[1].dwFlags);
789 hr = IDirectInputDevice8_Unacquire(di_keyboard);
790 ok(SUCCEEDED(hr), "IDirectInputDevice8_Acquire failed: %08x\n", hr);
791 hr = IDirectInputDevice8_Unacquire(di_mouse);
792 ok(SUCCEEDED(hr), "IDirectInputDevice8_Acquire failed: %08x\n", hr);
794 raw_devices_count = ARRAY_SIZE(raw_devices);
795 hr = GetRegisteredRawInputDevices(raw_devices, &raw_devices_count, sizeof(RAWINPUTDEVICE));
796 todo_wine
797 ok(hr == 1, "GetRegisteredRawInputDevices returned %d, raw_devices_count: %d\n", hr, raw_devices_count);
798 ok(raw_devices[0].usUsagePage == 1, "Unexpected raw device usage page: %x\n", raw_devices[0].usUsagePage);
799 ok(raw_devices[0].usUsage == 5, "Unexpected raw device usage: %x\n", raw_devices[0].usUsage);
800 ok(raw_devices[0].dwFlags == 0, "Unexpected raw device flags: %x\n", raw_devices[0].dwFlags);
801 ok(raw_devices[0].hwndTarget == hwnd, "Unexpected raw device target: %p\n", raw_devices[0].hwndTarget);
803 IDirectInputDevice8_Release(di_mouse);
804 IDirectInputDevice8_Release(di_keyboard);
805 IDirectInput8_Release(di);
807 DestroyWindow(hwnd);
810 static void test_keyboard_events(void)
812 HRESULT hr;
813 HWND hwnd = INVALID_HANDLE_VALUE;
814 IDirectInput8A *di;
815 IDirectInputDevice8A *di_keyboard;
816 DIPROPDWORD dp;
817 DIDEVICEOBJECTDATA obj_data[10];
818 DWORD data_size;
819 BYTE kbdata[256];
821 hr = CoCreateInstance(&CLSID_DirectInput8, 0, CLSCTX_INPROC_SERVER, &IID_IDirectInput8A, (LPVOID*)&di);
822 if (hr == DIERR_OLDDIRECTINPUTVERSION ||
823 hr == DIERR_BETADIRECTINPUTVERSION ||
824 hr == REGDB_E_CLASSNOTREG)
826 win_skip("test_keyboard_events requires dinput8\n");
827 return;
829 ok(SUCCEEDED(hr), "DirectInput8Create failed: %08x\n", hr);
831 hr = IDirectInput8_Initialize(di, GetModuleHandleA(NULL), DIRECTINPUT_VERSION);
832 if (hr == DIERR_OLDDIRECTINPUTVERSION || hr == DIERR_BETADIRECTINPUTVERSION)
834 win_skip("test_keyboard_events requires dinput8\n");
835 IDirectInput8_Release(di);
836 return;
838 ok(SUCCEEDED(hr), "IDirectInput8_Initialize failed: %08x\n", hr);
840 hwnd = CreateWindowExA(WS_EX_TOPMOST, "static", "dinput", WS_POPUP | WS_VISIBLE, 0, 0, 100, 100, NULL, NULL, NULL, NULL);
841 ok(hwnd != NULL, "CreateWindowExA failed\n");
843 hr = IDirectInput8_CreateDevice(di, &GUID_SysKeyboard, &di_keyboard, NULL);
844 ok(SUCCEEDED(hr), "IDirectInput8_CreateDevice failed: %08x\n", hr);
845 hr = IDirectInputDevice8_SetCooperativeLevel(di_keyboard, hwnd, DISCL_BACKGROUND | DISCL_NONEXCLUSIVE);
846 ok(SUCCEEDED(hr), "IDirectInput8_SetCooperativeLevel failed: %08x\n", hr);
847 hr = IDirectInputDevice8_SetDataFormat(di_keyboard, &c_dfDIKeyboard);
848 ok(SUCCEEDED(hr), "IDirectInputDevice8_SetDataFormat failed: %08x\n", hr);
849 dp.diph.dwSize = sizeof(DIPROPDWORD);
850 dp.diph.dwHeaderSize = sizeof(DIPROPHEADER);
851 dp.diph.dwObj = 0;
852 dp.diph.dwHow = DIPH_DEVICE;
853 dp.dwData = ARRAY_SIZE(obj_data);
854 IDirectInputDevice8_SetProperty(di_keyboard, DIPROP_BUFFERSIZE, &(dp.diph));
856 hr = IDirectInputDevice8_Acquire(di_keyboard);
857 ok(SUCCEEDED(hr), "IDirectInputDevice8_Acquire failed: %08x\n", hr);
859 /* Test injecting keyboard events with both VK and scancode given. */
860 keybd_event(VK_SPACE, DIK_SPACE, 0, 0);
861 flush_events();
862 IDirectInputDevice8_Poll(di_keyboard);
863 data_size = ARRAY_SIZE(obj_data);
864 hr = IDirectInputDevice8_GetDeviceData(di_keyboard, sizeof(DIDEVICEOBJECTDATA), obj_data, &data_size, 0);
865 ok(SUCCEEDED(hr), "Failed to get data hr=%08x\n", hr);
866 ok(data_size == 1, "Expected 1 element, received %d\n", data_size);
868 hr = IDirectInputDevice8_GetDeviceState(di_keyboard, sizeof(kbdata), kbdata);
869 ok(SUCCEEDED(hr), "IDirectInputDevice8_GetDeviceState failed: %08x\n", hr);
870 ok(kbdata[DIK_SPACE], "Expected DIK_SPACE key state down\n");
872 keybd_event(VK_SPACE, DIK_SPACE, KEYEVENTF_KEYUP, 0);
873 flush_events();
874 IDirectInputDevice8_Poll(di_keyboard);
875 data_size = ARRAY_SIZE(obj_data);
876 hr = IDirectInputDevice8_GetDeviceData(di_keyboard, sizeof(DIDEVICEOBJECTDATA), obj_data, &data_size, 0);
877 ok(SUCCEEDED(hr), "Failed to get data hr=%08x\n", hr);
878 ok(data_size == 1, "Expected 1 element, received %d\n", data_size);
880 /* Test injecting keyboard events with scancode=0.
881 * Windows DInput ignores the VK, sets scancode 0 to be pressed, and GetDeviceData returns no elements. */
882 keybd_event(VK_SPACE, 0, 0, 0);
883 flush_events();
884 IDirectInputDevice8_Poll(di_keyboard);
885 data_size = ARRAY_SIZE(obj_data);
886 hr = IDirectInputDevice8_GetDeviceData(di_keyboard, sizeof(DIDEVICEOBJECTDATA), obj_data, &data_size, 0);
887 ok(SUCCEEDED(hr), "Failed to get data hr=%08x\n", hr);
888 ok(data_size == 0, "Expected 0 elements, received %d\n", data_size);
890 hr = IDirectInputDevice8_GetDeviceState(di_keyboard, sizeof(kbdata), kbdata);
891 ok(SUCCEEDED(hr), "IDirectInputDevice8_GetDeviceState failed: %08x\n", hr);
892 todo_wine
893 ok(kbdata[0], "Expected key 0 state down\n");
895 keybd_event(VK_SPACE, 0, KEYEVENTF_KEYUP, 0);
896 flush_events();
897 IDirectInputDevice8_Poll(di_keyboard);
898 data_size = ARRAY_SIZE(obj_data);
899 hr = IDirectInputDevice8_GetDeviceData(di_keyboard, sizeof(DIDEVICEOBJECTDATA), obj_data, &data_size, 0);
900 ok(SUCCEEDED(hr), "Failed to get data hr=%08x\n", hr);
901 ok(data_size == 0, "Expected 0 elements, received %d\n", data_size);
903 hr = IDirectInputDevice8_Unacquire(di_keyboard);
904 ok(SUCCEEDED(hr), "IDirectInputDevice8_Unacquire failed: %08x\n", hr);
906 IDirectInputDevice8_Release(di_keyboard);
907 IDirectInput8_Release(di);
909 DestroyWindow(hwnd);
912 static void test_appdata_property(void)
914 HRESULT hr;
915 HINSTANCE hinst = GetModuleHandleA(NULL);
916 IDirectInputDevice8A *di_keyboard;
917 IDirectInput8A *pDI = NULL;
918 HWND hwnd;
919 DIPROPDWORD dw;
920 DIPROPPOINTER dp;
922 hr = CoCreateInstance(&CLSID_DirectInput8, 0, CLSCTX_INPROC_SERVER, &IID_IDirectInput8A, (LPVOID*)&pDI);
923 if (hr == DIERR_OLDDIRECTINPUTVERSION ||
924 hr == DIERR_BETADIRECTINPUTVERSION ||
925 hr == REGDB_E_CLASSNOTREG)
927 win_skip("DIPROP_APPDATA requires dinput8\n");
928 return;
930 ok(SUCCEEDED(hr), "DirectInput8 Create failed: hr=%08x\n", hr);
931 if (FAILED(hr)) return;
933 hr = IDirectInput8_Initialize(pDI,hinst, DIRECTINPUT_VERSION);
934 if (hr == DIERR_OLDDIRECTINPUTVERSION || hr == DIERR_BETADIRECTINPUTVERSION)
936 win_skip("DIPROP_APPDATA requires dinput8\n");
937 return;
939 ok(SUCCEEDED(hr), "DirectInput8 Initialize failed: hr=%08x\n", hr);
940 if (FAILED(hr)) return;
942 hwnd = CreateWindowExA(WS_EX_TOPMOST, "static", "dinput",
943 WS_POPUP | WS_VISIBLE, 0, 0, 100, 100, NULL, NULL, NULL, NULL);
944 ok(hwnd != NULL, "failed to create window\n");
946 hr = IDirectInput8_CreateDevice(pDI, &GUID_SysKeyboard, &di_keyboard, NULL);
947 ok(SUCCEEDED(hr), "IDirectInput8_CreateDevice failed: %08x\n", hr);
949 hr = IDirectInputDevice8_SetDataFormat(di_keyboard, &c_dfDIKeyboard);
950 ok(SUCCEEDED(hr), "IDirectInputDevice8_SetDataFormat failed: %08x\n", hr);
952 dw.diph.dwSize = sizeof(DIPROPDWORD);
953 dw.diph.dwHeaderSize = sizeof(DIPROPHEADER);
954 dw.diph.dwObj = 0;
955 dw.diph.dwHow = DIPH_DEVICE;
956 dw.dwData = 32;
957 hr = IDirectInputDevice8_SetProperty(di_keyboard, DIPROP_BUFFERSIZE, &(dw.diph));
958 ok(SUCCEEDED(hr), "IDirectInputDevice8_SetProperty failed hr=%08x\n", hr);
960 /* the default value */
961 test_device_input(di_keyboard, INPUT_KEYBOARD, 'A', -1);
963 dp.diph.dwHow = DIPH_DEVICE;
964 dp.diph.dwObj = 0;
965 dp.uData = 1;
966 hr = IDirectInputDevice8_SetProperty(di_keyboard, DIPROP_APPDATA, &(dp.diph));
967 ok(hr == DIERR_INVALIDPARAM, "IDirectInputDevice8_SetProperty APPDATA for the device should be invalid hr=%08x\n", hr);
969 dp.diph.dwSize = sizeof(dp);
970 dp.diph.dwHeaderSize = sizeof(DIPROPHEADER);
971 dp.diph.dwHow = DIPH_BYUSAGE;
972 dp.diph.dwObj = 2;
973 dp.uData = 2;
974 hr = IDirectInputDevice8_SetProperty(di_keyboard, DIPROP_APPDATA, &(dp.diph));
975 ok(hr == DIERR_UNSUPPORTED, "IDirectInputDevice8_SetProperty APPDATA by usage should be unsupported hr=%08x\n", hr);
977 dp.diph.dwHow = DIPH_BYID;
978 dp.diph.dwObj = DIDFT_MAKEINSTANCE(DIK_SPACE) | DIDFT_PSHBUTTON;
979 dp.uData = 3;
980 hr = IDirectInputDevice8_SetProperty(di_keyboard, DIPROP_APPDATA, &(dp.diph));
981 ok(SUCCEEDED(hr), "IDirectInputDevice8_SetProperty failed hr=%08x\n", hr);
983 dp.diph.dwHow = DIPH_BYOFFSET;
984 dp.diph.dwObj = DIK_A;
985 dp.uData = 4;
986 hr = IDirectInputDevice8_SetProperty(di_keyboard, DIPROP_APPDATA, &(dp.diph));
987 ok(SUCCEEDED(hr), "IDirectInputDevice8_SetProperty failed hr=%08x\n", hr);
989 dp.diph.dwHow = DIPH_BYOFFSET;
990 dp.diph.dwObj = DIK_B;
991 dp.uData = 5;
992 hr = IDirectInputDevice8_SetProperty(di_keyboard, DIPROP_APPDATA, &(dp.diph));
993 ok(SUCCEEDED(hr), "IDirectInputDevice8_SetProperty failed hr=%08x\n", hr);
995 test_device_input(di_keyboard, INPUT_KEYBOARD, VK_SPACE, 3);
996 test_device_input(di_keyboard, INPUT_KEYBOARD, 'A', 4);
997 test_device_input(di_keyboard, INPUT_KEYBOARD, 'B', 5);
998 test_device_input(di_keyboard, INPUT_KEYBOARD, 'C', -1);
1000 /* setting data format resets APPDATA */
1001 hr = IDirectInputDevice8_SetDataFormat(di_keyboard, &c_dfDIKeyboard);
1002 ok(SUCCEEDED(hr), "IDirectInputDevice8_SetDataFormat failed: %08x\n", hr);
1004 test_device_input(di_keyboard, INPUT_KEYBOARD, VK_SPACE, -1);
1005 test_device_input(di_keyboard, INPUT_KEYBOARD, 'A', -1);
1006 test_device_input(di_keyboard, INPUT_KEYBOARD, 'B', -1);
1007 test_device_input(di_keyboard, INPUT_KEYBOARD, 'C', -1);
1009 DestroyWindow(hwnd);
1010 IDirectInputDevice_Release(di_keyboard);
1011 IDirectInput_Release(pDI);
1014 START_TEST(device)
1016 CoInitialize(NULL);
1018 test_action_mapping();
1019 test_save_settings();
1020 test_mouse_keyboard();
1021 test_keyboard_events();
1022 test_appdata_property();
1024 CoUninitialize();