1 /* 2 * ReactOS kernel 3 * Copyright (C) 1998, 1999, 2000, 2001 ReactOS Team 4 * 5 * This program is free software; you can redistribute it and/or modify 6 * it under the terms of the GNU General Public License as published by 7 * the Free Software Foundation; either version 2 of the License, or 8 * (at your option) any later version. 9 * 10 * This program 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 13 * GNU General Public License for more details. 14 * 15 * You should have received a copy of the GNU General Public License 16 * along with this program; if not, write to the Free Software 17 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 18 */ 19 /* 20 * PROJECT: ReactOS user32.dll 21 * FILE: win32ss/user/user32/windows/input.c 22 * PURPOSE: Input 23 * PROGRAMMER: Casper S. Hornstrup (chorns@users.sourceforge.net) 24 * UPDATE HISTORY: 25 * 09-05-2001 CSH Created 26 */ 27 28 #include <user32.h> 29 30 #include <strsafe.h> 31 32 WINE_DEFAULT_DEBUG_CHANNEL(user32); 33 34 typedef struct tagIMEHOTKEYENTRY 35 { 36 DWORD dwHotKeyId; 37 UINT uVirtualKey; 38 UINT uModifiers; 39 HKL hKL; 40 } IMEHOTKEYENTRY, *PIMEHOTKEYENTRY; 41 42 // Japanese 43 IMEHOTKEYENTRY DefaultHotKeyTableJ[] = 44 { 45 { IME_JHOTKEY_CLOSE_OPEN, VK_KANJI, MOD_IGNORE_ALL_MODIFIER, NULL }, 46 }; 47 48 // Chinese Traditional 49 IMEHOTKEYENTRY DefaultHotKeyTableT[] = 50 { 51 { IME_THOTKEY_IME_NONIME_TOGGLE, VK_SPACE, MOD_LEFT | MOD_RIGHT | MOD_CONTROL, NULL }, 52 { IME_THOTKEY_SHAPE_TOGGLE, VK_SPACE, MOD_LEFT | MOD_RIGHT | MOD_SHIFT, NULL }, 53 }; 54 55 // Chinese Simplified 56 IMEHOTKEYENTRY DefaultHotKeyTableC[] = 57 { 58 { IME_CHOTKEY_IME_NONIME_TOGGLE, VK_SPACE, MOD_LEFT | MOD_RIGHT | MOD_CONTROL, NULL }, 59 { IME_CHOTKEY_SHAPE_TOGGLE, VK_SPACE, MOD_LEFT | MOD_RIGHT | MOD_SHIFT, NULL }, 60 }; 61 62 // The far-east flags 63 #define FE_JAPANESE (1 << 0) 64 #define FE_CHINESE_TRADITIONAL (1 << 1) 65 #define FE_CHINESE_SIMPLIFIED (1 << 2) 66 #define FE_KOREAN (1 << 3) 67 68 // Sets the far-east flags 69 // Win: SetFeKeyboardFlags 70 VOID FASTCALL IntSetFeKeyboardFlags(LANGID LangID, PBYTE pbFlags) 71 { 72 switch (LangID) 73 { 74 case MAKELANGID(LANG_JAPANESE, SUBLANG_DEFAULT): 75 *pbFlags |= FE_JAPANESE; 76 break; 77 78 case MAKELANGID(LANG_CHINESE, SUBLANG_CHINESE_TRADITIONAL): 79 case MAKELANGID(LANG_CHINESE, SUBLANG_CHINESE_HONGKONG): 80 *pbFlags |= FE_CHINESE_TRADITIONAL; 81 break; 82 83 case MAKELANGID(LANG_CHINESE, SUBLANG_CHINESE_SIMPLIFIED): 84 case MAKELANGID(LANG_CHINESE, SUBLANG_CHINESE_SINGAPORE): 85 *pbFlags |= FE_CHINESE_SIMPLIFIED; 86 break; 87 88 case MAKELANGID(LANG_KOREAN, SUBLANG_KOREAN): 89 *pbFlags |= FE_KOREAN; 90 break; 91 92 default: 93 break; 94 } 95 } 96 97 DWORD FASTCALL CliReadRegistryValue(HANDLE hKey, LPCWSTR pszName) 98 { 99 DWORD dwValue, cbValue; 100 LONG error; 101 102 cbValue = sizeof(dwValue); 103 error = RegQueryValueExW(hKey, pszName, NULL, NULL, (LPBYTE)&dwValue, &cbValue); 104 if (error != ERROR_SUCCESS || cbValue < sizeof(DWORD)) 105 return 0; 106 107 return dwValue; 108 } 109 110 BOOL APIENTRY 111 CliImmSetHotKeyWorker(DWORD dwHotKeyId, UINT uModifiers, UINT uVirtualKey, HKL hKL, DWORD dwAction) 112 { 113 if (dwAction == SETIMEHOTKEY_ADD) 114 { 115 if (IME_HOTKEY_DSWITCH_FIRST <= dwHotKeyId && dwHotKeyId <= IME_HOTKEY_DSWITCH_LAST) 116 { 117 if (!hKL) 118 goto Failure; 119 } 120 else 121 { 122 if (hKL) 123 goto Failure; 124 125 if (IME_KHOTKEY_SHAPE_TOGGLE <= dwHotKeyId && 126 dwHotKeyId < IME_THOTKEY_IME_NONIME_TOGGLE) 127 { 128 // The Korean cannot set the IME hotkeys 129 goto Failure; 130 } 131 } 132 133 #define MOD_ALL_MODS (MOD_ALT | MOD_CONTROL | MOD_SHIFT | MOD_WIN) 134 if ((uModifiers & MOD_ALL_MODS) && !(uModifiers & (MOD_LEFT | MOD_RIGHT))) 135 goto Failure; 136 #undef MOD_ALL_MODS 137 } 138 139 return NtUserSetImeHotKey(dwHotKeyId, uModifiers, uVirtualKey, hKL, dwAction); 140 141 Failure: 142 SetLastError(ERROR_INVALID_PARAMETER); 143 return FALSE; 144 } 145 146 BOOL APIENTRY 147 CliSaveImeHotKey(DWORD dwID, UINT uModifiers, UINT uVirtualKey, HKL hKL, BOOL bDelete) 148 { 149 WCHAR szName[MAX_PATH]; 150 LONG error; 151 HKEY hControlPanel = NULL, hInputMethod = NULL, hHotKeys = NULL, hKey = NULL; 152 BOOL ret = FALSE, bRevertOnFailure = FALSE; 153 154 if (bDelete) 155 { 156 StringCchPrintfW(szName, _countof(szName), 157 L"Control Panel\\Input Method\\Hot Keys\\%08lX", dwID); 158 error = RegDeleteKeyW(HKEY_CURRENT_USER, szName); 159 return (error == ERROR_SUCCESS); 160 } 161 162 // Open "Control Panel" 163 error = RegCreateKeyExW(HKEY_CURRENT_USER, L"Control Panel", 0, NULL, 0, KEY_ALL_ACCESS, 164 NULL, &hControlPanel, NULL); 165 if (error == ERROR_SUCCESS) 166 { 167 // Open "Input Method" 168 error = RegCreateKeyExW(hControlPanel, L"Input Method", 0, NULL, 0, KEY_ALL_ACCESS, 169 NULL, &hInputMethod, NULL); 170 if (error == ERROR_SUCCESS) 171 { 172 // Open "Hot Keys" 173 error = RegCreateKeyExW(hInputMethod, L"Hot Keys", 0, NULL, 0, KEY_ALL_ACCESS, 174 NULL, &hHotKeys, NULL); 175 if (error == ERROR_SUCCESS) 176 { 177 // Open "Key" 178 StringCchPrintfW(szName, _countof(szName), L"%08lX", dwID); 179 error = RegCreateKeyExW(hHotKeys, szName, 0, NULL, 0, KEY_ALL_ACCESS, 180 NULL, &hKey, NULL); 181 if (error == ERROR_SUCCESS) 182 { 183 bRevertOnFailure = TRUE; 184 185 // Set "Virtual Key" 186 error = RegSetValueExW(hKey, L"Virtual Key", 0, REG_BINARY, 187 (LPBYTE)&uVirtualKey, sizeof(uVirtualKey)); 188 if (error == ERROR_SUCCESS) 189 { 190 // Set "Key Modifiers" 191 error = RegSetValueExW(hKey, L"Key Modifiers", 0, REG_BINARY, 192 (LPBYTE)&uModifiers, sizeof(uModifiers)); 193 if (error == ERROR_SUCCESS) 194 { 195 // Set "Target IME" 196 error = RegSetValueExW(hKey, L"Target IME", 0, REG_BINARY, 197 (LPBYTE)&hKL, sizeof(hKL)); 198 if (error == ERROR_SUCCESS) 199 { 200 // Success! 201 ret = TRUE; 202 bRevertOnFailure = FALSE; 203 } 204 } 205 } 206 RegCloseKey(hKey); 207 } 208 RegCloseKey(hHotKeys); 209 } 210 RegCloseKey(hInputMethod); 211 } 212 RegCloseKey(hControlPanel); 213 } 214 215 if (bRevertOnFailure) 216 CliSaveImeHotKey(dwID, uVirtualKey, uModifiers, hKL, TRUE); 217 218 return ret; 219 } 220 221 /* 222 * @implemented 223 * Same as imm32!ImmSetHotKey. 224 */ 225 BOOL WINAPI CliImmSetHotKey(DWORD dwID, UINT uModifiers, UINT uVirtualKey, HKL hKL) 226 { 227 BOOL ret; 228 229 if (uVirtualKey == 0) // Delete? 230 { 231 ret = CliSaveImeHotKey(dwID, uModifiers, uVirtualKey, hKL, TRUE); 232 if (ret) 233 CliImmSetHotKeyWorker(dwID, uModifiers, uVirtualKey, hKL, SETIMEHOTKEY_DELETE); 234 return ret; 235 } 236 237 // Add 238 ret = CliImmSetHotKeyWorker(dwID, uModifiers, uVirtualKey, hKL, SETIMEHOTKEY_ADD); 239 if (ret) 240 { 241 ret = CliSaveImeHotKey(dwID, uModifiers, uVirtualKey, hKL, FALSE); 242 if (!ret) // Failure? 243 CliImmSetHotKeyWorker(dwID, uModifiers, uVirtualKey, hKL, SETIMEHOTKEY_DELETE); 244 } 245 246 return ret; 247 } 248 249 BOOL FASTCALL CliSetSingleHotKey(LPCWSTR pszSubKey, HANDLE hKey) 250 { 251 LONG error; 252 HKEY hSubKey; 253 DWORD dwHotKeyId = 0; 254 UINT uModifiers = 0, uVirtualKey = 0; 255 HKL hKL = NULL; 256 UNICODE_STRING ustrName; 257 258 error = RegOpenKeyExW(hKey, pszSubKey, 0, KEY_READ, &hSubKey); 259 if (error != ERROR_SUCCESS) 260 return FALSE; 261 262 RtlInitUnicodeString(&ustrName, pszSubKey); 263 RtlUnicodeStringToInteger(&ustrName, 16, &dwHotKeyId); 264 265 uModifiers = CliReadRegistryValue(hSubKey, L"Key Modifiers"); 266 hKL = (HKL)(ULONG_PTR)CliReadRegistryValue(hSubKey, L"Target IME"); 267 uVirtualKey = CliReadRegistryValue(hSubKey, L"Virtual Key"); 268 269 RegCloseKey(hSubKey); 270 271 return CliImmSetHotKeyWorker(dwHotKeyId, uModifiers, uVirtualKey, hKL, SETIMEHOTKEY_ADD); 272 } 273 274 BOOL FASTCALL CliGetImeHotKeysFromRegistry(VOID) 275 { 276 HKEY hKey; 277 LONG error; 278 BOOL ret = FALSE; 279 DWORD dwIndex, cchKeyName; 280 WCHAR szKeyName[16]; 281 282 error = RegOpenKeyExW(HKEY_CURRENT_USER, 283 L"Control Panel\\Input Method\\Hot Keys", 284 0, 285 KEY_ALL_ACCESS, 286 &hKey); 287 if (error != ERROR_SUCCESS) 288 return ret; 289 290 for (dwIndex = 0; ; ++dwIndex) 291 { 292 cchKeyName = _countof(szKeyName); 293 error = RegEnumKeyExW(hKey, dwIndex, szKeyName, &cchKeyName, NULL, NULL, NULL, NULL); 294 if (error == ERROR_NO_MORE_ITEMS || error != ERROR_SUCCESS) 295 break; 296 297 szKeyName[_countof(szKeyName) - 1] = 0; 298 299 if (CliSetSingleHotKey(szKeyName, hKey)) 300 ret = TRUE; 301 } 302 303 RegCloseKey(hKey); 304 return ret; 305 } 306 307 VOID APIENTRY CliGetPreloadKeyboardLayouts(PBYTE pbFlags) 308 { 309 WCHAR szValueName[8], szValue[16]; 310 UNICODE_STRING ustrValue; 311 DWORD dwKL, cbValue, dwType; 312 UINT iNumber; 313 HKEY hKey; 314 LONG error; 315 316 error = RegOpenKeyExW(HKEY_CURRENT_USER, L"Keyboard Layout\\Preload", 0, KEY_READ, &hKey); 317 if (error != ERROR_SUCCESS) 318 return; 319 320 for (iNumber = 1; iNumber < 1000; ++iNumber) 321 { 322 StringCchPrintfW(szValueName, _countof(szValueName), L"%u", iNumber); 323 324 cbValue = sizeof(szValue); 325 error = RegQueryValueExW(hKey, szValueName, NULL, &dwType, (LPBYTE)szValue, &cbValue); 326 if (error != ERROR_SUCCESS || dwType != REG_SZ) 327 break; 328 329 szValue[_countof(szValue) - 1] = 0; 330 331 RtlInitUnicodeString(&ustrValue, szValue); 332 RtlUnicodeStringToInteger(&ustrValue, 16, &dwKL); 333 334 IntSetFeKeyboardFlags(LOWORD(dwKL), pbFlags); 335 } 336 337 RegCloseKey(hKey); 338 } 339 340 VOID APIENTRY CliSetDefaultImeHotKeys(PIMEHOTKEYENTRY pEntries, UINT nCount, BOOL bCheck) 341 { 342 UINT uVirtualKey, uModifiers; 343 HKL hKL; 344 345 while (nCount-- > 0) 346 { 347 if (!bCheck || !NtUserGetImeHotKey(pEntries->dwHotKeyId, &uModifiers, &uVirtualKey, &hKL)) 348 { 349 CliImmSetHotKeyWorker(pEntries->dwHotKeyId, 350 pEntries->uModifiers, 351 pEntries->uVirtualKey, 352 pEntries->hKL, 353 SETIMEHOTKEY_ADD); 354 } 355 ++pEntries; 356 } 357 } 358 359 VOID APIENTRY CliImmInitializeHotKeys(DWORD dwAction, HKL hKL) 360 { 361 UINT nCount; 362 LPHKL pList; 363 UINT iIndex; 364 LANGID LangID; 365 BYTE bFlags = 0; 366 BOOL bCheck; 367 368 NtUserSetImeHotKey(0, 0, 0, NULL, SETIMEHOTKEY_DELETEALL); 369 370 bCheck = CliGetImeHotKeysFromRegistry(); 371 372 if (dwAction == SETIMEHOTKEY_DELETEALL) 373 { 374 LangID = LANGIDFROMLCID(GetUserDefaultLCID()); 375 IntSetFeKeyboardFlags(LangID, &bFlags); 376 377 CliGetPreloadKeyboardLayouts(&bFlags); 378 } 379 else 380 { 381 nCount = NtUserGetKeyboardLayoutList(0, NULL); 382 if (!nCount) 383 return; 384 385 pList = RtlAllocateHeap(RtlGetProcessHeap(), 0, nCount * sizeof(HKL)); 386 if (!pList) 387 return; 388 389 NtUserGetKeyboardLayoutList(nCount, pList); 390 391 for (iIndex = 0; iIndex < nCount; ++iIndex) 392 { 393 LangID = LOWORD(pList[iIndex]); 394 IntSetFeKeyboardFlags(LangID, &bFlags); 395 } 396 397 RtlFreeHeap(RtlGetProcessHeap(), 0, pList); 398 } 399 400 if (bFlags & FE_JAPANESE) 401 CliSetDefaultImeHotKeys(DefaultHotKeyTableJ, _countof(DefaultHotKeyTableJ), bCheck); 402 403 if (bFlags & FE_CHINESE_TRADITIONAL) 404 CliSetDefaultImeHotKeys(DefaultHotKeyTableT, _countof(DefaultHotKeyTableT), bCheck); 405 406 if (bFlags & FE_CHINESE_SIMPLIFIED) 407 CliSetDefaultImeHotKeys(DefaultHotKeyTableC, _countof(DefaultHotKeyTableC), bCheck); 408 } 409 410 /* 411 * @implemented 412 */ 413 BOOL 414 WINAPI 415 DragDetect( 416 HWND hWnd, 417 POINT pt) 418 { 419 return NtUserDragDetect(hWnd, pt); 420 #if 0 421 MSG msg; 422 RECT rect; 423 POINT tmp; 424 ULONG dx = GetSystemMetrics(SM_CXDRAG); 425 ULONG dy = GetSystemMetrics(SM_CYDRAG); 426 427 rect.left = pt.x - dx; 428 rect.right = pt.x + dx; 429 rect.top = pt.y - dy; 430 rect.bottom = pt.y + dy; 431 432 SetCapture(hWnd); 433 434 for (;;) 435 { 436 while ( 437 PeekMessageW(&msg, 0, WM_MOUSEFIRST, WM_MOUSELAST, PM_REMOVE) || 438 PeekMessageW(&msg, 0, WM_KEYFIRST, WM_KEYLAST, PM_REMOVE) 439 ) 440 { 441 if (msg.message == WM_LBUTTONUP) 442 { 443 ReleaseCapture(); 444 return FALSE; 445 } 446 if (msg.message == WM_MOUSEMOVE) 447 { 448 tmp.x = LOWORD(msg.lParam); 449 tmp.y = HIWORD(msg.lParam); 450 if (!PtInRect(&rect, tmp)) 451 { 452 ReleaseCapture(); 453 return TRUE; 454 } 455 } 456 if (msg.message == WM_KEYDOWN) 457 { 458 if (msg.wParam == VK_ESCAPE) 459 { 460 ReleaseCapture(); 461 return TRUE; 462 } 463 } 464 } 465 WaitMessage(); 466 } 467 return 0; 468 #endif 469 } 470 471 /* 472 * @implemented 473 */ 474 BOOL WINAPI 475 EnableWindow(HWND hWnd, BOOL bEnable) 476 { 477 return NtUserxEnableWindow(hWnd, bEnable); 478 } 479 480 /* 481 * @implemented 482 */ 483 SHORT 484 WINAPI 485 DECLSPEC_HOTPATCH 486 GetAsyncKeyState(int vKey) 487 { 488 if (vKey < 0 || vKey > 256) 489 return 0; 490 return (SHORT)NtUserGetAsyncKeyState((DWORD)vKey); 491 } 492 493 494 /* 495 * @implemented 496 */ 497 HKL WINAPI 498 GetKeyboardLayout(DWORD idThread) 499 { 500 return NtUserxGetKeyboardLayout(idThread); 501 } 502 503 504 /* 505 * @implemented 506 */ 507 UINT WINAPI 508 GetKBCodePage(VOID) 509 { 510 return GetOEMCP(); 511 } 512 513 514 /* 515 * @implemented 516 */ 517 int WINAPI 518 GetKeyNameTextA(LONG lParam, 519 LPSTR lpString, 520 int nSize) 521 { 522 LPWSTR pwszBuf; 523 UINT cchBuf = 0; 524 int iRet = 0; 525 BOOL defChar = FALSE; 526 527 pwszBuf = HeapAlloc(GetProcessHeap(), 0, nSize * sizeof(WCHAR)); 528 if (!pwszBuf) 529 return 0; 530 531 cchBuf = NtUserGetKeyNameText(lParam, pwszBuf, nSize); 532 533 iRet = WideCharToMultiByte(CP_ACP, 0, 534 pwszBuf, cchBuf, 535 lpString, nSize, ".", &defChar); // FIXME: do we need defChar? 536 lpString[iRet] = 0; 537 HeapFree(GetProcessHeap(), 0, pwszBuf); 538 539 return iRet; 540 } 541 542 /* 543 * @implemented 544 */ 545 int WINAPI 546 GetKeyNameTextW(LONG lParam, 547 LPWSTR lpString, 548 int nSize) 549 { 550 return NtUserGetKeyNameText(lParam, lpString, nSize); 551 } 552 553 /* 554 * @implemented 555 */ 556 SHORT 557 WINAPI 558 DECLSPEC_HOTPATCH 559 GetKeyState(int nVirtKey) 560 { 561 return (SHORT)NtUserGetKeyState((DWORD)nVirtKey); 562 } 563 564 /* 565 * @implemented 566 */ 567 BOOL WINAPI 568 GetKeyboardLayoutNameA(LPSTR pwszKLID) 569 { 570 WCHAR buf[KL_NAMELENGTH]; 571 572 if (!GetKeyboardLayoutNameW(buf)) 573 return FALSE; 574 575 if (!WideCharToMultiByte(CP_ACP, 0, buf, -1, pwszKLID, KL_NAMELENGTH, NULL, NULL)) 576 return FALSE; 577 578 return TRUE; 579 } 580 581 /* 582 * @implemented 583 */ 584 BOOL WINAPI 585 GetKeyboardLayoutNameW(LPWSTR pwszKLID) 586 { 587 UNICODE_STRING Name; 588 589 RtlInitEmptyUnicodeString(&Name, 590 pwszKLID, 591 KL_NAMELENGTH * sizeof(WCHAR)); 592 593 return NtUserGetKeyboardLayoutName(&Name); 594 } 595 596 /* 597 * @implemented 598 */ 599 int WINAPI 600 GetKeyboardType(int nTypeFlag) 601 { 602 return NtUserxGetKeyboardType(nTypeFlag); 603 } 604 605 /* 606 * @implemented 607 */ 608 BOOL WINAPI 609 GetLastInputInfo(PLASTINPUTINFO plii) 610 { 611 TRACE("%p\n", plii); 612 613 if (plii->cbSize != sizeof (*plii)) 614 { 615 SetLastError(ERROR_INVALID_PARAMETER); 616 return FALSE; 617 } 618 619 plii->dwTime = gpsi->dwLastRITEventTickCount; 620 return TRUE; 621 } 622 623 /* 624 * @implemented 625 */ 626 HKL WINAPI 627 LoadKeyboardLayoutA(LPCSTR pszKLID, 628 UINT Flags) 629 { 630 WCHAR wszKLID[16]; 631 632 if (!MultiByteToWideChar(CP_ACP, 0, pszKLID, -1, 633 wszKLID, sizeof(wszKLID)/sizeof(wszKLID[0]))) 634 { 635 return FALSE; 636 } 637 638 return LoadKeyboardLayoutW(wszKLID, Flags); 639 } 640 641 /* 642 * @unimplemented 643 */ 644 /* Win: LoadKeyboardLayoutWorker */ 645 HKL APIENTRY 646 IntLoadKeyboardLayout( 647 _In_ HKL hklUnload, 648 _In_z_ LPCWSTR pwszKLID, 649 _In_ LANGID wLangID, 650 _In_ UINT Flags, 651 _In_ BOOL unknown5) 652 { 653 DWORD dwhkl, dwType, dwSize; 654 UNICODE_STRING ustrKbdName; 655 UNICODE_STRING ustrKLID; 656 WCHAR wszRegKey[256] = L"SYSTEM\\CurrentControlSet\\Control\\Keyboard Layouts\\"; 657 WCHAR wszLayoutId[10], wszNewKLID[10]; 658 HKEY hKey; 659 HKL hNewKL; 660 661 /* LOWORD of dwhkl is Locale Identifier */ 662 dwhkl = LOWORD(wcstoul(pwszKLID, NULL, 16)); 663 664 if (Flags & KLF_SUBSTITUTE_OK) 665 { 666 /* Check substitutes key */ 667 if (RegOpenKeyExW(HKEY_CURRENT_USER, L"Keyboard Layout\\Substitutes", 0, 668 KEY_READ, &hKey) == ERROR_SUCCESS) 669 { 670 dwSize = sizeof(wszNewKLID); 671 if (RegQueryValueExW(hKey, pwszKLID, NULL, &dwType, (LPBYTE)wszNewKLID, &dwSize) == ERROR_SUCCESS) 672 { 673 /* Use new KLID value */ 674 pwszKLID = wszNewKLID; 675 } 676 677 /* Close the key now */ 678 RegCloseKey(hKey); 679 } 680 } 681 682 /* Append KLID at the end of registry key */ 683 StringCbCatW(wszRegKey, sizeof(wszRegKey), pwszKLID); 684 685 /* Open layout registry key for read */ 686 if (RegOpenKeyExW(HKEY_LOCAL_MACHINE, wszRegKey, 0, 687 KEY_READ, &hKey) == ERROR_SUCCESS) 688 { 689 dwSize = sizeof(wszLayoutId); 690 if (RegQueryValueExW(hKey, L"Layout Id", NULL, &dwType, (LPBYTE)wszLayoutId, &dwSize) == ERROR_SUCCESS) 691 { 692 /* If Layout Id is specified, use this value | f000 as HIWORD */ 693 /* FIXME: Microsoft Office expects this value to be something specific 694 * for Japanese and Korean Windows with an IME the value is 0xe001 695 * We should probably check to see if an IME exists and if so then 696 * set this word properly. 697 */ 698 dwhkl |= (0xf000 | wcstol(wszLayoutId, NULL, 16)) << 16; 699 } 700 701 /* Close the key now */ 702 RegCloseKey(hKey); 703 } 704 else 705 { 706 ERR("Could not find keyboard layout %S.\n", pwszKLID); 707 return NULL; 708 } 709 710 /* If Layout Id is not given HIWORD == LOWORD (for dwhkl) */ 711 if (!HIWORD(dwhkl)) 712 dwhkl |= dwhkl << 16; 713 714 ZeroMemory(&ustrKbdName, sizeof(ustrKbdName)); 715 RtlInitUnicodeString(&ustrKLID, pwszKLID); 716 hNewKL = NtUserLoadKeyboardLayoutEx(NULL, 0, &ustrKbdName, 717 NULL, &ustrKLID, 718 dwhkl, Flags); 719 CliImmInitializeHotKeys(SETIMEHOTKEY_ADD, hNewKL); 720 return hNewKL; 721 } 722 723 /* 724 * @implemented 725 */ 726 HKL WINAPI 727 LoadKeyboardLayoutW(LPCWSTR pwszKLID, 728 UINT Flags) 729 { 730 TRACE("(%s, 0x%X)", debugstr_w(pwszKLID), Flags); 731 return IntLoadKeyboardLayout(NULL, pwszKLID, 0, Flags, FALSE); 732 } 733 734 /* 735 * @unimplemented 736 */ 737 HKL WINAPI 738 LoadKeyboardLayoutEx(HKL hklUnload, 739 LPCWSTR pwszKLID, 740 UINT Flags) 741 { 742 FIXME("(%p, %s, 0x%X)", hklUnload, debugstr_w(pwszKLID), Flags); 743 if (!hklUnload) 744 return NULL; 745 return IntLoadKeyboardLayout(hklUnload, pwszKLID, 0, Flags, FALSE); 746 } 747 748 /* 749 * @implemented 750 */ 751 BOOL WINAPI UnloadKeyboardLayout(HKL hKL) 752 { 753 if (!NtUserUnloadKeyboardLayout(hKL)) 754 return FALSE; 755 756 CliImmInitializeHotKeys(SETIMEHOTKEY_DELETE, hKL); 757 return TRUE; 758 } 759 760 /* 761 * @implemented 762 */ 763 UINT WINAPI 764 MapVirtualKeyA(UINT uCode, 765 UINT uMapType) 766 { 767 return MapVirtualKeyExA(uCode, uMapType, GetKeyboardLayout(0)); 768 } 769 770 /* 771 * @implemented 772 */ 773 UINT WINAPI 774 MapVirtualKeyExA(UINT uCode, 775 UINT uMapType, 776 HKL dwhkl) 777 { 778 return MapVirtualKeyExW(uCode, uMapType, dwhkl); 779 } 780 781 782 /* 783 * @implemented 784 */ 785 UINT WINAPI 786 MapVirtualKeyExW(UINT uCode, 787 UINT uMapType, 788 HKL dwhkl) 789 { 790 return NtUserMapVirtualKeyEx(uCode, uMapType, 0, dwhkl); 791 } 792 793 794 /* 795 * @implemented 796 */ 797 UINT WINAPI 798 MapVirtualKeyW(UINT uCode, 799 UINT uMapType) 800 { 801 return MapVirtualKeyExW(uCode, uMapType, GetKeyboardLayout(0)); 802 } 803 804 805 /* 806 * @implemented 807 */ 808 DWORD WINAPI 809 OemKeyScan(WORD wOemChar) 810 { 811 WCHAR p; 812 SHORT Vk; 813 UINT Scan; 814 815 MultiByteToWideChar(CP_OEMCP, 0, (PCSTR)&wOemChar, 1, &p, 1); 816 Vk = VkKeyScanW(p); 817 Scan = MapVirtualKeyW((Vk & 0x00ff), 0); 818 if (!Scan) return -1; 819 /* 820 Page 450-1, MS W2k SuperBible by SAMS. Return, low word has the 821 scan code and high word has the shift state. 822 */ 823 return ((Vk & 0xff00) << 8) | Scan; 824 } 825 826 827 /* 828 * @implemented 829 */ 830 BOOL WINAPI 831 SetDoubleClickTime(UINT uInterval) 832 { 833 return (BOOL)NtUserSystemParametersInfo(SPI_SETDOUBLECLICKTIME, 834 uInterval, 835 NULL, 836 0); 837 } 838 839 840 /* 841 * @implemented 842 */ 843 BOOL 844 WINAPI 845 SwapMouseButton( 846 BOOL fSwap) 847 { 848 return NtUserxSwapMouseButton(fSwap); 849 } 850 851 852 /* 853 * @implemented 854 */ 855 int WINAPI 856 ToAscii(UINT uVirtKey, 857 UINT uScanCode, 858 CONST BYTE *lpKeyState, 859 LPWORD lpChar, 860 UINT uFlags) 861 { 862 return ToAsciiEx(uVirtKey, uScanCode, lpKeyState, lpChar, uFlags, 0); 863 } 864 865 866 /* 867 * @implemented 868 */ 869 int WINAPI 870 ToAsciiEx(UINT uVirtKey, 871 UINT uScanCode, 872 CONST BYTE *lpKeyState, 873 LPWORD lpChar, 874 UINT uFlags, 875 HKL dwhkl) 876 { 877 WCHAR UniChars[2]; 878 int Ret, CharCount; 879 880 Ret = ToUnicodeEx(uVirtKey, uScanCode, lpKeyState, UniChars, 2, uFlags, dwhkl); 881 CharCount = (Ret < 0 ? 1 : Ret); 882 WideCharToMultiByte(CP_ACP, 0, UniChars, CharCount, (LPSTR)lpChar, 2, NULL, NULL); 883 884 return Ret; 885 } 886 887 888 /* 889 * @implemented 890 */ 891 int WINAPI 892 ToUnicode(UINT wVirtKey, 893 UINT wScanCode, 894 CONST BYTE *lpKeyState, 895 LPWSTR pwszBuff, 896 int cchBuff, 897 UINT wFlags) 898 { 899 return ToUnicodeEx(wVirtKey, wScanCode, lpKeyState, pwszBuff, cchBuff, 900 wFlags, 0); 901 } 902 903 904 /* 905 * @implemented 906 */ 907 int WINAPI 908 ToUnicodeEx(UINT wVirtKey, 909 UINT wScanCode, 910 CONST BYTE *lpKeyState, 911 LPWSTR pwszBuff, 912 int cchBuff, 913 UINT wFlags, 914 HKL dwhkl) 915 { 916 return NtUserToUnicodeEx(wVirtKey, wScanCode, (PBYTE)lpKeyState, pwszBuff, cchBuff, 917 wFlags, dwhkl); 918 } 919 920 921 922 /* 923 * @implemented 924 */ 925 SHORT WINAPI 926 VkKeyScanA(CHAR ch) 927 { 928 WCHAR wChar; 929 930 if (IsDBCSLeadByte(ch)) 931 return -1; 932 933 MultiByteToWideChar(CP_ACP, 0, &ch, 1, &wChar, 1); 934 return VkKeyScanW(wChar); 935 } 936 937 938 /* 939 * @implemented 940 */ 941 SHORT WINAPI 942 VkKeyScanExA(CHAR ch, 943 HKL dwhkl) 944 { 945 WCHAR wChar; 946 947 if (IsDBCSLeadByte(ch)) 948 return -1; 949 950 MultiByteToWideChar(CP_ACP, 0, &ch, 1, &wChar, 1); 951 return VkKeyScanExW(wChar, dwhkl); 952 } 953 954 955 /* 956 * @implemented 957 */ 958 SHORT WINAPI 959 VkKeyScanExW(WCHAR ch, 960 HKL dwhkl) 961 { 962 return (SHORT)NtUserVkKeyScanEx(ch, dwhkl, TRUE); 963 } 964 965 966 /* 967 * @implemented 968 */ 969 SHORT WINAPI 970 VkKeyScanW(WCHAR ch) 971 { 972 return (SHORT)NtUserVkKeyScanEx(ch, 0, FALSE); 973 } 974 975 976 /* 977 * @implemented 978 */ 979 VOID 980 WINAPI 981 keybd_event( 982 BYTE bVk, 983 BYTE bScan, 984 DWORD dwFlags, 985 ULONG_PTR dwExtraInfo) 986 { 987 INPUT Input; 988 989 Input.type = INPUT_KEYBOARD; 990 Input.ki.wVk = bVk; 991 Input.ki.wScan = bScan; 992 Input.ki.dwFlags = dwFlags; 993 Input.ki.time = 0; 994 Input.ki.dwExtraInfo = dwExtraInfo; 995 996 NtUserSendInput(1, &Input, sizeof(INPUT)); 997 } 998 999 1000 /* 1001 * @implemented 1002 */ 1003 VOID 1004 WINAPI 1005 mouse_event( 1006 DWORD dwFlags, 1007 DWORD dx, 1008 DWORD dy, 1009 DWORD dwData, 1010 ULONG_PTR dwExtraInfo) 1011 { 1012 INPUT Input; 1013 1014 Input.type = INPUT_MOUSE; 1015 Input.mi.dx = dx; 1016 Input.mi.dy = dy; 1017 Input.mi.mouseData = dwData; 1018 Input.mi.dwFlags = dwFlags; 1019 Input.mi.time = 0; 1020 Input.mi.dwExtraInfo = dwExtraInfo; 1021 1022 NtUserSendInput(1, &Input, sizeof(INPUT)); 1023 } 1024 1025 /* EOF */ 1026