ReactOS 0.4.15-dev-6049-ge54b32b
keyboard.c
Go to the documentation of this file.
1/*
2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS kernel
4 * PURPOSE: Keyboard functions
5 * FILE: win32ss/user/ntuser/keyboard.c
6 * PROGRAMERS: Casper S. Hornstrup (chorns@users.sourceforge.net)
7 * Rafal Harabien (rafalh@reactos.org)
8 */
9
10#include <win32k.h>
12
13BYTE gafAsyncKeyState[256 * 2 / 8]; // 2 bits per key
14static BYTE gafAsyncKeyStateRecentDown[256 / 8]; // 1 bit per key
20
21/* FUNCTIONS *****************************************************************/
22
23/*
24 * InitKeyboardImpl
25 *
26 * Initialization -- Right now, just zero the key state
27 */
28CODE_SEG("INIT")
32{
35 // Clear and set default information.
37 gKeyboardInfo.KeyboardIdentifier.Type = 4; /* AT-101 */
38 gKeyboardInfo.NumberOfFunctionKeys = 12; /* We're doing an 101 for now, so return 12 F-keys */
39 return STATUS_SUCCESS;
40}
41
42/*
43 * IntKeyboardGetIndicatorTrans
44 *
45 * Asks the keyboard driver to send a small table that shows which
46 * lights should connect with which scancodes
47 */
48//static
51 PKEYBOARD_INDICATOR_TRANSLATION *ppIndicatorTrans)
52{
54 DWORD dwSize = 0;
55 IO_STATUS_BLOCK Block;
57
59
61 dwSize,
63
64 while (pRet)
65 {
66 Status = ZwDeviceIoControlFile(hKeyboardDevice,
67 NULL,
68 NULL,
69 NULL,
70 &Block,
72 NULL, 0,
73 pRet, dwSize);
74
76 break;
77
79
81
83 dwSize,
85 }
86
87 if (!pRet)
89
90 if (!NT_SUCCESS(Status))
91 {
93 return Status;
94 }
95
96 *ppIndicatorTrans = pRet;
97 return Status;
98}
99
100/*
101 * IntKeyboardUpdateLeds
102 *
103 * Sends the keyboard commands to turn on/off the lights
104 */
105static
108 WORD wVk,
109 WORD wScanCode)
110{
112 UINT i;
113 USHORT LedFlag = 0;
114 IO_STATUS_BLOCK Block;
115
118
119 switch (wVk)
120 {
121 case VK_CAPITAL: LedFlag = KEYBOARD_CAPS_LOCK_ON; break;
122 case VK_NUMLOCK: LedFlag = KEYBOARD_NUM_LOCK_ON; break;
123 case VK_SCROLL: LedFlag = KEYBOARD_SCROLL_LOCK_ON; break;
124 default:
126 {
128 {
130 break;
131 }
132 }
133 }
134
135 if (LedFlag)
136 {
137 gIndicators.LedFlags ^= LedFlag;
138
139 /* Update the lights on the hardware */
140 Status = ZwDeviceIoControlFile(hKeyboardDevice,
141 NULL,
142 NULL,
143 NULL,
144 &Block,
146 &gIndicators, sizeof(gIndicators),
147 NULL, 0);
148
149 return Status;
150 }
151
152 return STATUS_SUCCESS;
153}
154
155/*
156 * UserInitKeyboard
157 *
158 * Initializes keyboard indicators translation and their state
159 */
161UserInitKeyboard(HANDLE hKeyboardDevice)
162{
164 IO_STATUS_BLOCK Block;
165
167
168 Status = ZwDeviceIoControlFile(hKeyboardDevice,
169 NULL,
170 NULL,
171 NULL,
172 &Block,
174 NULL, 0,
176 sizeof(gIndicators));
177
178 if (!NT_SUCCESS(Status))
179 {
180 WARN("NtDeviceIoControlFile() failed, ignored\n");
183 }
184
191
192 // FIXME: Need device driver to work! HID support more than one!!!!
193 Status = ZwDeviceIoControlFile(hKeyboardDevice,
194 NULL,
195 NULL,
196 NULL,
197 &Block,
199 NULL, 0,
200 &gKeyboardInfo, sizeof(gKeyboardInfo));
201
202 if (!NT_SUCCESS(Status))
203 {
204 ERR("NtDeviceIoControlFile() failed, ignored\n");
205 }
206 TRACE("Keyboard type %u, subtype %u and number of func keys %u\n",
210}
211
212/*
213 * IntSimplifyVk
214 *
215 * Changes virtual keys which distinguish between left and right hand, to keys which don't distinguish
216 */
217static
218WORD
220{
221 switch (wVk)
222 {
223 case VK_LSHIFT:
224 case VK_RSHIFT:
225 return VK_SHIFT;
226
227 case VK_LCONTROL:
228 case VK_RCONTROL:
229 return VK_CONTROL;
230
231 case VK_LMENU:
232 case VK_RMENU:
233 return VK_MENU;
234
235 default:
236 return wVk;
237 }
238}
239
240/*
241 * IntFixVk
242 *
243 * Changes virtual keys which don't not distinguish between left and right hand to proper keys
244 */
245static
246WORD
248{
249 switch (wVk)
250 {
251 case VK_SHIFT:
252 return bExt ? VK_RSHIFT : VK_LSHIFT;
253
254 case VK_CONTROL:
255 return bExt ? VK_RCONTROL : VK_LCONTROL;
256
257 case VK_MENU:
258 return bExt ? VK_RMENU : VK_LMENU;
259
260 default:
261 return wVk;
262 }
263}
264
265/*
266 * IntTranslateNumpadKey
267 *
268 * Translates numpad keys when numlock is enabled
269 */
270static
271WORD
273{
274 switch (wVk)
275 {
276 case VK_INSERT: return VK_NUMPAD0;
277 case VK_END: return VK_NUMPAD1;
278 case VK_DOWN: return VK_NUMPAD2;
279 case VK_NEXT: return VK_NUMPAD3;
280 case VK_LEFT: return VK_NUMPAD4;
281 case VK_CLEAR: return VK_NUMPAD5;
282 case VK_RIGHT: return VK_NUMPAD6;
283 case VK_HOME: return VK_NUMPAD7;
284 case VK_UP: return VK_NUMPAD8;
285 case VK_PRIOR: return VK_NUMPAD9;
286 case VK_DELETE: return VK_DECIMAL;
287 default: return wVk;
288 }
289}
290
291/*
292 * IntGetModBits
293 *
294 * Gets layout specific modification bits, for example KBDSHIFT, KBDCTRL, KBDALT
295 */
296static
297DWORD
298IntGetModBits(PKBDTABLES pKbdTbl, PBYTE pKeyState)
299{
300 DWORD i, dwModBits = 0;
301
302 /* DumpKeyState( KeyState ); */
303
304 for (i = 0; pKbdTbl->pCharModifiers->pVkToBit[i].Vk; i++)
305 if (IS_KEY_DOWN(pKeyState, pKbdTbl->pCharModifiers->pVkToBit[i].Vk))
306 dwModBits |= pKbdTbl->pCharModifiers->pVkToBit[i].ModBits;
307
308 TRACE("Current Mod Bits: %lx\n", dwModBits);
309
310 return dwModBits;
311}
312
313/*
314 * IntTranslateChar
315 *
316 * Translates virtual key to character
317 */
318static
319BOOL
321 PBYTE pKeyState,
322 PBOOL pbDead,
323 PBOOL pbLigature,
324 PWCHAR pwcTranslatedChar,
325 PKBDTABLES pKbdTbl)
326{
327 PVK_TO_WCHAR_TABLE pVkToVchTbl;
328 PVK_TO_WCHARS10 pVkToVch;
329 DWORD i, dwModBits, dwVkModBits, dwModNumber = 0;
330 WCHAR wch;
331 BOOL bAltGr;
332 WORD wCaplokAttr;
333
334 dwModBits = pKeyState ? IntGetModBits(pKbdTbl, pKeyState) : 0;
335 bAltGr = pKeyState && (pKbdTbl->fLocaleFlags & KLLF_ALTGR) && IS_KEY_DOWN(pKeyState, VK_RMENU);
336 wCaplokAttr = bAltGr ? CAPLOKALTGR : CAPLOK;
337
338 TRACE("TryToTranslate: %04x %x\n", wVirtKey, dwModBits);
339
340 /* If ALT without CTRL has ben used, remove ALT flag */
341 if ((dwModBits & (KBDALT|KBDCTRL)) == KBDALT)
342 dwModBits &= ~KBDALT;
343
344 if (dwModBits > pKbdTbl->pCharModifiers->wMaxModBits)
345 {
346 TRACE("dwModBits %x > wMaxModBits %x\n", dwModBits, pKbdTbl->pCharModifiers->wMaxModBits);
347 return FALSE;
348 }
349
350 for (i = 0; pKbdTbl->pVkToWcharTable[i].pVkToWchars; i++)
351 {
352 pVkToVchTbl = &pKbdTbl->pVkToWcharTable[i];
353 pVkToVch = (PVK_TO_WCHARS10)(pVkToVchTbl->pVkToWchars);
354 while (pVkToVch->VirtualKey)
355 {
356 if (wVirtKey == (pVkToVch->VirtualKey & 0xFF))
357 {
358 dwVkModBits = dwModBits;
359
360 /* If CapsLock is enabled for this key and locked, add SHIFT bit */
361 if ((pVkToVch->Attributes & wCaplokAttr) &&
362 pKeyState &&
363 IS_KEY_LOCKED(pKeyState, VK_CAPITAL))
364 {
365 /* Note: we use special value here instead of getting VK_SHIFT mod bit - it's verified */
366 dwVkModBits ^= KBDSHIFT;
367 }
368
369 if (dwVkModBits > pKbdTbl->pCharModifiers->wMaxModBits)
370 break;
371
372 /* Get modification number */
373 dwModNumber = pKbdTbl->pCharModifiers->ModNumber[dwVkModBits];
374 if (dwModNumber >= pVkToVchTbl->nModifications)
375 {
376 TRACE("dwModNumber %u >= nModifications %u\n", dwModNumber, pVkToVchTbl->nModifications);
377 break;
378 }
379
380 /* Read character */
381 wch = pVkToVch->wch[dwModNumber];
382 if (wch == WCH_NONE)
383 break;
384
385 *pbDead = (wch == WCH_DEAD);
386 *pbLigature = (wch == WCH_LGTR);
387 *pwcTranslatedChar = wch;
388
389 TRACE("%lu %04x: dwModNumber %08x Char %04x\n",
390 i, wVirtKey, dwModNumber, wch);
391
392 if (*pbDead)
393 {
394 /* After WCH_DEAD, real character is located */
395 pVkToVch = (PVK_TO_WCHARS10)(((BYTE *)pVkToVch) + pVkToVchTbl->cbSize);
396 if (pVkToVch->VirtualKey != 0xFF)
397 {
398 WARN("Found dead key with no trailer in the table.\n");
399 WARN("VK: %04x, ADDR: %p\n", wVirtKey, pVkToVch);
400 break;
401 }
402 *pwcTranslatedChar = pVkToVch->wch[dwModNumber];
403 }
404 return TRUE;
405 }
406 pVkToVch = (PVK_TO_WCHARS10)(((BYTE *)pVkToVch) + pVkToVchTbl->cbSize);
407 }
408 }
409
410 /* If nothing has been found in layout, check if this is ASCII control character.
411 Note: we could add it to layout table, but windows does not have it there */
412 if (wVirtKey >= 'A' && wVirtKey <= 'Z' &&
413 pKeyState && IS_KEY_DOWN(pKeyState, VK_CONTROL) &&
414 !IS_KEY_DOWN(pKeyState, VK_MENU))
415 {
416 *pwcTranslatedChar = (wVirtKey - 'A') + 1; /* ASCII control character */
417 *pbDead = FALSE;
418 *pbLigature = FALSE;
419 return TRUE;
420 }
421
422 return FALSE;
423}
424
425/*
426 * IntToUnicodeEx
427 *
428 * Translates virtual key to characters
429 */
430static
431int APIENTRY
433 UINT wScanCode,
434 PBYTE pKeyState,
435 LPWSTR pwszBuff,
436 int cchBuff,
437 UINT wFlags,
438 PKBDTABLES pKbdTbl)
439{
440 WCHAR wchTranslatedChar;
441 BOOL bDead, bLigature;
442 static WCHAR wchDead = 0;
443 int iRet = 0;
444
445 ASSERT(pKbdTbl);
446
447 if (!IntTranslateChar(wVirtKey,
448 pKeyState,
449 &bDead,
450 &bLigature,
451 &wchTranslatedChar,
452 pKbdTbl))
453 {
454 return 0;
455 }
456
457 if (bLigature)
458 {
459 WARN("Not handling ligature (yet)\n" );
460 return 0;
461 }
462
463 /* If we got dead char in previous call check dead keys in keyboard layout */
464 if (wchDead)
465 {
466 UINT i;
467 WCHAR wchFirst, wchSecond;
468 TRACE("Previous dead char: %lc (%x)\n", wchDead, wchDead);
469
470 if (pKbdTbl->pDeadKey)
471 {
472 for (i = 0; pKbdTbl->pDeadKey[i].dwBoth; i++)
473 {
474 wchFirst = pKbdTbl->pDeadKey[i].dwBoth >> 16;
475 wchSecond = pKbdTbl->pDeadKey[i].dwBoth & 0xFFFF;
476 if (wchFirst == wchDead && wchSecond == wchTranslatedChar)
477 {
478 wchTranslatedChar = pKbdTbl->pDeadKey[i].wchComposed;
479 wchDead = 0;
480 bDead = FALSE;
481 break;
482 }
483 }
484 }
485 else
486 {
487#if defined(__GNUC__)
488 if (wchDead == 0x8000)
489 {
490 ERR("GCC is inventing bits, ignoring fake dead key\n");
491 wchDead = 0;
492 }
493#endif
494 }
495
496 TRACE("Final char: %lc (%x)\n", wchTranslatedChar, wchTranslatedChar);
497 }
498
499 /* Dead char has not been not found */
500 if (wchDead)
501 {
502 /* Treat both characters normally */
503 if (cchBuff > iRet)
504 pwszBuff[iRet++] = wchDead;
505 bDead = FALSE;
506 }
507
508 /* Add character to the buffer */
509 if (cchBuff > iRet)
510 pwszBuff[iRet++] = wchTranslatedChar;
511
512 /* Save dead character */
513 wchDead = bDead ? wchTranslatedChar : 0;
514
515 return bDead ? -iRet : iRet;
516}
517
518/*
519 * IntVkToVsc
520 *
521 * Translates virtual key to scan code
522 */
523static
526{
527 unsigned i;
528
529 ASSERT(pKbdTbl);
530
531 /* Check standard keys first */
532 for (i = 0; i < pKbdTbl->bMaxVSCtoVK; i++)
533 {
534 if ((pKbdTbl->pusVSCtoVK[i] & 0xFF) == wVk)
535 return i;
536 }
537
538 /* Check extended keys now */
539 for (i = 0; pKbdTbl->pVSCtoVK_E0[i].Vsc; i++)
540 {
541 if ((pKbdTbl->pVSCtoVK_E0[i].Vk & 0xFF) == wVk)
542 return 0xE000 | pKbdTbl->pVSCtoVK_E0[i].Vsc;
543 }
544
545 for (i = 0; pKbdTbl->pVSCtoVK_E1[i].Vsc; i++)
546 {
547 if ((pKbdTbl->pVSCtoVK_E1[i].Vk & 0xFF) == wVk)
548 return 0xE100 | pKbdTbl->pVSCtoVK_E1[i].Vsc;
549 }
550
551 /* Virtual key has not been found */
552 return 0;
553}
554
555/*
556 * IntVscToVk
557 *
558 * Translates prefixed scancode to virtual key
559 */
560static
562IntVscToVk(WORD wScanCode, PKBDTABLES pKbdTbl)
563{
564 unsigned i;
565 WORD wVk = 0;
566
567 ASSERT(pKbdTbl);
568
569 if ((wScanCode & 0xFF00) == 0xE000)
570 {
571 for (i = 0; pKbdTbl->pVSCtoVK_E0[i].Vsc; i++)
572 {
573 if (pKbdTbl->pVSCtoVK_E0[i].Vsc == (wScanCode & 0xFF))
574 {
575 wVk = pKbdTbl->pVSCtoVK_E0[i].Vk;
576 }
577 }
578 }
579 else if ((wScanCode & 0xFF00) == 0xE100)
580 {
581 for (i = 0; pKbdTbl->pVSCtoVK_E1[i].Vsc; i++)
582 {
583 if (pKbdTbl->pVSCtoVK_E1[i].Vsc == (wScanCode & 0xFF))
584 {
585 wVk = pKbdTbl->pVSCtoVK_E1[i].Vk;
586 }
587 }
588 }
589 else if (wScanCode < pKbdTbl->bMaxVSCtoVK)
590 {
591 wVk = pKbdTbl->pusVSCtoVK[wScanCode];
592 }
593
594 /* 0xFF nad 0x00 are invalid VKs */
595 return wVk != 0xFF ? wVk : 0;
596}
597
598/*
599 * IntVkToChar
600 *
601 * Translates virtual key to character, ignoring shift state
602 */
603static
606{
607 WCHAR wch;
608 BOOL bDead, bLigature;
609
610 ASSERT(pKbdTbl);
611
612 if (IntTranslateChar(wVk,
613 NULL,
614 &bDead,
615 &bLigature,
616 &wch,
617 pKbdTbl))
618 {
619 return wch;
620 }
621
622 return 0;
623}
624
625/*
626 * NtUserGetAsyncKeyState
627 *
628 * Gets key state from global bitmap
629 */
630SHORT
633{
634 WORD wRet = 0;
635
636 TRACE("Enter NtUserGetAsyncKeyState\n");
637
638 if (Key >= 0x100 || Key < 0)
639 {
641 ERR("Invalid parameter Key\n");
642 return 0;
643 }
644
646
648 wRet |= 0x8000; // If down, windows returns 0x8000.
649 if (gafAsyncKeyStateRecentDown[Key / 8] & (1 << (Key % 8)))
650 wRet |= 0x1;
651 gafAsyncKeyStateRecentDown[Key / 8] &= ~(1 << (Key % 8));
652
653 UserLeave();
654
655 TRACE("Leave NtUserGetAsyncKeyState, ret=%u\n", wRet);
656 return wRet;
657}
658
659/*
660 * UpdateAsyncKeyState
661 *
662 * Updates gafAsyncKeyState array
663 */
664static
667{
668 if (bIsDown)
669 {
670 /* If it's first key down event, xor lock bit */
671 if (!IS_KEY_DOWN(gafAsyncKeyState, wVk))
673
675 gafAsyncKeyStateRecentDown[wVk / 8] |= (1 << (wVk % 8));
676 }
677 else
679}
680
681/*
682 * co_CallLowLevelKeyboardHook
683 *
684 * Calls WH_KEYBOARD_LL hook
685 */
686static LRESULT
687co_CallLowLevelKeyboardHook(WORD wVk, WORD wScanCode, DWORD dwFlags, BOOL bInjected, DWORD dwTime, DWORD dwExtraInfo)
688{
689 KBDLLHOOKSTRUCT KbdHookData;
690 UINT uMsg;
691
692 KbdHookData.vkCode = wVk;
693 KbdHookData.scanCode = wScanCode;
694 KbdHookData.flags = 0;
696 KbdHookData.flags |= LLKHF_EXTENDED;
698 KbdHookData.flags |= LLKHF_ALTDOWN;
700 KbdHookData.flags |= LLKHF_UP;
701 if (bInjected)
702 KbdHookData.flags |= LLKHF_INJECTED;
703 KbdHookData.time = dwTime;
704 KbdHookData.dwExtraInfo = dwExtraInfo;
705
706 /* Note: it doesnt support WM_SYSKEYUP */
708 uMsg = WM_KEYUP;
710 uMsg = WM_SYSKEYDOWN;
711 else
712 uMsg = WM_KEYDOWN;
713
714 return co_HOOK_CallHooks(WH_KEYBOARD_LL, HC_ACTION, uMsg, (LPARAM)&KbdHookData);
715}
716
717/*
718 * SnapWindow
719 *
720 * Saves snapshot of specified window or whole screen in the clipboard
721 */
722static VOID
724{
725 HBITMAP hbm = NULL, hbmOld;
726 HDC hdc = NULL, hdcMem;
727 SETCLIPBDATA scd;
728 INT cx, cy;
729 PWND pWnd = NULL;
730
731 TRACE("SnapWindow(%p)\n", hWnd);
732
733 /* If no windows is given, make snapshot of desktop window */
734 if (!hWnd)
736
738 if (!pWnd)
739 {
740 ERR("Invalid window\n");
741 goto cleanup;
742 }
743
745 if (!hdc)
746 {
747 ERR("UserGetDCEx failed!\n");
748 goto cleanup;
749 }
750
751 cx = pWnd->rcWindow.right - pWnd->rcWindow.left;
752 cy = pWnd->rcWindow.bottom - pWnd->rcWindow.top;
753
755 if (!hbm)
756 {
757 ERR("NtGdiCreateCompatibleBitmap failed!\n");
758 goto cleanup;
759 }
760
762 if (!hdcMem)
763 {
764 ERR("NtGdiCreateCompatibleDC failed!\n");
765 goto cleanup;
766 }
767
768 hbmOld = NtGdiSelectBitmap(hdcMem, hbm);
769 NtGdiBitBlt(hdcMem, 0, 0, cx, cy, hdc, 0, 0, SRCCOPY, 0, 0);
770 NtGdiSelectBitmap(hdcMem, hbmOld);
772
773 /* Save snapshot in clipboard */
775 {
778 scd.fGlobalHandle = FALSE;
780 {
781 /* Bitmap is managed by system now */
782 hbm = NULL;
783 }
785 }
786
787cleanup:
788 if (hbm)
790 if (hdc)
791 UserReleaseDC(pWnd, hdc, FALSE);
792}
793
794/*
795 * UserSendKeyboardInput
796 *
797 * Process keyboard input from input devices and SendInput API
798 */
800ProcessKeyEvent(WORD wVk, WORD wScanCode, DWORD dwFlags, BOOL bInjected, DWORD dwTime, DWORD dwExtraInfo)
801{
802 WORD wSimpleVk = 0, wFixedVk, wVk2;
803 PUSER_MESSAGE_QUEUE pFocusQueue;
804 PTHREADINFO pti;
806 BOOL bIsDown = (dwFlags & KEYEVENTF_KEYUP) ? FALSE : TRUE;
807 BOOL bPacket = (dwFlags & KEYEVENTF_UNICODE) ? TRUE : FALSE;
808 BOOL bWasSimpleDown = FALSE, bPostMsg = TRUE, bIsSimpleDown;
809 MSG Msg;
810 static BOOL bMenuDownRecently = FALSE;
811
812 /* Get virtual key without shifts (VK_(L|R)* -> VK_*) */
813 wSimpleVk = IntSimplifyVk(wVk);
814
816 {
817 /* Japanese special! */
819 {
820 if (wSimpleVk == VK_OEM_ATTN)
821 wSimpleVk = VK_CAPITAL;
822 else if (wSimpleVk == VK_OEM_COPY)
823 wSimpleVk = VK_OEM_FINISH;
824 }
825 }
826
827 bWasSimpleDown = IS_KEY_DOWN(gafAsyncKeyState, wSimpleVk);
828
829 /* Update key without shifts */
830 wVk2 = IntFixVk(wSimpleVk, !bExt);
831 bIsSimpleDown = bIsDown || IS_KEY_DOWN(gafAsyncKeyState, wVk2);
832 UpdateAsyncKeyState(wSimpleVk, bIsSimpleDown);
833
834 if (bIsDown)
835 {
836 /* Update keyboard LEDs */
838 wSimpleVk,
839 wScanCode);
840 }
841
842 /* Call WH_KEYBOARD_LL hook */
843 if (co_CallLowLevelKeyboardHook(wVk, wScanCode, dwFlags, bInjected, dwTime, dwExtraInfo))
844 {
845 ERR("Kbd msg dropped by WH_KEYBOARD_LL hook\n");
846 bPostMsg = FALSE;
847 }
848
849 /* Check if this is a hotkey */
850 if (co_UserProcessHotKeys(wSimpleVk, bIsDown))
851 {
852 TRACE("HotKey Processed\n");
853 bPostMsg = FALSE;
854 }
855
856 wFixedVk = IntFixVk(wSimpleVk, bExt); /* LSHIFT + EXT = RSHIFT */
857 if (wSimpleVk == VK_SHIFT) /* shift can't be extended */
858 bExt = FALSE;
859
860 /* If we have a focus queue, post a keyboard message */
861 pFocusQueue = IntGetFocusMessageQueue();
862 TRACE("ProcessKeyEvent Q 0x%p Active pWnd 0x%p Focus pWnd 0x%p\n",
863 pFocusQueue,
864 (pFocusQueue ? pFocusQueue->spwndActive : 0),
865 (pFocusQueue ? pFocusQueue->spwndFocus : 0));
866
867 /* If it is F10 or ALT is down and CTRL is up, it's a system key */
868 if ( wVk == VK_F10 ||
869 (wSimpleVk == VK_MENU && bMenuDownRecently) ||
872 // See MSDN WM_SYSKEYDOWN/UP fixes last wine Win test_keyboard_input.
873 (pFocusQueue && !pFocusQueue->spwndFocus) )
874 {
875 bMenuDownRecently = FALSE; // reset
876 if (bIsDown)
877 {
878 Msg.message = WM_SYSKEYDOWN;
879 if (wSimpleVk == VK_MENU)
880 {
881 // Note: If only LALT is pressed WM_SYSKEYUP is generated instead of WM_KEYUP
882 bMenuDownRecently = TRUE;
883 }
884 }
885 else
886 Msg.message = WM_SYSKEYUP;
887 }
888 else
889 {
890 if (bIsDown)
891 Msg.message = WM_KEYDOWN;
892 else
893 Msg.message = WM_KEYUP;
894 }
895
896 /* Update async state of not simplified vk here.
897 See user32_apitest:GetKeyState */
898 UpdateAsyncKeyState(wFixedVk, bIsDown);
899
900 /* Alt-Tab/Esc Check. Use FocusQueue or RIT Queue */
901 if (bIsSimpleDown && !bWasSimpleDown &&
904 (wVk == VK_ESCAPE || wVk == VK_TAB))
905 {
906 TRACE("Alt-Tab/Esc Pressed wParam %x\n",wVk);
907 }
908
909 if (bIsDown && wVk == VK_SNAPSHOT)
910 {
911 if (pFocusQueue &&
914 {
915 // Snap from Active Window, Focus can be null.
916 SnapWindow(pFocusQueue->spwndActive ? UserHMGetHandle(pFocusQueue->spwndActive) : 0);
917 }
918 else
919 SnapWindow(NULL); // Snap Desktop.
920 }
921 else if (pFocusQueue && bPostMsg)
922 {
923 PWND Wnd = pFocusQueue->spwndFocus; // SysInit.....
924
925 pti = pFocusQueue->ptiKeyboard;
926
927 if (!Wnd && pFocusQueue->spwndActive) // SysInit.....
928 {
929 // Going with Active. WM_SYSKEYXXX last wine Win test_keyboard_input.
930 Wnd = pFocusQueue->spwndActive;
931 }
932 if (Wnd) pti = Wnd->head.pti;
933
934 /* Init message */
935 Msg.hwnd = Wnd ? UserHMGetHandle(Wnd) : NULL;
936 Msg.wParam = wFixedVk & 0xFF; /* Note: It's simplified by msg queue */
937 Msg.lParam = MAKELPARAM(1, wScanCode);
938 Msg.time = dwTime;
939 Msg.pt = gpsi->ptCursor;
940
941 if ( Msg.message == WM_KEYDOWN || Msg.message == WM_SYSKEYDOWN )
942 {
943 if ( (Msg.wParam == VK_SHIFT ||
944 Msg.wParam == VK_CONTROL ||
945 Msg.wParam == VK_MENU ) &&
947 {
948 ERR("Set last input\n");
949 //ptiLastInput = pti;
950 }
951 }
952
953 /* If it is VK_PACKET, high word of wParam is used for wchar */
954 if (!bPacket)
955 {
956 if (bExt)
957 Msg.lParam |= KF_EXTENDED << 16;
959 Msg.lParam |= KF_ALTDOWN << 16;
960 if (bWasSimpleDown)
961 Msg.lParam |= KF_REPEAT << 16;
962 if (!bIsDown)
963 Msg.lParam |= KF_UP << 16;
964 /* FIXME: Set KF_DLGMODE and KF_MENUMODE when needed */
965 if (pFocusQueue->QF_flags & QF_DIALOGACTIVE)
966 Msg.lParam |= KF_DLGMODE << 16;
967 if (pFocusQueue->MenuOwner) // pti->pMenuState->fMenuStarted
968 Msg.lParam |= KF_MENUMODE << 16;
969 }
970
971 // Post mouse move before posting key buttons, to keep it syned.
972 if (pFocusQueue->QF_flags & QF_MOUSEMOVED)
973 {
975 }
976
977 /* Post a keyboard message */
978 TRACE("Posting keyboard msg %u wParam 0x%x lParam 0x%x\n", Msg.message, Msg.wParam, Msg.lParam);
979 if (!Wnd) {ERR("Window is NULL\n");}
980 MsqPostMessage(pti, &Msg, TRUE, QS_KEY, 0, dwExtraInfo);
981 }
982 return TRUE;
983}
984
987{
988 WORD wScanCode, wVk;
989 PKL pKl = NULL;
990 PKBDTABLES pKbdTbl;
991 PUSER_MESSAGE_QUEUE pFocusQueue;
993 BOOL bExt = (pKbdInput->dwFlags & KEYEVENTF_EXTENDEDKEY) ? TRUE : FALSE;
994
996
997 /* Find the target thread whose locale is in effect */
998 pFocusQueue = IntGetFocusMessageQueue();
999
1000 if (pFocusQueue && pFocusQueue->ptiKeyboard)
1001 {
1002 pKl = pFocusQueue->ptiKeyboard->KeyboardLayout;
1003 }
1004
1005 if (!pKl)
1007 if (!pKl)
1008 {
1009 ERR("No keyboard layout!\n");
1010 return FALSE;
1011 }
1012
1013 pKbdTbl = pKl->spkf->pKbdTbl;
1014
1015 /* Note: wScan field is always used */
1016 wScanCode = pKbdInput->wScan;
1017
1018 if (pKbdInput->dwFlags & KEYEVENTF_UNICODE)
1019 {
1020 /* Generate WM_KEYDOWN msg with wParam == VK_PACKET and
1021 high order word of lParam == pKbdInput->wScan */
1022 wVk = VK_PACKET;
1023 }
1024 else
1025 {
1026 wScanCode &= 0x7F;
1027 if (pKbdInput->dwFlags & KEYEVENTF_SCANCODE)
1028 {
1029 /* Don't ignore invalid scan codes */
1030 wVk = IntVscToVk(wScanCode | (bExt ? 0xE000 : 0), pKbdTbl);
1031 if (!wVk) /* use 0xFF if vsc is invalid */
1032 wVk = 0xFF;
1033 }
1034 else
1035 {
1036 wVk = pKbdInput->wVk;
1037 }
1038
1039 /* Remove all virtual key flags (KBDEXT, KBDMULTIVK, KBDSPECIAL, KBDNUMPAD) */
1040 wVk &= 0xFF;
1041 }
1042
1043 /* If time is given, use it */
1044 if (pKbdInput->time)
1045 dwTime = pKbdInput->time;
1046 else
1047 {
1049 }
1050
1051 if (wVk == VK_RMENU && (pKbdTbl->fLocaleFlags & KLLF_ALTGR))
1052 {
1053 /* For AltGr keyboards RALT generates CTRL events */
1054 ProcessKeyEvent(VK_LCONTROL, 0, pKbdInput->dwFlags & KEYEVENTF_KEYUP, bInjected, dwTime, 0);
1055 }
1056
1057 /* Finally process this key */
1058 return ProcessKeyEvent(wVk, wScanCode, pKbdInput->dwFlags, bInjected, dwTime, pKbdInput->dwExtraInfo);
1059}
1060
1061/*
1062 * UserProcessKeyboardInput
1063 *
1064 * Process raw keyboard input data
1065 */
1066VOID NTAPI
1068 PKEYBOARD_INPUT_DATA pKbdInputData)
1069{
1070 WORD wScanCode, wVk;
1071 PKL pKl = NULL;
1072 PKBDTABLES pKbdTbl;
1073 PUSER_MESSAGE_QUEUE pFocusQueue;
1074
1075 /* Calculate scan code with prefix */
1076 wScanCode = pKbdInputData->MakeCode & 0x7F;
1077 if (pKbdInputData->Flags & KEY_E0)
1078 wScanCode |= 0xE000;
1079 if (pKbdInputData->Flags & KEY_E1)
1080 wScanCode |= 0xE100;
1081
1082 /* Find the target thread whose locale is in effect */
1083 pFocusQueue = IntGetFocusMessageQueue();
1084
1085 if (pFocusQueue && pFocusQueue->ptiKeyboard)
1086 {
1087 pKl = pFocusQueue->ptiKeyboard->KeyboardLayout;
1088 }
1089
1090 if (!pKl)
1092 if (!pKl)
1093 return;
1094
1095 pKbdTbl = pKl->spkf->pKbdTbl;
1096
1097 /* Convert scan code to virtual key.
1098 Note: We could call UserSendKeyboardInput using scan code,
1099 but it wouldn't interpret E1 key(s) properly */
1100 wVk = IntVscToVk(wScanCode, pKbdTbl);
1101 TRACE("UserProcessKeyboardInput: %x (break: %u) -> %x\n",
1102 wScanCode, (pKbdInputData->Flags & KEY_BREAK) ? 1u : 0, wVk);
1103
1104 if (wVk)
1105 {
1106 KEYBDINPUT KbdInput;
1107
1108 /* Support numlock */
1110 {
1111 wVk = IntTranslateNumpadKey(wVk & 0xFF);
1112 }
1113
1114 /* Send keyboard input */
1115 KbdInput.wVk = wVk & 0xFF;
1116 KbdInput.wScan = wScanCode & 0x7F;
1117 KbdInput.dwFlags = 0;
1118 if (pKbdInputData->Flags & KEY_BREAK)
1119 KbdInput.dwFlags |= KEYEVENTF_KEYUP;
1120
1121 if (wVk & KBDEXT)
1122 KbdInput.dwFlags |= KEYEVENTF_EXTENDEDKEY;
1123 //
1124 // Based on wine input:test_Input_blackbox this is okay. It seems the
1125 // bit did not get set and more research is needed. Now the right
1126 // shift works.
1127 //
1128 if (wVk == VK_RSHIFT)
1129 KbdInput.dwFlags |= KEYEVENTF_EXTENDEDKEY;
1130
1131 KbdInput.time = 0;
1132 KbdInput.dwExtraInfo = pKbdInputData->ExtraInformation;
1133 UserSendKeyboardInput(&KbdInput, FALSE);
1134
1135 /* E1 keys don't have break code */
1136 if (pKbdInputData->Flags & KEY_E1)
1137 {
1138 /* Send key up event */
1139 KbdInput.dwFlags |= KEYEVENTF_KEYUP;
1140 UserSendKeyboardInput(&KbdInput, FALSE);
1141 }
1142 }
1143}
1144
1145/*
1146 * IntTranslateKbdMessage
1147 *
1148 * Addes WM_(SYS)CHAR messages to message queue if message
1149 * describes key which produce character.
1150 */
1153 UINT flags)
1154{
1155 PTHREADINFO pti;
1156 INT cch = 0, i;
1157 WCHAR wch[3] = { 0 };
1158 MSG NewMsg = { 0 };
1159 PKBDTABLES pKbdTbl;
1160 BOOL bResult = FALSE;
1161
1162 switch(lpMsg->message)
1163 {
1164 case WM_KEYDOWN:
1165 case WM_KEYUP:
1166 case WM_SYSKEYDOWN:
1167 case WM_SYSKEYUP:
1168 break;
1169 default:
1170 return FALSE;
1171 }
1172
1174
1175 if (!pti->KeyboardLayout)
1176 {
1177 PKL pDefKL = W32kGetDefaultKeyLayout();
1178 UserAssignmentLock((PVOID*)&(pti->KeyboardLayout), pDefKL);
1179 if (pDefKL)
1180 {
1181 pti->pClientInfo->hKL = pDefKL->hkl;
1182 pKbdTbl = pDefKL->spkf->pKbdTbl;
1183 }
1184 else
1185 {
1186 pti->pClientInfo->hKL = NULL;
1187 pKbdTbl = NULL;
1188 }
1189 }
1190 else
1191 pKbdTbl = pti->KeyboardLayout->spkf->pKbdTbl;
1192 if (!pKbdTbl)
1193 return FALSE;
1194
1195 if (lpMsg->message != WM_KEYDOWN && lpMsg->message != WM_SYSKEYDOWN)
1196 return FALSE;
1197
1198 /* Init pt, hwnd and time msg fields */
1199 NewMsg.pt = gpsi->ptCursor;
1200 NewMsg.hwnd = lpMsg->hwnd;
1201 NewMsg.time = EngGetTickCount32();
1202
1203 TRACE("Enter IntTranslateKbdMessage msg %s, vk %x\n",
1204 lpMsg->message == WM_SYSKEYDOWN ? "WM_SYSKEYDOWN" : "WM_KEYDOWN", lpMsg->wParam);
1205
1206 if (lpMsg->wParam == VK_PACKET)
1207 {
1208 NewMsg.message = (lpMsg->message == WM_KEYDOWN) ? WM_CHAR : WM_SYSCHAR;
1209 NewMsg.wParam = HIWORD(lpMsg->lParam);
1210 NewMsg.lParam = LOWORD(lpMsg->lParam);
1211 MsqPostMessage(pti, &NewMsg, FALSE, QS_KEY, 0, 0);
1212 return TRUE;
1213 }
1214
1215 cch = IntToUnicodeEx(lpMsg->wParam,
1216 HIWORD(lpMsg->lParam) & 0xFF,
1217 pti->MessageQueue->afKeyState,
1218 wch,
1219 sizeof(wch) / sizeof(wch[0]),
1220 0,
1221 pKbdTbl);
1222
1223 if (cch)
1224 {
1225 if (cch > 0) /* Normal characters */
1226 NewMsg.message = (lpMsg->message == WM_KEYDOWN) ? WM_CHAR : WM_SYSCHAR;
1227 else /* Dead character */
1228 {
1229 cch = -cch;
1230 NewMsg.message =
1232 }
1233 NewMsg.lParam = lpMsg->lParam;
1234
1235 /* Send all characters */
1236 for (i = 0; i < cch; ++i)
1237 {
1238 TRACE("Msg: %x '%lc' (%04x) %08x\n", NewMsg.message, wch[i], wch[i], NewMsg.lParam);
1239 NewMsg.wParam = wch[i];
1240 MsqPostMessage(pti, &NewMsg, FALSE, QS_KEY, 0, 0);
1241 }
1242 bResult = TRUE;
1243 }
1244
1245 TRACE("Leave IntTranslateKbdMessage ret %d, cch %d, msg %x, wch %x\n",
1246 bResult, cch, NewMsg.message, NewMsg.wParam);
1247 return bResult;
1248}
1249
1250/*
1251 * Map a virtual key code, or virtual scan code, to a scan code, key code,
1252 * or unshifted unicode character.
1253 *
1254 * Code: See Below
1255 * Type:
1256 * 0 -- Code is a virtual key code that is converted into a virtual scan code
1257 * that does not distinguish between left and right shift keys.
1258 * 1 -- Code is a virtual scan code that is converted into a virtual key code
1259 * that does not distinguish between left and right shift keys.
1260 * 2 -- Code is a virtual key code that is converted into an unshifted unicode
1261 * character.
1262 * 3 -- Code is a virtual scan code that is converted into a virtual key code
1263 * that distinguishes left and right shift keys.
1264 * KeyLayout: Keyboard layout handle
1265 *
1266 * @implemented
1267 */
1268static UINT
1270{
1271 UINT uRet = 0;
1272
1273 switch (Type)
1274 {
1275 case MAPVK_VK_TO_VSC:
1276 uCode = IntFixVk(uCode, FALSE);
1277 uRet = IntVkToVsc(uCode, pKbdTbl);
1278 if (uRet > 0xFF) // Fail for scancodes with prefix (e0, e1)
1279 uRet = 0;
1280 break;
1281
1282 case MAPVK_VSC_TO_VK:
1283 uRet = IntVscToVk(uCode, pKbdTbl) & 0xFF;
1284 uRet = IntSimplifyVk(uRet);
1285 break;
1286
1287 case MAPVK_VK_TO_CHAR:
1288 uRet = (UINT)IntVkToChar(uCode, pKbdTbl);
1289 break;
1290
1291 case MAPVK_VSC_TO_VK_EX:
1292 uRet = IntVscToVk(uCode, pKbdTbl) & 0xFF;
1293 break;
1294
1295 case MAPVK_VK_TO_VSC_EX:
1296 uRet = IntVkToVsc(uCode, pKbdTbl);
1297 break;
1298
1299 default:
1301 ERR("Wrong type value: %u\n", Type);
1302 }
1303
1304 return uRet;
1305}
1306
1307/*
1308 * NtUserMapVirtualKeyEx
1309 *
1310 * Map a virtual key code, or virtual scan code, to a scan code, key code,
1311 * or unshifted unicode character. See IntMapVirtualKeyEx.
1312 */
1313UINT
1315NtUserMapVirtualKeyEx(UINT uCode, UINT uType, DWORD keyboardId, HKL dwhkl)
1316{
1317 PKBDTABLES pKbdTbl = NULL;
1318 UINT ret = 0;
1319
1320 TRACE("Enter NtUserMapVirtualKeyEx\n");
1322
1323 if (!dwhkl)
1324 {
1325 PTHREADINFO pti;
1326
1328 if (pti && pti->KeyboardLayout)
1329 pKbdTbl = pti->KeyboardLayout->spkf->pKbdTbl;
1330 }
1331 else
1332 {
1333 PKL pKl;
1334
1335 pKl = UserHklToKbl(dwhkl);
1336 if (pKl)
1337 pKbdTbl = pKl->spkf->pKbdTbl;
1338 }
1339
1340 if (pKbdTbl)
1341 ret = IntMapVirtualKeyEx(uCode, uType, pKbdTbl);
1342
1343 UserLeave();
1344 TRACE("Leave NtUserMapVirtualKeyEx, ret=%u\n", ret);
1345 return ret;
1346}
1347
1348/*
1349 * NtUserToUnicodeEx
1350 *
1351 * Translates virtual key to characters
1352 */
1353int
1356 UINT wVirtKey,
1357 UINT wScanCode,
1358 PBYTE pKeyStateUnsafe,
1359 LPWSTR pwszBuffUnsafe,
1360 INT cchBuff,
1361 UINT wFlags,
1362 HKL dwhkl)
1363{
1364 PTHREADINFO pti;
1365 BYTE afKeyState[256 * 2 / 8] = {0};
1366 PWCHAR pwszBuff = NULL;
1367 INT i, iRet = 0;
1368 PKL pKl = NULL;
1370
1371 TRACE("Enter NtUserSetKeyboardState\n");
1372
1373 /* Return 0 if SC_KEY_UP bit is set */
1374 if (wScanCode & SC_KEY_UP || wVirtKey >= 0x100)
1375 {
1376 ERR("Invalid parameter\n");
1377 return 0;
1378 }
1379
1380 _SEH2_TRY
1381 {
1382 /* Probe and copy key state to smaller bitmap */
1383 ProbeForRead(pKeyStateUnsafe, 256 * sizeof(BYTE), 1);
1384 for (i = 0; i < 256; ++i)
1385 {
1386 if (pKeyStateUnsafe[i] & KS_DOWN_BIT)
1387 SET_KEY_DOWN(afKeyState, i, TRUE);
1388 if (pKeyStateUnsafe[i] & KS_LOCK_BIT)
1389 SET_KEY_LOCKED(afKeyState, i, TRUE);
1390 }
1391 }
1393 {
1394 ERR("Cannot copy key state\n");
1396 _SEH2_YIELD(return 0);
1397 }
1398 _SEH2_END;
1399
1400 pwszBuff = ExAllocatePoolWithTag(NonPagedPool, sizeof(WCHAR) * cchBuff, TAG_STRING);
1401 if (!pwszBuff)
1402 {
1403 ERR("ExAllocatePoolWithTag(%u) failed\n", sizeof(WCHAR) * cchBuff);
1404 return 0;
1405 }
1406 RtlZeroMemory(pwszBuff, sizeof(WCHAR) * cchBuff);
1407
1408 UserEnterExclusive(); // Note: We modify wchDead static variable
1409
1410 if (dwhkl)
1411 pKl = UserHklToKbl(dwhkl);
1412
1413 if (!pKl)
1414 {
1416 pKl = pti->KeyboardLayout;
1417 }
1418
1419 if (pKl)
1420 {
1421 iRet = IntToUnicodeEx(wVirtKey,
1422 wScanCode,
1423 afKeyState,
1424 pwszBuff,
1425 cchBuff,
1426 wFlags,
1427 pKl->spkf->pKbdTbl);
1428
1429 if (iRet)
1430 {
1431 Status = MmCopyToCaller(pwszBuffUnsafe, pwszBuff, cchBuff * sizeof(WCHAR));
1432 }
1433 }
1434 else
1435 {
1436 ERR("No keyboard layout ?!\n");
1438 }
1439
1440 ExFreePoolWithTag(pwszBuff, TAG_STRING);
1441
1442 if (!NT_SUCCESS(Status))
1443 {
1444 iRet = 0;
1446 }
1447
1448 UserLeave();
1449 TRACE("Leave NtUserSetKeyboardState, ret=%i\n", iRet);
1450 return iRet;
1451}
1452
1453/*
1454 * NtUserGetKeyNameText
1455 *
1456 * Gets key name from keyboard layout
1457 */
1458DWORD
1461{
1462 PTHREADINFO pti;
1463 DWORD i, dwRet = 0;
1464 SIZE_T cchKeyName;
1465 WORD wScanCode = (lParam >> 16) & 0xFF;
1466 BOOL bExtKey = (HIWORD(lParam) & KF_EXTENDED) ? TRUE : FALSE;
1467 PKBDTABLES pKbdTbl;
1468 VSC_LPWSTR *pKeyNames = NULL;
1469 CONST WCHAR *pKeyName = NULL;
1470 WCHAR KeyNameBuf[2];
1471
1472 TRACE("Enter NtUserGetKeyNameText\n");
1473
1475
1476 /* Get current keyboard layout */
1478 pKbdTbl = pti ? pti->KeyboardLayout->spkf->pKbdTbl : 0;
1479
1480 if (!pKbdTbl || cchSize < 1)
1481 {
1482 ERR("Invalid parameter\n");
1483 goto cleanup;
1484 }
1485
1486 /* "Do not care" flag */
1488 {
1489 /* Note: We could do vsc -> vk -> vsc conversion, instead of using
1490 hardcoded scan codes, but it's not what Windows does */
1491 if (wScanCode == SCANCODE_RSHIFT && !bExtKey)
1492 wScanCode = SCANCODE_LSHIFT;
1493 else if (wScanCode == SCANCODE_CTRL || wScanCode == SCANCODE_ALT)
1494 bExtKey = FALSE;
1495 }
1496
1497 if (bExtKey)
1498 pKeyNames = pKbdTbl->pKeyNamesExt;
1499 else
1500 pKeyNames = pKbdTbl->pKeyNames;
1501
1502 for (i = 0; pKeyNames[i].pwsz; i++)
1503 {
1504 if (pKeyNames[i].vsc == wScanCode)
1505 {
1506 pKeyName = pKeyNames[i].pwsz;
1507 break;
1508 }
1509 }
1510
1511 if (!pKeyName)
1512 {
1513 WORD wVk = IntVscToVk(wScanCode, pKbdTbl);
1514
1515 if (wVk)
1516 {
1517 KeyNameBuf[0] = IntVkToChar(wVk, pKbdTbl);
1518 KeyNameBuf[1] = 0;
1519 if (KeyNameBuf[0])
1520 pKeyName = KeyNameBuf;
1521 }
1522 }
1523
1524 if (pKeyName)
1525 {
1526 cchKeyName = wcslen(pKeyName);
1527 if (cchKeyName > (cchSize - 1UL))
1528 cchKeyName = cchSize - 1UL; // Don't count '\0'
1529
1530 _SEH2_TRY
1531 {
1532 ProbeForWrite(lpString, (cchKeyName + 1) * sizeof(WCHAR), 1);
1533 RtlCopyMemory(lpString, pKeyName, cchKeyName * sizeof(WCHAR));
1534 lpString[cchKeyName] = UNICODE_NULL;
1535 dwRet = cchKeyName;
1536 }
1538 {
1540 }
1541 _SEH2_END;
1542 }
1543 else
1544 {
1546 }
1547
1548cleanup:
1549 UserLeave();
1550 TRACE("Leave NtUserGetKeyNameText, ret=%lu\n", dwRet);
1551 return dwRet;
1552}
1553
1554/*
1555 * UserGetKeyboardType
1556 *
1557 * Returns some keyboard specific information
1558 */
1561 DWORD dwTypeFlag)
1562{
1563 switch (dwTypeFlag)
1564 {
1565 case 0: /* Keyboard type */
1567 case 1: /* Keyboard Subtype */
1569 case 2: /* Number of F-keys */
1571 default:
1572 ERR("Unknown type!\n");
1573 return 0; /* Note: we don't have to set last error here */
1574 }
1575}
1576
1577/*
1578 * NtUserVkKeyScanEx
1579 *
1580 * Based on IntTranslateChar, instead of processing VirtualKey match,
1581 * look for wChar match.
1582 */
1583DWORD
1586 WCHAR wch,
1587 HKL dwhkl,
1588 BOOL bUsehKL)
1589{
1590 PKBDTABLES pKbdTbl;
1591 PVK_TO_WCHAR_TABLE pVkToWchTbl;
1592 PVK_TO_WCHARS10 pVkToWch;
1593 PKL pKl = NULL;
1594 DWORD i, dwModBits = 0, dwModNumber = 0, Ret = (DWORD)-1;
1595
1596 TRACE("NtUserVkKeyScanEx() wch %u, KbdLayout 0x%p\n", wch, dwhkl);
1598
1599 if (bUsehKL)
1600 {
1601 // Use given keyboard layout
1602 if (dwhkl)
1603 pKl = UserHklToKbl(dwhkl);
1604 }
1605 else
1606 {
1607 // Use thread keyboard layout
1608 pKl = ((PTHREADINFO)PsGetCurrentThreadWin32Thread())->KeyboardLayout;
1609 }
1610
1611 if (!pKl)
1612 goto Exit;
1613
1614 pKbdTbl = pKl->spkf->pKbdTbl;
1615
1616 // Interate through all VkToWchar tables while pVkToWchars is not NULL
1617 for (i = 0; pKbdTbl->pVkToWcharTable[i].pVkToWchars; i++)
1618 {
1619 pVkToWchTbl = &pKbdTbl->pVkToWcharTable[i];
1620 pVkToWch = (PVK_TO_WCHARS10)(pVkToWchTbl->pVkToWchars);
1621
1622 // Interate through all virtual keys
1623 while (pVkToWch->VirtualKey)
1624 {
1625 for (dwModNumber = 0; dwModNumber < pVkToWchTbl->nModifications; dwModNumber++)
1626 {
1627 if (pVkToWch->wch[dwModNumber] == wch)
1628 {
1629 dwModBits = pKbdTbl->pCharModifiers->ModNumber[dwModNumber];
1630 TRACE("i %lu wC %04x: dwModBits %08x dwModNumber %08x MaxModBits %08x\n",
1631 i, wch, dwModBits, dwModNumber, pKbdTbl->pCharModifiers->wMaxModBits);
1632 Ret = (dwModBits << 8) | (pVkToWch->VirtualKey & 0xFF);
1633 goto Exit;
1634 }
1635 }
1636 pVkToWch = (PVK_TO_WCHARS10)(((BYTE *)pVkToWch) + pVkToWchTbl->cbSize);
1637 }
1638 }
1639Exit:
1640 UserLeave();
1641 return Ret;
1642}
1643
1644/* EOF */
#define DCX_USESTYLE
Definition: GetDCEx.c:10
Type
Definition: Type.h:7
HWND hWnd
Definition: settings.c:17
LONG NTSTATUS
Definition: precomp.h:26
#define CF_BITMAP
Definition: constants.h:397
#define WARN(fmt,...)
Definition: debug.h:112
#define ERR(fmt,...)
Definition: debug.h:110
#define DBG_DEFAULT_CHANNEL(ch)
Definition: debug.h:103
struct @1609 Msg[]
LPARAM lParam
Definition: combotst.c:139
BOOL FASTCALL IntGdiDeleteDC(HDC, BOOL)
Definition: dclife.c:892
#define NULL
Definition: types.h:112
#define TRUE
Definition: types.h:120
#define FALSE
Definition: types.h:117
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
#define APIENTRY
Definition: api.h:79
#define ERROR_INVALID_PARAMETER
Definition: compat.h:101
PSERVERINFO gpsi
Definition: imm.c:18
static void cleanup(void)
Definition: main.c:1335
#define EngGetTickCount32()
Definition: eng.h:43
#define ExAllocatePoolWithTag(hernya, size, tag)
Definition: env_spec_w32.h:350
#define NonPagedPool
Definition: env_spec_w32.h:307
#define PagedPool
Definition: env_spec_w32.h:308
VOID NTAPI ProbeForRead(IN CONST VOID *Address, IN SIZE_T Length, IN ULONG Alignment)
Definition: exintrin.c:102
VOID NTAPI ProbeForWrite(IN PVOID Address, IN SIZE_T Length, IN ULONG Alignment)
Definition: exintrin.c:143
#define _SEH2_END
Definition: filesup.c:22
#define _SEH2_TRY
Definition: filesup.c:19
unsigned int BOOL
Definition: ntddk_ex.h:94
unsigned long DWORD
Definition: ntddk_ex.h:95
unsigned short WORD
Definition: ntddk_ex.h:93
Status
Definition: gdiplustypes.h:25
GLbitfield flags
Definition: glext.h:7161
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint i
Definition: glfuncs.h:248
#define EXCEPTION_EXECUTE_HANDLER
Definition: excpt.h:85
_CRTIMP size_t __cdecl wcslen(_In_z_ const wchar_t *_Str)
#define UserHMGetHandle(obj)
Definition: ntuser.h:230
static CODE_SEG("PAGE")
Definition: isapnp.c:1482
#define WCH_DEAD
Definition: kbd.h:114
#define SCANCODE_LSHIFT
Definition: kbd.h:128
#define SCANCODE_ALT
Definition: kbd.h:131
#define CAPLOK
Definition: kbd.h:118
#define WCH_LGTR
Definition: kbd.h:115
#define KBDALT
Definition: kbd.h:16
#define WCH_NONE
Definition: kbd.h:113
#define CAPLOKALTGR
Definition: kbd.h:120
#define KBDCTRL
Definition: kbd.h:15
#define KBDNUMPAD
Definition: kbd.h:11
#define SCANCODE_RSHIFT
Definition: kbd.h:129
#define KBDEXT
Definition: kbd.h:8
#define KLLF_ALTGR
Definition: kbd.h:91
#define SCANCODE_CTRL
Definition: kbd.h:130
#define KBDSHIFT
Definition: kbd.h:14
#define MmCopyToCaller(x, y, z)
Definition: mmcopy.h:19
#define ASSERT(a)
Definition: mode.c:44
#define ExFreePoolWithTag(_P, _T)
Definition: module.h:1109
PSDBQUERYRESULT_VISTA PVOID DWORD * dwSize
Definition: env.c:56
HDC hdc
Definition: main.c:9
static HBITMAP
Definition: button.c:44
static HDC
Definition: imagelist.c:92
static DWORD DWORD void LPSTR DWORD cch
Definition: str.c:202
UINT_PTR HKL
Definition: msctf.idl:104
VOID FASTCALL IntCoalesceMouseMove(PTHREADINFO pti)
Definition: msgqueue.c:551
VOID FASTCALL MsqPostMessage(PTHREADINFO pti, MSG *Msg, BOOLEAN HardwareMessage, DWORD MessageBits, DWORD dwQEvent, LONG_PTR ExtraInfo)
Definition: msgqueue.c:1337
#define QF_DIALOGACTIVE
Definition: msgqueue.h:106
#define QF_MOUSEMOVED
Definition: msgqueue.h:99
unsigned int UINT
Definition: ndis.h:50
#define FASTCALL
Definition: nt_native.h:50
#define DWORD
Definition: nt_native.h:44
#define UNICODE_NULL
#define KEYBOARD_CAPS_LOCK_ON
Definition: ntddkbd.h:81
#define KEY_BREAK
Definition: ntddkbd.h:71
#define IOCTL_KEYBOARD_QUERY_INDICATORS
Definition: ntddkbd.h:35
#define IOCTL_KEYBOARD_SET_INDICATORS
Definition: ntddkbd.h:47
#define IOCTL_KEYBOARD_QUERY_ATTRIBUTES
Definition: ntddkbd.h:32
struct _KEYBOARD_INDICATOR_TRANSLATION KEYBOARD_INDICATOR_TRANSLATION
#define IOCTL_KEYBOARD_QUERY_INDICATOR_TRANSLATION
Definition: ntddkbd.h:38
#define KEYBOARD_SCROLL_LOCK_ON
Definition: ntddkbd.h:83
#define KEY_E1
Definition: ntddkbd.h:73
#define KEY_E0
Definition: ntddkbd.h:72
#define KEYBOARD_NUM_LOCK_ON
Definition: ntddkbd.h:82
_In_ HBITMAP hbm
Definition: ntgdi.h:2776
__kernel_entry W32KAPI HBITMAP APIENTRY NtGdiCreateCompatibleBitmap(_In_ HDC hdc, _In_ INT cx, _In_ INT cy)
__kernel_entry W32KAPI HDC APIENTRY NtGdiCreateCompatibleDC(_In_opt_ HDC hdc)
__kernel_entry W32KAPI BOOL APIENTRY NtGdiBitBlt(_In_ HDC hdcDst, _In_ INT x, _In_ INT y, _In_ INT cx, _In_ INT cy, _In_opt_ HDC hdcSrc, _In_ INT xSrc, _In_ INT ySrc, _In_ DWORD rop4, _In_ DWORD crBackColor, _In_ FLONG fl)
__kernel_entry W32KAPI HBITMAP APIENTRY NtGdiSelectBitmap(_In_ HDC hdc, _In_ HBITMAP hbm)
NTSYSAPI NTSTATUS NTAPI ZwDeviceIoControlFile(IN HANDLE DeviceHandle, IN HANDLE Event OPTIONAL, IN PIO_APC_ROUTINE UserApcRoutine OPTIONAL, IN PVOID UserApcContext OPTIONAL, OUT PIO_STATUS_BLOCK IoStatusBlock, IN ULONG IoControlCode, IN PVOID InputBuffer, IN ULONG InputBufferSize, OUT PVOID OutputBuffer, IN ULONG OutputBufferSize)
PVOID NTAPI PsGetCurrentThreadWin32Thread(VOID)
Definition: thread.c:805
#define STATUS_INVALID_HANDLE
Definition: ntstatus.h:245
#define STATUS_NOT_SUPPORTED
Definition: ntstatus.h:423
LRESULT APIENTRY co_HOOK_CallHooks(INT HookId, INT Code, WPARAM wParam, LPARAM lParam)
Definition: hook.c:1102
PPROCESSINFO gppiInputProvider
Definition: ntuser.c:16
VOID FASTCALL UserLeave(VOID)
Definition: ntuser.c:254
VOID FASTCALL UserEnterShared(VOID)
Definition: ntuser.c:238
VOID FASTCALL UserEnterExclusive(VOID)
Definition: ntuser.c:245
struct _THREADINFO * PTHREADINFO
Definition: ntwin32.h:6
#define TAG_STRING
Definition: oslist.h:22
#define LOWORD(l)
Definition: pedump.c:82
#define CONST
Definition: pedump.c:81
BYTE * PBYTE
Definition: pedump.c:66
short SHORT
Definition: pedump.c:59
long LONG
Definition: pedump.c:60
unsigned short USHORT
Definition: pedump.c:61
_Out_opt_ int _Out_opt_ int * cy
Definition: commctrl.h:586
_Out_opt_ int * cx
Definition: commctrl.h:585
#define _SEH2_GetExceptionCode()
Definition: pseh2_64.h:159
#define _SEH2_EXCEPT(...)
Definition: pseh2_64.h:34
#define _SEH2_YIELD(__stmt)
Definition: pseh2_64.h:162
#define LANG_JAPANESE
Definition: nls.h:76
#define PRIMARYLANGID(l)
Definition: nls.h:16
#define STATUS_SUCCESS
Definition: shellext.h:65
#define STATUS_BUFFER_TOO_SMALL
Definition: shellext.h:69
static void Exit(void)
Definition: sock.c:1330
#define TRACE(s)
Definition: solgame.cpp:4
DWORD dwTime
Definition: solitaire.cpp:26
WCHAR wchComposed
Definition: kbd.h:58
DWORD dwBoth
Definition: kbd.h:57
USHORT IndicatorFlags
Definition: ntddkbd.h:115
USHORT MakeCode
Definition: ntddkbd.h:114
Definition: kbd.h:95
VSC_LPWSTR * pKeyNamesExt
Definition: kbd.h:100
PMODIFIERS pCharModifiers
Definition: kbd.h:96
BYTE bMaxVSCtoVK
Definition: kbd.h:103
PVK_TO_WCHAR_TABLE pVkToWcharTable
Definition: kbd.h:97
USHORT * pusVSCtoVK
Definition: kbd.h:102
DWORD fLocaleFlags
Definition: kbd.h:106
PVSC_VK pVSCtoVK_E0
Definition: kbd.h:104
PDEADKEY pDeadKey
Definition: kbd.h:98
VSC_LPWSTR * pKeyNames
Definition: kbd.h:99
PVSC_VK pVSCtoVK_E1
Definition: kbd.h:105
KEYBOARD_ID KeyboardIdentifier
Definition: ntddkbd.h:124
USHORT NumberOfFunctionKeys
Definition: ntddkbd.h:126
UCHAR Subtype
Definition: ntddkbd.h:102
UCHAR Type
Definition: ntddkbd.h:101
INDICATOR_LIST IndicatorList[1]
Definition: ntddkbd.h:120
ULONG ExtraInformation
Definition: ntddkbd.h:90
WORD wMaxModBits
Definition: kbd.h:28
BYTE ModNumber[]
Definition: kbd.h:29
PVK_TO_BIT pVkToBit
Definition: kbd.h:27
struct _CLIENTINFO * pClientInfo
Definition: win32.h:94
struct tagKL * KeyboardLayout
Definition: win32.h:90
struct _USER_MESSAGE_QUEUE * MessageQueue
Definition: win32.h:89
PTHREADINFO ptiKeyboard
Definition: msgqueue.h:56
BYTE ModBits
Definition: kbd.h:23
BYTE Vk
Definition: kbd.h:22
BYTE cbSize
Definition: kbd.h:53
PVK_TO_WCHARS1 pVkToWchars
Definition: kbd.h:51
BYTE nModifications
Definition: kbd.h:52
LPWSTR pwsz
Definition: kbd.h:68
USHORT Vk
Definition: kbd.h:73
BYTE Vsc
Definition: kbd.h:72
Definition: ntuser.h:689
THRDESKHEAD head
Definition: ntuser.h:690
RECT rcWindow
Definition: ntuser.h:711
struct _KBDTABLES * pKbdTbl
Definition: input.h:21
ULONG_PTR dwExtraInfo
Definition: winuser.h:3802
DWORD dwFlags
Definition: winable.h:49
WORD wVk
Definition: winable.h:47
WORD wScan
Definition: winable.h:48
ULONG_PTR dwExtraInfo
Definition: winable.h:51
DWORD time
Definition: winable.h:50
Definition: input.h:27
PKBDFILE spkf
Definition: input.h:33
HKL hkl
Definition: input.h:32
UINT message
Definition: winuser.h:3105
HWND hwnd
Definition: winuser.h:3104
WPARAM wParam
Definition: winuser.h:3106
LPARAM lParam
Definition: winuser.h:3107
LONG right
Definition: windef.h:308
LONG bottom
Definition: windef.h:309
LONG top
Definition: windef.h:307
LONG left
Definition: windef.h:306
BOOL fIncSerialNumber
Definition: ntuser.h:1164
BOOL fGlobalHandle
Definition: ntuser.h:1163
TW_UINT32 TW_UINT16 TW_UINT16 MSG
Definition: twain.h:1829
#define NTAPI
Definition: typedefs.h:36
ULONG_PTR SIZE_T
Definition: typedefs.h:80
int32_t INT
Definition: typedefs.h:58
#define RtlCopyMemory(Destination, Source, Length)
Definition: typedefs.h:263
#define RtlZeroMemory(Destination, Length)
Definition: typedefs.h:262
uint16_t * PWCHAR
Definition: typedefs.h:56
#define HIWORD(l)
Definition: typedefs.h:247
#define STATUS_INSUFFICIENT_RESOURCES
Definition: udferr_usr.h:158
PWND FASTCALL UserGetWindowObject(HWND hWnd)
Definition: window.c:122
INT FASTCALL UserReleaseDC(PWND Window, HDC hDc, BOOL EndPaint)
Definition: windc.c:918
HDC FASTCALL UserGetDCEx(PWND Window OPTIONAL, HANDLE ClipRegion, ULONG Flags)
int ret
HDC hdcMem
Definition: welcome.c:104
VOID FASTCALL SetLastNtError(NTSTATUS Status)
Definition: error.c:37
BOOL NTAPI GreDeleteObject(HGDIOBJ hobj)
Definition: gdiobj.c:1158
USHORT gusLanguageID
Definition: main.c:29
BOOL NTAPI UserEmptyClipboard(VOID)
Definition: clipboard.c:680
BOOL NTAPI UserCloseClipboard(VOID)
Definition: clipboard.c:545
BOOL NTAPI UserOpenClipboard(HWND hWnd)
Definition: clipboard.c:488
HANDLE NTAPI UserSetClipboardData(UINT fmt, HANDLE hData, PSETCLIPBDATA scd)
Definition: clipboard.c:1023
HWND FASTCALL IntGetDesktopWindow(VOID)
Definition: desktop.c:1374
PUSER_MESSAGE_QUEUE FASTCALL IntGetFocusMessageQueue(VOID)
Definition: desktop.c:1307
BOOL NTAPI co_UserProcessHotKeys(WORD wVk, BOOL bIsDown)
Definition: hotkey.c:177
HANDLE ghKeyboardDevice
Definition: input.c:19
#define SET_KEY_DOWN(ks, vk, down)
Definition: input.h:101
#define KS_DOWN_BIT
Definition: input.h:54
PKL NTAPI UserHklToKbl(HKL hKl)
Definition: kbdlayout.c:541
#define IS_KEY_DOWN(ks, vk)
Definition: input.h:99
#define SC_KEY_UP
Definition: input.h:57
#define LP_DO_NOT_CARE_BIT
Definition: input.h:59
#define KS_LOCK_BIT
Definition: input.h:55
#define IS_KEY_LOCKED(ks, vk)
Definition: input.h:100
#define SET_KEY_LOCKED(ks, vk, down)
Definition: input.h:104
PKL W32kGetDefaultKeyLayout(VOID)
Definition: kbdlayout.c:514
static KEYBOARD_INDICATOR_PARAMETERS gIndicators
Definition: keyboard.c:16
KEYBOARD_ATTRIBUTES gKeyboardInfo
Definition: keyboard.c:17
static DWORD IntGetModBits(PKBDTABLES pKbdTbl, PBYTE pKeyState)
Definition: keyboard.c:298
BOOL FASTCALL IntTranslateKbdMessage(LPMSG lpMsg, UINT flags)
Definition: keyboard.c:1152
static NTSTATUS APIENTRY IntKeyboardUpdateLeds(HANDLE hKeyboardDevice, WORD wVk, WORD wScanCode)
Definition: keyboard.c:107
VOID NTAPI UserProcessKeyboardInput(PKEYBOARD_INPUT_DATA pKbdInputData)
Definition: keyboard.c:1067
DWORD APIENTRY NtUserVkKeyScanEx(WCHAR wch, HKL dwhkl, BOOL bUsehKL)
Definition: keyboard.c:1585
int APIENTRY NtUserToUnicodeEx(UINT wVirtKey, UINT wScanCode, PBYTE pKeyStateUnsafe, LPWSTR pwszBuffUnsafe, INT cchBuff, UINT wFlags, HKL dwhkl)
Definition: keyboard.c:1355
BYTE gafAsyncKeyState[256 *2/8]
Definition: keyboard.c:13
BOOL NTAPI UserSendKeyboardInput(KEYBDINPUT *pKbdInput, BOOL bInjected)
Definition: keyboard.c:986
static WORD IntFixVk(WORD wVk, BOOL bExt)
Definition: keyboard.c:247
static VOID SnapWindow(HWND hWnd)
Definition: keyboard.c:723
static BOOL IntTranslateChar(WORD wVirtKey, PBYTE pKeyState, PBOOL pbDead, PBOOL pbLigature, PWCHAR pwcTranslatedChar, PKBDTABLES pKbdTbl)
Definition: keyboard.c:320
DWORD gdwLanguageToggleKey
Definition: keyboard.c:19
static int APIENTRY IntToUnicodeEx(UINT wVirtKey, UINT wScanCode, PBYTE pKeyState, LPWSTR pwszBuff, int cchBuff, UINT wFlags, PKBDTABLES pKbdTbl)
Definition: keyboard.c:432
static WCHAR FASTCALL IntVkToChar(WORD wVk, PKBDTABLES pKbdTbl)
Definition: keyboard.c:605
int gLanguageToggleKeyState
Definition: keyboard.c:18
DWORD APIENTRY NtUserGetKeyNameText(LONG lParam, LPWSTR lpString, int cchSize)
Definition: keyboard.c:1460
static LRESULT co_CallLowLevelKeyboardHook(WORD wVk, WORD wScanCode, DWORD dwFlags, BOOL bInjected, DWORD dwTime, DWORD dwExtraInfo)
Definition: keyboard.c:687
static PKEYBOARD_INDICATOR_TRANSLATION gpKeyboardIndicatorTrans
Definition: keyboard.c:15
static UINT IntMapVirtualKeyEx(UINT uCode, UINT Type, PKBDTABLES pKbdTbl)
Definition: keyboard.c:1269
VOID NTAPI UserInitKeyboard(HANDLE hKeyboardDevice)
Definition: keyboard.c:161
NTSTATUS APIENTRY IntKeyboardGetIndicatorTrans(HANDLE hKeyboardDevice, PKEYBOARD_INDICATOR_TRANSLATION *ppIndicatorTrans)
Definition: keyboard.c:50
static BYTE gafAsyncKeyStateRecentDown[256/8]
Definition: keyboard.c:14
DWORD FASTCALL UserGetKeyboardType(DWORD dwTypeFlag)
Definition: keyboard.c:1560
static VOID NTAPI UpdateAsyncKeyState(WORD wVk, BOOL bIsDown)
Definition: keyboard.c:666
SHORT APIENTRY NtUserGetAsyncKeyState(INT Key)
Definition: keyboard.c:632
NTSTATUS NTAPI InitKeyboardImpl(VOID)
Definition: keyboard.c:31
BOOL NTAPI ProcessKeyEvent(WORD wVk, WORD wScanCode, DWORD dwFlags, BOOL bInjected, DWORD dwTime, DWORD dwExtraInfo)
Definition: keyboard.c:800
static WORD FASTCALL IntVkToVsc(WORD wVk, PKBDTABLES pKbdTbl)
Definition: keyboard.c:525
static WORD FASTCALL IntVscToVk(WORD wScanCode, PKBDTABLES pKbdTbl)
Definition: keyboard.c:562
static WORD IntSimplifyVk(WORD wVk)
Definition: keyboard.c:219
static WORD IntTranslateNumpadKey(WORD wVk)
Definition: keyboard.c:272
UINT APIENTRY NtUserMapVirtualKeyEx(UINT uCode, UINT uType, DWORD keyboardId, HKL dwhkl)
Definition: keyboard.c:1315
PVOID FASTCALL UserAssignmentLock(PVOID *ppvObj, PVOID pvNew)
Definition: object.c:840
#define USERTAG_KBDTABLE
Definition: tags.h:247
_In_ DWORD _Out_ _In_ WORD wFlags
Definition: wincon.h:531
_In_ PCCERT_CONTEXT _In_ DWORD dwFlags
Definition: wincrypt.h:1176
ENGAPI VOID APIENTRY EngSetLastError(_In_ ULONG iError)
Definition: error.c:28
LONG_PTR LPARAM
Definition: windef.h:208
LONG_PTR LRESULT
Definition: windef.h:209
BOOL * PBOOL
Definition: windef.h:161
#define SRCCOPY
Definition: wingdi.h:333
#define VK_CLEAR
Definition: winuser.h:2190
#define QS_KEY
Definition: winuser.h:868
#define VK_NUMPAD3
Definition: winuser.h:2232
#define VK_SNAPSHOT
Definition: winuser.h:2221
#define VK_TAB
Definition: winuser.h:2189
#define MAKELPARAM(l, h)
Definition: winuser.h:3998
#define WM_KEYUP
Definition: winuser.h:1706
#define LLKHF_EXTENDED
Definition: winuser.h:2635
#define DCX_WINDOW
Definition: winuser.h:2103
#define VK_NUMPAD1
Definition: winuser.h:2230
#define VK_F10
Definition: winuser.h:2254
#define VK_NUMPAD2
Definition: winuser.h:2231
#define VK_CAPITAL
Definition: winuser.h:2196
#define MAPVK_VSC_TO_VK_EX
Definition: winuser.h:2348
#define VK_NUMPAD4
Definition: winuser.h:2233
#define KF_ALTDOWN
Definition: winuser.h:2439
#define VK_SCROLL
Definition: winuser.h:2270
#define KF_EXTENDED
Definition: winuser.h:2436
#define VK_CONTROL
Definition: winuser.h:2193
#define HC_ACTION
Definition: winuser.h:48
#define VK_RSHIFT
Definition: winuser.h:2273
#define VK_UP
Definition: winuser.h:2215
#define VK_OEM_FINISH
Definition: winuser.h:2329
#define VK_LSHIFT
Definition: winuser.h:2272
#define VK_LCONTROL
Definition: winuser.h:2274
#define VK_NUMPAD0
Definition: winuser.h:2229
#define LLKHF_ALTDOWN
Definition: winuser.h:2637
#define VK_NUMPAD6
Definition: winuser.h:2235
#define MAPVK_VSC_TO_VK
Definition: winuser.h:2346
#define VK_NEXT
Definition: winuser.h:2211
#define VK_RCONTROL
Definition: winuser.h:2275
#define KF_UP
Definition: winuser.h:2441
#define KF_MENUMODE
Definition: winuser.h:2438
#define WM_SYSCHAR
Definition: winuser.h:1711
#define WM_SYSDEADCHAR
Definition: winuser.h:1712
#define VK_RMENU
Definition: winuser.h:2277
#define VK_NUMPAD9
Definition: winuser.h:2238
#define VK_OEM_ATTN
Definition: winuser.h:2328
#define VK_OEM_COPY
Definition: winuser.h:2330
#define VK_END
Definition: winuser.h:2212
#define VK_HOME
Definition: winuser.h:2213
#define LLKHF_UP
Definition: winuser.h:2638
#define WM_SYSKEYUP
Definition: winuser.h:1710
#define WH_KEYBOARD_LL
Definition: winuser.h:43
#define LLKHF_INJECTED
Definition: winuser.h:2636
#define WM_CHAR
Definition: winuser.h:1707
#define MAPVK_VK_TO_CHAR
Definition: winuser.h:2347
#define VK_NUMPAD5
Definition: winuser.h:2234
#define VK_LEFT
Definition: winuser.h:2214
#define KEYEVENTF_EXTENDEDKEY
Definition: winuser.h:1095
#define VK_NUMPAD7
Definition: winuser.h:2236
#define VK_RIGHT
Definition: winuser.h:2216
#define VK_DOWN
Definition: winuser.h:2217
#define VK_NUMLOCK
Definition: winuser.h:2269
#define KF_REPEAT
Definition: winuser.h:2440
#define VK_SHIFT
Definition: winuser.h:2192
#define VK_PRIOR
Definition: winuser.h:2210
#define VK_DELETE
Definition: winuser.h:2223
#define MAPVK_VK_TO_VSC
Definition: winuser.h:2345
#define WM_KEYDOWN
Definition: winuser.h:1705
#define VK_NUMPAD8
Definition: winuser.h:2237
#define MAPVK_VK_TO_VSC_EX
Definition: winuser.h:2349
#define VK_DECIMAL
Definition: winuser.h:2243
#define VK_ESCAPE
Definition: winuser.h:2204
#define WM_DEADCHAR
Definition: winuser.h:1708
#define KEYEVENTF_KEYUP
Definition: winuser.h:1096
#define WM_SYSKEYDOWN
Definition: winuser.h:1709
#define VK_INSERT
Definition: winuser.h:2222
#define KF_DLGMODE
Definition: winuser.h:2437
#define VK_LMENU
Definition: winuser.h:2276
#define VK_MENU
Definition: winuser.h:2194
__wchar_t WCHAR
Definition: xmlstorage.h:180
WCHAR * LPWSTR
Definition: xmlstorage.h:184
unsigned char BYTE
Definition: xxhash.c:193