ReactOS  0.4.15-dev-5496-g599ba9c
kbdlayout.c
Go to the documentation of this file.
1 /*
2  * PROJECT: ReactOS Win32k subsystem
3  * LICENSE: GPL - See COPYING in the top level directory
4  * FILE: win32ss/user/ntuser/kbdlayout.c
5  * PURPOSE: Keyboard layout management
6  * COPYRIGHT: Copyright 2007 Saveliy Tretiakov
7  * Copyright 2008 Colin Finck
8  * Copyright 2011 Rafal Harabien
9  * Copyright 2022 Katayama Hirofumi MZ <katayama.hirofumi.mz@gmail.com>
10  */
11 
12 #include <win32k.h>
13 #include <ddk/immdev.h>
14 
15 // Was included only because of CP_ACP and required the
16 // definition of SYSTEMTIME in ndk\rtltypes.h
17 //#include <winnls.h>
18 #define CP_ACP 0
19 
20 DBG_DEFAULT_CHANNEL(UserKbdLayout);
21 
22 PKL gspklBaseLayout = NULL; /* FIXME: Please move this to pWinSta->spklList */
27 
29 
30 /* PRIVATE FUNCTIONS ******************************************************/
31 
32 /*
33  * Retrieves a PKL by an input locale identifier (HKL).
34  * @implemented
35  * Win: HKLtoPKL
36  */
38 {
39  PKL pFirstKL, pKL;
40 
41  pFirstKL = pti->KeyboardLayout;
42  if (!pFirstKL)
43  return NULL;
44 
45  pKL = pFirstKL;
46 
47  /* hKL can have special value HKL_NEXT or HKL_PREV */
48  if (hKL == (HKL)(ULONG_PTR)HKL_NEXT) /* Looking forward */
49  {
50  do
51  {
52  pKL = pKL->pklNext;
53  if (!(pKL->dwKL_Flags & KLF_UNLOAD))
54  return pKL;
55  } while (pKL != pFirstKL);
56  }
57  else if (hKL == (HKL)(ULONG_PTR)HKL_PREV) /* Looking backward */
58  {
59  do
60  {
61  pKL = pKL->pklPrev;
62  if (!(pKL->dwKL_Flags & KLF_UNLOAD))
63  return pKL;
64  } while (pKL != pFirstKL);
65  }
66  else if (HIWORD(hKL)) /* hKL is a full input locale identifier */
67  {
68  /* No KLF_UNLOAD check */
69  do
70  {
71  if (pKL->hkl == hKL)
72  return pKL;
73 
74  pKL = pKL->pklNext;
75  } while (pKL != pFirstKL);
76  }
77  else /* Language only specified */
78  {
79  /* No KLF_UNLOAD check */
80  do
81  {
82  if (LOWORD(pKL->hkl) == LOWORD(hKL)) /* Low word is language ID */
83  return pKL;
84 
85  pKL = pKL->pklNext;
86  } while (pKL != pFirstKL);
87  }
88 
89  return NULL;
90 }
91 
92 /*
93  * A helper function for NtUserGetKeyboardLayoutList.
94  * @implemented
95  * Win: _GetKeyboardLayoutList
96  */
97 static UINT APIENTRY
100  _In_ ULONG nBuff,
101  _Out_ HKL *pHklBuff)
102 {
103  UINT ret = 0;
104  PKL pKL, pFirstKL;
105 
106  pFirstKL = gspklBaseLayout; /* FIXME: Use pWinSta->spklList instead */
107  if (!pWinSta || !pFirstKL)
108  return 0;
109 
110  pKL = pFirstKL;
111 
112  if (nBuff == 0)
113  {
114  /* Count the effective PKLs */
115  do
116  {
117  if (!(pKL->dwKL_Flags & KLF_UNLOAD))
118  ++ret;
119  pKL = pKL->pklNext;
120  } while (pKL != pFirstKL);
121  }
122  else
123  {
124  /* Copy the effective HKLs to pHklBuff */
125  do
126  {
127  if (!(pKL->dwKL_Flags & KLF_UNLOAD))
128  {
129  *pHklBuff = pKL->hkl;
130  ++pHklBuff;
131  ++ret;
132  --nBuff;
133 
134  if (nBuff == 0)
135  break;
136  }
137  pKL = pKL->pklNext;
138  } while (pKL != pFirstKL);
139  }
140 
141  return ret;
142 }
143 
144 #if 0 && DBG
145 
146 static VOID
147 DumpKbdLayout(
148  IN PKBDTABLES pKbdTbl)
149 {
150  PVK_TO_BIT pVkToBit;
151  PVK_TO_WCHAR_TABLE pVkToWchTbl;
152  PVSC_VK pVscVk;
153  ULONG i;
154 
155  DbgPrint("Kbd layout: fLocaleFlags %x bMaxVSCtoVK %x\n",
156  pKbdTbl->fLocaleFlags, pKbdTbl->bMaxVSCtoVK);
157  DbgPrint("wMaxModBits %x\n",
158  pKbdTbl->pCharModifiers ? pKbdTbl->pCharModifiers->wMaxModBits
159  : 0);
160 
161  if (pKbdTbl->pCharModifiers)
162  {
163  pVkToBit = pKbdTbl->pCharModifiers->pVkToBit;
164  if (pVkToBit)
165  {
166  for (; pVkToBit->Vk; ++pVkToBit)
167  {
168  DbgPrint("VkToBit %x -> %x\n", pVkToBit->Vk, pVkToBit->ModBits);
169  }
170  }
171 
172  for (i = 0; i <= pKbdTbl->pCharModifiers->wMaxModBits; ++i)
173  {
174  DbgPrint("ModNumber %x -> %x\n", i, pKbdTbl->pCharModifiers->ModNumber[i]);
175  }
176  }
177 
178  pVkToWchTbl = pKbdTbl->pVkToWcharTable;
179  if (pVkToWchTbl)
180  {
181  for (; pVkToWchTbl->pVkToWchars; ++pVkToWchTbl)
182  {
183  PVK_TO_WCHARS1 pVkToWch = pVkToWchTbl->pVkToWchars;
184 
185  DbgPrint("pVkToWchTbl nModifications %x cbSize %x\n",
186  pVkToWchTbl->nModifications, pVkToWchTbl->cbSize);
187  if (pVkToWch)
188  {
189  while (pVkToWch->VirtualKey)
190  {
191  DbgPrint("pVkToWch VirtualKey %x Attributes %x wc { ",
192  pVkToWch->VirtualKey, pVkToWch->Attributes);
193  for (i = 0; i < pVkToWchTbl->nModifications; ++i)
194  {
195  DbgPrint("%x ", pVkToWch->wch[i]);
196  }
197  DbgPrint("}\n");
198  pVkToWch = (PVK_TO_WCHARS1)(((PBYTE)pVkToWch) + pVkToWchTbl->cbSize);
199  }
200  }
201  }
202  }
203 
204 // TODO: DeadKeys, KeyNames, KeyNamesExt, KeyNamesDead
205 
206  DbgPrint("pusVSCtoVK: { ");
207  if (pKbdTbl->pusVSCtoVK)
208  {
209  for (i = 0; i < pKbdTbl->bMaxVSCtoVK; ++i)
210  {
211  DbgPrint("%x -> %x, ", i, pKbdTbl->pusVSCtoVK[i]);
212  }
213  }
214  DbgPrint("}\n");
215 
216  DbgPrint("pVSCtoVK_E0: { ");
217  pVscVk = pKbdTbl->pVSCtoVK_E0;
218  if (pVscVk)
219  {
220  for (; pVscVk->Vsc; ++pVscVk)
221  {
222  DbgPrint("%x -> %x, ", pVscVk->Vsc, pVscVk->Vk);
223  }
224  }
225  DbgPrint("}\n");
226 
227  DbgPrint("pVSCtoVK_E1: { ");
228  pVscVk = pKbdTbl->pVSCtoVK_E1;
229  if (pVscVk)
230  {
231  for (; pVscVk->Vsc; ++pVscVk)
232  {
233  DbgPrint("%x -> %x, ", pVscVk->Vsc, pVscVk->Vk);
234  }
235  }
236  DbgPrint("}\n");
237 
238 // TODO: Ligatures
239 }
240 
241 #endif // DBG
242 
243 
244 /*
245  * UserLoadKbdDll
246  *
247  * Loads keyboard layout DLL and gets address to KbdTables
248  */
249 static BOOL
250 UserLoadKbdDll(WCHAR *pwszLayoutPath,
251  HANDLE *phModule,
252  PKBDTABLES *pKbdTables)
253 {
254  PFN_KBDLAYERDESCRIPTOR pfnKbdLayerDescriptor;
255 
256  /* Load keyboard layout DLL */
257  TRACE("Loading Keyboard DLL %ws\n", pwszLayoutPath);
258  *phModule = EngLoadImage(pwszLayoutPath);
259  if (!(*phModule))
260  {
261  ERR("Failed to load dll %ws\n", pwszLayoutPath);
262  return FALSE;
263  }
264 
265  /* Find KbdLayerDescriptor function and get layout tables */
266  TRACE("Loaded %ws\n", pwszLayoutPath);
267  pfnKbdLayerDescriptor = EngFindImageProcAddress(*phModule, "KbdLayerDescriptor");
268 
269  /* FIXME: Windows reads file instead of executing!
270  It's not safe to kbdlayout DLL in kernel mode! */
271 
272  if (pfnKbdLayerDescriptor)
273  *pKbdTables = pfnKbdLayerDescriptor();
274  else
275  ERR("Error: %ws has no KbdLayerDescriptor()\n", pwszLayoutPath);
276 
277  if (!pfnKbdLayerDescriptor || !*pKbdTables)
278  {
279  ERR("Failed to load the keyboard layout.\n");
280  EngUnloadImage(*phModule);
281  return FALSE;
282  }
283 
284 #if 0 && DBG
285  /* Dump keyboard layout */
286  DumpKbdLayout(*pKbdTables);
287 #endif
288 
289  return TRUE;
290 }
291 
292 /*
293  * UserLoadKbdFile
294  *
295  * Loads keyboard layout DLL and creates KBDFILE object
296  */
297 static PKBDFILE
299 {
300  PKBDFILE pkf, pRet = NULL;
302  ULONG cbSize;
303  HKEY hKey = NULL;
304  WCHAR wszLayoutPath[MAX_PATH] = L"\\SystemRoot\\System32\\";
305  WCHAR wszLayoutRegKey[256] = L"\\REGISTRY\\Machine\\SYSTEM\\CurrentControlSet\\"
306  L"Control\\Keyboard Layouts\\";
307 
308  /* Create keyboard layout file object */
310  if (!pkf)
311  {
312  ERR("Failed to create object!\n");
313  return NULL;
314  }
315 
316  /* Set keyboard layout name */
317  swprintf(pkf->awchKF, L"%wZ", pwszKLID);
318 
319  /* Open layout registry key */
320  RtlStringCbCatW(wszLayoutRegKey, sizeof(wszLayoutRegKey), pkf->awchKF);
321  Status = RegOpenKey(wszLayoutRegKey, &hKey);
322  if (!NT_SUCCESS(Status))
323  {
324  ERR("Failed to open keyboard layouts registry key %ws (%lx)\n", wszLayoutRegKey, Status);
325  goto cleanup;
326  }
327 
328  /* Read filename of layout DLL */
329  cbSize = (ULONG)(sizeof(wszLayoutPath) - wcslen(wszLayoutPath)*sizeof(WCHAR));
331  L"Layout File",
332  REG_SZ,
333  wszLayoutPath + wcslen(wszLayoutPath),
334  &cbSize);
335 
336  if (!NT_SUCCESS(Status))
337  {
338  ERR("Can't get layout filename for %wZ (%lx)\n", pwszKLID, Status);
339  goto cleanup;
340  }
341 
342  /* Load keyboard file now */
343  if (!UserLoadKbdDll(wszLayoutPath, &pkf->hBase, &pkf->pKbdTbl))
344  {
345  ERR("Failed to load %ws dll!\n", wszLayoutPath);
346  goto cleanup;
347  }
348 
349  /* Update next field */
350  pkf->pkfNext = gpkfList;
351  gpkfList = pkf;
352 
353  /* Return keyboard file */
354  pRet = pkf;
355 
356 cleanup:
357  if (hKey)
358  ZwClose(hKey);
359  if (pkf)
360  UserDereferenceObject(pkf); // we dont need ptr anymore
361  if (!pRet)
362  {
363  /* We have failed - destroy created object */
364  if (pkf)
366  }
367 
368  return pRet;
369 }
370 
371 /*
372  * UserLoadKbdLayout
373  *
374  * Loads keyboard layout and creates KL object
375  */
376 static PKL
378 {
379  LCID lCid;
380  CHARSETINFO cs;
381  PKL pKl;
382 
383  /* Create keyboard layout object */
385  if (!pKl)
386  {
387  ERR("Failed to create object!\n");
388  return NULL;
389  }
390 
391  pKl->hkl = hKL;
392  pKl->spkf = UserLoadKbdFile(pustrKLID);
393 
394  /* Dereference keyboard layout */
396 
397  /* If we failed, remove KL object */
398  if (!pKl->spkf)
399  {
400  ERR("UserLoadKbdFile(%wZ) failed!\n", pustrKLID);
402  return NULL;
403  }
404 
405  // Up to Language Identifiers..
406  if (!NT_SUCCESS(RtlUnicodeStringToInteger(pustrKLID, 16, (PULONG)&lCid)))
407  {
408  ERR("RtlUnicodeStringToInteger failed for '%wZ'\n", pustrKLID);
410  return NULL;
411  }
412 
413  TRACE("Language Identifiers %wZ LCID 0x%x\n", pustrKLID, lCid);
414  if (co_IntGetCharsetInfo(lCid, &cs))
415  {
416  pKl->iBaseCharset = cs.ciCharset;
417  pKl->dwFontSigs = cs.fs.fsCsb[0];
418  pKl->CodePage = (USHORT)cs.ciACP;
419  TRACE("Charset %u Font Sig %lu CodePage %u\n",
420  pKl->iBaseCharset, pKl->dwFontSigs, pKl->CodePage);
421  }
422  else
423  {
424  pKl->iBaseCharset = ANSI_CHARSET;
425  pKl->dwFontSigs = FS_LATIN1;
426  pKl->CodePage = CP_ACP;
427  }
428 
429  // Set initial system character set and font signature.
430  if (gSystemFS == 0)
431  {
433  gSystemFS = pKl->dwFontSigs;
434  }
435 
436  return pKl;
437 }
438 
439 /*
440  * UnloadKbdFile
441  *
442  * Destroys specified Keyboard File object
443  */
444 static
445 VOID
447 {
448  PKBDFILE *ppkfLink = &gpkfList;
449  NT_ASSERT(pkf != NULL);
450 
451  /* Find previous object */
452  while (*ppkfLink)
453  {
454  if (*ppkfLink == pkf)
455  break;
456 
457  ppkfLink = &(*ppkfLink)->pkfNext;
458  }
459 
460  if (*ppkfLink == pkf)
461  *ppkfLink = pkf->pkfNext;
462 
463  EngUnloadImage(pkf->hBase);
464  UserDeleteObject(pkf->head.h, TYPE_KBDFILE);
465 }
466 
467 /*
468  * UserUnloadKbl
469  *
470  * Unloads specified Keyboard Layout if possible
471  */
472 BOOL
474 {
475  /* According to msdn, UnloadKeyboardLayout can fail
476  if the keyboard layout identifier was preloaded. */
477  if (pKl == gspklBaseLayout)
478  {
479  if (pKl->pklNext == pKl->pklPrev)
480  {
481  /* There is only one layout */
482  return FALSE;
483  }
484 
485  /* Set next layout as default */
486  gspklBaseLayout = pKl->pklNext;
487  }
488 
489  if (pKl->head.cLockObj > 1)
490  {
491  /* Layout is used by other threads */
492  pKl->dwKL_Flags |= KLF_UNLOAD;
493  return FALSE;
494  }
495 
496  /* Unload the layout */
497  pKl->pklPrev->pklNext = pKl->pklNext;
498  pKl->pklNext->pklPrev = pKl->pklPrev;
499  UnloadKbdFile(pKl->spkf);
500  if (pKl->piiex)
501  {
503  }
505  return TRUE;
506 }
507 
508 /*
509  * W32kGetDefaultKeyLayout
510  *
511  * Returns default layout for new threads
512  */
513 PKL
515 {
516  PKL pKl = gspklBaseLayout;
517 
518  if (!pKl)
519  return NULL;
520 
521  /* Return not unloaded layout */
522  do
523  {
524  if (!(pKl->dwKL_Flags & KLF_UNLOAD))
525  return pKl;
526 
527  pKl = pKl->pklPrev; /* Confirmed on Win2k */
528  } while(pKl != gspklBaseLayout);
529 
530  /* We have not found proper KL */
531  return NULL;
532 }
533 
534 /*
535  * UserHklToKbl
536  *
537  * Gets KL object from hkl value
538  */
539 PKL
540 NTAPI
542 {
543  PKL pKl = gspklBaseLayout;
544 
545  if (!gspklBaseLayout)
546  return NULL;
547 
548  do
549  {
550  if (pKl->hkl == hKl)
551  return pKl;
552 
553  pKl = pKl->pklNext;
554  } while (pKl != gspklBaseLayout);
555 
556  return NULL;
557 }
558 
559 // Win: ReorderKeyboardLayouts
562  _Inout_ PWINSTATION_OBJECT pWinSta,
563  _Inout_ PKL pNewKL)
564 {
565  PKL pOldKL = gspklBaseLayout;
566 
567  if ((pWinSta->Flags & WSS_NOIO) || pNewKL == pOldKL)
568  return;
569 
570  pNewKL->pklPrev->pklNext = pNewKL->pklNext;
571  pNewKL->pklNext->pklPrev = pNewKL->pklPrev;
572  pNewKL->pklNext = pOldKL;
573  pNewKL->pklPrev = pOldKL->pklPrev;
574  pOldKL->pklPrev->pklNext = pNewKL;
575  pOldKL->pklPrev = pNewKL;
576  gspklBaseLayout = pNewKL; /* Should we use UserAssignmentLock? */
577 }
578 
579 /*
580  * UserSetDefaultInputLang
581  *
582  * Sets default kyboard layout for system. Called from UserSystemParametersInfo.
583  */
584 BOOL
585 NTAPI
587 {
588  PKL pKl;
589 
590  pKl = UserHklToKbl(hKl);
591  if (!pKl)
592  return FALSE;
593 
595  return TRUE;
596 }
597 
598 /*
599  * co_UserActivateKbl
600  *
601  * Activates given layout in specified thread
602  */
603 static PKL
605 {
606  PKL pklPrev;
607  PWND pWnd;
608 
609  pklPrev = pti->KeyboardLayout;
610 
611  UserAssignmentLock((PVOID*)&(pti->KeyboardLayout), pKl);
612  pti->pClientInfo->hKL = pKl->hkl;
613 
614  if (Flags & KLF_SETFORPROCESS)
615  {
616  FIXME("KLF_SETFORPROCESS\n");
617  }
618 
619  if (!(pWnd = pti->MessageQueue->spwndFocus))
620  {
621  pWnd = pti->MessageQueue->spwndActive;
622  }
623 
624  // Send WM_INPUTLANGCHANGE to thread's focus window
625  co_IntSendMessage( pWnd ? UserHMGetHandle(pWnd) : 0,
626  WM_INPUTLANGCHANGE,
627  (WPARAM)pKl->iBaseCharset, // FIXME: How to set it?
628  (LPARAM)pKl->hkl); // hkl
629 
630  return pklPrev;
631 }
632 
633 // Win: xxxImmActivateLayout
636  _Inout_ PTHREADINFO pti,
637  _Inout_ PKL pKL)
638 {
639  PWND pImeWnd;
640  HWND hImeWnd;
642 
643  if (pti->KeyboardLayout == pKL)
644  return;
645 
646  pImeWnd = pti->spwndDefaultIme;
647  if (pImeWnd)
648  {
649  UserRefObjectCo(pImeWnd, &Ref);
650  hImeWnd = UserHMGetHandle(pImeWnd);
652  UserDerefObjectCo(pImeWnd);
653  }
654 
655  UserAssignmentLock((PVOID*)&(pti->KeyboardLayout), pKL);
656  pti->pClientInfo->hKL = pKL->hkl;
657 }
658 
659 /* Win: xxxInternalActivateKeyboardLayout */
662  _Inout_ PKL pKL,
663  _In_ ULONG uFlags,
664  _Inout_ PWND pWnd)
665 {
666  HKL hOldKL = NULL;
667  PKL pOldKL = NULL;
669  PWND pTargetWnd, pImeWnd;
670  HWND hTargetWnd, hImeWnd;
671  USER_REFERENCE_ENTRY Ref1, Ref2;
673 
674  if (pti->KeyboardLayout)
675  {
676  pOldKL = pti->KeyboardLayout;
677  if (pOldKL)
678  hOldKL = pOldKL->hkl;
679  }
680 
681  if (uFlags & KLF_RESET)
682  {
683  FIXME("KLF_RESET\n");
684  }
685 
686  if (!(uFlags & KLF_SETFORPROCESS) && pKL == pti->KeyboardLayout)
687  return hOldKL;
688 
689  pKL->wchDiacritic = 0;
690 
691  if (pOldKL)
692  UserRefObjectCo(pOldKL, &Ref1);
693 
694  if (pti->TIF_flags & TIF_CSRSSTHREAD)
695  {
697  ClientInfo->CodePage = pKL->CodePage;
698  ClientInfo->hKL = pKL->hkl;
699  }
700  else if (uFlags & KLF_SETFORPROCESS)
701  {
702  FIXME("KLF_SETFORPROCESS\n");
703  }
704  else
705  {
706  if (IS_IMM_MODE())
707  IntImmActivateLayout(pti, pKL);
708  else
710 
711  ClientInfo->CodePage = pKL->CodePage;
712  ClientInfo->hKL = pKL->hkl;
713  }
714 
715  if (gptiForeground && (gptiForeground->ppi == pti->ppi))
716  {
717  /* Send shell message */
718  co_IntShellHookNotify(HSHELL_LANGUAGE, 0, (LPARAM)pKL->hkl);
719  }
720 
721  if (pti->MessageQueue)
722  {
723  /* Determine the target window */
724  pTargetWnd = pti->MessageQueue->spwndFocus;
725  if (!pTargetWnd)
726  {
727  pTargetWnd = pti->MessageQueue->spwndActive;
728  if (!pTargetWnd)
729  pTargetWnd = pWnd;
730  }
731 
732  /* Send WM_INPUTLANGCHANGE message */
733  if (pTargetWnd)
734  {
735  UserRefObjectCo(pTargetWnd, &Ref2);
736  hTargetWnd = UserHMGetHandle(pTargetWnd);
737  co_IntSendMessage(hTargetWnd, WM_INPUTLANGCHANGE, pKL->iBaseCharset, (LPARAM)pKL->hkl);
738  UserDerefObjectCo(pTargetWnd);
739  }
740  }
741 
742  /* Send WM_IME_SYSTEM:IMS_SENDNOTIFICATION message if necessary */
743  if (pti && !(pti->TIF_flags & TIF_CSRSSTHREAD))
744  {
745  if (IS_IME_HKL(pKL->hkl) || IS_CICERO_MODE())
746  {
747  pImeWnd = pti->spwndDefaultIme;
748  if (pImeWnd)
749  {
750  UserRefObjectCo(pImeWnd, &Ref2);
751  BOOL bProcess = !!(pti->TIF_flags & KLF_SETFORPROCESS);
752  hImeWnd = UserHMGetHandle(pImeWnd);
754  UserDerefObjectCo(pImeWnd);
755  }
756  }
757  }
758 
759  if (pOldKL)
760  UserDerefObjectCo(pOldKL);
761  return hOldKL;
762 }
763 
764 /* Win: xxxActivateKeyboardLayout */
767  _Inout_ PWINSTATION_OBJECT pWinSta,
768  _In_ HKL hKL,
769  _In_ ULONG uFlags,
770  _Inout_ PWND pWnd)
771 {
772  PKL pKL;
774 
775  pKL = IntHKLtoPKL(pti, hKL);
776  if (!pKL)
777  {
778  ERR("Invalid HKL %p!\n", hKL);
779  return NULL;
780  }
781 
782  if (uFlags & KLF_REORDER)
783  IntReorderKeyboardLayouts(pWinSta, pKL);
784 
785  return co_UserActivateKeyboardLayout(pKL, uFlags, pWnd);
786 }
787 
788 // Win: xxxInternalUnloadKeyboardLayout
789 static BOOL APIENTRY
791  _Inout_ PWINSTATION_OBJECT pWinSta,
792  _Inout_ PKL pKL,
794 {
795  PKL pNextKL;
796  USER_REFERENCE_ENTRY Ref1, Ref2;
797  PTHREADINFO pti = gptiCurrent;
798 
799  if (pKL == gspklBaseLayout && !(dwFlags & 0x80000000))
800  return FALSE;
801 
802  UserRefObjectCo(pKL, &Ref1); /* Add reference */
803 
804  /* Regard as unloaded */
806  pKL->dwKL_Flags |= KLF_UNLOAD;
807 
808  if (!(dwFlags & 0x80000000) && pti->KeyboardLayout == pKL)
809  {
810  pNextKL = IntHKLtoPKL(pti, (HKL)(ULONG_PTR)HKL_NEXT);
811  if (pNextKL)
812  {
813  UserRefObjectCo(pNextKL, &Ref2); /* Add reference */
815  UserDerefObjectCo(pNextKL); /* Release reference */
816  }
817  }
818 
819  if (gspklBaseLayout == pKL && pKL != pKL->pklNext)
820  {
821  /* Set next layout as default (FIXME: Use UserAssignmentLock?) */
822  gspklBaseLayout = pKL->pklNext;
823  }
824 
825  UserDerefObjectCo(pKL); /* Release reference */
826 
827  if (pti->pDeskInfo->fsHooks)
828  {
829  co_IntShellHookNotify(HSHELL_LANGUAGE, 0, 0);
830  gLCIDSentToShell = 0;
831  }
832 
833  return TRUE;
834 }
835 
836 // Win: xxxUnloadKeyboardLayout
837 static BOOL APIENTRY
839 {
840  PKL pKL = IntHKLtoPKL(gptiCurrent, hKL);
841  if (!pKL)
842  {
843  ERR("Invalid HKL %p!\n", hKL);
844  return FALSE;
845  }
846  return co_IntUnloadKeyboardLayoutEx(pWinSta, pKL, 0);
847 }
848 
849 /* EXPORTS *******************************************************************/
850 
851 /*
852  * UserGetKeyboardLayout
853  *
854  * Returns hkl of given thread keyboard layout
855  */
859 {
860  PTHREADINFO pti;
861  PLIST_ENTRY ListEntry;
862  PKL pKl;
863 
865 
866  if (!dwThreadId)
867  {
868  pKl = pti->KeyboardLayout;
869  return pKl ? pKl->hkl : NULL;
870  }
871 
872  ListEntry = pti->rpdesk->PtiList.Flink;
873 
874  //
875  // Search the Desktop Thread list for related Desktop active Threads.
876  //
877  while(ListEntry != &pti->rpdesk->PtiList)
878  {
879  pti = CONTAINING_RECORD(ListEntry, THREADINFO, PtiLink);
880 
881  if (PsGetThreadId(pti->pEThread) == UlongToHandle(dwThreadId))
882  {
883  pKl = pti->KeyboardLayout;
884  return pKl ? pKl->hkl : NULL;
885  }
886 
887  ListEntry = ListEntry->Flink;
888  }
889 
890  return NULL;
891 }
892 
893 /*
894  * NtUserGetKeyboardLayoutList
895  *
896  * Returns list of loaded keyboard layouts in system
897  */
898 UINT
899 APIENTRY
901  ULONG nBuff,
902  HKL *pHklBuff)
903 {
904  UINT ret = 0;
905  PWINSTATION_OBJECT pWinSta;
906 
907  if (!pHklBuff)
908  nBuff = 0;
909 
910  UserEnterShared();
911 
912  if (nBuff > MAXULONG / sizeof(HKL))
913  {
915  goto Quit;
916  }
917 
918  _SEH2_TRY
919  {
920  ProbeForWrite(pHklBuff, nBuff * sizeof(HKL), 1);
921  }
923  {
925  goto Quit;
926  }
927  _SEH2_END;
928 
929  pWinSta = IntGetProcessWindowStation(NULL);
930 
931  _SEH2_TRY
932  {
933  ret = IntGetKeyboardLayoutList(pWinSta, nBuff, pHklBuff);
934  }
936  {
938  goto Quit;
939  }
940  _SEH2_END;
941 
942 Quit:
943  UserLeave();
944  return ret;
945 }
946 
947 /*
948  * NtUserGetKeyboardLayoutName
949  *
950  * Returns KLID of current thread keyboard layout
951  */
952 BOOL
953 APIENTRY
955  _Inout_ PUNICODE_STRING pustrName)
956 {
957  BOOL bRet = FALSE;
958  PKL pKl;
959  PTHREADINFO pti;
960  UNICODE_STRING ustrNameSafe;
962 
963  UserEnterShared();
964 
966  pKl = pti->KeyboardLayout;
967 
968  if (!pKl)
969  goto cleanup;
970 
971  _SEH2_TRY
972  {
973  ProbeForWriteUnicodeString(pustrName);
974  ustrNameSafe = *pustrName;
975 
976  ProbeForWrite(ustrNameSafe.Buffer, ustrNameSafe.MaximumLength, 1);
977 
978  if (IS_IME_HKL(pKl->hkl))
979  {
980  Status = RtlIntegerToUnicodeString((ULONG)(ULONG_PTR)pKl->hkl, 16, &ustrNameSafe);
981  }
982  else
983  {
984  if (ustrNameSafe.MaximumLength < KL_NAMELENGTH * sizeof(WCHAR))
985  {
987  goto cleanup;
988  }
989 
990  /* FIXME: Do not use awchKF */
991  ustrNameSafe.Length = 0;
992  Status = RtlAppendUnicodeToString(&ustrNameSafe, pKl->spkf->awchKF);
993  }
994 
995  if (NT_SUCCESS(Status))
996  {
997  *pustrName = ustrNameSafe;
998  bRet = TRUE;
999  }
1000  }
1002  {
1004  }
1005  _SEH2_END;
1006 
1007 cleanup:
1008  UserLeave();
1009  return bRet;
1010 }
1011 
1012 /* Win: xxxImmLoadLayout */
1014 {
1015  PIMEINFOEX piiex;
1016 
1017  if (!IS_IME_HKL(hKL) && !IS_CICERO_MODE())
1018  return NULL;
1019 
1021  if (!piiex)
1022  return NULL;
1023 
1024  if (!co_ClientImmLoadLayout(hKL, piiex))
1025  {
1027  return NULL;
1028  }
1029 
1030  return piiex;
1031 }
1032 
1033 /*
1034  * NtUserLoadKeyboardLayoutEx
1035  *
1036  * Loads keyboard layout with given locale id
1037  *
1038  * NOTE: We adopt a different design from Microsoft's one for security reason.
1039  * We don't use the 1st and 3rd parameters of NtUserLoadKeyboardLayoutEx.
1040  */
1041 HKL
1042 APIENTRY
1044  IN HANDLE Handle, // hFile (See downloads.securityfocus.com/vulnerabilities/exploits/43774.c)
1045  IN DWORD offTable, // Offset to KbdTables
1046  IN PUNICODE_STRING puszKeyboardName, // Not used?
1047  IN HKL hklUnload,
1048  IN PUNICODE_STRING pustrKLID,
1049  IN DWORD hkl,
1050  IN UINT Flags)
1051 {
1052  HKL hklRet = NULL;
1053  PKL pKl = NULL, pklLast;
1055  UNICODE_STRING ustrSafeKLID;
1056 
1059  KLF_RESET|KLF_SHIFTLOCK))
1060  {
1061  ERR("Invalid flags: %x\n", Flags);
1063  return NULL;
1064  }
1065 
1066  /* FIXME: It seems KLF_RESET is only supported for WINLOGON */
1067 
1068  RtlInitEmptyUnicodeString(&ustrSafeKLID, Buffer, sizeof(Buffer));
1069  _SEH2_TRY
1070  {
1071  ProbeForRead(pustrKLID, sizeof(*pustrKLID), 1);
1072  ProbeForRead(pustrKLID->Buffer, sizeof(pustrKLID->Length), 1);
1073  RtlCopyUnicodeString(&ustrSafeKLID, pustrKLID);
1074  }
1076  {
1078  _SEH2_YIELD(return NULL);
1079  }
1080  _SEH2_END;
1081 
1083 
1084  /* If hklUnload is specified, unload it and load new layput as default */
1085  if (hklUnload && (hklUnload != UlongToHandle(hkl)))
1086  {
1087  pKl = UserHklToKbl(hklUnload);
1088  if (pKl)
1089  UserUnloadKbl(pKl);
1090  }
1091 
1092  /* Let's see if layout was already loaded. */
1093  pKl = UserHklToKbl(UlongToHandle(hkl));
1094  if (!pKl)
1095  {
1096  /* It wasn't, so load it. */
1097  pKl = UserLoadKbdLayout(&ustrSafeKLID, UlongToHandle(hkl));
1098  if (!pKl)
1099  goto cleanup;
1100 
1101  if (gspklBaseLayout)
1102  {
1103  /* Find last not unloaded layout */
1104  pklLast = gspklBaseLayout->pklPrev;
1105  while (pklLast != gspklBaseLayout && pklLast->dwKL_Flags & KLF_UNLOAD)
1106  pklLast = pklLast->pklPrev;
1107 
1108  /* Add new layout to the list */
1109  pKl->pklNext = pklLast->pklNext;
1110  pKl->pklPrev = pklLast;
1111  pKl->pklNext->pklPrev = pKl;
1112  pKl->pklPrev->pklNext = pKl;
1113  }
1114  else
1115  {
1116  /* This is the first layout */
1117  pKl->pklNext = pKl;
1118  pKl->pklPrev = pKl;
1119  gspklBaseLayout = pKl;
1120  }
1121 
1123  }
1124 
1125  /* If this layout was prepared to unload, undo it */
1126  pKl->dwKL_Flags &= ~KLF_UNLOAD;
1127 
1128  /* Activate this layout in current thread */
1129  if (Flags & KLF_ACTIVATE)
1131 
1132  /* Send shell message */
1133  if (!(Flags & KLF_NOTELLSHELL))
1134  co_IntShellHookNotify(HSHELL_LANGUAGE, 0, (LPARAM)hkl);
1135 
1136  /* Return hkl on success */
1137  hklRet = UlongToHandle(hkl);
1138 
1139  /* FIXME: KLF_REPLACELANG
1140  KLF_REORDER */
1141 
1142 cleanup:
1143  UserLeave();
1144  return hklRet;
1145 }
1146 
1147 /*
1148  * NtUserActivateKeyboardLayout
1149  *
1150  * Activates specified layout for thread or process
1151  */
1152 HKL
1153 NTAPI
1155  HKL hKL,
1156  ULONG Flags)
1157 {
1158  PWINSTATION_OBJECT pWinSta;
1159  HKL hOldKL;
1160 
1162 
1163  /* FIXME */
1164 
1165  pWinSta = IntGetProcessWindowStation(NULL);
1166  hOldKL = co_IntActivateKeyboardLayout(pWinSta, hKL, Flags, NULL);
1167  UserLeave();
1168 
1169  return hOldKL;
1170 }
1171 
1172 /*
1173  * NtUserUnloadKeyboardLayout
1174  *
1175  * Unloads keyboard layout with specified hkl value
1176  */
1177 BOOL
1178 APIENTRY
1180  HKL hKl)
1181 {
1182  BOOL ret;
1183  PWINSTATION_OBJECT pWinSta;
1184 
1186 
1187  pWinSta = IntGetProcessWindowStation(NULL);
1188  ret = IntUnloadKeyboardLayout(pWinSta, hKl);
1189 
1190  UserLeave();
1191  return ret;
1192 }
1193 
1194 /* EOF */
_SEH2_TRY
Definition: create.c:4226
#define KLF_REORDER
Definition: winuser.h:114
#define ERROR_INVALID_PARAMETER
Definition: compat.h:101
static BOOL UserLoadKbdDll(WCHAR *pwszLayoutPath, HANDLE *phModule, PKBDTABLES *pKbdTables)
Definition: kbdlayout.c:250
VOID FASTCALL UserEnterShared(VOID)
Definition: ntuser.c:238
struct tagKL * pklPrev
Definition: input.h:30
PVK_TO_WCHARS1 pVkToWchars
Definition: kbd.h:51
#define IN
Definition: typedefs.h:39
#define KLF_UNLOAD
Definition: input.h:51
DBG_DEFAULT_CHANNEL(UserKbdLayout)
BOOL FASTCALL UserDeleteObject(HANDLE h, HANDLE_TYPE type)
Definition: object.c:717
#define KL_NAMELENGTH
Definition: winuser.h:122
BYTE ModBits
Definition: kbd.h:23
#define _Inout_
Definition: ms_sal.h:378
#define DbgPrint
Definition: hal.h:12
BOOL UserUnloadKbl(PKL pKl)
Definition: kbdlayout.c:473
static BOOL APIENTRY co_IntUnloadKeyboardLayoutEx(_Inout_ PWINSTATION_OBJECT pWinSta, _Inout_ PKL pKL, _In_ DWORD dwFlags)
Definition: kbdlayout.c:790
USHORT MaximumLength
Definition: env_spec_w32.h:370
PVOID FASTCALL UserAssignmentLock(PVOID *ppvObj, PVOID pvNew)
Definition: object.c:840
#define _Out_
Definition: ms_sal.h:345
BOOL APIENTRY co_IntGetCharsetInfo(LCID Locale, PCHARSETINFO pCs)
Definition: callback.c:1040
PKL gspklBaseLayout
Definition: kbdlayout.c:22
#define KLF_ACTIVATE
Definition: winuser.h:111
#define TRUE
Definition: types.h:120
NTSYSAPI NTSTATUS NTAPI ZwClose(_In_ HANDLE Handle)
#define IS_IMM_MODE()
Definition: ntuser.h:1232
HANDLE h
Definition: ntuser.h:181
FLONG TIF_flags
Definition: win32.h:95
Definition: kbd.h:21
PVOID NTAPI PsGetCurrentThreadWin32Thread(VOID)
Definition: thread.c:805
LONG NTSTATUS
Definition: precomp.h:26
BYTE Vsc
Definition: kbd.h:72
static __inline VOID UserRefObjectCo(PVOID obj, PUSER_REFERENCE_ENTRY UserReferenceEntry)
Definition: object.h:27
#define KLF_NOTELLSHELL
Definition: winuser.h:116
PKBDFILE gpkfList
Definition: kbdlayout.c:23
BOOL FASTCALL UserDereferenceObject(PVOID Object)
Definition: object.c:644
PIMEINFOEX piiex
Definition: input.h:38
HKL APIENTRY NtUserLoadKeyboardLayoutEx(IN HANDLE Handle, IN DWORD offTable, IN PUNICODE_STRING puszKeyboardName, IN HKL hklUnload, IN PUNICODE_STRING pustrKLID, IN DWORD hkl, IN UINT Flags)
Definition: kbdlayout.c:1043
DWORD LCID
Definition: nls.h:13
UINT_PTR WPARAM
Definition: windef.h:207
_SEH2_END
Definition: create.c:4400
UINT uFlags
Definition: api.c:59
UINT gSystemCPCharSet
Definition: kbdlayout.c:25
NTSTRSAFEAPI RtlStringCbCatW(_Inout_updates_bytes_(cbDest) _Always_(_Post_z_) NTSTRSAFE_PWSTR pszDest, _In_ size_t cbDest, _In_ NTSTRSAFE_PCWSTR pszSrc)
Definition: ntstrsafe.h:636
#define FASTCALL
Definition: nt_native.h:50
VOID APIENTRY IntImmActivateLayout(_Inout_ PTHREADINFO pti, _Inout_ PKL pKL)
Definition: kbdlayout.c:635
struct _DESKTOP * rpdesk
Definition: win32.h:92
VOID NTAPI ProbeForWrite(IN PVOID Address, IN SIZE_T Length, IN ULONG Alignment)
Definition: exintrin.c:143
PVOID FASTCALL UserCreateObject(PUSER_HANDLE_TABLE ht, PDESKTOP pDesktop, PTHREADINFO pti, HANDLE *h, HANDLE_TYPE type, ULONG size)
Definition: object.c:568
NTSYSAPI VOID NTAPI RtlCopyUnicodeString(PUNICODE_STRING DestinationString, PUNICODE_STRING SourceString)
struct _THREADINFO * GetW32ThreadInfo(VOID)
Definition: misc.c:801
PPROCESSINFO ppi
Definition: win32.h:88
uint32_t ULONG_PTR
Definition: typedefs.h:65
USHORT Vk
Definition: kbd.h:73
CLIENT_DATA ClientInfo
VOID FASTCALL IntReorderKeyboardLayouts(_Inout_ PWINSTATION_OBJECT pWinSta, _Inout_ PKL pNewKL)
Definition: kbdlayout.c:561
PTHREADINFO gptiForeground
Definition: focus.c:15
uint32_t cs
Definition: isohybrid.c:75
#define L(x)
Definition: ntvdm.h:50
PKL FASTCALL IntHKLtoPKL(_Inout_ PTHREADINFO pti, _In_ HKL hKL)
Definition: kbdlayout.c:37
NTSTATUS(* NTAPI)(IN PFILE_FULL_EA_INFORMATION EaBuffer, IN ULONG EaLength, OUT PULONG ErrorOffset)
Definition: IoEaTest.cpp:117
#define FALSE
Definition: types.h:117
#define TIF_CSRSSTHREAD
Definition: ntuser.h:265
DWORD gSystemFS
Definition: kbdlayout.c:24
unsigned int BOOL
Definition: ntddk_ex.h:94
static __inline VOID UserDerefObjectCo(PVOID obj)
Definition: object.h:40
#define FIXME(fmt,...)
Definition: debug.h:111
HEAD head
Definition: input.h:28
#define WSS_NOIO
Definition: winsta.h:9
Definition: object.h:3
Definition: input.h:26
#define _In_
Definition: ms_sal.h:308
#define KLF_UNLOADPREVIOUS
Definition: winuser.h:113
LONG_PTR LPARAM
Definition: windef.h:208
struct _WND * spwndDefaultIme
Definition: win32.h:131
Definition: bufpool.h:45
WCHAR awchKF[20]
Definition: input.h:19
PTHREADINFO gptiCurrent
Definition: ntuser.c:15
PIMEINFOEX FASTCALL co_UserImmLoadLayout(_In_ HKL hKL)
Definition: kbdlayout.c:1013
BYTE nModifications
Definition: kbd.h:52
UINT iBaseCharset
Definition: input.h:35
void * PVOID
Definition: retypes.h:9
#define WM_IME_SYSTEM
Definition: undocuser.h:60
PFLT_MESSAGE_WAITER_QUEUE CONTAINING_RECORD(Csq, DEVICE_EXTENSION, IrpQueue)) -> WaiterQ.mLock) _IRQL_raises_(DISPATCH_LEVEL) VOID NTAPI FltpAcquireMessageWaiterLock(_In_ PIO_CSQ Csq, _Out_ PKIRQL Irql)
Definition: Messaging.c:560
#define ProbeForWriteUnicodeString(Ptr)
Definition: probe.h:48
BOOL APIENTRY co_ClientImmLoadLayout(_In_ HKL hKL, _Inout_ PIMEINFOEX pImeInfoEx)
Definition: callback.c:1278
#define KLF_SUBSTITUTE_OK
Definition: winuser.h:112
#define CP_ACP
Definition: kbdlayout.c:18
VOID FASTCALL UserEnterExclusive(VOID)
Definition: ntuser.c:245
Status
Definition: gdiplustypes.h:24
#define UserHMGetHandle(obj)
Definition: ntuser.h:230
NTSTATUS RtlAppendUnicodeToString(IN PUNICODE_STRING Str1, IN PWSTR Str2)
Definition: string_lib.cpp:62
struct _LIST_ENTRY * Flink
Definition: typedefs.h:121
NTSYSAPI NTSTATUS NTAPI RtlIntegerToUnicodeString(ULONG Value, ULONG Base, PUNICODE_STRING String)
#define TRACE(s)
Definition: solgame.cpp:4
_Must_inspect_result_ _In_ ULONG Flags
Definition: wsk.h:170
PKL W32kGetDefaultKeyLayout(VOID)
Definition: kbdlayout.c:514
HKL FASTCALL UserGetKeyboardLayout(DWORD dwThreadId)
Definition: kbdlayout.c:857
static BOOL APIENTRY IntUnloadKeyboardLayout(_Inout_ PWINSTATION_OBJECT pWinSta, _In_ HKL hKL)
Definition: kbdlayout.c:838
USHORT CodePage
Definition: input.h:36
__wchar_t WCHAR
Definition: xmlstorage.h:180
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
#define EXCEPTION_EXECUTE_HANDLER
Definition: excpt.h:85
#define UlongToHandle(ul)
Definition: basetsd.h:97
#define IMS_SENDNOTIFICATION
Definition: immdev.h:43
HKL hkl
Definition: input.h:32
#define USERTAG_IME
Definition: tags.h:240
#define MAX_PATH
Definition: compat.h:34
Definition: kbd.h:95
#define IS_CICERO_MODE()
Definition: ntuser.h:1233
struct tagKBDFILE * pkfNext
Definition: input.h:18
BOOL APIENTRY NtUserUnloadKeyboardLayout(HKL hKl)
Definition: kbdlayout.c:1179
unsigned long DWORD
Definition: ntddk_ex.h:95
ENGAPI HANDLE APIENTRY EngLoadImage(_In_ LPWSTR pwszDriver)
Definition: ldevobj.c:902
struct _CLIENTINFO * pClientInfo
Definition: win32.h:94
#define ExAllocatePoolWithTag(hernya, size, tag)
Definition: env_spec_w32.h:350
#define IMS_ACTIVATELAYOUT
Definition: immdev.h:40
BYTE cbSize
Definition: kbd.h:53
int ret
struct _KBDTABLES * pKbdTbl
Definition: input.h:21
DWORD dwThreadId
Definition: fdebug.c:31
VOID NTAPI ProbeForRead(IN CONST VOID *Address, IN SIZE_T Length, IN ULONG Alignment)
Definition: exintrin.c:102
LRESULT FASTCALL co_IntSendMessage(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam)
Definition: message.c:1446
DWORD dwKL_Flags
Definition: input.h:31
_In_ PCCERT_CONTEXT _In_ DWORD dwFlags
Definition: wincrypt.h:1175
#define VOID
Definition: acefi.h:82
DWORD dwFontSigs
Definition: input.h:34
static PKL co_UserActivateKbl(PTHREADINFO pti, PKL pKl, UINT Flags)
Definition: kbdlayout.c:604
BYTE Vk
Definition: kbd.h:22
DWORD cLockObj
Definition: ntuser.h:182
Definition: typedefs.h:119
HKL APIENTRY co_IntActivateKeyboardLayout(_Inout_ PWINSTATION_OBJECT pWinSta, _In_ HKL hKL, _In_ ULONG uFlags, _Inout_ PWND pWnd)
Definition: kbdlayout.c:766
HKL APIENTRY co_UserActivateKeyboardLayout(_Inout_ PKL pKL, _In_ ULONG uFlags, _Inout_ PWND pWnd)
Definition: kbdlayout.c:661
HANDLE NTAPI PsGetThreadId(IN PETHREAD Thread)
Definition: thread.c:705
UINT_PTR HKL
Definition: msctf.idl:101
int _cdecl swprintf(const WCHAR *,...)
struct tagKL * KeyboardLayout
Definition: win32.h:90
VOID FASTCALL SetLastNtError(NTSTATUS Status)
Definition: error.c:37
Definition: kbd.h:71
struct tagKL * pklNext
Definition: input.h:29
#define KLF_REPLACELANG
Definition: winuser.h:115
#define MAXULONG
Definition: typedefs.h:251
HEAD head
Definition: input.h:17
#define ERR(fmt,...)
Definition: debug.h:110
Definition: ntuser.h:688
struct _USER_MESSAGE_QUEUE * MessageQueue
Definition: win32.h:89
VOID FASTCALL UserLeave(VOID)
Definition: ntuser.c:254
BOOL NTAPI UserSetDefaultInputLang(HKL hKl)
Definition: kbdlayout.c:586
HKL hkl
Definition: msctf.idl:611
#define IS_IME_HKL(hKL)
Definition: input.h:88
BOOL APIENTRY NtUserGetKeyboardLayoutName(_Inout_ PUNICODE_STRING pustrName)
Definition: kbdlayout.c:954
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
static UINT APIENTRY IntGetKeyboardLayoutList(_Inout_ PWINSTATION_OBJECT pWinSta, _In_ ULONG nBuff, _Out_ HKL *pHklBuff)
Definition: kbdlayout.c:98
unsigned short USHORT
Definition: pedump.c:61
FxAutoRegKey hKey
#define HKL_NEXT
Definition: winuser.h:109
HKL NTAPI NtUserActivateKeyboardLayout(HKL hKL, ULONG Flags)
Definition: kbdlayout.c:1154
#define KLF_SETFORPROCESS
Definition: winuser.h:117
ENGAPI PVOID APIENTRY EngFindImageProcAddress(_In_ HANDLE hModule, _In_ LPSTR lpProcName)
Definition: ldevobj.c:925
HANDLE hBase
Definition: input.h:20
DWORD gLCIDSentToShell
Definition: kbdlayout.c:26
PVOID(* PFN_KBDLAYERDESCRIPTOR)(VOID)
Definition: kbdlayout.c:28
unsigned int * PULONG
Definition: retypes.h:1
unsigned int UINT
Definition: ndis.h:50
#define NULL
Definition: types.h:112
#define HKL_PREV
Definition: winuser.h:110
VOID co_IntShellHookNotify(WPARAM Message, WPARAM wParam, LPARAM lParam)
Definition: desktop.c:1692
_CRTIMP size_t __cdecl wcslen(_In_z_ const wchar_t *_Str)
#define FS_LATIN1
Definition: wingdi.h:560
PKBDFILE spkf
Definition: input.h:33
_In_ HANDLE Handle
Definition: extypes.h:390
#define RegQueryValue
Definition: winreg.h:523
NTSYSAPI NTSTATUS NTAPI RtlUnicodeStringToInteger(PUNICODE_STRING String, ULONG Base, PULONG Value)
#define HIWORD(l)
Definition: typedefs.h:247
unsigned int ULONG
Definition: retypes.h:1
PKL NTAPI UserHklToKbl(HKL hKl)
Definition: kbdlayout.c:541
ENGAPI VOID APIENTRY EngUnloadImage(_In_ HANDLE hModule)
Definition: ldevobj.c:911
char * cleanup(char *str)
Definition: wpickclick.c:99
#define _SEH2_EXCEPT(...)
Definition: pseh2_64.h:40
static PKBDFILE UserLoadKbdFile(PUNICODE_STRING pwszKLID)
Definition: kbdlayout.c:298
#define _SEH2_GetExceptionCode()
Definition: pseh2_64.h:165
#define _SEH2_YIELD(__stmt)
Definition: pseh2_64.h:168
#define ANSI_CHARSET
Definition: wingdi.h:383
static VOID UnloadKbdFile(_In_ PKBDFILE pkf)
Definition: kbdlayout.c:446
UINT APIENTRY NtUserGetKeyboardLayoutList(ULONG nBuff, HKL *pHklBuff)
Definition: kbdlayout.c:900
struct _DESKTOPINFO * pDeskInfo
Definition: win32.h:93
#define RegOpenKey
Definition: winreg.h:519
PUSER_HANDLE_TABLE gHandleTable
Definition: object.c:13
PWINSTATION_OBJECT FASTCALL IntGetProcessWindowStation(HWINSTA *phWinSta OPTIONAL)
Definition: winsta.c:400
#define ExFreePoolWithTag(_P, _T)
Definition: module.h:1099
BYTE * PBYTE
Definition: pedump.c:66
#define LOWORD(l)
Definition: pedump.c:82
#define ERROR_INVALID_FLAGS
Definition: winerror.h:583
ENGAPI VOID APIENTRY EngSetLastError(_In_ ULONG iError)
Definition: error.c:28
#define APIENTRY
Definition: api.h:79
static PKL UserLoadKbdLayout(PUNICODE_STRING pustrKLID, HKL hKL)
Definition: kbdlayout.c:377
#define NT_ASSERT
Definition: rtlfuncs.h:3310
#define REG_SZ
Definition: layer.c:22
BOOL FASTCALL UserMarkObjectDestroy(PVOID Object)
Definition: object.c:621