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