00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
#include "precomp.h"
00013
#pragma hdrstop
00014
00015
00016
00017
00018
BOOL xxxInternalUnloadKeyboardLayout(
PWINDOWSTATION,
PKL, UINT);
00019
VOID ReorderKeyboardLayouts(
PWINDOWSTATION,
PKL);
00020
00021
00022
00023
00024 #define FIXUP_PTR(p, pBase) ((p) ? (p) = (PVOID)((PBYTE)pBase + (WORD)(ULONG_PTR)(p)) : 0)
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040 PKL HKLtoPKL(
00041
PTHREADINFO pti,
00042 HKL hkl)
00043 {
00044
PKL pklActive;
00045
PKL pkl;
00046
00047 UserAssert(pti !=
NULL);
00048
if ((pklActive = pti->
spklActive) ==
NULL) {
00049
return NULL;
00050 }
00051
00052 pkl = pklActive;
00053
00054
if (hkl == (HKL)HKL_PREV) {
00055
do {
00056 pkl = pkl->
pklPrev;
00057
if (!(pkl->
dwKL_Flags &
KL_UNLOADED)) {
00058
return pkl;
00059 }
00060 }
while (pkl != pklActive);
00061
return NULL;
00062 }
else if (hkl == (HKL)HKL_NEXT) {
00063
do {
00064 pkl = pkl->
pklNext;
00065
if (!(pkl->
dwKL_Flags &
KL_UNLOADED)) {
00066
return pkl;
00067 }
00068 }
while (pkl != pklActive);
00069
return NULL;
00070 }
00071
00072
00073
00074
00075
00076
00077
if (HandleToUlong(hkl) & 0xffff0000) {
00078
do {
00079
if (pkl->
hkl == hkl) {
00080
return pkl;
00081 }
00082 pkl = pkl->
pklNext;
00083 }
while (pkl != pklActive);
00084 }
else {
00085
do {
00086
if (LOWORD(HandleToUlong(pkl->
hkl)) == LOWORD(HandleToUlong(hkl))) {
00087
return pkl;
00088 }
00089 pkl = pkl->
pklNext;
00090 }
while (pkl != pklActive);
00091 }
00092
00093
return NULL;
00094 }
00095
00096
00097
00098
00099
00100
00101
00102
00103
00104
00105
00106 PKBDTABLES
ReadLayoutFile(
00107
PKBDFILE pkf,
00108 HANDLE hFile,
00109 UINT offTable,
00110 PKBDNLSTABLES *ppNlsTables)
00111 {
00112 HANDLE hmap;
00113 SIZE_T ulViewSize = 0;
00114
NTSTATUS Status;
00115 PIMAGE_DOS_HEADER DosHdr;
00116 PIMAGE_NT_HEADERS NtHeader;
00117 PIMAGE_SECTION_HEADER SectionTableEntry;
00118 ULONG NumberOfSubsections;
00119 ULONG OffsetToSectionTable;
00120
PBYTE pBaseDst, pBaseVirt;
00121 PKBDTABLES pktNew =
NULL;
00122
DWORD dwDataSize;
00123 PKBDNLSTABLES pknlstNew =
NULL;
00124
UINT offNlsTable = HIWORD(offTable);
00125
00126
00127
00128 offTable &= 0x0000FFFF;
00129
00130
00131
00132
00133 *ppNlsTables =
NULL;
00134
00135
00136
00137
00138 DosHdr =
NULL;
00139
Status = ZwCreateSection(&hmap, SECTION_ALL_ACCESS,
NULL,
00140
NULL, PAGE_READONLY, SEC_COMMIT, hFile);
00141
if (!
NT_SUCCESS(
Status))
00142
return NULL;
00143
00144
Status = ZwMapViewOfSection(hmap, NtCurrentProcess(), &DosHdr, 0, 0,
NULL,
00145 &ulViewSize, ViewShare, 0, PAGE_READONLY);
00146
if (!
NT_SUCCESS(
Status)) {
00147
goto exitread;
00148 }
00149
00150
00151
00152
00153
00154
00155 NtHeader = (PIMAGE_NT_HEADERS)((
PBYTE)DosHdr + (ULONG)DosHdr->e_lfanew);
00156
00157
00158
00159
00160 NumberOfSubsections = NtHeader->FileHeader.NumberOfSections;
00161
00162
00163
00164
00165
00166 OffsetToSectionTable =
sizeof(ULONG) +
00167
sizeof(IMAGE_FILE_HEADER) +
00168 NtHeader->FileHeader.SizeOfOptionalHeader;
00169 SectionTableEntry = (PIMAGE_SECTION_HEADER)((
PBYTE)NtHeader +
00170 OffsetToSectionTable);
00171
00172
while (NumberOfSubsections > 0) {
00173
if (strcmp(SectionTableEntry->Name,
".data") == 0)
00174
break;
00175
00176 SectionTableEntry++;
00177 NumberOfSubsections--;
00178 }
00179
if (NumberOfSubsections == 0) {
00180
goto exitread;
00181 }
00182
00183
00184
00185
00186 offTable -= SectionTableEntry->VirtualAddress;
00187 dwDataSize = SectionTableEntry->Misc.VirtualSize;
00188
00189
00190
00191
00192 pBaseDst = UserAllocPool(dwDataSize, TAG_KBDTABLE);
00193
if (pBaseDst !=
NULL) {
00194 VK_TO_WCHAR_TABLE *pVkToWcharTable;
00195 VSC_LPWSTR *pKeyName;
00196 LPWSTR *lpDeadKey;
00197
00198 pkf->
hBase = (HANDLE)pBaseDst;
00199 RtlMoveMemory(pBaseDst, (
PBYTE)DosHdr +
00200 SectionTableEntry->PointerToRawData, dwDataSize);
00201
00202
if (
ISTS()) {
00203 pkf->
Size = dwDataSize;
00204 }
00205
00206
00207
00208
00209 pktNew = (PKBDTABLES)(pBaseDst + offTable);
00210
00211
00212
00213
00214
00215
00216 pBaseVirt = pBaseDst - SectionTableEntry->VirtualAddress;
00217
00218
FIXUP_PTR(pktNew->pCharModifiers, pBaseVirt);
00219
FIXUP_PTR(pktNew->pCharModifiers->pVkToBit, pBaseVirt);
00220
if (
FIXUP_PTR(pktNew->pVkToWcharTable, pBaseVirt)) {
00221
for (pVkToWcharTable = pktNew->pVkToWcharTable;
00222 pVkToWcharTable->pVkToWchars !=
NULL; pVkToWcharTable++)
00223
FIXUP_PTR(pVkToWcharTable->pVkToWchars, pBaseVirt);
00224 }
00225
FIXUP_PTR(pktNew->pDeadKey, pBaseVirt);
00226
00227
00228
00229
if (GET_KBD_VERSION(pktNew)) {
00230
FIXUP_PTR(pktNew->pLigature, pBaseVirt);
00231 }
00232
if (
FIXUP_PTR(pktNew->pKeyNames, pBaseVirt)) {
00233
for (pKeyName = pktNew->pKeyNames; pKeyName->vsc != 0; pKeyName++)
00234
FIXUP_PTR(pKeyName->pwsz, pBaseVirt);
00235 }
00236
if (
FIXUP_PTR(pktNew->pKeyNamesExt, pBaseVirt)) {
00237
for (pKeyName = pktNew->pKeyNamesExt; pKeyName->vsc != 0; pKeyName++)
00238
FIXUP_PTR(pKeyName->pwsz, pBaseVirt);
00239 }
00240
if (
FIXUP_PTR(pktNew->pKeyNamesDead, pBaseVirt)) {
00241
for (lpDeadKey = pktNew->pKeyNamesDead; *lpDeadKey !=
NULL;
00242 lpDeadKey++)
00243
FIXUP_PTR(*lpDeadKey, pBaseVirt);
00244 }
00245
FIXUP_PTR(pktNew->pusVSCtoVK, pBaseVirt);
00246
FIXUP_PTR(pktNew->pVSCtoVK_E0, pBaseVirt);
00247
FIXUP_PTR(pktNew->pVSCtoVK_E1, pBaseVirt);
00248
00249
if (offNlsTable) {
00250
00251
00252
00253 offNlsTable -= SectionTableEntry->VirtualAddress;
00254 pknlstNew = (PKBDNLSTABLES)(pBaseDst + offNlsTable);
00255
00256
00257
00258
00259
FIXUP_PTR(pknlstNew->pVkToF, pBaseVirt);
00260
FIXUP_PTR(pknlstNew->pusMouseVKey, pBaseVirt);
00261
00262
00263
00264
00265 *ppNlsTables = pknlstNew;
00266
00267
#if DBG_FE
00268
{
00269
UINT NumOfVkToF = pknlstNew->NumOfVkToF;
00270
00271
DbgPrint(
"NumOfVkToF - %d\n",NumOfVkToF);
00272
00273
while(NumOfVkToF) {
00274
DbgPrint(
"VK = %x\n",pknlstNew->pVkToF[NumOfVkToF-1].Vk);
00275 NumOfVkToF--;
00276 }
00277 }
00278
#endif // DBG_FE
00279
}
00280 }
00281
00282 exitread:
00283
00284
00285
00286
00287 ZwUnmapViewOfSection(NtCurrentProcess(), DosHdr);
00288 ZwClose(hmap);
00289
00290
return pktNew;
00291 }
00292
00293 PKBDTABLES
PrepareFallbackKeyboardFile(
PKBDFILE pkf)
00294 {
00295
PBYTE pBaseDst;
00296
00297 pBaseDst = UserAllocPool(
sizeof(KBDTABLES), TAG_KBDTABLE);
00298
if (pBaseDst !=
NULL) {
00299 RtlCopyMemory(pBaseDst, &
KbdTablesFallback,
sizeof KbdTablesFallback);
00300
00301
00302 }
00303 pkf->
hBase = (HANDLE)pBaseDst;
00304 pkf->
pKbdNlsTbl =
NULL;
00305
return (PKBDTABLES)pBaseDst;
00306 }
00307
00308
00309
00310
00311
00312
00313
00314
00315
00316 PKBDFILE LoadKeyboardLayoutFile(
00317 HANDLE hFile,
00318 UINT offTable,
00319 LPCWSTR pwszKLID)
00320 {
00321
PKBDFILE pkf =
gpkfList;
00322
00323
if (pkf) {
00324
int iCmp;
00325
00326
do {
00327 iCmp = wcscmp(pkf->
awchKF, pwszKLID);
00328
if (iCmp == 0) {
00329
00330
00331
00332
00333
return pkf;
00334 }
00335 pkf = pkf->
pkfNext;
00336 }
while (pkf);
00337 }
00338
00339
00340
00341
00342 pkf = (
PKBDFILE)
HMAllocObject(
NULL,
NULL,
TYPE_KBDFILE,
sizeof(
KBDFILE));
00343
if (!pkf) {
00344 RIPMSG0(RIP_WARNING,
"Keyboard Layout File: out of memory");
00345
return (
PKBDFILE)
NULL;
00346 }
00347
00348
00349
00350
00351
if (hFile !=
NULL) {
00352
00353
00354
00355 pkf->
pKbdTbl =
ReadLayoutFile(pkf, hFile, offTable, &(pkf->
pKbdNlsTbl));
00356 }
else {
00357
00358
00359
00360
00361
00362
00363
00364 pkf->
pKbdTbl =
PrepareFallbackKeyboardFile(pkf);
00365
00366 }
00367
00368
if (pkf->
pKbdTbl ==
NULL) {
00369
HMFreeObject(pkf);
00370
return (
PKBDFILE)
NULL;
00371 }
00372
00373
wcsncpycch(pkf->
awchKF, pwszKLID,
sizeof(pkf->
awchKF) /
sizeof(WCHAR));
00374
00375
00376
00377
00378 pkf->
pkfNext =
gpkfList;
00379
gpkfList = pkf;
00380
00381
return pkf;
00382 }
00383
00384
00385
00386
00387
00388
00389
00390 VOID RemoveKeyboardLayoutFile(
00391
PKBDFILE pkf)
00392 {
00393
PKBDFILE pkfPrev, pkfCur;
00394
00395
00396
if (
gpKbdTbl == pkf->
pKbdTbl) {
00397
gpKbdTbl = &
KbdTablesFallback;
00398 }
00399
if (
gpKbdNlsTbl == pkf->
pKbdNlsTbl) {
00400
gpKbdNlsTbl =
NULL;
00401 }
00402
00403
00404
00405
00406
if (pkf ==
gpkfList) {
00407
00408
00409
00410
gpkfList = pkf->
pkfNext;
00411
return;
00412 }
00413 pkfPrev =
gpkfList;
00414 pkfCur =
gpkfList->
pkfNext;
00415
while (pkf != pkfCur) {
00416 pkfPrev = pkfCur;
00417 pkfCur = pkfCur->
pkfNext;
00418 }
00419
00420
00421
00422 pkfPrev->
pkfNext = pkfCur->
pkfNext;
00423 }
00424
00425
00426
00427
00428
00429
00430
00431
00432
00433
00434
void
00435 DestroyKF(
PKBDFILE pkf)
00436 {
00437
if (!
HMMarkObjectDestroy(pkf))
00438
return;
00439
00440
RemoveKeyboardLayoutFile(pkf);
00441 UserFreePool(pkf->
hBase);
00442
HMFreeObject(pkf);
00443 }
00444
00445 INT GetThreadsWithPKL(
00446
PTHREADINFO **ppptiList,
00447
PKL pkl)
00448 {
00449
PTHREADINFO ptiT, *pptiT, *pptiListAllocated;
00450
INT cThreads, cThreadsAllocated;
00451
PWINDOWSTATION pwinsta;
00452
PDESKTOP pdesk;
00453 PLIST_ENTRY pHead, pEntry;
00454
00455
if (ppptiList !=
NULL)
00456 *ppptiList =
NULL;
00457
00458 cThreads = 0;
00459
00460
00461
00462
00463 cThreadsAllocated = 128;
00464 pptiListAllocated = UserAllocPool(cThreadsAllocated *
sizeof(
PTHREADINFO),
00465 TAG_SYSTEM);
00466
00467
if (pptiListAllocated ==
NULL) {
00468 RIPMSG0(RIP_WARNING,
"GetPKLinThreads: out of memory");
00469
return 0;
00470 }
00471
00472
00473
for (pwinsta =
grpWinStaList; pwinsta !=
NULL ; pwinsta = pwinsta->
rpwinstaNext) {
00474
00475
00476
for (pdesk = pwinsta->
rpdeskList; pdesk !=
NULL ; pdesk = pdesk->
rpdeskNext) {
00477
00478 pHead = &pdesk->
PtiList;
00479
00480
00481
for (pEntry = pHead->Flink; pEntry != pHead; pEntry = pEntry->Flink) {
00482
00483 ptiT = CONTAINING_RECORD(pEntry,
THREADINFO, PtiLink);
00484
00485
if (ptiT ==
NULL) {
00486
continue;
00487 }
00488
00489
if (pkl && (pkl != ptiT->
spklActive)) {
00490
continue;
00491 }
00492
00493
if (cThreads == cThreadsAllocated) {
00494
00495 cThreadsAllocated += 128;
00496
00497 pptiT = UserReAllocPool(pptiListAllocated,
00498 cThreads *
sizeof(
PTHREADINFO),
00499 cThreadsAllocated *
sizeof(
PTHREADINFO),
00500 TAG_SYSTEM);
00501
00502
if (pptiT ==
NULL) {
00503 RIPMSG0(RIP_ERROR,
"GetPKLinThreads: Out of memory");
00504 UserFreePool(pptiListAllocated);
00505
return 0;
00506 }
00507
00508 pptiListAllocated = pptiT;
00509
00510 }
00511
00512 pptiListAllocated[cThreads++] = ptiT;
00513 }
00514 }
00515 }
00516
00517
00518
00519
00520
for (ptiT =
PpiFromProcess(
gpepCSRSS)->ptiList; ptiT !=
NULL; ptiT = ptiT->
ptiSibling) {
00521
00522
if (pkl && (pkl != ptiT->
spklActive)) {
00523
continue;
00524 }
00525
00526
if (cThreads == cThreadsAllocated) {
00527
00528 cThreadsAllocated += 128;
00529
00530 pptiT = UserReAllocPool(pptiListAllocated,
00531 cThreads *
sizeof(
PTHREADINFO),
00532 cThreadsAllocated *
sizeof(
PTHREADINFO),
00533 TAG_SYSTEM);
00534
00535
if (pptiT ==
NULL) {
00536 RIPMSG0(RIP_ERROR,
"GetPKLinThreads: Out of memory");
00537 UserFreePool(pptiListAllocated);
00538
return 0;
00539 }
00540
00541 pptiListAllocated = pptiT;
00542
00543 }
00544
00545 pptiListAllocated[cThreads++] = ptiT;
00546 }
00547
00548
if (cThreads == 0) {
00549 UserFreePool(pptiListAllocated);
00550 }
else if (ppptiList !=
NULL) {
00551 *ppptiList = pptiListAllocated;
00552 }
else {
00553 UserFreePool(pptiListAllocated);
00554 }
00555
00556
return cThreads;
00557 }
00558
00559
00560 VOID xxxSetPKLinThreads(
00561
PKL pklNew,
00562
PKL pklToBeReplaced)
00563 {
00564
PTHREADINFO *pptiList;
00565
INT cThreads, i;
00566
00567 UserAssert(pklNew != pklToBeReplaced);
00568
00569
CheckLock(pklNew);
00570
CheckLock(pklToBeReplaced);
00571
00572 cThreads =
GetThreadsWithPKL(&pptiList, pklToBeReplaced);
00573
00574
00575
00576
00577
if (pklNew &&
gptiForeground &&
gptiForeground->
spklActive == pklToBeReplaced) {
00578
ChangeForegroundKeyboardTable(pklToBeReplaced, pklNew);
00579 }
00580
00581
if (pptiList !=
NULL) {
00582
if (pklToBeReplaced ==
NULL) {
00583
for (i = 0; i < cThreads; i++) {
00584
Lock(&pptiList[i]->spklActive, pklNew);
00585 }
00586 }
else {
00587
00588
00589
00590
00591
xxxImmActivateAndUnloadThreadsLayout(pptiList, cThreads,
NULL,
00592 pklNew, HandleToUlong(pklToBeReplaced->hkl));
00593 }
00594 UserFreePool(pptiList);
00595 }
00596
00597
00598
00599
00600
00601
00602
00603
if (pklToBeReplaced) {
00604
if (pklToBeReplaced->pklNext == pklNew) {
00605
00606
00607
00608
return;
00609 }
00610
00611
00612
00613
00614
00615
00616 pklNew->
pklPrev->
pklNext = pklNew->
pklNext;
00617 pklNew->
pklNext->
pklPrev = pklNew->
pklPrev;
00618
00619 pklNew->
pklNext = pklToBeReplaced->
pklNext;
00620 pklNew->
pklPrev = pklToBeReplaced;
00621
00622 pklToBeReplaced->
pklNext->
pklPrev = pklNew;
00623 pklToBeReplaced->
pklNext = pklNew;
00624 }
00625 }
00626
00627 VOID xxxFreeImeKeyboardLayouts(
00628
PWINDOWSTATION pwinsta)
00629 {
00630
PTHREADINFO *pptiList;
00631
INT cThreads;
00632
00633
if (pwinsta->
dwWSF_Flags &
WSF_NOIO)
00634
return;
00635
00636
00637
00638
00639 cThreads =
GetThreadsWithPKL(&pptiList,
NULL);
00640
if (pptiList !=
NULL) {
00641
xxxImmUnloadThreadsLayout(pptiList, cThreads,
NULL,
IFL_UNLOADIME);
00642 UserFreePool(pptiList);
00643 }
00644
00645
return;
00646 }
00647
00648
00649
00650
00651
00652
00653
00654 HKL
xxxLoadKeyboardLayoutEx(
00655
PWINDOWSTATION pwinsta,
00656 HANDLE hFile,
00657 HKL hklToBeReplaced,
00658 UINT offTable,
00659 LPCWSTR pwszKLID,
00660 UINT KbdInputLocale,
00661 UINT Flags)
00662 {
00663
PKL pkl, pklFirst, pklToBeReplaced;
00664
PKBDFILE pkf;
00665 CHARSETINFO cs;
00666
TL tlpkl;
00667
PTHREADINFO ptiCurrent;
00668 UNICODE_STRING strLcidKF;
00669 LCID lcidKF;
00670
BOOL bCharSet;
00671
PIMEINFOEX piiex;
00672
00673
00674
00675
00676
00677
if ((KbdInputLocale == 0) || (pwinsta->
dwWSF_Flags &
WSF_NOIO)) {
00678
return NULL;
00679 }
00680
00681
00682
00683
00684
00685 ptiCurrent =
PtiCurrent();
00686
if (hklToBeReplaced && !(pklToBeReplaced =
HKLtoPKL(ptiCurrent, hklToBeReplaced))) {
00687
return NULL;
00688 }
00689
if (KbdInputLocale == HandleToUlong(hklToBeReplaced)) {
00690
00691
00692
00693
return pklToBeReplaced->
hkl;
00694 }
00695
00696
if (Flags & KLF_RESET) {
00697
00698
00699
00700
if (ptiCurrent->pEThread->Cid.UniqueProcess !=
gpidLogon) {
00701 RIPERR0(ERROR_INVALID_FLAGS, RIP_WARNING,
00702
"Invalid flag passed to LoadKeyboardLayout" );
00703
return NULL;
00704 }
00705
xxxFreeImeKeyboardLayouts(pwinsta);
00706
00707
00708
00709
00710
00711
00712
xxxFreeKeyboardLayouts(pwinsta,
FALSE);
00713 }
00714
00715
00716
00717
00718 pkl = pklFirst = pwinsta->
spklList;
00719
00720
if (pkl) {
00721
do {
00722
if (pkl->
hkl == (HKL)IntToPtr( KbdInputLocale )) {
00723
00724
00725
00726
00727
00728
00729
00730
00731
if (pkl->
dwKL_Flags &
KL_UNLOADED) {
00732
00733
PHE phe =
HMPheFromObject(pkl);
00734
00735 UserAssert(phe->
bFlags &
HANDLEF_DESTROY);
00736 phe->
bFlags &= ~
HANDLEF_DESTROY;
00737
#if DBG
00738
phe->
bFlags &= ~
HANDLEF_MARKED_OK;
00739
#endif
00740
pkl->
dwKL_Flags &= ~
KL_UNLOADED;
00741 }
else if (!(Flags & KLF_RESET)) {
00742
00743
00744
00745
00746 Flags &= ~KLF_NOTELLSHELL;
00747 }
00748
00749
goto AllPresentAndCorrectSir;
00750 }
00751 pkl = pkl->
pklNext;
00752 }
while (pkl != pklFirst);
00753 }
00754
00755
if (
IS_IME_KBDLAYOUT((HKL)IntToPtr( KbdInputLocale ))) {
00756
00757
00758
00759
00760
00761
00762 piiex =
xxxImmLoadLayout((HKL)IntToPtr( KbdInputLocale ));
00763
if (piiex ==
NULL && !(Flags & KLF_RESET)) {
00764 RIPMSG1(RIP_WARNING,
00765
"Keyboard Layout: xxxImmLoadLayout(%lx) failed", KbdInputLocale);
00766
return NULL;
00767 }
00768 }
else {
00769 piiex =
NULL;
00770 }
00771
00772
00773
00774
00775
00776
00777
if (
gSystemFS == 0) {
00778 LCID lcid;
00779
00780 ZwQueryDefaultLocale(
FALSE, &lcid);
00781
if (
xxxClientGetCharsetInfo(lcid, &cs)) {
00782
gSystemFS = cs.fs.fsCsb[0];
00783
gSystemCPCharSet = (
BYTE)cs.ciCharset;
00784 }
else {
00785
gSystemFS = 0xFFFF;
00786
gSystemCPCharSet = ANSI_CHARSET;
00787 }
00788 }
00789
00790
00791
00792
00793
00794
00795
00796
00797
00798
00799
00800
RtlInitUnicodeString(&strLcidKF, pwszKLID + 4);
00801
RtlUnicodeStringToInteger(&strLcidKF, 16, (PULONG)&lcidKF);
00802 bCharSet =
xxxClientGetCharsetInfo(lcidKF, &cs);
00803
00804
00805
00806
00807
00808
if (!(pkf =
LoadKeyboardLayoutFile(hFile, offTable, pwszKLID))) {
00809
goto freePiiex;
00810 }
00811
00812
00813
00814 pkl = (
PKL)
HMAllocObject(
NULL,
NULL,
TYPE_KBDLAYOUT,
sizeof(
KL));
00815
if (!pkl) {
00816 RIPMSG0(RIP_WARNING,
"Keyboard Layout: out of memory");
00817 UserFreePool(pkf->
hBase);
00818
HMMarkObjectDestroy(pkf);
00819
HMUnlockObject(pkf);
00820 freePiiex:
00821
if (piiex) {
00822 UserFreePool(piiex);
00823 }
00824
return NULL;
00825 }
00826
00827
00828
00829
00830 pkl->
pklNext = pkl;
00831 pkl->
pklPrev = pkl;
00832
00833
00834
00835
00836 pkl->
dwKL_Flags = 0;
00837 pkl->
wchDiacritic = 0;
00838 pkl->
hkl = (HKL)IntToPtr( KbdInputLocale );
00839
Lock(&pkl->
spkf, pkf);
00840
00841 pkl->
spkf->
pKbdTbl->fLocaleFlags |= KLL_LAYOUT_ATTR_FROM_KLF(Flags);
00842
00843 pkl->
piiex = piiex;
00844
00845
if (bCharSet) {
00846 pkl->
CodePage = (WORD)cs.ciACP;
00847 pkl->
dwFontSigs = cs.fs.fsCsb[1];
00848 pkl->
iBaseCharset = cs.ciCharset;
00849 }
else {
00850 pkl->
CodePage = CP_ACP;
00851 pkl->
dwFontSigs = FS_LATIN1;
00852 pkl->
iBaseCharset = ANSI_CHARSET;
00853 }
00854
00855
00856
00857
00858 pklFirst = pwinsta->
spklList;
00859
if (pklFirst ==
NULL) {
00860
Lock(&pwinsta->
spklList, pkl);
00861 }
else {
00862 pkl->
pklNext = pklFirst;
00863 pkl->
pklPrev = pklFirst->
pklPrev;
00864 pklFirst->
pklPrev->
pklNext = pkl;
00865 pklFirst->
pklPrev = pkl;
00866 }
00867
00868 AllPresentAndCorrectSir:
00869
00870
00871
ThreadLockAlwaysWithPti(ptiCurrent, pkl, &tlpkl);
00872
00873
if (hklToBeReplaced) {
00874
TL tlPKLToBeReplaced;
00875
ThreadLockAlwaysWithPti(ptiCurrent, pklToBeReplaced, &tlPKLToBeReplaced);
00876
xxxSetPKLinThreads(pkl, pklToBeReplaced);
00877
xxxInternalUnloadKeyboardLayout(pwinsta, pklToBeReplaced, KLF_INITTIME);
00878
ThreadUnlock(&tlPKLToBeReplaced);
00879 }
00880
00881
if (Flags & KLF_REORDER) {
00882
ReorderKeyboardLayouts(pwinsta, pkl);
00883 }
00884
00885
if (!(Flags & KLF_NOTELLSHELL) &&
IsHooked(
PtiCurrent(),
WHF_SHELL)) {
00886
xxxCallHook(HSHELL_LANGUAGE, (WPARAM)
NULL, (LPARAM)0, WH_SHELL);
00887
gLCIDSentToShell = 0;
00888 }
00889
00890
if (Flags & KLF_ACTIVATE) {
00891
TL tlPKL;
00892
ThreadLockAlwaysWithPti(ptiCurrent, pkl, &tlPKL);
00893
xxxInternalActivateKeyboardLayout(pkl, Flags,
NULL);
00894
ThreadUnlock(&tlPKL);
00895 }
00896
00897
if (Flags & KLF_RESET) {
00898 RIPMSG2(RIP_VERBOSE,
"Flag & KLF_RESET, locking gspklBaseLayout(%08x) with new kl(%08x)",
00899
gspklBaseLayout ?
gspklBaseLayout->
hkl : 0,
00900 pkl->
hkl);
00901
Lock(&
gspklBaseLayout, pkl);
00902
xxxSetPKLinThreads(pkl,
NULL);
00903 }
00904
00905
00906
00907
00908
00909 pkl =
ThreadUnlock(&tlpkl);
00910
if (pkl ==
NULL) {
00911
return NULL;
00912 }
00913
return pkl->
hkl;
00914 }
00915
00916 HKL
xxxActivateKeyboardLayout(
00917
PWINDOWSTATION pwinsta,
00918 HKL hkl,
00919 UINT Flags,
00920
PWND pwnd)
00921 {
00922
PKL pkl;
00923
TL tlPKL;
00924 HKL hklRet;
00925
PTHREADINFO ptiCurrent =
PtiCurrent();
00926
00927
CheckLock(pwnd);
00928
00929 pkl =
HKLtoPKL(ptiCurrent, hkl);
00930
if (pkl ==
NULL) {
00931
return 0;
00932 }
00933
00934
if (Flags & KLF_REORDER) {
00935
ReorderKeyboardLayouts(pwinsta, pkl);
00936 }
00937
00938
ThreadLockAlwaysWithPti(ptiCurrent, pkl, &tlPKL);
00939 hklRet =
xxxInternalActivateKeyboardLayout(pkl, Flags, pwnd);
00940
ThreadUnlock(&tlPKL);
00941
return hklRet;
00942 }
00943
00944 VOID ReorderKeyboardLayouts(
00945
PWINDOWSTATION pwinsta,
00946
PKL pkl)
00947 {
00948
PKL pklFirst = pwinsta->
spklList;
00949
00950
if (pwinsta->
dwWSF_Flags &
WSF_NOIO) {
00951 RIPMSG1(RIP_ERROR,
"ReorderKeyboardLayouts called for non-interactive windowstation %#p",
00952 pwinsta);
00953
return;
00954 }
00955
00956 UserAssert(pklFirst !=
NULL);
00957
00958
00959
00960
00961
if (pkl == pklFirst) {
00962
return;
00963 }
00964
00965
00966
00967 pkl->
pklPrev->
pklNext = pkl->
pklNext;
00968 pkl->
pklNext->
pklPrev = pkl->
pklPrev;
00969
00970
00971
00972
00973 pkl->
pklNext = pklFirst;
00974 pkl->
pklPrev = pklFirst->
pklPrev;
00975
00976 pklFirst->
pklPrev->
pklNext = pkl;
00977 pklFirst->
pklPrev = pkl;
00978
00979
Lock(&pwinsta->
spklList, pkl);
00980 }
00981
00982 VOID ChangeForegroundKeyboardTable(
PKL pklOld,
PKL pklNew)
00983 {
00984
CheckCritIn();
00985 UserAssert(pklNew !=
NULL);
00986
00987
if (pklOld == pklNew || (pklOld !=
NULL && pklOld->
spkf == pklNew->
spkf)) {
00988
return;
00989 }
00990
00991
00992
00993
00994
00995
00996
00997
00998
00999
01000
01001
01002
01003
01004
if (pklOld && JAPANESE_KBD_LAYOUT(pklOld->
hkl)) {
01005
if (!JAPANESE_KBD_LAYOUT(pklNew->
hkl)) {
01006
01007
01008
gfKanaToggle = (
TestAsyncKeyStateToggle(VK_KANA) != 0);
01009 RIPMSG0(RIP_VERBOSE,
"Old kbd is JPN. VK_KANA toggle is being cleared.\n");
01010
ClearAsyncKeyStateToggle(VK_KANA);
01011
ClearRawKeyToggle(VK_KANA);
01012
UpdateKeyLights(
TRUE);
01013 }
01014 }
else if (JAPANESE_KBD_LAYOUT(pklNew->
hkl)) {
01015
01016
01017
01018 RIPMSG0(RIP_VERBOSE,
"New kbd is JPN. ");
01019
if (
gfKanaToggle) {
01020 RIPMSG0(RIP_VERBOSE,
"VK_KANA is being set.\n");
01021
SetAsyncKeyStateToggle(VK_KANA);
01022
SetRawKeyToggle(VK_KANA);
01023
if (
gptiForeground &&
gptiForeground->
pq) {
01024
SetKeyStateToggle(
gptiForeground->
pq, VK_KANA);
01025 }
01026 }
else {
01027 RIPMSG0(RIP_VERBOSE,
"VK_KANA is beging cleared.\n");
01028
ClearAsyncKeyStateToggle(VK_KANA);
01029
ClearRawKeyToggle(VK_KANA);
01030
if (
gptiForeground &&
gptiForeground->
pq) {
01031
ClearKeyStateToggle(
gptiForeground->
pq, VK_KANA);
01032 }
01033 }
01034
UpdateKeyLights(
TRUE);
01035 }
01036
01037
01038
01039
01040
gpKbdTbl = pklNew->
spkf->
pKbdTbl;
01041
if (
ISTS()) {
01042
ghKbdTblBase = pklNew->
spkf->
hBase;
01043
guKbdTblSize = pklNew->
spkf->
Size;
01044 }
01045
01046 UserAssert(pklNew);
01047 TAGMSG2(DBGTAG_IMM,
"ChangeForegroundKeyboardTable:Changing KL NLS Table: prev HKL=%x to new HKL=%x\n", pklOld ? pklOld->
hkl : 0, pklNew->
hkl);
01048 TAGMSG1(DBGTAG_IMM,
"ChangeForegroundKeyboardTable: new gpKbdNlsTbl=%x\n", pklNew->
spkf->
pKbdNlsTbl);
01049
gpKbdNlsTbl = pklNew->
spkf->
pKbdNlsTbl;
01050 }
01051
01052
01053
01054
01055
01056
01057
01058
01059 void ResetPushState(
PTHREADINFO pti, UINT uVk)
01060 {
01061 TAGMSG1(DBGTAG_IMM,
"ResetPushState: has to reset the push state of vk=%x\n", uVk);
01062
if (uVk != 0) {
01063
ClearAsyncKeyStateDown(uVk);
01064
ClearAsyncKeyStateDown(uVk);
01065
ClearRawKeyDown(uVk);
01066
ClearRawKeyToggle(uVk);
01067
ClearKeyStateDown(pti->
pq, uVk);
01068
ClearKeyStateToggle(pti->
pq, uVk);
01069 }
01070 }
01071
01072
01073
01074
01075
01076
01077
01078
01079
01080
01081
01082
01083
01084
01085
01086
01087
01088
01089
01090
01091
01092
01093
01094
01095
01096
01097
01098
01099
01100
01101
01102
01103
01104 void AdjustPushState(
PTHREADINFO ptiCurrent, BYTE bBaseVk, BYTE bVkL, BYTE bVkR,
PKL pklPrev,
PKL pklNew)
01105 {
01106 BOOLEAN fDownL =
FALSE, fDownR =
FALSE;
01107 BOOLEAN fVanishL =
FALSE, fVanishR =
FALSE;
01108
01109
UINT uScanCode1, uScanCode2;
01110
01111
if (bVkL) {
01112 fDownL =
TestRawKeyDown(bVkL) ||
TestAsyncKeyStateDown(bVkL) ||
TestKeyStateDown(ptiCurrent->
pq, bVkL);
01113 uScanCode1 =
InternalMapVirtualKeyEx(bVkL, 0, pklPrev->
spkf->
pKbdTbl);
01114 uScanCode2 =
InternalMapVirtualKeyEx(bVkL, 0, pklNew->
spkf->
pKbdTbl);
01115 fVanishL = (uScanCode1 && uScanCode2 == 0);
01116
if (fVanishL) {
01117
ResetPushState(ptiCurrent, bVkL);
01118 }
01119 }
01120
01121
if (bVkR) {
01122 fDownR =
TestRawKeyDown(bVkR) ||
TestAsyncKeyStateDown(bVkR) ||
TestKeyStateDown(ptiCurrent->
pq, bVkR);
01123 uScanCode1 =
InternalMapVirtualKeyEx(bVkR, 0, pklPrev->
spkf->
pKbdTbl);
01124 uScanCode2 =
InternalMapVirtualKeyEx(bVkR, 0, pklNew->
spkf->
pKbdTbl);
01125 fVanishR = (uScanCode1 && uScanCode2 == 0);
01126
if (fVanishR) {
01127
ResetPushState(ptiCurrent, bVkR);
01128 }
01129 }
01130
01131
if (bBaseVk) {
01132 TAGMSG4(DBGTAG_IMM,
"fDL(%d) fVL(%d) fDR(%d) fVR(%d)\n", fDownL, fVanishL, fDownR, fVanishR);
01133
if (((fDownL & fVanishL & ((BOOLEAN)~fDownR | (fDownR & fVanishR))) | ((BOOLEAN)~fDownL & fDownR & fVanishR)) & 1) {
01134 TAGMSG1(DBGTAG_IMM,
"AdjustPushState(): Going to reset %x\n", bBaseVk);
01135
ResetPushState(ptiCurrent, bBaseVk);
01136 }
01137 }
01138 }
01139
01140 VOID AdjustPushStateForKL(
PTHREADINFO ptiCurrent, PBYTE pbDone,
PKL pklTarget,
PKL pklPrev,
PKL pklNew)
01141 {
01142 CONST VK_TO_BIT* pVkToBits;
01143
01144 UserAssert(pklPrev);
01145
CheckLock(pklPrev);
01146 UserAssert(pklNew);
01147
CheckLock(pklNew);
01148
01149
if (pklTarget->
spkf ==
NULL || pklPrev->
spkf ==
NULL) {
01150
return;
01151 }
01152
01153 pVkToBits = pklTarget->
spkf->
pKbdTbl->pCharModifiers->pVkToBit;
01154
01155
for (; pVkToBits->Vk; ++pVkToBits) {
01156
BYTE bVkVar1 = 0, bVkVar2 = 0;
01157
01158
01159
01160
01161 UserAssert(pVkToBits->Vk < 0x100);
01162
if (pbDone[pVkToBits->Vk >> 3] & (1 << (pVkToBits->Vk & 7))) {
01163
continue;
01164 }
01165
01166
switch (pVkToBits->Vk) {
01167
case VK_SHIFT:
01168 bVkVar1 = VK_LSHIFT;
01169 bVkVar2 = VK_RSHIFT;
01170
break;
01171
case VK_CONTROL:
01172 bVkVar1 = VK_LCONTROL;
01173 bVkVar2 = VK_RCONTROL;
01174
break;
01175
case VK_MENU:
01176 bVkVar1 = VK_LMENU;
01177 bVkVar2 = VK_RMENU;
01178
break;
01179 }
01180
01181 TAGMSG3(DBGTAG_IMM,
"Adjusting VK=%x var1=%x var2=%x\n", pVkToBits->Vk, bVkVar1, bVkVar2);
01182
01183
AdjustPushState(ptiCurrent, pVkToBits->Vk, bVkVar1, bVkVar2, pklPrev, pklNew);
01184
01185 pbDone[pVkToBits->Vk >> 3] |= (1 << (pVkToBits->Vk & 7));
01186 }
01187 }
01188
01189
01190
01191
01192
01193
01194
01195
01196
01197
01198
01199
01200
01201
01202
01203 HKL
xxxInternalActivateKeyboardLayout(
01204
PKL pkl,
01205 UINT Flags,
01206
PWND pwnd)
01207 {
01208 HKL hklPrev;
01209
PKL pklPrev;
01210
TL tlpklPrev;
01211
PTHREADINFO ptiCurrent =
PtiCurrent();
01212
01213
CheckLock(pkl);
01214
CheckLock(pwnd);
01215
01216
01217
01218
01219
01220
if (ptiCurrent->
spklActive != (
PKL)
NULL) {
01221 pklPrev = ptiCurrent->
spklActive;
01222 hklPrev = ptiCurrent->
spklActive->
hkl;
01223 }
else {
01224 pklPrev =
NULL;
01225 hklPrev = (HKL)0;
01226 }
01227
01228
01229
01230
01231
01232
if (Flags & KLF_RESET) {
01233
gdwKeyboardAttributes = KLL_GLOBAL_ATTR_FROM_KLF(Flags);
01234 }
01235
01236
01237
01238
01239
if (!(Flags & KLF_SETFORPROCESS) && (pkl == ptiCurrent->
spklActive)) {
01240
return hklPrev;
01241 }
01242
01243
01244
01245
01246 pkl->
wchDiacritic = 0;
01247
01248
01249
01250
01251
01252
01253
01254
01255
01256
ThreadLockWithPti(ptiCurrent, pklPrev, &tlpklPrev);
01257
01258
01259
01260
01261
01262
if (ptiCurrent->
TIF_flags &
TIF_CSRSSTHREAD) {
01263
Lock(&ptiCurrent->
spklActive, pkl);
01264 ptiCurrent->
pClientInfo->
CodePage = pkl->
CodePage;
01265
#if 0 // see Raid #58025 and #78586
01266
ptiCurrent->
pClientInfo->
hKL = pkl->
hkl;
01267 PLIST_ENTRY pHead;
01268 PLIST_ENTRY pEntry;
01269
PQ pqCurrent = ptiCurrent->
pq;
01270
PTHREADINFO ptiT;
01271
01272 pHead = &(
grpdeskRitInput->
PtiList);
01273
for (pEntry = pHead->Flink; pEntry != pHead; pEntry = pEntry->Flink) {
01274 ptiT = CONTAINING_RECORD(pEntry,
THREADINFO, PtiLink);
01275
if (ptiT->
pq == pqCurrent) {
01276
Lock(&ptiT->
spklActive, pkl);
01277 UserAssert(ptiT->
pClientInfo !=
NULL);
01278 ptiT->
pClientInfo->
CodePage = pkl->
CodePage;
01279 ptiT->
pClientInfo->
hKL = pkl->
hkl;
01280 }
01281 }
01282
#endif
01283
}
else if ((Flags & KLF_SETFORPROCESS) && !(ptiCurrent->
TIF_flags &
TIF_16BIT)) {
01284
01285
01286
01287
PTHREADINFO ptiT;
01288
01289
if (
IS_IME_ENABLED()) {
01290
01291
01292
01293 UserAssert(
PsGetCurrentProcess() !=
gpepCSRSS);
01294
01295
if (!
xxxImmActivateThreadsLayout(ptiCurrent->
ppi->
ptiList,
NULL, pkl)) {
01296 RIPMSG1(RIP_WARNING,
"no layout change necessary via xxxImmActivateThreadLayout() for process %lx", ptiCurrent->
ppi);
01297
goto UnlockAndGo;
01298 }
01299 }
else {
01300
BOOL fKLChanged =
FALSE;
01301
01302
for (ptiT = ptiCurrent->
ppi->
ptiList; ptiT !=
NULL; ptiT = ptiT->
ptiSibling) {
01303
if (ptiT->
spklActive != pkl && (ptiT->
TIF_flags &
TIF_INCLEANUP) == 0) {
01304
Lock(&ptiT->
spklActive, pkl);
01305 UserAssert(ptiT->
pClientInfo !=
NULL);
01306 ptiT->
pClientInfo->
CodePage = pkl->
CodePage;
01307 ptiT->
pClientInfo->
hKL = pkl->
hkl;
01308 fKLChanged =
TRUE;
01309 }
01310 }
01311
if (!fKLChanged) {
01312 RIPMSG1(RIP_WARNING,
"no layout change necessary for process %lx ?", ptiCurrent->
ppi);
01313
goto UnlockAndGo;
01314 }
01315 }
01316
01317 }
else {
01318
if (
IS_IME_ENABLED()) {
01319
xxxImmActivateLayout(ptiCurrent, pkl);
01320 }
else {
01321
Lock(&ptiCurrent->
spklActive, pkl);
01322 }
01323 UserAssert(ptiCurrent->
pClientInfo !=
NULL);
01324
if ((ptiCurrent->
TIF_flags &
TIF_INCLEANUP) == 0) {
01325 ptiCurrent->
pClientInfo->
CodePage = pkl->
CodePage;
01326 ptiCurrent->
pClientInfo->
hKL = pkl->
hkl;
01327 }
01328 }
01329
01330
01331
01332
01333
01334
01335
01336
01337
01338
01339
01340
01341
01342
01343
01344
01345
01346
if (ptiCurrent->
pq) {
01347
if (pklPrev) {
01348
BYTE baDone[256 / 8];
01349
01350 RtlZeroMemory(baDone,
sizeof baDone);
01351
01352
01353
01354
01355
01356 TAGMSG2(DBGTAG_IMM,
"Changing KL from %08lx to %08lx", pklPrev->
hkl, pkl->
hkl);
01357
AdjustPushStateForKL(ptiCurrent, baDone, pklPrev, pklPrev, pkl);
01358
AdjustPushStateForKL(ptiCurrent, baDone, pkl, pklPrev, pkl);
01359
01360
if (pklPrev->
spkf && (pklPrev->
spkf->
pKbdTbl->fLocaleFlags & KLLF_ALTGR)) {
01361
01362
01363
01364
01365 TAGMSG0(DBGTAG_IMM,
"Clearing VK_LCONTROL for AltGr\n");
01366
ResetPushState(ptiCurrent, VK_LCONTROL);
01367 }
01368 }
01369
else {
01370
01371
01372
01373
int i;
01374
for (i = 0; i <
CBKEYSTATE; i++) {
01375 ptiCurrent->
pq->
afKeyState[i] &= KEYSTATE_TOGGLE_BYTEMASK;
01376
gafAsyncKeyState[i] &= KEYSTATE_TOGGLE_BYTEMASK;
01377
gafRawKeyState[i] &= KEYSTATE_TOGGLE_BYTEMASK;
01378 }
01379 }
01380 }
01381
01382
01383
01384
01385
if (
gptiForeground && (
gptiForeground->
ppi == ptiCurrent->
ppi)) {
01386
ChangeForegroundKeyboardTable(pklPrev, pkl);
01387
01388
01389
01390
01391
01392
01393
01394
if (
gLCIDSentToShell != pkl->
hkl && (ptiCurrent !=
gptiRit)) {
01395
if (
IsHooked(ptiCurrent,
WHF_SHELL)) {
01396
gLCIDSentToShell = pkl->
hkl;
01397
xxxCallHook(HSHELL_LANGUAGE, (WPARAM)
NULL, (LPARAM)pkl->
hkl, WH_SHELL);
01398 }
01399 }
01400 }
01401
01402
01403
01404
01405
if (ptiCurrent->
pq) {
01406
PWND pwndT;
01407
TL tlpwndT;
01408
01409
01410
01411
01412
01413 pwndT = ptiCurrent->
pq->
spwndFocus;
01414
if (pwndT ==
NULL) {
01415 pwndT = ptiCurrent->
pq->
spwndActive;
01416
if (pwndT ==
NULL) {
01417 pwndT = pwnd;
01418 }
01419 }
01420
01421
if (pwndT !=
NULL) {
01422
ThreadLockAlwaysWithPti( ptiCurrent, pwndT, &tlpwndT);
01423
xxxSendMessage(pwndT, WM_INPUTLANGCHANGE, (WPARAM)pkl->
iBaseCharset, (LPARAM)pkl->
hkl);
01424
ThreadUnlock(&tlpwndT);
01425 }
01426 }
01427
01428
01429
01430
01431
if (ptiCurrent && ptiCurrent->
spwndDefaultIme &&
01432 (ptiCurrent->
TIF_flags &
TIF_CSRSSTHREAD) == 0) {
01433
if (
IS_IME_KBDLAYOUT(pkl->
hkl)) {
01434
BOOL fForProcess = (ptiCurrent->
TIF_flags & KLF_SETFORPROCESS) && !(ptiCurrent->
TIF_flags &
TIF_16BIT);
01435
TL tlpwndIme;
01436
01437 TAGMSG1(DBGTAG_IMM,
"Sending IMS_SENDNOTIFICATION to pwnd=%p", ptiCurrent->
spwndDefaultIme);
01438
01439
ThreadLockAlwaysWithPti(ptiCurrent, ptiCurrent->
spwndDefaultIme, &tlpwndIme);
01440
xxxSendMessage(ptiCurrent->
spwndDefaultIme, WM_IME_SYSTEM, IMS_SENDNOTIFICATION, fForProcess);
01441
ThreadUnlock(&tlpwndIme);
01442 }
01443 }
01444
01445 UnlockAndGo:
01446
ThreadUnlock(&tlpklPrev);
01447
01448
return hklPrev;
01449 }
01450
01451 BOOL xxxUnloadKeyboardLayout(
01452
PWINDOWSTATION pwinsta,
01453 HKL hkl)
01454 {
01455
PKL pkl;
01456
01457
01458
01459
01460
01461 pkl =
HKLtoPKL(
PtiCurrent(), hkl);
01462
if (pkl ==
NULL) {
01463
return FALSE;
01464 }
01465
01466
return xxxInternalUnloadKeyboardLayout(pwinsta, pkl, 0);
01467 }
01468
01469 HKL
_GetKeyboardLayout(
01470 DWORD idThread)
01471 {
01472
PTHREADINFO ptiT;
01473 PLIST_ENTRY pHead, pEntry;
01474
01475
CheckCritIn();
01476
01477
01478
01479
01480
if (idThread == 0) {
01481
PKL pklActive =
PtiCurrentShared()->spklActive;
01482
01483
if (pklActive ==
NULL) {
01484
return (HKL)0;
01485 }
01486
return pklActive->
hkl;
01487 }
01488
01489
01490
01491 pHead = &
PtiCurrent()->rpdesk->PtiList;
01492
for (pEntry = pHead->Flink; pEntry != pHead; pEntry = pEntry->Flink) {
01493 ptiT = CONTAINING_RECORD(pEntry,
THREADINFO, PtiLink);
01494
if (ptiT->pEThread->Cid.UniqueThread == (HANDLE)LongToHandle( idThread )) {
01495
if (ptiT->
spklActive ==
NULL) {
01496
return (HKL)0;
01497 }
01498
return ptiT->
spklActive->
hkl;
01499 }
01500 }
01501
01502
01503
01504
return (HKL)0;
01505 }
01506
01507 UINT _GetKeyboardLayoutList(
01508
PWINDOWSTATION pwinsta,
01509 UINT nItems,
01510 HKL *ccxlpBuff)
01511 {
01512
UINT nHKL = 0;
01513
PKL pkl, pklFirst;
01514
01515
if (!pwinsta) {
01516
return 0;
01517 }
01518
01519 pkl = pwinsta->
spklList;
01520
01521
01522
01523
01524
if (pkl ==
NULL) {
01525
01526
return 0;
01527 }
01528
01529
01530
01531
01532 UserAssert(ccxlpBuff || (nItems == 0));
01533
01534 pklFirst = pkl;
01535
if (nItems) {
01536
try {
01537
do {
01538
if (!(pkl->dwKL_Flags &
KL_UNLOADED)) {
01539
if (nItems-- == 0) {
01540
break;
01541 }
01542 nHKL++;
01543 *ccxlpBuff++ = pkl->
hkl;
01544 }
01545 pkl = pkl->pklNext;
01546 }
while (pkl != pklFirst);
01547 } except (
EXCEPTION_EXECUTE_HANDLER) {
01548 RIPERR1(ERROR_INVALID_PARAMETER, RIP_ERROR,
01549
"_GetKeyBoardLayoutList: exception writing ccxlpBuff %lx", ccxlpBuff);
01550
return 0;
01551 }
01552 }
else do {
01553
if (!(pkl->dwKL_Flags &
KL_UNLOADED)) {
01554 nHKL++;
01555 }
01556 pkl = pkl->pklNext;
01557 }
while (pkl != pklFirst);
01558
01559
return nHKL;
01560 }
01561
01562
01563
01564
01565
01566
01567
01568
01569
01570
01571 BOOL xxxInternalUnloadKeyboardLayout(
01572
PWINDOWSTATION pwinsta,
01573
PKL pkl,
01574 UINT Flags)
01575 {
01576
PTHREADINFO ptiCurrent =
PtiCurrent();
01577
TL tlpkl;
01578
01579 UserAssert(pkl);
01580
01581
01582
01583
01584
01585
if ((pkl ==
gspklBaseLayout) && !(Flags & KLF_INITTIME)) {
01586
return FALSE;
01587 }
01588
01589
01590
01591
01592
ThreadLockAlwaysWithPti(ptiCurrent, pkl, &tlpkl);
01593
01594
01595
01596
01597
01598
HMMarkObjectDestroy(pkl);
01599 pkl->
dwKL_Flags |=
KL_UNLOADED;
01600
01601
01602
01603
01604
01605
if (!(Flags & KLF_INITTIME)) {
01606 UserAssert(ptiCurrent->
spklActive !=
NULL);
01607
if (ptiCurrent->
spklActive == pkl) {
01608
PKL pklNext;
01609 pklNext =
HKLtoPKL(ptiCurrent, (HKL)HKL_NEXT);
01610
if (pklNext !=
NULL) {
01611
TL tlPKL;
01612
ThreadLockAlwaysWithPti(ptiCurrent, pklNext, &tlPKL);
01613
xxxInternalActivateKeyboardLayout(pklNext, Flags,
NULL);
01614
ThreadUnlock(&tlPKL);
01615 }
01616 }
01617 }
01618
01619
01620
01621
01622
01623
if (pwinsta->
spklList == pkl) {
01624 UserAssert(pkl !=
NULL);
01625
if (pkl != pkl->
pklNext) {
01626 pkl =
Lock(&pwinsta->
spklList, pkl->
pklNext);
01627 UserAssert(pkl !=
NULL);
01628 }
01629 }
01630
01631
01632
01633
01634
ThreadUnlock(&tlpkl);
01635
01636
01637
01638
01639
if (
IsHooked(ptiCurrent,
WHF_SHELL)) {
01640
xxxCallHook(HSHELL_LANGUAGE, (WPARAM)
NULL, (LPARAM)0, WH_SHELL);
01641
gLCIDSentToShell = 0;
01642 }
01643
01644
return TRUE;
01645 }
01646
01647 VOID xxxFreeKeyboardLayouts(
01648
PWINDOWSTATION pwinsta, BOOL bUnlock)
01649 {
01650
PKL pkl;
01651
01652
01653
01654
01655
01656
01657
01658
01659
01660
01661
while ((pkl =
HKLtoPKL(
PtiCurrent(), (HKL)HKL_NEXT)) !=
NULL) {
01662
xxxInternalUnloadKeyboardLayout(pwinsta, pkl, KLF_INITTIME);
01663 }
01664
01665
01666
01667
01668
01669
01670
01671
01672
01673
if (bUnlock) {
01674
Unlock(&pwinsta->
spklList);
01675 }
01676 }
01677
01678
01679
01680
01681
01682
01683
01684
01685
01686
01687
01688 VOID DestroyKL(
01689
PKL pkl)
01690 {
01691
PKBDFILE pkf;
01692
01693
01694
01695
01696
01697 pkl->
pklPrev->
pklNext = pkl->
pklNext;
01698 pkl->
pklNext->
pklPrev = pkl->
pklPrev;
01699
01700
01701
01702
01703 pkf =
Unlock(&pkl->
spkf);
01704
if (pkf) {
01705
DestroyKF(pkf);
01706 }
01707
01708
if (pkl->
piiex !=
NULL) {
01709 UserFreePool(pkl->
piiex);
01710 }
01711
01712
01713
01714
01715
HMFreeObject(pkl);
01716 }