ReactOS  0.4.11-dev-195-gef016bf
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  */
30 NTAPI
32 {
35  // Clear and set default information.
36  RtlZeroMemory(&gKeyboardInfo, sizeof(gKeyboardInfo));
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 
58  dwSize = sizeof(KEYBOARD_INDICATOR_TRANSLATION);
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 
75  if (Status != STATUS_BUFFER_TOO_SMALL)
76  break;
77 
79 
80  dwSize += sizeof(KEYBOARD_INDICATOR_TRANSLATION);
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 
116  if (!gpKeyboardIndicatorTrans)
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:
125  for (i = 0; i < gpKeyboardIndicatorTrans->NumberOfIndicatorKeys; i++)
126  {
127  if (gpKeyboardIndicatorTrans->IndicatorList[i].MakeCode == wScanCode)
128  {
129  LedFlag = gpKeyboardIndicatorTrans->IndicatorList[i].IndicatorFlags;
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 
166  IntKeyboardGetIndicatorTrans(hKeyboardDevice, &gpKeyboardIndicatorTrans);
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 
186  gIndicators.LedFlags & KEYBOARD_CAPS_LOCK_ON);
188  gIndicators.LedFlags & KEYBOARD_NUM_LOCK_ON);
190  gIndicators.LedFlags & KEYBOARD_SCROLL_LOCK_ON);
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",
207  gKeyboardInfo.KeyboardIdentifier.Type,
208  gKeyboardInfo.KeyboardIdentifier.Subtype,
209  gKeyboardInfo.NumberOfFunctionKeys);
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  for (i = 0; pKbdTbl->pDeadKey[i].dwBoth; i++)
471  {
472  wchFirst = pKbdTbl->pDeadKey[i].dwBoth >> 16;
473  wchSecond = pKbdTbl->pDeadKey[i].dwBoth & 0xFFFF;
474  if (wchFirst == wchDead && wchSecond == wchTranslatedChar)
475  {
476  wchTranslatedChar = pKbdTbl->pDeadKey[i].wchComposed;
477  wchDead = 0;
478  bDead = FALSE;
479  break;
480  }
481  }
482 
483  TRACE("Final char: %lc (%x)\n", wchTranslatedChar, wchTranslatedChar);
484  }
485 
486  /* Dead char has not been not found */
487  if (wchDead)
488  {
489  /* Treat both characters normally */
490  if (cchBuff > iRet)
491  pwszBuff[iRet++] = wchDead;
492  bDead = FALSE;
493  }
494 
495  /* Add character to the buffer */
496  if (cchBuff > iRet)
497  pwszBuff[iRet++] = wchTranslatedChar;
498 
499  /* Save dead character */
500  wchDead = bDead ? wchTranslatedChar : 0;
501 
502  return bDead ? -iRet : iRet;
503 }
504 
505 /*
506  * IntVkToVsc
507  *
508  * Translates virtual key to scan code
509  */
510 static
513 {
514  unsigned i;
515 
516  ASSERT(pKbdTbl);
517 
518  /* Check standard keys first */
519  for (i = 0; i < pKbdTbl->bMaxVSCtoVK; i++)
520  {
521  if ((pKbdTbl->pusVSCtoVK[i] & 0xFF) == wVk)
522  return i;
523  }
524 
525  /* Check extended keys now */
526  for (i = 0; pKbdTbl->pVSCtoVK_E0[i].Vsc; i++)
527  {
528  if ((pKbdTbl->pVSCtoVK_E0[i].Vk & 0xFF) == wVk)
529  return 0xE000 | pKbdTbl->pVSCtoVK_E0[i].Vsc;
530  }
531 
532  for (i = 0; pKbdTbl->pVSCtoVK_E1[i].Vsc; i++)
533  {
534  if ((pKbdTbl->pVSCtoVK_E1[i].Vk & 0xFF) == wVk)
535  return 0xE100 | pKbdTbl->pVSCtoVK_E1[i].Vsc;
536  }
537 
538  /* Virtual key has not been found */
539  return 0;
540 }
541 
542 /*
543  * IntVscToVk
544  *
545  * Translates prefixed scancode to virtual key
546  */
547 static
549 IntVscToVk(WORD wScanCode, PKBDTABLES pKbdTbl)
550 {
551  unsigned i;
552  WORD wVk = 0;
553 
554  ASSERT(pKbdTbl);
555 
556  if ((wScanCode & 0xFF00) == 0xE000)
557  {
558  for (i = 0; pKbdTbl->pVSCtoVK_E0[i].Vsc; i++)
559  {
560  if (pKbdTbl->pVSCtoVK_E0[i].Vsc == (wScanCode & 0xFF))
561  {
562  wVk = pKbdTbl->pVSCtoVK_E0[i].Vk;
563  }
564  }
565  }
566  else if ((wScanCode & 0xFF00) == 0xE100)
567  {
568  for (i = 0; pKbdTbl->pVSCtoVK_E1[i].Vsc; i++)
569  {
570  if (pKbdTbl->pVSCtoVK_E1[i].Vsc == (wScanCode & 0xFF))
571  {
572  wVk = pKbdTbl->pVSCtoVK_E1[i].Vk;
573  }
574  }
575  }
576  else if (wScanCode < pKbdTbl->bMaxVSCtoVK)
577  {
578  wVk = pKbdTbl->pusVSCtoVK[wScanCode];
579  }
580 
581  /* 0xFF nad 0x00 are invalid VKs */
582  return wVk != 0xFF ? wVk : 0;
583 }
584 
585 /*
586  * IntVkToChar
587  *
588  * Translates virtual key to character, ignoring shift state
589  */
590 static
593 {
594  WCHAR wch;
595  BOOL bDead, bLigature;
596 
597  ASSERT(pKbdTbl);
598 
599  if (IntTranslateChar(wVk,
600  NULL,
601  &bDead,
602  &bLigature,
603  &wch,
604  pKbdTbl))
605  {
606  return wch;
607  }
608 
609  return 0;
610 }
611 
612 /*
613  * NtUserGetAsyncKeyState
614  *
615  * Gets key state from global bitmap
616  */
617 SHORT
618 APIENTRY
620 {
621  WORD wRet = 0;
622 
623  TRACE("Enter NtUserGetAsyncKeyState\n");
624 
625  if (Key >= 0x100)
626  {
628  ERR("Invalid parameter Key\n");
629  return 0;
630  }
631 
633 
634  if (IS_KEY_DOWN(gafAsyncKeyState, Key))
635  wRet |= 0x8000; // If down, windows returns 0x8000.
636  if (gafAsyncKeyStateRecentDown[Key / 8] & (1 << (Key % 8)))
637  wRet |= 0x1;
638  gafAsyncKeyStateRecentDown[Key / 8] &= ~(1 << (Key % 8));
639 
640  UserLeave();
641 
642  TRACE("Leave NtUserGetAsyncKeyState, ret=%u\n", wRet);
643  return wRet;
644 }
645 
646 /*
647  * UpdateAsyncKeyState
648  *
649  * Updates gafAsyncKeyState array
650  */
651 static
652 VOID NTAPI
654 {
655  if (bIsDown)
656  {
657  /* If it's first key down event, xor lock bit */
658  if (!IS_KEY_DOWN(gafAsyncKeyState, wVk))
660 
662  gafAsyncKeyStateRecentDown[wVk / 8] |= (1 << (wVk % 8));
663  }
664  else
666 }
667 
668 /*
669  * co_CallLowLevelKeyboardHook
670  *
671  * Calls WH_KEYBOARD_LL hook
672  */
673 static LRESULT
674 co_CallLowLevelKeyboardHook(WORD wVk, WORD wScanCode, DWORD dwFlags, BOOL bInjected, DWORD dwTime, DWORD dwExtraInfo)
675 {
676  KBDLLHOOKSTRUCT KbdHookData;
677  UINT uMsg;
678 
679  KbdHookData.vkCode = wVk;
680  KbdHookData.scanCode = wScanCode;
681  KbdHookData.flags = 0;
682  if (dwFlags & KEYEVENTF_EXTENDEDKEY)
683  KbdHookData.flags |= LLKHF_EXTENDED;
685  KbdHookData.flags |= LLKHF_ALTDOWN;
686  if (dwFlags & KEYEVENTF_KEYUP)
687  KbdHookData.flags |= LLKHF_UP;
688  if (bInjected)
689  KbdHookData.flags |= LLKHF_INJECTED;
690  KbdHookData.time = dwTime;
691  KbdHookData.dwExtraInfo = dwExtraInfo;
692 
693  /* Note: it doesnt support WM_SYSKEYUP */
694  if (dwFlags & KEYEVENTF_KEYUP)
695  uMsg = WM_KEYUP;
697  uMsg = WM_SYSKEYDOWN;
698  else
699  uMsg = WM_KEYDOWN;
700 
701  return co_HOOK_CallHooks(WH_KEYBOARD_LL, HC_ACTION, uMsg, (LPARAM)&KbdHookData);
702 }
703 
704 /*
705  * SnapWindow
706  *
707  * Saves snapshot of specified window or whole screen in the clipboard
708  */
709 static VOID
711 {
712  HBITMAP hbm = NULL, hbmOld;
713  HDC hdc = NULL, hdcMem;
714  SETCLIPBDATA scd;
715  INT cx, cy;
716  PWND pWnd = NULL;
717 
718  TRACE("SnapWindow(%p)\n", hWnd);
719 
720  /* If no windows is given, make snapshot of desktop window */
721  if (!hWnd)
722  hWnd = IntGetDesktopWindow();
723 
724  pWnd = UserGetWindowObject(hWnd);
725  if (!pWnd)
726  {
727  ERR("Invalid window\n");
728  goto cleanup;
729  }
730 
731  hdc = UserGetDCEx(pWnd, NULL, DCX_USESTYLE | DCX_WINDOW);
732  if (!hdc)
733  {
734  ERR("UserGetDCEx failed!\n");
735  goto cleanup;
736  }
737 
738  cx = pWnd->rcWindow.right - pWnd->rcWindow.left;
739  cy = pWnd->rcWindow.bottom - pWnd->rcWindow.top;
740 
741  hbm = NtGdiCreateCompatibleBitmap(hdc, cx, cy);
742  if (!hbm)
743  {
744  ERR("NtGdiCreateCompatibleBitmap failed!\n");
745  goto cleanup;
746  }
747 
748  hdcMem = NtGdiCreateCompatibleDC(hdc);
749  if (!hdcMem)
750  {
751  ERR("NtGdiCreateCompatibleDC failed!\n");
752  goto cleanup;
753  }
754 
755  hbmOld = NtGdiSelectBitmap(hdcMem, hbm);
756  NtGdiBitBlt(hdcMem, 0, 0, cx, cy, hdc, 0, 0, SRCCOPY, 0, 0);
757  NtGdiSelectBitmap(hdcMem, hbmOld);
758  IntGdiDeleteDC(hdcMem, FALSE);
759 
760  /* Save snapshot in clipboard */
761  if (UserOpenClipboard(NULL))
762  {
764  scd.fIncSerialNumber = TRUE;
765  scd.fGlobalHandle = FALSE;
766  if (UserSetClipboardData(CF_BITMAP, hbm, &scd))
767  {
768  /* Bitmap is managed by system now */
769  hbm = NULL;
770  }
772  }
773 
774 cleanup:
775  if (hbm)
776  GreDeleteObject(hbm);
777  if (hdc)
778  UserReleaseDC(pWnd, hdc, FALSE);
779 }
780 
781 /*
782  * UserSendKeyboardInput
783  *
784  * Process keyboard input from input devices and SendInput API
785  */
786 BOOL NTAPI
787 ProcessKeyEvent(WORD wVk, WORD wScanCode, DWORD dwFlags, BOOL bInjected, DWORD dwTime, DWORD dwExtraInfo)
788 {
789  WORD wSimpleVk = 0, wFixedVk, wVk2;
790  PUSER_MESSAGE_QUEUE pFocusQueue;
791  PTHREADINFO pti;
792  BOOL bExt = (dwFlags & KEYEVENTF_EXTENDEDKEY) ? TRUE : FALSE;
793  BOOL bIsDown = (dwFlags & KEYEVENTF_KEYUP) ? FALSE : TRUE;
794  BOOL bPacket = (dwFlags & KEYEVENTF_UNICODE) ? TRUE : FALSE;
795  BOOL bWasSimpleDown = FALSE, bPostMsg = TRUE, bIsSimpleDown;
796  MSG Msg;
797  static BOOL bMenuDownRecently = FALSE;
798 
799  /* Get virtual key without shifts (VK_(L|R)* -> VK_*) */
800  wSimpleVk = IntSimplifyVk(wVk);
801  bWasSimpleDown = IS_KEY_DOWN(gafAsyncKeyState, wSimpleVk);
802 
803  /* Update key without shifts */
804  wVk2 = IntFixVk(wSimpleVk, !bExt);
805  bIsSimpleDown = bIsDown || IS_KEY_DOWN(gafAsyncKeyState, wVk2);
806  UpdateAsyncKeyState(wSimpleVk, bIsSimpleDown);
807 
808  if (bIsDown)
809  {
810  /* Update keyboard LEDs */
812  wSimpleVk,
813  wScanCode);
814  }
815 
816  /* Call WH_KEYBOARD_LL hook */
817  if (co_CallLowLevelKeyboardHook(wVk, wScanCode, dwFlags, bInjected, dwTime, dwExtraInfo))
818  {
819  ERR("Kbd msg dropped by WH_KEYBOARD_LL hook\n");
820  bPostMsg = FALSE;
821  }
822 
823  /* Check if this is a hotkey */
824  if (co_UserProcessHotKeys(wSimpleVk, bIsDown))
825  {
826  TRACE("HotKey Processed\n");
827  bPostMsg = FALSE;
828  }
829 
830  wFixedVk = IntFixVk(wSimpleVk, bExt); /* LSHIFT + EXT = RSHIFT */
831  if (wSimpleVk == VK_SHIFT) /* shift can't be extended */
832  bExt = FALSE;
833 
834  /* If we have a focus queue, post a keyboard message */
835  pFocusQueue = IntGetFocusMessageQueue();
836  TRACE("ProcessKeyEvent Q 0x%p Active pWnd 0x%p Focus pWnd 0x%p\n",
837  pFocusQueue,
838  (pFocusQueue ? pFocusQueue->spwndActive : 0),
839  (pFocusQueue ? pFocusQueue->spwndFocus : 0));
840 
841  /* If it is F10 or ALT is down and CTRL is up, it's a system key */
842  if ( wVk == VK_F10 ||
843  (wSimpleVk == VK_MENU && bMenuDownRecently) ||
846  // See MSDN WM_SYSKEYDOWN/UP fixes last wine Win test_keyboard_input.
847  (pFocusQueue && !pFocusQueue->spwndFocus) )
848  {
849  bMenuDownRecently = FALSE; // reset
850  if (bIsDown)
851  {
852  Msg.message = WM_SYSKEYDOWN;
853  if (wSimpleVk == VK_MENU)
854  {
855  // Note: If only LALT is pressed WM_SYSKEYUP is generated instead of WM_KEYUP
856  bMenuDownRecently = TRUE;
857  }
858  }
859  else
860  Msg.message = WM_SYSKEYUP;
861  }
862  else
863  {
864  if (bIsDown)
865  Msg.message = WM_KEYDOWN;
866  else
867  Msg.message = WM_KEYUP;
868  }
869 
870  /* Update async state of not simplified vk here.
871  See user32_apitest:GetKeyState */
872  UpdateAsyncKeyState(wFixedVk, bIsDown);
873 
874  /* Alt-Tab/Esc Check. Use FocusQueue or RIT Queue */
875  if (bIsSimpleDown && !bWasSimpleDown &&
878  (wVk == VK_ESCAPE || wVk == VK_TAB))
879  {
880  TRACE("Alt-Tab/Esc Pressed wParam %x\n",wVk);
881  }
882 
883  if (bIsDown && wVk == VK_SNAPSHOT)
884  {
885  if (pFocusQueue &&
888  {
889  // Snap from Active Window, Focus can be null.
890  SnapWindow(pFocusQueue->spwndActive ? UserHMGetHandle(pFocusQueue->spwndActive) : 0);
891  }
892  else
893  SnapWindow(NULL); // Snap Desktop.
894  }
895  else if (pFocusQueue && bPostMsg)
896  {
897  PWND Wnd = pFocusQueue->spwndFocus; // SysInit.....
898 
899  pti = pFocusQueue->ptiKeyboard;
900 
901  if (!Wnd && pFocusQueue->spwndActive) // SysInit.....
902  {
903  // Going with Active. WM_SYSKEYXXX last wine Win test_keyboard_input.
904  Wnd = pFocusQueue->spwndActive;
905  }
906  if (Wnd) pti = Wnd->head.pti;
907 
908  /* Init message */
909  Msg.hwnd = Wnd ? UserHMGetHandle(Wnd) : NULL;
910  Msg.wParam = wFixedVk & 0xFF; /* Note: It's simplified by msg queue */
911  Msg.lParam = MAKELPARAM(1, wScanCode);
912  Msg.time = dwTime;
913  Msg.pt = gpsi->ptCursor;
914 
915  if ( Msg.message == WM_KEYDOWN || Msg.message == WM_SYSKEYDOWN )
916  {
917  if ( (Msg.wParam == VK_SHIFT ||
918  Msg.wParam == VK_CONTROL ||
919  Msg.wParam == VK_MENU ) &&
920  !IS_KEY_DOWN(gafAsyncKeyState, Msg.wParam))
921  {
922  ERR("Set last input\n");
923  //ptiLastInput = pti;
924  }
925  }
926 
927  /* If it is VK_PACKET, high word of wParam is used for wchar */
928  if (!bPacket)
929  {
930  if (bExt)
931  Msg.lParam |= KF_EXTENDED << 16;
933  Msg.lParam |= KF_ALTDOWN << 16;
934  if (bWasSimpleDown)
935  Msg.lParam |= KF_REPEAT << 16;
936  if (!bIsDown)
937  Msg.lParam |= KF_UP << 16;
938  /* FIXME: Set KF_DLGMODE and KF_MENUMODE when needed */
939  if (pFocusQueue->QF_flags & QF_DIALOGACTIVE)
940  Msg.lParam |= KF_DLGMODE << 16;
941  if (pFocusQueue->MenuOwner) // pti->pMenuState->fMenuStarted
942  Msg.lParam |= KF_MENUMODE << 16;
943  }
944 
945  // Post mouse move before posting key buttons, to keep it syned.
946  if (pFocusQueue->QF_flags & QF_MOUSEMOVED)
947  {
949  }
950 
951  /* Post a keyboard message */
952  TRACE("Posting keyboard msg %u wParam 0x%x lParam 0x%x\n", Msg.message, Msg.wParam, Msg.lParam);
953  if (!Wnd) {ERR("Window is NULL\n");}
954  MsqPostMessage(pti, &Msg, TRUE, QS_KEY, 0, dwExtraInfo);
955  }
956  return TRUE;
957 }
958 
959 BOOL NTAPI
960 UserSendKeyboardInput(KEYBDINPUT *pKbdInput, BOOL bInjected)
961 {
962  WORD wScanCode, wVk;
963  PKL pKl = NULL;
964  PKBDTABLES pKbdTbl;
965  PUSER_MESSAGE_QUEUE pFocusQueue;
966  LARGE_INTEGER LargeTickCount;
967  DWORD dwTime;
968  BOOL bExt = (pKbdInput->dwFlags & KEYEVENTF_EXTENDEDKEY) ? TRUE : FALSE;
969 
971 
972  /* Find the target thread whose locale is in effect */
973  pFocusQueue = IntGetFocusMessageQueue();
974 
975  if (pFocusQueue && pFocusQueue->ptiKeyboard)
976  {
977  pKl = pFocusQueue->ptiKeyboard->KeyboardLayout;
978  }
979 
980  if (!pKl)
981  pKl = W32kGetDefaultKeyLayout();
982  if (!pKl)
983  {
984  ERR("No keyboard layout!\n");
985  return FALSE;
986  }
987 
988  pKbdTbl = pKl->spkf->pKbdTbl;
989 
990  /* Note: wScan field is always used */
991  wScanCode = pKbdInput->wScan;
992 
993  if (pKbdInput->dwFlags & KEYEVENTF_UNICODE)
994  {
995  /* Generate WM_KEYDOWN msg with wParam == VK_PACKET and
996  high order word of lParam == pKbdInput->wScan */
997  wVk = VK_PACKET;
998  }
999  else
1000  {
1001  wScanCode &= 0x7F;
1002  if (pKbdInput->dwFlags & KEYEVENTF_SCANCODE)
1003  {
1004  /* Don't ignore invalid scan codes */
1005  wVk = IntVscToVk(wScanCode | (bExt ? 0xE000 : 0), pKbdTbl);
1006  if (!wVk) /* use 0xFF if vsc is invalid */
1007  wVk = 0xFF;
1008  }
1009  else
1010  {
1011  wVk = pKbdInput->wVk & 0xFF;
1012  }
1013  }
1014 
1015  /* If time is given, use it */
1016  if (pKbdInput->time)
1017  dwTime = pKbdInput->time;
1018  else
1019  {
1020  KeQueryTickCount(&LargeTickCount);
1021  dwTime = MsqCalculateMessageTime(&LargeTickCount);
1022  }
1023 
1024  if (wVk == VK_RMENU && (pKbdTbl->fLocaleFlags & KLLF_ALTGR))
1025  {
1026  /* For AltGr keyboards RALT generates CTRL events */
1027  ProcessKeyEvent(VK_LCONTROL, 0, pKbdInput->dwFlags & KEYEVENTF_KEYUP, bInjected, dwTime, 0);
1028  }
1029 
1030  /* Finally process this key */
1031  return ProcessKeyEvent(wVk, wScanCode, pKbdInput->dwFlags, bInjected, dwTime, pKbdInput->dwExtraInfo);
1032 }
1033 
1034 /*
1035  * UserProcessKeyboardInput
1036  *
1037  * Process raw keyboard input data
1038  */
1039 VOID NTAPI
1041  PKEYBOARD_INPUT_DATA pKbdInputData)
1042 {
1043  WORD wScanCode, wVk;
1044  PKL pKl = NULL;
1045  PKBDTABLES pKbdTbl;
1046  PUSER_MESSAGE_QUEUE pFocusQueue;
1047 
1048  /* Calculate scan code with prefix */
1049  wScanCode = pKbdInputData->MakeCode & 0x7F;
1050  if (pKbdInputData->Flags & KEY_E0)
1051  wScanCode |= 0xE000;
1052  if (pKbdInputData->Flags & KEY_E1)
1053  wScanCode |= 0xE100;
1054 
1055  /* Find the target thread whose locale is in effect */
1056  pFocusQueue = IntGetFocusMessageQueue();
1057 
1058  if (pFocusQueue && pFocusQueue->ptiKeyboard)
1059  {
1060  pKl = pFocusQueue->ptiKeyboard->KeyboardLayout;
1061  }
1062 
1063  if (!pKl)
1064  pKl = W32kGetDefaultKeyLayout();
1065  if (!pKl)
1066  return;
1067 
1068  pKbdTbl = pKl->spkf->pKbdTbl;
1069 
1070  /* Convert scan code to virtual key.
1071  Note: We could call UserSendKeyboardInput using scan code,
1072  but it wouldn't interpret E1 key(s) properly */
1073  wVk = IntVscToVk(wScanCode, pKbdTbl);
1074  TRACE("UserProcessKeyboardInput: %x (break: %u) -> %x\n",
1075  wScanCode, (pKbdInputData->Flags & KEY_BREAK) ? 1u : 0, wVk);
1076 
1077  if (wVk)
1078  {
1079  KEYBDINPUT KbdInput;
1080 
1081  /* Support numlock */
1083  {
1084  wVk = IntTranslateNumpadKey(wVk & 0xFF);
1085  }
1086 
1087  /* Send keyboard input */
1088  KbdInput.wVk = wVk & 0xFF;
1089  KbdInput.wScan = wScanCode & 0x7F;
1090  KbdInput.dwFlags = 0;
1091  if (pKbdInputData->Flags & KEY_BREAK)
1092  KbdInput.dwFlags |= KEYEVENTF_KEYUP;
1093 
1094  if (wVk & KBDEXT)
1095  KbdInput.dwFlags |= KEYEVENTF_EXTENDEDKEY;
1096  //
1097  // Based on wine input:test_Input_blackbox this is okay. It seems the
1098  // bit did not get set and more research is needed. Now the right
1099  // shift works.
1100  //
1101  if (wVk == VK_RSHIFT)
1102  KbdInput.dwFlags |= KEYEVENTF_EXTENDEDKEY;
1103 
1104  KbdInput.time = 0;
1105  KbdInput.dwExtraInfo = pKbdInputData->ExtraInformation;
1106  UserSendKeyboardInput(&KbdInput, FALSE);
1107 
1108  /* E1 keys don't have break code */
1109  if (pKbdInputData->Flags & KEY_E1)
1110  {
1111  /* Send key up event */
1112  KbdInput.dwFlags |= KEYEVENTF_KEYUP;
1113  UserSendKeyboardInput(&KbdInput, FALSE);
1114  }
1115  }
1116 }
1117 
1118 /*
1119  * IntTranslateKbdMessage
1120  *
1121  * Addes WM_(SYS)CHAR messages to message queue if message
1122  * describes key which produce character.
1123  */
1124 BOOL FASTCALL
1126  UINT flags)
1127 {
1128  PTHREADINFO pti;
1129  INT cch = 0, i;
1130  WCHAR wch[3] = { 0 };
1131  MSG NewMsg = { 0 };
1132  PKBDTABLES pKbdTbl;
1133  LARGE_INTEGER LargeTickCount;
1134  BOOL bResult = FALSE;
1135 
1136  switch(lpMsg->message)
1137  {
1138  case WM_KEYDOWN:
1139  case WM_KEYUP:
1140  case WM_SYSKEYDOWN:
1141  case WM_SYSKEYUP:
1142  break;
1143  default:
1144  return FALSE;
1145  }
1146 
1148 
1149  if (!pti->KeyboardLayout)
1150  {
1152  pti->pClientInfo->hKL = pti->KeyboardLayout ? pti->KeyboardLayout->hkl : NULL;
1153  pKbdTbl = pti->KeyboardLayout ? pti->KeyboardLayout->spkf->pKbdTbl : NULL;
1154  }
1155  else
1156  pKbdTbl = pti->KeyboardLayout->spkf->pKbdTbl;
1157  if (!pKbdTbl)
1158  return FALSE;
1159 
1160  if (lpMsg->message != WM_KEYDOWN && lpMsg->message != WM_SYSKEYDOWN)
1161  return FALSE;
1162 
1163  /* Init pt, hwnd and time msg fields */
1164  NewMsg.pt = gpsi->ptCursor;
1165  NewMsg.hwnd = lpMsg->hwnd;
1166  KeQueryTickCount(&LargeTickCount);
1167  NewMsg.time = MsqCalculateMessageTime(&LargeTickCount);
1168 
1169  TRACE("Enter IntTranslateKbdMessage msg %s, vk %x\n",
1170  lpMsg->message == WM_SYSKEYDOWN ? "WM_SYSKEYDOWN" : "WM_KEYDOWN", lpMsg->wParam);
1171 
1172  if (lpMsg->wParam == VK_PACKET)
1173  {
1174  NewMsg.message = (lpMsg->message == WM_KEYDOWN) ? WM_CHAR : WM_SYSCHAR;
1175  NewMsg.wParam = HIWORD(lpMsg->lParam);
1176  NewMsg.lParam = LOWORD(lpMsg->lParam);
1177  MsqPostMessage(pti, &NewMsg, FALSE, QS_KEY, 0, 0);
1178  return TRUE;
1179  }
1180 
1181  cch = IntToUnicodeEx(lpMsg->wParam,
1182  HIWORD(lpMsg->lParam) & 0xFF,
1183  pti->MessageQueue->afKeyState,
1184  wch,
1185  sizeof(wch) / sizeof(wch[0]),
1186  0,
1187  pKbdTbl);
1188 
1189  if (cch)
1190  {
1191  if (cch > 0) /* Normal characters */
1192  NewMsg.message = (lpMsg->message == WM_KEYDOWN) ? WM_CHAR : WM_SYSCHAR;
1193  else /* Dead character */
1194  {
1195  cch = -cch;
1196  NewMsg.message =
1197  (lpMsg->message == WM_KEYDOWN) ? WM_DEADCHAR : WM_SYSDEADCHAR;
1198  }
1199  NewMsg.lParam = lpMsg->lParam;
1200 
1201  /* Send all characters */
1202  for (i = 0; i < cch; ++i)
1203  {
1204  TRACE("Msg: %x '%lc' (%04x) %08x\n", NewMsg.message, wch[i], wch[i], NewMsg.lParam);
1205  NewMsg.wParam = wch[i];
1206  MsqPostMessage(pti, &NewMsg, FALSE, QS_KEY, 0, 0);
1207  }
1208  bResult = TRUE;
1209  }
1210 
1211  TRACE("Leave IntTranslateKbdMessage ret %d, cch %d, msg %x, wch %x\n",
1212  bResult, cch, NewMsg.message, NewMsg.wParam);
1213  return bResult;
1214 }
1215 
1216 /*
1217  * Map a virtual key code, or virtual scan code, to a scan code, key code,
1218  * or unshifted unicode character.
1219  *
1220  * Code: See Below
1221  * Type:
1222  * 0 -- Code is a virtual key code that is converted into a virtual scan code
1223  * that does not distinguish between left and right shift keys.
1224  * 1 -- Code is a virtual scan code that is converted into a virtual key code
1225  * that does not distinguish between left and right shift keys.
1226  * 2 -- Code is a virtual key code that is converted into an unshifted unicode
1227  * character.
1228  * 3 -- Code is a virtual scan code that is converted into a virtual key code
1229  * that distinguishes left and right shift keys.
1230  * KeyLayout: Keyboard layout handle
1231  *
1232  * @implemented
1233  */
1234 static UINT
1236 {
1237  UINT uRet = 0;
1238 
1239  switch (Type)
1240  {
1241  case MAPVK_VK_TO_VSC:
1242  uCode = IntFixVk(uCode, FALSE);
1243  uRet = IntVkToVsc(uCode, pKbdTbl);
1244  if (uRet > 0xFF) // Fail for scancodes with prefix (e0, e1)
1245  uRet = 0;
1246  break;
1247 
1248  case MAPVK_VSC_TO_VK:
1249  uRet = IntVscToVk(uCode, pKbdTbl) & 0xFF;
1250  uRet = IntSimplifyVk(uRet);
1251  break;
1252 
1253  case MAPVK_VK_TO_CHAR:
1254  uRet = (UINT)IntVkToChar(uCode, pKbdTbl);
1255  break;
1256 
1257  case MAPVK_VSC_TO_VK_EX:
1258  uRet = IntVscToVk(uCode, pKbdTbl) & 0xFF;
1259  break;
1260 
1261  case MAPVK_VK_TO_VSC_EX:
1262  uRet = IntVkToVsc(uCode, pKbdTbl);
1263  break;
1264 
1265  default:
1267  ERR("Wrong type value: %u\n", Type);
1268  }
1269 
1270  return uRet;
1271 }
1272 
1273 /*
1274  * NtUserMapVirtualKeyEx
1275  *
1276  * Map a virtual key code, or virtual scan code, to a scan code, key code,
1277  * or unshifted unicode character. See IntMapVirtualKeyEx.
1278  */
1279 UINT
1280 APIENTRY
1281 NtUserMapVirtualKeyEx(UINT uCode, UINT uType, DWORD keyboardId, HKL dwhkl)
1282 {
1283  PKBDTABLES pKbdTbl = NULL;
1284  UINT ret = 0;
1285 
1286  TRACE("Enter NtUserMapVirtualKeyEx\n");
1287  UserEnterShared();
1288 
1289  if (!dwhkl)
1290  {
1291  PTHREADINFO pti;
1292 
1294  if (pti && pti->KeyboardLayout)
1295  pKbdTbl = pti->KeyboardLayout->spkf->pKbdTbl;
1296  }
1297  else
1298  {
1299  PKL pKl;
1300 
1301  pKl = UserHklToKbl(dwhkl);
1302  if (pKl)
1303  pKbdTbl = pKl->spkf->pKbdTbl;
1304  }
1305 
1306  if (pKbdTbl)
1307  ret = IntMapVirtualKeyEx(uCode, uType, pKbdTbl);
1308 
1309  UserLeave();
1310  TRACE("Leave NtUserMapVirtualKeyEx, ret=%u\n", ret);
1311  return ret;
1312 }
1313 
1314 /*
1315  * NtUserToUnicodeEx
1316  *
1317  * Translates virtual key to characters
1318  */
1319 int
1320 APIENTRY
1322  UINT wVirtKey,
1323  UINT wScanCode,
1324  PBYTE pKeyStateUnsafe,
1325  LPWSTR pwszBuffUnsafe,
1326  INT cchBuff,
1327  UINT wFlags,
1328  HKL dwhkl)
1329 {
1330  PTHREADINFO pti;
1331  BYTE afKeyState[256 * 2 / 8] = {0};
1332  PWCHAR pwszBuff = NULL;
1333  INT i, iRet = 0;
1334  PKL pKl = NULL;
1335 
1336  TRACE("Enter NtUserSetKeyboardState\n");
1337 
1338  /* Return 0 if SC_KEY_UP bit is set */
1339  if (wScanCode & SC_KEY_UP || wVirtKey >= 0x100)
1340  {
1341  ERR("Invalid parameter\n");
1342  return 0;
1343  }
1344 
1345  _SEH2_TRY
1346  {
1347  /* Probe and copy key state to smaller bitmap */
1348  ProbeForRead(pKeyStateUnsafe, 256 * sizeof(BYTE), 1);
1349  for (i = 0; i < 256; ++i)
1350  {
1351  if (pKeyStateUnsafe[i] & KS_DOWN_BIT)
1352  SET_KEY_DOWN(afKeyState, i, TRUE);
1353  if (pKeyStateUnsafe[i] & KS_LOCK_BIT)
1354  SET_KEY_LOCKED(afKeyState, i, TRUE);
1355  }
1356  }
1358  {
1359  ERR("Cannot copy key state\n");
1361  _SEH2_YIELD(return 0);
1362  }
1363  _SEH2_END;
1364 
1365  pwszBuff = ExAllocatePoolWithTag(NonPagedPool, sizeof(WCHAR) * cchBuff, TAG_STRING);
1366  if (!pwszBuff)
1367  {
1368  ERR("ExAllocatePoolWithTag(%u) failed\n", sizeof(WCHAR) * cchBuff);
1369  return 0;
1370  }
1371  RtlZeroMemory(pwszBuff, sizeof(WCHAR) * cchBuff);
1372 
1373  UserEnterExclusive(); // Note: We modify wchDead static variable
1374 
1375  if (dwhkl)
1376  pKl = UserHklToKbl(dwhkl);
1377 
1378  if (!pKl)
1379  {
1381  pKl = pti->KeyboardLayout;
1382  }
1383 
1384  iRet = IntToUnicodeEx(wVirtKey,
1385  wScanCode,
1386  afKeyState,
1387  pwszBuff,
1388  cchBuff,
1389  wFlags,
1390  pKl ? pKl->spkf->pKbdTbl : NULL);
1391 
1392  MmCopyToCaller(pwszBuffUnsafe, pwszBuff, cchBuff * sizeof(WCHAR));
1393  ExFreePoolWithTag(pwszBuff, TAG_STRING);
1394 
1395  UserLeave();
1396  TRACE("Leave NtUserSetKeyboardState, ret=%i\n", iRet);
1397  return iRet;
1398 }
1399 
1400 /*
1401  * NtUserGetKeyNameText
1402  *
1403  * Gets key name from keyboard layout
1404  */
1405 DWORD
1406 APIENTRY
1407 NtUserGetKeyNameText(LONG lParam, LPWSTR lpString, int cchSize)
1408 {
1409  PTHREADINFO pti;
1410  DWORD i, dwRet = 0;
1411  SIZE_T cchKeyName;
1412  WORD wScanCode = (lParam >> 16) & 0xFF;
1413  BOOL bExtKey = (HIWORD(lParam) & KF_EXTENDED) ? TRUE : FALSE;
1414  PKBDTABLES pKbdTbl;
1415  VSC_LPWSTR *pKeyNames = NULL;
1416  CONST WCHAR *pKeyName = NULL;
1417  WCHAR KeyNameBuf[2];
1418 
1419  TRACE("Enter NtUserGetKeyNameText\n");
1420 
1421  UserEnterShared();
1422 
1423  /* Get current keyboard layout */
1425  pKbdTbl = pti ? pti->KeyboardLayout->spkf->pKbdTbl : 0;
1426 
1427  if (!pKbdTbl || cchSize < 1)
1428  {
1429  ERR("Invalid parameter\n");
1430  goto cleanup;
1431  }
1432 
1433  /* "Do not care" flag */
1434  if(lParam & LP_DO_NOT_CARE_BIT)
1435  {
1436  /* Note: We could do vsc -> vk -> vsc conversion, instead of using
1437  hardcoded scan codes, but it's not what Windows does */
1438  if (wScanCode == SCANCODE_RSHIFT && !bExtKey)
1439  wScanCode = SCANCODE_LSHIFT;
1440  else if (wScanCode == SCANCODE_CTRL || wScanCode == SCANCODE_ALT)
1441  bExtKey = FALSE;
1442  }
1443 
1444  if (bExtKey)
1445  pKeyNames = pKbdTbl->pKeyNamesExt;
1446  else
1447  pKeyNames = pKbdTbl->pKeyNames;
1448 
1449  for (i = 0; pKeyNames[i].pwsz; i++)
1450  {
1451  if (pKeyNames[i].vsc == wScanCode)
1452  {
1453  pKeyName = pKeyNames[i].pwsz;
1454  break;
1455  }
1456  }
1457 
1458  if (!pKeyName)
1459  {
1460  WORD wVk = IntVscToVk(wScanCode, pKbdTbl);
1461 
1462  if (wVk)
1463  {
1464  KeyNameBuf[0] = IntVkToChar(wVk, pKbdTbl);
1465  KeyNameBuf[1] = 0;
1466  if (KeyNameBuf[0])
1467  pKeyName = KeyNameBuf;
1468  }
1469  }
1470 
1471  if (pKeyName)
1472  {
1473  cchKeyName = wcslen(pKeyName);
1474  if (cchKeyName > (cchSize - 1UL))
1475  cchKeyName = cchSize - 1UL; // Don't count '\0'
1476 
1477  _SEH2_TRY
1478  {
1479  ProbeForWrite(lpString, (cchKeyName + 1) * sizeof(WCHAR), 1);
1480  RtlCopyMemory(lpString, pKeyName, cchKeyName * sizeof(WCHAR));
1481  lpString[cchKeyName] = UNICODE_NULL;
1482  dwRet = cchKeyName;
1483  }
1485  {
1487  }
1488  _SEH2_END;
1489  }
1490  else
1491  {
1493  }
1494 
1495 cleanup:
1496  UserLeave();
1497  TRACE("Leave NtUserGetKeyNameText, ret=%lu\n", dwRet);
1498  return dwRet;
1499 }
1500 
1501 /*
1502  * UserGetKeyboardType
1503  *
1504  * Returns some keyboard specific information
1505  */
1508  DWORD dwTypeFlag)
1509 {
1510  switch (dwTypeFlag)
1511  {
1512  case 0: /* Keyboard type */
1513  return (DWORD)gKeyboardInfo.KeyboardIdentifier.Type;
1514  case 1: /* Keyboard Subtype */
1515  return (DWORD)gKeyboardInfo.KeyboardIdentifier.Subtype;
1516  case 2: /* Number of F-keys */
1517  return (DWORD)gKeyboardInfo.NumberOfFunctionKeys;
1518  default:
1519  ERR("Unknown type!\n");
1520  return 0; /* Note: we don't have to set last error here */
1521  }
1522 }
1523 
1524 /*
1525  * NtUserVkKeyScanEx
1526  *
1527  * Based on IntTranslateChar, instead of processing VirtualKey match,
1528  * look for wChar match.
1529  */
1530 DWORD
1531 APIENTRY
1533  WCHAR wch,
1534  HKL dwhkl,
1535  BOOL bUsehKL)
1536 {
1537  PKBDTABLES pKbdTbl;
1538  PVK_TO_WCHAR_TABLE pVkToWchTbl;
1539  PVK_TO_WCHARS10 pVkToWch;
1540  PKL pKl = NULL;
1541  DWORD i, dwModBits = 0, dwModNumber = 0, Ret = (DWORD)-1;
1542 
1543  TRACE("NtUserVkKeyScanEx() wch %u, KbdLayout 0x%p\n", wch, dwhkl);
1544  UserEnterShared();
1545 
1546  if (bUsehKL)
1547  {
1548  // Use given keyboard layout
1549  if (dwhkl)
1550  pKl = UserHklToKbl(dwhkl);
1551  }
1552  else
1553  {
1554  // Use thread keyboard layout
1556  }
1557 
1558  if (!pKl)
1559  goto Exit;
1560 
1561  pKbdTbl = pKl->spkf->pKbdTbl;
1562 
1563  // Interate through all VkToWchar tables while pVkToWchars is not NULL
1564  for (i = 0; pKbdTbl->pVkToWcharTable[i].pVkToWchars; i++)
1565  {
1566  pVkToWchTbl = &pKbdTbl->pVkToWcharTable[i];
1567  pVkToWch = (PVK_TO_WCHARS10)(pVkToWchTbl->pVkToWchars);
1568 
1569  // Interate through all virtual keys
1570  while (pVkToWch->VirtualKey)
1571  {
1572  for (dwModNumber = 0; dwModNumber < pVkToWchTbl->nModifications; dwModNumber++)
1573  {
1574  if (pVkToWch->wch[dwModNumber] == wch)
1575  {
1576  dwModBits = pKbdTbl->pCharModifiers->ModNumber[dwModNumber];
1577  TRACE("i %lu wC %04x: dwModBits %08x dwModNumber %08x MaxModBits %08x\n",
1578  i, wch, dwModBits, dwModNumber, pKbdTbl->pCharModifiers->wMaxModBits);
1579  Ret = (dwModBits << 8) | (pVkToWch->VirtualKey & 0xFF);
1580  goto Exit;
1581  }
1582  }
1583  pVkToWch = (PVK_TO_WCHARS10)(((BYTE *)pVkToWch) + pVkToWchTbl->cbSize);
1584  }
1585  }
1586 Exit:
1587  UserLeave();
1588  return Ret;
1589 }
1590 
1591 /* EOF */
WCHAR wchComposed
Definition: kbd.h:58
int UINT uType
Definition: wglext.h:470
#define ERROR_INVALID_PARAMETER
Definition: compat.h:91
USHORT MakeCode
Definition: ntddkbd.h:114
#define HDC
Definition: msvc.h:22
#define VK_NUMPAD8
Definition: winuser.h:2201
VOID FASTCALL UserEnterShared(VOID)
Definition: ntuser.c:237
PVK_TO_WCHARS1 pVkToWchars
Definition: kbd.h:51
#define VK_NUMPAD0
Definition: winuser.h:2193
#define KF_MENUMODE
Definition: winuser.h:2402
unsigned short WORD
Definition: ntddk_ex.h:93
BOOL NTAPI GreDeleteObject(HGDIOBJ hobj)
Definition: gdiobj.c:1153
#define USERTAG_KBDTABLE
Definition: tags.h:246
#define TRUE
Definition: types.h:120
NTSYSAPI VOID NTAPI RtlCopyMemory(VOID UNALIGNED *Destination, CONST VOID UNALIGNED *Source, ULONG Length)
struct @1570 Msg[]
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
#define HBITMAP
Definition: msvc.h:28
BYTE ModBits
Definition: kbd.h:23
#define KBDCTRL
Definition: kbd.h:15
Type
Definition: Type.h:6
#define WM_CHAR
Definition: winuser.h:1693
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:1092
#define VK_NUMPAD6
Definition: winuser.h:2199
ASSERT((InvokeOnSuccess||InvokeOnError||InvokeOnCancel)?(CompletionRoutine!=NULL):TRUE)
USHORT IndicatorFlags
Definition: ntddkbd.h:115
__wchar_t WCHAR
Definition: xmlstorage.h:180
BOOL FASTCALL IntGdiDeleteDC(HDC, BOOL)
Definition: dclife.c:881
#define VK_RMENU
Definition: winuser.h:2241
#define TAG_STRING
Definition: oslist.c:24
BYTE gafAsyncKeyState[256 *2/8]
Definition: keyboard.c:13
BOOL FASTCALL IntTranslateKbdMessage(LPMSG lpMsg, UINT flags)
Definition: keyboard.c:1125
#define VK_LSHIFT
Definition: winuser.h:2236
TW_UINT32 TW_UINT16 TW_UINT16 MSG
Definition: twain.h:1827
#define SCANCODE_RSHIFT
Definition: kbd.h:129
#define WARN(fmt,...)
Definition: debug.h:111
#define MAKELPARAM(l, h)
Definition: winuser.h:3915
PVOID NTAPI PsGetCurrentThreadWin32Thread(VOID)
Definition: thread.c:805
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:2198
static KEYBOARD_INDICATOR_PARAMETERS gIndicators
Definition: keyboard.c:16
INIT_FUNCTION NTSTATUS NTAPI InitKeyboardImpl(VOID)
Definition: keyboard.c:31
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
UINT uMsg
Definition: precomp.h:45
__kernel_entry W32KAPI HBITMAP APIENTRY NtGdiSelectBitmap(_In_ HDC hdc, _In_ HBITMAP hbm)
LONG top
Definition: windef.h:297
HANDLE HWND
Definition: compat.h:13
static WORD FASTCALL IntVscToVk(WORD wScanCode, PKBDTABLES pKbdTbl)
Definition: keyboard.c:549
DWORD time
Definition: winable.h:50
#define DCX_USESTYLE
Definition: GetDCEx.c:10
#define VK_LEFT
Definition: winuser.h:2178
#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:3069
GLenum GLclampf GLint GLenum GLuint GLenum GLenum GLsizei GLenum const GLvoid GLfloat GLfloat GLfloat GLfloat GLclampd GLint 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 GLboolean GLboolean GLboolean GLint GLenum GLsizei const GLvoid GLenum GLint GLenum GLint GLint GLsizei GLint GLenum GLint GLint GLint GLint GLsizei GLenum GLsizei const GLuint GLboolean GLenum GLenum GLint GLsizei GLenum GLsizei GLenum const GLvoid GLboolean const GLboolean GLenum const GLdouble * u
Definition: glfuncs.h:88
#define MmCopyToCaller(x, y, z)
Definition: mmcopy.h:19
#define KF_UP
Definition: winuser.h:2405
#define VK_TAB
Definition: winuser.h:2153
#define VK_DOWN
Definition: winuser.h:2181
#define VK_INSERT
Definition: winuser.h:2186
#define KEYBOARD_CAPS_LOCK_ON
Definition: ntddkbd.h:81
#define VK_DECIMAL
Definition: winuser.h:2207
#define VK_PRIOR
Definition: winuser.h:2174
#define VK_MENU
Definition: winuser.h:2158
uint16_t * PWCHAR
Definition: typedefs.h:54
LONG left
Definition: windef.h:296
PVSC_VK pVSCtoVK_E0
Definition: kbd.h:104
DWORD fLocaleFlags
Definition: kbd.h:106
BOOL NTAPI UserOpenClipboard(HWND hWnd)
Definition: clipboard.c:470
#define KEY_BREAK
Definition: ntddkbd.h:71
BOOL NTAPI UserSendKeyboardInput(KEYBDINPUT *pKbdInput, BOOL bInjected)
Definition: keyboard.c:960
#define VK_ESCAPE
Definition: winuser.h:2168
#define QF_DIALOGACTIVE
Definition: msgqueue.h:106
#define VK_NUMPAD9
Definition: winuser.h:2202
LONG right
Definition: windef.h:298
#define KF_DLGMODE
Definition: winuser.h:2401
static __inline LONG MsqCalculateMessageTime(IN PLARGE_INTEGER TickCount)
Definition: msgqueue.h:253
#define FASTCALL
Definition: nt_native.h:50
HANDLE ghKeyboardDevice
Definition: input.c:19
VOID NTAPI UserProcessKeyboardInput(PKEYBOARD_INPUT_DATA pKbdInputData)
Definition: keyboard.c:1040
PUSER_MESSAGE_QUEUE FASTCALL IntGetFocusMessageQueue(VOID)
Definition: desktop.c:1254
#define MAPVK_VSC_TO_VK_EX
Definition: winuser.h:2312
PSERVERINFO gpsi
Definition: main.c:27
int32_t INT
Definition: typedefs.h:56
#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
DWORD DWORD
Definition: winlogon.h:84
#define CAPLOK
Definition: kbd.h:118
static LRESULT co_CallLowLevelKeyboardHook(WORD wVk, WORD wScanCode, DWORD dwFlags, BOOL bInjected, DWORD dwTime, DWORD dwExtraInfo)
Definition: keyboard.c:674
#define DCX_WINDOW
Definition: winuser.h:2074
#define VK_NEXT
Definition: winuser.h:2175
#define STATUS_BUFFER_TOO_SMALL
Definition: shellext.h:52
#define SCANCODE_LSHIFT
Definition: kbd.h:128
_SEH2_TRY
Definition: create.c:4250
#define VK_F10
Definition: winuser.h:2218
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
GLenum GLclampf GLint i
Definition: glfuncs.h:14
#define VK_HOME
Definition: winuser.h:2177
NTSTATUS(* NTAPI)(IN PFILE_FULL_EA_INFORMATION EaBuffer, IN ULONG EaLength, OUT PULONG ErrorOffset)
Definition: IoEaTest.cpp:117
#define VK_UP
Definition: winuser.h:2179
#define FALSE
Definition: types.h:117
#define UNICODE_NULL
BOOL NTAPI UserCloseClipboard(VOID)
Definition: clipboard.c:527
long LONG
Definition: pedump.c:60
#define SET_KEY_DOWN(ks, vk, down)
Definition: input.h:100
LONG_PTR LPARAM
Definition: windef.h:208
short SHORT
Definition: pedump.c:59
#define WM_SYSCHAR
Definition: winuser.h:1697
PDEADKEY pDeadKey
Definition: kbd.h:98
#define LLKHF_UP
Definition: winuser.h:2602
#define EXCEPTION_EXECUTE_HANDLER
Definition: excpt.h:85
_Out_opt_ int _Out_opt_ int * cy
Definition: commctrl.h:570
BOOL fGlobalHandle
Definition: ntuser.h:1117
static WORD FASTCALL IntVkToVsc(WORD wVk, PKBDTABLES pKbdTbl)
Definition: keyboard.c:512
#define VK_SHIFT
Definition: winuser.h:2156
THRDESKHEAD head
Definition: ntuser.h:659
HDC hdc
Definition: msvc.h:53
#define APIENTRY
Definition: nt_native.h:48
#define CF_BITMAP
Definition: constants.h:397
static DWORD DWORD void LPSTR DWORD cch
Definition: str.c:201
#define CAPLOKALTGR
Definition: kbd.h:120
PPROCESSINFO gppiInputProvider
Definition: ntuser.c:16
smooth NULL
Definition: ftsmooth.c:416
Definition: input.h:26
#define VK_NUMPAD3
Definition: winuser.h:2196
__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:1691
#define IS_KEY_LOCKED(ks, vk)
Definition: input.h:99
LPARAM lParam
Definition: winuser.h:3070
UINT APIENTRY NtUserMapVirtualKeyEx(UINT uCode, UINT uType, DWORD keyboardId, HKL dwhkl)
Definition: keyboard.c:1281
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:103
VOID NTAPI KeQueryTickCount(IN PLARGE_INTEGER TickCount)
Definition: clock.c:165
#define VK_DELETE
Definition: winuser.h:2187
static PKEYBOARD_INDICATOR_TRANSLATION gpKeyboardIndicatorTrans
Definition: keyboard.c:15
#define CONST
Definition: compiler.h:170
#define KF_EXTENDED
Definition: winuser.h:2400
DWORD dwTime
Definition: solitaire.cpp:25
DWORD dwFlags
Definition: winable.h:49
VOID FASTCALL UserEnterExclusive(VOID)
Definition: ntuser.c:243
#define UserHMGetHandle(obj)
Definition: ntuser.h:208
#define KF_REPEAT
Definition: winuser.h:2404
#define MAPVK_VSC_TO_VK
Definition: winuser.h:2310
#define IOCTL_KEYBOARD_QUERY_INDICATORS
Definition: ntddkbd.h:35
#define WM_DEADCHAR
Definition: winuser.h:1694
VSC_LPWSTR * pKeyNames
Definition: kbd.h:99
#define TRACE(s)
Definition: solgame.cpp:4
unsigned int BOOL
Definition: ntddk_ex.h:94
struct _THREADINFO * PTHREADINFO
Definition: ntwin32.h:6
LONG NTSTATUS
Definition: precomp.h:26
BYTE ModNumber[]
Definition: kbd.h:29
#define _SEH2_YIELD(STMT_)
Definition: pseh2_64.h:8
#define WH_KEYBOARD_LL
Definition: winuser.h:43
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:24
#define MAPVK_VK_TO_VSC
Definition: winuser.h:2309
static void Exit(void)
Definition: sock.c:1331
#define MAPVK_VK_TO_VSC_EX
Definition: winuser.h:2313
WORD wMaxModBits
Definition: kbd.h:28
Definition: kbd.h:95
#define WM_KEYUP
Definition: winuser.h:1692
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
VOID FASTCALL MsqPostMessage(PTHREADINFO pti, MSG *Msg, BOOLEAN HardwareMessage, DWORD MessageBits, DWORD dwQEvent, LONG_PTR ExtraInfo)
Definition: msgqueue.c:1342
#define VK_NUMPAD4
Definition: winuser.h:2197
static WORD IntTranslateNumpadKey(WORD wVk)
Definition: keyboard.c:272
struct _CLIENTINFO * pClientInfo
Definition: win32.h:93
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:1407
#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:1089
PVK_TO_BIT pVkToBit
Definition: kbd.h:27
#define LLKHF_INJECTED
Definition: winuser.h:2600
SHORT APIENTRY NtUserGetAsyncKeyState(INT Key)
Definition: keyboard.c:619
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_RCONTROL
Definition: winuser.h:2239
#define VK_LMENU
Definition: winuser.h:2240
#define VK_RSHIFT
Definition: winuser.h:2237
_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:653
#define LLKHF_EXTENDED
Definition: winuser.h:2599
USHORT * pusVSCtoVK
Definition: kbd.h:102
RECT rcWindow
Definition: ntuser.h:680
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:89
VOID FASTCALL SetLastNtError(NTSTATUS Status)
Definition: error.c:36
#define KEY_E1
Definition: ntddkbd.h:73
__kernel_entry W32KAPI HDC APIENTRY NtGdiCreateCompatibleDC(_In_opt_ HDC hdc)
unsigned char BYTE
Definition: ntddk_ex.h:96
Status
Definition: gdiplustypes.h:24
VOID NTAPI UserInitKeyboard(HANDLE hKeyboardDevice)
Definition: keyboard.c:161
#define VK_RIGHT
Definition: winuser.h:2180
#define VK_NUMPAD7
Definition: winuser.h:2200
DWORD APIENTRY NtUserVkKeyScanEx(WCHAR wch, HKL dwhkl, BOOL bUsehKL)
Definition: keyboard.c:1532
static UINT IntMapVirtualKeyEx(UINT uCode, UINT Type, PKBDTABLES pKbdTbl)
Definition: keyboard.c:1235
#define MAPVK_VK_TO_CHAR
Definition: winuser.h:2311
static WORD IntSimplifyVk(WORD wVk)
Definition: keyboard.c:219
BOOL NTAPI UserEmptyClipboard(VOID)
Definition: clipboard.c:662
_In_ DWORD _Out_ _In_ WORD wFlags
Definition: wincon.h:519
#define ERR(fmt,...)
Definition: debug.h:109
#define KBDEXT
Definition: kbd.h:8
Definition: ntuser.h:657
struct _USER_MESSAGE_QUEUE * MessageQueue
Definition: win32.h:88
VOID FASTCALL UserLeave(VOID)
Definition: ntuser.c:251
#define WCH_LGTR
Definition: kbd.h:115
HWND FASTCALL IntGetDesktopWindow(VOID)
Definition: desktop.c:1321
ULONG_PTR SIZE_T
Definition: typedefs.h:78
#define SC_KEY_UP
Definition: input.h:57
#define KBDALT
Definition: kbd.h:16
DWORD *typedef HANDLE
Definition: winlogon.h:61
_SEH2_END
Definition: create.c:4424
WORD wScan
Definition: winable.h:48
USHORT NumberOfFunctionKeys
Definition: ntddkbd.h:126
#define VK_SCROLL
Definition: winuser.h:2234
#define VK_NUMLOCK
Definition: winuser.h:2233
DWORD dwBoth
Definition: kbd.h:57
static DWORD
Definition: keyboard.c:34
#define WM_SYSDEADCHAR
Definition: winuser.h:1698
#define LLKHF_ALTDOWN
Definition: winuser.h:2601
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:1696
_In_ HBITMAP hbm
Definition: ntgdi.h:2776
static WORD IntFixVk(WORD wVk, BOOL bExt)
Definition: keyboard.c:247
BOOL fIncSerialNumber
Definition: ntuser.h:1118
BOOL NTAPI ProcessKeyEvent(WORD wVk, WORD wScanCode, DWORD dwFlags, BOOL bInjected, DWORD dwTime, DWORD dwExtraInfo)
Definition: keyboard.c:787
#define KEYBOARD_SCROLL_LOCK_ON
Definition: ntddkbd.h:83
PKL W32kGetDefaultKeyLayout(VOID)
Definition: kbdlayout.c:343
#define VK_CAPITAL
Definition: winuser.h:2160
DBG_DEFAULT_CHANNEL(UserKbd)
UINT WPARAM LPARAM lParam
Definition: precomp.h:45
#define VK_NUMPAD2
Definition: winuser.h:2195
unsigned int UINT
Definition: ndis.h:50
PMODIFIERS pCharModifiers
Definition: kbd.h:96
ULONG ExtraInformation
Definition: ntddkbd.h:90
INT FASTCALL UserReleaseDC(PWND Window, HDC hDc, BOOL EndPaint)
Definition: windc.c:917
static WCHAR FASTCALL IntVkToChar(WORD wVk, PKBDTABLES pKbdTbl)
Definition: keyboard.c:592
#define WCH_DEAD
Definition: kbd.h:114
#define KEYEVENTF_EXTENDEDKEY
Definition: winuser.h:1091
HWND hwnd
Definition: winuser.h:3067
#define KF_ALTDOWN
Definition: winuser.h:2403
#define VK_CONTROL
Definition: winuser.h:2157
DWORD FASTCALL UserGetKeyboardType(DWORD dwTypeFlag)
Definition: keyboard.c:1507
_Out_opt_ int * cx
Definition: commctrl.h:570
PKBDFILE spkf
Definition: input.h:33
#define KS_DOWN_BIT
Definition: input.h:54
#define WM_SYSKEYDOWN
Definition: winuser.h:1695
#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 STATUS_NOT_SUPPORTED
Definition: ntstatus.h:409
#define HIWORD(l)
Definition: typedefs.h:246
NTSTATUS APIENTRY IntKeyboardGetIndicatorTrans(HANDLE hKeyboardDevice, PKEYBOARD_INDICATOR_TRANSLATION *ppIndicatorTrans)
Definition: keyboard.c:50
LONG bottom
Definition: windef.h:299
#define RtlZeroMemory(Destination, Length)
Definition: typedefs.h:261
KEYBOARD_ATTRIBUTES gKeyboardInfo
Definition: keyboard.c:17
#define IS_KEY_DOWN(ks, vk)
Definition: input.h:98
char * cleanup(char *str)
Definition: wpickclick.c:99
ULONG_PTR dwExtraInfo
Definition: winable.h:51
#define _SEH2_EXCEPT(...)
Definition: pseh2_64.h:6
#define VK_CLEAR
Definition: winuser.h:2154
#define ExFreePoolWithTag(_P, _T)
Definition: module.h:1099
#define _SEH2_GetExceptionCode()
Definition: pseh2_64.h:12
#define IOCTL_KEYBOARD_SET_INDICATORS
Definition: ntddkbd.h:47
LONG_PTR LRESULT
Definition: windef.h:209
#define VK_LCONTROL
Definition: winuser.h:2238
#define VK_NUMPAD1
Definition: winuser.h:2194
#define QS_KEY
Definition: winuser.h:883
ULONG_PTR dwExtraInfo
Definition: winuser.h:3754
UINT message
Definition: winuser.h:3068
#define UINT
Definition: msvc.h:27
return STATUS_SUCCESS
Definition: btrfs.c:2710
#define SET_KEY_LOCKED(ks, vk, down)
Definition: input.h:103
#define QF_MOUSEMOVED
Definition: msgqueue.h:99
WCHAR * LPWSTR
Definition: xmlstorage.h:184
#define LP_DO_NOT_CARE_BIT
Definition: input.h:59
#define UL
Definition: tui.h:70
PVSC_VK pVSCtoVK_E1
Definition: kbd.h:105
BYTE * PBYTE
Definition: pedump.c:66
#define VK_SNAPSHOT
Definition: winuser.h:2185
#define LOWORD(l)
Definition: pedump.c:82
WORD wVk
Definition: winable.h:47
#define VK_END
Definition: winuser.h:2176
size_t __cdecl wcslen(_In_z_ const wchar_t *_Str)
#define SRCCOPY
Definition: wingdi.h:331
HANDLE NTAPI UserSetClipboardData(UINT fmt, HANDLE hData, PSETCLIPBDATA scd)
Definition: clipboard.c:995
ENGAPI VOID APIENTRY EngSetLastError(_In_ ULONG iError)
Definition: error.c:27
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:1321
KeyboardLayout
Definition: utils.h:36
PKL NTAPI UserHklToKbl(HKL hKl)
Definition: kbdlayout.c:370
static VOID SnapWindow(HWND hWnd)
Definition: keyboard.c:710
#define INIT_FUNCTION
Definition: ntoskrnl.h:11
#define SCANCODE_CTRL
Definition: kbd.h:130
DWORD dwSize
Definition: wglext.h:734