Main Page | Class Hierarchy | Class List | File List | Class Members | File Members

kbdlyout.c File Reference

#include "precomp.h"

Go to the source code of this file.

Defines

#define FIXUP_PTR(p, pBase)   ((p) ? (p) = (PVOID)((PBYTE)pBase + (WORD)(ULONG_PTR)(p)) : 0)

Functions

BOOL xxxInternalUnloadKeyboardLayout (PWINDOWSTATION, PKL, UINT)
VOID ReorderKeyboardLayouts (PWINDOWSTATION, PKL)
PKL HKLtoPKL (PTHREADINFO pti, HKL hkl)
PKBDTABLES ReadLayoutFile (PKBDFILE pkf, HANDLE hFile, UINT offTable, PKBDNLSTABLES *ppNlsTables)
PKBDTABLES PrepareFallbackKeyboardFile (PKBDFILE pkf)
PKBDFILE LoadKeyboardLayoutFile (HANDLE hFile, UINT offTable, LPCWSTR pwszKLID)
VOID RemoveKeyboardLayoutFile (PKBDFILE pkf)
void DestroyKF (PKBDFILE pkf)
INT GetThreadsWithPKL (PTHREADINFO **ppptiList, PKL pkl)
VOID xxxSetPKLinThreads (PKL pklNew, PKL pklToBeReplaced)
VOID xxxFreeImeKeyboardLayouts (PWINDOWSTATION pwinsta)
HKL xxxLoadKeyboardLayoutEx (PWINDOWSTATION pwinsta, HANDLE hFile, HKL hklToBeReplaced, UINT offTable, LPCWSTR pwszKLID, UINT KbdInputLocale, UINT Flags)
HKL xxxActivateKeyboardLayout (PWINDOWSTATION pwinsta, HKL hkl, UINT Flags, PWND pwnd)
VOID ChangeForegroundKeyboardTable (PKL pklOld, PKL pklNew)
void ResetPushState (PTHREADINFO pti, UINT uVk)
void AdjustPushState (PTHREADINFO ptiCurrent, BYTE bBaseVk, BYTE bVkL, BYTE bVkR, PKL pklPrev, PKL pklNew)
VOID AdjustPushStateForKL (PTHREADINFO ptiCurrent, PBYTE pbDone, PKL pklTarget, PKL pklPrev, PKL pklNew)
HKL xxxInternalActivateKeyboardLayout (PKL pkl, UINT Flags, PWND pwnd)
BOOL xxxUnloadKeyboardLayout (PWINDOWSTATION pwinsta, HKL hkl)
HKL _GetKeyboardLayout (DWORD idThread)
UINT _GetKeyboardLayoutList (PWINDOWSTATION pwinsta, UINT nItems, HKL *ccxlpBuff)
VOID xxxFreeKeyboardLayouts (PWINDOWSTATION pwinsta, BOOL bUnlock)
VOID DestroyKL (PKL pkl)


Define Documentation

#define FIXUP_PTR p,
pBase   )     ((p) ? (p) = (PVOID)((PBYTE)pBase + (WORD)(ULONG_PTR)(p)) : 0)
 

Definition at line 24 of file kbdlyout.c.

Referenced by ReadLayoutFile().


Function Documentation

HKL _GetKeyboardLayout DWORD  idThread  ) 
 

Definition at line 1469 of file kbdlyout.c.

References CheckCritIn, tagKL::hkl, NULL, PtiCurrent, PtiCurrentShared, and tagTHREADINFO::spklActive.

Referenced by GetActiveHKL().

01471 { 01472 PTHREADINFO ptiT; 01473 PLIST_ENTRY pHead, pEntry; 01474 01475 CheckCritIn(); 01476 01477 /* 01478 * If idThread is NULL return hkl of the current thread 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 * Look for idThread 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 * idThread doesn't exist 01503 */ 01504 return (HKL)0; 01505 }

UINT _GetKeyboardLayoutList PWINDOWSTATION  pwinsta,
UINT  nItems,
HKL *  ccxlpBuff
 

Definition at line 1507 of file kbdlyout.c.

References EXCEPTION_EXECUTE_HANDLER, tagKL::hkl, KL_UNLOADED, NULL, tagWINDOWSTATION::spklList, and UINT.

Referenced by NtUserGetKeyboardLayoutList().

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 * Windowstations that do not take input could have no layouts 01523 */ 01524 if (pkl == NULL) { 01525 // SetLastError() ???? 01526 return 0; 01527 } 01528 01529 /* 01530 * The client/server thunk sets nItems to 0 if ccxlpBuff == NULL 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 }

void AdjustPushState PTHREADINFO  ptiCurrent,
BYTE  bBaseVk,
BYTE  bVkL,
BYTE  bVkR,
PKL  pklPrev,
PKL  pklNew
 

Definition at line 1104 of file kbdlyout.c.

References FALSE, InternalMapVirtualKeyEx(), tagKBDFILE::pKbdTbl, tagTHREADINFO::pq, ResetPushState(), tagKL::spkf, TestAsyncKeyStateDown, TestKeyStateDown, TestRawKeyDown, and UINT.

Referenced by AdjustPushStateForKL().

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 }

VOID AdjustPushStateForKL PTHREADINFO  ptiCurrent,
PBYTE  pbDone,
PKL  pklTarget,
PKL  pklPrev,
PKL  pklNew
 

Definition at line 1140 of file kbdlyout.c.

References AdjustPushState(), BYTE, CheckLock, NULL, tagKBDFILE::pKbdTbl, tagKL::spkf, and VOID().

Referenced by xxxInternalActivateKeyboardLayout().

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 // Is it already processed ? 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 }

VOID ChangeForegroundKeyboardTable PKL  pklOld,
PKL  pklNew
 

Definition at line 982 of file kbdlyout.c.

References CheckCritIn, ClearAsyncKeyStateToggle, ClearKeyStateToggle, ClearRawKeyToggle, gfKanaToggle, ghKbdTblBase, gpKbdNlsTbl, gpKbdTbl, gptiForeground, guKbdTblSize, tagKBDFILE::hBase, tagKL::hkl, ISTS, NULL, tagKBDFILE::pKbdNlsTbl, tagKBDFILE::pKbdTbl, tagTHREADINFO::pq, SetAsyncKeyStateToggle, SetKeyStateToggle, SetRawKeyToggle, tagKBDFILE::Size, tagKL::spkf, TestAsyncKeyStateToggle, TRUE, UpdateKeyLights(), and VOID().

Referenced by SetForegroundThread(), xxxInternalActivateKeyboardLayout(), and xxxSetPKLinThreads().

00983 { 00984 CheckCritIn(); 00985 UserAssert(pklNew != NULL); 00986 00987 if (pklOld == pklNew || (pklOld != NULL && pklOld->spkf == pklNew->spkf)) { 00988 return; 00989 } 00990 00991 // Manage the VK_KANA toggle key for Japanese KL. 00992 // Since VK_HANGUL and VK_KANA share the same VK value and 00993 // VK_KANA is a toggle key, when keyboard layouts are switched, 00994 // VK_KANA toggle status should be restored. 00995 00996 // 00997 // If: 00998 // 1) Old and New keyboard layouts are both Japanese, do nothing. 00999 // 2) Old and New keyboard layouts are not Japanese, do nothing. 01000 // 3) Old keyboard is Japanese and new one is not, clear the KANA toggle. 01001 // 4) New keyboard is Japanese and old one is not, restore the KANA toggle. 01002 // 01003 01004 if (pklOld && JAPANESE_KBD_LAYOUT(pklOld->hkl)) { 01005 if (!JAPANESE_KBD_LAYOUT(pklNew->hkl)) { 01006 // Old keyboard layout is Japanese and the new one is not Japanese, 01007 // so we save the current KANA toggle status and clear it. 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 // Previous keyboard layout does not exist or is not Japanese, 01016 // and the new one is Japanese. 01017 // Have to restore the KANA toggle status. 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 * Set gpKbdTbl so foreground thread processes AltGr appropriately 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 }

void DestroyKF PKBDFILE  pkf  ) 
 

Definition at line 435 of file kbdlyout.c.

References tagKBDFILE::hBase, HMFreeObject(), HMMarkObjectDestroy(), and RemoveKeyboardLayoutFile().

Referenced by DestroyKL().

00436 { 00437 if (!HMMarkObjectDestroy(pkf)) 00438 return; 00439 00440 RemoveKeyboardLayoutFile(pkf); 00441 UserFreePool(pkf->hBase); 00442 HMFreeObject(pkf); 00443 }

VOID DestroyKL PKL  pkl  ) 
 

Definition at line 1688 of file kbdlyout.c.

References DestroyKF(), HMFreeObject(), NULL, tagKL::piiex, tagKL::pklNext, tagKL::pklPrev, tagKL::spkf, Unlock, and VOID().

Referenced by Win32kNtUserCleanup().

01690 { 01691 PKBDFILE pkf; 01692 01693 /* 01694 * Cut it out of the pwinsta->spklList circular bidirectional list. 01695 * We know pwinsta->spklList != pkl, since pkl is unlocked. 01696 */ 01697 pkl->pklPrev->pklNext = pkl->pklNext; 01698 pkl->pklNext->pklPrev = pkl->pklPrev; 01699 01700 /* 01701 * Unlock its pkf 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 * Free the pkl itself. 01714 */ 01715 HMFreeObject(pkl); 01716 }

INT GetThreadsWithPKL PTHREADINFO **  ppptiList,
PKL  pkl
 

Definition at line 445 of file kbdlyout.c.

References gpepCSRSS, grpWinStaList, INT, NULL, PpiFromProcess, PTHREADINFO, tagDESKTOP::PtiList, tagTHREADINFO::ptiSibling, tagWINDOWSTATION::rpdeskList, tagDESKTOP::rpdeskNext, tagWINDOWSTATION::rpwinstaNext, and tagTHREADINFO::spklActive.

Referenced by xxxFreeImeKeyboardLayouts(), and xxxSetPKLinThreads().

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 * allocate a first list for 128 entries 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 // for all the winstations 00473 for (pwinsta = grpWinStaList; pwinsta != NULL ; pwinsta = pwinsta->rpwinstaNext) { 00474 00475 // for all the desktops in that winstation 00476 for (pdesk = pwinsta->rpdeskList; pdesk != NULL ; pdesk = pdesk->rpdeskNext) { 00477 00478 pHead = &pdesk->PtiList; 00479 00480 // for all the threads in that desktop 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)) { // #99321 cmp pkls, not hkls? 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 * add CSRSS threads 00519 */ 00520 for (ptiT = PpiFromProcess(gpepCSRSS)->ptiList; ptiT != NULL; ptiT = ptiT->ptiSibling) { 00521 00522 if (pkl && (pkl != ptiT->spklActive)) { // #99321 cmp pkls, not hkls? 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 }

PKL HKLtoPKL PTHREADINFO  pti,
HKL  hkl
 

Definition at line 40 of file kbdlyout.c.

References tagKL::dwKL_Flags, tagKL::hkl, KL_UNLOADED, NULL, tagKL::pklNext, tagKL::pklPrev, and tagTHREADINFO::spklActive.

Referenced by NtUserMapVirtualKeyEx(), NtUserSetThreadLayoutHandles(), NtUserVkKeyScanEx(), xxxActivateKeyboardLayout(), xxxFreeKeyboardLayouts(), xxxInternalToUnicode(), xxxInternalUnloadKeyboardLayout(), xxxLoadKeyboardLayoutEx(), xxxScanSysQueue(), xxxSystemParametersInfo(), and xxxUnloadKeyboardLayout().

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 * Find the pkl for this hkl. 00074 * If the kbd layout isn't specified (in the HIWORD), ignore it and look 00075 * for a Locale match only. (Mohamed Hamid's fix for Word bug) 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 }

PKBDFILE LoadKeyboardLayoutFile HANDLE  hFile,
UINT  offTable,
LPCWSTR  pwszKLID
 

Definition at line 316 of file kbdlyout.c.

References tagKBDFILE::awchKF, gpkfList, HMAllocObject(), HMFreeObject(), NULL, tagKBDFILE::pKbdNlsTbl, tagKBDFILE::pKbdTbl, tagKBDFILE::pkfNext, PrepareFallbackKeyboardFile(), ReadLayoutFile(), TYPE_KBDFILE, and wcsncpycch().

Referenced by xxxLoadKeyboardLayoutEx().

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 * The layout is already loaded. 00332 */ 00333 return pkf; 00334 } 00335 pkf = pkf->pkfNext; 00336 } while (pkf); 00337 } 00338 00339 /* 00340 * Allocate a new Keyboard File structure. 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 * Load layout table. 00350 */ 00351 if (hFile != NULL) { 00352 /* 00353 * Load NLS layout table also... 00354 */ 00355 pkf->pKbdTbl = ReadLayoutFile(pkf, hFile, offTable, &(pkf->pKbdNlsTbl)); 00356 } else { 00357 /* 00358 * We failed to open the keyboard layout file in client side 00359 * because the dll was missing. 00360 * If this ever happens, we used to fail creating 00361 * a window station, but we should allow a user 00362 * at least to boot the system. 00363 */ 00364 pkf->pKbdTbl = PrepareFallbackKeyboardFile(pkf); 00365 // Note: pkf->pKbdNlsTbl has been NULL'ed in PrepareFallbackKeyboardFile() 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 * Put keyboard layout file at front of list. 00377 */ 00378 pkf->pkfNext = gpkfList; 00379 gpkfList = pkf; 00380 00381 return pkf; 00382 }

PKBDTABLES PrepareFallbackKeyboardFile PKBDFILE  pkf  ) 
 

Definition at line 293 of file kbdlyout.c.

References tagKBDFILE::hBase, KbdTablesFallback, NULL, PBYTE, and tagKBDFILE::pKbdNlsTbl.

Referenced by LoadKeyboardLayoutFile().

00294 { 00295 PBYTE pBaseDst; 00296 00297 pBaseDst = UserAllocPool(sizeof(KBDTABLES), TAG_KBDTABLE); 00298 if (pBaseDst != NULL) { 00299 RtlCopyMemory(pBaseDst, &KbdTablesFallback, sizeof KbdTablesFallback); 00300 // Note: Unlike ReadLayoutFile(), 00301 // we don't need to fix up pointers in struct KBDFILE. 00302 } 00303 pkf->hBase = (HANDLE)pBaseDst; 00304 pkf->pKbdNlsTbl = NULL; 00305 return (PKBDTABLES)pBaseDst; 00306 }

PKBDTABLES ReadLayoutFile PKBDFILE  pkf,
HANDLE  hFile,
UINT  offTable,
PKBDNLSTABLES *  ppNlsTables
 

Definition at line 106 of file kbdlyout.c.

References DbgPrint, DWORD, FIXUP_PTR, tagKBDFILE::hBase, ISTS, NT_SUCCESS, NTSTATUS(), NULL, PBYTE, tagKBDFILE::Size, Status, and UINT.

Referenced by LoadKeyboardLayoutFile().

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 * Mask off hiword. 00127 */ 00128 offTable &= 0x0000FFFF; 00129 00130 /* 00131 * Initialize KbdNlsTables with NULL. 00132 */ 00133 *ppNlsTables = NULL; 00134 00135 /* 00136 * Map the layout file into memory 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 * HACK Part 2! We find the .data section in the file header 00152 * and by subtracting the virtual address from offTable find 00153 * the offset in the section of the layout table. 00154 */ 00155 NtHeader = (PIMAGE_NT_HEADERS)((PBYTE)DosHdr + (ULONG)DosHdr->e_lfanew); 00156 00157 /* 00158 * Build the next subsections. 00159 */ 00160 NumberOfSubsections = NtHeader->FileHeader.NumberOfSections; 00161 00162 /* 00163 * At this point the object table is read in (if it was not 00164 * already read in) and may displace the image header. 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 * We found the section, now compute starting offset and the table size. 00185 */ 00186 offTable -= SectionTableEntry->VirtualAddress; 00187 dwDataSize = SectionTableEntry->Misc.VirtualSize; 00188 00189 /* 00190 * Allocate layout table and copy from file. 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; // For shadow hotkey processing 00204 } 00205 00206 /* 00207 * Compute table address and fixup pointers in table. 00208 */ 00209 pktNew = (PKBDTABLES)(pBaseDst + offTable); 00210 00211 /* 00212 * The address in the data section has the virtual address 00213 * added in, so we need to adjust the fixup pointer to 00214 * compensate. 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 * Version 1 layouts support ligatures. 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 * Compute table address and fixup pointers in table. 00252 */ 00253 offNlsTable -= SectionTableEntry->VirtualAddress; 00254 pknlstNew = (PKBDNLSTABLES)(pBaseDst + offNlsTable); 00255 00256 /* 00257 * Fixup the address. 00258 */ 00259 FIXUP_PTR(pknlstNew->pVkToF, pBaseVirt); 00260 FIXUP_PTR(pknlstNew->pusMouseVKey, pBaseVirt); 00261 00262 /* 00263 * Save the pointer. 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 * Unmap and release the mapped section. 00286 */ 00287 ZwUnmapViewOfSection(NtCurrentProcess(), DosHdr); 00288 ZwClose(hmap); 00289 00290 return pktNew; 00291 }

VOID RemoveKeyboardLayoutFile PKBDFILE  pkf  ) 
 

Definition at line 390 of file kbdlyout.c.

References gpKbdNlsTbl, gpKbdTbl, gpkfList, KbdTablesFallback, NULL, tagKBDFILE::pKbdNlsTbl, tagKBDFILE::pKbdTbl, tagKBDFILE::pkfNext, and VOID().

Referenced by DestroyKF().

00392 { 00393 PKBDFILE pkfPrev, pkfCur; 00394 00395 // FE: NT4 SP4 #107809 00396 if (gpKbdTbl == pkf->pKbdTbl) { 00397 gpKbdTbl = &KbdTablesFallback; 00398 } 00399 if (gpKbdNlsTbl == pkf->pKbdNlsTbl) { 00400 gpKbdNlsTbl = NULL; 00401 } 00402 00403 /* 00404 * Good old linked list management 101 00405 */ 00406 if (pkf == gpkfList) { 00407 /* 00408 * Head of the list. 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 * Found it! 00421 */ 00422 pkfPrev->pkfNext = pkfCur->pkfNext; 00423 }

VOID ReorderKeyboardLayouts PWINDOWSTATION  ,
PKL 
 

Definition at line 944 of file kbdlyout.c.

References tagWINDOWSTATION::dwWSF_Flags, Lock, NULL, tagKL::pklNext, tagKL::pklPrev, tagWINDOWSTATION::spklList, VOID(), and WSF_NOIO.

Referenced by xxxActivateKeyboardLayout(), and xxxLoadKeyboardLayoutEx().

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 * If the layout is already at the front of the list there's nothing to do. 00960 */ 00961 if (pkl == pklFirst) { 00962 return; 00963 } 00964 /* 00965 * Cut pkl from circular list: 00966 */ 00967 pkl->pklPrev->pklNext = pkl->pklNext; 00968 pkl->pklNext->pklPrev = pkl->pklPrev; 00969 00970 /* 00971 * Insert pkl at front of list 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 }

void ResetPushState PTHREADINFO  pti,
UINT  uVk
 

Definition at line 1059 of file kbdlyout.c.

References ClearAsyncKeyStateDown, ClearKeyStateDown, ClearKeyStateToggle, ClearRawKeyDown, ClearRawKeyToggle, and tagTHREADINFO::pq.

Referenced by AdjustPushState(), and xxxInternalActivateKeyboardLayout().

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 }

HKL xxxActivateKeyboardLayout PWINDOWSTATION  pwinsta,
HKL  hkl,
UINT  Flags,
PWND  pwnd
 

Definition at line 916 of file kbdlyout.c.

References CheckLock, HKLtoPKL(), NULL, PtiCurrent, ReorderKeyboardLayouts(), ThreadLockAlwaysWithPti, ThreadUnlock, and xxxInternalActivateKeyboardLayout().

Referenced by NtUserActivateKeyboardLayout(), and xxxDefWindowProc().

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 }

VOID xxxFreeImeKeyboardLayouts PWINDOWSTATION  pwinsta  ) 
 

Definition at line 627 of file kbdlyout.c.

References tagWINDOWSTATION::dwWSF_Flags, GetThreadsWithPKL(), IFL_UNLOADIME, INT, NULL, VOID(), WSF_NOIO, and xxxImmUnloadThreadsLayout().

Referenced by xxxLoadKeyboardLayoutEx().

00629 { 00630 PTHREADINFO *pptiList; 00631 INT cThreads; 00632 00633 if (pwinsta->dwWSF_Flags & WSF_NOIO) 00634 return; 00635 00636 /* 00637 * should make GetThreadsWithPKL aware of pwinsta? 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 }

VOID xxxFreeKeyboardLayouts PWINDOWSTATION  pwinsta,
BOOL  bUnlock
 

Definition at line 1647 of file kbdlyout.c.

References HKLtoPKL(), NULL, PtiCurrent, tagWINDOWSTATION::spklList, Unlock, VOID(), and xxxInternalUnloadKeyboardLayout().

Referenced by xxxLoadKeyboardLayoutEx().

01649 { 01650 PKL pkl; 01651 01652 /* 01653 * Unload all of the windowstation's layouts. 01654 * They may still be locked by some threads (eg: console), so this 01655 * may not destroy them all, but it will mark them all KL_UNLOADED. 01656 * Set KLF_INITTIME to ensure that the default layout (gspklBaseLayout) 01657 * gets unloaded too. 01658 * Note: it's much faster to unload non-active layouts, so start with 01659 * the next loaded layout, leaving the active layout till last. 01660 */ 01661 while ((pkl = HKLtoPKL(PtiCurrent(), (HKL)HKL_NEXT)) != NULL) { 01662 xxxInternalUnloadKeyboardLayout(pwinsta, pkl, KLF_INITTIME); 01663 } 01664 01665 /* 01666 * The WindowStation is being destroyed, or one user's layouts are being 01667 * replaced by another user's, so it's OK to Unlock spklList. 01668 * Any layout still in the double-linked circular KL list will still be 01669 * pointed to by gspklBaseLayout: this is important, since we don't want 01670 * to leak any KL or KBDFILE objects by losing pointers to them. 01671 * There are no layouts when we first come here (during bootup). 01672 */ 01673 if (bUnlock) { 01674 Unlock(&pwinsta->spklList); 01675 } 01676 }

HKL xxxInternalActivateKeyboardLayout PKL  pkl,
UINT  Flags,
PWND  pwnd
 

Definition at line 1203 of file kbdlyout.c.

References AdjustPushStateForKL(), tagQ::afKeyState, BOOL, BYTE, CBKEYSTATE, ChangeForegroundKeyboardTable(), CheckLock, _CLIENTINFO::CodePage, tagKL::CodePage, FALSE, gafAsyncKeyState, gafRawKeyState, gdwKeyboardAttributes, gLCIDSentToShell, gpepCSRSS, gptiForeground, gptiRit, grpdeskRitInput, tagKL::hkl, _CLIENTINFO::hKL, tagKL::iBaseCharset, IS_IME_ENABLED, IS_IME_KBDLAYOUT, IsHooked, Lock, NULL, tagTHREADINFO::pClientInfo, tagKBDFILE::pKbdTbl, tagTHREADINFO::ppi, tagTHREADINFO::pq, PsGetCurrentProcess, PtiCurrent, tagDESKTOP::PtiList, tagPROCESSINFO::ptiList, tagTHREADINFO::ptiSibling, ResetPushState(), tagKL::spkf, tagTHREADINFO::spklActive, tagQ::spwndActive, tagTHREADINFO::spwndDefaultIme, tagQ::spwndFocus, ThreadLockAlwaysWithPti, ThreadLockWithPti, ThreadUnlock, TIF_16BIT, TIF_CSRSSTHREAD, tagTHREADINFO::TIF_flags, TIF_INCLEANUP, TRUE, tagKL::wchDiacritic, WHF_SHELL, xxxCallHook(), xxxImmActivateLayout(), xxxImmActivateThreadsLayout(), and xxxSendMessage().

Referenced by xxxActivateKeyboardLayout(), xxxInternalUnloadKeyboardLayout(), and xxxLoadKeyboardLayoutEx().

01207 { 01208 HKL hklPrev; 01209 PKL pklPrev; 01210 TL tlpklPrev; 01211 PTHREADINFO ptiCurrent = PtiCurrent(); 01212 01213 CheckLock(pkl); 01214 CheckLock(pwnd); 01215 01216 /* 01217 * Remember what is about to become the "previously" active hkl 01218 * for the return value. 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 * ShiftLock/CapsLock is a global feature applying to all layouts 01230 * Only Winlogon and the Input Locales cpanel applet set KLF_RESET. 01231 */ 01232 if (Flags & KLF_RESET) { 01233 gdwKeyboardAttributes = KLL_GLOBAL_ATTR_FROM_KLF(Flags); 01234 } 01235 01236 /* 01237 * Early out 01238 */ 01239 if (!(Flags & KLF_SETFORPROCESS) && (pkl == ptiCurrent->spklActive)) { 01240 return hklPrev; 01241 } 01242 01243 /* 01244 * Clear out diacritics when switching kbd layouts #102838 01245 */ 01246 pkl->wchDiacritic = 0; 01247 01248 /* 01249 * Update the active layout in the pti. KLF_SETFORPROCESS will always be set 01250 * when the keyboard layout switch is initiated by the keyboard hotkey. 01251 */ 01252 01253 /* 01254 * Lock the previous keyboard layout for it's used later. 01255 */ 01256 ThreadLockWithPti(ptiCurrent, pklPrev, &tlpklPrev); 01257 01258 /* 01259 * Is this is a console thread, apply this change to any process in it's 01260 * window. This can really help character-mode apps! (#58025) 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 * For 16 bit app., only the calling thread will have its active layout updated. 01286 */ 01287 PTHREADINFO ptiT; 01288 01289 if (IS_IME_ENABLED()) { 01290 /* 01291 * Only allow *NOT* CSRSS to make this call 01292 */ 01293 UserAssert(PsGetCurrentProcess() != gpepCSRSS); 01294 // pti->pClientInfo is updated in xxxImmActivateThreadsLayout() 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 * Some keys (pressed to switch layout) may still be down. When these come 01332 * back up, they may have different VK values due to the new layout, so the 01333 * original key will be left stuck down. (eg: an ISV layout from Attachmate 01334 * and the CAN/CSA layout, both of which redefine the right-hand Ctrl key's 01335 * VK so switching to that layout with right Ctrl+Shift will leave the Ctrl 01336 * stuck down). 01337 * The solution is to clear all the keydown bits whenever we switch layouts 01338 * (leaving the toggle bits alone to preserve CapsLock, NumLock etc.). This 01339 * also solves the AltGr problem, where the simulated Ctrl key doesn't come 01340 * back up if we switch to a non-AltGr layout before releasing AltGr - IanJa 01341 * 01342 * Clear down bits only if necessary --- i.e. if the VK value differs between 01343 * old and new keyboard layout. We have to take complex path for some of the 01344 * keys, like Ctrl or Alt, may have left and right equivalents. - HiroYama 01345 */ 01346 if (ptiCurrent->pq) { 01347 if (pklPrev) { 01348 BYTE baDone[256 / 8]; 01349 01350 RtlZeroMemory(baDone, sizeof baDone); 01351 01352 /* 01353 * Clear the toggle state if needed. First check the modifier keys 01354 * of pklPrev. Next check the modifier keys of pklNew. 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 * If the previous keyboard has AltGr, clear the left control anyway. 01363 * See xxxAltGr(). 01364 */ 01365 TAGMSG0(DBGTAG_IMM, "Clearing VK_LCONTROL for AltGr\n"); 01366 ResetPushState(ptiCurrent, VK_LCONTROL); 01367 } 01368 } 01369 else { 01370 /* 01371 * If the current keyboard is unkown, clear all the push state. 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 * Call the Shell hook with the new language. 01384 */ 01385 if (gptiForeground && (gptiForeground->ppi == ptiCurrent->ppi)) { 01386 ChangeForegroundKeyboardTable(pklPrev, pkl); 01387 01388 /* 01389 * Only call the hook if we are the foreground process, to prevent 01390 * background apps from changing the indicator. (All console apps 01391 * are part of the same process, but I have never seen a cmd window 01392 * app change the layout, let alone in the background) 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 * Tell the app what happened 01404 */ 01405 if (ptiCurrent->pq) { 01406 PWND pwndT; 01407 TL tlpwndT; 01408 01409 /* 01410 * If we have no Focus window, use the Active window. 01411 * eg: Console full-screen has NULL focus window. 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 * Tell IME to send mode update notification 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 }

BOOL xxxInternalUnloadKeyboardLayout PWINDOWSTATION  ,
PKL  ,
UINT 
 

Definition at line 1571 of file kbdlyout.c.

References BOOL, tagKL::dwKL_Flags, FALSE, gLCIDSentToShell, gspklBaseLayout, HKLtoPKL(), HMMarkObjectDestroy(), IsHooked, KL_UNLOADED, Lock, NULL, tagKL::pklNext, PtiCurrent, tagTHREADINFO::spklActive, tagWINDOWSTATION::spklList, ThreadLockAlwaysWithPti, ThreadUnlock, TRUE, WHF_SHELL, xxxCallHook(), and xxxInternalActivateKeyboardLayout().

Referenced by xxxFreeKeyboardLayouts(), xxxLoadKeyboardLayoutEx(), and xxxUnloadKeyboardLayout().

01575 { 01576 PTHREADINFO ptiCurrent = PtiCurrent(); 01577 TL tlpkl; 01578 01579 UserAssert(pkl); 01580 01581 /* 01582 * Never unload the default layout, unless we are destroying the current 01583 * windowstation or replacing one user's layouts with another's. 01584 */ 01585 if ((pkl == gspklBaseLayout) && !(Flags & KLF_INITTIME)) { 01586 return FALSE; 01587 } 01588 01589 /* 01590 * Keeps pkl good, but also allows destruction when unlocked later 01591 */ 01592 ThreadLockAlwaysWithPti(ptiCurrent, pkl, &tlpkl); 01593 01594 /* 01595 * Mark it for destruction so it gets removed when the lock count reaches 0 01596 * Mark it KL_UNLOADED so that it appears to be gone from the toggle list 01597 */ 01598 HMMarkObjectDestroy(pkl); 01599 pkl->dwKL_Flags |= KL_UNLOADED; 01600 01601 /* 01602 * If unloading this thread's active layout, helpfully activate the next one 01603 * (Don't bother if KLF_INITTIME - unloading all previous user's layouts) 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 * If this pkl == pwinsta->spklList, give it a chance to be destroyed by 01621 * unlocking it from pwinsta->spklList. 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); // gspklBaseLayout and ThreadLocked pkl 01628 } 01629 } 01630 01631 /* 01632 * This finally destroys the unloaded layout if it is not in use anywhere 01633 */ 01634 ThreadUnlock(&tlpkl); 01635 01636 /* 01637 * Update keyboard list. 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 }

HKL xxxLoadKeyboardLayoutEx PWINDOWSTATION  pwinsta,
HANDLE  hFile,
HKL  hklToBeReplaced,
UINT  offTable,
LPCWSTR  pwszKLID,
UINT  KbdInputLocale,
UINT  Flags
 

Definition at line 654 of file kbdlyout.c.

References _HANDLEENTRY::bFlags, BOOL, BYTE, tagKL::CodePage, tagKL::dwFontSigs, tagKL::dwKL_Flags, tagWINDOWSTATION::dwWSF_Flags, FALSE, gLCIDSentToShell, gpidLogon, gspklBaseLayout, gSystemCPCharSet, gSystemFS, HANDLEF_DESTROY, HANDLEF_MARKED_OK, tagKBDFILE::hBase, tagKL::hkl, HKLtoPKL(), HMAllocObject(), HMMarkObjectDestroy(), HMPheFromObject, HMUnlockObject, tagKL::iBaseCharset, IS_IME_KBDLAYOUT, IsHooked, KL_UNLOADED, LoadKeyboardLayoutFile(), Lock, NULL, tagKL::piiex, tagKBDFILE::pKbdTbl, tagKL::pklNext, tagKL::pklPrev, PtiCurrent, ReorderKeyboardLayouts(), RtlInitUnicodeString(), RtlUnicodeStringToInteger(), tagKL::spkf, tagWINDOWSTATION::spklList, ThreadLockAlwaysWithPti, ThreadUnlock, TYPE_KBDLAYOUT, tagKL::wchDiacritic, WHF_SHELL, WSF_NOIO, xxxCallHook(), xxxClientGetCharsetInfo(), xxxFreeImeKeyboardLayouts(), xxxFreeKeyboardLayouts(), xxxImmLoadLayout(), xxxInternalActivateKeyboardLayout(), xxxInternalUnloadKeyboardLayout(), and xxxSetPKLinThreads().

Referenced by NtUserLoadKeyboardLayoutEx(), and xxxCreateWindowStation().

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 * If the windowstation does not do I/O, don't load the 00675 * layout. Also check KdbInputLocale for #307132 00676 */ 00677 if ((KbdInputLocale == 0) || (pwinsta->dwWSF_Flags & WSF_NOIO)) { 00678 return NULL; 00679 } 00680 00681 /* 00682 * If hklToBeReplaced is non-NULL make sure it's valid. 00683 * NOTE: may want to verify they're not passing HKL_NEXT or HKL_PREV. 00684 */ 00685 ptiCurrent = PtiCurrent(); 00686 if (hklToBeReplaced && !(pklToBeReplaced = HKLtoPKL(ptiCurrent, hklToBeReplaced))) { 00687 return NULL; 00688 } 00689 if (KbdInputLocale == HandleToUlong(hklToBeReplaced)) { 00690 /* 00691 * Replacing a layout/lang pair with itself. Nothing to do. 00692 */ 00693 return pklToBeReplaced->hkl; 00694 } 00695 00696 if (Flags & KLF_RESET) { 00697 /* 00698 * Only WinLogon can use this flag 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 * Make sure we don't lose track of the left-over layouts 00708 * They have been unloaded, but are still in use by some threads). 00709 * The FALSE will prevent xxxFreeKeyboardLayouts from unlocking the 00710 * unloaded layouts. 00711 */ 00712 xxxFreeKeyboardLayouts(pwinsta, FALSE); 00713 } 00714 00715 /* 00716 * Does this hkl already exist? 00717 */ 00718 pkl = pklFirst = pwinsta->spklList; 00719 00720 if (pkl) { 00721 do { 00722 if (pkl->hkl == (HKL)IntToPtr( KbdInputLocale )) { 00723 /* 00724 * The hkl already exists. 00725 */ 00726 00727 /* 00728 * If it is unloaded (but not yet destroyed because it is 00729 * still is use), recover it. 00730 */ 00731 if (pkl->dwKL_Flags & KL_UNLOADED) { 00732 // stop it from being destroyed if not is use. 00733 PHE phe = HMPheFromObject(pkl); 00734 // An unloaded layout must be marked for destroy. 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 * If it was already loaded and we didn't change all layouts 00744 * with KLF_RESET, there is nothing to tell the shell about 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 * This is an IME keyboard layout, do a callback 00758 * to read the extended IME information structure. 00759 * Note: We can't fail the call so easily if 00760 * KLF_RESET is specified. 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 * Get the system font's font signature. These are 64-bit FS_xxx values, 00774 * but we are only asking for an ANSI ones, so gSystemFS is just a DWORD. 00775 * gSystemFS is consulted when posting WM_INPUTLANGCHANGEREQUEST (input.c) 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 * Use the Keyboard Layout's LCID to calculate the charset, codepage etc, 00792 * so that characters from that layout don't just becomes ?s if the input 00793 * locale doesn't match. This allows "dumb" applications to display the 00794 * text if the user chooses the right font. 00795 * We can't just use the HIWORD of KbdInputLocale because if a variant 00796 * keyboard layout was chosen, this will be something like F008 - have to 00797 * look inside the KF to get the real LCID of the kbdfile: this will be 00798 * something like L"00010419", and we want the last 4 digits. 00799 */ 00800 RtlInitUnicodeString(&strLcidKF, pwszKLID + 4); 00801 RtlUnicodeStringToInteger(&strLcidKF, 16, (PULONG)&lcidKF); 00802 bCharSet = xxxClientGetCharsetInfo(lcidKF, &cs); 00803 00804 /* 00805 * Keyboard Layout Handle object does not exist. Load keyboard layout file, 00806 * if not already loaded. 00807 */ 00808 if (!(pkf = LoadKeyboardLayoutFile(hFile, offTable, pwszKLID))) { 00809 goto freePiiex; 00810 } 00811 /* 00812 * Allocate a new Keyboard Layout structure (hkl) 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 * Link to itself in case we have to DestroyKL 00829 */ 00830 pkl->pklNext = pkl; 00831 pkl->pklPrev = pkl; 00832 00833 /* 00834 * Init KL 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]; // font signature mask (FS_xxx values) 00848 pkl->iBaseCharset = cs.ciCharset; // charset value 00849 } else { 00850 pkl->CodePage = CP_ACP; 00851 pkl->dwFontSigs = FS_LATIN1; 00852 pkl->iBaseCharset = ANSI_CHARSET; 00853 } 00854 00855 /* 00856 * Insert KL in the double-linked circular list, at the end. 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 // FE_IME 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 * Use the hkl as the layout handle 00907 * If the KL is freed somehow, return NULL for safety. -- ianja -- 00908 */ 00909 pkl = ThreadUnlock(&tlpkl); 00910 if (pkl == NULL) { 00911 return NULL; 00912 } 00913 return pkl->hkl; 00914 }

VOID xxxSetPKLinThreads PKL  pklNew,
PKL  pklToBeReplaced
 

Definition at line 560 of file kbdlyout.c.

References ChangeForegroundKeyboardTable(), CheckLock, GetThreadsWithPKL(), gptiForeground, INT, Lock, NULL, tagKL::pklNext, tagKL::pklPrev, tagTHREADINFO::spklActive, VOID(), and xxxImmActivateAndUnloadThreadsLayout().

Referenced by xxxLoadKeyboardLayoutEx().

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 * Will the foreground thread's keyboard layout change? 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 * This is a replace. First, deactivate the *replaced* IME by 00589 * activating the pklNew. Second, unload the *replaced* IME. 00590 */ 00591 xxxImmActivateAndUnloadThreadsLayout(pptiList, cThreads, NULL, 00592 pklNew, HandleToUlong(pklToBeReplaced->hkl)); 00593 } 00594 UserFreePool(pptiList); 00595 } 00596 00597 /* 00598 * If this is a replace, link the new layout immediately after the 00599 * layout being replaced. This maintains ordering of layouts when 00600 * the *replaced* layout is unloaded. The input locale panel in the 00601 * regional settings applet depends on this. 00602 */ 00603 if (pklToBeReplaced) { 00604 if (pklToBeReplaced->pklNext == pklNew) { 00605 /* 00606 * Ordering already correct. Nothing to do. 00607 */ 00608 return; 00609 } 00610 /* 00611 * Move new layout immediately after layout being replaced. 00612 * 1. Remove new layout from current position. 00613 * 2. Update links in new layout. 00614 * 3. Link new layout into desired position. 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 }

BOOL xxxUnloadKeyboardLayout PWINDOWSTATION  pwinsta,
HKL  hkl
 

Definition at line 1451 of file kbdlyout.c.

References BOOL, FALSE, HKLtoPKL(), NULL, PtiCurrent, and xxxInternalUnloadKeyboardLayout().

Referenced by NtUserUnloadKeyboardLayout().

01454 { 01455 PKL pkl; 01456 01457 /* 01458 * Validate HKL and check to make sure an app isn't attempting to unload a system 01459 * preloaded layout. 01460 */ 01461 pkl = HKLtoPKL(PtiCurrent(), hkl); 01462 if (pkl == NULL) { 01463 return FALSE; 01464 } 01465 01466 return xxxInternalUnloadKeyboardLayout(pwinsta, pkl, 0); 01467 }


Generated on Sat May 15 19:44:24 2004 for test by doxygen 1.3.7