1 /* 2 * Copyright (c) 2005 Robert Reif 3 * 4 * This library is free software; you can redistribute it and/or 5 * modify it under the terms of the GNU Lesser General Public 6 * License as published by the Free Software Foundation; either 7 * version 2.1 of the License, or (at your option) any later version. 8 * 9 * This library is distributed in the hope that it will be useful, 10 * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 12 * Lesser General Public License for more details. 13 * 14 * You should have received a copy of the GNU Lesser General Public 15 * License along with this library; if not, write to the Free Software 16 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA 17 */ 18 19 #define DIRECTINPUT_VERSION 0x0700 20 21 #define COBJMACROS 22 #include <windows.h> 23 24 #include <math.h> 25 #include <stdio.h> 26 #include <stdlib.h> 27 28 #include "wine/test.h" 29 #include "windef.h" 30 #include "wingdi.h" 31 #include "dinput.h" 32 33 /* to make things easier with PSDK without a dinput.lib */ 34 static HRESULT (WINAPI *pDirectInputCreateA)(HINSTANCE,DWORD,IDirectInputA **,IUnknown *); 35 36 static void pump_messages(void) 37 { 38 MSG msg; 39 40 while (PeekMessageA(&msg, 0, 0, 0, PM_REMOVE)) 41 { 42 TranslateMessage(&msg); 43 DispatchMessageA(&msg); 44 } 45 } 46 47 static HKL activate_keyboard_layout(LANGID langid, HKL *hkl_orig) 48 { 49 HKL hkl, hkl_current; 50 char hkl_name[64]; 51 52 sprintf(hkl_name, "%08x", langid); 53 trace("Loading keyboard layout %s\n", hkl_name); 54 hkl = LoadKeyboardLayoutA(hkl_name, 0); 55 if (!hkl) 56 { 57 win_skip("Unable to load keyboard layout %s\n", hkl_name); 58 return 0; 59 } 60 *hkl_orig = ActivateKeyboardLayout(hkl, 0); 61 ok(*hkl_orig != 0, "Unable to activate keyboard layout %s\n", hkl_name); 62 if (!*hkl_orig) return 0; 63 64 hkl_current = GetKeyboardLayout(0); 65 if (LOWORD(hkl_current) != langid) 66 { 67 /* FIXME: Wine can't activate different keyboard layouts. 68 * for testing purposes use this workaround: 69 * setxkbmap us && LANG=en_US.UTF-8 make test 70 * setxkbmap fr && LANG=fr_FR.UTF-8 make test 71 * setxkbmap de && LANG=de_DE.UTF-8 make test 72 */ 73 skip("current %08x != langid %08x\n", LOWORD(hkl_current), langid); 74 return 0; 75 } 76 77 return hkl; 78 } 79 80 static void acquire_tests(IDirectInputA *pDI, HWND hwnd) 81 { 82 HRESULT hr; 83 IDirectInputDeviceA *pKeyboard; 84 BYTE kbd_state[256]; 85 LONG custom_state[6]; 86 int i; 87 DIOBJECTDATAFORMAT dodf[] = 88 { 89 { &GUID_Key, sizeof(LONG) * 0, DIDFT_MAKEINSTANCE(DIK_Q)|DIDFT_BUTTON, 0 }, 90 { &GUID_Key, sizeof(LONG) * 1, DIDFT_MAKEINSTANCE(DIK_W)|DIDFT_BUTTON, 0 }, 91 { &GUID_Key, sizeof(LONG) * 2, DIDFT_MAKEINSTANCE(DIK_E)|DIDFT_BUTTON, 0 }, 92 { &GUID_Key, sizeof(LONG) * 4, DIDFT_MAKEINSTANCE(DIK_R)|DIDFT_BUTTON, 0 }, 93 }; 94 DIDATAFORMAT df; 95 HKL hkl, hkl_orig; 96 UINT prev_raw_devices_count, raw_devices_count; 97 98 hkl = activate_keyboard_layout(MAKELANGID(LANG_ENGLISH, SUBLANG_DEFAULT), &hkl_orig); 99 if (!hkl) return; 100 101 df.dwSize = sizeof( df ); 102 df.dwObjSize = sizeof( DIOBJECTDATAFORMAT ); 103 df.dwFlags = DIDF_RELAXIS; 104 df.dwDataSize = sizeof( custom_state ); 105 df.dwNumObjs = ARRAY_SIZE(dodf); 106 df.rgodf = dodf; 107 108 hr = IDirectInput_CreateDevice(pDI, &GUID_SysKeyboard, &pKeyboard, NULL); 109 ok(SUCCEEDED(hr), "IDirectInput_CreateDevice() failed: %08x\n", hr); 110 if (FAILED(hr)) return; 111 112 hr = IDirectInputDevice_SetDataFormat(pKeyboard, &c_dfDIKeyboard); 113 ok(SUCCEEDED(hr), "IDirectInputDevice_SetDataFormat() failed: %08x\n", hr); 114 hr = IDirectInputDevice_SetCooperativeLevel(pKeyboard, NULL, DISCL_NONEXCLUSIVE | DISCL_BACKGROUND); 115 ok(SUCCEEDED(hr), "IDirectInputDevice_SetCooperativeLevel() failed: %08x\n", hr); 116 hr = IDirectInputDevice_GetDeviceState(pKeyboard, 10, kbd_state); 117 ok(hr == DIERR_NOTACQUIRED, "IDirectInputDevice_GetDeviceState(10,) should have failed: %08x\n", hr); 118 hr = IDirectInputDevice_GetDeviceState(pKeyboard, sizeof(kbd_state), kbd_state); 119 ok(hr == DIERR_NOTACQUIRED, "IDirectInputDevice_GetDeviceState() should have failed: %08x\n", hr); 120 hr = IDirectInputDevice_Unacquire(pKeyboard); 121 ok(hr == S_FALSE, "IDirectInputDevice_Unacquire() should have failed: %08x\n", hr); 122 hr = IDirectInputDevice_Acquire(pKeyboard); 123 ok(SUCCEEDED(hr), "IDirectInputDevice_Acquire() failed: %08x\n", hr); 124 hr = IDirectInputDevice_Acquire(pKeyboard); 125 ok(hr == S_FALSE, "IDirectInputDevice_Acquire() should have failed: %08x\n", hr); 126 hr = IDirectInputDevice_GetDeviceState(pKeyboard, 10, kbd_state); 127 ok(hr == DIERR_INVALIDPARAM, "IDirectInputDevice_GetDeviceState(10,) should have failed: %08x\n", hr); 128 hr = IDirectInputDevice_GetDeviceState(pKeyboard, sizeof(kbd_state), kbd_state); 129 ok(SUCCEEDED(hr), "IDirectInputDevice_GetDeviceState() failed: %08x\n", hr); 130 hr = IDirectInputDevice_Unacquire(pKeyboard); 131 ok(SUCCEEDED(hr), "IDirectInputDevice_Uncquire() failed: %08x\n", hr); 132 hr = IDirectInputDevice_SetDataFormat( pKeyboard , &df ); 133 ok(SUCCEEDED(hr), "IDirectInputDevice_SetDataFormat() failed: %08x\n", hr); 134 hr = IDirectInputDevice_Acquire(pKeyboard); 135 ok(SUCCEEDED(hr), "IDirectInputDevice_Acquire() failed: %08x\n", hr); 136 hr = IDirectInputDevice_GetDeviceState(pKeyboard, sizeof(custom_state), custom_state); 137 ok(SUCCEEDED(hr), "IDirectInputDevice_GetDeviceState(4,) failed: %08x\n", hr); 138 hr = IDirectInputDevice_GetDeviceState(pKeyboard, sizeof(kbd_state), kbd_state); 139 ok(hr == DIERR_INVALIDPARAM, "IDirectInputDevice_GetDeviceState(256,) should have failed: %08x\n", hr); 140 141 memset(custom_state, 0x56, sizeof(custom_state)); 142 IDirectInputDevice_GetDeviceState(pKeyboard, sizeof(custom_state), custom_state); 143 for (i = 0; i < ARRAY_SIZE(custom_state); i++) 144 ok(custom_state[i] == 0, "Should be zeroed, got 0x%08x\n", custom_state[i]); 145 146 /* simulate some keyboard input */ 147 SetFocus(hwnd); 148 pump_messages(); 149 150 keybd_event('Q', 0, 0, 0); 151 hr = IDirectInputDevice_GetDeviceState(pKeyboard, sizeof(custom_state), custom_state); 152 ok(SUCCEEDED(hr), "IDirectInputDevice_GetDeviceState() failed: %08x\n", hr); 153 if (!custom_state[0]) 154 win_skip("Keyboard event not processed, skipping test\n"); 155 else 156 { 157 /* unacquiring should reset the device state */ 158 hr = IDirectInputDevice_Unacquire(pKeyboard); 159 ok(SUCCEEDED(hr), "IDirectInputDevice_Unacquire() failed: %08x\n", hr); 160 hr = IDirectInputDevice_Acquire(pKeyboard); 161 ok(SUCCEEDED(hr), "IDirectInputDevice_Acquire() failed: %08x\n", hr); 162 hr = IDirectInputDevice_GetDeviceState(pKeyboard, sizeof(custom_state), custom_state); 163 ok(SUCCEEDED(hr), "IDirectInputDevice_GetDeviceState failed: %08x\n", hr); 164 for (i = 0; i < ARRAY_SIZE(custom_state); i++) 165 ok(custom_state[i] == 0, "Should be zeroed, got 0x%08x\n", custom_state[i]); 166 } 167 keybd_event('Q', 0, KEYEVENTF_KEYUP, 0); 168 169 prev_raw_devices_count = 0; 170 GetRegisteredRawInputDevices(NULL, &prev_raw_devices_count, sizeof(RAWINPUTDEVICE)); 171 ok(prev_raw_devices_count == 0 || broken(prev_raw_devices_count == 1) /* wxppro, w2003std */, 172 "Unexpected raw devices registered: %d\n", prev_raw_devices_count); 173 174 hr = IDirectInputDevice_Acquire(pKeyboard); 175 ok(SUCCEEDED(hr), "IDirectInputDevice_Acquire() failed: %08x\n", hr); 176 177 raw_devices_count = 0; 178 GetRegisteredRawInputDevices(NULL, &raw_devices_count, sizeof(RAWINPUTDEVICE)); 179 ok(raw_devices_count == prev_raw_devices_count, 180 "Unexpected raw devices registered: %d\n", raw_devices_count); 181 182 hr = IDirectInputDevice_Unacquire(pKeyboard); 183 ok(SUCCEEDED(hr), "IDirectInputDevice_Unacquire() failed: %08x\n", hr); 184 185 if (pKeyboard) IUnknown_Release(pKeyboard); 186 187 ActivateKeyboardLayout(hkl_orig, 0); 188 UnloadKeyboardLayout(hkl); 189 } 190 191 static const HRESULT SetCoop_null_window[16] = { 192 E_INVALIDARG, E_INVALIDARG, E_INVALIDARG, E_INVALIDARG, 193 E_INVALIDARG, E_HANDLE, E_HANDLE, E_INVALIDARG, 194 E_INVALIDARG, E_HANDLE, S_OK, E_INVALIDARG, 195 E_INVALIDARG, E_INVALIDARG, E_INVALIDARG, E_INVALIDARG}; 196 197 static const HRESULT SetCoop_invalid_window[16] = { 198 E_INVALIDARG, E_INVALIDARG, E_INVALIDARG, E_INVALIDARG, 199 E_INVALIDARG, E_HANDLE, E_HANDLE, E_INVALIDARG, 200 E_INVALIDARG, E_HANDLE, E_HANDLE, E_INVALIDARG, 201 E_INVALIDARG, E_INVALIDARG, E_INVALIDARG, E_INVALIDARG}; 202 203 static const HRESULT SetCoop_real_window[16] = { 204 E_INVALIDARG, E_INVALIDARG, E_INVALIDARG, E_INVALIDARG, 205 E_INVALIDARG, S_OK, S_OK, E_INVALIDARG, 206 E_INVALIDARG, E_NOTIMPL, S_OK, E_INVALIDARG, 207 E_INVALIDARG, E_INVALIDARG, E_INVALIDARG, E_INVALIDARG}; 208 209 static const HRESULT SetCoop_child_window[16] = { 210 E_INVALIDARG, E_INVALIDARG, E_INVALIDARG, E_INVALIDARG, 211 E_INVALIDARG, E_HANDLE, E_HANDLE, E_INVALIDARG, 212 E_INVALIDARG, E_HANDLE, E_HANDLE, E_INVALIDARG, 213 E_INVALIDARG, E_INVALIDARG, E_INVALIDARG, E_INVALIDARG}; 214 215 static void test_set_coop(IDirectInputA *pDI, HWND hwnd) 216 { 217 HRESULT hr; 218 IDirectInputDeviceA *pKeyboard = NULL; 219 int i; 220 HWND child; 221 222 hr = IDirectInput_CreateDevice(pDI, &GUID_SysKeyboard, &pKeyboard, NULL); 223 ok(SUCCEEDED(hr), "IDirectInput_CreateDevice() failed: %08x\n", hr); 224 if (FAILED(hr)) return; 225 226 for (i=0; i<16; i++) 227 { 228 hr = IDirectInputDevice_SetCooperativeLevel(pKeyboard, NULL, i); 229 ok(hr == SetCoop_null_window[i], "SetCooperativeLevel(NULL, %d): %08x\n", i, hr); 230 } 231 for (i=0; i<16; i++) 232 { 233 hr = IDirectInputDevice_SetCooperativeLevel(pKeyboard, (HWND)0x400000, i); 234 ok(hr == SetCoop_invalid_window[i], "SetCooperativeLevel(invalid, %d): %08x\n", i, hr); 235 } 236 for (i=0; i<16; i++) 237 { 238 hr = IDirectInputDevice_SetCooperativeLevel(pKeyboard, hwnd, i); 239 ok(hr == SetCoop_real_window[i], "SetCooperativeLevel(hwnd, %d): %08x\n", i, hr); 240 } 241 242 child = CreateWindowA("static", "Title", WS_CHILD | WS_VISIBLE, 10, 10, 50, 50, hwnd, NULL, 243 NULL, NULL); 244 ok(child != NULL, "err: %d\n", GetLastError()); 245 246 for (i=0; i<16; i++) 247 { 248 hr = IDirectInputDevice_SetCooperativeLevel(pKeyboard, child, i); 249 ok(hr == SetCoop_child_window[i], "SetCooperativeLevel(child, %d): %08x\n", i, hr); 250 } 251 252 DestroyWindow(child); 253 if (pKeyboard) IUnknown_Release(pKeyboard); 254 } 255 256 static void test_get_prop(IDirectInputA *pDI, HWND hwnd) 257 { 258 HRESULT hr; 259 IDirectInputDeviceA *pKeyboard = NULL; 260 DIPROPRANGE diprg; 261 262 hr = IDirectInput_CreateDevice(pDI, &GUID_SysKeyboard, &pKeyboard, NULL); 263 ok(SUCCEEDED(hr), "IDirectInput_CreateDevice() failed: %08x\n", hr); 264 if (FAILED(hr)) return; 265 266 memset(&diprg, 0, sizeof(diprg)); 267 diprg.diph.dwSize = sizeof(DIPROPRANGE); 268 diprg.diph.dwHeaderSize = sizeof(DIPROPHEADER); 269 diprg.diph.dwHow = DIPH_DEVICE; 270 diprg.diph.dwObj = 0; 271 272 hr = IDirectInputDevice_GetProperty(pKeyboard, DIPROP_RANGE, &diprg.diph); 273 ok(hr == DIERR_UNSUPPORTED, "IDirectInputDevice_GetProperty() did not return DIPROP_RANGE but: %08x\n", hr); 274 275 if (pKeyboard) IUnknown_Release(pKeyboard); 276 } 277 278 static void test_capabilities(IDirectInputA *pDI, HWND hwnd) 279 { 280 HRESULT hr; 281 IDirectInputDeviceA *pKeyboard = NULL; 282 DIDEVCAPS caps; 283 int kbd_type, kbd_subtype, dev_subtype; 284 285 hr = IDirectInput_CreateDevice(pDI, &GUID_SysKeyboard, &pKeyboard, NULL); 286 ok(SUCCEEDED(hr), "IDirectInput_CreateDevice() failed: %08x\n", hr); 287 if (FAILED(hr)) return; 288 289 caps.dwSize = sizeof(caps); 290 hr = IDirectInputDevice_GetCapabilities(pKeyboard, &caps); 291 292 ok (SUCCEEDED(hr), "GetCapabilities failed: 0x%08x\n", hr); 293 ok (caps.dwFlags & DIDC_ATTACHED, "GetCapabilities dwFlags: 0x%08x\n", caps.dwFlags); 294 ok (GET_DIDEVICE_TYPE(caps.dwDevType) == DIDEVTYPE_KEYBOARD, 295 "GetCapabilities invalid device type for dwDevType: 0x%08x\n", caps.dwDevType); 296 kbd_type = GetKeyboardType(0); 297 kbd_subtype = GetKeyboardType(1); 298 dev_subtype = GET_DIDEVICE_SUBTYPE(caps.dwDevType); 299 if (kbd_type == 4 || (kbd_type == 7 && kbd_subtype == 0)) 300 ok (dev_subtype == DIDEVTYPEKEYBOARD_PCENH, 301 "GetCapabilities invalid device subtype for dwDevType: 0x%08x (%04x:%04x)\n", 302 caps.dwDevType, kbd_type, kbd_subtype); 303 else if (kbd_type == 7 && kbd_subtype == 2) 304 ok (dev_subtype == DIDEVTYPEKEYBOARD_JAPAN106, 305 "GetCapabilities invalid device subtype for dwDevType: 0x%08x (%04x:%04x)\n", 306 caps.dwDevType, kbd_type, kbd_subtype); 307 else 308 ok (dev_subtype != DIDEVTYPEKEYBOARD_UNKNOWN, 309 "GetCapabilities invalid device subtype for dwDevType: 0x%08x (%04x:%04x)\n", 310 caps.dwDevType, kbd_type, kbd_subtype); 311 312 IUnknown_Release(pKeyboard); 313 } 314 315 static void test_dik_codes(IDirectInputA *dI, HWND hwnd, LANGID langid) 316 { 317 static const struct key2dik 318 { 319 BYTE key, dik, todo; 320 } key2dik_en[] = 321 { 322 {'Q',DIK_Q}, {'W',DIK_W}, {'E',DIK_E}, {'R',DIK_R}, {'T',DIK_T}, {'Y',DIK_Y}, 323 {'[',DIK_LBRACKET}, {']',DIK_RBRACKET}, {'.',DIK_PERIOD} 324 }, 325 key2dik_fr[] = 326 { 327 {'A',DIK_Q}, {'Z',DIK_W}, {'E',DIK_E}, {'R',DIK_R}, {'T',DIK_T}, {'Y',DIK_Y}, 328 {'^',DIK_LBRACKET}, {'$',DIK_RBRACKET}, {':',DIK_PERIOD} 329 }, 330 key2dik_de[] = 331 { 332 {'Q',DIK_Q}, {'W',DIK_W}, {'E',DIK_E}, {'R',DIK_R}, {'T',DIK_T}, {'Z',DIK_Y}, 333 {'\xfc',DIK_LBRACKET,1}, {'+',DIK_RBRACKET}, {'.',DIK_PERIOD} 334 }, 335 key2dik_ja[] = 336 { 337 {'Q',DIK_Q}, {'W',DIK_W}, {'E',DIK_E}, {'R',DIK_R}, {'T',DIK_T}, {'Y',DIK_Y}, 338 {'@',DIK_AT}, {']',DIK_RBRACKET}, {'.',DIK_PERIOD} 339 }; 340 static const struct 341 { 342 LANGID langid; 343 const struct key2dik *map; 344 DWORD type; 345 } expected[] = 346 { 347 { MAKELANGID(LANG_ENGLISH, SUBLANG_DEFAULT), 348 key2dik_en, DIDEVTYPEKEYBOARD_PCENH }, 349 { MAKELANGID(LANG_FRENCH, SUBLANG_FRENCH), 350 key2dik_fr, DIDEVTYPEKEYBOARD_PCENH }, 351 { MAKELANGID(LANG_GERMAN, SUBLANG_GERMAN), 352 key2dik_de, DIDEVTYPEKEYBOARD_PCENH }, 353 { MAKELANGID(LANG_JAPANESE, SUBLANG_JAPANESE_JAPAN), 354 key2dik_ja, DIDEVTYPEKEYBOARD_JAPAN106 } 355 }; 356 const struct key2dik *map = NULL; 357 UINT i; 358 HRESULT hr; 359 IDirectInputDeviceA *device; 360 DIDEVCAPS caps; 361 HKL hkl, hkl_orig; 362 MSG msg; 363 364 for (i = 0; i < ARRAY_SIZE(expected); i++) 365 { 366 if (expected[i].langid == langid) 367 { 368 map = expected[i].map; 369 break; 370 } 371 } 372 ok(map != NULL, "can't find mapping for langid %04x\n", langid); 373 if (!map) return; 374 375 hr = IDirectInput_CreateDevice(dI, &GUID_SysKeyboard, &device, NULL); 376 ok(hr == S_OK, "CreateDevice() failed: %08x\n", hr); 377 hr = IDirectInputDevice_SetDataFormat(device, &c_dfDIKeyboard); 378 ok(hr == S_OK, "SetDataFormat() failed: %08x\n", hr); 379 hr = IDirectInputDevice_Acquire(device); 380 ok(hr == S_OK, "Acquire() failed: %08x\n", hr); 381 caps.dwSize = sizeof( caps ); 382 hr = IDirectInputDevice_GetCapabilities(device, &caps); 383 ok(hr == S_OK, "GetDeviceInstance() failed: %08x\n", hr); 384 if (expected[i].type != GET_DIDEVICE_SUBTYPE(caps.dwDevType)) { 385 skip("Keyboard type(%u) doesn't match for lang %04x\n", 386 GET_DIDEVICE_SUBTYPE(caps.dwDevType), langid); 387 goto fail; 388 } 389 390 hkl = activate_keyboard_layout(langid, &hkl_orig); 391 if (!hkl) goto fail; 392 393 SetFocus(hwnd); 394 pump_messages(); 395 396 for (i = 0; i < ARRAY_SIZE(key2dik_en); i++) 397 { 398 BYTE kbd_state[256]; 399 UINT n; 400 WORD vkey, scan; 401 INPUT in; 402 403 n = VkKeyScanExW(map[i].key, hkl); 404 todo_wine_if(map[i].todo & 1) 405 ok(n != 0xffff, "%u: failed to get virtual key value for %c(%02x)\n", i, map[i].key, map[i].key); 406 vkey = LOBYTE(n); 407 n = MapVirtualKeyExA(vkey, MAPVK_VK_TO_CHAR, hkl) & 0xff; 408 todo_wine_if(map[i].todo & 1) 409 ok(n == map[i].key, "%u: expected %c(%02x), got %c(%02x)\n", i, map[i].key, map[i].key, n, n); 410 scan = MapVirtualKeyExA(vkey, MAPVK_VK_TO_VSC, hkl); 411 /* scan codes match the DIK_ codes on US keyboard. 412 however, it isn't true for symbols and punctuations in other layouts. */ 413 if (isalpha(map[i].key) || langid == MAKELANGID(LANG_ENGLISH, SUBLANG_DEFAULT)) 414 ok(scan == map[i].dik, "%u: expected %02x, got %02x\n", i, map[i].dik, n); 415 else 416 todo_wine_if(map[i].todo & 1) 417 ok(scan, "%u: fail to get scan code value, expected %02x (vkey=%02x)\n", 418 i, map[i].dik, vkey); 419 420 in.type = INPUT_KEYBOARD; 421 U(in).ki.wVk = vkey; 422 U(in).ki.wScan = scan; 423 U(in).ki.dwFlags = 0; 424 U(in).ki.dwExtraInfo = 0; 425 U(in).ki.time = 0; 426 n = SendInput(1, &in, sizeof(in)); 427 ok(n == 1, "got %u\n", n); 428 429 if (!PeekMessageA(&msg, hwnd, 0, 0, PM_REMOVE)) 430 { 431 U(in).ki.dwFlags = KEYEVENTF_KEYUP; 432 SendInput(1, &in, sizeof(in)); 433 win_skip("failed to queue keyboard event\n"); 434 break; 435 } 436 ok(msg.message == WM_KEYDOWN, "expected WM_KEYDOWN, got %04x\n", msg.message); 437 DispatchMessageA(&msg); 438 439 n = MapVirtualKeyExA(msg.wParam, MAPVK_VK_TO_CHAR, hkl); 440 trace("keydown wParam: %#08lx (%c) lParam: %#08lx, MapVirtualKey(MAPVK_VK_TO_CHAR) = %c\n", 441 msg.wParam, isprint(LOWORD(msg.wParam)) ? LOWORD(msg.wParam) : '?', 442 msg.lParam, isprint(n) ? n : '?'); 443 444 pump_messages(); 445 446 hr = IDirectInputDevice_GetDeviceState(device, sizeof(kbd_state), kbd_state); 447 ok(hr == S_OK, "GetDeviceState() failed: %08x\n", hr); 448 449 /* this never happens on real hardware but tesbot VMs seem to have timing issues */ 450 if (i == 0 && kbd_state[map[0].dik] != 0x80) 451 { 452 win_skip("dinput failed to handle keyboard event\n"); 453 break; 454 } 455 456 todo_wine_if(map[i].todo) 457 ok(kbd_state[map[i].dik] == 0x80, "DI key %#x has state %#x\n", map[i].dik, kbd_state[map[i].dik]); 458 459 U(in).ki.dwFlags = KEYEVENTF_KEYUP; 460 n = SendInput(1, &in, sizeof(in)); 461 ok(n == 1, "got %u\n", n); 462 463 pump_messages(); 464 } 465 466 ActivateKeyboardLayout(hkl_orig, 0); 467 UnloadKeyboardLayout(hkl); 468 fail: 469 IDirectInputDevice_Unacquire(device); 470 IUnknown_Release(device); 471 } 472 473 static void test_GetDeviceInfo(IDirectInputA *pDI) 474 { 475 HRESULT hr; 476 IDirectInputDeviceA *pKey = NULL; 477 DIDEVICEINSTANCEA instA; 478 DIDEVICEINSTANCE_DX3A inst3A; 479 480 hr = IDirectInput_CreateDevice(pDI, &GUID_SysKeyboard, &pKey, NULL); 481 ok(SUCCEEDED(hr), "IDirectInput_CreateDevice() failed: %08x\n", hr); 482 if (FAILED(hr)) return; 483 484 instA.dwSize = sizeof(instA); 485 hr = IDirectInputDevice_GetDeviceInfo(pKey, &instA); 486 ok(SUCCEEDED(hr), "got %08x\n", hr); 487 488 inst3A.dwSize = sizeof(inst3A); 489 hr = IDirectInputDevice_GetDeviceInfo(pKey, (DIDEVICEINSTANCEA *)&inst3A); 490 ok(SUCCEEDED(hr), "got %08x\n", hr); 491 492 ok(instA.dwSize != inst3A.dwSize, "got %d, %d \n", instA.dwSize, inst3A.dwSize); 493 ok(IsEqualGUID(&instA.guidInstance, &inst3A.guidInstance), "got %s, %s\n", 494 wine_dbgstr_guid(&instA.guidInstance), wine_dbgstr_guid(&inst3A.guidInstance) ); 495 ok(IsEqualGUID(&instA.guidProduct, &inst3A.guidProduct), "got %s, %s\n", 496 wine_dbgstr_guid(&instA.guidProduct), wine_dbgstr_guid(&inst3A.guidProduct) ); 497 ok(instA.dwDevType == inst3A.dwDevType, "got %d, %d\n", instA.dwDevType, inst3A.dwDevType); 498 499 IUnknown_Release(pKey); 500 } 501 502 static void keyboard_tests(DWORD version) 503 { 504 HRESULT hr; 505 IDirectInputA *pDI = NULL; 506 HINSTANCE hInstance = GetModuleHandleW(NULL); 507 HWND hwnd; 508 ULONG ref = 0; 509 510 hr = pDirectInputCreateA(hInstance, version, &pDI, NULL); 511 if (hr == DIERR_OLDDIRECTINPUTVERSION) 512 { 513 skip("Tests require a newer dinput version\n"); 514 return; 515 } 516 ok(SUCCEEDED(hr), "DirectInputCreateA() failed: %08x\n", hr); 517 if (FAILED(hr)) return; 518 519 hwnd = CreateWindowA("static", "Title", WS_OVERLAPPEDWINDOW | WS_VISIBLE, 10, 10, 200, 200, 520 NULL, NULL, NULL, NULL); 521 ok(hwnd != NULL, "err: %d\n", GetLastError()); 522 SetForegroundWindow( hwnd ); 523 524 if (hwnd) 525 { 526 pump_messages(); 527 528 acquire_tests(pDI, hwnd); 529 test_set_coop(pDI, hwnd); 530 test_get_prop(pDI, hwnd); 531 test_capabilities(pDI, hwnd); 532 test_GetDeviceInfo(pDI); 533 534 test_dik_codes(pDI, hwnd, MAKELANGID(LANG_ENGLISH, SUBLANG_DEFAULT)); 535 test_dik_codes(pDI, hwnd, MAKELANGID(LANG_FRENCH, SUBLANG_FRENCH)); 536 test_dik_codes(pDI, hwnd, MAKELANGID(LANG_GERMAN, SUBLANG_GERMAN)); 537 test_dik_codes(pDI, hwnd, MAKELANGID(LANG_JAPANESE, SUBLANG_JAPANESE_JAPAN)); 538 } 539 540 DestroyWindow(hwnd); 541 if (pDI) ref = IUnknown_Release(pDI); 542 ok(!ref, "IDirectInput_Release() reference count = %d\n", ref); 543 } 544 545 START_TEST(keyboard) 546 { 547 pDirectInputCreateA = (void *)GetProcAddress(GetModuleHandleA("dinput.dll"), "DirectInputCreateA"); 548 549 CoInitialize(NULL); 550 551 keyboard_tests(0x0700); 552 553 CoUninitialize(); 554 } 555