ReactOS 0.4.17-dev-1321-g5c122a9
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
22
23#include <cjkcode.h>
24
25/* State for Alt+Numpad character entry */
26static enum _ALTNUM_STATE
27{
29 ALTNUM_OEM, // Alt xxx
30 ALTNUM_ACP, // Alt 0xxx
31 ALTNUM_HEX_ACP, // Alt .xxx
32 ALTNUM_HEX_UTF // Alt +xxx
34
37
38/* FUNCTIONS *****************************************************************/
39
40/*
41 * InitKeyboardImpl
42 *
43 * Initialization -- Right now, just zero the key state
44 */
45CODE_SEG("INIT")
49{
52 // Clear and set default information.
54 gKeyboardInfo.KeyboardIdentifier.Type = 4; /* AT-101 */
55 gKeyboardInfo.NumberOfFunctionKeys = 12; /* We're doing an 101 for now, so return 12 F-keys */
56 return STATUS_SUCCESS;
57}
58
59/*
60 * IntKeyboardGetIndicatorTrans
61 *
62 * Asks the keyboard driver to send a small table that shows which
63 * lights should connect with which scancodes
64 */
65//static
68 PKEYBOARD_INDICATOR_TRANSLATION *ppIndicatorTrans)
69{
71 DWORD dwSize = 0;
74
76
78 dwSize,
80
81 while (pRet)
82 {
83 Status = ZwDeviceIoControlFile(hKeyboardDevice,
84 NULL,
85 NULL,
86 NULL,
87 &Block,
89 NULL, 0,
90 pRet, dwSize);
91
93 break;
94
96
98
100 dwSize,
102 }
103
104 if (!pRet)
106
107 if (!NT_SUCCESS(Status))
108 {
110 return Status;
111 }
112
113 *ppIndicatorTrans = pRet;
114 return Status;
115}
116
117/*
118 * IntKeyboardUpdateLeds
119 *
120 * Sends the keyboard commands to turn on/off the lights
121 */
122static
125 WORD wVk,
126 WORD wScanCode)
127{
129 UINT i;
130 USHORT LedFlag = 0;
132
135
136 switch (wVk)
137 {
138 case VK_CAPITAL: LedFlag = KEYBOARD_CAPS_LOCK_ON; break;
139 case VK_NUMLOCK: LedFlag = KEYBOARD_NUM_LOCK_ON; break;
140 case VK_SCROLL: LedFlag = KEYBOARD_SCROLL_LOCK_ON; break;
141 default:
143 {
145 {
147 break;
148 }
149 }
150 }
151
152 if (LedFlag)
153 {
154 gIndicators.LedFlags ^= LedFlag;
155
156 /* Update the lights on the hardware */
157 Status = ZwDeviceIoControlFile(hKeyboardDevice,
158 NULL,
159 NULL,
160 NULL,
161 &Block,
163 &gIndicators, sizeof(gIndicators),
164 NULL, 0);
165
166 return Status;
167 }
168
169 return STATUS_SUCCESS;
170}
171
172/*
173 * UserInitKeyboard
174 *
175 * Initializes keyboard indicators translation and their state
176 */
178UserInitKeyboard(HANDLE hKeyboardDevice)
179{
182
184
185 Status = ZwDeviceIoControlFile(hKeyboardDevice,
186 NULL,
187 NULL,
188 NULL,
189 &Block,
191 NULL, 0,
193 sizeof(gIndicators));
194
195 if (!NT_SUCCESS(Status))
196 {
197 WARN("NtDeviceIoControlFile() failed, ignored\n");
200 }
201
208}
209
210/*
211 * IntSimplifyVk
212 *
213 * Changes virtual keys which distinguish between left and right hand, to keys which don't distinguish
214 */
215static
216WORD
218{
219 switch (wVk)
220 {
221 case VK_LSHIFT:
222 case VK_RSHIFT:
223 return VK_SHIFT;
224
225 case VK_LCONTROL:
226 case VK_RCONTROL:
227 return VK_CONTROL;
228
229 case VK_LMENU:
230 case VK_RMENU:
231 return VK_MENU;
232
233 default:
234 return wVk;
235 }
236}
237
238/*
239 * IntFixVk
240 *
241 * Changes virtual keys which don't not distinguish between left and right hand to proper keys
242 */
243static
244WORD
246{
247 switch (wVk)
248 {
249 case VK_SHIFT:
250 return bExt ? VK_RSHIFT : VK_LSHIFT;
251
252 case VK_CONTROL:
253 return bExt ? VK_RCONTROL : VK_LCONTROL;
254
255 case VK_MENU:
256 return bExt ? VK_RMENU : VK_LMENU;
257
258 default:
259 return wVk;
260 }
261}
262
263/*
264 * IntTranslateNumpadKey
265 *
266 * Translates numpad keys when numlock is enabled
267 */
268static
269WORD
271{
272 switch (wVk)
273 {
274 case VK_INSERT: return VK_NUMPAD0;
275 case VK_END: return VK_NUMPAD1;
276 case VK_DOWN: return VK_NUMPAD2;
277 case VK_NEXT: return VK_NUMPAD3;
278 case VK_LEFT: return VK_NUMPAD4;
279 case VK_CLEAR: return VK_NUMPAD5;
280 case VK_RIGHT: return VK_NUMPAD6;
281 case VK_HOME: return VK_NUMPAD7;
282 case VK_UP: return VK_NUMPAD8;
283 case VK_PRIOR: return VK_NUMPAD9;
284 case VK_DELETE: return VK_DECIMAL;
285 default: return wVk;
286 }
287}
288
289/*
290 * IntGetModBits
291 *
292 * Gets layout specific modification bits, for example KBDSHIFT, KBDCTRL, KBDALT
293 */
294static
295DWORD
296IntGetModBits(PKBDTABLES pKbdTbl, PBYTE pKeyState)
297{
298 DWORD i, dwModBits = 0;
299
300 /* DumpKeyState( KeyState ); */
301
302 for (i = 0; pKbdTbl->pCharModifiers->pVkToBit[i].Vk; i++)
303 if (IS_KEY_DOWN(pKeyState, pKbdTbl->pCharModifiers->pVkToBit[i].Vk))
304 dwModBits |= pKbdTbl->pCharModifiers->pVkToBit[i].ModBits;
305
306 TRACE("Current Mod Bits: %lx\n", dwModBits);
307
308 return dwModBits;
309}
310
311/*
312 * IntTranslateChar
313 *
314 * Translates virtual key to character
315 */
316static
317BOOL
319 PBYTE pKeyState,
320 PBOOL pbDead,
321 PBOOL pbLigature,
322 PWCHAR pwcTranslatedChar,
323 PKBDTABLES pKbdTbl)
324{
325 PVK_TO_WCHAR_TABLE pVkToVchTbl;
326 PVK_TO_WCHARS10 pVkToVch;
327 DWORD i, dwModBits, dwVkModBits, dwModNumber = 0;
328 WCHAR wch;
329 BOOL bAltGr;
330 WORD wCaplokAttr;
331
332 dwModBits = pKeyState ? IntGetModBits(pKbdTbl, pKeyState) : 0;
333 bAltGr = pKeyState && (pKbdTbl->fLocaleFlags & KLLF_ALTGR) && IS_KEY_DOWN(pKeyState, VK_RMENU);
334 wCaplokAttr = bAltGr ? CAPLOKALTGR : CAPLOK;
335
336 TRACE("TryToTranslate: %04x %x\n", wVirtKey, dwModBits);
337
338 /* If ALT without CTRL has ben used, remove ALT flag */
339 if ((dwModBits & (KBDALT|KBDCTRL)) == KBDALT)
340 dwModBits &= ~KBDALT;
341
342 if (dwModBits > pKbdTbl->pCharModifiers->wMaxModBits)
343 {
344 TRACE("dwModBits %x > wMaxModBits %x\n", dwModBits, pKbdTbl->pCharModifiers->wMaxModBits);
345 return FALSE;
346 }
347
348 for (i = 0; pKbdTbl->pVkToWcharTable[i].pVkToWchars; i++)
349 {
350 pVkToVchTbl = &pKbdTbl->pVkToWcharTable[i];
351 pVkToVch = (PVK_TO_WCHARS10)(pVkToVchTbl->pVkToWchars);
352 while (pVkToVch->VirtualKey)
353 {
354 if (wVirtKey == (pVkToVch->VirtualKey & 0xFF))
355 {
356 dwVkModBits = dwModBits;
357
358 /* If CapsLock is enabled for this key and locked, add SHIFT bit */
359 if ((pVkToVch->Attributes & wCaplokAttr) &&
360 pKeyState &&
361 IS_KEY_LOCKED(pKeyState, VK_CAPITAL))
362 {
363 /* Note: we use special value here instead of getting VK_SHIFT mod bit - it's verified */
364 dwVkModBits ^= KBDSHIFT;
365 }
366
367 if (dwVkModBits > pKbdTbl->pCharModifiers->wMaxModBits)
368 break;
369
370 /* Get modification number */
371 dwModNumber = pKbdTbl->pCharModifiers->ModNumber[dwVkModBits];
372 if (dwModNumber >= pVkToVchTbl->nModifications)
373 {
374 TRACE("dwModNumber %u >= nModifications %u\n", dwModNumber, pVkToVchTbl->nModifications);
375 break;
376 }
377
378 /* Read character */
379 wch = pVkToVch->wch[dwModNumber];
380 if (wch == WCH_NONE)
381 break;
382
383 *pbDead = (wch == WCH_DEAD);
384 *pbLigature = (wch == WCH_LGTR);
385 *pwcTranslatedChar = wch;
386
387 TRACE("%lu %04x: dwModNumber %08x Char %04x\n",
388 i, wVirtKey, dwModNumber, wch);
389
390 if (*pbDead)
391 {
392 /* After WCH_DEAD, real character is located */
393 pVkToVch = (PVK_TO_WCHARS10)(((BYTE *)pVkToVch) + pVkToVchTbl->cbSize);
394 if (pVkToVch->VirtualKey != 0xFF)
395 {
396 WARN("Found dead key with no trailer in the table.\n");
397 WARN("VK: %04x, ADDR: %p\n", wVirtKey, pVkToVch);
398 break;
399 }
400 *pwcTranslatedChar = pVkToVch->wch[dwModNumber];
401 }
402 return TRUE;
403 }
404 pVkToVch = (PVK_TO_WCHARS10)(((BYTE *)pVkToVch) + pVkToVchTbl->cbSize);
405 }
406 }
407
408 /* If nothing has been found in layout, check if this is ASCII control character.
409 Note: we could add it to layout table, but windows does not have it there */
410 if (wVirtKey >= 'A' && wVirtKey <= 'Z' &&
411 pKeyState && IS_KEY_DOWN(pKeyState, VK_CONTROL) &&
412 !IS_KEY_DOWN(pKeyState, VK_MENU))
413 {
414 *pwcTranslatedChar = (wVirtKey - 'A') + 1; /* ASCII control character */
415 *pbDead = FALSE;
416 *pbLigature = FALSE;
417 return TRUE;
418 }
419
420 return FALSE;
421}
422
423/*
424 * IntToUnicodeEx
425 *
426 * Translates virtual key to characters
427 */
428static
429int APIENTRY
431 UINT wScanCode,
432 PBYTE pKeyState,
433 LPWSTR pwszBuff,
434 int cchBuff,
435 UINT wFlags,
436 PKBDTABLES pKbdTbl)
437{
438 WCHAR wchTranslatedChar;
439 BOOL bDead, bLigature;
440 static WCHAR wchDead = 0;
441 int iRet = 0;
442
443 ASSERT(pKbdTbl);
444
445 if (!IntTranslateChar(wVirtKey,
446 pKeyState,
447 &bDead,
448 &bLigature,
449 &wchTranslatedChar,
450 pKbdTbl))
451 {
452 return 0;
453 }
454
455 if (bLigature)
456 {
457 WARN("Not handling ligature (yet)\n" );
458 return 0;
459 }
460
461 /* If we got dead char in previous call check dead keys in keyboard layout */
462 if (wchDead)
463 {
464 UINT i;
465 WCHAR wchFirst, wchSecond;
466 TRACE("Previous dead char: %lc (%x)\n", wchDead, wchDead);
467
468 if (pKbdTbl->pDeadKey)
469 {
470 for (i = 0; pKbdTbl->pDeadKey[i].dwBoth; i++)
471 {
472 wchFirst = pKbdTbl->pDeadKey[i].dwBoth >> 16;
473 wchSecond = pKbdTbl->pDeadKey[i].dwBoth & 0xFFFF;
474 if (wchFirst == wchDead && wchSecond == wchTranslatedChar)
475 {
476 wchTranslatedChar = pKbdTbl->pDeadKey[i].wchComposed;
477 wchDead = 0;
478 bDead = FALSE;
479 break;
480 }
481 }
482 }
483 else
484 {
485#if defined(__GNUC__)
486 if (wchDead == 0x8000)
487 {
488 ERR("GCC is inventing bits, ignoring fake dead key\n");
489 wchDead = 0;
490 }
491#endif
492 }
493
494 TRACE("Final char: %lc (%x)\n", wchTranslatedChar, wchTranslatedChar);
495 }
496
497 /* Dead char has not been not found */
498 if (wchDead)
499 {
500 /* Treat both characters normally */
501 if (cchBuff > iRet)
502 pwszBuff[iRet++] = wchDead;
503 bDead = FALSE;
504 }
505
506 /* Add character to the buffer */
507 if (cchBuff > iRet)
508 pwszBuff[iRet++] = wchTranslatedChar;
509
510 /* Save dead character */
511 wchDead = bDead ? wchTranslatedChar : 0;
512
513 return bDead ? -iRet : iRet;
514}
515
516/*
517 * IntVkToVsc
518 *
519 * Translates virtual key to scan code
520 */
521static
524{
525 unsigned i;
526
527 ASSERT(pKbdTbl);
528
529 /* Check standard keys first */
530 for (i = 0; i < pKbdTbl->bMaxVSCtoVK; i++)
531 {
532 if ((pKbdTbl->pusVSCtoVK[i] & 0xFF) == wVk)
533 return i;
534 }
535
536 /* Check extended keys now */
537 for (i = 0; pKbdTbl->pVSCtoVK_E0[i].Vsc; i++)
538 {
539 if ((pKbdTbl->pVSCtoVK_E0[i].Vk & 0xFF) == wVk)
540 return 0xE000 | pKbdTbl->pVSCtoVK_E0[i].Vsc;
541 }
542
543 for (i = 0; pKbdTbl->pVSCtoVK_E1[i].Vsc; i++)
544 {
545 if ((pKbdTbl->pVSCtoVK_E1[i].Vk & 0xFF) == wVk)
546 return 0xE100 | pKbdTbl->pVSCtoVK_E1[i].Vsc;
547 }
548
549 /* Virtual key has not been found */
550 return 0;
551}
552
553/*
554 * IntVscToVk
555 *
556 * Translates prefixed scancode to virtual key
557 */
558static
560IntVscToVk(WORD wScanCode, PKBDTABLES pKbdTbl)
561{
562 unsigned i;
563 WORD wVk = 0;
564
565 ASSERT(pKbdTbl);
566
567 if ((wScanCode & 0xFF00) == 0xE000)
568 {
569 for (i = 0; pKbdTbl->pVSCtoVK_E0[i].Vsc; i++)
570 {
571 if (pKbdTbl->pVSCtoVK_E0[i].Vsc == (wScanCode & 0xFF))
572 {
573 wVk = pKbdTbl->pVSCtoVK_E0[i].Vk;
574 }
575 }
576 }
577 else if ((wScanCode & 0xFF00) == 0xE100)
578 {
579 for (i = 0; pKbdTbl->pVSCtoVK_E1[i].Vsc; i++)
580 {
581 if (pKbdTbl->pVSCtoVK_E1[i].Vsc == (wScanCode & 0xFF))
582 {
583 wVk = pKbdTbl->pVSCtoVK_E1[i].Vk;
584 }
585 }
586 }
587 else if (wScanCode < pKbdTbl->bMaxVSCtoVK)
588 {
589 wVk = pKbdTbl->pusVSCtoVK[wScanCode];
590 }
591
592 /* 0xFF nad 0x00 are invalid VKs */
593 return wVk != 0xFF ? wVk : 0;
594}
595
596/*
597 * IntVkToChar
598 *
599 * Translates virtual key to character, ignoring shift state
600 */
601static
604{
605 WCHAR wch;
606 BOOL bDead, bLigature;
607
608 ASSERT(pKbdTbl);
609
610 if (IntTranslateChar(wVk,
611 NULL,
612 &bDead,
613 &bLigature,
614 &wch,
615 pKbdTbl))
616 {
617 return wch;
618 }
619
620 return 0;
621}
622
623/*
624 * NtUserGetAsyncKeyState
625 *
626 * Gets key state from global bitmap
627 */
628SHORT
631{
632 WORD wRet = 0;
633
634 TRACE("Enter NtUserGetAsyncKeyState\n");
635
636 if (Key >= 0x100 || Key < 0)
637 {
639 ERR("Invalid parameter Key\n");
640 return 0;
641 }
642
644
646 wRet |= 0x8000; // If down, windows returns 0x8000.
647 if (gafAsyncKeyStateRecentDown[Key / 8] & (1 << (Key % 8)))
648 wRet |= 0x1;
649 gafAsyncKeyStateRecentDown[Key / 8] &= ~(1 << (Key % 8));
650
651 UserLeave();
652
653 TRACE("Leave NtUserGetAsyncKeyState, ret=%u\n", wRet);
654 return wRet;
655}
656
657/*
658 * UpdateAsyncKeyState
659 *
660 * Updates gafAsyncKeyState array
661 */
662static
665{
666 if (bIsDown)
667 {
668 /* If it's first key down event, xor lock bit */
669 if (!IS_KEY_DOWN(gafAsyncKeyState, wVk))
671
673 gafAsyncKeyStateRecentDown[wVk / 8] |= (1 << (wVk % 8));
674 }
675 else
677}
678
679/*
680 * co_CallLowLevelKeyboardHook
681 *
682 * Calls WH_KEYBOARD_LL hook
683 */
684static LRESULT
685co_CallLowLevelKeyboardHook(WORD wVk, WORD wScanCode, DWORD dwFlags, BOOL bInjected, DWORD dwTime, DWORD dwExtraInfo)
686{
687 KBDLLHOOKSTRUCT KbdHookData;
688 UINT uMsg;
689
690 KbdHookData.vkCode = wVk;
691 KbdHookData.scanCode = wScanCode;
692 KbdHookData.flags = 0;
694 KbdHookData.flags |= LLKHF_EXTENDED;
696 KbdHookData.flags |= LLKHF_ALTDOWN;
698 KbdHookData.flags |= LLKHF_UP;
699 if (bInjected)
700 KbdHookData.flags |= LLKHF_INJECTED;
701 KbdHookData.time = dwTime;
702 KbdHookData.dwExtraInfo = dwExtraInfo;
703
704 /* Note: it doesnt support WM_SYSKEYUP */
706 uMsg = WM_KEYUP;
708 uMsg = WM_SYSKEYDOWN;
709 else
710 uMsg = WM_KEYDOWN;
711
712 return co_HOOK_CallHooks(WH_KEYBOARD_LL, HC_ACTION, uMsg, (LPARAM)&KbdHookData);
713}
714
715/*
716 * SnapWindow
717 *
718 * Saves snapshot of specified window or whole screen in the clipboard
719 */
720static VOID
722{
723 HBITMAP hbm = NULL, hbmOld;
724 HDC hdc = NULL, hdcMem;
725 SETCLIPBDATA scd;
726 INT cx, cy;
727 PWND pWnd = NULL;
728
729 TRACE("SnapWindow(%p)\n", hWnd);
730
731 /* If no windows is given, make snapshot of desktop window */
732 if (!hWnd)
734
736 if (!pWnd)
737 {
738 ERR("Invalid window\n");
739 goto cleanup;
740 }
741
743 if (!hdc)
744 {
745 ERR("UserGetDCEx failed!\n");
746 goto cleanup;
747 }
748
749 cx = pWnd->rcWindow.right - pWnd->rcWindow.left;
750 cy = pWnd->rcWindow.bottom - pWnd->rcWindow.top;
751
753 if (!hbm)
754 {
755 ERR("NtGdiCreateCompatibleBitmap failed!\n");
756 goto cleanup;
757 }
758
760 if (!hdcMem)
761 {
762 ERR("NtGdiCreateCompatibleDC failed!\n");
763 goto cleanup;
764 }
765
766 hbmOld = NtGdiSelectBitmap(hdcMem, hbm);
767 NtGdiBitBlt(hdcMem, 0, 0, cx, cy, hdc, 0, 0, SRCCOPY, CLR_INVALID, 0);
768 NtGdiSelectBitmap(hdcMem, hbmOld);
770
771 /* Save snapshot in clipboard */
773 {
776 scd.fGlobalHandle = FALSE;
778 {
779 /* Bitmap is managed by system now */
780 hbm = NULL;
781 }
783 }
784
785cleanup:
786 if (hbm)
788 if (hdc)
789 UserReleaseDC(pWnd, hdc, FALSE);
790}
791
792/* Find the next/previous keyboard layout of the same/different language */
793static PKL FASTCALL
795 _In_ PKL pKL,
796 _In_ BOOL bNext,
797 _In_ BOOL bSameLang)
798{
799 PKL pFirstKL = pKL;
800 LANGID LangID = LOWORD(pKL->hkl);
801
802 do
803 {
804 pKL = (bNext ? pKL->pklNext : pKL->pklPrev);
805
806 if (!(pKL->dwKL_Flags & KL_UNLOAD) && bSameLang == (LangID == LOWORD(pKL->hkl)))
807 return pKL;
808 } while (pKL != pFirstKL);
809
810 return pFirstKL;
811}
812
813/* Perform layout toggle by [Left Alt]+Shift or Ctrl+Shift */
814static VOID
816 _In_ PUSER_MESSAGE_QUEUE pFocusQueue,
817 _In_ BOOL bSameLang,
818 _In_ INT nKeyState)
819{
820 PWND pWnd;
821 PTHREADINFO pti;
822 PKL pkl;
823 WPARAM wParam = 0;
824
825 if (!pFocusQueue)
826 {
827 ERR("IntLanguageToggle(): NULL pFocusQueue\n");
828 return;
829 }
830 pWnd = pFocusQueue->spwndFocus;
831 if (!pWnd)
832 pWnd = pFocusQueue->spwndActive;
833 if (!pWnd)
834 return;
835
836 pti = pWnd->head.pti;
837 pkl = pti->KeyboardLayout;
838
839 if (nKeyState == INPUTLANGCHANGE_FORWARD)
840 pkl = IntGetNextKL(pkl, TRUE, bSameLang);
841 else if (nKeyState == INPUTLANGCHANGE_BACKWARD)
842 pkl = IntGetNextKL(pkl, FALSE, bSameLang);
843
844 if (gSystemFS & pkl->dwFontSigs)
845 wParam |= INPUTLANGCHANGE_SYSCHARSET;
846
847 UserPostMessage(UserHMGetHandle(pWnd), WM_INPUTLANGCHANGEREQUEST, wParam, (LPARAM)pkl->hkl);
848}
849
850/* Check Language Toggle by [Left Alt]+Shift or Ctrl+Shift */
851static BOOL
853 _In_ PUSER_MESSAGE_QUEUE pFocusQueue,
854 _In_ BOOL bIsDown,
855 _In_ WORD wVk,
856 _Inout_ PINT pKeyState)
857{
858 if (bIsDown) /* Toggle key combination is pressed? */
859 {
860 if (wVk == VK_LSHIFT)
861 *pKeyState = INPUTLANGCHANGE_FORWARD;
862 else if (wVk == VK_RSHIFT)
863 *pKeyState = INPUTLANGCHANGE_BACKWARD;
864 else if (!wVk && IS_KEY_DOWN(gafAsyncKeyState, VK_LSHIFT))
865 *pKeyState = INPUTLANGCHANGE_FORWARD;
866 else if (!wVk && IS_KEY_DOWN(gafAsyncKeyState, VK_RSHIFT))
867 *pKeyState = INPUTLANGCHANGE_BACKWARD;
868 else
869 return FALSE;
870 }
871 else
872 {
873 if (*pKeyState == 0)
874 return FALSE;
875
876 IntLanguageToggle(pFocusQueue, (pKeyState == &gLayoutToggleKeyState), *pKeyState);
877 *pKeyState = 0;
878 }
879 return TRUE;
880}
881
896static BOOL
898 _In_ WORD wVk,
899 _In_ BOOL bIsDown,
900 _In_ DWORD dwTime /*,
901 _In_ PUSER_MESSAGE_QUEUE pFocusQueue */)
902{
903 if (bIsDown &&
906 {
907 TRACE("VK_MENU && !VK_CONTROL - wVk: 0x%04x\n", wVk);
908
909 /* Initialize the Alt+Numpad state if necessary */
911 {
912 if (gbEnableHexNumpad && (wVk == VK_DECIMAL)) // || (wVk == VK_OEM_PERIOD)
913 gAltNumPadState = ALTNUM_HEX_ACP, wVk = VK_NUMPAD0; // Replace '.' by '0'
914 else if (gbEnableHexNumpad && (wVk == VK_ADD)) // || (wVk == VK_OEM_PLUS)
915 gAltNumPadState = ALTNUM_HEX_UTF, wVk = VK_NUMPAD0; // Replace '+' by '0'
916 else if (wVk >= VK_NUMPAD0 && wVk <= VK_NUMPAD9) // || (wVk >= '0' && wVk <= '9')
918 else
919 return FALSE; /* Unhandled, do regular key processing */
920 }
921
922 /* Check the incoming key */
923 switch (gAltNumPadState)
924 {
925 case ALTNUM_OEM: case ALTNUM_ACP:
926 {
927 UINT uDigit;
928
929 /* Check if it is a numpad digit */
930 if (wVk >= VK_NUMPAD0 && wVk <= VK_NUMPAD9)
931 uDigit = wVk - VK_NUMPAD0;
932 // else if (wVk >= '0' && wVk <= '9')
933 // uDigit = wVk - '0';
934 else
935 break;
936
937 /* Build the decimal value; the value can overflow
938 * and be truncated (same behaviour as on Windows) */
939 gAltNumPadValue = (gAltNumPadValue * 10) + uDigit;
940 return TRUE; /* No key processing needs to be done */
941 }
943 {
944 UINT uDigit;
945
946 /* Check if it represents a valid hexadecimal digit */
947 if (wVk >= VK_NUMPAD0 && wVk <= VK_NUMPAD9)
948 uDigit = wVk - VK_NUMPAD0;
949 else if (wVk >= '0' && wVk <= '9')
950 uDigit = wVk - '0';
951 else if (wVk >= 'A' && wVk <= 'F')
952 uDigit = wVk - 'A' + 10;
953 else
954 break;
955
956 /* Build the hexadecimal value; the value can overflow
957 * and be truncated (same behaviour as on Windows) */
958 gAltNumPadValue = (gAltNumPadValue * 16) + uDigit;
959 return TRUE; /* No key processing needs to be done */
960 }
962 }
963
964 /* If the incoming key is not the ALT key, reset the Alt+Numpad state */
965 if (wVk != VK_MENU)
966 {
968 gAltNumPadValue = 0;
969 }
970 }
971 TRACE("gAltNumPadState: %lu, gAltNumPadValue: %lu\n",
973
974 /* Check for the end of an Alt+Numpad sequence, triggered by the ALT key release */
975 if ((gAltNumPadState != ALTNUM_INACTIVE) && !bIsDown && (wVk == VK_MENU))
976 {
978
979 TRACE("End of Alt+Numpad\n");
980 if (gAltNumPadValue != 0 && pFocusQueue && pFocusQueue->ptiKeyboard)
981 {
983 WCHAR wchUnicodeChar;
984
985 /* Convert the input codepoint value to UTF-16 */
987 {
988 /* Convert the Unicode codepoint to UTF-16 */
989 // FIXME: We currently support only the Basic Multilingual Plane
990 // (equivalent to UCS-2) and don't exclude the surrogate range
991 // (U+D800 to U+DFFF). In the future, we should handle all the
992 // valid values, generating two UTF-16 code units if necessary
993 // so as to support the other Unicode planes.
994 // See https://en.wikipedia.org/wiki/UTF-16#Description
995 wchUnicodeChar = (WCHAR)(gAltNumPadValue & 0xFFFF);
997 }
998 else
999 {
1000 NTSTATUS (NTAPI* pRtlCPToUnicodeN)(
1004 _In_reads_bytes_(BytesInString) PCCH String,
1005 _In_ ULONG BytesInString);
1006
1007 USHORT AnsiCP, OemCP, wCodePage, mbChar;
1008
1009 /* Check the current codepage and select a conversion function.
1010 * NOTE: Windows WIN32K invokes the ClientCharToWchar
1011 * USER32 callback to perform the conversion. */
1012 RtlGetDefaultCodePage(&AnsiCP, &OemCP);
1014 {
1015 // TODO: Handle console where we do not know its active
1016 // OEM codepage. In this case we need to directly send
1017 // the raw OEM numpad value, OR'ed with ALTNUMPAD_BIT.
1018 // For more details, see:
1019 // https://github.com/microsoft/terminal/blob/e20e1f7bf92b61580baea69483a74a7f4578a586/src/host/stream.cpp#L170
1020
1021 /* Use the current OEM codepage -> Unicode function */
1022 wCodePage = OemCP;
1023 pRtlCPToUnicodeN = RtlOemToUnicodeN;
1024 }
1025 else // if ((gAltNumPadState == ALTNUM_ACP) ||
1026 // (gAltNumPadState == ALTNUM_HEX_ACP))
1027 {
1028 /* Use the current ANSI codepage (ACP) MultiByte -> Unicode function */
1029 wCodePage = AnsiCP;
1030 pRtlCPToUnicodeN = RtlMultiByteToUnicodeN;
1031 }
1032
1033 /* For CJK codepages, keep the input value on 2 bytes,
1034 * otherwise truncate it to 1 byte for legacy behaviour. */
1035 if (IsCJKCodePage(wCodePage))
1036 {
1037 mbChar = (USHORT)(gAltNumPadValue & 0xFFFF);
1038 }
1039 else
1040 {
1041 /*
1042 * NOTE: the input value is considered modulo 256 as it is
1043 * stored in a 1-byte CHAR. Other input systems that hook and
1044 * re-implement the Alt+Numpad system (e.g. RichEdit, ...)
1045 * store instead the value in a 2-byte WORD, i.e. consider
1046 * the value modulo 65536.
1047 * See: https://devblogs.microsoft.com/oldnewthing/20240702-00/?p=109951
1048 */
1049 mbChar = (USHORT)(gAltNumPadValue & 0xFF);
1050 }
1051
1052 Status = pRtlCPToUnicodeN(&wchUnicodeChar,
1053 sizeof(wchUnicodeChar),
1054 NULL,
1055 (PCCH)&mbChar,
1056 sizeof(mbChar));
1057 }
1058
1059 /* Post the Unicode character to the focused message queue if conversion succeeded */
1060 if (NT_SUCCESS(Status))
1061 {
1062 MSG msgChar;
1063 msgChar.hwnd = pFocusQueue->spwndFocus ? UserHMGetHandle(pFocusQueue->spwndFocus) : NULL;
1064 msgChar.message = WM_CHAR;
1065 msgChar.wParam = wchUnicodeChar;
1066 msgChar.lParam = 1;
1067 msgChar.time = dwTime;
1068 msgChar.pt = gpsi->ptCursor;
1069
1070 MsqPostMessage(pFocusQueue->ptiKeyboard, &msgChar, FALSE, QS_KEY, 0, 0);
1071 }
1072 }
1073
1074 /* Reset the Alt+Numpad state */
1076 gAltNumPadValue = 0;
1077 }
1078
1079 return FALSE; /* More key processing has to be done */
1080}
1081
1082/*
1083 * UserSendKeyboardInput
1084 *
1085 * Process keyboard input from input devices and SendInput API
1086 */
1087BOOL NTAPI
1088ProcessKeyEvent(WORD wVk, WORD wScanCode, DWORD dwFlags, BOOL bInjected, DWORD dwTime, DWORD dwExtraInfo)
1089{
1090 WORD wSimpleVk, wFixedVk, wVk2;
1091 PUSER_MESSAGE_QUEUE pFocusQueue;
1092 PTHREADINFO pti;
1094 BOOL bIsDown = (dwFlags & KEYEVENTF_KEYUP) ? FALSE : TRUE;
1095 BOOL bPacket = (dwFlags & KEYEVENTF_UNICODE) ? TRUE : FALSE;
1096 BOOL bWasSimpleDown = FALSE, bPostMsg = TRUE, bIsSimpleDown;
1097 MSG Msg;
1098 static BOOL bMenuDownRecently = FALSE;
1099 BOOL bLangToggled = FALSE;
1100
1101 /* Get virtual key without shifts (VK_(L|R)* -> VK_*) */
1102 wSimpleVk = IntSimplifyVk(wVk);
1103
1105 {
1106 /* Japanese special! */
1108 {
1109 if (wSimpleVk == VK_OEM_ATTN)
1110 wSimpleVk = VK_CAPITAL;
1111 else if (wSimpleVk == VK_OEM_COPY)
1112 wSimpleVk = VK_OEM_FINISH;
1113 }
1114 }
1115
1116 /* Handle Alt+Numpad character composition */
1117 if (IntHandleAltNumpad(wSimpleVk, bIsDown, dwTime))
1118 return TRUE;
1119
1120 bWasSimpleDown = IS_KEY_DOWN(gafAsyncKeyState, wSimpleVk);
1121
1122 /* Update key without shifts */
1123 wVk2 = IntFixVk(wSimpleVk, !bExt);
1124 bIsSimpleDown = bIsDown || IS_KEY_DOWN(gafAsyncKeyState, wVk2);
1125 UpdateAsyncKeyState(wSimpleVk, bIsSimpleDown);
1126
1127 if (bIsDown)
1128 {
1129 /* Update keyboard LEDs */
1131 wSimpleVk,
1132 wScanCode);
1133 }
1134
1135 /* Call WH_KEYBOARD_LL hook */
1136 if (co_CallLowLevelKeyboardHook(wVk, wScanCode, dwFlags, bInjected, dwTime, dwExtraInfo))
1137 {
1138 ERR("Kbd msg dropped by WH_KEYBOARD_LL hook\n");
1139 bPostMsg = FALSE;
1140 }
1141
1142 /* Check if this is a hotkey */
1143 if (co_UserProcessHotKeys(wSimpleVk, bIsDown))
1144 {
1145 TRACE("HotKey Processed\n");
1146 bPostMsg = FALSE;
1147 }
1148
1149 wFixedVk = IntFixVk(wSimpleVk, bExt); /* LSHIFT + EXT = RSHIFT */
1150 if (wSimpleVk == VK_SHIFT) /* shift can't be extended */
1151 bExt = FALSE;
1152
1153 /* If we have a focus queue, post a keyboard message */
1154 pFocusQueue = IntGetFocusMessageQueue();
1155 TRACE("ProcessKeyEvent Q 0x%p Active pWnd 0x%p Focus pWnd 0x%p\n",
1156 pFocusQueue,
1157 (pFocusQueue ? pFocusQueue->spwndActive : NULL),
1158 (pFocusQueue ? pFocusQueue->spwndFocus : NULL));
1159
1160 /* If it is F10 or ALT is down and CTRL is up, it's a system key */
1161 if ( wVk == VK_F10 ||
1162 (wSimpleVk == VK_MENU && bMenuDownRecently) ||
1165 // See MSDN WM_SYSKEYDOWN/UP fixes last wine Win test_keyboard_input.
1166 (pFocusQueue && !pFocusQueue->spwndFocus) )
1167 {
1168 bMenuDownRecently = FALSE; // reset
1169 if (bIsDown)
1170 {
1171 Msg.message = WM_SYSKEYDOWN;
1172 if (wSimpleVk == VK_MENU)
1173 {
1174 // Note: If only LALT is pressed WM_SYSKEYUP is generated instead of WM_KEYUP
1175 bMenuDownRecently = TRUE;
1176 }
1177 }
1178 else
1179 Msg.message = WM_SYSKEYUP;
1180 }
1181 else
1182 {
1183 if (bIsDown)
1184 Msg.message = WM_KEYDOWN;
1185 else
1186 Msg.message = WM_KEYUP;
1187 }
1188
1189 /* Update async state of not simplified vk here.
1190 See user32_apitest:GetKeyState */
1191 UpdateAsyncKeyState(wFixedVk, bIsDown);
1192
1193 /* Alt-Tab/Esc Check. Use FocusQueue or RIT Queue */
1194 if (bIsSimpleDown && !bWasSimpleDown &&
1197 (wVk == VK_ESCAPE || wVk == VK_TAB))
1198 {
1199 TRACE("Alt-Tab/Esc Pressed wParam %x\n",wVk);
1200 }
1201
1202 /*
1203 * Check Language/Layout Toggle by [Left Alt]+Shift or Ctrl+Shift.
1204 * @see https://learn.microsoft.com/en-us/previous-versions/windows/it-pro/windows-2000-server/cc976564%28v=technet.10%29
1205 */
1207 {
1208 if (wSimpleVk == VK_SHIFT) /* Shift key is pressed or released */
1209 {
1210 UINT targetKey = ((gdwLanguageToggleKey == 1) ? VK_LMENU : VK_CONTROL);
1211 if (IS_KEY_DOWN(gafAsyncKeyState, targetKey))
1212 bLangToggled = IntCheckLanguageToggle(pFocusQueue, bIsDown, wVk, &gLanguageToggleKeyState);
1213 }
1214 else if ((wSimpleVk == VK_MENU && gdwLanguageToggleKey == 1) ||
1215 (wSimpleVk == VK_CONTROL && gdwLanguageToggleKey == 2))
1216 {
1218 bLangToggled = IntCheckLanguageToggle(pFocusQueue, bIsDown, 0, &gLanguageToggleKeyState);
1219 }
1220 }
1221 if (!bLangToggled && (gdwLayoutToggleKey == 1 || gdwLayoutToggleKey == 2))
1222 {
1223 if (wSimpleVk == VK_SHIFT) /* Shift key is pressed or released */
1224 {
1225 UINT targetKey = ((gdwLayoutToggleKey == 1) ? VK_LMENU : VK_CONTROL);
1226 if (IS_KEY_DOWN(gafAsyncKeyState, targetKey))
1227 IntCheckLanguageToggle(pFocusQueue, bIsDown, wVk, &gLayoutToggleKeyState);
1228 }
1229 else if ((wSimpleVk == VK_MENU && gdwLayoutToggleKey == 1) ||
1230 (wSimpleVk == VK_CONTROL && gdwLayoutToggleKey == 2))
1231 {
1233 IntCheckLanguageToggle(pFocusQueue, bIsDown, 0, &gLayoutToggleKeyState);
1234 }
1235 }
1236
1237 if (bIsDown && wVk == VK_SNAPSHOT)
1238 {
1239 if (pFocusQueue &&
1242 {
1243 // Snap from Active Window, Focus can be null.
1244 SnapWindow(pFocusQueue->spwndActive ? UserHMGetHandle(pFocusQueue->spwndActive) : NULL);
1245 }
1246 else
1247 SnapWindow(NULL); // Snap Desktop.
1248 }
1249 else if (pFocusQueue && bPostMsg)
1250 {
1251 PWND Wnd = pFocusQueue->spwndFocus; // SysInit.....
1252
1253 pti = pFocusQueue->ptiKeyboard;
1254
1255 if (!Wnd && pFocusQueue->spwndActive) // SysInit.....
1256 {
1257 // Going with Active. WM_SYSKEYXXX last wine Win test_keyboard_input.
1258 Wnd = pFocusQueue->spwndActive;
1259 }
1260 if (Wnd) pti = Wnd->head.pti;
1261
1262 /* Init message */
1263 Msg.hwnd = Wnd ? UserHMGetHandle(Wnd) : NULL;
1264 Msg.wParam = wFixedVk & 0xFF; /* Note: It's simplified by msg queue */
1265 Msg.lParam = MAKELPARAM(1, wScanCode);
1266 Msg.time = dwTime;
1267 Msg.pt = gpsi->ptCursor;
1268
1269 if ( Msg.message == WM_KEYDOWN || Msg.message == WM_SYSKEYDOWN )
1270 {
1271 if ( (Msg.wParam == VK_SHIFT ||
1272 Msg.wParam == VK_CONTROL ||
1273 Msg.wParam == VK_MENU ) &&
1275 {
1276 ERR("Set last input\n");
1277 //ptiLastInput = pti;
1278 }
1279 }
1280
1281 /* If it is VK_PACKET, high word of wParam is used for wchar */
1282 if (!bPacket)
1283 {
1284 if (bExt)
1285 Msg.lParam |= KF_EXTENDED << 16;
1287 Msg.lParam |= KF_ALTDOWN << 16;
1288 if (bWasSimpleDown)
1289 Msg.lParam |= KF_REPEAT << 16;
1290 if (!bIsDown)
1291 Msg.lParam |= KF_UP << 16;
1292 /* FIXME: Set KF_DLGMODE and KF_MENUMODE when needed */
1293 if (pFocusQueue->QF_flags & QF_DIALOGACTIVE)
1294 Msg.lParam |= KF_DLGMODE << 16;
1295 if (pFocusQueue->MenuOwner) // pti->pMenuState->fMenuStarted
1296 Msg.lParam |= KF_MENUMODE << 16;
1297 }
1298
1299 // Post mouse move before posting key buttons, to keep it syned.
1300 if (pFocusQueue->QF_flags & QF_MOUSEMOVED)
1301 {
1303 }
1304
1305 /* Post a keyboard message */
1306 TRACE("Posting keyboard msg %u wParam 0x%x lParam 0x%x\n", Msg.message, Msg.wParam, Msg.lParam);
1307 if (!Wnd) {ERR("Window is NULL\n");}
1308 MsqPostMessage(pti, &Msg, TRUE, QS_KEY, 0, dwExtraInfo);
1309 }
1310 return TRUE;
1311}
1312
1313BOOL NTAPI
1315{
1316 WORD wScanCode, wVk;
1317 PKL pKl = NULL;
1318 PKBDTABLES pKbdTbl;
1319 PUSER_MESSAGE_QUEUE pFocusQueue;
1320 DWORD dwTime;
1321 BOOL bExt = (pKbdInput->dwFlags & KEYEVENTF_EXTENDEDKEY) ? TRUE : FALSE;
1322
1324
1325 /* Find the target thread whose locale is in effect */
1326 pFocusQueue = IntGetFocusMessageQueue();
1327
1328 if (pFocusQueue && pFocusQueue->ptiKeyboard)
1329 {
1330 pKl = pFocusQueue->ptiKeyboard->KeyboardLayout;
1331 }
1332
1333 if (!pKl)
1335 if (!pKl)
1336 {
1337 ERR("No keyboard layout!\n");
1338 return FALSE;
1339 }
1340
1341 pKbdTbl = pKl->spkf->pKbdTbl;
1342
1343 /* Note: wScan field is always used */
1344 wScanCode = pKbdInput->wScan;
1345
1346 if (pKbdInput->dwFlags & KEYEVENTF_UNICODE)
1347 {
1348 /* Generate WM_KEYDOWN msg with wParam == VK_PACKET and
1349 high order word of lParam == pKbdInput->wScan */
1350 wVk = VK_PACKET;
1351 }
1352 else
1353 {
1354 wScanCode &= 0x7F;
1355 if (pKbdInput->dwFlags & KEYEVENTF_SCANCODE)
1356 {
1357 /* Don't ignore invalid scan codes */
1358 wVk = IntVscToVk(wScanCode | (bExt ? 0xE000 : 0), pKbdTbl);
1359 if (!wVk) /* use 0xFF if vsc is invalid */
1360 wVk = 0xFF;
1361 }
1362 else
1363 {
1364 wVk = pKbdInput->wVk;
1365 }
1366
1367 /* Remove all virtual key flags (KBDEXT, KBDMULTIVK, KBDSPECIAL, KBDNUMPAD) */
1368 wVk &= 0xFF;
1369 }
1370
1371 /* If time is given, use it */
1372 if (pKbdInput->time)
1373 dwTime = pKbdInput->time;
1374 else
1375 {
1377 }
1378
1379 if (wVk == VK_RMENU && (pKbdTbl->fLocaleFlags & KLLF_ALTGR))
1380 {
1381 /* For AltGr keyboards RALT generates CTRL events */
1382 ProcessKeyEvent(VK_LCONTROL, 0, pKbdInput->dwFlags & KEYEVENTF_KEYUP, bInjected, dwTime, 0);
1383 }
1384
1385 /* Finally process this key */
1386 return ProcessKeyEvent(wVk, wScanCode, pKbdInput->dwFlags, bInjected, dwTime, pKbdInput->dwExtraInfo);
1387}
1388
1389VOID
1390WINAPI
1392 PINPUT_DEVICE_INFO pDeviceInfo,
1393 PKEYBOARD_INPUT_DATA pKbdInputData,
1394 WORD wScanCode, WORD wVk)
1395{
1396 PTHREADINFO pti;
1397 HWND hwndTarget;
1398 WPARAM wParam;
1399 HRAWINPUT hRawInput;
1400 RAWKEYBOARD kb = {0};
1401 MSG Msg = {0};
1402 BOOL bIsDown = (pKbdInputData->Flags & KEY_BREAK) ? FALSE : TRUE;
1403
1404 if (!UserGetRawInputTarget(RIM_TYPEKEYBOARD, &pti, &hwndTarget, &wParam))
1405 return;
1406
1407 kb.MakeCode = wScanCode & 0x7F;
1408
1409 if (bIsDown)
1410 kb.Flags = RI_KEY_MAKE;
1411 else
1412 kb.Flags = RI_KEY_BREAK;
1413 kb.VKey = wVk & 0xFF; // Note: wVk is simplified by msg queue
1414
1415 if (bIsDown)
1416 kb.Message = WM_KEYDOWN;
1417 else
1418 kb.Message = WM_KEYUP;
1419 if (pKbdInputData->Flags & KEY_E1)
1420 {
1421 kb.Flags |= RI_KEY_E1;
1422 }
1423 if (pKbdInputData->Flags & KEY_E0)
1424 {
1425 kb.Flags |= RI_KEY_E0;
1426 }
1427
1428 kb.ExtraInformation = pKbdInputData->ExtraInformation;
1429 hRawInput = UserCreateRawInput(pti,
1430 RIM_TYPEKEYBOARD,
1431 (HANDLE)pDeviceInfo,
1432 wParam,
1433 &kb,
1434 sizeof(kb));
1435 if (!hRawInput)
1436 return;
1437
1438 Msg.hwnd = hwndTarget;
1439 Msg.message = WM_INPUT;
1440 Msg.wParam = wParam;
1441 Msg.lParam = (LPARAM)hRawInput;
1442 Msg.time = EngGetTickCount32();
1443 Msg.pt = gpsi->ptCursor;
1444
1445 if (!MsqPostMessage(pti, &Msg, TRUE, QS_RAWINPUT, 0, 0))
1446 UserFreeRawInput(pti->MessageQueue, hRawInput);
1447}
1448
1449/*
1450 * UserProcessKeyboardInput
1451 *
1452 * Process raw keyboard input data
1453 */
1454VOID NTAPI
1456 PINPUT_DEVICE_INFO pDeviceInfo,
1457 PKEYBOARD_INPUT_DATA pKbdInputData)
1458{
1459 WORD wScanCode, wVk;
1460 PKL pKl = NULL;
1461 PKBDTABLES pKbdTbl;
1462 PUSER_MESSAGE_QUEUE pFocusQueue;
1463
1464 /* Calculate scan code with prefix */
1465 wScanCode = pKbdInputData->MakeCode & 0x7F;
1466 if (pKbdInputData->Flags & KEY_E0)
1467 wScanCode |= 0xE000;
1468 if (pKbdInputData->Flags & KEY_E1)
1469 wScanCode |= 0xE100;
1470
1471 /* Find the target thread whose locale is in effect */
1472 pFocusQueue = IntGetFocusMessageQueue();
1473
1474 if (pFocusQueue && pFocusQueue->ptiKeyboard)
1475 {
1476 pKl = pFocusQueue->ptiKeyboard->KeyboardLayout;
1477 }
1478
1479 if (!pKl)
1481 if (!pKl)
1482 return;
1483
1484 pKbdTbl = pKl->spkf->pKbdTbl;
1485
1486 /* Convert scan code to virtual key.
1487 Note: We could call UserSendKeyboardInput using scan code,
1488 but it wouldn't interpret E1 key(s) properly */
1489 wVk = IntVscToVk(wScanCode, pKbdTbl);
1490 TRACE("UserProcessKeyboardInput: %x (break: %u) -> %x\n",
1491 wScanCode, (pKbdInputData->Flags & KEY_BREAK) ? 1u : 0, wVk);
1492
1493 if (RawInputEnabled == TRUE)
1494 UserRawInputProcessKeyboardInput(pDeviceInfo, pKbdInputData, wScanCode, wVk);
1495
1496 if (wVk)
1497 {
1498 KEYBDINPUT KbdInput;
1499
1500 /* Support numlock */
1502 {
1503 wVk = IntTranslateNumpadKey(wVk & 0xFF);
1504 }
1505
1506 /* Send keyboard input */
1507 KbdInput.wVk = wVk & 0xFF;
1508 KbdInput.wScan = wScanCode & 0x7F;
1509 KbdInput.dwFlags = 0;
1510 if (pKbdInputData->Flags & KEY_BREAK)
1511 KbdInput.dwFlags |= KEYEVENTF_KEYUP;
1512
1513 if (wVk & KBDEXT)
1514 KbdInput.dwFlags |= KEYEVENTF_EXTENDEDKEY;
1515 //
1516 // Based on wine input:test_Input_blackbox this is okay. It seems the
1517 // bit did not get set and more research is needed. Now the right
1518 // shift works.
1519 //
1520 if (wVk == VK_RSHIFT)
1521 KbdInput.dwFlags |= KEYEVENTF_EXTENDEDKEY;
1522
1523 KbdInput.time = 0;
1524 KbdInput.dwExtraInfo = pKbdInputData->ExtraInformation;
1525 UserSendKeyboardInput(&KbdInput, FALSE);
1526
1527 /* E1 keys don't have break code */
1528 if (pKbdInputData->Flags & KEY_E1)
1529 {
1530 /* Send key up event */
1531 KbdInput.dwFlags |= KEYEVENTF_KEYUP;
1532 UserSendKeyboardInput(&KbdInput, FALSE);
1533 }
1534 }
1535}
1536
1537/*
1538 * IntTranslateKbdMessage
1539 *
1540 * Addes WM_(SYS)CHAR messages to message queue if message
1541 * describes key which produce character.
1542 */
1545 UINT flags)
1546{
1547 PTHREADINFO pti;
1548 INT cch = 0, i;
1549 WCHAR wch[3] = { 0 };
1550 MSG NewMsg = { 0 };
1551 PKBDTABLES pKbdTbl;
1552 BOOL bResult = FALSE;
1553
1554 switch(lpMsg->message)
1555 {
1556 case WM_KEYDOWN:
1557 case WM_KEYUP:
1558 case WM_SYSKEYDOWN:
1559 case WM_SYSKEYUP:
1560 break;
1561 default:
1562 return FALSE;
1563 }
1564
1566
1567 if (!pti->KeyboardLayout)
1568 {
1569 PKL pDefKL = W32kGetDefaultKeyLayout();
1570 UserAssignmentLock((PVOID*)&(pti->KeyboardLayout), pDefKL);
1571 if (pDefKL)
1572 {
1573 pti->pClientInfo->hKL = pDefKL->hkl;
1574 pKbdTbl = pDefKL->spkf->pKbdTbl;
1575 }
1576 else
1577 {
1578 pti->pClientInfo->hKL = NULL;
1579 pKbdTbl = NULL;
1580 }
1581 }
1582 else
1583 pKbdTbl = pti->KeyboardLayout->spkf->pKbdTbl;
1584 if (!pKbdTbl)
1585 return FALSE;
1586
1587 if (lpMsg->message != WM_KEYDOWN && lpMsg->message != WM_SYSKEYDOWN)
1588 return FALSE;
1589
1590 /* Init pt, hwnd and time msg fields */
1591 NewMsg.pt = gpsi->ptCursor;
1592 NewMsg.hwnd = lpMsg->hwnd;
1593 NewMsg.time = EngGetTickCount32();
1594
1595 TRACE("Enter IntTranslateKbdMessage msg %s, vk %x\n",
1596 lpMsg->message == WM_SYSKEYDOWN ? "WM_SYSKEYDOWN" : "WM_KEYDOWN", lpMsg->wParam);
1597
1598 if (lpMsg->wParam == VK_PACKET)
1599 {
1600 NewMsg.message = (lpMsg->message == WM_KEYDOWN) ? WM_CHAR : WM_SYSCHAR;
1601 NewMsg.wParam = HIWORD(lpMsg->lParam);
1602 NewMsg.lParam = LOWORD(lpMsg->lParam);
1603 MsqPostMessage(pti, &NewMsg, FALSE, QS_KEY, 0, 0);
1604 return TRUE;
1605 }
1606
1607 cch = IntToUnicodeEx(lpMsg->wParam,
1608 HIWORD(lpMsg->lParam) & 0xFF,
1609 pti->MessageQueue->afKeyState,
1610 wch,
1611 sizeof(wch) / sizeof(wch[0]),
1612 0,
1613 pKbdTbl);
1614
1615 if (cch)
1616 {
1617 if (cch > 0) /* Normal characters */
1618 NewMsg.message = (lpMsg->message == WM_KEYDOWN) ? WM_CHAR : WM_SYSCHAR;
1619 else /* Dead character */
1620 {
1621 cch = -cch;
1622 NewMsg.message =
1624 }
1625 NewMsg.lParam = lpMsg->lParam;
1626
1627 /* Send all characters */
1628 for (i = 0; i < cch; ++i)
1629 {
1630 TRACE("Msg: %x '%lc' (%04x) %08x\n", NewMsg.message, wch[i], wch[i], NewMsg.lParam);
1631 NewMsg.wParam = wch[i];
1632 MsqPostMessage(pti, &NewMsg, FALSE, QS_KEY, 0, 0);
1633 }
1634 bResult = TRUE;
1635 }
1636
1637 TRACE("Leave IntTranslateKbdMessage ret %d, cch %d, msg %x, wch %x\n",
1638 bResult, cch, NewMsg.message, NewMsg.wParam);
1639 return bResult;
1640}
1641
1642/*
1643 * Map a virtual key code, or virtual scan code, to a scan code, key code,
1644 * or unshifted unicode character.
1645 *
1646 * Code: See Below
1647 * Type:
1648 * 0 -- Code is a virtual key code that is converted into a virtual scan code
1649 * that does not distinguish between left and right shift keys.
1650 * 1 -- Code is a virtual scan code that is converted into a virtual key code
1651 * that does not distinguish between left and right shift keys.
1652 * 2 -- Code is a virtual key code that is converted into an unshifted unicode
1653 * character.
1654 * 3 -- Code is a virtual scan code that is converted into a virtual key code
1655 * that distinguishes left and right shift keys.
1656 * KeyLayout: Keyboard layout handle
1657 *
1658 * @implemented
1659 */
1660static UINT
1662{
1663 UINT uRet = 0;
1664
1665 switch (Type)
1666 {
1667 case MAPVK_VK_TO_VSC:
1668 uCode = IntFixVk(uCode, FALSE);
1669 uRet = IntVkToVsc(uCode, pKbdTbl);
1670 if (uRet > 0xFF) // Fail for scancodes with prefix (e0, e1)
1671 uRet = 0;
1672 break;
1673
1674 case MAPVK_VSC_TO_VK:
1675 uRet = IntVscToVk(uCode, pKbdTbl) & 0xFF;
1676 uRet = IntSimplifyVk(uRet);
1677 break;
1678
1679 case MAPVK_VK_TO_CHAR:
1680 uRet = (UINT)IntVkToChar(uCode, pKbdTbl);
1681 break;
1682
1683 case MAPVK_VSC_TO_VK_EX:
1684 uRet = IntVscToVk(uCode, pKbdTbl) & 0xFF;
1685 break;
1686
1687 case MAPVK_VK_TO_VSC_EX:
1688 uRet = IntVkToVsc(uCode, pKbdTbl);
1689 break;
1690
1691 default:
1693 ERR("Wrong type value: %u\n", Type);
1694 }
1695
1696 return uRet;
1697}
1698
1699/*
1700 * NtUserMapVirtualKeyEx
1701 *
1702 * Map a virtual key code, or virtual scan code, to a scan code, key code,
1703 * or unshifted unicode character. See IntMapVirtualKeyEx.
1704 */
1705UINT
1707NtUserMapVirtualKeyEx(UINT uCode, UINT uType, DWORD keyboardId, HKL dwhkl)
1708{
1709 PKBDTABLES pKbdTbl = NULL;
1710 UINT ret = 0;
1711
1712 TRACE("Enter NtUserMapVirtualKeyEx\n");
1714
1715 if (!dwhkl)
1716 {
1717 PTHREADINFO pti;
1718
1720 if (pti && pti->KeyboardLayout)
1721 pKbdTbl = pti->KeyboardLayout->spkf->pKbdTbl;
1722 }
1723 else
1724 {
1725 PKL pKl;
1726
1727 pKl = UserHklToKbl(dwhkl);
1728 if (pKl)
1729 pKbdTbl = pKl->spkf->pKbdTbl;
1730 }
1731
1732 if (pKbdTbl)
1733 ret = IntMapVirtualKeyEx(uCode, uType, pKbdTbl);
1734
1735 UserLeave();
1736 TRACE("Leave NtUserMapVirtualKeyEx, ret=%u\n", ret);
1737 return ret;
1738}
1739
1740/*
1741 * NtUserToUnicodeEx
1742 *
1743 * Translates virtual key to characters
1744 */
1745int
1748 UINT wVirtKey,
1749 UINT wScanCode,
1750 PBYTE pKeyStateUnsafe,
1751 LPWSTR pwszBuffUnsafe,
1752 INT cchBuff,
1753 UINT wFlags,
1754 HKL dwhkl)
1755{
1756 PTHREADINFO pti;
1757 BYTE afKeyState[256 * 2 / 8] = {0};
1758 PWCHAR pwszBuff = NULL;
1759 INT i, iRet = 0;
1760 PKL pKl = NULL;
1762
1763 TRACE("Enter NtUserSetKeyboardState\n");
1764
1765 /* Return 0 if SC_KEY_UP bit is set */
1766 if (wScanCode & SC_KEY_UP || wVirtKey >= 0x100)
1767 {
1768 ERR("Invalid parameter\n");
1769 return 0;
1770 }
1771
1772 _SEH2_TRY
1773 {
1774 /* Probe and copy key state to smaller bitmap */
1775 ProbeForRead(pKeyStateUnsafe, 256 * sizeof(BYTE), 1);
1776 for (i = 0; i < 256; ++i)
1777 {
1778 if (pKeyStateUnsafe[i] & KS_DOWN_BIT)
1779 SET_KEY_DOWN(afKeyState, i, TRUE);
1780 if (pKeyStateUnsafe[i] & KS_LOCK_BIT)
1781 SET_KEY_LOCKED(afKeyState, i, TRUE);
1782 }
1783 }
1785 {
1786 ERR("Cannot copy key state\n");
1788 _SEH2_YIELD(return 0);
1789 }
1790 _SEH2_END;
1791
1792 pwszBuff = ExAllocatePoolWithTag(NonPagedPool, sizeof(WCHAR) * cchBuff, TAG_STRING);
1793 if (!pwszBuff)
1794 {
1795 ERR("ExAllocatePoolWithTag(%u) failed\n", sizeof(WCHAR) * cchBuff);
1796 return 0;
1797 }
1798 RtlZeroMemory(pwszBuff, sizeof(WCHAR) * cchBuff);
1799
1800 UserEnterExclusive(); // Note: We modify wchDead static variable
1801
1802 if (dwhkl)
1803 pKl = UserHklToKbl(dwhkl);
1804
1805 if (!pKl)
1806 {
1808 pKl = pti->KeyboardLayout;
1809 }
1810
1811 if (pKl)
1812 {
1813 iRet = IntToUnicodeEx(wVirtKey,
1814 wScanCode,
1815 afKeyState,
1816 pwszBuff,
1817 cchBuff,
1818 wFlags,
1819 pKl->spkf->pKbdTbl);
1820
1821 if (iRet)
1822 {
1823 Status = MmCopyToCaller(pwszBuffUnsafe, pwszBuff, cchBuff * sizeof(WCHAR));
1824 }
1825 }
1826 else
1827 {
1828 ERR("No keyboard layout ?!\n");
1830 }
1831
1832 ExFreePoolWithTag(pwszBuff, TAG_STRING);
1833
1834 if (!NT_SUCCESS(Status))
1835 {
1836 iRet = 0;
1838 }
1839
1840 UserLeave();
1841 TRACE("Leave NtUserSetKeyboardState, ret=%i\n", iRet);
1842 return iRet;
1843}
1844
1845/*
1846 * NtUserGetKeyNameText
1847 *
1848 * Gets key name from keyboard layout
1849 */
1850DWORD
1853{
1854 PTHREADINFO pti;
1855 DWORD i, dwRet = 0;
1856 SIZE_T cchKeyName;
1857 WORD wScanCode = (lParam >> 16) & 0xFF;
1858 BOOL bExtKey = (HIWORD(lParam) & KF_EXTENDED) ? TRUE : FALSE;
1859 PKBDTABLES pKbdTbl;
1860 VSC_LPWSTR *pKeyNames = NULL;
1861 CONST WCHAR *pKeyName = NULL;
1862 WCHAR KeyNameBuf[2];
1863
1864 TRACE("Enter NtUserGetKeyNameText\n");
1865
1867
1868 /* Get current keyboard layout */
1870 pKbdTbl = pti ? pti->KeyboardLayout->spkf->pKbdTbl : NULL;
1871
1872 if (!pKbdTbl || cchSize < 1)
1873 {
1874 ERR("Invalid parameter\n");
1875 goto cleanup;
1876 }
1877
1878 /* "Do not care" flag */
1880 {
1881 /* Note: We could do vsc -> vk -> vsc conversion, instead of using
1882 hardcoded scan codes, but it's not what Windows does */
1883 if (wScanCode == SCANCODE_RSHIFT && !bExtKey)
1884 wScanCode = SCANCODE_LSHIFT;
1885 else if (wScanCode == SCANCODE_CTRL || wScanCode == SCANCODE_ALT)
1886 bExtKey = FALSE;
1887 }
1888
1889 if (bExtKey)
1890 pKeyNames = pKbdTbl->pKeyNamesExt;
1891 else
1892 pKeyNames = pKbdTbl->pKeyNames;
1893
1894 for (i = 0; pKeyNames[i].pwsz; i++)
1895 {
1896 if (pKeyNames[i].vsc == wScanCode)
1897 {
1898 pKeyName = pKeyNames[i].pwsz;
1899 break;
1900 }
1901 }
1902
1903 if (!pKeyName)
1904 {
1905 WORD wVk = IntVscToVk(wScanCode, pKbdTbl);
1906
1907 if (wVk)
1908 {
1909 KeyNameBuf[0] = IntVkToChar(wVk, pKbdTbl);
1910 KeyNameBuf[1] = 0;
1911 if (KeyNameBuf[0])
1912 pKeyName = KeyNameBuf;
1913 }
1914 }
1915
1916 if (pKeyName)
1917 {
1918 cchKeyName = wcslen(pKeyName);
1919 if (cchKeyName > (cchSize - 1UL))
1920 cchKeyName = cchSize - 1UL; // Don't count '\0'
1921
1922 _SEH2_TRY
1923 {
1924 ProbeForWrite(lpString, (cchKeyName + 1) * sizeof(WCHAR), 1);
1925 RtlCopyMemory(lpString, pKeyName, cchKeyName * sizeof(WCHAR));
1926 lpString[cchKeyName] = UNICODE_NULL;
1927 dwRet = cchKeyName;
1928 }
1930 {
1932 }
1933 _SEH2_END;
1934 }
1935 else
1936 {
1938 }
1939
1940cleanup:
1941 UserLeave();
1942 TRACE("Leave NtUserGetKeyNameText, ret=%lu\n", dwRet);
1943 return dwRet;
1944}
1945
1946/*
1947 * UserGetKeyboardType
1948 *
1949 * Returns some keyboard specific information
1950 */
1953 DWORD dwTypeFlag)
1954{
1955 switch (dwTypeFlag)
1956 {
1957 case 0: /* Keyboard type */
1959 case 1: /* Keyboard Subtype */
1961 case 2: /* Number of F-keys */
1963 default:
1964 ERR("Unknown type!\n");
1965 return 0; /* Note: we don't have to set last error here */
1966 }
1967}
1968
1969/*
1970 * NtUserVkKeyScanEx
1971 *
1972 * Based on IntTranslateChar, instead of processing VirtualKey match,
1973 * look for wChar match.
1974 */
1975DWORD
1978 WCHAR wch,
1979 HKL dwhkl,
1980 BOOL bUsehKL)
1981{
1982 PKBDTABLES pKbdTbl;
1983 PVK_TO_WCHAR_TABLE pVkToWchTbl;
1984 PVK_TO_WCHARS10 pVkToWch;
1985 PKL pKl = NULL;
1986 DWORD i, dwModBits = 0, dwModNumber = 0, Ret = (DWORD)-1;
1987
1988 TRACE("NtUserVkKeyScanEx() wch %u, KbdLayout 0x%p\n", wch, dwhkl);
1990
1991 if (bUsehKL)
1992 {
1993 // Use given keyboard layout
1994 if (dwhkl)
1995 pKl = UserHklToKbl(dwhkl);
1996 }
1997 else
1998 {
1999 // Use thread keyboard layout
2000 pKl = ((PTHREADINFO)PsGetCurrentThreadWin32Thread())->KeyboardLayout;
2001 }
2002
2003 if (!pKl)
2004 goto Exit;
2005
2006 pKbdTbl = pKl->spkf->pKbdTbl;
2007
2008 // Interate through all VkToWchar tables while pVkToWchars is not NULL
2009 for (i = 0; pKbdTbl->pVkToWcharTable[i].pVkToWchars; i++)
2010 {
2011 pVkToWchTbl = &pKbdTbl->pVkToWcharTable[i];
2012 pVkToWch = (PVK_TO_WCHARS10)(pVkToWchTbl->pVkToWchars);
2013
2014 // Interate through all virtual keys
2015 while (pVkToWch->VirtualKey)
2016 {
2017 for (dwModNumber = 0; dwModNumber < pVkToWchTbl->nModifications; dwModNumber++)
2018 {
2019 if (pVkToWch->wch[dwModNumber] == wch)
2020 {
2021 dwModBits = pKbdTbl->pCharModifiers->ModNumber[dwModNumber];
2022 TRACE("i %lu wC %04x: dwModBits %08x dwModNumber %08x MaxModBits %08x\n",
2023 i, wch, dwModBits, dwModNumber, pKbdTbl->pCharModifiers->wMaxModBits);
2024 Ret = (dwModBits << 8) | (pVkToWch->VirtualKey & 0xFF);
2025 goto Exit;
2026 }
2027 }
2028 pVkToWch = (PVK_TO_WCHARS10)(((BYTE *)pVkToWch) + pVkToWchTbl->cbSize);
2029 }
2030 }
2031Exit:
2032 UserLeave();
2033 return Ret;
2034}
2035
2036/* EOF */
#define CODE_SEG(...)
#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: precomp.h:61
#define ERR(fmt,...)
Definition: precomp.h:57
#define DBG_DEFAULT_CHANNEL(ch)
Definition: debug.h:106
#define IsCJKCodePage(CodePage)
Definition: cjkcode.h:27
struct @1907 Msg[]
WPARAM wParam
Definition: combotst.c:138
LPARAM lParam
Definition: combotst.c:139
#define STATUS_INVALID_HANDLE
Definition: d3dkmdt.h:40
#define STATUS_NOT_SUPPORTED
Definition: d3dkmdt.h:48
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:33
#define APIENTRY
Definition: api.h:79
#define NTSTATUS
Definition: precomp.h:19
#define ERROR_INVALID_PARAMETER
Definition: compat.h:101
static void cleanup(void)
Definition: main.c:1335
_ACRTIMP size_t __cdecl wcslen(const wchar_t *)
Definition: wcs.c:2988
return ret
Definition: mutex.c:147
#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
unsigned short WORD
Definition: ntddk_ex.h:93
unsigned int BOOL
Definition: ntddk_ex.h:94
unsigned long DWORD
Definition: ntddk_ex.h:95
Status
Definition: gdiplustypes.h:24
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
unsigned int UINT
Definition: sysinfo.c:13
PSERVERINFO gpsi
Definition: imm.c:18
#define UserHMGetHandle(obj)
Definition: ntuser.h:233
#define EXCEPTION_EXECUTE_HANDLER
Definition: excpt.h:90
#define WCH_DEAD
Definition: kbd.h:170
#define SCANCODE_LSHIFT
Definition: kbd.h:184
#define SCANCODE_ALT
Definition: kbd.h:187
#define CAPLOK
Definition: kbd.h:174
#define WCH_LGTR
Definition: kbd.h:171
#define KBDALT
Definition: kbd.h:71
#define WCH_NONE
Definition: kbd.h:169
#define CAPLOKALTGR
Definition: kbd.h:176
#define KBDCTRL
Definition: kbd.h:70
#define KBDNUMPAD
Definition: kbd.h:66
#define SCANCODE_RSHIFT
Definition: kbd.h:185
#define KBDEXT
Definition: kbd.h:63
#define KLLF_ALTGR
Definition: kbd.h:147
#define SCANCODE_CTRL
Definition: kbd.h:186
#define KBDSHIFT
Definition: kbd.h:69
USHORT LANGID
Definition: mui.h:9
LONG_PTR LPARAM
Definition: minwindef.h:175
LONG_PTR LRESULT
Definition: minwindef.h:176
UINT_PTR WPARAM
Definition: minwindef.h:174
int * PINT
Definition: minwindef.h:150
BOOL * PBOOL
Definition: minwindef.h:137
#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:88
UINT_PTR HKL
Definition: msctf.idl:125
VOID FASTCALL IntCoalesceMouseMove(PTHREADINFO pti)
Definition: msgqueue.c:551
BOOL 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:109
#define QF_MOUSEMOVED
Definition: msgqueue.h:102
*BytesInUnicodeString PWCH _In_ ULONG _Out_opt_ PULONG BytesInUnicodeString
Definition: rtlfuncs.h:2082
NTSYSAPI VOID NTAPI RtlGetDefaultCodePage(_Out_ PUSHORT AnsiCodePage, _Out_ PUSHORT OemCodePage)
*BytesInUnicodeString PWCH _In_ ULONG MaxBytesInUnicodeString
Definition: rtlfuncs.h:2081
_In_ LPWSTR _In_ DWORD _In_ DWORD _In_ DWORD dwFlags
Definition: netsh.h:141
_Use_decl_annotations_ NTSTATUS NTAPI RtlMultiByteToUnicodeN(_Out_ PWCH UnicodeString, _In_ ULONG UnicodeSize, _Out_opt_ PULONG ResultSize, _In_ PCCH MbString, _In_ ULONG MbSize)
Definition: nlsboot.c:63
_Use_decl_annotations_ NTSTATUS NTAPI RtlOemToUnicodeN(_Out_ PWCHAR UnicodeString, _In_ ULONG UnicodeSize, _Out_opt_ PULONG ResultSize, _In_ PCCH OemString, _In_ ULONG OemSize)
Definition: nlsboot.c:283
#define _In_reads_bytes_(s)
Definition: no_sal2.h:170
#define _Out_opt_
Definition: no_sal2.h:214
#define _Inout_
Definition: no_sal2.h:162
#define _Out_writes_bytes_to_(s, c)
Definition: no_sal2.h:190
#define _In_
Definition: no_sal2.h:158
#define FASTCALL
Definition: nt_native.h:50
#define DWORD
Definition: nt_native.h:44
WCHAR * PWCH
Definition: ntbasedef.h:422
#define DEFAULT_UNREACHABLE
#define UNICODE_NULL
CONST CHAR * PCCH
Definition: ntbasedef.h:404
#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
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
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:829
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:255
VOID FASTCALL UserEnterShared(VOID)
Definition: ntuser.c:241
VOID FASTCALL UserEnterExclusive(VOID)
Definition: ntuser.c:247
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 WCHAR
Definition: pedump.c:58
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
_In_ HBITMAP hbm
Definition: ntgdi.h:2804
__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)
#define VK_CLEAR
Definition: winuser.h:2236
#define QS_KEY
Definition: winuser.h:885
#define VK_NUMPAD3
Definition: winuser.h:2278
#define VK_SNAPSHOT
Definition: winuser.h:2267
#define VK_TAB
Definition: winuser.h:2235
#define MAKELPARAM(l, h)
Definition: winuser.h:4116
#define WM_KEYUP
Definition: winuser.h:1744
#define LLKHF_EXTENDED
Definition: winuser.h:2687
#define DCX_WINDOW
Definition: winuser.h:2149
#define VK_NUMPAD1
Definition: winuser.h:2276
#define VK_F10
Definition: winuser.h:2300
#define VK_NUMPAD2
Definition: winuser.h:2277
#define VK_CAPITAL
Definition: winuser.h:2242
#define MAPVK_VSC_TO_VK_EX
Definition: winuser.h:2394
#define VK_NUMPAD4
Definition: winuser.h:2279
#define KF_ALTDOWN
Definition: winuser.h:2485
#define VK_SCROLL
Definition: winuser.h:2316
#define KF_EXTENDED
Definition: winuser.h:2482
#define VK_CONTROL
Definition: winuser.h:2239
#define HC_ACTION
Definition: winuser.h:48
#define VK_RSHIFT
Definition: winuser.h:2319
#define VK_UP
Definition: winuser.h:2261
#define WM_INPUT
Definition: winuser.h:1740
#define VK_OEM_FINISH
Definition: winuser.h:2375
#define VK_LSHIFT
Definition: winuser.h:2318
#define VK_LCONTROL
Definition: winuser.h:2320
#define VK_NUMPAD0
Definition: winuser.h:2275
#define LLKHF_ALTDOWN
Definition: winuser.h:2689
#define VK_NUMPAD6
Definition: winuser.h:2281
#define MAPVK_VSC_TO_VK
Definition: winuser.h:2392
#define VK_NEXT
Definition: winuser.h:2257
#define VK_RCONTROL
Definition: winuser.h:2321
#define KF_UP
Definition: winuser.h:2487
#define KF_MENUMODE
Definition: winuser.h:2484
#define WM_SYSCHAR
Definition: winuser.h:1749
#define WM_SYSDEADCHAR
Definition: winuser.h:1750
#define VK_RMENU
Definition: winuser.h:2323
#define VK_NUMPAD9
Definition: winuser.h:2284
#define VK_OEM_ATTN
Definition: winuser.h:2374
#define VK_OEM_COPY
Definition: winuser.h:2376
#define VK_END
Definition: winuser.h:2258
#define VK_HOME
Definition: winuser.h:2259
#define VK_ADD
Definition: winuser.h:2286
#define LLKHF_UP
Definition: winuser.h:2690
#define WM_SYSKEYUP
Definition: winuser.h:1748
#define WH_KEYBOARD_LL
Definition: winuser.h:43
#define LLKHF_INJECTED
Definition: winuser.h:2688
#define WM_CHAR
Definition: winuser.h:1745
#define MAPVK_VK_TO_CHAR
Definition: winuser.h:2393
#define VK_NUMPAD5
Definition: winuser.h:2280
#define VK_LEFT
Definition: winuser.h:2260
#define KEYEVENTF_EXTENDEDKEY
Definition: winuser.h:1112
#define VK_NUMPAD7
Definition: winuser.h:2282
#define VK_RIGHT
Definition: winuser.h:2262
#define VK_DOWN
Definition: winuser.h:2263
#define VK_NUMLOCK
Definition: winuser.h:2315
#define KF_REPEAT
Definition: winuser.h:2486
#define VK_SHIFT
Definition: winuser.h:2238
#define VK_PRIOR
Definition: winuser.h:2256
#define VK_DELETE
Definition: winuser.h:2269
#define MAPVK_VK_TO_VSC
Definition: winuser.h:2391
#define WM_KEYDOWN
Definition: winuser.h:1743
#define VK_NUMPAD8
Definition: winuser.h:2283
#define MAPVK_VK_TO_VSC_EX
Definition: winuser.h:2395
#define VK_DECIMAL
Definition: winuser.h:2289
#define VK_ESCAPE
Definition: winuser.h:2250
#define WM_DEADCHAR
Definition: winuser.h:1746
#define KEYEVENTF_KEYUP
Definition: winuser.h:1113
#define WM_SYSKEYDOWN
Definition: winuser.h:1747
#define VK_INSERT
Definition: winuser.h:2268
#define KF_DLGMODE
Definition: winuser.h:2483
#define VK_LMENU
Definition: winuser.h:2322
#define VK_MENU
Definition: winuser.h:2240
#define _SEH2_GetExceptionCode()
Definition: pseh2_64.h:204
#define _SEH2_EXCEPT(...)
Definition: pseh2_64.h:104
#define _SEH2_END
Definition: pseh2_64.h:194
#define _SEH2_TRY
Definition: pseh2_64.h:93
#define _SEH2_YIELD(__stmt)
Definition: pseh2_64.h:207
#define LANG_JAPANESE
Definition: nls.h:76
#define PRIMARYLANGID(l)
Definition: nls.h:16
#define UINT
Definition: utils.c:29
_In_ UINT _In_ UINT cch
Definition: shellapi.h:428
#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:27
long bottom
Definition: dcommon.idl:29
long right
Definition: dcommon.idl:29
long left
Definition: dcommon.idl:29
long top
Definition: dcommon.idl:29
USHORT IndicatorFlags
Definition: ntddkbd.h:115
USHORT MakeCode
Definition: ntddkbd.h:114
BYTE bMaxVSCtoVK
Definition: kbd.h:159
DWORD fLocaleFlags
Definition: kbd.h:162
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
struct _CLIENTINFO * pClientInfo
Definition: win32.h:95
struct tagKL * KeyboardLayout
Definition: win32.h:91
struct _USER_MESSAGE_QUEUE * MessageQueue
Definition: win32.h:90
PTHREADINFO ptiKeyboard
Definition: msgqueue.h:56
BYTE nModifications
Definition: kbd.h:107
Definition: ntuser.h:698
THRDESKHEAD head
Definition: ntuser.h:699
RECT rcWindow
Definition: ntuser.h:720
struct _KBDTABLES * pKbdTbl
Definition: input.h:22
ULONG_PTR dwExtraInfo
Definition: winuser.h:3920
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:28
DWORD dwFontSigs
Definition: input.h:35
PKBDFILE spkf
Definition: input.h:34
HKL hkl
Definition: input.h:33
UINT message
Definition: winuser.h:3223
HWND hwnd
Definition: winuser.h:3222
WPARAM wParam
Definition: winuser.h:3224
LPARAM lParam
Definition: winuser.h:3225
BOOL fIncSerialNumber
Definition: ntuser.h:1176
BOOL fGlobalHandle
Definition: ntuser.h:1175
TW_UINT32 TW_UINT16 TW_UINT16 MSG
Definition: twain.h:1829
uint32_t * PULONG
Definition: typedefs.h:59
uint16_t * LPWSTR
Definition: typedefs.h:56
#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
uint32_t ULONG
Definition: typedefs.h:59
#define HIWORD(l)
Definition: typedefs.h:247
#define STATUS_INSUFFICIENT_RESOURCES
Definition: udferr_usr.h:158
#define KL_UNLOAD
Definition: undocuser.h:183
PWND FASTCALL UserGetWindowObject(HWND hWnd)
Definition: window.c:123
INT FASTCALL UserReleaseDC(PWND Window, HDC hDc, BOOL EndPaint)
Definition: windc.c:918
HDC FASTCALL UserGetDCEx(PWND Window OPTIONAL, HANDLE ClipRegion, ULONG Flags)
PUSBUSER_REQUEST_HEADER Block
Definition: userreq.cpp:697
_Must_inspect_result_ _In_ WDFDEVICE _In_ WDFSTRING String
Definition: wdfdevice.h:2439
WDF_EXTERN_C_START typedef _Must_inspect_result_ _In_opt_ PCUNICODE_STRING UnicodeString
Definition: wdfstring.h:64
_Must_inspect_result_ _In_ WDFUSBDEVICE _In_opt_ WDFREQUEST _In_opt_ PWDF_REQUEST_SEND_OPTIONS _Out_writes_opt_ NumCharacters PUSHORT _Inout_ PUSHORT _In_ UCHAR _In_opt_ USHORT LangID
Definition: wdfusb.h:1083
HDC hdcMem
Definition: welcome.c:104
VOID FASTCALL SetLastNtError(_In_ NTSTATUS Status)
Definition: error.c:30
BOOL NTAPI GreDeleteObject(HGDIOBJ hobj)
Definition: gdiobj.c:1158
USHORT gusLanguageID
Definition: init.c:12
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:1402
PUSER_MESSAGE_QUEUE FASTCALL IntGetFocusMessageQueue(VOID)
Definition: desktop.c:1335
BOOL NTAPI co_UserProcessHotKeys(WORD wVk, BOOL bIsDown)
Definition: hotkey.c:191
HANDLE ghKeyboardDevice
Definition: input.c:33
#define SET_KEY_DOWN(ks, vk, down)
Definition: input.h:176
#define KS_DOWN_BIT
Definition: input.h:88
BOOL FASTCALL UserFreeRawInput(PUSER_MESSAGE_QUEUE MessageQueue, HRAWINPUT hRawInput)
Definition: rawinput.c:364
BOOL FASTCALL UserGetRawInputTarget(DWORD dwType, PTHREADINFO *ppti, HWND *phwndTarget, WPARAM *pwParam)
Definition: rawinput.c:413
DWORD gSystemFS
Definition: kbdlayout.c:24
PKL NTAPI UserHklToKbl(HKL hKl)
Definition: kbdlayout.c:539
#define IS_KEY_DOWN(ks, vk)
Definition: input.h:174
HRAWINPUT FASTCALL UserCreateRawInput(PTHREADINFO pti, DWORD dwType, HANDLE hDevice, WPARAM wParam, CONST VOID *pData, UINT cbData)
Definition: rawinput.c:323
#define SC_KEY_UP
Definition: input.h:91
#define LP_DO_NOT_CARE_BIT
Definition: input.h:93
#define KS_LOCK_BIT
Definition: input.h:89
#define IS_KEY_LOCKED(ks, vk)
Definition: input.h:175
#define SET_KEY_LOCKED(ks, vk, down)
Definition: input.h:179
PKL W32kGetDefaultKeyLayout(VOID)
Definition: kbdlayout.c:512
BOOLEAN RawInputEnabled
Definition: rawinput.c:38
static KEYBOARD_INDICATOR_PARAMETERS gIndicators
Definition: keyboard.c:16
KEYBOARD_ATTRIBUTES gKeyboardInfo
Definition: keyboard.c:17
static ULONG gAltNumPadValue
Definition: keyboard.c:35
static DWORD IntGetModBits(PKBDTABLES pKbdTbl, PBYTE pKeyState)
Definition: keyboard.c:296
static enum _ALTNUM_STATE gAltNumPadState
BOOL FASTCALL IntTranslateKbdMessage(LPMSG lpMsg, UINT flags)
Definition: keyboard.c:1544
VOID WINAPI UserRawInputProcessKeyboardInput(PINPUT_DEVICE_INFO pDeviceInfo, PKEYBOARD_INPUT_DATA pKbdInputData, WORD wScanCode, WORD wVk)
Definition: keyboard.c:1391
static NTSTATUS APIENTRY IntKeyboardUpdateLeds(HANDLE hKeyboardDevice, WORD wVk, WORD wScanCode)
Definition: keyboard.c:124
DWORD APIENTRY NtUserVkKeyScanEx(WCHAR wch, HKL dwhkl, BOOL bUsehKL)
Definition: keyboard.c:1977
static INT gLayoutToggleKeyState
Definition: keyboard.c:20
int APIENTRY NtUserToUnicodeEx(UINT wVirtKey, UINT wScanCode, PBYTE pKeyStateUnsafe, LPWSTR pwszBuffUnsafe, INT cchBuff, UINT wFlags, HKL dwhkl)
Definition: keyboard.c:1747
BYTE gafAsyncKeyState[256 *2/8]
Definition: keyboard.c:13
BOOL NTAPI UserSendKeyboardInput(KEYBDINPUT *pKbdInput, BOOL bInjected)
Definition: keyboard.c:1314
static WORD IntFixVk(WORD wVk, BOOL bExt)
Definition: keyboard.c:245
static VOID SnapWindow(HWND hWnd)
Definition: keyboard.c:721
static BOOL IntTranslateChar(WORD wVirtKey, PBYTE pKeyState, PBOOL pbDead, PBOOL pbLigature, PWCHAR pwcTranslatedChar, PKBDTABLES pKbdTbl)
Definition: keyboard.c:318
_ALTNUM_STATE
Definition: keyboard.c:27
@ ALTNUM_INACTIVE
Definition: keyboard.c:28
@ ALTNUM_HEX_UTF
Definition: keyboard.c:32
@ ALTNUM_OEM
Definition: keyboard.c:29
@ ALTNUM_HEX_ACP
Definition: keyboard.c:31
@ ALTNUM_ACP
Definition: keyboard.c:30
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:430
static WCHAR FASTCALL IntVkToChar(WORD wVk, PKBDTABLES pKbdTbl)
Definition: keyboard.c:603
DWORD gdwLayoutToggleKey
Definition: keyboard.c:21
static BOOL IntCheckLanguageToggle(_In_ PUSER_MESSAGE_QUEUE pFocusQueue, _In_ BOOL bIsDown, _In_ WORD wVk, _Inout_ PINT pKeyState)
Definition: keyboard.c:852
DWORD APIENTRY NtUserGetKeyNameText(LONG lParam, LPWSTR lpString, int cchSize)
Definition: keyboard.c:1852
static LRESULT co_CallLowLevelKeyboardHook(WORD wVk, WORD wScanCode, DWORD dwFlags, BOOL bInjected, DWORD dwTime, DWORD dwExtraInfo)
Definition: keyboard.c:685
static PKL FASTCALL IntGetNextKL(_In_ PKL pKL, _In_ BOOL bNext, _In_ BOOL bSameLang)
Definition: keyboard.c:794
static PKEYBOARD_INDICATOR_TRANSLATION gpKeyboardIndicatorTrans
Definition: keyboard.c:15
static UINT IntMapVirtualKeyEx(UINT uCode, UINT Type, PKBDTABLES pKbdTbl)
Definition: keyboard.c:1661
VOID NTAPI UserInitKeyboard(HANDLE hKeyboardDevice)
Definition: keyboard.c:178
static BOOL IntHandleAltNumpad(_In_ WORD wVk, _In_ BOOL bIsDown, _In_ DWORD dwTime)
Handles Alt+Numpad character composition.
Definition: keyboard.c:897
NTSTATUS APIENTRY IntKeyboardGetIndicatorTrans(HANDLE hKeyboardDevice, PKEYBOARD_INDICATOR_TRANSLATION *ppIndicatorTrans)
Definition: keyboard.c:67
static BYTE gafAsyncKeyStateRecentDown[256/8]
Definition: keyboard.c:14
DWORD FASTCALL UserGetKeyboardType(DWORD dwTypeFlag)
Definition: keyboard.c:1952
static VOID NTAPI UpdateAsyncKeyState(WORD wVk, BOOL bIsDown)
Definition: keyboard.c:664
SHORT APIENTRY NtUserGetAsyncKeyState(INT Key)
Definition: keyboard.c:630
static INT gLanguageToggleKeyState
Definition: keyboard.c:18
NTSTATUS NTAPI InitKeyboardImpl(VOID)
Definition: keyboard.c:48
VOID NTAPI UserProcessKeyboardInput(PINPUT_DEVICE_INFO pDeviceInfo, PKEYBOARD_INPUT_DATA pKbdInputData)
Definition: keyboard.c:1455
BOOL NTAPI ProcessKeyEvent(WORD wVk, WORD wScanCode, DWORD dwFlags, BOOL bInjected, DWORD dwTime, DWORD dwExtraInfo)
Definition: keyboard.c:1088
BOOL gbEnableHexNumpad
Definition: keyboard.c:36
static WORD FASTCALL IntVkToVsc(WORD wVk, PKBDTABLES pKbdTbl)
Definition: keyboard.c:523
static WORD FASTCALL IntVscToVk(WORD wScanCode, PKBDTABLES pKbdTbl)
Definition: keyboard.c:560
static VOID IntLanguageToggle(_In_ PUSER_MESSAGE_QUEUE pFocusQueue, _In_ BOOL bSameLang, _In_ INT nKeyState)
Definition: keyboard.c:815
static WORD IntSimplifyVk(WORD wVk)
Definition: keyboard.c:217
static WORD IntTranslateNumpadKey(WORD wVk)
Definition: keyboard.c:270
UINT APIENTRY NtUserMapVirtualKeyEx(UINT uCode, UINT uType, DWORD keyboardId, HKL dwhkl)
Definition: keyboard.c:1707
BOOL FASTCALL UserPostMessage(HWND Wnd, UINT Msg, WPARAM wParam, LPARAM lParam)
Definition: message.c:1397
PVOID FASTCALL UserAssignmentLock(PVOID *ppvObj, PVOID pvNew)
Definition: object.c:861
#define USERTAG_KBDTABLE
Definition: tags.h:247
WINBASEAPI _In_ DWORD _Out_ _In_ WORD wFlags
Definition: wincon_undoc.h:337
ENGAPI VOID APIENTRY EngSetLastError(_In_ ULONG iError)
Definition: error.c:21
#define WINAPI
Definition: msvc.h:6
#define CLR_INVALID
Definition: wingdi.h:883
#define SRCCOPY
Definition: wingdi.h:333
unsigned char BYTE
Definition: xxhash.c:193