1de1dc0f293ead057bc066bb034b731616d23960
[reactos.git] / win32ss / user / user32 / windows / input.c
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 * @implemented
643 */
644 HKL WINAPI
645 LoadKeyboardLayoutW(LPCWSTR pwszKLID,
646 UINT Flags)
647 {
648 DWORD dwhkl, dwType, dwSize;
649 UNICODE_STRING ustrKbdName;
650 UNICODE_STRING ustrKLID;
651 WCHAR wszRegKey[256] = L"SYSTEM\\CurrentControlSet\\Control\\Keyboard Layouts\\";
652 WCHAR wszLayoutId[10], wszNewKLID[10];
653 HKEY hKey;
654
655 /* LOWORD of dwhkl is Locale Identifier */
656 dwhkl = LOWORD(wcstoul(pwszKLID, NULL, 16));
657
658 if (Flags & KLF_SUBSTITUTE_OK)
659 {
660 /* Check substitutes key */
661 if (RegOpenKeyExW(HKEY_CURRENT_USER, L"Keyboard Layout\\Substitutes", 0,
662 KEY_READ, &hKey) == ERROR_SUCCESS)
663 {
664 dwSize = sizeof(wszNewKLID);
665 if (RegQueryValueExW(hKey, pwszKLID, NULL, &dwType, (LPBYTE)wszNewKLID, &dwSize) == ERROR_SUCCESS)
666 {
667 /* Use new KLID value */
668 pwszKLID = wszNewKLID;
669 }
670
671 /* Close the key now */
672 RegCloseKey(hKey);
673 }
674 }
675
676 /* Append KLID at the end of registry key */
677 StringCbCatW(wszRegKey, sizeof(wszRegKey), pwszKLID);
678
679 /* Open layout registry key for read */
680 if (RegOpenKeyExW(HKEY_LOCAL_MACHINE, wszRegKey, 0,
681 KEY_READ, &hKey) == ERROR_SUCCESS)
682 {
683 dwSize = sizeof(wszLayoutId);
684 if (RegQueryValueExW(hKey, L"Layout Id", NULL, &dwType, (LPBYTE)wszLayoutId, &dwSize) == ERROR_SUCCESS)
685 {
686 /* If Layout Id is specified, use this value | f000 as HIWORD */
687 /* FIXME: Microsoft Office expects this value to be something specific
688 * for Japanese and Korean Windows with an IME the value is 0xe001
689 * We should probably check to see if an IME exists and if so then
690 * set this word properly.
691 */
692 dwhkl |= (0xf000 | wcstol(wszLayoutId, NULL, 16)) << 16;
693 }
694
695 /* Close the key now */
696 RegCloseKey(hKey);
697 }
698 else
699 {
700 ERR("Could not find keyboard layout %S.\n", pwszKLID);
701 return NULL;
702 }
703
704 /* If Layout Id is not given HIWORD == LOWORD (for dwhkl) */
705 if (!HIWORD(dwhkl))
706 dwhkl |= dwhkl << 16;
707
708 ZeroMemory(&ustrKbdName, sizeof(ustrKbdName));
709 RtlInitUnicodeString(&ustrKLID, pwszKLID);
710 return NtUserLoadKeyboardLayoutEx(NULL, 0, &ustrKbdName,
711 NULL, &ustrKLID,
712 dwhkl, Flags);
713 }
714
715 /*
716 * @implemented
717 */
718 BOOL WINAPI UnloadKeyboardLayout(HKL hKL)
719 {
720 if (!NtUserUnloadKeyboardLayout(hKL))
721 return FALSE;
722
723 CliImmInitializeHotKeys(SETIMEHOTKEY_DELETE, hKL);
724 return TRUE;
725 }
726
727 /*
728 * @implemented
729 */
730 UINT WINAPI
731 MapVirtualKeyA(UINT uCode,
732 UINT uMapType)
733 {
734 return MapVirtualKeyExA(uCode, uMapType, GetKeyboardLayout(0));
735 }
736
737 /*
738 * @implemented
739 */
740 UINT WINAPI
741 MapVirtualKeyExA(UINT uCode,
742 UINT uMapType,
743 HKL dwhkl)
744 {
745 return MapVirtualKeyExW(uCode, uMapType, dwhkl);
746 }
747
748
749 /*
750 * @implemented
751 */
752 UINT WINAPI
753 MapVirtualKeyExW(UINT uCode,
754 UINT uMapType,
755 HKL dwhkl)
756 {
757 return NtUserMapVirtualKeyEx(uCode, uMapType, 0, dwhkl);
758 }
759
760
761 /*
762 * @implemented
763 */
764 UINT WINAPI
765 MapVirtualKeyW(UINT uCode,
766 UINT uMapType)
767 {
768 return MapVirtualKeyExW(uCode, uMapType, GetKeyboardLayout(0));
769 }
770
771
772 /*
773 * @implemented
774 */
775 DWORD WINAPI
776 OemKeyScan(WORD wOemChar)
777 {
778 WCHAR p;
779 SHORT Vk;
780 UINT Scan;
781
782 MultiByteToWideChar(CP_OEMCP, 0, (PCSTR)&wOemChar, 1, &p, 1);
783 Vk = VkKeyScanW(p);
784 Scan = MapVirtualKeyW((Vk & 0x00ff), 0);
785 if (!Scan) return -1;
786 /*
787 Page 450-1, MS W2k SuperBible by SAMS. Return, low word has the
788 scan code and high word has the shift state.
789 */
790 return ((Vk & 0xff00) << 8) | Scan;
791 }
792
793
794 /*
795 * @implemented
796 */
797 BOOL WINAPI
798 SetDoubleClickTime(UINT uInterval)
799 {
800 return (BOOL)NtUserSystemParametersInfo(SPI_SETDOUBLECLICKTIME,
801 uInterval,
802 NULL,
803 0);
804 }
805
806
807 /*
808 * @implemented
809 */
810 BOOL
811 WINAPI
812 SwapMouseButton(
813 BOOL fSwap)
814 {
815 return NtUserxSwapMouseButton(fSwap);
816 }
817
818
819 /*
820 * @implemented
821 */
822 int WINAPI
823 ToAscii(UINT uVirtKey,
824 UINT uScanCode,
825 CONST BYTE *lpKeyState,
826 LPWORD lpChar,
827 UINT uFlags)
828 {
829 return ToAsciiEx(uVirtKey, uScanCode, lpKeyState, lpChar, uFlags, 0);
830 }
831
832
833 /*
834 * @implemented
835 */
836 int WINAPI
837 ToAsciiEx(UINT uVirtKey,
838 UINT uScanCode,
839 CONST BYTE *lpKeyState,
840 LPWORD lpChar,
841 UINT uFlags,
842 HKL dwhkl)
843 {
844 WCHAR UniChars[2];
845 int Ret, CharCount;
846
847 Ret = ToUnicodeEx(uVirtKey, uScanCode, lpKeyState, UniChars, 2, uFlags, dwhkl);
848 CharCount = (Ret < 0 ? 1 : Ret);
849 WideCharToMultiByte(CP_ACP, 0, UniChars, CharCount, (LPSTR)lpChar, 2, NULL, NULL);
850
851 return Ret;
852 }
853
854
855 /*
856 * @implemented
857 */
858 int WINAPI
859 ToUnicode(UINT wVirtKey,
860 UINT wScanCode,
861 CONST BYTE *lpKeyState,
862 LPWSTR pwszBuff,
863 int cchBuff,
864 UINT wFlags)
865 {
866 return ToUnicodeEx(wVirtKey, wScanCode, lpKeyState, pwszBuff, cchBuff,
867 wFlags, 0);
868 }
869
870
871 /*
872 * @implemented
873 */
874 int WINAPI
875 ToUnicodeEx(UINT wVirtKey,
876 UINT wScanCode,
877 CONST BYTE *lpKeyState,
878 LPWSTR pwszBuff,
879 int cchBuff,
880 UINT wFlags,
881 HKL dwhkl)
882 {
883 return NtUserToUnicodeEx(wVirtKey, wScanCode, (PBYTE)lpKeyState, pwszBuff, cchBuff,
884 wFlags, dwhkl);
885 }
886
887
888
889 /*
890 * @implemented
891 */
892 SHORT WINAPI
893 VkKeyScanA(CHAR ch)
894 {
895 WCHAR wChar;
896
897 if (IsDBCSLeadByte(ch))
898 return -1;
899
900 MultiByteToWideChar(CP_ACP, 0, &ch, 1, &wChar, 1);
901 return VkKeyScanW(wChar);
902 }
903
904
905 /*
906 * @implemented
907 */
908 SHORT WINAPI
909 VkKeyScanExA(CHAR ch,
910 HKL dwhkl)
911 {
912 WCHAR wChar;
913
914 if (IsDBCSLeadByte(ch))
915 return -1;
916
917 MultiByteToWideChar(CP_ACP, 0, &ch, 1, &wChar, 1);
918 return VkKeyScanExW(wChar, dwhkl);
919 }
920
921
922 /*
923 * @implemented
924 */
925 SHORT WINAPI
926 VkKeyScanExW(WCHAR ch,
927 HKL dwhkl)
928 {
929 return (SHORT)NtUserVkKeyScanEx(ch, dwhkl, TRUE);
930 }
931
932
933 /*
934 * @implemented
935 */
936 SHORT WINAPI
937 VkKeyScanW(WCHAR ch)
938 {
939 return (SHORT)NtUserVkKeyScanEx(ch, 0, FALSE);
940 }
941
942
943 /*
944 * @implemented
945 */
946 VOID
947 WINAPI
948 keybd_event(
949 BYTE bVk,
950 BYTE bScan,
951 DWORD dwFlags,
952 ULONG_PTR dwExtraInfo)
953 {
954 INPUT Input;
955
956 Input.type = INPUT_KEYBOARD;
957 Input.ki.wVk = bVk;
958 Input.ki.wScan = bScan;
959 Input.ki.dwFlags = dwFlags;
960 Input.ki.time = 0;
961 Input.ki.dwExtraInfo = dwExtraInfo;
962
963 NtUserSendInput(1, &Input, sizeof(INPUT));
964 }
965
966
967 /*
968 * @implemented
969 */
970 VOID
971 WINAPI
972 mouse_event(
973 DWORD dwFlags,
974 DWORD dx,
975 DWORD dy,
976 DWORD dwData,
977 ULONG_PTR dwExtraInfo)
978 {
979 INPUT Input;
980
981 Input.type = INPUT_MOUSE;
982 Input.mi.dx = dx;
983 Input.mi.dy = dy;
984 Input.mi.mouseData = dwData;
985 Input.mi.dwFlags = dwFlags;
986 Input.mi.time = 0;
987 Input.mi.dwExtraInfo = dwExtraInfo;
988
989 NtUserSendInput(1, &Input, sizeof(INPUT));
990 }
991
992 /* EOF */