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 97 hkl = activate_keyboard_layout(MAKELANGID(LANG_ENGLISH, SUBLANG_DEFAULT), &hkl_orig); 98 if (!hkl) return; 99 100 df.dwSize = sizeof( df ); 101 df.dwObjSize = sizeof( DIOBJECTDATAFORMAT ); 102 df.dwFlags = DIDF_RELAXIS; 103 df.dwDataSize = sizeof( custom_state ); 104 df.dwNumObjs = ARRAY_SIZE(dodf); 105 df.rgodf = dodf; 106 107 hr = IDirectInput_CreateDevice(pDI, &GUID_SysKeyboard, &pKeyboard, NULL); 108 ok(SUCCEEDED(hr), "IDirectInput_CreateDevice() failed: %08x\n", hr); 109 if (FAILED(hr)) return; 110 111 hr = IDirectInputDevice_SetDataFormat(pKeyboard, &c_dfDIKeyboard); 112 ok(SUCCEEDED(hr), "IDirectInputDevice_SetDataFormat() failed: %08x\n", hr); 113 hr = IDirectInputDevice_SetCooperativeLevel(pKeyboard, NULL, DISCL_NONEXCLUSIVE | DISCL_BACKGROUND); 114 ok(SUCCEEDED(hr), "IDirectInputDevice_SetCooperativeLevel() failed: %08x\n", hr); 115 hr = IDirectInputDevice_GetDeviceState(pKeyboard, 10, kbd_state); 116 ok(hr == DIERR_NOTACQUIRED, "IDirectInputDevice_GetDeviceState(10,) should have failed: %08x\n", hr); 117 hr = IDirectInputDevice_GetDeviceState(pKeyboard, sizeof(kbd_state), kbd_state); 118 ok(hr == DIERR_NOTACQUIRED, "IDirectInputDevice_GetDeviceState() should have failed: %08x\n", hr); 119 hr = IDirectInputDevice_Unacquire(pKeyboard); 120 ok(hr == S_FALSE, "IDirectInputDevice_Unacquire() should have failed: %08x\n", hr); 121 hr = IDirectInputDevice_Acquire(pKeyboard); 122 ok(SUCCEEDED(hr), "IDirectInputDevice_Acquire() failed: %08x\n", hr); 123 hr = IDirectInputDevice_Acquire(pKeyboard); 124 ok(hr == S_FALSE, "IDirectInputDevice_Acquire() should have failed: %08x\n", hr); 125 hr = IDirectInputDevice_GetDeviceState(pKeyboard, 10, kbd_state); 126 ok(hr == DIERR_INVALIDPARAM, "IDirectInputDevice_GetDeviceState(10,) should have failed: %08x\n", hr); 127 hr = IDirectInputDevice_GetDeviceState(pKeyboard, sizeof(kbd_state), kbd_state); 128 ok(SUCCEEDED(hr), "IDirectInputDevice_GetDeviceState() failed: %08x\n", hr); 129 hr = IDirectInputDevice_Unacquire(pKeyboard); 130 ok(SUCCEEDED(hr), "IDirectInputDevice_Uncquire() failed: %08x\n", hr); 131 hr = IDirectInputDevice_SetDataFormat( pKeyboard , &df ); 132 ok(SUCCEEDED(hr), "IDirectInputDevice_SetDataFormat() failed: %08x\n", hr); 133 hr = IDirectInputDevice_Acquire(pKeyboard); 134 ok(SUCCEEDED(hr), "IDirectInputDevice_Acquire() failed: %08x\n", hr); 135 hr = IDirectInputDevice_GetDeviceState(pKeyboard, sizeof(custom_state), custom_state); 136 ok(SUCCEEDED(hr), "IDirectInputDevice_GetDeviceState(4,) failed: %08x\n", hr); 137 hr = IDirectInputDevice_GetDeviceState(pKeyboard, sizeof(kbd_state), kbd_state); 138 ok(hr == DIERR_INVALIDPARAM, "IDirectInputDevice_GetDeviceState(256,) should have failed: %08x\n", hr); 139 140 memset(custom_state, 0x56, sizeof(custom_state)); 141 IDirectInputDevice_GetDeviceState(pKeyboard, sizeof(custom_state), custom_state); 142 for (i = 0; i < ARRAY_SIZE(custom_state); i++) 143 ok(custom_state[i] == 0, "Should be zeroed, got 0x%08x\n", custom_state[i]); 144 145 /* simulate some keyboard input */ 146 SetFocus(hwnd); 147 pump_messages(); 148 149 keybd_event('Q', 0, 0, 0); 150 hr = IDirectInputDevice_GetDeviceState(pKeyboard, sizeof(custom_state), custom_state); 151 ok(SUCCEEDED(hr), "IDirectInputDevice_GetDeviceState() failed: %08x\n", hr); 152 if (!custom_state[0]) 153 win_skip("Keyboard event not processed, skipping test\n"); 154 else 155 { 156 /* unacquiring should reset the device state */ 157 hr = IDirectInputDevice_Unacquire(pKeyboard); 158 ok(SUCCEEDED(hr), "IDirectInputDevice_Unacquire() failed: %08x\n", hr); 159 hr = IDirectInputDevice_Acquire(pKeyboard); 160 ok(SUCCEEDED(hr), "IDirectInputDevice_Acquire() failed: %08x\n", hr); 161 hr = IDirectInputDevice_GetDeviceState(pKeyboard, sizeof(custom_state), custom_state); 162 ok(SUCCEEDED(hr), "IDirectInputDevice_GetDeviceState failed: %08x\n", hr); 163 for (i = 0; i < ARRAY_SIZE(custom_state); i++) 164 ok(custom_state[i] == 0, "Should be zeroed, got 0x%08x\n", custom_state[i]); 165 } 166 keybd_event('Q', 0, KEYEVENTF_KEYUP, 0); 167 168 if (pKeyboard) IUnknown_Release(pKeyboard); 169 170 ActivateKeyboardLayout(hkl_orig, 0); 171 UnloadKeyboardLayout(hkl); 172 } 173 174 static const HRESULT SetCoop_null_window[16] = { 175 E_INVALIDARG, E_INVALIDARG, E_INVALIDARG, E_INVALIDARG, 176 E_INVALIDARG, E_HANDLE, E_HANDLE, E_INVALIDARG, 177 E_INVALIDARG, E_HANDLE, S_OK, E_INVALIDARG, 178 E_INVALIDARG, E_INVALIDARG, E_INVALIDARG, E_INVALIDARG}; 179 180 static const HRESULT SetCoop_invalid_window[16] = { 181 E_INVALIDARG, E_INVALIDARG, E_INVALIDARG, E_INVALIDARG, 182 E_INVALIDARG, E_HANDLE, E_HANDLE, E_INVALIDARG, 183 E_INVALIDARG, E_HANDLE, E_HANDLE, E_INVALIDARG, 184 E_INVALIDARG, E_INVALIDARG, E_INVALIDARG, E_INVALIDARG}; 185 186 static const HRESULT SetCoop_real_window[16] = { 187 E_INVALIDARG, E_INVALIDARG, E_INVALIDARG, E_INVALIDARG, 188 E_INVALIDARG, S_OK, S_OK, E_INVALIDARG, 189 E_INVALIDARG, E_NOTIMPL, S_OK, E_INVALIDARG, 190 E_INVALIDARG, E_INVALIDARG, E_INVALIDARG, E_INVALIDARG}; 191 192 static const HRESULT SetCoop_child_window[16] = { 193 E_INVALIDARG, E_INVALIDARG, E_INVALIDARG, E_INVALIDARG, 194 E_INVALIDARG, E_HANDLE, E_HANDLE, E_INVALIDARG, 195 E_INVALIDARG, E_HANDLE, E_HANDLE, E_INVALIDARG, 196 E_INVALIDARG, E_INVALIDARG, E_INVALIDARG, E_INVALIDARG}; 197 198 static void test_set_coop(IDirectInputA *pDI, HWND hwnd) 199 { 200 HRESULT hr; 201 IDirectInputDeviceA *pKeyboard = NULL; 202 int i; 203 HWND child; 204 205 hr = IDirectInput_CreateDevice(pDI, &GUID_SysKeyboard, &pKeyboard, NULL); 206 ok(SUCCEEDED(hr), "IDirectInput_CreateDevice() failed: %08x\n", hr); 207 if (FAILED(hr)) return; 208 209 for (i=0; i<16; i++) 210 { 211 hr = IDirectInputDevice_SetCooperativeLevel(pKeyboard, NULL, i); 212 ok(hr == SetCoop_null_window[i], "SetCooperativeLevel(NULL, %d): %08x\n", i, hr); 213 } 214 for (i=0; i<16; i++) 215 { 216 hr = IDirectInputDevice_SetCooperativeLevel(pKeyboard, (HWND)0x400000, i); 217 ok(hr == SetCoop_invalid_window[i], "SetCooperativeLevel(invalid, %d): %08x\n", i, hr); 218 } 219 for (i=0; i<16; i++) 220 { 221 hr = IDirectInputDevice_SetCooperativeLevel(pKeyboard, hwnd, i); 222 ok(hr == SetCoop_real_window[i], "SetCooperativeLevel(hwnd, %d): %08x\n", i, hr); 223 } 224 225 child = CreateWindowA("static", "Title", WS_CHILD | WS_VISIBLE, 10, 10, 50, 50, hwnd, NULL, 226 NULL, NULL); 227 ok(child != NULL, "err: %d\n", GetLastError()); 228 229 for (i=0; i<16; i++) 230 { 231 hr = IDirectInputDevice_SetCooperativeLevel(pKeyboard, child, i); 232 ok(hr == SetCoop_child_window[i], "SetCooperativeLevel(child, %d): %08x\n", i, hr); 233 } 234 235 DestroyWindow(child); 236 if (pKeyboard) IUnknown_Release(pKeyboard); 237 } 238 239 static void test_get_prop(IDirectInputA *pDI, HWND hwnd) 240 { 241 HRESULT hr; 242 IDirectInputDeviceA *pKeyboard = NULL; 243 DIPROPRANGE diprg; 244 245 hr = IDirectInput_CreateDevice(pDI, &GUID_SysKeyboard, &pKeyboard, NULL); 246 ok(SUCCEEDED(hr), "IDirectInput_CreateDevice() failed: %08x\n", hr); 247 if (FAILED(hr)) return; 248 249 memset(&diprg, 0, sizeof(diprg)); 250 diprg.diph.dwSize = sizeof(DIPROPRANGE); 251 diprg.diph.dwHeaderSize = sizeof(DIPROPHEADER); 252 diprg.diph.dwHow = DIPH_DEVICE; 253 diprg.diph.dwObj = 0; 254 255 hr = IDirectInputDevice_GetProperty(pKeyboard, DIPROP_RANGE, &diprg.diph); 256 ok(hr == DIERR_UNSUPPORTED, "IDirectInputDevice_GetProperty() did not return DIPROP_RANGE but: %08x\n", hr); 257 258 if (pKeyboard) IUnknown_Release(pKeyboard); 259 } 260 261 static void test_capabilities(IDirectInputA *pDI, HWND hwnd) 262 { 263 HRESULT hr; 264 IDirectInputDeviceA *pKeyboard = NULL; 265 DIDEVCAPS caps; 266 int kbd_type, kbd_subtype, dev_subtype; 267 268 hr = IDirectInput_CreateDevice(pDI, &GUID_SysKeyboard, &pKeyboard, NULL); 269 ok(SUCCEEDED(hr), "IDirectInput_CreateDevice() failed: %08x\n", hr); 270 if (FAILED(hr)) return; 271 272 caps.dwSize = sizeof(caps); 273 hr = IDirectInputDevice_GetCapabilities(pKeyboard, &caps); 274 275 ok (SUCCEEDED(hr), "GetCapabilities failed: 0x%08x\n", hr); 276 ok (caps.dwFlags & DIDC_ATTACHED, "GetCapabilities dwFlags: 0x%08x\n", caps.dwFlags); 277 ok (GET_DIDEVICE_TYPE(caps.dwDevType) == DIDEVTYPE_KEYBOARD, 278 "GetCapabilities invalid device type for dwDevType: 0x%08x\n", caps.dwDevType); 279 kbd_type = GetKeyboardType(0); 280 kbd_subtype = GetKeyboardType(1); 281 dev_subtype = GET_DIDEVICE_SUBTYPE(caps.dwDevType); 282 if (kbd_type == 4 || (kbd_type == 7 && kbd_subtype == 0)) 283 ok (dev_subtype == DIDEVTYPEKEYBOARD_PCENH, 284 "GetCapabilities invalid device subtype for dwDevType: 0x%08x (%04x:%04x)\n", 285 caps.dwDevType, kbd_type, kbd_subtype); 286 else if (kbd_type == 7 && kbd_subtype == 2) 287 ok (dev_subtype == DIDEVTYPEKEYBOARD_JAPAN106, 288 "GetCapabilities invalid device subtype for dwDevType: 0x%08x (%04x:%04x)\n", 289 caps.dwDevType, kbd_type, kbd_subtype); 290 else 291 ok (dev_subtype != DIDEVTYPEKEYBOARD_UNKNOWN, 292 "GetCapabilities invalid device subtype for dwDevType: 0x%08x (%04x:%04x)\n", 293 caps.dwDevType, kbd_type, kbd_subtype); 294 295 IUnknown_Release(pKeyboard); 296 } 297 298 static void test_dik_codes(IDirectInputA *dI, HWND hwnd, LANGID langid) 299 { 300 static const struct key2dik 301 { 302 BYTE key, dik, todo; 303 } key2dik_en[] = 304 { 305 {'Q',DIK_Q}, {'W',DIK_W}, {'E',DIK_E}, {'R',DIK_R}, {'T',DIK_T}, {'Y',DIK_Y}, 306 {'[',DIK_LBRACKET}, {']',DIK_RBRACKET}, {'.',DIK_PERIOD} 307 }, 308 key2dik_fr[] = 309 { 310 {'A',DIK_Q}, {'Z',DIK_W}, {'E',DIK_E}, {'R',DIK_R}, {'T',DIK_T}, {'Y',DIK_Y}, 311 {'^',DIK_LBRACKET}, {'$',DIK_RBRACKET}, {':',DIK_PERIOD} 312 }, 313 key2dik_de[] = 314 { 315 {'Q',DIK_Q}, {'W',DIK_W}, {'E',DIK_E}, {'R',DIK_R}, {'T',DIK_T}, {'Z',DIK_Y}, 316 {'\xfc',DIK_LBRACKET,1}, {'+',DIK_RBRACKET}, {'.',DIK_PERIOD} 317 }, 318 key2dik_ja[] = 319 { 320 {'Q',DIK_Q}, {'W',DIK_W}, {'E',DIK_E}, {'R',DIK_R}, {'T',DIK_T}, {'Y',DIK_Y}, 321 {'@',DIK_AT}, {']',DIK_RBRACKET}, {'.',DIK_PERIOD} 322 }; 323 static const struct 324 { 325 LANGID langid; 326 const struct key2dik *map; 327 DWORD type; 328 } expected[] = 329 { 330 { MAKELANGID(LANG_ENGLISH, SUBLANG_DEFAULT), 331 key2dik_en, DIDEVTYPEKEYBOARD_PCENH }, 332 { MAKELANGID(LANG_FRENCH, SUBLANG_FRENCH), 333 key2dik_fr, DIDEVTYPEKEYBOARD_PCENH }, 334 { MAKELANGID(LANG_GERMAN, SUBLANG_GERMAN), 335 key2dik_de, DIDEVTYPEKEYBOARD_PCENH }, 336 { MAKELANGID(LANG_JAPANESE, SUBLANG_JAPANESE_JAPAN), 337 key2dik_ja, DIDEVTYPEKEYBOARD_JAPAN106 } 338 }; 339 const struct key2dik *map = NULL; 340 UINT i; 341 HRESULT hr; 342 IDirectInputDeviceA *device; 343 DIDEVCAPS caps; 344 HKL hkl, hkl_orig; 345 MSG msg; 346 347 for (i = 0; i < ARRAY_SIZE(expected); i++) 348 { 349 if (expected[i].langid == langid) 350 { 351 map = expected[i].map; 352 break; 353 } 354 } 355 ok(map != NULL, "can't find mapping for langid %04x\n", langid); 356 if (!map) return; 357 358 hr = IDirectInput_CreateDevice(dI, &GUID_SysKeyboard, &device, NULL); 359 ok(hr == S_OK, "CreateDevice() failed: %08x\n", hr); 360 hr = IDirectInputDevice_SetDataFormat(device, &c_dfDIKeyboard); 361 ok(hr == S_OK, "SetDataFormat() failed: %08x\n", hr); 362 hr = IDirectInputDevice_Acquire(device); 363 ok(hr == S_OK, "Acquire() failed: %08x\n", hr); 364 caps.dwSize = sizeof( caps ); 365 hr = IDirectInputDevice_GetCapabilities(device, &caps); 366 ok(hr == S_OK, "GetDeviceInstance() failed: %08x\n", hr); 367 if (expected[i].type != GET_DIDEVICE_SUBTYPE(caps.dwDevType)) { 368 skip("Keyboard type(%u) doesn't match for lang %04x\n", 369 GET_DIDEVICE_SUBTYPE(caps.dwDevType), langid); 370 goto fail; 371 } 372 373 hkl = activate_keyboard_layout(langid, &hkl_orig); 374 if (!hkl) goto fail; 375 376 SetFocus(hwnd); 377 pump_messages(); 378 379 for (i = 0; i < ARRAY_SIZE(key2dik_en); i++) 380 { 381 BYTE kbd_state[256]; 382 UINT n; 383 WORD vkey, scan; 384 INPUT in; 385 386 n = VkKeyScanExW(map[i].key, hkl); 387 todo_wine_if(map[i].todo & 1) 388 ok(n != 0xffff, "%u: failed to get virtual key value for %c(%02x)\n", i, map[i].key, map[i].key); 389 vkey = LOBYTE(n); 390 n = MapVirtualKeyExA(vkey, MAPVK_VK_TO_CHAR, hkl) & 0xff; 391 todo_wine_if(map[i].todo & 1) 392 ok(n == map[i].key, "%u: expected %c(%02x), got %c(%02x)\n", i, map[i].key, map[i].key, n, n); 393 scan = MapVirtualKeyExA(vkey, MAPVK_VK_TO_VSC, hkl); 394 /* scan codes match the DIK_ codes on US keyboard. 395 however, it isn't true for symbols and punctuations in other layouts. */ 396 if (isalpha(map[i].key) || langid == MAKELANGID(LANG_ENGLISH, SUBLANG_DEFAULT)) 397 ok(scan == map[i].dik, "%u: expected %02x, got %02x\n", i, map[i].dik, n); 398 else 399 todo_wine_if(map[i].todo & 1) 400 ok(scan, "%u: fail to get scan code value, expected %02x (vkey=%02x)\n", 401 i, map[i].dik, vkey); 402 403 in.type = INPUT_KEYBOARD; 404 U(in).ki.wVk = vkey; 405 U(in).ki.wScan = scan; 406 U(in).ki.dwFlags = 0; 407 U(in).ki.dwExtraInfo = 0; 408 U(in).ki.time = 0; 409 n = SendInput(1, &in, sizeof(in)); 410 ok(n == 1, "got %u\n", n); 411 412 if (!PeekMessageA(&msg, hwnd, 0, 0, PM_REMOVE)) 413 { 414 U(in).ki.dwFlags = KEYEVENTF_KEYUP; 415 SendInput(1, &in, sizeof(in)); 416 win_skip("failed to queue keyboard event\n"); 417 break; 418 } 419 ok(msg.message == WM_KEYDOWN, "expected WM_KEYDOWN, got %04x\n", msg.message); 420 DispatchMessageA(&msg); 421 422 n = MapVirtualKeyExA(msg.wParam, MAPVK_VK_TO_CHAR, hkl); 423 trace("keydown wParam: %#08lx (%c) lParam: %#08lx, MapVirtualKey(MAPVK_VK_TO_CHAR) = %c\n", 424 msg.wParam, isprint(LOWORD(msg.wParam)) ? LOWORD(msg.wParam) : '?', 425 msg.lParam, isprint(n) ? n : '?'); 426 427 pump_messages(); 428 429 hr = IDirectInputDevice_GetDeviceState(device, sizeof(kbd_state), kbd_state); 430 ok(hr == S_OK, "GetDeviceState() failed: %08x\n", hr); 431 432 /* this never happens on real hardware but tesbot VMs seem to have timing issues */ 433 if (i == 0 && kbd_state[map[0].dik] != 0x80) 434 { 435 win_skip("dinput failed to handle keyboard event\n"); 436 break; 437 } 438 439 todo_wine_if(map[i].todo) 440 ok(kbd_state[map[i].dik] == 0x80, "DI key %#x has state %#x\n", map[i].dik, kbd_state[map[i].dik]); 441 442 U(in).ki.dwFlags = KEYEVENTF_KEYUP; 443 n = SendInput(1, &in, sizeof(in)); 444 ok(n == 1, "got %u\n", n); 445 446 pump_messages(); 447 } 448 449 ActivateKeyboardLayout(hkl_orig, 0); 450 UnloadKeyboardLayout(hkl); 451 fail: 452 IDirectInputDevice_Unacquire(device); 453 IUnknown_Release(device); 454 } 455 456 static void keyboard_tests(DWORD version) 457 { 458 HRESULT hr; 459 IDirectInputA *pDI = NULL; 460 HINSTANCE hInstance = GetModuleHandleW(NULL); 461 HWND hwnd; 462 ULONG ref = 0; 463 464 hr = pDirectInputCreateA(hInstance, version, &pDI, NULL); 465 if (hr == DIERR_OLDDIRECTINPUTVERSION) 466 { 467 skip("Tests require a newer dinput version\n"); 468 return; 469 } 470 ok(SUCCEEDED(hr), "DirectInputCreateA() failed: %08x\n", hr); 471 if (FAILED(hr)) return; 472 473 hwnd = CreateWindowA("static", "Title", WS_OVERLAPPEDWINDOW | WS_VISIBLE, 10, 10, 200, 200, 474 NULL, NULL, NULL, NULL); 475 ok(hwnd != NULL, "err: %d\n", GetLastError()); 476 SetForegroundWindow( hwnd ); 477 478 if (hwnd) 479 { 480 pump_messages(); 481 482 acquire_tests(pDI, hwnd); 483 test_set_coop(pDI, hwnd); 484 test_get_prop(pDI, hwnd); 485 test_capabilities(pDI, hwnd); 486 487 test_dik_codes(pDI, hwnd, MAKELANGID(LANG_ENGLISH, SUBLANG_DEFAULT)); 488 test_dik_codes(pDI, hwnd, MAKELANGID(LANG_FRENCH, SUBLANG_FRENCH)); 489 test_dik_codes(pDI, hwnd, MAKELANGID(LANG_GERMAN, SUBLANG_GERMAN)); 490 test_dik_codes(pDI, hwnd, MAKELANGID(LANG_JAPANESE, SUBLANG_JAPANESE_JAPAN)); 491 } 492 493 DestroyWindow(hwnd); 494 if (pDI) ref = IUnknown_Release(pDI); 495 ok(!ref, "IDirectInput_Release() reference count = %d\n", ref); 496 } 497 498 START_TEST(keyboard) 499 { 500 pDirectInputCreateA = (void *)GetProcAddress(GetModuleHandleA("dinput.dll"), "DirectInputCreateA"); 501 502 CoInitialize(NULL); 503 504 keyboard_tests(0x0700); 505 506 CoUninitialize(); 507 } 508