ReactOS 0.4.16-dev-1946-g52006dd
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/* FUNCTIONS *****************************************************************/
24
25/*
26 * InitKeyboardImpl
27 *
28 * Initialization -- Right now, just zero the key state
29 */
30CODE_SEG("INIT")
34{
37 // Clear and set default information.
39 gKeyboardInfo.KeyboardIdentifier.Type = 4; /* AT-101 */
40 gKeyboardInfo.NumberOfFunctionKeys = 12; /* We're doing an 101 for now, so return 12 F-keys */
41 return STATUS_SUCCESS;
42}
43
44/*
45 * IntKeyboardGetIndicatorTrans
46 *
47 * Asks the keyboard driver to send a small table that shows which
48 * lights should connect with which scancodes
49 */
50//static
53 PKEYBOARD_INDICATOR_TRANSLATION *ppIndicatorTrans)
54{
56 DWORD dwSize = 0;
57 IO_STATUS_BLOCK Block;
59
61
63 dwSize,
65
66 while (pRet)
67 {
68 Status = ZwDeviceIoControlFile(hKeyboardDevice,
69 NULL,
70 NULL,
71 NULL,
72 &Block,
74 NULL, 0,
75 pRet, dwSize);
76
78 break;
79
81
83
85 dwSize,
87 }
88
89 if (!pRet)
91
92 if (!NT_SUCCESS(Status))
93 {
95 return Status;
96 }
97
98 *ppIndicatorTrans = pRet;
99 return Status;
100}
101
102/*
103 * IntKeyboardUpdateLeds
104 *
105 * Sends the keyboard commands to turn on/off the lights
106 */
107static
110 WORD wVk,
111 WORD wScanCode)
112{
114 UINT i;
115 USHORT LedFlag = 0;
116 IO_STATUS_BLOCK Block;
117
120
121 switch (wVk)
122 {
123 case VK_CAPITAL: LedFlag = KEYBOARD_CAPS_LOCK_ON; break;
124 case VK_NUMLOCK: LedFlag = KEYBOARD_NUM_LOCK_ON; break;
125 case VK_SCROLL: LedFlag = KEYBOARD_SCROLL_LOCK_ON; break;
126 default:
128 {
130 {
132 break;
133 }
134 }
135 }
136
137 if (LedFlag)
138 {
139 gIndicators.LedFlags ^= LedFlag;
140
141 /* Update the lights on the hardware */
142 Status = ZwDeviceIoControlFile(hKeyboardDevice,
143 NULL,
144 NULL,
145 NULL,
146 &Block,
148 &gIndicators, sizeof(gIndicators),
149 NULL, 0);
150
151 return Status;
152 }
153
154 return STATUS_SUCCESS;
155}
156
157/*
158 * UserInitKeyboard
159 *
160 * Initializes keyboard indicators translation and their state
161 */
163UserInitKeyboard(HANDLE hKeyboardDevice)
164{
166 IO_STATUS_BLOCK Block;
167
169
170 Status = ZwDeviceIoControlFile(hKeyboardDevice,
171 NULL,
172 NULL,
173 NULL,
174 &Block,
176 NULL, 0,
178 sizeof(gIndicators));
179
180 if (!NT_SUCCESS(Status))
181 {
182 WARN("NtDeviceIoControlFile() failed, ignored\n");
185 }
186
193
194 // FIXME: Need device driver to work! HID support more than one!!!!
195 Status = ZwDeviceIoControlFile(hKeyboardDevice,
196 NULL,
197 NULL,
198 NULL,
199 &Block,
201 NULL, 0,
202 &gKeyboardInfo, sizeof(gKeyboardInfo));
203
204 if (!NT_SUCCESS(Status))
205 {
206 ERR("NtDeviceIoControlFile() failed, ignored\n");
207 }
208 TRACE("Keyboard type %u, subtype %u and number of func keys %u\n",
212}
213
214/*
215 * IntSimplifyVk
216 *
217 * Changes virtual keys which distinguish between left and right hand, to keys which don't distinguish
218 */
219static
220WORD
222{
223 switch (wVk)
224 {
225 case VK_LSHIFT:
226 case VK_RSHIFT:
227 return VK_SHIFT;
228
229 case VK_LCONTROL:
230 case VK_RCONTROL:
231 return VK_CONTROL;
232
233 case VK_LMENU:
234 case VK_RMENU:
235 return VK_MENU;
236
237 default:
238 return wVk;
239 }
240}
241
242/*
243 * IntFixVk
244 *
245 * Changes virtual keys which don't not distinguish between left and right hand to proper keys
246 */
247static
248WORD
250{
251 switch (wVk)
252 {
253 case VK_SHIFT:
254 return bExt ? VK_RSHIFT : VK_LSHIFT;
255
256 case VK_CONTROL:
257 return bExt ? VK_RCONTROL : VK_LCONTROL;
258
259 case VK_MENU:
260 return bExt ? VK_RMENU : VK_LMENU;
261
262 default:
263 return wVk;
264 }
265}
266
267/*
268 * IntTranslateNumpadKey
269 *
270 * Translates numpad keys when numlock is enabled
271 */
272static
273WORD
275{
276 switch (wVk)
277 {
278 case VK_INSERT: return VK_NUMPAD0;
279 case VK_END: return VK_NUMPAD1;
280 case VK_DOWN: return VK_NUMPAD2;
281 case VK_NEXT: return VK_NUMPAD3;
282 case VK_LEFT: return VK_NUMPAD4;
283 case VK_CLEAR: return VK_NUMPAD5;
284 case VK_RIGHT: return VK_NUMPAD6;
285 case VK_HOME: return VK_NUMPAD7;
286 case VK_UP: return VK_NUMPAD8;
287 case VK_PRIOR: return VK_NUMPAD9;
288 case VK_DELETE: return VK_DECIMAL;
289 default: return wVk;
290 }
291}
292
293/*
294 * IntGetModBits
295 *
296 * Gets layout specific modification bits, for example KBDSHIFT, KBDCTRL, KBDALT
297 */
298static
299DWORD
300IntGetModBits(PKBDTABLES pKbdTbl, PBYTE pKeyState)
301{
302 DWORD i, dwModBits = 0;
303
304 /* DumpKeyState( KeyState ); */
305
306 for (i = 0; pKbdTbl->pCharModifiers->pVkToBit[i].Vk; i++)
307 if (IS_KEY_DOWN(pKeyState, pKbdTbl->pCharModifiers->pVkToBit[i].Vk))
308 dwModBits |= pKbdTbl->pCharModifiers->pVkToBit[i].ModBits;
309
310 TRACE("Current Mod Bits: %lx\n", dwModBits);
311
312 return dwModBits;
313}
314
315/*
316 * IntTranslateChar
317 *
318 * Translates virtual key to character
319 */
320static
321BOOL
323 PBYTE pKeyState,
324 PBOOL pbDead,
325 PBOOL pbLigature,
326 PWCHAR pwcTranslatedChar,
327 PKBDTABLES pKbdTbl)
328{
329 PVK_TO_WCHAR_TABLE pVkToVchTbl;
330 PVK_TO_WCHARS10 pVkToVch;
331 DWORD i, dwModBits, dwVkModBits, dwModNumber = 0;
332 WCHAR wch;
333 BOOL bAltGr;
334 WORD wCaplokAttr;
335
336 dwModBits = pKeyState ? IntGetModBits(pKbdTbl, pKeyState) : 0;
337 bAltGr = pKeyState && (pKbdTbl->fLocaleFlags & KLLF_ALTGR) && IS_KEY_DOWN(pKeyState, VK_RMENU);
338 wCaplokAttr = bAltGr ? CAPLOKALTGR : CAPLOK;
339
340 TRACE("TryToTranslate: %04x %x\n", wVirtKey, dwModBits);
341
342 /* If ALT without CTRL has ben used, remove ALT flag */
343 if ((dwModBits & (KBDALT|KBDCTRL)) == KBDALT)
344 dwModBits &= ~KBDALT;
345
346 if (dwModBits > pKbdTbl->pCharModifiers->wMaxModBits)
347 {
348 TRACE("dwModBits %x > wMaxModBits %x\n", dwModBits, pKbdTbl->pCharModifiers->wMaxModBits);
349 return FALSE;
350 }
351
352 for (i = 0; pKbdTbl->pVkToWcharTable[i].pVkToWchars; i++)
353 {
354 pVkToVchTbl = &pKbdTbl->pVkToWcharTable[i];
355 pVkToVch = (PVK_TO_WCHARS10)(pVkToVchTbl->pVkToWchars);
356 while (pVkToVch->VirtualKey)
357 {
358 if (wVirtKey == (pVkToVch->VirtualKey & 0xFF))
359 {
360 dwVkModBits = dwModBits;
361
362 /* If CapsLock is enabled for this key and locked, add SHIFT bit */
363 if ((pVkToVch->Attributes & wCaplokAttr) &&
364 pKeyState &&
365 IS_KEY_LOCKED(pKeyState, VK_CAPITAL))
366 {
367 /* Note: we use special value here instead of getting VK_SHIFT mod bit - it's verified */
368 dwVkModBits ^= KBDSHIFT;
369 }
370
371 if (dwVkModBits > pKbdTbl->pCharModifiers->wMaxModBits)
372 break;
373
374 /* Get modification number */
375 dwModNumber = pKbdTbl->pCharModifiers->ModNumber[dwVkModBits];
376 if (dwModNumber >= pVkToVchTbl->nModifications)
377 {
378 TRACE("dwModNumber %u >= nModifications %u\n", dwModNumber, pVkToVchTbl->nModifications);
379 break;
380 }
381
382 /* Read character */
383 wch = pVkToVch->wch[dwModNumber];
384 if (wch == WCH_NONE)
385 break;
386
387 *pbDead = (wch == WCH_DEAD);
388 *pbLigature = (wch == WCH_LGTR);
389 *pwcTranslatedChar = wch;
390
391 TRACE("%lu %04x: dwModNumber %08x Char %04x\n",
392 i, wVirtKey, dwModNumber, wch);
393
394 if (*pbDead)
395 {
396 /* After WCH_DEAD, real character is located */
397 pVkToVch = (PVK_TO_WCHARS10)(((BYTE *)pVkToVch) + pVkToVchTbl->cbSize);
398 if (pVkToVch->VirtualKey != 0xFF)
399 {
400 WARN("Found dead key with no trailer in the table.\n");
401 WARN("VK: %04x, ADDR: %p\n", wVirtKey, pVkToVch);
402 break;
403 }
404 *pwcTranslatedChar = pVkToVch->wch[dwModNumber];
405 }
406 return TRUE;
407 }
408 pVkToVch = (PVK_TO_WCHARS10)(((BYTE *)pVkToVch) + pVkToVchTbl->cbSize);
409 }
410 }
411
412 /* If nothing has been found in layout, check if this is ASCII control character.
413 Note: we could add it to layout table, but windows does not have it there */
414 if (wVirtKey >= 'A' && wVirtKey <= 'Z' &&
415 pKeyState && IS_KEY_DOWN(pKeyState, VK_CONTROL) &&
416 !IS_KEY_DOWN(pKeyState, VK_MENU))
417 {
418 *pwcTranslatedChar = (wVirtKey - 'A') + 1; /* ASCII control character */
419 *pbDead = FALSE;
420 *pbLigature = FALSE;
421 return TRUE;
422 }
423
424 return FALSE;
425}
426
427/*
428 * IntToUnicodeEx
429 *
430 * Translates virtual key to characters
431 */
432static
433int APIENTRY
435 UINT wScanCode,
436 PBYTE pKeyState,
437 LPWSTR pwszBuff,
438 int cchBuff,
439 UINT wFlags,
440 PKBDTABLES pKbdTbl)
441{
442 WCHAR wchTranslatedChar;
443 BOOL bDead, bLigature;
444 static WCHAR wchDead = 0;
445 int iRet = 0;
446
447 ASSERT(pKbdTbl);
448
449 if (!IntTranslateChar(wVirtKey,
450 pKeyState,
451 &bDead,
452 &bLigature,
453 &wchTranslatedChar,
454 pKbdTbl))
455 {
456 return 0;
457 }
458
459 if (bLigature)
460 {
461 WARN("Not handling ligature (yet)\n" );
462 return 0;
463 }
464
465 /* If we got dead char in previous call check dead keys in keyboard layout */
466 if (wchDead)
467 {
468 UINT i;
469 WCHAR wchFirst, wchSecond;
470 TRACE("Previous dead char: %lc (%x)\n", wchDead, wchDead);
471
472 if (pKbdTbl->pDeadKey)
473 {
474 for (i = 0; pKbdTbl->pDeadKey[i].dwBoth; i++)
475 {
476 wchFirst = pKbdTbl->pDeadKey[i].dwBoth >> 16;
477 wchSecond = pKbdTbl->pDeadKey[i].dwBoth & 0xFFFF;
478 if (wchFirst == wchDead && wchSecond == wchTranslatedChar)
479 {
480 wchTranslatedChar = pKbdTbl->pDeadKey[i].wchComposed;
481 wchDead = 0;
482 bDead = FALSE;
483 break;
484 }
485 }
486 }
487 else
488 {
489#if defined(__GNUC__)
490 if (wchDead == 0x8000)
491 {
492 ERR("GCC is inventing bits, ignoring fake dead key\n");
493 wchDead = 0;
494 }
495#endif
496 }
497
498 TRACE("Final char: %lc (%x)\n", wchTranslatedChar, wchTranslatedChar);
499 }
500
501 /* Dead char has not been not found */
502 if (wchDead)
503 {
504 /* Treat both characters normally */
505 if (cchBuff > iRet)
506 pwszBuff[iRet++] = wchDead;
507 bDead = FALSE;
508 }
509
510 /* Add character to the buffer */
511 if (cchBuff > iRet)
512 pwszBuff[iRet++] = wchTranslatedChar;
513
514 /* Save dead character */
515 wchDead = bDead ? wchTranslatedChar : 0;
516
517 return bDead ? -iRet : iRet;
518}
519
520/*
521 * IntVkToVsc
522 *
523 * Translates virtual key to scan code
524 */
525static
528{
529 unsigned i;
530
531 ASSERT(pKbdTbl);
532
533 /* Check standard keys first */
534 for (i = 0; i < pKbdTbl->bMaxVSCtoVK; i++)
535 {
536 if ((pKbdTbl->pusVSCtoVK[i] & 0xFF) == wVk)
537 return i;
538 }
539
540 /* Check extended keys now */
541 for (i = 0; pKbdTbl->pVSCtoVK_E0[i].Vsc; i++)
542 {
543 if ((pKbdTbl->pVSCtoVK_E0[i].Vk & 0xFF) == wVk)
544 return 0xE000 | pKbdTbl->pVSCtoVK_E0[i].Vsc;
545 }
546
547 for (i = 0; pKbdTbl->pVSCtoVK_E1[i].Vsc; i++)
548 {
549 if ((pKbdTbl->pVSCtoVK_E1[i].Vk & 0xFF) == wVk)
550 return 0xE100 | pKbdTbl->pVSCtoVK_E1[i].Vsc;
551 }
552
553 /* Virtual key has not been found */
554 return 0;
555}
556
557/*
558 * IntVscToVk
559 *
560 * Translates prefixed scancode to virtual key
561 */
562static
564IntVscToVk(WORD wScanCode, PKBDTABLES pKbdTbl)
565{
566 unsigned i;
567 WORD wVk = 0;
568
569 ASSERT(pKbdTbl);
570
571 if ((wScanCode & 0xFF00) == 0xE000)
572 {
573 for (i = 0; pKbdTbl->pVSCtoVK_E0[i].Vsc; i++)
574 {
575 if (pKbdTbl->pVSCtoVK_E0[i].Vsc == (wScanCode & 0xFF))
576 {
577 wVk = pKbdTbl->pVSCtoVK_E0[i].Vk;
578 }
579 }
580 }
581 else if ((wScanCode & 0xFF00) == 0xE100)
582 {
583 for (i = 0; pKbdTbl->pVSCtoVK_E1[i].Vsc; i++)
584 {
585 if (pKbdTbl->pVSCtoVK_E1[i].Vsc == (wScanCode & 0xFF))
586 {
587 wVk = pKbdTbl->pVSCtoVK_E1[i].Vk;
588 }
589 }
590 }
591 else if (wScanCode < pKbdTbl->bMaxVSCtoVK)
592 {
593 wVk = pKbdTbl->pusVSCtoVK[wScanCode];
594 }
595
596 /* 0xFF nad 0x00 are invalid VKs */
597 return wVk != 0xFF ? wVk : 0;
598}
599
600/*
601 * IntVkToChar
602 *
603 * Translates virtual key to character, ignoring shift state
604 */
605static
608{
609 WCHAR wch;
610 BOOL bDead, bLigature;
611
612 ASSERT(pKbdTbl);
613
614 if (IntTranslateChar(wVk,
615 NULL,
616 &bDead,
617 &bLigature,
618 &wch,
619 pKbdTbl))
620 {
621 return wch;
622 }
623
624 return 0;
625}
626
627/*
628 * NtUserGetAsyncKeyState
629 *
630 * Gets key state from global bitmap
631 */
632SHORT
635{
636 WORD wRet = 0;
637
638 TRACE("Enter NtUserGetAsyncKeyState\n");
639
640 if (Key >= 0x100 || Key < 0)
641 {
643 ERR("Invalid parameter Key\n");
644 return 0;
645 }
646
648
650 wRet |= 0x8000; // If down, windows returns 0x8000.
651 if (gafAsyncKeyStateRecentDown[Key / 8] & (1 << (Key % 8)))
652 wRet |= 0x1;
653 gafAsyncKeyStateRecentDown[Key / 8] &= ~(1 << (Key % 8));
654
655 UserLeave();
656
657 TRACE("Leave NtUserGetAsyncKeyState, ret=%u\n", wRet);
658 return wRet;
659}
660
661/*
662 * UpdateAsyncKeyState
663 *
664 * Updates gafAsyncKeyState array
665 */
666static
669{
670 if (bIsDown)
671 {
672 /* If it's first key down event, xor lock bit */
673 if (!IS_KEY_DOWN(gafAsyncKeyState, wVk))
675
677 gafAsyncKeyStateRecentDown[wVk / 8] |= (1 << (wVk % 8));
678 }
679 else
681}
682
683/*
684 * co_CallLowLevelKeyboardHook
685 *
686 * Calls WH_KEYBOARD_LL hook
687 */
688static LRESULT
689co_CallLowLevelKeyboardHook(WORD wVk, WORD wScanCode, DWORD dwFlags, BOOL bInjected, DWORD dwTime, DWORD dwExtraInfo)
690{
691 KBDLLHOOKSTRUCT KbdHookData;
692 UINT uMsg;
693
694 KbdHookData.vkCode = wVk;
695 KbdHookData.scanCode = wScanCode;
696 KbdHookData.flags = 0;
698 KbdHookData.flags |= LLKHF_EXTENDED;
700 KbdHookData.flags |= LLKHF_ALTDOWN;
702 KbdHookData.flags |= LLKHF_UP;
703 if (bInjected)
704 KbdHookData.flags |= LLKHF_INJECTED;
705 KbdHookData.time = dwTime;
706 KbdHookData.dwExtraInfo = dwExtraInfo;
707
708 /* Note: it doesnt support WM_SYSKEYUP */
710 uMsg = WM_KEYUP;
712 uMsg = WM_SYSKEYDOWN;
713 else
714 uMsg = WM_KEYDOWN;
715
716 return co_HOOK_CallHooks(WH_KEYBOARD_LL, HC_ACTION, uMsg, (LPARAM)&KbdHookData);
717}
718
719/*
720 * SnapWindow
721 *
722 * Saves snapshot of specified window or whole screen in the clipboard
723 */
724static VOID
726{
727 HBITMAP hbm = NULL, hbmOld;
728 HDC hdc = NULL, hdcMem;
729 SETCLIPBDATA scd;
730 INT cx, cy;
731 PWND pWnd = NULL;
732
733 TRACE("SnapWindow(%p)\n", hWnd);
734
735 /* If no windows is given, make snapshot of desktop window */
736 if (!hWnd)
738
740 if (!pWnd)
741 {
742 ERR("Invalid window\n");
743 goto cleanup;
744 }
745
747 if (!hdc)
748 {
749 ERR("UserGetDCEx failed!\n");
750 goto cleanup;
751 }
752
753 cx = pWnd->rcWindow.right - pWnd->rcWindow.left;
754 cy = pWnd->rcWindow.bottom - pWnd->rcWindow.top;
755
757 if (!hbm)
758 {
759 ERR("NtGdiCreateCompatibleBitmap failed!\n");
760 goto cleanup;
761 }
762
764 if (!hdcMem)
765 {
766 ERR("NtGdiCreateCompatibleDC failed!\n");
767 goto cleanup;
768 }
769
770 hbmOld = NtGdiSelectBitmap(hdcMem, hbm);
771 NtGdiBitBlt(hdcMem, 0, 0, cx, cy, hdc, 0, 0, SRCCOPY, 0, 0);
772 NtGdiSelectBitmap(hdcMem, hbmOld);
774
775 /* Save snapshot in clipboard */
777 {
780 scd.fGlobalHandle = FALSE;
782 {
783 /* Bitmap is managed by system now */
784 hbm = NULL;
785 }
787 }
788
789cleanup:
790 if (hbm)
792 if (hdc)
793 UserReleaseDC(pWnd, hdc, FALSE);
794}
795
796/* Find the next/previous keyboard layout of the same/different language */
797static PKL FASTCALL
799 _In_ PKL pKL,
800 _In_ BOOL bNext,
801 _In_ BOOL bSameLang)
802{
803 PKL pFirstKL = pKL;
804 LANGID LangID = LOWORD(pKL->hkl);
805
806 do
807 {
808 pKL = (bNext ? pKL->pklNext : pKL->pklPrev);
809
810 if (!(pKL->dwKL_Flags & KL_UNLOAD) && bSameLang == (LangID == LOWORD(pKL->hkl)))
811 return pKL;
812 } while (pKL != pFirstKL);
813
814 return pFirstKL;
815}
816
817/* Perform layout toggle by [Left Alt]+Shift or Ctrl+Shift */
818static VOID
820 _In_ PUSER_MESSAGE_QUEUE pFocusQueue,
821 _In_ BOOL bSameLang,
822 _In_ INT nKeyState)
823{
824 PWND pWnd;
825 PTHREADINFO pti;
826 PKL pkl;
827 WPARAM wParam = 0;
828
829 if (!pFocusQueue)
830 {
831 ERR("IntLanguageToggle(): NULL pFocusQueue\n");
832 return;
833 }
834 pWnd = pFocusQueue->spwndFocus;
835 if (!pWnd)
836 pWnd = pFocusQueue->spwndActive;
837 if (!pWnd)
838 return;
839
840 pti = pWnd->head.pti;
841 pkl = pti->KeyboardLayout;
842
843 if (nKeyState == INPUTLANGCHANGE_FORWARD)
844 pkl = IntGetNextKL(pkl, TRUE, bSameLang);
845 else if (nKeyState == INPUTLANGCHANGE_BACKWARD)
846 pkl = IntGetNextKL(pkl, FALSE, bSameLang);
847
848 if (gSystemFS & pkl->dwFontSigs)
849 wParam |= INPUTLANGCHANGE_SYSCHARSET;
850
851 UserPostMessage(UserHMGetHandle(pWnd), WM_INPUTLANGCHANGEREQUEST, wParam, (LPARAM)pkl->hkl);
852}
853
854/* Check Language Toggle by [Left Alt]+Shift or Ctrl+Shift */
855static BOOL
857 _In_ PUSER_MESSAGE_QUEUE pFocusQueue,
858 _In_ BOOL bIsDown,
859 _In_ WORD wVk,
860 _Inout_ PINT pKeyState)
861{
862 if (bIsDown) /* Toggle key combination is pressed? */
863 {
864 if (wVk == VK_LSHIFT)
865 *pKeyState = INPUTLANGCHANGE_FORWARD;
866 else if (wVk == VK_RSHIFT)
867 *pKeyState = INPUTLANGCHANGE_BACKWARD;
868 else if (!wVk && IS_KEY_DOWN(gafAsyncKeyState, VK_LSHIFT))
869 *pKeyState = INPUTLANGCHANGE_FORWARD;
870 else if (!wVk && IS_KEY_DOWN(gafAsyncKeyState, VK_RSHIFT))
871 *pKeyState = INPUTLANGCHANGE_BACKWARD;
872 else
873 return FALSE;
874 }
875 else
876 {
877 if (*pKeyState == 0)
878 return FALSE;
879
880 IntLanguageToggle(pFocusQueue, (pKeyState == &gLayoutToggleKeyState), *pKeyState);
881 *pKeyState = 0;
882 }
883 return TRUE;
884}
885
886/*
887 * UserSendKeyboardInput
888 *
889 * Process keyboard input from input devices and SendInput API
890 */
892ProcessKeyEvent(WORD wVk, WORD wScanCode, DWORD dwFlags, BOOL bInjected, DWORD dwTime, DWORD dwExtraInfo)
893{
894 WORD wSimpleVk = 0, wFixedVk, wVk2;
895 PUSER_MESSAGE_QUEUE pFocusQueue;
896 PTHREADINFO pti;
898 BOOL bIsDown = (dwFlags & KEYEVENTF_KEYUP) ? FALSE : TRUE;
899 BOOL bPacket = (dwFlags & KEYEVENTF_UNICODE) ? TRUE : FALSE;
900 BOOL bWasSimpleDown = FALSE, bPostMsg = TRUE, bIsSimpleDown;
901 MSG Msg;
902 static BOOL bMenuDownRecently = FALSE;
903 BOOL bLangToggled = FALSE;
904
905 /* Get virtual key without shifts (VK_(L|R)* -> VK_*) */
906 wSimpleVk = IntSimplifyVk(wVk);
907
909 {
910 /* Japanese special! */
912 {
913 if (wSimpleVk == VK_OEM_ATTN)
914 wSimpleVk = VK_CAPITAL;
915 else if (wSimpleVk == VK_OEM_COPY)
916 wSimpleVk = VK_OEM_FINISH;
917 }
918 }
919
920 bWasSimpleDown = IS_KEY_DOWN(gafAsyncKeyState, wSimpleVk);
921
922 /* Update key without shifts */
923 wVk2 = IntFixVk(wSimpleVk, !bExt);
924 bIsSimpleDown = bIsDown || IS_KEY_DOWN(gafAsyncKeyState, wVk2);
925 UpdateAsyncKeyState(wSimpleVk, bIsSimpleDown);
926
927 if (bIsDown)
928 {
929 /* Update keyboard LEDs */
931 wSimpleVk,
932 wScanCode);
933 }
934
935 /* Call WH_KEYBOARD_LL hook */
936 if (co_CallLowLevelKeyboardHook(wVk, wScanCode, dwFlags, bInjected, dwTime, dwExtraInfo))
937 {
938 ERR("Kbd msg dropped by WH_KEYBOARD_LL hook\n");
939 bPostMsg = FALSE;
940 }
941
942 /* Check if this is a hotkey */
943 if (co_UserProcessHotKeys(wSimpleVk, bIsDown))
944 {
945 TRACE("HotKey Processed\n");
946 bPostMsg = FALSE;
947 }
948
949 wFixedVk = IntFixVk(wSimpleVk, bExt); /* LSHIFT + EXT = RSHIFT */
950 if (wSimpleVk == VK_SHIFT) /* shift can't be extended */
951 bExt = FALSE;
952
953 /* If we have a focus queue, post a keyboard message */
954 pFocusQueue = IntGetFocusMessageQueue();
955 TRACE("ProcessKeyEvent Q 0x%p Active pWnd 0x%p Focus pWnd 0x%p\n",
956 pFocusQueue,
957 (pFocusQueue ? pFocusQueue->spwndActive : 0),
958 (pFocusQueue ? pFocusQueue->spwndFocus : 0));
959
960 /* If it is F10 or ALT is down and CTRL is up, it's a system key */
961 if ( wVk == VK_F10 ||
962 (wSimpleVk == VK_MENU && bMenuDownRecently) ||
965 // See MSDN WM_SYSKEYDOWN/UP fixes last wine Win test_keyboard_input.
966 (pFocusQueue && !pFocusQueue->spwndFocus) )
967 {
968 bMenuDownRecently = FALSE; // reset
969 if (bIsDown)
970 {
971 Msg.message = WM_SYSKEYDOWN;
972 if (wSimpleVk == VK_MENU)
973 {
974 // Note: If only LALT is pressed WM_SYSKEYUP is generated instead of WM_KEYUP
975 bMenuDownRecently = TRUE;
976 }
977 }
978 else
979 Msg.message = WM_SYSKEYUP;
980 }
981 else
982 {
983 if (bIsDown)
984 Msg.message = WM_KEYDOWN;
985 else
986 Msg.message = WM_KEYUP;
987 }
988
989 /* Update async state of not simplified vk here.
990 See user32_apitest:GetKeyState */
991 UpdateAsyncKeyState(wFixedVk, bIsDown);
992
993 /* Alt-Tab/Esc Check. Use FocusQueue or RIT Queue */
994 if (bIsSimpleDown && !bWasSimpleDown &&
997 (wVk == VK_ESCAPE || wVk == VK_TAB))
998 {
999 TRACE("Alt-Tab/Esc Pressed wParam %x\n",wVk);
1000 }
1001
1002 /*
1003 * Check Language/Layout Toggle by [Left Alt]+Shift or Ctrl+Shift.
1004 * @see https://learn.microsoft.com/en-us/previous-versions/windows/it-pro/windows-2000-server/cc976564%28v=technet.10%29
1005 */
1007 {
1008 if (wSimpleVk == VK_SHIFT) /* Shift key is pressed or released */
1009 {
1010 UINT targetKey = ((gdwLanguageToggleKey == 1) ? VK_LMENU : VK_CONTROL);
1011 if (IS_KEY_DOWN(gafAsyncKeyState, targetKey))
1012 bLangToggled = IntCheckLanguageToggle(pFocusQueue, bIsDown, wVk, &gLanguageToggleKeyState);
1013 }
1014 else if ((wSimpleVk == VK_MENU && gdwLanguageToggleKey == 1) ||
1015 (wSimpleVk == VK_CONTROL && gdwLanguageToggleKey == 2))
1016 {
1018 bLangToggled = IntCheckLanguageToggle(pFocusQueue, bIsDown, 0, &gLanguageToggleKeyState);
1019 }
1020 }
1021 if (!bLangToggled && (gdwLayoutToggleKey == 1 || gdwLayoutToggleKey == 2))
1022 {
1023 if (wSimpleVk == VK_SHIFT) /* Shift key is pressed or released */
1024 {
1025 UINT targetKey = ((gdwLayoutToggleKey == 1) ? VK_LMENU : VK_CONTROL);
1026 if (IS_KEY_DOWN(gafAsyncKeyState, targetKey))
1027 IntCheckLanguageToggle(pFocusQueue, bIsDown, wVk, &gLayoutToggleKeyState);
1028 }
1029 else if ((wSimpleVk == VK_MENU && gdwLayoutToggleKey == 1) ||
1030 (wSimpleVk == VK_CONTROL && gdwLayoutToggleKey == 2))
1031 {
1033 IntCheckLanguageToggle(pFocusQueue, bIsDown, 0, &gLayoutToggleKeyState);
1034 }
1035 }
1036
1037 if (bIsDown && wVk == VK_SNAPSHOT)
1038 {
1039 if (pFocusQueue &&
1042 {
1043 // Snap from Active Window, Focus can be null.
1044 SnapWindow(pFocusQueue->spwndActive ? UserHMGetHandle(pFocusQueue->spwndActive) : 0);
1045 }
1046 else
1047 SnapWindow(NULL); // Snap Desktop.
1048 }
1049 else if (pFocusQueue && bPostMsg)
1050 {
1051 PWND Wnd = pFocusQueue->spwndFocus; // SysInit.....
1052
1053 pti = pFocusQueue->ptiKeyboard;
1054
1055 if (!Wnd && pFocusQueue->spwndActive) // SysInit.....
1056 {
1057 // Going with Active. WM_SYSKEYXXX last wine Win test_keyboard_input.
1058 Wnd = pFocusQueue->spwndActive;
1059 }
1060 if (Wnd) pti = Wnd->head.pti;
1061
1062 /* Init message */
1063 Msg.hwnd = Wnd ? UserHMGetHandle(Wnd) : NULL;
1064 Msg.wParam = wFixedVk & 0xFF; /* Note: It's simplified by msg queue */
1065 Msg.lParam = MAKELPARAM(1, wScanCode);
1066 Msg.time = dwTime;
1067 Msg.pt = gpsi->ptCursor;
1068
1069 if ( Msg.message == WM_KEYDOWN || Msg.message == WM_SYSKEYDOWN )
1070 {
1071 if ( (Msg.wParam == VK_SHIFT ||
1072 Msg.wParam == VK_CONTROL ||
1073 Msg.wParam == VK_MENU ) &&
1075 {
1076 ERR("Set last input\n");
1077 //ptiLastInput = pti;
1078 }
1079 }
1080
1081 /* If it is VK_PACKET, high word of wParam is used for wchar */
1082 if (!bPacket)
1083 {
1084 if (bExt)
1085 Msg.lParam |= KF_EXTENDED << 16;
1087 Msg.lParam |= KF_ALTDOWN << 16;
1088 if (bWasSimpleDown)
1089 Msg.lParam |= KF_REPEAT << 16;
1090 if (!bIsDown)
1091 Msg.lParam |= KF_UP << 16;
1092 /* FIXME: Set KF_DLGMODE and KF_MENUMODE when needed */
1093 if (pFocusQueue->QF_flags & QF_DIALOGACTIVE)
1094 Msg.lParam |= KF_DLGMODE << 16;
1095 if (pFocusQueue->MenuOwner) // pti->pMenuState->fMenuStarted
1096 Msg.lParam |= KF_MENUMODE << 16;
1097 }
1098
1099 // Post mouse move before posting key buttons, to keep it syned.
1100 if (pFocusQueue->QF_flags & QF_MOUSEMOVED)
1101 {
1103 }
1104
1105 /* Post a keyboard message */
1106 TRACE("Posting keyboard msg %u wParam 0x%x lParam 0x%x\n", Msg.message, Msg.wParam, Msg.lParam);
1107 if (!Wnd) {ERR("Window is NULL\n");}
1108 MsqPostMessage(pti, &Msg, TRUE, QS_KEY, 0, dwExtraInfo);
1109 }
1110 return TRUE;
1111}
1112
1113BOOL NTAPI
1115{
1116 WORD wScanCode, wVk;
1117 PKL pKl = NULL;
1118 PKBDTABLES pKbdTbl;
1119 PUSER_MESSAGE_QUEUE pFocusQueue;
1120 DWORD dwTime;
1121 BOOL bExt = (pKbdInput->dwFlags & KEYEVENTF_EXTENDEDKEY) ? TRUE : FALSE;
1122
1124
1125 /* Find the target thread whose locale is in effect */
1126 pFocusQueue = IntGetFocusMessageQueue();
1127
1128 if (pFocusQueue && pFocusQueue->ptiKeyboard)
1129 {
1130 pKl = pFocusQueue->ptiKeyboard->KeyboardLayout;
1131 }
1132
1133 if (!pKl)
1135 if (!pKl)
1136 {
1137 ERR("No keyboard layout!\n");
1138 return FALSE;
1139 }
1140
1141 pKbdTbl = pKl->spkf->pKbdTbl;
1142
1143 /* Note: wScan field is always used */
1144 wScanCode = pKbdInput->wScan;
1145
1146 if (pKbdInput->dwFlags & KEYEVENTF_UNICODE)
1147 {
1148 /* Generate WM_KEYDOWN msg with wParam == VK_PACKET and
1149 high order word of lParam == pKbdInput->wScan */
1150 wVk = VK_PACKET;
1151 }
1152 else
1153 {
1154 wScanCode &= 0x7F;
1155 if (pKbdInput->dwFlags & KEYEVENTF_SCANCODE)
1156 {
1157 /* Don't ignore invalid scan codes */
1158 wVk = IntVscToVk(wScanCode | (bExt ? 0xE000 : 0), pKbdTbl);
1159 if (!wVk) /* use 0xFF if vsc is invalid */
1160 wVk = 0xFF;
1161 }
1162 else
1163 {
1164 wVk = pKbdInput->wVk;
1165 }
1166
1167 /* Remove all virtual key flags (KBDEXT, KBDMULTIVK, KBDSPECIAL, KBDNUMPAD) */
1168 wVk &= 0xFF;
1169 }
1170
1171 /* If time is given, use it */
1172 if (pKbdInput->time)
1173 dwTime = pKbdInput->time;
1174 else
1175 {
1177 }
1178
1179 if (wVk == VK_RMENU && (pKbdTbl->fLocaleFlags & KLLF_ALTGR))
1180 {
1181 /* For AltGr keyboards RALT generates CTRL events */
1182 ProcessKeyEvent(VK_LCONTROL, 0, pKbdInput->dwFlags & KEYEVENTF_KEYUP, bInjected, dwTime, 0);
1183 }
1184
1185 /* Finally process this key */
1186 return ProcessKeyEvent(wVk, wScanCode, pKbdInput->dwFlags, bInjected, dwTime, pKbdInput->dwExtraInfo);
1187}
1188
1189/*
1190 * UserProcessKeyboardInput
1191 *
1192 * Process raw keyboard input data
1193 */
1194VOID NTAPI
1196 PKEYBOARD_INPUT_DATA pKbdInputData)
1197{
1198 WORD wScanCode, wVk;
1199 PKL pKl = NULL;
1200 PKBDTABLES pKbdTbl;
1201 PUSER_MESSAGE_QUEUE pFocusQueue;
1202
1203 /* Calculate scan code with prefix */
1204 wScanCode = pKbdInputData->MakeCode & 0x7F;
1205 if (pKbdInputData->Flags & KEY_E0)
1206 wScanCode |= 0xE000;
1207 if (pKbdInputData->Flags & KEY_E1)
1208 wScanCode |= 0xE100;
1209
1210 /* Find the target thread whose locale is in effect */
1211 pFocusQueue = IntGetFocusMessageQueue();
1212
1213 if (pFocusQueue && pFocusQueue->ptiKeyboard)
1214 {
1215 pKl = pFocusQueue->ptiKeyboard->KeyboardLayout;
1216 }
1217
1218 if (!pKl)
1220 if (!pKl)
1221 return;
1222
1223 pKbdTbl = pKl->spkf->pKbdTbl;
1224
1225 /* Convert scan code to virtual key.
1226 Note: We could call UserSendKeyboardInput using scan code,
1227 but it wouldn't interpret E1 key(s) properly */
1228 wVk = IntVscToVk(wScanCode, pKbdTbl);
1229 TRACE("UserProcessKeyboardInput: %x (break: %u) -> %x\n",
1230 wScanCode, (pKbdInputData->Flags & KEY_BREAK) ? 1u : 0, wVk);
1231
1232 if (wVk)
1233 {
1234 KEYBDINPUT KbdInput;
1235
1236 /* Support numlock */
1238 {
1239 wVk = IntTranslateNumpadKey(wVk & 0xFF);
1240 }
1241
1242 /* Send keyboard input */
1243 KbdInput.wVk = wVk & 0xFF;
1244 KbdInput.wScan = wScanCode & 0x7F;
1245 KbdInput.dwFlags = 0;
1246 if (pKbdInputData->Flags & KEY_BREAK)
1247 KbdInput.dwFlags |= KEYEVENTF_KEYUP;
1248
1249 if (wVk & KBDEXT)
1250 KbdInput.dwFlags |= KEYEVENTF_EXTENDEDKEY;
1251 //
1252 // Based on wine input:test_Input_blackbox this is okay. It seems the
1253 // bit did not get set and more research is needed. Now the right
1254 // shift works.
1255 //
1256 if (wVk == VK_RSHIFT)
1257 KbdInput.dwFlags |= KEYEVENTF_EXTENDEDKEY;
1258
1259 KbdInput.time = 0;
1260 KbdInput.dwExtraInfo = pKbdInputData->ExtraInformation;
1261 UserSendKeyboardInput(&KbdInput, FALSE);
1262
1263 /* E1 keys don't have break code */
1264 if (pKbdInputData->Flags & KEY_E1)
1265 {
1266 /* Send key up event */
1267 KbdInput.dwFlags |= KEYEVENTF_KEYUP;
1268 UserSendKeyboardInput(&KbdInput, FALSE);
1269 }
1270 }
1271}
1272
1273/*
1274 * IntTranslateKbdMessage
1275 *
1276 * Addes WM_(SYS)CHAR messages to message queue if message
1277 * describes key which produce character.
1278 */
1281 UINT flags)
1282{
1283 PTHREADINFO pti;
1284 INT cch = 0, i;
1285 WCHAR wch[3] = { 0 };
1286 MSG NewMsg = { 0 };
1287 PKBDTABLES pKbdTbl;
1288 BOOL bResult = FALSE;
1289
1290 switch(lpMsg->message)
1291 {
1292 case WM_KEYDOWN:
1293 case WM_KEYUP:
1294 case WM_SYSKEYDOWN:
1295 case WM_SYSKEYUP:
1296 break;
1297 default:
1298 return FALSE;
1299 }
1300
1302
1303 if (!pti->KeyboardLayout)
1304 {
1305 PKL pDefKL = W32kGetDefaultKeyLayout();
1306 UserAssignmentLock((PVOID*)&(pti->KeyboardLayout), pDefKL);
1307 if (pDefKL)
1308 {
1309 pti->pClientInfo->hKL = pDefKL->hkl;
1310 pKbdTbl = pDefKL->spkf->pKbdTbl;
1311 }
1312 else
1313 {
1314 pti->pClientInfo->hKL = NULL;
1315 pKbdTbl = NULL;
1316 }
1317 }
1318 else
1319 pKbdTbl = pti->KeyboardLayout->spkf->pKbdTbl;
1320 if (!pKbdTbl)
1321 return FALSE;
1322
1323 if (lpMsg->message != WM_KEYDOWN && lpMsg->message != WM_SYSKEYDOWN)
1324 return FALSE;
1325
1326 /* Init pt, hwnd and time msg fields */
1327 NewMsg.pt = gpsi->ptCursor;
1328 NewMsg.hwnd = lpMsg->hwnd;
1329 NewMsg.time = EngGetTickCount32();
1330
1331 TRACE("Enter IntTranslateKbdMessage msg %s, vk %x\n",
1332 lpMsg->message == WM_SYSKEYDOWN ? "WM_SYSKEYDOWN" : "WM_KEYDOWN", lpMsg->wParam);
1333
1334 if (lpMsg->wParam == VK_PACKET)
1335 {
1336 NewMsg.message = (lpMsg->message == WM_KEYDOWN) ? WM_CHAR : WM_SYSCHAR;
1337 NewMsg.wParam = HIWORD(lpMsg->lParam);
1338 NewMsg.lParam = LOWORD(lpMsg->lParam);
1339 MsqPostMessage(pti, &NewMsg, FALSE, QS_KEY, 0, 0);
1340 return TRUE;
1341 }
1342
1343 cch = IntToUnicodeEx(lpMsg->wParam,
1344 HIWORD(lpMsg->lParam) & 0xFF,
1345 pti->MessageQueue->afKeyState,
1346 wch,
1347 sizeof(wch) / sizeof(wch[0]),
1348 0,
1349 pKbdTbl);
1350
1351 if (cch)
1352 {
1353 if (cch > 0) /* Normal characters */
1354 NewMsg.message = (lpMsg->message == WM_KEYDOWN) ? WM_CHAR : WM_SYSCHAR;
1355 else /* Dead character */
1356 {
1357 cch = -cch;
1358 NewMsg.message =
1360 }
1361 NewMsg.lParam = lpMsg->lParam;
1362
1363 /* Send all characters */
1364 for (i = 0; i < cch; ++i)
1365 {
1366 TRACE("Msg: %x '%lc' (%04x) %08x\n", NewMsg.message, wch[i], wch[i], NewMsg.lParam);
1367 NewMsg.wParam = wch[i];
1368 MsqPostMessage(pti, &NewMsg, FALSE, QS_KEY, 0, 0);
1369 }
1370 bResult = TRUE;
1371 }
1372
1373 TRACE("Leave IntTranslateKbdMessage ret %d, cch %d, msg %x, wch %x\n",
1374 bResult, cch, NewMsg.message, NewMsg.wParam);
1375 return bResult;
1376}
1377
1378/*
1379 * Map a virtual key code, or virtual scan code, to a scan code, key code,
1380 * or unshifted unicode character.
1381 *
1382 * Code: See Below
1383 * Type:
1384 * 0 -- Code is a virtual key code that is converted into a virtual scan code
1385 * that does not distinguish between left and right shift keys.
1386 * 1 -- Code is a virtual scan code that is converted into a virtual key code
1387 * that does not distinguish between left and right shift keys.
1388 * 2 -- Code is a virtual key code that is converted into an unshifted unicode
1389 * character.
1390 * 3 -- Code is a virtual scan code that is converted into a virtual key code
1391 * that distinguishes left and right shift keys.
1392 * KeyLayout: Keyboard layout handle
1393 *
1394 * @implemented
1395 */
1396static UINT
1398{
1399 UINT uRet = 0;
1400
1401 switch (Type)
1402 {
1403 case MAPVK_VK_TO_VSC:
1404 uCode = IntFixVk(uCode, FALSE);
1405 uRet = IntVkToVsc(uCode, pKbdTbl);
1406 if (uRet > 0xFF) // Fail for scancodes with prefix (e0, e1)
1407 uRet = 0;
1408 break;
1409
1410 case MAPVK_VSC_TO_VK:
1411 uRet = IntVscToVk(uCode, pKbdTbl) & 0xFF;
1412 uRet = IntSimplifyVk(uRet);
1413 break;
1414
1415 case MAPVK_VK_TO_CHAR:
1416 uRet = (UINT)IntVkToChar(uCode, pKbdTbl);
1417 break;
1418
1419 case MAPVK_VSC_TO_VK_EX:
1420 uRet = IntVscToVk(uCode, pKbdTbl) & 0xFF;
1421 break;
1422
1423 case MAPVK_VK_TO_VSC_EX:
1424 uRet = IntVkToVsc(uCode, pKbdTbl);
1425 break;
1426
1427 default:
1429 ERR("Wrong type value: %u\n", Type);
1430 }
1431
1432 return uRet;
1433}
1434
1435/*
1436 * NtUserMapVirtualKeyEx
1437 *
1438 * Map a virtual key code, or virtual scan code, to a scan code, key code,
1439 * or unshifted unicode character. See IntMapVirtualKeyEx.
1440 */
1441UINT
1443NtUserMapVirtualKeyEx(UINT uCode, UINT uType, DWORD keyboardId, HKL dwhkl)
1444{
1445 PKBDTABLES pKbdTbl = NULL;
1446 UINT ret = 0;
1447
1448 TRACE("Enter NtUserMapVirtualKeyEx\n");
1450
1451 if (!dwhkl)
1452 {
1453 PTHREADINFO pti;
1454
1456 if (pti && pti->KeyboardLayout)
1457 pKbdTbl = pti->KeyboardLayout->spkf->pKbdTbl;
1458 }
1459 else
1460 {
1461 PKL pKl;
1462
1463 pKl = UserHklToKbl(dwhkl);
1464 if (pKl)
1465 pKbdTbl = pKl->spkf->pKbdTbl;
1466 }
1467
1468 if (pKbdTbl)
1469 ret = IntMapVirtualKeyEx(uCode, uType, pKbdTbl);
1470
1471 UserLeave();
1472 TRACE("Leave NtUserMapVirtualKeyEx, ret=%u\n", ret);
1473 return ret;
1474}
1475
1476/*
1477 * NtUserToUnicodeEx
1478 *
1479 * Translates virtual key to characters
1480 */
1481int
1484 UINT wVirtKey,
1485 UINT wScanCode,
1486 PBYTE pKeyStateUnsafe,
1487 LPWSTR pwszBuffUnsafe,
1488 INT cchBuff,
1489 UINT wFlags,
1490 HKL dwhkl)
1491{
1492 PTHREADINFO pti;
1493 BYTE afKeyState[256 * 2 / 8] = {0};
1494 PWCHAR pwszBuff = NULL;
1495 INT i, iRet = 0;
1496 PKL pKl = NULL;
1498
1499 TRACE("Enter NtUserSetKeyboardState\n");
1500
1501 /* Return 0 if SC_KEY_UP bit is set */
1502 if (wScanCode & SC_KEY_UP || wVirtKey >= 0x100)
1503 {
1504 ERR("Invalid parameter\n");
1505 return 0;
1506 }
1507
1508 _SEH2_TRY
1509 {
1510 /* Probe and copy key state to smaller bitmap */
1511 ProbeForRead(pKeyStateUnsafe, 256 * sizeof(BYTE), 1);
1512 for (i = 0; i < 256; ++i)
1513 {
1514 if (pKeyStateUnsafe[i] & KS_DOWN_BIT)
1515 SET_KEY_DOWN(afKeyState, i, TRUE);
1516 if (pKeyStateUnsafe[i] & KS_LOCK_BIT)
1517 SET_KEY_LOCKED(afKeyState, i, TRUE);
1518 }
1519 }
1521 {
1522 ERR("Cannot copy key state\n");
1524 _SEH2_YIELD(return 0);
1525 }
1526 _SEH2_END;
1527
1528 pwszBuff = ExAllocatePoolWithTag(NonPagedPool, sizeof(WCHAR) * cchBuff, TAG_STRING);
1529 if (!pwszBuff)
1530 {
1531 ERR("ExAllocatePoolWithTag(%u) failed\n", sizeof(WCHAR) * cchBuff);
1532 return 0;
1533 }
1534 RtlZeroMemory(pwszBuff, sizeof(WCHAR) * cchBuff);
1535
1536 UserEnterExclusive(); // Note: We modify wchDead static variable
1537
1538 if (dwhkl)
1539 pKl = UserHklToKbl(dwhkl);
1540
1541 if (!pKl)
1542 {
1544 pKl = pti->KeyboardLayout;
1545 }
1546
1547 if (pKl)
1548 {
1549 iRet = IntToUnicodeEx(wVirtKey,
1550 wScanCode,
1551 afKeyState,
1552 pwszBuff,
1553 cchBuff,
1554 wFlags,
1555 pKl->spkf->pKbdTbl);
1556
1557 if (iRet)
1558 {
1559 Status = MmCopyToCaller(pwszBuffUnsafe, pwszBuff, cchBuff * sizeof(WCHAR));
1560 }
1561 }
1562 else
1563 {
1564 ERR("No keyboard layout ?!\n");
1566 }
1567
1568 ExFreePoolWithTag(pwszBuff, TAG_STRING);
1569
1570 if (!NT_SUCCESS(Status))
1571 {
1572 iRet = 0;
1574 }
1575
1576 UserLeave();
1577 TRACE("Leave NtUserSetKeyboardState, ret=%i\n", iRet);
1578 return iRet;
1579}
1580
1581/*
1582 * NtUserGetKeyNameText
1583 *
1584 * Gets key name from keyboard layout
1585 */
1586DWORD
1589{
1590 PTHREADINFO pti;
1591 DWORD i, dwRet = 0;
1592 SIZE_T cchKeyName;
1593 WORD wScanCode = (lParam >> 16) & 0xFF;
1594 BOOL bExtKey = (HIWORD(lParam) & KF_EXTENDED) ? TRUE : FALSE;
1595 PKBDTABLES pKbdTbl;
1596 VSC_LPWSTR *pKeyNames = NULL;
1597 CONST WCHAR *pKeyName = NULL;
1598 WCHAR KeyNameBuf[2];
1599
1600 TRACE("Enter NtUserGetKeyNameText\n");
1601
1603
1604 /* Get current keyboard layout */
1606 pKbdTbl = pti ? pti->KeyboardLayout->spkf->pKbdTbl : 0;
1607
1608 if (!pKbdTbl || cchSize < 1)
1609 {
1610 ERR("Invalid parameter\n");
1611 goto cleanup;
1612 }
1613
1614 /* "Do not care" flag */
1616 {
1617 /* Note: We could do vsc -> vk -> vsc conversion, instead of using
1618 hardcoded scan codes, but it's not what Windows does */
1619 if (wScanCode == SCANCODE_RSHIFT && !bExtKey)
1620 wScanCode = SCANCODE_LSHIFT;
1621 else if (wScanCode == SCANCODE_CTRL || wScanCode == SCANCODE_ALT)
1622 bExtKey = FALSE;
1623 }
1624
1625 if (bExtKey)
1626 pKeyNames = pKbdTbl->pKeyNamesExt;
1627 else
1628 pKeyNames = pKbdTbl->pKeyNames;
1629
1630 for (i = 0; pKeyNames[i].pwsz; i++)
1631 {
1632 if (pKeyNames[i].vsc == wScanCode)
1633 {
1634 pKeyName = pKeyNames[i].pwsz;
1635 break;
1636 }
1637 }
1638
1639 if (!pKeyName)
1640 {
1641 WORD wVk = IntVscToVk(wScanCode, pKbdTbl);
1642
1643 if (wVk)
1644 {
1645 KeyNameBuf[0] = IntVkToChar(wVk, pKbdTbl);
1646 KeyNameBuf[1] = 0;
1647 if (KeyNameBuf[0])
1648 pKeyName = KeyNameBuf;
1649 }
1650 }
1651
1652 if (pKeyName)
1653 {
1654 cchKeyName = wcslen(pKeyName);
1655 if (cchKeyName > (cchSize - 1UL))
1656 cchKeyName = cchSize - 1UL; // Don't count '\0'
1657
1658 _SEH2_TRY
1659 {
1660 ProbeForWrite(lpString, (cchKeyName + 1) * sizeof(WCHAR), 1);
1661 RtlCopyMemory(lpString, pKeyName, cchKeyName * sizeof(WCHAR));
1662 lpString[cchKeyName] = UNICODE_NULL;
1663 dwRet = cchKeyName;
1664 }
1666 {
1668 }
1669 _SEH2_END;
1670 }
1671 else
1672 {
1674 }
1675
1676cleanup:
1677 UserLeave();
1678 TRACE("Leave NtUserGetKeyNameText, ret=%lu\n", dwRet);
1679 return dwRet;
1680}
1681
1682/*
1683 * UserGetKeyboardType
1684 *
1685 * Returns some keyboard specific information
1686 */
1689 DWORD dwTypeFlag)
1690{
1691 switch (dwTypeFlag)
1692 {
1693 case 0: /* Keyboard type */
1695 case 1: /* Keyboard Subtype */
1697 case 2: /* Number of F-keys */
1699 default:
1700 ERR("Unknown type!\n");
1701 return 0; /* Note: we don't have to set last error here */
1702 }
1703}
1704
1705/*
1706 * NtUserVkKeyScanEx
1707 *
1708 * Based on IntTranslateChar, instead of processing VirtualKey match,
1709 * look for wChar match.
1710 */
1711DWORD
1714 WCHAR wch,
1715 HKL dwhkl,
1716 BOOL bUsehKL)
1717{
1718 PKBDTABLES pKbdTbl;
1719 PVK_TO_WCHAR_TABLE pVkToWchTbl;
1720 PVK_TO_WCHARS10 pVkToWch;
1721 PKL pKl = NULL;
1722 DWORD i, dwModBits = 0, dwModNumber = 0, Ret = (DWORD)-1;
1723
1724 TRACE("NtUserVkKeyScanEx() wch %u, KbdLayout 0x%p\n", wch, dwhkl);
1726
1727 if (bUsehKL)
1728 {
1729 // Use given keyboard layout
1730 if (dwhkl)
1731 pKl = UserHklToKbl(dwhkl);
1732 }
1733 else
1734 {
1735 // Use thread keyboard layout
1736 pKl = ((PTHREADINFO)PsGetCurrentThreadWin32Thread())->KeyboardLayout;
1737 }
1738
1739 if (!pKl)
1740 goto Exit;
1741
1742 pKbdTbl = pKl->spkf->pKbdTbl;
1743
1744 // Interate through all VkToWchar tables while pVkToWchars is not NULL
1745 for (i = 0; pKbdTbl->pVkToWcharTable[i].pVkToWchars; i++)
1746 {
1747 pVkToWchTbl = &pKbdTbl->pVkToWcharTable[i];
1748 pVkToWch = (PVK_TO_WCHARS10)(pVkToWchTbl->pVkToWchars);
1749
1750 // Interate through all virtual keys
1751 while (pVkToWch->VirtualKey)
1752 {
1753 for (dwModNumber = 0; dwModNumber < pVkToWchTbl->nModifications; dwModNumber++)
1754 {
1755 if (pVkToWch->wch[dwModNumber] == wch)
1756 {
1757 dwModBits = pKbdTbl->pCharModifiers->ModNumber[dwModNumber];
1758 TRACE("i %lu wC %04x: dwModBits %08x dwModNumber %08x MaxModBits %08x\n",
1759 i, wch, dwModBits, dwModNumber, pKbdTbl->pCharModifiers->wMaxModBits);
1760 Ret = (dwModBits << 8) | (pVkToWch->VirtualKey & 0xFF);
1761 goto Exit;
1762 }
1763 }
1764 pVkToWch = (PVK_TO_WCHARS10)(((BYTE *)pVkToWch) + pVkToWchTbl->cbSize);
1765 }
1766 }
1767Exit:
1768 UserLeave();
1769 return Ret;
1770}
1771
1772/* 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
WPARAM wParam
Definition: combotst.c:138
LPARAM lParam
Definition: combotst.c:139
struct @1765 Msg[]
#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 ERROR_INVALID_PARAMETER
Definition: compat.h:101
static void cleanup(void)
Definition: main.c:1335
return ret
Definition: mutex.c:146
#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: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
PSERVERINFO gpsi
Definition: imm.c:18
_CRTIMP size_t __cdecl wcslen(_In_z_ const wchar_t *_Str)
#define UserHMGetHandle(obj)
Definition: ntuser.h:230
#define EXCEPTION_EXECUTE_HANDLER
Definition: excpt.h:90
#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
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
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
_In_ LPWSTR _In_ DWORD _In_ DWORD _In_ DWORD dwFlags
Definition: netsh.h:141
#define _Inout_
Definition: no_sal2.h:162
#define _In_
Definition: no_sal2.h:158
#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
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:258
VOID FASTCALL UserEnterShared(VOID)
Definition: ntuser.c:242
VOID FASTCALL UserEnterExclusive(VOID)
Definition: ntuser.c:249
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:181
#define _SEH2_EXCEPT(...)
Definition: pseh2_64.h:82
#define _SEH2_END
Definition: pseh2_64.h:171
#define _SEH2_TRY
Definition: pseh2_64.h:71
#define _SEH2_YIELD(__stmt)
Definition: pseh2_64.h:184
#define LANG_JAPANESE
Definition: nls.h:76
#define PRIMARYLANGID(l)
Definition: nls.h:16
_In_ UINT _In_ UINT cch
Definition: shellapi.h:432
#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
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:694
THRDESKHEAD head
Definition: ntuser.h:695
RECT rcWindow
Definition: ntuser.h:716
struct _KBDTABLES * pKbdTbl
Definition: input.h:21
ULONG_PTR dwExtraInfo
Definition: winuser.h:3914
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
DWORD dwFontSigs
Definition: input.h:34
PKBDFILE spkf
Definition: input.h:33
HKL hkl
Definition: input.h:32
UINT message
Definition: winuser.h:3217
HWND hwnd
Definition: winuser.h:3216
WPARAM wParam
Definition: winuser.h:3218
LPARAM lParam
Definition: winuser.h:3219
LONG right
Definition: windef.h:102
LONG bottom
Definition: windef.h:103
LONG top
Definition: windef.h:101
LONG left
Definition: windef.h:100
BOOL fIncSerialNumber
Definition: ntuser.h:1169
BOOL fGlobalHandle
Definition: ntuser.h:1168
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
#define KL_UNLOAD
Definition: undocuser.h:183
PWND FASTCALL UserGetWindowObject(HWND hWnd)
Definition: window.c:124
INT FASTCALL UserReleaseDC(PWND Window, HDC hDc, BOOL EndPaint)
Definition: windc.c:918
HDC FASTCALL UserGetDCEx(PWND Window OPTIONAL, HANDLE ClipRegion, ULONG Flags)
_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:31
BOOL NTAPI GreDeleteObject(HGDIOBJ hobj)
Definition: gdiobj.c:1165
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:1391
PUSER_MESSAGE_QUEUE FASTCALL IntGetFocusMessageQueue(VOID)
Definition: desktop.c:1324
BOOL NTAPI co_UserProcessHotKeys(WORD wVk, BOOL bIsDown)
Definition: hotkey.c:191
HANDLE ghKeyboardDevice
Definition: input.c:19
#define SET_KEY_DOWN(ks, vk, down)
Definition: input.h:105
#define KS_DOWN_BIT
Definition: input.h:51
DWORD gSystemFS
Definition: kbdlayout.c:24
PKL NTAPI UserHklToKbl(HKL hKl)
Definition: kbdlayout.c:539
#define IS_KEY_DOWN(ks, vk)
Definition: input.h:103
#define SC_KEY_UP
Definition: input.h:54
#define LP_DO_NOT_CARE_BIT
Definition: input.h:56
#define KS_LOCK_BIT
Definition: input.h:52
#define IS_KEY_LOCKED(ks, vk)
Definition: input.h:104
#define SET_KEY_LOCKED(ks, vk, down)
Definition: input.h:108
PKL W32kGetDefaultKeyLayout(VOID)
Definition: kbdlayout.c:512
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:300
BOOL FASTCALL IntTranslateKbdMessage(LPMSG lpMsg, UINT flags)
Definition: keyboard.c:1280
static NTSTATUS APIENTRY IntKeyboardUpdateLeds(HANDLE hKeyboardDevice, WORD wVk, WORD wScanCode)
Definition: keyboard.c:109
VOID NTAPI UserProcessKeyboardInput(PKEYBOARD_INPUT_DATA pKbdInputData)
Definition: keyboard.c:1195
DWORD APIENTRY NtUserVkKeyScanEx(WCHAR wch, HKL dwhkl, BOOL bUsehKL)
Definition: keyboard.c:1713
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:1483
BYTE gafAsyncKeyState[256 *2/8]
Definition: keyboard.c:13
BOOL NTAPI UserSendKeyboardInput(KEYBDINPUT *pKbdInput, BOOL bInjected)
Definition: keyboard.c:1114
static WORD IntFixVk(WORD wVk, BOOL bExt)
Definition: keyboard.c:249
static VOID SnapWindow(HWND hWnd)
Definition: keyboard.c:725
static BOOL IntTranslateChar(WORD wVirtKey, PBYTE pKeyState, PBOOL pbDead, PBOOL pbLigature, PWCHAR pwcTranslatedChar, PKBDTABLES pKbdTbl)
Definition: keyboard.c:322
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:434
static WCHAR FASTCALL IntVkToChar(WORD wVk, PKBDTABLES pKbdTbl)
Definition: keyboard.c:607
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:856
DWORD APIENTRY NtUserGetKeyNameText(LONG lParam, LPWSTR lpString, int cchSize)
Definition: keyboard.c:1588
static LRESULT co_CallLowLevelKeyboardHook(WORD wVk, WORD wScanCode, DWORD dwFlags, BOOL bInjected, DWORD dwTime, DWORD dwExtraInfo)
Definition: keyboard.c:689
static PKL FASTCALL IntGetNextKL(_In_ PKL pKL, _In_ BOOL bNext, _In_ BOOL bSameLang)
Definition: keyboard.c:798
static PKEYBOARD_INDICATOR_TRANSLATION gpKeyboardIndicatorTrans
Definition: keyboard.c:15
static UINT IntMapVirtualKeyEx(UINT uCode, UINT Type, PKBDTABLES pKbdTbl)
Definition: keyboard.c:1397
VOID NTAPI UserInitKeyboard(HANDLE hKeyboardDevice)
Definition: keyboard.c:163
NTSTATUS APIENTRY IntKeyboardGetIndicatorTrans(HANDLE hKeyboardDevice, PKEYBOARD_INDICATOR_TRANSLATION *ppIndicatorTrans)
Definition: keyboard.c:52
static BYTE gafAsyncKeyStateRecentDown[256/8]
Definition: keyboard.c:14
DWORD FASTCALL UserGetKeyboardType(DWORD dwTypeFlag)
Definition: keyboard.c:1688
static VOID NTAPI UpdateAsyncKeyState(WORD wVk, BOOL bIsDown)
Definition: keyboard.c:668
SHORT APIENTRY NtUserGetAsyncKeyState(INT Key)
Definition: keyboard.c:634
INT gLanguageToggleKeyState
Definition: keyboard.c:18
NTSTATUS NTAPI InitKeyboardImpl(VOID)
Definition: keyboard.c:33
BOOL NTAPI ProcessKeyEvent(WORD wVk, WORD wScanCode, DWORD dwFlags, BOOL bInjected, DWORD dwTime, DWORD dwExtraInfo)
Definition: keyboard.c:892
static WORD FASTCALL IntVkToVsc(WORD wVk, PKBDTABLES pKbdTbl)
Definition: keyboard.c:527
static WORD FASTCALL IntVscToVk(WORD wScanCode, PKBDTABLES pKbdTbl)
Definition: keyboard.c:564
static VOID IntLanguageToggle(_In_ PUSER_MESSAGE_QUEUE pFocusQueue, _In_ BOOL bSameLang, _In_ INT nKeyState)
Definition: keyboard.c:819
static WORD IntSimplifyVk(WORD wVk)
Definition: keyboard.c:221
static WORD IntTranslateNumpadKey(WORD wVk)
Definition: keyboard.c:274
UINT APIENTRY NtUserMapVirtualKeyEx(UINT uCode, UINT uType, DWORD keyboardId, HKL dwhkl)
Definition: keyboard.c:1443
BOOL FASTCALL UserPostMessage(HWND Wnd, UINT Msg, WPARAM wParam, LPARAM lParam)
Definition: message.c:1395
PVOID FASTCALL UserAssignmentLock(PVOID *ppvObj, PVOID pvNew)
Definition: object.c:839
#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:22
#define SRCCOPY
Definition: wingdi.h:333
#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:4110
#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 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 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
__wchar_t WCHAR
Definition: xmlstorage.h:180
WCHAR * LPWSTR
Definition: xmlstorage.h:184
unsigned char BYTE
Definition: xxhash.c:193