ReactOS  0.4.15-dev-4914-g2220e56
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 
14 // Was included only because of CP_ACP and required the
15 // definition of SYSTEMTIME in ndk\rtltypes.h
16 //#include <winnls.h>
17 #define CP_ACP 0
18 
19 DBG_DEFAULT_CHANNEL(UserKbdLayout);
20 
21 PKL gspklBaseLayout = NULL; /* FIXME: Please move this to pWinSta->spklList */
25 
27 
28 /* PRIVATE FUNCTIONS ******************************************************/
29 
30 // Win: _GetKeyboardLayoutList
31 static UINT APIENTRY
34  _In_ ULONG nBuff,
35  _Out_ HKL *pHklBuff)
36 {
37  UINT ret = 0;
38  PKL pKL, pFirstKL;
39 
40  pFirstKL = gspklBaseLayout; /* FIXME: Use pWinSta->spklList instead */
41  if (!pWinSta || !pFirstKL)
42  return 0;
43 
44  pKL = pFirstKL;
45 
46  if (nBuff == 0)
47  {
48  /* Count the effective PKLs */
49  do
50  {
51  if (!(pKL->dwKL_Flags & KLF_UNLOAD))
52  ++ret;
53  pKL = pKL->pklNext;
54  } while (pKL != pFirstKL);
55  }
56  else
57  {
58  /* Copy the effective HKLs to pHklBuff */
59  do
60  {
61  if (!(pKL->dwKL_Flags & KLF_UNLOAD))
62  {
63  *pHklBuff = pKL->hkl;
64  ++pHklBuff;
65  ++ret;
66  --nBuff;
67 
68  if (nBuff == 0)
69  break;
70  }
71  pKL = pKL->pklNext;
72  } while (pKL != pFirstKL);
73  }
74 
75  return ret;
76 }
77 
78 #if 0 && DBG
79 
80 static VOID
81 DumpKbdLayout(
82  IN PKBDTABLES pKbdTbl)
83 {
84  PVK_TO_BIT pVkToBit;
85  PVK_TO_WCHAR_TABLE pVkToWchTbl;
86  PVSC_VK pVscVk;
87  ULONG i;
88 
89  DbgPrint("Kbd layout: fLocaleFlags %x bMaxVSCtoVK %x\n",
90  pKbdTbl->fLocaleFlags, pKbdTbl->bMaxVSCtoVK);
91  DbgPrint("wMaxModBits %x\n",
92  pKbdTbl->pCharModifiers ? pKbdTbl->pCharModifiers->wMaxModBits
93  : 0);
94 
95  if (pKbdTbl->pCharModifiers)
96  {
97  pVkToBit = pKbdTbl->pCharModifiers->pVkToBit;
98  if (pVkToBit)
99  {
100  for (; pVkToBit->Vk; ++pVkToBit)
101  {
102  DbgPrint("VkToBit %x -> %x\n", pVkToBit->Vk, pVkToBit->ModBits);
103  }
104  }
105 
106  for (i = 0; i <= pKbdTbl->pCharModifiers->wMaxModBits; ++i)
107  {
108  DbgPrint("ModNumber %x -> %x\n", i, pKbdTbl->pCharModifiers->ModNumber[i]);
109  }
110  }
111 
112  pVkToWchTbl = pKbdTbl->pVkToWcharTable;
113  if (pVkToWchTbl)
114  {
115  for (; pVkToWchTbl->pVkToWchars; ++pVkToWchTbl)
116  {
117  PVK_TO_WCHARS1 pVkToWch = pVkToWchTbl->pVkToWchars;
118 
119  DbgPrint("pVkToWchTbl nModifications %x cbSize %x\n",
120  pVkToWchTbl->nModifications, pVkToWchTbl->cbSize);
121  if (pVkToWch)
122  {
123  while (pVkToWch->VirtualKey)
124  {
125  DbgPrint("pVkToWch VirtualKey %x Attributes %x wc { ",
126  pVkToWch->VirtualKey, pVkToWch->Attributes);
127  for (i = 0; i < pVkToWchTbl->nModifications; ++i)
128  {
129  DbgPrint("%x ", pVkToWch->wch[i]);
130  }
131  DbgPrint("}\n");
132  pVkToWch = (PVK_TO_WCHARS1)(((PBYTE)pVkToWch) + pVkToWchTbl->cbSize);
133  }
134  }
135  }
136  }
137 
138 // TODO: DeadKeys, KeyNames, KeyNamesExt, KeyNamesDead
139 
140  DbgPrint("pusVSCtoVK: { ");
141  if (pKbdTbl->pusVSCtoVK)
142  {
143  for (i = 0; i < pKbdTbl->bMaxVSCtoVK; ++i)
144  {
145  DbgPrint("%x -> %x, ", i, pKbdTbl->pusVSCtoVK[i]);
146  }
147  }
148  DbgPrint("}\n");
149 
150  DbgPrint("pVSCtoVK_E0: { ");
151  pVscVk = pKbdTbl->pVSCtoVK_E0;
152  if (pVscVk)
153  {
154  for (; pVscVk->Vsc; ++pVscVk)
155  {
156  DbgPrint("%x -> %x, ", pVscVk->Vsc, pVscVk->Vk);
157  }
158  }
159  DbgPrint("}\n");
160 
161  DbgPrint("pVSCtoVK_E1: { ");
162  pVscVk = pKbdTbl->pVSCtoVK_E1;
163  if (pVscVk)
164  {
165  for (; pVscVk->Vsc; ++pVscVk)
166  {
167  DbgPrint("%x -> %x, ", pVscVk->Vsc, pVscVk->Vk);
168  }
169  }
170  DbgPrint("}\n");
171 
172 // TODO: Ligatures
173 }
174 
175 #endif // DBG
176 
177 
178 /*
179  * UserLoadKbdDll
180  *
181  * Loads keyboard layout DLL and gets address to KbdTables
182  */
183 static BOOL
184 UserLoadKbdDll(WCHAR *pwszLayoutPath,
185  HANDLE *phModule,
186  PKBDTABLES *pKbdTables)
187 {
188  PFN_KBDLAYERDESCRIPTOR pfnKbdLayerDescriptor;
189 
190  /* Load keyboard layout DLL */
191  TRACE("Loading Keyboard DLL %ws\n", pwszLayoutPath);
192  *phModule = EngLoadImage(pwszLayoutPath);
193  if (!(*phModule))
194  {
195  ERR("Failed to load dll %ws\n", pwszLayoutPath);
196  return FALSE;
197  }
198 
199  /* Find KbdLayerDescriptor function and get layout tables */
200  TRACE("Loaded %ws\n", pwszLayoutPath);
201  pfnKbdLayerDescriptor = EngFindImageProcAddress(*phModule, "KbdLayerDescriptor");
202 
203  /* FIXME: Windows reads file instead of executing!
204  It's not safe to kbdlayout DLL in kernel mode! */
205 
206  if (pfnKbdLayerDescriptor)
207  *pKbdTables = pfnKbdLayerDescriptor();
208  else
209  ERR("Error: %ws has no KbdLayerDescriptor()\n", pwszLayoutPath);
210 
211  if (!pfnKbdLayerDescriptor || !*pKbdTables)
212  {
213  ERR("Failed to load the keyboard layout.\n");
214  EngUnloadImage(*phModule);
215  return FALSE;
216  }
217 
218 #if 0 && DBG
219  /* Dump keyboard layout */
220  DumpKbdLayout(*pKbdTables);
221 #endif
222 
223  return TRUE;
224 }
225 
226 /*
227  * UserLoadKbdFile
228  *
229  * Loads keyboard layout DLL and creates KBDFILE object
230  */
231 static PKBDFILE
233 {
234  PKBDFILE pkf, pRet = NULL;
236  ULONG cbSize;
237  HKEY hKey = NULL;
238  WCHAR wszLayoutPath[MAX_PATH] = L"\\SystemRoot\\System32\\";
239  WCHAR wszLayoutRegKey[256] = L"\\REGISTRY\\Machine\\SYSTEM\\CurrentControlSet\\"
240  L"Control\\Keyboard Layouts\\";
241 
242  /* Create keyboard layout file object */
244  if (!pkf)
245  {
246  ERR("Failed to create object!\n");
247  return NULL;
248  }
249 
250  /* Set keyboard layout name */
251  swprintf(pkf->awchKF, L"%wZ", pwszKLID);
252 
253  /* Open layout registry key */
254  RtlStringCbCatW(wszLayoutRegKey, sizeof(wszLayoutRegKey), pkf->awchKF);
255  Status = RegOpenKey(wszLayoutRegKey, &hKey);
256  if (!NT_SUCCESS(Status))
257  {
258  ERR("Failed to open keyboard layouts registry key %ws (%lx)\n", wszLayoutRegKey, Status);
259  goto cleanup;
260  }
261 
262  /* Read filename of layout DLL */
263  cbSize = (ULONG)(sizeof(wszLayoutPath) - wcslen(wszLayoutPath)*sizeof(WCHAR));
265  L"Layout File",
266  REG_SZ,
267  wszLayoutPath + wcslen(wszLayoutPath),
268  &cbSize);
269 
270  if (!NT_SUCCESS(Status))
271  {
272  ERR("Can't get layout filename for %wZ (%lx)\n", pwszKLID, Status);
273  goto cleanup;
274  }
275 
276  /* Load keyboard file now */
277  if (!UserLoadKbdDll(wszLayoutPath, &pkf->hBase, &pkf->pKbdTbl))
278  {
279  ERR("Failed to load %ws dll!\n", wszLayoutPath);
280  goto cleanup;
281  }
282 
283  /* Update next field */
284  pkf->pkfNext = gpkfList;
285  gpkfList = pkf;
286 
287  /* Return keyboard file */
288  pRet = pkf;
289 
290 cleanup:
291  if (hKey)
292  ZwClose(hKey);
293  if (pkf)
294  UserDereferenceObject(pkf); // we dont need ptr anymore
295  if (!pRet)
296  {
297  /* We have failed - destroy created object */
298  if (pkf)
300  }
301 
302  return pRet;
303 }
304 
305 /*
306  * UserLoadKbdLayout
307  *
308  * Loads keyboard layout and creates KL object
309  */
310 static PKL
312 {
313  LCID lCid;
314  CHARSETINFO cs;
315  PKL pKl;
316 
317  /* Create keyboard layout object */
319  if (!pKl)
320  {
321  ERR("Failed to create object!\n");
322  return NULL;
323  }
324 
325  pKl->hkl = hKL;
326  pKl->spkf = UserLoadKbdFile(pustrKLID);
327 
328  /* Dereference keyboard layout */
330 
331  /* If we failed, remove KL object */
332  if (!pKl->spkf)
333  {
334  ERR("UserLoadKbdFile(%wZ) failed!\n", pustrKLID);
336  return NULL;
337  }
338 
339  // Up to Language Identifiers..
340  if (!NT_SUCCESS(RtlUnicodeStringToInteger(pustrKLID, 16, (PULONG)&lCid)))
341  {
342  ERR("RtlUnicodeStringToInteger failed for '%wZ'\n", pustrKLID);
344  return NULL;
345  }
346 
347  TRACE("Language Identifiers %wZ LCID 0x%x\n", pustrKLID, lCid);
348  if (co_IntGetCharsetInfo(lCid, &cs))
349  {
350  pKl->iBaseCharset = cs.ciCharset;
351  pKl->dwFontSigs = cs.fs.fsCsb[0];
352  pKl->CodePage = (USHORT)cs.ciACP;
353  TRACE("Charset %u Font Sig %lu CodePage %u\n",
354  pKl->iBaseCharset, pKl->dwFontSigs, pKl->CodePage);
355  }
356  else
357  {
358  pKl->iBaseCharset = ANSI_CHARSET;
359  pKl->dwFontSigs = FS_LATIN1;
360  pKl->CodePage = CP_ACP;
361  }
362 
363  // Set initial system character set and font signature.
364  if (gSystemFS == 0)
365  {
367  gSystemFS = pKl->dwFontSigs;
368  }
369 
370  return pKl;
371 }
372 
373 /*
374  * UnloadKbdFile
375  *
376  * Destroys specified Keyboard File object
377  */
378 static
379 VOID
381 {
382  PKBDFILE *ppkfLink = &gpkfList;
383  NT_ASSERT(pkf != NULL);
384 
385  /* Find previous object */
386  while (*ppkfLink)
387  {
388  if (*ppkfLink == pkf)
389  break;
390 
391  ppkfLink = &(*ppkfLink)->pkfNext;
392  }
393 
394  if (*ppkfLink == pkf)
395  *ppkfLink = pkf->pkfNext;
396 
397  EngUnloadImage(pkf->hBase);
398  UserDeleteObject(pkf->head.h, TYPE_KBDFILE);
399 }
400 
401 /*
402  * UserUnloadKbl
403  *
404  * Unloads specified Keyboard Layout if possible
405  */
406 BOOL
408 {
409  /* According to msdn, UnloadKeyboardLayout can fail
410  if the keyboard layout identifier was preloaded. */
411  if (pKl == gspklBaseLayout)
412  {
413  if (pKl->pklNext == pKl->pklPrev)
414  {
415  /* There is only one layout */
416  return FALSE;
417  }
418 
419  /* Set next layout as default */
420  gspklBaseLayout = pKl->pklNext;
421  }
422 
423  if (pKl->head.cLockObj > 1)
424  {
425  /* Layout is used by other threads */
426  pKl->dwKL_Flags |= KLF_UNLOAD;
427  return FALSE;
428  }
429 
430  /* Unload the layout */
431  pKl->pklPrev->pklNext = pKl->pklNext;
432  pKl->pklNext->pklPrev = pKl->pklPrev;
433  UnloadKbdFile(pKl->spkf);
435  return TRUE;
436 }
437 
438 /*
439  * W32kGetDefaultKeyLayout
440  *
441  * Returns default layout for new threads
442  */
443 PKL
445 {
446  PKL pKl = gspklBaseLayout;
447 
448  if (!pKl)
449  return NULL;
450 
451  /* Return not unloaded layout */
452  do
453  {
454  if (!(pKl->dwKL_Flags & KLF_UNLOAD))
455  return pKl;
456 
457  pKl = pKl->pklPrev; /* Confirmed on Win2k */
458  } while(pKl != gspklBaseLayout);
459 
460  /* We have not found proper KL */
461  return NULL;
462 }
463 
464 /*
465  * UserHklToKbl
466  *
467  * Gets KL object from hkl value
468  */
469 PKL
470 NTAPI
472 {
473  PKL pKl = gspklBaseLayout;
474 
475  if (!gspklBaseLayout)
476  return NULL;
477 
478  do
479  {
480  if (pKl->hkl == hKl)
481  return pKl;
482 
483  pKl = pKl->pklNext;
484  } while (pKl != gspklBaseLayout);
485 
486  return NULL;
487 }
488 
489 /*
490  * UserSetDefaultInputLang
491  *
492  * Sets default kyboard layout for system. Called from UserSystemParametersInfo.
493  */
494 BOOL
495 NTAPI
497 {
498  PKL pKl;
499 
500  pKl = UserHklToKbl(hKl);
501  if (!pKl)
502  return FALSE;
503 
504  gspklBaseLayout = pKl;
505  return TRUE;
506 }
507 
508 /*
509  * co_UserActivateKbl
510  *
511  * Activates given layout in specified thread
512  */
513 static PKL
515 {
516  PKL pklPrev;
517  PWND pWnd;
518 
519  pklPrev = pti->KeyboardLayout;
520  if (pklPrev)
521  UserDereferenceObject(pklPrev);
522 
523  pti->KeyboardLayout = pKl;
524  pti->pClientInfo->hKL = pKl->hkl;
525  UserReferenceObject(pKl);
526 
527  if (Flags & KLF_SETFORPROCESS)
528  {
529  // FIXME
530  }
531 
532  if (!(pWnd = pti->MessageQueue->spwndFocus))
533  {
534  pWnd = pti->MessageQueue->spwndActive;
535  }
536 
537  // Send WM_INPUTLANGCHANGE to thread's focus window
538  co_IntSendMessage( pWnd ? UserHMGetHandle(pWnd) : 0,
539  WM_INPUTLANGCHANGE,
540  (WPARAM)pKl->iBaseCharset, // FIXME: How to set it?
541  (LPARAM)pKl->hkl); // hkl
542 
543  return pklPrev;
544 }
545 
546 /* EXPORTS *******************************************************************/
547 
548 /*
549  * UserGetKeyboardLayout
550  *
551  * Returns hkl of given thread keyboard layout
552  */
556 {
557  PTHREADINFO pti;
558  PLIST_ENTRY ListEntry;
559  PKL pKl;
560 
562 
563  if (!dwThreadId)
564  {
565  pKl = pti->KeyboardLayout;
566  return pKl ? pKl->hkl : NULL;
567  }
568 
569  ListEntry = pti->rpdesk->PtiList.Flink;
570 
571  //
572  // Search the Desktop Thread list for related Desktop active Threads.
573  //
574  while(ListEntry != &pti->rpdesk->PtiList)
575  {
576  pti = CONTAINING_RECORD(ListEntry, THREADINFO, PtiLink);
577 
578  if (PsGetThreadId(pti->pEThread) == UlongToHandle(dwThreadId))
579  {
580  pKl = pti->KeyboardLayout;
581  return pKl ? pKl->hkl : NULL;
582  }
583 
584  ListEntry = ListEntry->Flink;
585  }
586 
587  return NULL;
588 }
589 
590 /*
591  * NtUserGetKeyboardLayoutList
592  *
593  * Returns list of loaded keyboard layouts in system
594  */
595 UINT
596 APIENTRY
598  ULONG nBuff,
599  HKL *pHklBuff)
600 {
601  UINT ret = 0;
602  PWINSTATION_OBJECT pWinSta;
603 
604  if (!pHklBuff)
605  nBuff = 0;
606 
607  UserEnterShared();
608 
609  if (nBuff > MAXULONG / sizeof(HKL))
610  {
612  goto Quit;
613  }
614 
615  _SEH2_TRY
616  {
617  ProbeForWrite(pHklBuff, nBuff * sizeof(HKL), 1);
618  }
620  {
622  goto Quit;
623  }
624  _SEH2_END;
625 
626  pWinSta = IntGetProcessWindowStation(NULL);
627 
628  _SEH2_TRY
629  {
630  ret = IntGetKeyboardLayoutList(pWinSta, nBuff, pHklBuff);
631  }
633  {
635  goto Quit;
636  }
637  _SEH2_END;
638 
639 Quit:
640  UserLeave();
641  return ret;
642 }
643 
644 /*
645  * NtUserGetKeyboardLayoutName
646  *
647  * Returns KLID of current thread keyboard layout
648  */
649 BOOL
650 APIENTRY
652  _Inout_ PUNICODE_STRING pustrName)
653 {
654  BOOL bRet = FALSE;
655  PKL pKl;
656  PTHREADINFO pti;
657  UNICODE_STRING ustrTemp;
658 
659  UserEnterShared();
660 
662  pKl = pti->KeyboardLayout;
663 
664  if (!pKl)
665  goto cleanup;
666 
667  _SEH2_TRY
668  {
669  ProbeForWriteUnicodeString(pustrName);
670  ProbeForWrite(pustrName->Buffer, pustrName->MaximumLength, 1);
671 
672  if (IS_IME_HKL(pKl->hkl))
673  {
674  RtlIntegerToUnicodeString((ULONG)(ULONG_PTR)pKl->hkl, 16, pustrName);
675  }
676  else
677  {
678  if (pustrName->MaximumLength < KL_NAMELENGTH * sizeof(WCHAR))
679  {
681  goto cleanup;
682  }
683  RtlInitUnicodeString(&ustrTemp, pKl->spkf->awchKF); /* FIXME: Do not use awchKF */
684  RtlCopyUnicodeString(pustrName, &ustrTemp);
685  }
686 
687  bRet = TRUE;
688  }
690  {
692  }
693  _SEH2_END;
694 
695 cleanup:
696  UserLeave();
697  return bRet;
698 }
699 
700 /*
701  * NtUserLoadKeyboardLayoutEx
702  *
703  * Loads keyboard layout with given locale id
704  */
705 HKL
706 APIENTRY
708  IN HANDLE Handle, // hFile (See downloads.securityfocus.com/vulnerabilities/exploits/43774.c)
709  IN DWORD offTable, // Offset to KbdTables
710  IN PUNICODE_STRING puszKeyboardName, // Not used?
711  IN HKL hklUnload,
712  IN PUNICODE_STRING pustrKLID,
713  IN DWORD hkl,
714  IN UINT Flags)
715 {
716  HKL hklRet = NULL;
717  PKL pKl = NULL, pklLast;
718  WCHAR Buffer[9];
719  UNICODE_STRING ustrSafeKLID;
720 
723  KLF_RESET|KLF_SHIFTLOCK))
724  {
725  ERR("Invalid flags: %x\n", Flags);
727  return NULL;
728  }
729 
730  /* FIXME: It seems KLF_RESET is only supported for WINLOGON */
731 
732  RtlInitEmptyUnicodeString(&ustrSafeKLID, Buffer, sizeof(Buffer));
733  _SEH2_TRY
734  {
735  ProbeForRead(pustrKLID, sizeof(*pustrKLID), 1);
736  ProbeForRead(pustrKLID->Buffer, sizeof(pustrKLID->Length), 1);
737  RtlCopyUnicodeString(&ustrSafeKLID, pustrKLID);
738  }
740  {
742  _SEH2_YIELD(return NULL);
743  }
744  _SEH2_END;
745 
747 
748  /* If hklUnload is specified, unload it and load new layput as default */
749  if (hklUnload && (hklUnload != UlongToHandle(hkl)))
750  {
751  pKl = UserHklToKbl(hklUnload);
752  if (pKl)
753  UserUnloadKbl(pKl);
754  }
755 
756  /* Let's see if layout was already loaded. */
758  if (!pKl)
759  {
760  /* It wasn't, so load it. */
761  pKl = UserLoadKbdLayout(&ustrSafeKLID, UlongToHandle(hkl));
762  if (!pKl)
763  goto cleanup;
764 
765  if (gspklBaseLayout)
766  {
767  /* Find last not unloaded layout */
768  pklLast = gspklBaseLayout->pklPrev;
769  while (pklLast != gspklBaseLayout && pklLast->dwKL_Flags & KLF_UNLOAD)
770  pklLast = pklLast->pklPrev;
771 
772  /* Add new layout to the list */
773  pKl->pklNext = pklLast->pklNext;
774  pKl->pklPrev = pklLast;
775  pKl->pklNext->pklPrev = pKl;
776  pKl->pklPrev->pklNext = pKl;
777  }
778  else
779  {
780  /* This is the first layout */
781  pKl->pklNext = pKl;
782  pKl->pklPrev = pKl;
783  gspklBaseLayout = pKl;
784  }
785  }
786 
787  /* If this layout was prepared to unload, undo it */
788  pKl->dwKL_Flags &= ~KLF_UNLOAD;
789 
790  /* Activate this layout in current thread */
791  if (Flags & KLF_ACTIVATE)
793 
794  /* Send shell message */
795  if (!(Flags & KLF_NOTELLSHELL))
796  co_IntShellHookNotify(HSHELL_LANGUAGE, 0, (LPARAM)hkl);
797 
798  /* Return hkl on success */
799  hklRet = UlongToHandle(hkl);
800 
801  /* FIXME: KLF_REPLACELANG
802  KLF_REORDER */
803 
804 cleanup:
805  UserLeave();
806  return hklRet;
807 }
808 
809 /*
810  * NtUserActivateKeyboardLayout
811  *
812  * Activates specified layout for thread or process
813  */
814 HKL
815 APIENTRY
817  HKL hKl,
818  ULONG Flags)
819 {
820  PKL pKl = NULL;
821  HKL hkl = NULL;
822  PTHREADINFO pti;
823 
825 
827 
828  /* hKl can have special value HKL_NEXT or HKL_PREV */
829  if (hKl == (HKL)HKL_NEXT)
830  {
831  /* Get next keyboard layout starting with current */
832  if (pti->KeyboardLayout)
833  pKl = pti->KeyboardLayout->pklNext;
834  }
835  else if (hKl == (HKL)HKL_PREV)
836  {
837  /* Get previous keyboard layout starting with current */
838  if (pti->KeyboardLayout)
839  pKl = pti->KeyboardLayout->pklPrev;
840  }
841  else
842  pKl = UserHklToKbl(hKl);
843 
844  if (!pKl)
845  {
846  ERR("Invalid HKL %p!\n", hKl);
847  goto cleanup;
848  }
849 
850  hkl = pKl->hkl;
851 
852  /* FIXME: KLF_RESET
853  KLF_SHIFTLOCK */
854 
855  if (Flags & KLF_REORDER)
856  gspklBaseLayout = pKl;
857 
858  if (pKl != pti->KeyboardLayout)
859  {
860  /* Activate layout for current thread */
861  pKl = co_UserActivateKbl(pti, pKl, Flags);
862 
863  /* Send shell message */
864  if (!(Flags & KLF_NOTELLSHELL))
865  co_IntShellHookNotify(HSHELL_LANGUAGE, 0, (LPARAM)hkl);
866  }
867 
868 cleanup:
869  UserLeave();
870  return hkl;
871 }
872 
873 /*
874  * NtUserUnloadKeyboardLayout
875  *
876  * Unloads keyboard layout with specified hkl value
877  */
878 BOOL
879 APIENTRY
881  HKL hKl)
882 {
883  PKL pKl;
884  BOOL bRet = FALSE;
885 
887 
888  pKl = UserHklToKbl(hKl);
889  if (pKl)
890  bRet = UserUnloadKbl(pKl);
891  else
892  ERR("Invalid HKL %p!\n", hKl);
893 
894  UserLeave();
895  return bRet;
896 }
897 
898 /* EOF */
#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:184
VOID FASTCALL UserEnterShared(VOID)
Definition: ntuser.c:242
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:407
#define _Out_
Definition: ms_sal.h:345
BOOL APIENTRY co_IntGetCharsetInfo(LCID Locale, PCHARSETINFO pCs)
Definition: callback.c:1040
PKL gspklBaseLayout
Definition: kbdlayout.c:21
#define KLF_ACTIVATE
Definition: winuser.h:111
#define TRUE
Definition: types.h:120
NTSYSAPI NTSTATUS NTAPI ZwClose(_In_ HANDLE Handle)
HANDLE h
Definition: ntuser.h:173
Definition: kbd.h:21
PVOID NTAPI PsGetCurrentThreadWin32Thread(VOID)
Definition: thread.c:805
LONG NTSTATUS
Definition: precomp.h:26
BYTE Vsc
Definition: kbd.h:72
#define KLF_NOTELLSHELL
Definition: winuser.h:116
PKBDFILE gpkfList
Definition: kbdlayout.c:22
BOOL FASTCALL UserDereferenceObject(PVOID Object)
Definition: object.c:644
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:707
DWORD LCID
Definition: nls.h:13
UINT_PTR WPARAM
Definition: windef.h:207
UINT gSystemCPCharSet
Definition: kbdlayout.c:24
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
struct _DESKTOP * rpdesk
Definition: win32.h:93
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)
_SEH2_TRY
Definition: create.c:4226
uint32_t ULONG_PTR
Definition: typedefs.h:65
USHORT Vk
Definition: kbd.h:73
uint32_t cs
Definition: isohybrid.c:75
#define L(x)
Definition: ntvdm.h:50
NTSTATUS(* NTAPI)(IN PFILE_FULL_EA_INFORMATION EaBuffer, IN ULONG EaLength, OUT PULONG ErrorOffset)
Definition: IoEaTest.cpp:117
#define FALSE
Definition: types.h:117
DWORD gSystemFS
Definition: kbdlayout.c:23
unsigned int BOOL
Definition: ntddk_ex.h:94
HEAD head
Definition: input.h:28
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
#define IS_IME_HKL(hkl)
Definition: ntuser.h:1203
Definition: bufpool.h:45
WCHAR awchKF[20]
Definition: input.h:19
BYTE nModifications
Definition: kbd.h:52
UINT iBaseCharset
Definition: input.h:35
void * PVOID
Definition: retypes.h:9
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
#define KLF_SUBSTITUTE_OK
Definition: winuser.h:112
#define CP_ACP
Definition: kbdlayout.c:17
VOID FASTCALL UserEnterExclusive(VOID)
Definition: ntuser.c:249
Status
Definition: gdiplustypes.h:24
#define UserHMGetHandle(obj)
Definition: ntuser.h:222
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:444
HKL FASTCALL UserGetKeyboardLayout(DWORD dwThreadId)
Definition: kbdlayout.c:554
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
HKL hkl
Definition: input.h:32
#define MAX_PATH
Definition: compat.h:34
Definition: kbd.h:95
struct tagKBDFILE * pkfNext
Definition: input.h:18
BOOL APIENTRY NtUserUnloadKeyboardLayout(HKL hKl)
Definition: kbdlayout.c:880
unsigned long DWORD
Definition: ntddk_ex.h:95
ENGAPI HANDLE APIENTRY EngLoadImage(_In_ LPWSTR pwszDriver)
Definition: ldevobj.c:879
struct _CLIENTINFO * pClientInfo
Definition: win32.h:95
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
#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:514
BYTE Vk
Definition: kbd.h:22
DWORD cLockObj
Definition: ntuser.h:174
Definition: typedefs.h:119
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:91
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:672
struct _USER_MESSAGE_QUEUE * MessageQueue
Definition: win32.h:90
VOID FASTCALL UserLeave(VOID)
Definition: ntuser.c:258
BOOL NTAPI UserSetDefaultInputLang(HKL hKl)
Definition: kbdlayout.c:496
_SEH2_END
Definition: create.c:4400
HKL hkl
Definition: msctf.idl:611
BOOL APIENTRY NtUserGetKeyboardLayoutName(_Inout_ PUNICODE_STRING pustrName)
Definition: kbdlayout.c:651
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:32
unsigned short USHORT
Definition: pedump.c:61
FxAutoRegKey hKey
#define HKL_NEXT
Definition: winuser.h:109
#define KLF_SETFORPROCESS
Definition: winuser.h:117
ENGAPI PVOID APIENTRY EngFindImageProcAddress(_In_ HANDLE hModule, _In_ LPSTR lpProcName)
Definition: ldevobj.c:902
HANDLE hBase
Definition: input.h:20
PVOID(* PFN_KBDLAYERDESCRIPTOR)(VOID)
Definition: kbdlayout.c:26
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)
unsigned int ULONG
Definition: retypes.h:1
PKL NTAPI UserHklToKbl(HKL hKl)
Definition: kbdlayout.c:471
NTSYSAPI VOID NTAPI RtlInitUnicodeString(PUNICODE_STRING DestinationString, PCWSTR SourceString)
ENGAPI VOID APIENTRY EngUnloadImage(_In_ HANDLE hModule)
Definition: ldevobj.c:888
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:232
#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:380
UINT APIENTRY NtUserGetKeyboardLayoutList(ULONG nBuff, HKL *pHklBuff)
Definition: kbdlayout.c:597
#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
BYTE * PBYTE
Definition: pedump.c:66
#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:311
VOID FASTCALL UserReferenceObject(PVOID obj)
Definition: object.c:731
#define NT_ASSERT
Definition: rtlfuncs.h:3310
#define REG_SZ
Definition: layer.c:22
HKL APIENTRY NtUserActivateKeyboardLayout(HKL hKl, ULONG Flags)
Definition: kbdlayout.c:816