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

ntimm.c File Reference

#include "precomp.h"

Go to the source code of this file.

Functions

PIMC CreateInputContext (ULONG_PTR dwClientImcData)
BOOL DestroyInputContext (IN PIMC pImc)
VOID FreeInputContext (IN PIMC pImc)
BOOL UpdateInputContext (IN PIMC pImc, IN UPDATEINPUTCONTEXTCLASS UpdateType, IN ULONG_PTR UpdateValue)
HIMC AssociateInputContext (IN PWND pWnd, IN PIMC pImc)
AIC_STATUS AssociateInputContextEx (IN PWND pWnd, IN PIMC pImc, IN DWORD dwFlag)
VOID xxxFocusSetInputContext (IN PWND pWnd, IN BOOL fActivate, IN BOOL fQueueMsg)
UINT BuildHimcList (PTHREADINFO pti, UINT cHimcMax, HIMC *ccxphimcFirst)
PWND xxxCreateDefaultImeWindow (IN PWND pwnd, IN ATOM atomT, IN HANDLE hInst)
BOOL xxxImmActivateThreadsLayout (PTHREADINFO pti, PTLBLOCK ptlBlockPrev, PKL pkl)
VOID xxxImmActivateAndUnloadThreadsLayout (IN PTHREADINFO *ptiList, IN UINT nEntries, IN PTLBLOCK ptlBlockPrev, PKL pklCurrent, DWORD dwHklReplace)
VOID xxxImmActivateLayout (IN PTHREADINFO pti, IN PKL pkl)
VOID xxxImmUnloadThreadsLayout (IN PTHREADINFO *ptiList, IN UINT nEntries, IN PTLBLOCK ptlBlockPrev, IN DWORD dwFlag)
VOID xxxImmUnloadLayout (IN PTHREADINFO pti, IN DWORD dwFlag)
PIMEINFOEX xxxImmLoadLayout (IN HKL hKL)
BOOL GetImeInfoEx (PWINDOWSTATION pwinsta, PIMEINFOEX piiex, IMEINFOEXCLASS SearchType)
BOOL SetImeInfoEx (PWINDOWSTATION pwinsta, PIMEINFOEX piiex)
DWORD xxxImmProcessKey (IN PQ pq, IN PWND pwnd, IN UINT message, IN WPARAM wParam, IN LPARAM lParam)
BOOL ImeCanDestroyDefIME (PWND pwndDefaultIme, PWND pwndDestroy)
BOOL IsChildSameThread (PWND pwndParent, PWND pwndChild)
BOOL ImeCanDestroyDefIMEforChild (PWND pwndDefaultIme, PWND pwndDestroy)
VOID ImeCheckTopmost (PWND pwndIme)
VOID ImeSetFutureOwner (PWND pwndIme, PWND pwndOrgOwner)
VOID ImeSetTopmostChild (PWND pwndParent, BOOL fMakeTopmost)
PWND GetLastTopMostWindowNoIME (PWND pwndRoot)
VOID ImeSetTopmost (PWND pwndRootIme, BOOL fMakeTopmost, PWND pwndInsertBefore)
PSOFTKBDDATA ProbeAndCaptureSoftKbdData (PSOFTKBDDATA Source)
VOID SetConvMode (PTHREADINFO pti, DWORD dwConversion)
VOID xxxNotifyIMEStatus (IN PWND pwnd, IN DWORD dwOpen, IN DWORD dwConversion)
BOOL xxxCheckImeShowStatus (PWND pwndIme, PTHREADINFO pti)
LRESULT xxxSendMessageToUI (PTHREADINFO ptiIme, PIMEUI pimeui, UINT message, WPARAM wParam, LPARAM lParam)
VOID xxxSendOpenStatusNotify (PTHREADINFO ptiIme, PIMEUI pimeui, PWND pwndApp, BOOL fOpen)
VOID xxxNotifyImeShowStatus (PWND pwndIme)
BOOL xxxSetIMEShowStatus (IN BOOL fShow)
VOID xxxBroadcastImeShowStatusChange (PWND pwndIme, BOOL fShow)
VOID xxxCheckImeShowStatusInThread (PWND pwndIme)
BOOL _GetIMEShowStatus (VOID)

Variables

CONST WCHAR wszDefaultIme [] = L"Default IME"


Function Documentation

BOOL _GetIMEShowStatus VOID   ) 
 

Definition at line 2705 of file ntimm.c.

References BOOL, FALSE, and gfIMEShowStatus.

Referenced by xxxSystemParametersInfo().

02706 { 02707 return gfIMEShowStatus != FALSE; 02708 }

HIMC AssociateInputContext IN PWND  pWnd,
IN PIMC  pImc
 

Definition at line 289 of file ntimm.c.

References PtoH.

Referenced by AssociateInputContextEx(), and DestroyInputContext().

00292 { 00293 HIMC hImcRet = pWnd->hImc; 00294 pWnd->hImc = (HIMC)PtoH(pImc); 00295 00296 return hImcRet; 00297 }

AIC_STATUS AssociateInputContextEx IN PWND  pWnd,
IN PIMC  pImc,
IN DWORD  dwFlag
 

Definition at line 299 of file ntimm.c.

References AIC_ERROR, AIC_FOCUSCONTEXTCHANGED, AIC_STATUS, AIC_SUCCESS, AssociateInputContext(), BOOL, BuildHwndList(), BWL_ENUMCHILDREN, BWL_ENUMLIST, FreeHwndList(), GETPTI, tagWND::hImc, NULL, NULL_HIMC, tagTHREADINFO::pq, PtiCurrent, PtoH, RevalidateHwnd, tagBWL::rghwnd, tagTHREADINFO::spDefaultImc, tagQ::spwndFocus, and Status.

Referenced by NtUserAssociateInputContext().

00303 { 00304 PTHREADINFO ptiWnd = GETPTI(pWnd); 00305 PWND pWndFocus = ptiWnd->pq->spwndFocus; 00306 HIMC hImcFocus = pWndFocus->hImc; 00307 BOOL fIgnoreNoContext = (dwFlag & IACE_IGNORENOCONTEXT) == IACE_IGNORENOCONTEXT; 00308 AIC_STATUS Status = AIC_SUCCESS; 00309 00310 if (dwFlag & IACE_DEFAULT) { 00311 /* 00312 * use default input context. 00313 */ 00314 pImc = ptiWnd->spDefaultImc; 00315 00316 } else if (pImc != NULL && GETPTI(pImc) != ptiWnd) { 00317 /* 00318 * Cannot associate input context to window created 00319 * by other thread. 00320 */ 00321 RIPERR0(ERROR_ACCESS_DENIED, RIP_WARNING, 00322 "AssociateInputContextEx: pwnd not of Imc pti"); 00323 return AIC_ERROR; 00324 } 00325 00326 /* 00327 * Cannot do association under different process context. 00328 */ 00329 if (GETPTI(pWnd)->ppi != PtiCurrent()->ppi) { 00330 RIPERR0(ERROR_ACCESS_DENIED, RIP_WARNING, 00331 "AssociateInputContextEx: pwnd not of current ppi"); 00332 return AIC_ERROR; 00333 } 00334 00335 /* 00336 * Finally, make sure they are on the same desktop. 00337 */ 00338 if (pImc != NULL && pImc->head.rpdesk != pWnd->head.rpdesk) { 00339 RIPERR0(ERROR_ACCESS_DENIED, RIP_WARNING, 00340 "AssociateInputContextEx: no desktop access"); 00341 return AIC_ERROR; 00342 } 00343 00344 /* 00345 * If IACE_CHILDREN is specified, associate the input context 00346 * to the child windows of pWnd as well. 00347 */ 00348 if ((dwFlag & IACE_CHILDREN) && pWnd->spwndChild != NULL) { 00349 PBWL pbwl; 00350 PWND pwndT; 00351 HWND *phwndT; 00352 00353 pbwl = BuildHwndList(pWnd->spwndChild, 00354 BWL_ENUMLIST|BWL_ENUMCHILDREN, ptiWnd); 00355 00356 if (pbwl != NULL) { 00357 00358 for (phwndT = pbwl->rghwnd; *phwndT != (HWND)1; phwndT++) { 00359 /* 00360 * Make sure this hwnd is still around. 00361 */ 00362 if ((pwndT = RevalidateHwnd(*phwndT)) == NULL) 00363 continue; 00364 00365 if (pwndT->hImc == (HIMC)PtoH(pImc)) 00366 continue; 00367 00368 if (pwndT->hImc == NULL_HIMC && fIgnoreNoContext) 00369 continue; 00370 00371 AssociateInputContext(pwndT, pImc); 00372 00373 if (pwndT == pWndFocus) 00374 Status = AIC_FOCUSCONTEXTCHANGED; 00375 } 00376 00377 FreeHwndList(pbwl); 00378 } 00379 } 00380 00381 /* 00382 * Associate the input context to pWnd. 00383 */ 00384 if (pWnd->hImc != NULL_HIMC || !fIgnoreNoContext) { 00385 if (pWnd->hImc != (HIMC)PtoH(pImc)) { 00386 AssociateInputContext(pWnd, pImc); 00387 if (pWnd == pWndFocus) 00388 Status = AIC_FOCUSCONTEXTCHANGED; 00389 } 00390 } 00391 00392 return Status; 00393 }

UINT BuildHimcList PTHREADINFO  pti,
UINT  cHimcMax,
HIMC *  ccxphimcFirst
 

Definition at line 475 of file ntimm.c.

References FALSE, NULL, tagIMC::pImcNext, PtiCurrent, tagTHREADINFO::ptiSibling, PtoH, tagTHREADINFO::spDefaultImc, and UINT.

Referenced by ImmEnumInputContext(), and NtUserBuildHimcList().

00479 { 00480 PIMC pImcT; 00481 UINT i = 0; 00482 00483 if (pti == NULL) { 00484 /* 00485 * Build the list which contains all IMCs created by calling process. 00486 */ 00487 for (pti = PtiCurrent()->ppi->ptiList; pti != NULL; pti = pti->ptiSibling) { 00488 pImcT = pti->spDefaultImc; 00489 while (pImcT != NULL) { 00490 if (i < cHimcMax) { 00491 try { 00492 ccxphimcFirst[i] = (HIMC)PtoH(pImcT); 00493 } except (W32ExceptionHandler(FALSE, RIP_WARNING)) { 00494 } 00495 } 00496 i++; 00497 pImcT = pImcT->pImcNext; 00498 } 00499 } 00500 } 00501 else { 00502 /* 00503 * Build the list which contains all IMCs created by specified thread. 00504 */ 00505 pImcT = pti->spDefaultImc; 00506 while (pImcT != NULL) { 00507 if (i < cHimcMax) { 00508 try { 00509 ccxphimcFirst[i] = (HIMC)PtoH(pImcT); 00510 } except (W32ExceptionHandler(FALSE, RIP_WARNING)) { 00511 } 00512 } 00513 i++; 00514 pImcT = pImcT->pImcNext; 00515 } 00516 } 00517 00518 return i; 00519 }

PIMC CreateInputContext ULONG_PTR  dwClientImcData  ) 
 

Definition at line 40 of file ntimm.c.

References tagTHREADINFO::amdesk, tagIMC::dwClientImcData, HMAllocObject(), IS_IME_ENABLED, Lock, NULL, tagIMC::pImcNext, PtiCurrentShared, RETURN_IF_ACCESS_DENIED, tagTHREADINFO::rpdesk, tagTHREADINFO::spDefaultImc, TIF_DISABLEIME, tagTHREADINFO::TIF_flags, and TYPE_INPUTCONTEXT.

00042 { 00043 PTHREADINFO ptiCurrent; 00044 PIMC pImc; 00045 PDESKTOP pdesk = NULL; 00046 00047 ptiCurrent = PtiCurrentShared(); 00048 00049 /* 00050 * Only for thread that wants IME processing. 00051 */ 00052 if ((ptiCurrent->TIF_flags & TIF_DISABLEIME) || !IS_IME_ENABLED()) { 00053 RIPMSG1(RIP_VERBOSE, "CreateInputContext: TIF_DISABLEIME or !IME Enabled. pti=%#p", ptiCurrent); 00054 return NULL; 00055 } 00056 00057 /* 00058 * If pti->spDefaultImc is NULL (means this is the first instance) 00059 * but dwClientImcData is not 0, some bogus application like NtCrash 00060 * has tried to trick the kernel. Just bail out. 00061 */ 00062 if (dwClientImcData != 0 && ptiCurrent->spDefaultImc == NULL) { 00063 RIPMSG2(RIP_WARNING, "CreateInputContext: bogus value(0x%08x) is passed. pti=%#p", 00064 dwClientImcData, ptiCurrent); 00065 return NULL; 00066 } 00067 00068 /* 00069 * If the windowstation has been initialized, allocate from 00070 * the current desktop. 00071 */ 00072 pdesk = ptiCurrent->rpdesk; 00073 #ifdef LATER 00074 RETURN_IF_ACCESS_DENIED(ptiCurrent->amdesk, DESKTOP_CREATEINPUTCONTEXT, NULL); 00075 #else 00076 if (ptiCurrent->rpdesk == NULL) { 00077 return NULL; 00078 } 00079 #endif 00080 00081 pImc = HMAllocObject(ptiCurrent, pdesk, TYPE_INPUTCONTEXT, sizeof(IMC)); 00082 00083 if (pImc == NULL) { 00084 RIPMSG0(RIP_WARNING, "CreateInputContext: out of memory"); 00085 return NULL; 00086 } 00087 00088 if (dwClientImcData == 0) { 00089 /* 00090 * We are creating default input context for current thread. 00091 * Initialize the default input context as head of the 00092 * per-thread IMC list. 00093 */ 00094 UserAssert(ptiCurrent->spDefaultImc == NULL); 00095 Lock(&ptiCurrent->spDefaultImc, pImc); 00096 pImc->pImcNext = NULL; 00097 } 00098 else { 00099 /* 00100 * Link it to the per-thread IMC list. 00101 */ 00102 UserAssert(ptiCurrent->spDefaultImc != NULL); 00103 pImc->pImcNext = ptiCurrent->spDefaultImc->pImcNext; 00104 ptiCurrent->spDefaultImc->pImcNext = pImc; 00105 } 00106 00107 pImc->dwClientImcData = dwClientImcData; 00108 00109 return pImc; 00110 }

BOOL DestroyInputContext IN PIMC  pImc  ) 
 

Definition at line 122 of file ntimm.c.

References AssociateInputContext(), _HANDLEENTRY::bFlags, BOOL, BuildHwndList(), BWL_ENUMCHILDREN, BWL_ENUMLIST, FALSE, FreeHwndList(), GETPTI, HANDLEF_DESTROY, tagWND::hImc, HMDestroyUnlockedObject(), HMPheFromObject, NULL, tagDESKTOP::pDeskInfo, PtiCurrent, PtoH, RevalidateHwnd, tagBWL::rghwnd, tagTHREADINFO::rpdesk, tagTHREADINFO::spDefaultImc, tagDESKTOPINFO::spwnd, tagWND::spwndChild, and TRUE.

Referenced by ImmDestroyContext(), ImmDllInitialize(), and NtUserDestroyInputContext().

00124 { 00125 PTHREADINFO ptiImcOwner; 00126 PBWL pbwl; 00127 PWND pwnd; 00128 HWND *phwnd; 00129 PHE phe; 00130 00131 ptiImcOwner = GETPTI(pImc); 00132 00133 /* 00134 * Cannot destroy input context from other thread. 00135 */ 00136 if (ptiImcOwner != PtiCurrent()) { 00137 RIPERR0(ERROR_ACCESS_DENIED, RIP_WARNING, 00138 "DestroyInputContext: pImc not of current pti"); 00139 return FALSE; 00140 } 00141 00142 /* 00143 * Cannot destroy default input context. 00144 */ 00145 if (pImc == ptiImcOwner->spDefaultImc) { 00146 RIPERR0(ERROR_INVALID_PARAMETER, RIP_WARNING, 00147 "DestroyInputContext: can't destroy default Imc"); 00148 return FALSE; 00149 } 00150 00151 /* 00152 * Cleanup destroyed input context from each associated window. 00153 */ 00154 pbwl = BuildHwndList(ptiImcOwner->rpdesk->pDeskInfo->spwnd->spwndChild, 00155 BWL_ENUMLIST|BWL_ENUMCHILDREN, ptiImcOwner); 00156 00157 if (pbwl != NULL) { 00158 00159 for (phwnd = pbwl->rghwnd; *phwnd != (HWND)1; phwnd++) { 00160 /* 00161 * Make sure this hwnd is still around. 00162 */ 00163 if ((pwnd = RevalidateHwnd(*phwnd)) == NULL) 00164 continue; 00165 00166 /* 00167 * Cleanup by associating the default input context. 00168 */ 00169 if (pwnd->hImc == (HIMC)PtoH(pImc)) 00170 AssociateInputContext(pwnd, ptiImcOwner->spDefaultImc); 00171 } 00172 00173 FreeHwndList(pbwl); 00174 } 00175 00176 phe = HMPheFromObject(pImc); 00177 00178 /* 00179 * Make sure this object isn't already marked to be destroyed - we'll 00180 * do no good if we try to destroy it now since it is locked. 00181 */ 00182 if (!(phe->bFlags & HANDLEF_DESTROY)) 00183 HMDestroyUnlockedObject(phe); 00184 00185 return TRUE; 00186 }

VOID FreeInputContext IN PIMC  pImc  ) 
 

Definition at line 198 of file ntimm.c.

References GETPTI, HMFreeObject(), HMMarkObjectDestroy(), NULL, tagIMC::pImcNext, and VOID().

00200 { 00201 PIMC pImcT; 00202 00203 /* 00204 * Mark it for destruction. If it the object is locked it can't 00205 * be freed right now. 00206 */ 00207 if (!HMMarkObjectDestroy((PVOID)pImc)) 00208 return; 00209 00210 /* 00211 * Unlink it. 00212 */ 00213 pImcT = GETPTI(pImc)->spDefaultImc; 00214 00215 while (pImcT != NULL && pImcT->pImcNext != pImc) 00216 pImcT = pImcT->pImcNext; 00217 00218 if (pImcT != NULL) 00219 pImcT->pImcNext = pImc->pImcNext; 00220 00221 /* 00222 * We're really going to free the input context. 00223 */ 00224 HMFreeObject((PVOID)pImc); 00225 00226 return; 00227 }

BOOL GetImeInfoEx PWINDOWSTATION  pwinsta,
PIMEINFOEX  piiex,
IMEINFOEXCLASS  SearchType
 

Definition at line 1166 of file ntimm.c.

References BOOL, FALSE, tagIMEINFOEX::hkl, tagKL::hkl, IM_FILE_SIZE, ImeInfoExImeFileName, ImeInfoExKeyboardLayout, NULL, tagKL::piiex, tagKL::pklNext, tagWINDOWSTATION::spklList, TRUE, and tagIMEINFOEX::wszImeFile.

01170 { 01171 PKL pkl, pklFirst; 01172 01173 /* 01174 * Note: this check was forced to insert due to winmm.dll who indirectly 01175 * loads imm32.dll in CSRSS context. CSRSS is not always bound to 01176 * specific window station, thus pwinsta could be NULL. 01177 * This has been avoided by not loading imm32.dll. 01178 * After winmm.dll gets removed from CSRSS, this if statement should be 01179 * removed, or substituted as an assertion. 01180 */ 01181 if (pwinsta == NULL) { 01182 return FALSE; 01183 } 01184 01185 /* 01186 * Keyboard layer has not been initialized. 01187 */ 01188 if (pwinsta->spklList == NULL) 01189 return FALSE; 01190 01191 pkl = pklFirst = pwinsta->spklList; 01192 01193 switch (SearchType) { 01194 case ImeInfoExKeyboardLayout: 01195 do { 01196 if (pkl->hkl == piiex->hkl) { 01197 01198 if (pkl->piiex == NULL) 01199 break; 01200 01201 RtlCopyMemory(piiex, pkl->piiex, sizeof(IMEINFOEX)); 01202 return TRUE; 01203 } 01204 pkl = pkl->pklNext; 01205 } while (pkl != pklFirst); 01206 break; 01207 01208 case ImeInfoExImeFileName: 01209 do { 01210 if (pkl->piiex != NULL && 01211 !_wcsnicmp(pkl->piiex->wszImeFile, piiex->wszImeFile, IM_FILE_SIZE)) { 01212 01213 RtlCopyMemory(piiex, pkl->piiex, sizeof(IMEINFOEX)); 01214 return TRUE; 01215 } 01216 pkl = pkl->pklNext; 01217 } while (pkl != pklFirst); 01218 break; 01219 01220 default: 01221 break; 01222 } 01223 01224 return FALSE; 01225 }

PWND GetLastTopMostWindowNoIME PWND  pwndRoot  ) 
 

Definition at line 1891 of file ntimm.c.

References _GetDesktopWindow(), tagCLS::atomClassName, tagSERVERINFO::atomSysClass, BOOL, CFIME, FALSE, gpsi, ICLS_IME, NULL, tagWND::pcls, tagWND::spwndChild, tagWND::spwndNext, tagWND::spwndOwner, TestCF, TestWF, TRUE, and WEFTOPMOST.

Referenced by ImeSetTopmost().

01892 { 01893 PWND pwndT = _GetDesktopWindow(); 01894 PWND pwndRet = NULL; 01895 01896 /* 01897 * pwndRoot should not be NULL, and should be IME window. 01898 */ 01899 UserAssert(pwndRoot && pwndRoot->pcls->atomClassName == gpsi->atomSysClass[ICLS_IME]); 01900 01901 if (pwndT == NULL || pwndT->spwndChild == NULL) { 01902 #if _DBG 01903 if (pwndT == NULL) { 01904 RIPMSG0(RIP_WARNING, "GetLastTopMostWindowNoIME: there's no desktop window !!"); 01905 } 01906 else { 01907 RIPMSG0(RIP_WARNING, "GetLastTopMostWindowNoIME: there is no toplevel window !!"); 01908 } 01909 #endif 01910 return NULL; 01911 } 01912 01913 /* 01914 * Get the first child of the desktop window. 01915 */ 01916 pwndT = pwndT->spwndChild; 01917 01918 /* 01919 * Loop through the toplevel windows while they are topmost. 01920 */ 01921 while (TestWF(pwndT, WEFTOPMOST)) { 01922 PWND pwndOwner = pwndT; 01923 BOOL fOwned = FALSE; 01924 01925 /* 01926 * If pwndT is a IME related window, track the owner. If pwndRoot is not 01927 * pwndT's owner, remember pwndT as a candidate. 01928 */ 01929 if (TestCF(pwndT,CFIME) || (pwndT->pcls->atomClassName == gpsi->atomSysClass[ICLS_IME])) { 01930 while (pwndOwner != NULL) { 01931 if (pwndRoot == pwndOwner) { 01932 fOwned = TRUE; 01933 break; 01934 } 01935 pwndOwner = pwndOwner->spwndOwner; 01936 } 01937 } 01938 if (!fOwned) 01939 pwndRet = pwndT; 01940 01941 /* 01942 * Next toplevel window. 01943 */ 01944 pwndT = pwndT->spwndNext; 01945 UserAssert(pwndT->spwndParent == _GetDesktopWindow()); 01946 } 01947 01948 return pwndRet; 01949 }

BOOL ImeCanDestroyDefIME PWND  pwndDefaultIme,
PWND  pwndDestroy
 

Definition at line 1503 of file ntimm.c.

References tagCLS::atomClassName, tagSERVERINFO::atomSysClass, BOOL, CFIME, FALSE, gpsi, ICLS_IME, ImeCheckTopmost(), ImeSetFutureOwner(), NULL, tagWND::pcls, ProbeAndReadStructure, tagWND::spwndNext, tagWND::spwndOwner, TestCF, TRUE, and Unlock.

01506 { 01507 PWND pwnd; 01508 PIMEUI pimeui; 01509 01510 pimeui = ((PIMEWND)pwndDefaultIme)->pimeui; 01511 01512 if (pimeui == NULL || (LONG_PTR)pimeui == (LONG_PTR)-1) 01513 return FALSE; 01514 01515 try { 01516 if (ProbeAndReadStructure(pimeui, IMEUI).fDestroy) { 01517 return FALSE; 01518 } 01519 } except (W32ExceptionHandler(FALSE, RIP_WARNING)) { 01520 } 01521 01522 /* 01523 * If the pwndDestroy has no owner/ownee relationship with 01524 * pwndDefaultIme, don't bother to change anything. 01525 * 01526 * If pwndDefaultIme->spwndOwner is NULL, this means we need 01527 * to search for a new good owner window. 01528 */ 01529 if ( pwndDefaultIme->spwndOwner != NULL ) { 01530 for (pwnd = pwndDefaultIme->spwndOwner; 01531 pwnd != pwndDestroy && pwnd != NULL; pwnd = pwnd->spwndOwner) ; 01532 01533 if (pwnd == NULL) 01534 return FALSE; 01535 } 01536 01537 /* 01538 * If the destroying window is IME or UI window, do nothing 01539 */ 01540 pwnd = pwndDestroy; 01541 01542 while (pwnd != NULL) { 01543 if (TestCF(pwnd, CFIME) || 01544 pwnd->pcls->atomClassName == gpsi->atomSysClass[ICLS_IME]) 01545 return FALSE; 01546 01547 pwnd = pwnd->spwndOwner; 01548 } 01549 01550 ImeSetFutureOwner(pwndDefaultIme, pwndDestroy); 01551 01552 /* 01553 * If new owner is lower z-order than IME class window, 01554 * we need to check topmost to change z-order. 01555 */ 01556 pwnd = pwndDefaultIme->spwndOwner; 01557 while (pwnd != NULL && pwnd != pwndDefaultIme) 01558 pwnd = pwnd->spwndNext; 01559 01560 if (pwnd == pwndDefaultIme) 01561 ImeCheckTopmost(pwndDefaultIme); 01562 01563 #if DBG 01564 CheckOwnerCirculate(pwndDefaultIme); 01565 #endif 01566 01567 /* 01568 * If ImeSetFutureOwner can not find the owner window any 01569 * more, this IME window should be destroyed. 01570 */ 01571 if (pwndDefaultIme->spwndOwner == NULL || 01572 pwndDestroy == pwndDefaultIme->spwndOwner) { 01573 01574 // RIPMSG1(RIP_WARNING, "ImeCanDestroyDefIME: TRUE for pwnd=%#p", pwndDestroy); 01575 Unlock(&pwndDefaultIme->spwndOwner); 01576 01577 /* 01578 * Return TRUE! Please destroy me. 01579 */ 01580 return TRUE; 01581 } 01582 01583 return FALSE; 01584 }

BOOL ImeCanDestroyDefIMEforChild PWND  pwndDefaultIme,
PWND  pwndDestroy
 

Definition at line 1687 of file ntimm.c.

References BOOL, FALSE, GETPTI, IsChildSameThread(), NULL, ProbeAndReadStructure, PWNDDESKTOP, tagWND::spwndParent, and TRUE.

01690 { 01691 PWND pwnd; 01692 PIMEUI pimeui; 01693 01694 pimeui = ((PIMEWND)pwndDefaultIme)->pimeui; 01695 01696 /* 01697 * If this window is not for Child Thread..... 01698 */ 01699 if (pimeui == NULL || (LONG_PTR)pimeui == (LONG_PTR)-1) 01700 return FALSE; 01701 01702 try { 01703 if (!ProbeAndReadStructure(pimeui, IMEUI).fChildThreadDef) { 01704 return FALSE; 01705 } 01706 } except (W32ExceptionHandler(FALSE, RIP_WARNING)) { 01707 } 01708 01709 /* 01710 * If parent belongs to different thread, 01711 * we don't need to check any more... 01712 */ 01713 if (pwndDestroy->spwndParent == NULL || 01714 GETPTI(pwndDestroy) == GETPTI(pwndDestroy->spwndParent)) 01715 return FALSE; 01716 01717 pwnd = pwndDestroy; 01718 01719 while (pwnd != NULL && pwnd != PWNDDESKTOP(pwnd)) { 01720 if (IsChildSameThread(pwnd->spwndParent, pwndDestroy)) 01721 return FALSE; 01722 pwnd = pwnd->spwndParent; 01723 } 01724 01725 /* 01726 * We could not find any other window created by GETPTI(pwndDestroy). 01727 * Let's destroy the default IME window of this Q. 01728 */ 01729 return TRUE; 01730 }

VOID ImeCheckTopmost PWND  pwndIme  ) 
 

Definition at line 1740 of file ntimm.c.

References GETPTI, gptiForeground, ImeSetTopmost(), NULL, tagWND::spwndOwner, TestWF, VOID(), and WEFTOPMOST.

01742 { 01743 if (pwndIme->spwndOwner) { 01744 PWND pwndInsertBeforeThis; 01745 /* 01746 * The ime window have to be same topmost tyle with the owner window. 01747 * If the Q of this window is not foreground Q, we don't need to 01748 * forground the IME window. 01749 * But the topmost attribute of owner was changed, this IME window 01750 * should be re-calced. 01751 */ 01752 if (GETPTI(pwndIme) == gptiForeground) { 01753 pwndInsertBeforeThis = NULL; 01754 } else { 01755 pwndInsertBeforeThis = pwndIme->spwndOwner; 01756 } 01757 01758 ImeSetTopmost(pwndIme, TestWF(pwndIme->spwndOwner, WEFTOPMOST) != 0, pwndInsertBeforeThis); 01759 } 01760 }

VOID ImeSetFutureOwner PWND  pwndIme,
PWND  pwndOrgOwner
 

Definition at line 1770 of file ntimm.c.

References tagCLS::atomClassName, tagSERVERINFO::atomSysClass, CFIME, GETPTI, gpsi, ICLS_IME, ICLS_MENU, Lock, NULL, tagWND::pcls, tagWND::spwndChild, tagWND::spwndNext, tagWND::spwndOwner, tagWND::spwndParent, TestCF, TestWF, VOID(), WFBOTTOMMOST, WFCHILD, and WFINDESTROY.

01773 { 01774 PWND pwnd, pwndOwner; 01775 PTHREADINFO ptiImeWnd = GETPTI(pwndIme); 01776 01777 if (pwndOrgOwner == NULL || TestWF(pwndOrgOwner, WFCHILD)) 01778 return; 01779 01780 pwnd = pwndOrgOwner; 01781 01782 /* 01783 * Get top of owner created by the same thread. 01784 */ 01785 while ((pwndOwner = pwnd->spwndOwner) != NULL && 01786 GETPTI(pwndOwner) == ptiImeWnd) 01787 pwnd = pwndOwner; 01788 01789 /* 01790 * Bottom window can not be the owner of IME window easily... 01791 */ 01792 if (TestWF(pwnd, WFBOTTOMMOST) && !TestWF(pwndOrgOwner, WFBOTTOMMOST)) 01793 pwnd = pwndOrgOwner; 01794 01795 /* 01796 * CS_IME class or "IME" class windows can not be the owner of 01797 * IME windows. 01798 */ 01799 if (TestCF(pwnd, CFIME) || 01800 pwnd->pcls->atomClassName == gpsi->atomSysClass[ICLS_IME]) 01801 pwnd = pwndOrgOwner; 01802 01803 /* 01804 * If hwndOrgOwner is a top of owner, we start to search 01805 * another top owner window in same queue. 01806 */ 01807 if (pwndOrgOwner == pwnd && pwnd->spwndParent != NULL) { 01808 PWND pwndT; 01809 01810 for (pwndT = pwnd->spwndParent->spwndChild; 01811 pwndT != NULL; pwndT = pwndT->spwndNext) { 01812 01813 if (GETPTI(pwnd) != GETPTI(pwndT)) 01814 continue; 01815 01816 if (pwndT->pcls->atomClassName == gpsi->atomSysClass[ICLS_MENU]) 01817 continue; 01818 01819 /* 01820 * CS_IME class or "IME" class windows can not be the owner of 01821 * IME windows. 01822 */ 01823 if (TestCF(pwndT, CFIME) || 01824 pwndT->pcls->atomClassName == gpsi->atomSysClass[ICLS_IME]) 01825 continue; 01826 01827 // We don't like the window that is being destroyed. 01828 if (TestWF(pwndT, WFINDESTROY)) 01829 continue; 01830 01831 /* 01832 * !!!!WARNING!!!!! 01833 * Is hwndT a good owner of hIMEwnd?? 01834 * 1. Of cource, it should no CHILD window! 01835 * 2. If it is hwnd,.. I know it and find next! 01836 * 3. Does hwndT have owner in the same thread? 01837 */ 01838 if (!TestWF(pwndT, WFCHILD) && pwnd != pwndT && 01839 (pwndT->spwndOwner == NULL || 01840 GETPTI(pwndT) != GETPTI(pwndT->spwndOwner))) { 01841 UserAssert(GETPTI(pwndIme) == GETPTI(pwndT)); 01842 pwnd = pwndT; 01843 break; 01844 } 01845 } 01846 } 01847 01848 UserAssert(!TestCF(pwnd, CFIME)); 01849 Lock(&pwndIme->spwndOwner, pwnd); 01850 01851 return; 01852 }

VOID ImeSetTopmost PWND  pwndRootIme,
BOOL  fMakeTopmost,
PWND  pwndInsertBefore
 

Definition at line 1995 of file ntimm.c.

References tagCLS::atomClassName, tagSERVERINFO::atomSysClass, CFIME, ClrWF, FALSE, GetLastTopMostWindowNoIME(), GETPTI, gpsi, ICLS_IME, ImeSetTopmostChild(), LinkWindow(), NULL, tagWND::pcls, PWND_TOP, SetWF, tagWND::spwndChild, tagWND::spwndNext, tagWND::spwndOwner, tagWND::spwndParent, TestCF, TestWF, TRUE, UnlinkWindow(), VOID(), WEFTOPMOST, and WFBOTTOMMOST.

01999 { 02000 PWND pwndParent = pwndRootIme->spwndParent; 02001 PWND pwndInsert = PWND_TOP; // pwnd which should be prior to pwndRootIme. 02002 PWND pwnd, pwndT; 02003 PWND pwndInsertFirst; 02004 BOOLEAN fFound; 02005 02006 if (pwndParent == NULL) 02007 return; 02008 02009 pwnd = pwndParent->spwndChild; 02010 02011 if (!fMakeTopmost) { 02012 /* 02013 * Get the last topmost window. This should be after unlink pwndRootIme 02014 * because pwndRootIme may be the last topmost window. 02015 */ 02016 pwndInsert = GetLastTopMostWindowNoIME(pwndRootIme); 02017 02018 if (pwndInsertBefore) { 02019 02020 fFound = FALSE; 02021 pwndT = pwndInsert; 02022 02023 while (pwndT != NULL && pwndT->spwndNext != pwndInsertBefore) { 02024 if (pwndT == pwndRootIme) 02025 fFound = TRUE; 02026 pwndT = pwndT->spwndNext; 02027 } 02028 02029 if (pwndT == NULL || fFound) 02030 return; 02031 02032 pwndInsert = pwndT; 02033 } 02034 02035 if (TestWF(pwndRootIme->spwndOwner, WFBOTTOMMOST)) { 02036 pwndT = pwndInsert; 02037 02038 while (pwndT != NULL && pwndT != pwndRootIme->spwndOwner) { 02039 if (!TestCF(pwndT, CFIME) && 02040 pwndT->pcls->atomClassName != gpsi->atomSysClass[ICLS_IME]) { 02041 pwndInsert = pwndT; 02042 } 02043 pwndT = pwndT->spwndNext; 02044 } 02045 } 02046 } 02047 02048 pwndInsertFirst = pwndInsert; 02049 02050 /* 02051 * Enum the all toplevel windows and if the owner of the window is same as 02052 * the owner of pwndRootIme, the window should be changed the position of 02053 * window link. 02054 */ 02055 while (pwnd != NULL) { 02056 /* 02057 * Get the next window before calling ImeSetTopmost. 02058 * Because the next window will be changed in LinkWindow. 02059 */ 02060 PWND pwndNext = pwnd->spwndNext; 02061 02062 /* 02063 * the owner relation between IME and UI window is in same thread. 02064 */ 02065 if (GETPTI(pwnd) != GETPTI(pwndRootIme)) 02066 goto ist_next; 02067 02068 /* 02069 * pwnd have to be CS_IME class or "IME" class. 02070 */ 02071 if (!TestCF(pwnd, CFIME) && 02072 pwnd->pcls->atomClassName != gpsi->atomSysClass[ICLS_IME]) 02073 goto ist_next; 02074 02075 /* 02076 * If pwnd is pwndInsert, we don't need to do anything... 02077 */ 02078 if (pwnd == pwndInsert) 02079 goto ist_next; 02080 02081 pwndT = pwnd; 02082 while (pwndT != NULL) { 02083 if (pwndT == pwndRootIme) { 02084 /* 02085 * Found!! 02086 * pwnd is the ownee of pwndRootIme. 02087 */ 02088 02089 UserAssert(GETPTI(pwnd) == GETPTI(pwndRootIme)); 02090 UserAssert(TestCF(pwnd,CFIME) || 02091 (pwnd->pcls->atomClassName == gpsi->atomSysClass[ICLS_IME])); 02092 UserAssert(pwnd != pwndInsert); 02093 02094 UnlinkWindow(pwnd, pwndParent); 02095 02096 if (fMakeTopmost) { 02097 if (pwndInsert != PWND_TOP) 02098 UserAssert(TestWF(pwndInsert, WEFTOPMOST)); 02099 SetWF(pwnd, WEFTOPMOST); 02100 } 02101 else { 02102 if (pwndInsert == PWND_TOP) { 02103 /* 02104 * In rare cases, the first toplevel window could be the one we'll look next, 02105 * who may still have obscure topmost flag. 02106 */ 02107 UserAssert(pwndParent->spwndChild == pwndNext || !TestWF(pwndParent->spwndChild, WEFTOPMOST)); 02108 } 02109 else if (pwndInsert->spwndNext != NULL) { 02110 /* 02111 * In rare cases, pwndInsert->spwndNext could be the one we'll look next, 02112 * who may still have obscure topmost flag. 02113 */ 02114 UserAssert(pwndInsert->spwndNext == pwndNext || !TestWF(pwndInsert->spwndNext, WEFTOPMOST)); 02115 } 02116 ClrWF(pwnd, WEFTOPMOST); 02117 } 02118 02119 LinkWindow(pwnd, pwndInsert, pwndParent); 02120 #if 0 // Let's see what happens if we disable this 02121 ImeSetTopmostChild(pwnd, fMakeTopmost); 02122 #endif 02123 02124 pwndInsert = pwnd; 02125 break; // goto ist_next; 02126 } 02127 pwndT = pwndT->spwndOwner; 02128 } 02129 ist_next: 02130 pwnd = pwndNext; 02131 02132 /* 02133 * Skip the windows that were inserted before. 02134 */ 02135 if (pwnd != NULL && pwnd == pwndInsertFirst) 02136 pwnd = pwndInsert->spwndNext; 02137 02138 #if DBG 02139 if (pwnd) 02140 ImeCheckSetTopmostLink(pwnd, pwndInsertFirst, pwndInsert); 02141 #endif 02142 } 02143 }

VOID ImeSetTopmostChild PWND  pwndParent,
BOOL  fMakeTopmost
 

Definition at line 1862 of file ntimm.c.

References ClrWF, ImeSetTopmostChild(), NULL, SetWF, tagWND::spwndChild, tagWND::spwndNext, VOID(), and WEFTOPMOST.

01865 { 01866 PWND pwnd = pwndParent->spwndChild; 01867 01868 while (pwnd != NULL) { 01869 if (fMakeTopmost) 01870 SetWF(pwnd, WEFTOPMOST); 01871 else 01872 ClrWF(pwnd, WEFTOPMOST); 01873 01874 ImeSetTopmostChild(pwnd, fMakeTopmost); 01875 01876 pwnd = pwnd->spwndNext; 01877 } 01878 01879 return; 01880 }

BOOL IsChildSameThread PWND  pwndParent,
PWND  pwndChild
 

Definition at line 1594 of file ntimm.c.

References tagCLS::atomClassName, tagSERVERINFO::atomSysClass, BOOL, CFIME, FALSE, GETPTI, gpsi, ICLS_IME, ICLS_MENU, NULL, tagWND::pcls, tagWND::spwndChild, tagWND::spwndNext, tagWND::spwndOwner, tagWND::spwndParent, TestCF, TestwndChild, and TRUE.

01597 { 01598 PWND pwnd; 01599 PTHREADINFO ptiChild = GETPTI(pwndChild); 01600 01601 for (pwnd = pwndParent->spwndChild; pwnd; pwnd = pwnd->spwndNext) { 01602 /* 01603 * If pwnd is not child window, we need to skip MENU window and 01604 * IME related window. 01605 */ 01606 if (!TestwndChild(pwnd)) { 01607 PWND pwndOwner = pwnd; 01608 BOOL fFoundOwner = FALSE; 01609 01610 /* 01611 * Skip MENU window. 01612 */ 01613 if (pwnd->pcls->atomClassName == gpsi->atomSysClass[ICLS_MENU]) 01614 continue; 01615 01616 while (pwndOwner != NULL) { 01617 /* 01618 * CS_IME class or "IME" class windows can not be the owner of 01619 * IME windows. 01620 */ 01621 if (TestCF(pwndOwner, CFIME) || 01622 pwndOwner->pcls->atomClassName == gpsi->atomSysClass[ICLS_IME]) { 01623 fFoundOwner = TRUE; 01624 break; 01625 } 01626 01627 pwndOwner = pwndOwner->spwndOwner; 01628 } 01629 01630 if (fFoundOwner) 01631 continue; 01632 } 01633 01634 /* 01635 * We need to skip pwndChild. 01636 */ 01637 if (pwnd == pwndChild) 01638 continue; 01639 01640 /* 01641 * pwnd and pwndChild are on same thread? 01642 */ 01643 if (GETPTI(pwnd) == ptiChild) { 01644 PWND pwndT = pwnd; 01645 BOOL fFoundImeWnd = FALSE; 01646 01647 /* 01648 * Check again. If hwndT is children or ownee of 01649 * IME related window, skip it. 01650 */ 01651 if (TestwndChild(pwndT)) { 01652 01653 for (; TestwndChild(pwndT) && GETPTI(pwndT) == ptiChild; 01654 pwndT = pwndT->spwndParent) { 01655 if (TestCF(pwndT, CFIME) || 01656 pwndT->pcls->atomClassName == gpsi->atomSysClass[ICLS_IME]) 01657 fFoundImeWnd = TRUE; 01658 } 01659 } 01660 01661 if (!TestwndChild(pwndT)) { 01662 01663 for (; pwndT != NULL && GETPTI(pwndT) == ptiChild; 01664 pwndT = pwndT->spwndOwner) { 01665 if (TestCF(pwndT, CFIME) || 01666 pwndT->pcls->atomClassName == gpsi->atomSysClass[ICLS_IME]) 01667 fFoundImeWnd = TRUE; 01668 } 01669 } 01670 01671 if (!fFoundImeWnd) 01672 return TRUE; 01673 } 01674 } 01675 01676 return FALSE; 01677 }

PSOFTKBDDATA ProbeAndCaptureSoftKbdData PSOFTKBDDATA  Source  ) 
 

Definition at line 2154 of file ntimm.c.

References BYTE, DWORD, ExRaiseStatus(), NULL, ProbeAndReadUlong, ProbeForReadBuffer, TRUE, and UINT.

Referenced by MESSAGECALL().

02156 { 02157 PSOFTKBDDATA Destination = NULL; 02158 DWORD cbSize; 02159 UINT uCount; 02160 02161 try { 02162 uCount = ProbeAndReadUlong((PULONG)Source); 02163 02164 #if defined(_X86_) 02165 ProbeForReadBuffer(&Source->wCode, uCount, sizeof(BYTE)); 02166 #else 02167 ProbeForReadBuffer(&Source->wCode, uCount, sizeof(WORD)); 02168 #endif 02169 02170 cbSize = FIELD_OFFSET(SOFTKBDDATA, wCode[0]) 02171 + uCount * sizeof(WORD) * 256; 02172 02173 Destination = (PSOFTKBDDATA)UserAllocPool(cbSize, TAG_IME); 02174 02175 if (Destination != NULL) { 02176 RtlCopyMemory(Destination, Source, cbSize); 02177 } else { 02178 ExRaiseStatus(STATUS_NO_MEMORY); 02179 } 02180 02181 } except (W32ExceptionHandler(TRUE, RIP_WARNING)) { 02182 02183 if (Destination != NULL) { 02184 UserFreePool(Destination); 02185 } 02186 02187 return NULL; 02188 } 02189 02190 return Destination; 02191 }

VOID SetConvMode PTHREADINFO  pti,
DWORD  dwConversion
 

Definition at line 2196 of file ntimm.c.

References ClearKeyStateDown, ClearKeyStateToggle, tagKL::hkl, NULL, tagTHREADINFO::pq, SetKeyStateDown, SetKeyStateToggle, tagTHREADINFO::spklActive, and VOID().

Referenced by xxxNotifyIMEStatus().

02197 { 02198 if ( pti->spklActive == NULL ) 02199 return; 02200 02201 switch ( PRIMARYLANGID(HandleToUlong(pti->spklActive->hkl)) ) { 02202 case LANG_JAPANESE: 02203 02204 ClearKeyStateDown(pti->pq, VK_DBE_ALPHANUMERIC); 02205 ClearKeyStateToggle(pti->pq, VK_DBE_ALPHANUMERIC); 02206 ClearKeyStateDown(pti->pq, VK_DBE_KATAKANA); 02207 ClearKeyStateToggle(pti->pq, VK_DBE_KATAKANA); 02208 ClearKeyStateDown(pti->pq, VK_DBE_HIRAGANA); 02209 ClearKeyStateToggle(pti->pq, VK_DBE_HIRAGANA); 02210 02211 if ( dwConversion & IME_CMODE_NATIVE ) { 02212 if ( dwConversion & IME_CMODE_KATAKANA ) { 02213 SetKeyStateDown( pti->pq, VK_DBE_KATAKANA); 02214 SetKeyStateToggle( pti->pq, VK_DBE_KATAKANA); 02215 } else { 02216 SetKeyStateDown( pti->pq, VK_DBE_HIRAGANA); 02217 SetKeyStateToggle( pti->pq, VK_DBE_HIRAGANA); 02218 } 02219 } else { 02220 SetKeyStateDown( pti->pq, VK_DBE_ALPHANUMERIC); 02221 SetKeyStateToggle( pti->pq, VK_DBE_ALPHANUMERIC); 02222 } 02223 02224 if ( dwConversion & IME_CMODE_FULLSHAPE ) { 02225 SetKeyStateDown( pti->pq, VK_DBE_DBCSCHAR); 02226 SetKeyStateToggle( pti->pq, VK_DBE_DBCSCHAR); 02227 ClearKeyStateDown(pti->pq, VK_DBE_SBCSCHAR); 02228 ClearKeyStateToggle(pti->pq, VK_DBE_SBCSCHAR); 02229 } else { 02230 SetKeyStateDown( pti->pq, VK_DBE_SBCSCHAR); 02231 SetKeyStateToggle( pti->pq, VK_DBE_SBCSCHAR); 02232 ClearKeyStateDown(pti->pq, VK_DBE_DBCSCHAR); 02233 ClearKeyStateToggle(pti->pq, VK_DBE_DBCSCHAR); 02234 } 02235 02236 if ( dwConversion & IME_CMODE_ROMAN ) { 02237 SetKeyStateDown( pti->pq, VK_DBE_ROMAN); 02238 SetKeyStateToggle( pti->pq, VK_DBE_ROMAN); 02239 ClearKeyStateDown(pti->pq, VK_DBE_NOROMAN); 02240 ClearKeyStateToggle(pti->pq, VK_DBE_NOROMAN); 02241 } else { 02242 SetKeyStateDown( pti->pq, VK_DBE_NOROMAN); 02243 SetKeyStateToggle( pti->pq, VK_DBE_NOROMAN); 02244 ClearKeyStateDown(pti->pq, VK_DBE_ROMAN); 02245 ClearKeyStateToggle(pti->pq, VK_DBE_ROMAN); 02246 } 02247 02248 if ( dwConversion & IME_CMODE_CHARCODE ) { 02249 SetKeyStateDown( pti->pq, VK_DBE_CODEINPUT); 02250 SetKeyStateToggle( pti->pq, VK_DBE_CODEINPUT); 02251 ClearKeyStateDown(pti->pq, VK_DBE_NOCODEINPUT); 02252 ClearKeyStateToggle(pti->pq, VK_DBE_NOCODEINPUT); 02253 } else { 02254 SetKeyStateDown( pti->pq, VK_DBE_NOCODEINPUT); 02255 SetKeyStateToggle( pti->pq, VK_DBE_NOCODEINPUT); 02256 ClearKeyStateDown(pti->pq, VK_DBE_CODEINPUT); 02257 ClearKeyStateToggle(pti->pq, VK_DBE_CODEINPUT); 02258 } 02259 break; 02260 02261 case LANG_KOREAN: 02262 if ( dwConversion & IME_CMODE_NATIVE) { 02263 SetKeyStateToggle( pti->pq, VK_HANGUL); 02264 } else { 02265 ClearKeyStateToggle( pti->pq, VK_HANGUL); 02266 } 02267 02268 if ( dwConversion & IME_CMODE_FULLSHAPE ) { 02269 SetKeyStateToggle( pti->pq, VK_JUNJA); 02270 } else { 02271 ClearKeyStateToggle( pti->pq, VK_JUNJA); 02272 } 02273 02274 if ( dwConversion & IME_CMODE_HANJACONVERT ) { 02275 SetKeyStateToggle( pti->pq, VK_HANJA); 02276 } else { 02277 ClearKeyStateToggle( pti->pq, VK_HANJA); 02278 } 02279 break; 02280 02281 default: 02282 break; 02283 } 02284 return; 02285 }

BOOL SetImeInfoEx PWINDOWSTATION  pwinsta,
PIMEINFOEX  piiex
 

Definition at line 1237 of file ntimm.c.

References BOOL, FALSE, tagIMEINFOEX::fLoadFlag, tagIMEINFOEX::hkl, tagKL::hkl, IMEF_NONLOAD, NULL, tagKL::piiex, tagKL::pklNext, tagWINDOWSTATION::spklList, and TRUE.

01240 { 01241 PKL pkl, pklFirst; 01242 01243 if (pwinsta == NULL) { 01244 return FALSE; 01245 } 01246 01247 UserAssert(pwinsta->spklList != NULL); 01248 01249 pkl = pklFirst = pwinsta->spklList; 01250 01251 do { 01252 if (pkl->hkl == piiex->hkl) { 01253 01254 /* 01255 * Error out for non-IME based keyboard layout. 01256 */ 01257 if (pkl->piiex == NULL) 01258 return FALSE; 01259 01260 /* 01261 * Update kernel side IMEINFOEX for this keyboard layout 01262 * only if this is its first loading. 01263 */ 01264 if (pkl->piiex->fLoadFlag == IMEF_NONLOAD) { 01265 RtlCopyMemory(pkl->piiex, piiex, sizeof(IMEINFOEX)); 01266 } 01267 01268 return TRUE; 01269 } 01270 pkl = pkl->pklNext; 01271 01272 } while (pkl != pklFirst); 01273 01274 return FALSE; 01275 }

BOOL UpdateInputContext IN PIMC  pImc,
IN UPDATEINPUTCONTEXTCLASS  UpdateType,
IN ULONG_PTR  UpdateValue
 

Definition at line 239 of file ntimm.c.

References BOOL, FALSE, GETPTI, tagTHREADINFO::ppi, PtiCurrent, TRUE, UpdateClientInputContext, and UpdateInUseImeWindow.

Referenced by NtUserUpdateInputContext().

00243 { 00244 PTHREADINFO ptiCurrent, ptiImcOwner; 00245 00246 ptiCurrent = PtiCurrent(); 00247 ptiImcOwner = GETPTI(pImc); 00248 00249 /* 00250 * Cannot update input context from other process. 00251 */ 00252 if (ptiImcOwner->ppi != ptiCurrent->ppi) { 00253 RIPERR0(ERROR_ACCESS_DENIED, RIP_WARNING, "UpdateInputContext: pImc not of current ppi"); 00254 return FALSE; 00255 } 00256 00257 00258 switch (UpdateType) { 00259 00260 case UpdateClientInputContext: 00261 if (pImc->dwClientImcData != 0) { 00262 RIPERR0(RIP_WARNING, RIP_WARNING, "UpdateInputContext: pImc->dwClientImcData != 0"); 00263 return FALSE; 00264 } 00265 pImc->dwClientImcData = UpdateValue; 00266 break; 00267 00268 case UpdateInUseImeWindow: 00269 pImc->hImeWnd = (HWND)UpdateValue; 00270 break; 00271 00272 default: 00273 return FALSE; 00274 } 00275 00276 return TRUE; 00277 }

VOID xxxBroadcastImeShowStatusChange PWND  pwndIme,
BOOL  fShow
 

Definition at line 2679 of file ntimm.c.

References CheckCritIn, gfIMEShowStatus, VOID(), and xxxNotifyImeShowStatus().

02680 { 02681 CheckCritIn(); 02682 02683 gfIMEShowStatus = !!fShow; 02684 xxxNotifyImeShowStatus(pwndIme); 02685 }

BOOL xxxCheckImeShowStatus PWND  pwndIme,
PTHREADINFO  pti
 

Definition at line 2375 of file ntimm.c.

References tagCLS::atomClassName, tagSERVERINFO::atomSysClass, BOOL, BuildHwndList(), BWL_ENUMLIST, FALSE, FreeHwndList(), tagIMEUI::fShowStatus, GETPTI, gpsi, tagIMEUI::hwndIMC, ICLS_IME, KeAttachProcess(), KeDetachProcess(), L, NULL, tagWND::pcls, PHWND, tagTHREADINFO::ppi, ProbeAndReadStructure, PtiCurrent, RevalidateHwnd, tagBWL::rghwnd, tagWND::spwndChild, tagWND::spwndParent, TestWF, ThreadLockAlways, ThreadUnlock, TIF_INCLEANUP, TRUE, WFINDESTROY, and xxxSendMessage().

Referenced by xxxCheckImeShowStatusInThread(), and xxxNotifyImeShowStatus().

02376 { 02377 PBWL pbwl; 02378 PHWND phwnd; 02379 BOOL fRet = FALSE; 02380 PTHREADINFO ptiCurrent = PtiCurrent(); 02381 02382 if (TestWF(pwndIme, WFINDESTROY)) { 02383 return FALSE; 02384 } 02385 02386 // Parent window of IME window should be the desktop window 02387 UserAssert(pwndIme); 02388 UserAssert(pwndIme->spwndParent == GETPTI(pwndIme)->pDeskInfo->spwnd); 02389 02390 pbwl = BuildHwndList(pwndIme->spwndParent->spwndChild, BWL_ENUMLIST, NULL); 02391 if (pbwl != NULL) { 02392 fRet = TRUE; 02393 for (phwnd = pbwl->rghwnd; *phwnd != (HWND)1; phwnd++) { 02394 PWND pwndT = RevalidateHwnd(*phwnd); 02395 02396 // If pwndT is the current active IME window, we should skip it 02397 // since it's the only one window allowed to show status, and 02398 // we've already taken care of it. 02399 if (pwndT == NULL || (/*pwndIme && */pwndIme == pwndT)) { // Can skip pwndIme != NULL test 02400 continue; 02401 } 02402 02403 // We are going to touch IME windows only 02404 if (pwndT->pcls->atomClassName == gpsi->atomSysClass[ICLS_IME] && 02405 !TestWF(pwndT, WFINDESTROY)) { 02406 02407 PIMEUI pimeui = ((PIMEWND)pwndT)->pimeui; 02408 02409 if (pimeui == NULL || pimeui == (PIMEUI)-1) { 02410 continue; 02411 } 02412 02413 if (pti == NULL || pti == GETPTI(pwndT)) { 02414 BOOLEAN fAttached = FALSE; 02415 PWND pwndIMC; 02416 02417 // If pwndT is not a window of the current process, we have to138163 02418 // attach the process to get access to pimeui. 02419 if (GETPTI(pwndT)->ppi != ptiCurrent->ppi) { 02420 RIPMSG0(RIP_VERBOSE, "Attaching process in xxxCheckImeShowStatus"); 02421 KeAttachProcess(&GETPTI(pwndT)->ppi->Process->Pcb); 02422 fAttached = TRUE; 02423 } 02424 02425 try { 02426 if (ProbeAndReadStructure(pimeui, IMEUI).fShowStatus) { 02427 if (pti == NULL) { 02428 RIPMSG0(RIP_VERBOSE, "xxxCheckImeShowStatus: the status window is shown !!"); 02429 } 02430 if ((pwndIMC = RevalidateHwnd(pimeui->hwndIMC)) != NULL) { 02431 pimeui->fShowStatus = FALSE; 02432 } 02433 } else { 02434 pwndIMC = NULL; 02435 } 02436 02437 } except (W32ExceptionHandler(FALSE, RIP_WARNING)) { 02438 pwndIMC = NULL; 02439 } 02440 if (fAttached) { 02441 KeDetachProcess(); 02442 } 02443 02444 if (pwndIMC && GETPTI(pwndIMC) && !(GETPTI(pwndIMC)->TIF_flags & TIF_INCLEANUP)) { 02445 TL tl; 02446 02447 ThreadLockAlways(pwndIMC, &tl); 02448 RIPMSG1(RIP_VERBOSE, "Sending WM_IME_NOTIFY to %#p, IMN_CLOSESTATUSWINDOW", pwndIMC); 02449 xxxSendMessage(pwndIMC, WM_IME_NOTIFY, IMN_CLOSESTATUSWINDOW, 0L); 02450 ThreadUnlock(&tl); 02451 } 02452 02453 } 02454 } 02455 } 02456 FreeHwndList(pbwl); 02457 } 02458 return fRet; 02459 }

VOID xxxCheckImeShowStatusInThread PWND  pwndIme  ) 
 

Definition at line 2694 of file ntimm.c.

References GETPTI, IS_IME_ENABLED, TestWF, VOID(), WFINDESTROY, and xxxCheckImeShowStatus().

02695 { 02696 if (IS_IME_ENABLED()) { 02697 UserAssert(pwndIme); 02698 02699 if (!TestWF(pwndIme, WFINDESTROY)) { 02700 xxxCheckImeShowStatus(pwndIme, GETPTI(pwndIme)); 02701 } 02702 } 02703 }

PWND xxxCreateDefaultImeWindow IN PWND  pwnd,
IN ATOM  atomT,
IN HANDLE  hInst
 

Definition at line 531 of file ntimm.c.

References tagSERVERINFO::atomSysClass, CFIME, CreateInputContext(), DesktopAlloc(), DesktopFree, DTAG_IMETEXT, DWORD, FALSE, GETPTI, gpidLogon, gpsi, hInst, ICLS_IME, NULL, tagDESKTOP::pheapDesktop, tagTHREADINFO::ppi, ProbeForWrite(), PtiCurrentShared, tagTHREADINFO::rpdesk, RtlInitLargeUnicodeString(), tagTHREADINFO::spDefaultImc, tagTHREADINFO::spwndDefaultIme, TestCF, TestWF, TestwndChild, ThreadLock, ThreadUnlock, TIF_DISABLEIME, tagTHREADINFO::TIF_flags, TRUE, UINT, VER40, WFSERVERSIDEPROC, wszDefaultIme, and xxxCreateWindowEx().

Referenced by xxxCreateWindowEx().

00535 { 00536 LARGE_STRING strWindowName; 00537 PWND pwndDefaultIme; 00538 TL tlpwnd; 00539 PIMEUI pimeui; 00540 PTHREADINFO ptiCurrent = PtiCurrentShared(); 00541 LPWSTR pwszDefaultIme; 00542 00543 UserAssert(ptiCurrent == GETPTI(pwnd) && ptiCurrent->spwndDefaultIme == NULL); 00544 00545 /* 00546 * Those conditions should have been checked by WantImeWindow() 00547 * before xxxCreateDefaultImeWindow gets called. 00548 */ 00549 UserAssert(!(ptiCurrent->TIF_flags & TIF_DISABLEIME)); 00550 UserAssert(!TestWF(pwnd, WFSERVERSIDEPROC)); 00551 00552 /* 00553 * The first Winlogon thread starts without default input context. 00554 * Create it now. 00555 */ 00556 if (ptiCurrent->spDefaultImc == NULL && 00557 ptiCurrent->pEThread->Cid.UniqueProcess == gpidLogon) 00558 CreateInputContext(0); 00559 00560 /* 00561 * No default IME window for thread that doesn't have 00562 * default input context 00563 */ 00564 if (ptiCurrent->spDefaultImc == NULL) 00565 return (PWND)NULL; 00566 00567 /* 00568 * Avoid recursion 00569 */ 00570 if (atomT == gpsi->atomSysClass[ICLS_IME] || TestCF(pwnd, CFIME)) 00571 return (PWND)NULL; 00572 00573 /* 00574 * B#12165-win95b 00575 * Yet MFC does another nice. We need to avoid to give an IME window 00576 * to the child of desktop window which is in different process. 00577 */ 00578 if (TestwndChild(pwnd) && GETPTI(pwnd->spwndParent)->ppi != ptiCurrent->ppi && 00579 !(pwnd->style & WS_VISIBLE)) 00580 return (PWND)NULL; 00581 00582 if (ptiCurrent->rpdesk->pheapDesktop == NULL) 00583 return (PWND)NULL; 00584 00585 /* 00586 * Allocate storage for L"Default IME" string from desktop heap 00587 * so that it can be referenced from USER32.DLL in user mode. 00588 */ 00589 pwszDefaultIme = (LPWSTR)DesktopAlloc(ptiCurrent->rpdesk, 00590 sizeof(wszDefaultIme), 00591 DTAG_IMETEXT); 00592 if (pwszDefaultIme == NULL) 00593 return (PWND)NULL; 00594 00595 RtlCopyMemory(pwszDefaultIme, wszDefaultIme, sizeof(wszDefaultIme)); 00596 00597 RtlInitLargeUnicodeString((PLARGE_UNICODE_STRING)&strWindowName, 00598 pwszDefaultIme, 00599 (UINT)-1); 00600 00601 ThreadLock(pwnd, &tlpwnd); 00602 00603 pwndDefaultIme = xxxCreateWindowEx( (DWORD)0, 00604 (PLARGE_STRING)gpsi->atomSysClass[ICLS_IME], 00605 (PLARGE_STRING)&strWindowName, 00606 WS_POPUP | WS_DISABLED, 00607 0, 0, 0, 0, 00608 pwnd, (PMENU)NULL, 00609 hInst, NULL, VER40); 00610 00611 00612 if (pwndDefaultIme != NULL) { 00613 pimeui = ((PIMEWND)pwndDefaultIme)->pimeui; 00614 UserAssert(pimeui != NULL && (LONG_PTR)pimeui != (LONG_PTR)-1); 00615 try { 00616 ProbeForWrite(pimeui, sizeof *pimeui, sizeof(DWORD)); 00617 pimeui->fDefault = TRUE; 00618 if (TestwndChild(pwnd) && GETPTI(pwnd->spwndParent) != ptiCurrent) { 00619 pimeui->fChildThreadDef = TRUE; 00620 } 00621 } except (W32ExceptionHandler(FALSE, RIP_WARNING)) { 00622 } 00623 } 00624 00625 ThreadUnlock(&tlpwnd); 00626 00627 DesktopFree(ptiCurrent->rpdesk, pwszDefaultIme); 00628 00629 return pwndDefaultIme; 00630 }

VOID xxxFocusSetInputContext IN PWND  pWnd,
IN BOOL  fActivate,
IN BOOL  fQueueMsg
 

Definition at line 405 of file ntimm.c.

References tagSERVERINFO::atomSysClass, CFIME, CheckLock, GETPTI, gpsi, HWq, ICLS_IME, L, NULL, tagTHREADINFO::spwndDefaultIme, TestCF, TestWF, ThreadLockAlways, ThreadUnlock, tagTHREADINFO::TIF_flags, TIF_INCLEANUP, VOID(), WFDESTROYED, xxxSendMessage(), and xxxSendMessageCallback().

Referenced by CancelInputState(), xxxDeactivate(), xxxDestroyWindow(), and xxxSendFocusMessages().

00409 { 00410 PTHREADINFO pti; 00411 PWND pwndDefaultIme; 00412 TL tlpwndDefaultIme; 00413 00414 CheckLock(pWnd); 00415 00416 pti = GETPTI(pWnd); 00417 00418 /* 00419 * CS_IME class or "IME" class windows can not be SetActivated to hImc. 00420 * WinWord 6.0 US Help calls ShowWindow with the default IME window. 00421 * HELPMACROS get the default IME window by calling GetNextWindow(). 00422 */ 00423 if (TestCF(pWnd, CFIME) || 00424 (pWnd->pcls->atomClassName == gpsi->atomSysClass[ICLS_IME])) 00425 return; 00426 00427 /* 00428 * Do nothing if the thread does not have default IME window. 00429 */ 00430 if ((pwndDefaultIme = pti->spwndDefaultIme) == NULL) 00431 return; 00432 00433 /* 00434 * If the thread is going away or the default IME window is being vanished, 00435 * then do nothing. 00436 */ 00437 if (pti->TIF_flags & TIF_INCLEANUP) 00438 return; 00439 00440 UserAssert(!TestWF(pwndDefaultIme, WFDESTROYED)); 00441 00442 ThreadLockAlways(pwndDefaultIme, &tlpwndDefaultIme); 00443 00444 if (fQueueMsg) { 00445 xxxSendMessageCallback(pwndDefaultIme, WM_IME_SYSTEM, 00446 fActivate ? IMS_ACTIVATECONTEXT : IMS_DEACTIVATECONTEXT, 00447 (LPARAM)HWq(pWnd), NULL, 1L, 0); 00448 } else { 00449 xxxSendMessage(pwndDefaultIme, WM_IME_SYSTEM, 00450 fActivate ? IMS_ACTIVATECONTEXT : IMS_DEACTIVATECONTEXT, 00451 (LPARAM)HWq(pWnd)); 00452 } 00453 00454 #if _DBG 00455 if (pti->spwndDefaultIme != pwndDefaultIme) { 00456 RIPMSG1(RIP_WARNING, "pti(%#p)->spwndDefaultIme got freed during the callback.", pti); 00457 } 00458 #endif 00459 00460 ThreadUnlock(&tlpwndDefaultIme); 00461 00462 return; 00463 }

VOID xxxImmActivateAndUnloadThreadsLayout IN PTHREADINFO ptiList,
IN UINT  nEntries,
IN PTLBLOCK  ptlBlockPrev,
PKL  pklCurrent,
DWORD  dwHklReplace
 

Definition at line 749 of file ntimm.c.

References CheckLock, tagKL::CodePage, dwFlags, DWORD, FALSE, tagKL::hkl, IFL_DEACTIVATEIME, INT, IS_IME_KBDLAYOUT, KeAttachProcess(), KeDetachProcess(), tagTLBLOCK::list, Lock, NULL, tagTHREADINFO::pClientInfo, tagTHREADINFO::ppi, PtiCurrentShared, tagTLBLOCK::ptlBlockPrev, ThreadLockPti, THREADS_PER_TLBLOCK, ThreadUnlockPti, TIF_INCLEANUP, TRUE, VOID(), xxxImmActivateLayout(), and xxxImmUnloadLayout().

Referenced by xxxSetPKLinThreads().

00755 { 00756 TLBLOCK tlBlock; 00757 PTHREADINFO ptiCurrent; 00758 int i, cThreads; 00759 enum { RUN_ACTIVATE = 1, RUN_UNLOAD = 2, RUN_FLAGS_MASK = RUN_ACTIVATE | RUN_UNLOAD, RUN_INVALID = 0xffff0000 }; 00760 00761 CheckLock(pklCurrent); 00762 00763 ptiCurrent = PtiCurrentShared(); 00764 00765 tlBlock.ptlBlockPrev = ptlBlockPrev; 00766 00767 /* 00768 * Build a list of threads that we need to unload their IME DLL(s). 00769 * We can't just walk the ptiList while we're doing the work, because 00770 * for IME based keyboard layout, we will do callback to client side 00771 * and the pti could get deleted out while we leave the critical section. 00772 */ 00773 for (i = 0, cThreads = 0; i < (INT)nEntries; i++) { 00774 DWORD dwFlags = 0; 00775 00776 /* 00777 * Skip all the *do nothing* cases in xxxImmActivateLayout 00778 * so as to minimize the # of TLBLOCKs required. 00779 */ 00780 if (ptiList[i]->TIF_flags & TIF_INCLEANUP) { 00781 dwFlags = RUN_INVALID; 00782 } 00783 else if (ptiList[i]->spklActive != pklCurrent) { 00784 if (ptiList[i]->spwndDefaultIme == NULL) { 00785 BOOLEAN fAttached = FALSE; 00786 00787 Lock(&ptiList[i]->spklActive, pklCurrent); 00788 if (ptiList[i]->pClientInfo != ptiCurrent->pClientInfo && 00789 ptiList[i]->ppi != ptiCurrent->ppi) { 00790 /* 00791 * If the thread is in another process, attach 00792 * to that process so that we can access its ClientInfo. 00793 */ 00794 KeAttachProcess(&ptiList[i]->ppi->Process->Pcb); 00795 fAttached = TRUE; 00796 } 00797 00798 try { 00799 ptiList[i]->pClientInfo->CodePage = pklCurrent->CodePage; 00800 ptiList[i]->pClientInfo->hKL = pklCurrent->hkl; 00801 } except (W32ExceptionHandler(FALSE, RIP_WARNING)) { 00802 dwFlags = RUN_INVALID; 00803 } 00804 if (fAttached) { 00805 KeDetachProcess(); 00806 } 00807 } else { 00808 dwFlags = RUN_ACTIVATE; 00809 } 00810 } 00811 00812 /* 00813 * Skip all the *do nothing* cases in xxxImmUnloadLayout() 00814 * so as to minimize the # of TLBLOCK required. 00815 * (#99321) 00816 */ 00817 if (ptiList[i]->spwndDefaultIme != NULL && 00818 ptiList[i]->spklActive != NULL && 00819 (dwHklReplace != IFL_DEACTIVATEIME || IS_IME_KBDLAYOUT(ptiList[i]->spklActive->hkl)) && 00820 dwFlags != RUN_INVALID) { 00821 dwFlags |= RUN_UNLOAD; 00822 } 00823 00824 if (dwFlags && dwFlags != RUN_INVALID) { 00825 ThreadLockPti(ptiCurrent, ptiList[i], &tlBlock.list[cThreads].tlpti); 00826 #if DBG 00827 tlBlock.list[cThreads].dwUnlockedCount = 0; 00828 #endif 00829 tlBlock.list[cThreads].pti = ptiList[i]; 00830 tlBlock.list[cThreads++].dwFlags = dwFlags; 00831 00832 if (cThreads == THREADS_PER_TLBLOCK) { 00833 i++; // 1 more before exit the loop. 00834 break; 00835 } 00836 } 00837 } 00838 00839 /* 00840 * If we can't service all the threads in this run, 00841 * call xxxImmActivateAndUnloadThreadsLayout again for a new TLBLOCK. 00842 */ 00843 if (i < (INT)nEntries) { 00844 ptiList += i; 00845 nEntries -= i; 00846 xxxImmActivateAndUnloadThreadsLayout(ptiList, nEntries, &tlBlock, pklCurrent, dwHklReplace); 00847 return; 00848 } 00849 00850 /* 00851 * Finally, we can do the actual keyboard layout activation 00852 * starting from this run. Work on current TLBLOCK first. 00853 * We walk the list backwards so that the pti unlocks will 00854 * be done in the right order. 00855 */ 00856 i = cThreads - 1; 00857 for (ptlBlockPrev = &tlBlock; ptlBlockPrev != NULL; ptlBlockPrev = ptlBlockPrev->ptlBlockPrev) { 00858 for ( ; i >= 0; i--) { 00859 if ((ptlBlockPrev->list[i].dwFlags & RUN_ACTIVATE) && 00860 !(ptlBlockPrev->list[i].pti->TIF_flags & TIF_INCLEANUP)) { 00861 xxxImmActivateLayout(ptlBlockPrev->list[i].pti, pklCurrent); 00862 } 00863 00864 // unlock the thread if the thread is only locked for the first run 00865 if ((ptlBlockPrev->list[i].dwFlags & RUN_FLAGS_MASK) == RUN_ACTIVATE) { 00866 ThreadUnlockPti(ptiCurrent, &ptlBlockPrev->list[i].tlpti); 00867 #if DBG 00868 ptlBlockPrev->list[i].dwUnlockedCount++; 00869 #endif 00870 } 00871 } 00872 i = THREADS_PER_TLBLOCK - 1; 00873 } 00874 00875 i = cThreads - 1; 00876 for (ptlBlockPrev = &tlBlock; ptlBlockPrev != NULL; ptlBlockPrev = ptlBlockPrev->ptlBlockPrev) { 00877 for ( ; i >= 0; --i) { 00878 if (ptlBlockPrev->list[i].dwFlags & RUN_UNLOAD) { 00879 if (!(ptlBlockPrev->list[i].pti->TIF_flags & TIF_INCLEANUP)) { 00880 xxxImmUnloadLayout(ptlBlockPrev->list[i].pti, dwHklReplace); 00881 } 00882 else { 00883 RIPMSG1(RIP_WARNING, "xxxImmActivateAndUnloadThreadsLayout: thread %#p is cleaned up.", 00884 ptlBlockPrev->list[i].pti); 00885 } 00886 // unlock the thread 00887 UserAssert((ptlBlockPrev->list[i].dwFlags & RUN_FLAGS_MASK) != RUN_ACTIVATE); 00888 UserAssert(ptlBlockPrev->list[i].dwUnlockedCount == 0); 00889 ThreadUnlockPti(ptiCurrent, &ptlBlockPrev->list[i].tlpti); 00890 #if DBG 00891 ptlBlockPrev->list[i].dwUnlockedCount++; 00892 #endif 00893 } 00894 } 00895 i = THREADS_PER_TLBLOCK - 1; 00896 } 00897 00898 #if DBG 00899 // Check if all the locked thread is properly unlocked 00900 i = cThreads - 1; 00901 for (ptlBlockPrev = &tlBlock; ptlBlockPrev; ptlBlockPrev = ptlBlockPrev->ptlBlockPrev) { 00902 for ( ; i >= 0; --i) { 00903 UserAssert(ptlBlockPrev->list[i].dwUnlockedCount == 1); 00904 } 00905 i = THREADS_PER_TLBLOCK - 1; 00906 } 00907 #endif 00908 00909 return; 00910 }

VOID xxxImmActivateLayout IN PTHREADINFO  pti,
IN PKL  pkl
 

Definition at line 921 of file ntimm.c.

References CheckLock, Lock, NULL, PtiCurrentShared, tagTHREADINFO::spwndDefaultIme, ThreadLockAlwaysWithPti, ThreadUnlock, VOID(), and xxxSendMessage().

Referenced by xxxImmActivateAndUnloadThreadsLayout(), xxxImmActivateThreadsLayout(), and xxxInternalActivateKeyboardLayout().

00924 { 00925 TL tlpwndDefaultIme; 00926 PTHREADINFO ptiCurrent; 00927 00928 CheckLock(pkl); 00929 00930 /* 00931 * Do nothing if it's already been the current active layout. 00932 */ 00933 if (pti->spklActive == pkl) 00934 return; 00935 00936 if (pti->spwndDefaultIme == NULL) { 00937 /* 00938 * Only activate kernel side keyboard layout if this pti 00939 * doesn't have the default IME window. 00940 */ 00941 Lock(&pti->spklActive, pkl); 00942 return; 00943 } 00944 00945 ptiCurrent = PtiCurrentShared(); 00946 00947 /* 00948 * Activate client side IME based keyboard layout. 00949 */ 00950 ThreadLockAlwaysWithPti(ptiCurrent, pti->spwndDefaultIme, &tlpwndDefaultIme); 00951 xxxSendMessage(pti->spwndDefaultIme, WM_IME_SYSTEM, 00952 (WPARAM)IMS_ACTIVATETHREADLAYOUT, (LPARAM)pkl->hkl); 00953 ThreadUnlock(&tlpwndDefaultIme); 00954 00955 Lock(&pti->spklActive, pkl); 00956 00957 return; 00958 }

BOOL xxxImmActivateThreadsLayout PTHREADINFO  pti,
PTLBLOCK  ptlBlockPrev,
PKL  pkl
 

Definition at line 646 of file ntimm.c.

References BOOL, CheckLock, _CLIENTINFO::CI_flags, CI_INPUTCONTEXT_REINIT, _CLIENTINFO::CodePage, tagKL::CodePage, FALSE, tagKL::hkl, _CLIENTINFO::hKL, tagTHREADINFO::hklPrev, INT, tagTLBLOCK::list, Lock, NULL, tagTHREADINFO::pClientInfo, tagTHREADINFO::ppi, PpiCurrent, PtiCurrentShared, tagTHREADINFO::ptiSibling, PTLBLOCK, tagTLBLOCK::ptlBlockPrev, tagTHREADINFO::spDefaultImc, tagTHREADINFO::spklActive, tagTHREADINFO::spwndDefaultIme, ThreadLockPti, THREADS_PER_TLBLOCK, ThreadUnlockPti, tagTHREADINFO::TIF_flags, TIF_INCLEANUP, TLBLOCK, TRUE, UINT, and xxxImmActivateLayout().

Referenced by xxxInternalActivateKeyboardLayout().

00650 { 00651 TLBLOCK tlBlock; 00652 PTHREADINFO ptiCurrent, ptiT; 00653 UINT cThreads = 0; 00654 INT i; 00655 00656 CheckLock(pkl); 00657 00658 ptiCurrent = PtiCurrentShared(); 00659 00660 /* 00661 * Build a list of threads that we need to update their active layouts. 00662 * We can't just walk the ptiT list while we're doing the work, because 00663 * for IME based keyboard layout, we will do callback to client side 00664 * and the ptiT could get deleted out while we leave the critical section. 00665 */ 00666 for (ptiT = pti; ptiT != NULL; ptiT = ptiT->ptiSibling) { 00667 /* 00668 * Skip all the *do nothing* cases in xxxImmActivateLayout 00669 * so as to minimize the # of TLBLOCK required. 00670 */ 00671 if (ptiT->spklActive == pkl || (ptiT->TIF_flags & TIF_INCLEANUP)) 00672 continue; 00673 00674 UserAssert(ptiT->pClientInfo != NULL); 00675 UserAssert(ptiT->ppi == PpiCurrent()); // can't access pClientInfo of other process 00676 00677 if (ptiT->spwndDefaultIme == NULL) { 00678 /* 00679 * Keyboard layout is being switched but there's no way to callback 00680 * the client side to activate&initialize input context now. 00681 * Let's do hkl switching only in the kernel side for this thread 00682 * but remember the input context needs to be re-initialized 00683 * when this GUI thread recreates the default IME window later. 00684 */ 00685 ptiT->hklPrev = ptiT->spklActive->hkl; 00686 Lock(&ptiT->spklActive, pkl); 00687 if (ptiT->spDefaultImc) { 00688 ptiT->pClientInfo->CI_flags |= CI_INPUTCONTEXT_REINIT; 00689 RIPMSG1(RIP_VERBOSE, "xxxImmActivateThreadsLayout: ptiT(%08p) will be re-initialized.", ptiT); 00690 } 00691 UserAssert((ptiT->TIF_flags & TIF_INCLEANUP) == 0); 00692 ptiT->pClientInfo->hKL = pkl->hkl; 00693 ptiT->pClientInfo->CodePage = pkl->CodePage; 00694 continue; 00695 } 00696 00697 ThreadLockPti(ptiCurrent, ptiT, &tlBlock.list[cThreads].tlpti); 00698 tlBlock.list[cThreads++].pti = ptiT; 00699 00700 if (cThreads == THREADS_PER_TLBLOCK) 00701 break; 00702 } 00703 00704 /* 00705 * Return FALSE if all the threads already had the pkl active. 00706 */ 00707 if (ptlBlockPrev == NULL && ptiT == NULL && cThreads == 0) 00708 return FALSE; 00709 00710 /* 00711 * If we can't service all the threads in this run, 00712 * call ImmActivateThreadsLayout() again for a new TLBLOCK. 00713 */ 00714 if (ptiT != NULL && ptiT->ptiSibling != NULL) { 00715 tlBlock.ptlBlockPrev = ptlBlockPrev; 00716 return xxxImmActivateThreadsLayout(ptiT->ptiSibling, &tlBlock, pkl); 00717 } 00718 00719 /* 00720 * Finally, we can do the actual keyboard layout activation 00721 * starting from this run. Work on current TLBLOCK first. 00722 * We walk the list backwards so that the pti unlocks will 00723 * be done in the right order. 00724 */ 00725 00726 tlBlock.ptlBlockPrev = ptlBlockPrev; 00727 ptlBlockPrev = &tlBlock; 00728 00729 while (ptlBlockPrev != NULL) { 00730 for (i = cThreads - 1; i >= 0; --i) { 00731 if ((ptlBlockPrev->list[i].pti->TIF_flags & TIF_INCLEANUP) == 0) { 00732 ptiT = ptlBlockPrev->list[i].pti; 00733 UserAssert(ptiT); 00734 xxxImmActivateLayout(ptiT, pkl); 00735 if ((ptiT->TIF_flags & TIF_INCLEANUP) == 0) { 00736 ptiT->pClientInfo->hKL = pkl->hkl; 00737 ptiT->pClientInfo->CodePage = pkl->CodePage; 00738 } 00739 } 00740 ThreadUnlockPti(ptiCurrent, &ptlBlockPrev->list[i].tlpti); 00741 } 00742 ptlBlockPrev = ptlBlockPrev->ptlBlockPrev; 00743 cThreads = THREADS_PER_TLBLOCK; 00744 } 00745 00746 return TRUE; 00747 }

PIMEINFOEX xxxImmLoadLayout IN HKL  hKL  ) 
 

Definition at line 1118 of file ntimm.c.

References ClientImmLoadLayout(), IS_IME_KBDLAYOUT, NULL, PtiCurrent, ThreadLockPool, ThreadUnlockAndFreePool, and ThreadUnlockPool.

Referenced by xxxLoadKeyboardLayoutEx().

01120 { 01121 PIMEINFOEX piiex; 01122 PTHREADINFO ptiCurrent; 01123 TL tlPool; 01124 01125 /* 01126 * No IMEINFOEX for non-IME based keyboard layout. 01127 */ 01128 if (!IS_IME_KBDLAYOUT(hKL)) 01129 return (PIMEINFOEX)NULL; 01130 01131 piiex = (PIMEINFOEX)UserAllocPool(sizeof(IMEINFOEX), TAG_IME); 01132 01133 if (piiex == NULL) { 01134 RIPMSG1(RIP_WARNING, 01135 "xxxImmLoadLayout: failed to create piiex for hkl = %lx", hKL); 01136 return (PIMEINFOEX)NULL; 01137 } 01138 01139 ptiCurrent = PtiCurrent(); 01140 01141 /* 01142 * Lock this allocations since we are going to the client side 01143 */ 01144 ThreadLockPool(ptiCurrent, piiex, &tlPool); 01145 01146 if (!ClientImmLoadLayout(hKL, piiex)) { 01147 ThreadUnlockAndFreePool(ptiCurrent, &tlPool); 01148 return (PIMEINFOEX)NULL; 01149 } 01150 01151 ThreadUnlockPool(ptiCurrent, &tlPool); 01152 01153 return piiex; 01154 }

DWORD xxxImmProcessKey IN PQ  pq,
IN PWND  pwnd,
IN UINT  message,
IN WPARAM  wParam,
IN LPARAM  lParam
 

Definition at line 1286 of file ntimm.c.

References _PostMessage(), BOOL, CheckImeHotKey(), CheckLock, ClientImmProcessKey(), tagKL::dwFontSigs, _tagIMEHOTKEY::dwHotKeyID, DWORD, FALSE, GetAppImeCompatFlags(), GETPTI, gSystemFS, _tagIMEHOTKEYOBJ::hk, _tagIMEHOTKEY::hKL, tagKL::hkl, HtoP, tagIMEINFOEX::ImeInfo, IPHK_HOTKEY, IS_IME_ENABLED, NULL, tagKL::piiex, PtiCurrent, PtoH, and UINT.

Referenced by xxxScanSysQueue().

01292 { 01293 UINT uVKey; 01294 PKL pkl; 01295 DWORD dwHotKeyID; 01296 DWORD dwReturn = 0; 01297 PIMC pImc = NULL; 01298 BOOL fDBERoman = FALSE; 01299 PIMEHOTKEYOBJ pImeHotKeyObj; 01300 HKL hklTarget; 01301 01302 CheckLock(pwnd); 01303 01304 // 01305 // we're interested in only keyboard messages. 01306 // 01307 if ( message != WM_KEYDOWN && 01308 message != WM_SYSKEYDOWN && 01309 message != WM_KEYUP && 01310 message != WM_SYSKEYUP ) { 01311 01312 return dwReturn; 01313 } 01314 01315 // 01316 // Check if it's IME hotkey. This must be done before checking 01317 // the keyboard layout because IME hotkey handler should be 01318 // called even if current keyboard layout is non-IME layout. 01319 // 01320 pkl = GETPTI(pwnd)->spklActive; 01321 if ( pkl == NULL ) { 01322 return dwReturn; 01323 } 01324 01325 uVKey = (UINT)wParam & 0xff; 01326 01327 pImeHotKeyObj = CheckImeHotKey(pq, uVKey, lParam); 01328 if (pImeHotKeyObj) { 01329 dwHotKeyID = pImeHotKeyObj->hk.dwHotKeyID; 01330 hklTarget = pImeHotKeyObj->hk.hKL; 01331 } 01332 else { 01333 dwHotKeyID = IME_INVALID_HOTKEY; 01334 hklTarget = (HKL)NULL; 01335 } 01336 01337 // 01338 // Handle Direct KL switching here. 01339 // 01340 if (dwHotKeyID >= IME_HOTKEY_DSWITCH_FIRST && dwHotKeyID <= IME_HOTKEY_DSWITCH_LAST) { 01341 UserAssert(hklTarget != NULL); 01342 if (pkl->hkl != hklTarget) { 01343 // 01344 // Post the message only if the new Keyboard Layout is different from 01345 // the current Keyboard Layout. 01346 // 01347 _PostMessage(pwnd, WM_INPUTLANGCHANGEREQUEST, 01348 (pkl->dwFontSigs & gSystemFS) ? INPUTLANGCHANGE_SYSCHARSET : 0, 01349 (LPARAM)hklTarget); 01350 } 01351 if (GetAppImeCompatFlags(GETPTI(pwnd)) & IMECOMPAT_HYDRACLIENT) { 01352 return 0; 01353 } 01354 return IPHK_HOTKEY; 01355 } 01356 01357 if (!IS_IME_ENABLED()) { 01358 // 01359 // Since IMM is disabled, no need to process further. 01360 // Just bail out. 01361 // 01362 return 0; 01363 } 01364 01365 if ( dwHotKeyID != IME_INVALID_HOTKEY ) { 01366 // 01367 // if it's a valid hotkey, go straight and call back 01368 // the IME in the client side. 01369 // 01370 goto ProcessKeyCallClient; 01371 } 01372 01373 // 01374 // if it's not a hotkey, we may want to check something 01375 // before calling back. 01376 // 01377 if ( pkl->piiex == NULL ) { 01378 return dwReturn; 01379 } 01380 01381 // 01382 // Check input context 01383 // 01384 pImc = HtoP(pwnd->hImc); 01385 if ( pImc == NULL ) { 01386 return dwReturn; 01387 } 01388 01389 #ifdef LATER 01390 // 01391 // If there is an easy way to check the input context open/close status 01392 // from the kernel side, IME_PROP_NO_KEYS_ON_CLOSE checking should be 01393 // done here in kernel side. [ 3/10/96 takaok] 01394 // 01395 01396 // 01397 // Check IME_PROP_NO_KEYS_ON_CLOSE bit 01398 // 01399 // if the current imc is not open and IME doesn't need 01400 // keys when being closed, we don't pass any keyboard 01401 // input to ime except hotkey and keys that change 01402 // the keyboard status. 01403 // 01404 if ( (piix->ImeInfo.fdwProperty & IME_PROP_NO_KEYS_ON_CLOSE) && 01405 (!pimc->fdwState & IMC_OPEN) && 01406 uVKey != VK_SHIFT && // 0x10 01407 uVKey != VK_CONTROL && // 0x11 01408 uVKey != VK_CAPITAL && // 0x14 01409 uVKey != VK_KANA && // 0x15 01410 uVKey != VK_NUMLOCK && // 0x90 01411 uVKey != VK_SCROLL ) // 0x91 01412 { 01413 // Check if Korea Hanja conversion mode 01414 if( !(pimc->fdwConvMode & IME_CMODE_HANJACONVERT) ) { 01415 return dwReturn; 01416 } 01417 } 01418 #endif 01419 01420 // 01421 // if the IME doesn't need key up messages, we don't call ime. 01422 // 01423 if ( lParam & 0x80000000 && // set if key up, clear if key down 01424 pkl->piiex->ImeInfo.fdwProperty & IME_PROP_IGNORE_UPKEYS ) 01425 { 01426 return dwReturn; 01427 } 01428 01429 // 01430 // we don't want to handle sys keys since many functions for 01431 // acceelerators won't work without this 01432 // 01433 fDBERoman = (BOOL)( (uVKey == VK_DBE_ROMAN) || 01434 (uVKey == VK_DBE_NOROMAN) || 01435 (uVKey == VK_DBE_HIRAGANA) || 01436 (uVKey == VK_DBE_KATAKANA) || 01437 (uVKey == VK_DBE_CODEINPUT) || 01438 (uVKey == VK_DBE_NOCODEINPUT) || 01439 (uVKey == VK_DBE_IME_WORDREGISTER) || 01440 (uVKey == VK_DBE_IME_DIALOG) ); 01441 01442 if (message == WM_SYSKEYDOWN || message == WM_SYSKEYUP ) { 01443 // 01444 // IME may be waiting for VK_MENU, VK_F10 or VK_DBE_xxx 01445 // 01446 if ( uVKey != VK_MENU && uVKey != VK_F10 && !fDBERoman ) { 01447 return dwReturn; 01448 } 01449 } 01450 01451 // 01452 // check if the IME doesn't need ALT key 01453 // 01454 if ( !(pkl->piiex->ImeInfo.fdwProperty & IME_PROP_NEED_ALTKEY) ) { 01455 // 01456 // IME doesn't need ALT key 01457 // 01458 // we don't pass the ALT and ALT+xxx except VK_DBE_xxx keys. 01459 // 01460 if ( ! fDBERoman && 01461 (uVKey == VK_MENU || (lParam & 0x20000000)) // KF_ALTDOWN 01462 ) 01463 { 01464 return dwReturn; 01465 } 01466 } 01467 01468 // 01469 // finaly call back the client 01470 // 01471 01472 ProcessKeyCallClient: 01473 01474 if ((uVKey & 0xff) == VK_PACKET) { 01475 // 01476 // need to retrieve UNICODE character from pti 01477 // 01478 uVKey = MAKELONG(wParam, PtiCurrent()->wchInjected); 01479 } 01480 dwReturn = ClientImmProcessKey( PtoH(pwnd), 01481 pkl->hkl, 01482 uVKey, 01483 lParam, 01484 dwHotKeyID); 01485 01486 // 01487 // Hydra server wants to see the IME hotkeys. 01488 // 01489 if (GetAppImeCompatFlags(GETPTI(pwnd)) & IMECOMPAT_HYDRACLIENT) { 01490 dwReturn &= ~IPHK_HOTKEY; 01491 } 01492 return dwReturn; 01493 }

VOID xxxImmUnloadLayout IN PTHREADINFO  pti,
IN DWORD  dwFlag
 

Definition at line 1070 of file ntimm.c.

References CMSHUNGAPPTIMEOUT, IFL_DEACTIVATEIME, IS_IME_KBDLAYOUT, NULL, PtiCurrentShared, tagTHREADINFO::spwndDefaultIme, ThreadLockAlwaysWithPti, ThreadUnlock, VOID(), and xxxSendMessageTimeout().

Referenced by xxxImmActivateAndUnloadThreadsLayout(), and xxxImmUnloadThreadsLayout().

01073 { 01074 TL tlpwndDefaultIme; 01075 PTHREADINFO ptiCurrent; 01076 ULONG_PTR dwResult; 01077 LRESULT r; 01078 01079 /* 01080 * Do nothing if the thread does not have default IME window. 01081 */ 01082 if (pti->spwndDefaultIme == NULL) 01083 return; 01084 01085 if (pti->spklActive == NULL) 01086 return; 01087 01088 if (dwFlag == IFL_DEACTIVATEIME && 01089 !IS_IME_KBDLAYOUT(pti->spklActive->hkl)) 01090 return; 01091 01092 ptiCurrent = PtiCurrentShared(); 01093 01094 ThreadLockAlwaysWithPti(ptiCurrent, pti->spwndDefaultIme, &tlpwndDefaultIme); 01095 r = xxxSendMessageTimeout(pti->spwndDefaultIme, WM_IME_SYSTEM, 01096 IMS_UNLOADTHREADLAYOUT, (LONG)dwFlag, 01097 SMTO_NOTIMEOUTIFNOTHUNG, CMSHUNGAPPTIMEOUT, &dwResult); 01098 01099 if (!r) { 01100 RIPMSG1(RIP_WARNING, "Timeout in xxxImmUnloadLayout: perhaps this thread (0x%x) is not pumping messages.", 01101 pti->pEThread->Cid.UniqueThread); 01102 } 01103 01104 ThreadUnlock(&tlpwndDefaultIme); 01105 01106 return; 01107 }

VOID xxxImmUnloadThreadsLayout IN PTHREADINFO ptiList,
IN UINT  nEntries,
IN PTLBLOCK  ptlBlockPrev,
IN DWORD  dwFlag
 

Definition at line 961 of file ntimm.c.

References FALSE, IFL_DEACTIVATEIME, IFL_UNLOADIME, INT, IS_IME_KBDLAYOUT, tagTLBLOCK::list, NULL, PtiCurrentShared, tagTLBLOCK::ptlBlockPrev, ThreadLockPti, THREADS_PER_TLBLOCK, ThreadUnlockPti, TIF_INCLEANUP, TRUE, VOID(), and xxxImmUnloadLayout().

Referenced by xxxFreeImeKeyboardLayouts().

00966 { 00967 TLBLOCK tlBlock; 00968 PTHREADINFO ptiCurrent; 00969 INT i, cThreads; 00970 BOOLEAN fPerformUnlock; 00971 00972 ptiCurrent = PtiCurrentShared(); 00973 tlBlock.ptlBlockPrev = ptlBlockPrev; 00974 00975 /* 00976 * Build a list of threads that we need to unload their IME DLL(s). 00977 * We can't just walk the ptiList while we're doing the work, because 00978 * for IME based keyboard layout, we will do callback to client side 00979 * and the pti could get deleted out while we leave the critical section. 00980 */ 00981 for (i = 0, cThreads = 0; i < (INT)nEntries; i++) { 00982 /* 00983 * Skip all the *do nothing* cases in xxxImmUnloadLayout() 00984 * so as to minimize the # of TLBLOCK required. 00985 */ 00986 if ((ptiList[i]->TIF_flags & TIF_INCLEANUP) || ptiList[i]->spwndDefaultIme == NULL) 00987 continue; 00988 00989 if (ptiList[i]->spklActive == NULL) 00990 continue; 00991 00992 if (dwFlag == IFL_DEACTIVATEIME && 00993 !IS_IME_KBDLAYOUT(ptiList[i]->spklActive->hkl)) // #99321 00994 continue; 00995 00996 #if DBG 00997 tlBlock.list[cThreads].dwUnlockedCount = 0; 00998 #endif 00999 ThreadLockPti(ptiCurrent, ptiList[i], &tlBlock.list[cThreads].tlpti); 01000 tlBlock.list[cThreads++].pti = ptiList[i]; 01001 if (cThreads == THREADS_PER_TLBLOCK) { 01002 i++; // 1 more before exit the loop. 01003 break; 01004 } 01005 } 01006 01007 if (i < (INT)nEntries) { 01008 ptiList += i; 01009 nEntries -= i; 01010 xxxImmUnloadThreadsLayout(ptiList, nEntries, &tlBlock, dwFlag); 01011 return; 01012 } 01013 01014 UserAssert(dwFlag == IFL_UNLOADIME || dwFlag == IFL_DEACTIVATEIME); 01015 if (dwFlag == IFL_UNLOADIME) { 01016 dwFlag = IFL_DEACTIVATEIME; 01017 fPerformUnlock = FALSE; 01018 } else { 01019 fPerformUnlock = TRUE; 01020 } 01021 RepeatForUnload: 01022 /* 01023 * Finally, we can unload the IME based keyboard layout 01024 * starting from this run. Work on current TLBLOCK first. 01025 * We walk the list backwards so that the pti unlocks will 01026 * be done in the right order. 01027 */ 01028 i = cThreads - 1; 01029 for (ptlBlockPrev = &tlBlock; ptlBlockPrev; ptlBlockPrev = ptlBlockPrev->ptlBlockPrev) { 01030 for ( ; i >= 0; --i) { 01031 if (!(ptlBlockPrev->list[i].pti->TIF_flags & TIF_INCLEANUP)) { 01032 xxxImmUnloadLayout(ptlBlockPrev->list[i].pti, dwFlag); 01033 } 01034 else { 01035 RIPMSG2(RIP_WARNING, "Thread %#p is cleaned during the loop for %x!", ptlBlockPrev->list[i].pti, dwFlag); 01036 } 01037 01038 if (fPerformUnlock) { 01039 #if DBG 01040 ptlBlockPrev->list[i].dwUnlockedCount++; 01041 #endif 01042 ThreadUnlockPti(ptiCurrent, &ptlBlockPrev->list[i].tlpti); 01043 } 01044 } 01045 i = THREADS_PER_TLBLOCK - 1; 01046 } 01047 01048 if (!fPerformUnlock) { 01049 fPerformUnlock = TRUE; 01050 dwFlag = IFL_UNLOADIME; 01051 goto RepeatForUnload; 01052 } 01053 01054 #if DBG 01055 // Check if all the locked thread is properly unlocked 01056 i = cThreads - 1; 01057 for (ptlBlockPrev = &tlBlock; ptlBlockPrev; ptlBlockPrev = ptlBlockPrev->ptlBlockPrev) { 01058 for ( ; i >= 0; --i) { 01059 UserAssert(ptlBlockPrev->list[i].dwUnlockedCount == 1); 01060 } 01061 i = THREADS_PER_TLBLOCK - 1; 01062 } 01063 #endif 01064 01065 return; 01066 }

VOID xxxNotifyImeShowStatus PWND  pwndIme  ) 
 

Definition at line 2544 of file ntimm.c.

References BOOL, FALSE, tagIMEUI::fShowStatus, GETPTI, gfIMEShowStatus, tagIMEUI::hwndIMC, IS_IME_ENABLED, KeAttachProcess(), KeDetachProcess(), NULL, ProbeAndReadStructure, PtiCurrent, RevalidateHwnd, TestWF, TRUE, VOID(), WFINDESTROY, xxxCheckImeShowStatus(), and xxxSendOpenStatusNotify().

Referenced by xxxBroadcastImeShowStatusChange(), and xxxSetIMEShowStatus().

02545 { 02546 PIMEUI pimeui; 02547 BOOL fShow; 02548 PWND pwnd; 02549 PTHREADINFO ptiIme, ptiCurrent; 02550 BOOL fSendOpenStatusNotify = FALSE; 02551 02552 if (!IS_IME_ENABLED() || TestWF(pwndIme, WFINDESTROY)) { 02553 RIPMSG0(RIP_WARNING, "IME is not enabled or in destroy."); 02554 return; 02555 } 02556 02557 ptiCurrent = PtiCurrent(); 02558 ptiIme = GETPTI(pwndIme); 02559 02560 if (ptiIme != ptiCurrent) { 02561 RIPMSG1(RIP_VERBOSE, "Attaching pti=%#p", ptiIme); 02562 KeAttachProcess(&GETPTI(pwndIme)->ppi->Process->Pcb); 02563 } 02564 02565 try { 02566 pimeui = ((PIMEWND)pwndIme)->pimeui; 02567 fShow = gfIMEShowStatus && ProbeAndReadStructure(pimeui, IMEUI).fCtrlShowStatus; 02568 02569 pwnd = RevalidateHwnd(pimeui->hwndIMC); 02570 02571 if (pwnd != NULL || (pwnd = GETPTI(pwndIme)->pq->spwndFocus) != NULL) { 02572 RIPMSG0(RIP_VERBOSE, "Setting new show status."); 02573 fSendOpenStatusNotify = TRUE; 02574 pimeui->fShowStatus = fShow; 02575 } 02576 } except (W32ExceptionHandler(FALSE, RIP_WARNING)) { 02577 if (ptiIme != ptiCurrent) { 02578 KeDetachProcess(); 02579 } 02580 return; 02581 } 02582 if (ptiIme != ptiCurrent) { 02583 KeDetachProcess(); 02584 } 02585 02586 if (fSendOpenStatusNotify) { 02587 RIPMSG1(RIP_VERBOSE, "Sending OpenStatus fShow=%d", fShow); 02588 xxxSendOpenStatusNotify(ptiIme, pimeui, pwnd, fShow); 02589 } 02590 02591 // Check the show status of all IME windows in the system. 02592 if (!TestWF(pwndIme, WFINDESTROY)) { 02593 xxxCheckImeShowStatus(pwndIme, NULL); 02594 } 02595 }

VOID xxxNotifyIMEStatus IN PWND  pwnd,
IN DWORD  dwOpen,
IN DWORD  dwConversion
 

Definition at line 2295 of file ntimm.c.

References CheckLock, gdwIMEConversionStatus, gdwIMEOpenStatus, GETPTI, gHimcFocus, gptiForeground, tagKL::hkl, HWq, IsHooked, NlsKbdSendIMENotification(), NULL, tagTHREADINFO::pq, SetConvMode(), tagTHREADINFO::spklActive, VOID(), WHF_SHELL, and xxxCallHook().

Referenced by NtUserNotifyIMEStatus().

02299 { 02300 PTHREADINFO pti; 02301 02302 CheckLock(pwnd); 02303 02304 if ( (pti = GETPTI(pwnd)) != NULL && gptiForeground != NULL ) { 02305 if ( pti == gptiForeground || pti->pq == gptiForeground->pq ) { 02306 02307 if ( gHimcFocus != pwnd->hImc || 02308 gdwIMEOpenStatus != dwOpen || 02309 gdwIMEConversionStatus != dwConversion ) { 02310 02311 // 02312 // save the new status 02313 // 02314 gHimcFocus = pwnd->hImc; 02315 if ( gHimcFocus != (HIMC)NULL ) { 02316 02317 RIPMSG2(RIP_VERBOSE, "xxxNotifyIMEStatus: newOpen=%x newConv=%x", 02318 dwOpen, dwConversion); 02319 gdwIMEOpenStatus = dwOpen; 02320 gdwIMEConversionStatus = dwConversion; 02321 02322 // 02323 // set keyboard states that are related to IME conversion status 02324 // 02325 SetConvMode(pti, dwOpen ? dwConversion : 0); 02326 } 02327 02328 // 02329 // notify shell the IME status change 02330 // 02331 // Implementation note: [takaok 9/5/96] 02332 // 02333 // Using HSHELL_LANGUAGE is not the best way to inform shell 02334 // IME status change because we didn't change the keyboard layout. 02335 // ( The spec says HSHELL_LANGUAGE is for keyboard layout change. 02336 // Also passing window handle as WPARAM is not documented ) 02337 // 02338 // This is same as what Win95 does. I won't change this for now 02339 // because in the future shell will be developed by a different 02340 // group in MS. 02341 // 02342 // Currently only Korean Windows is interested in getting 02343 // the conversion status change. 02344 // 02345 if (IsHooked(pti, WHF_SHELL)) { 02346 HKL hkl = NULL; 02347 02348 if (pti->spklActive != NULL) { 02349 hkl = pti->spklActive->hkl; 02350 } 02351 xxxCallHook(HSHELL_LANGUAGE, (WPARAM)HWq(pwnd), (LPARAM)hkl, WH_SHELL); 02352 } 02353 02354 // 02355 // notify keyboard driver 02356 // 02357 NlsKbdSendIMENotification(dwOpen,dwConversion); 02358 } 02359 } 02360 } 02361 }

LRESULT xxxSendMessageToUI PTHREADINFO  ptiIme,
PIMEUI  pimeui,
UINT  message,
WPARAM  wParam,
LPARAM  lParam
 

Definition at line 2461 of file ntimm.c.

References BOOL, CheckCritIn, FALSE, KeAttachProcess(), KeDetachProcess(), L, tagIMEUI::nCntInIMEProc, NULL, tagTHREADINFO::ppi, ProbeAndReadStructure, ProbeAndReadUlong, PtiCurrent, RevalidateHwnd, ThreadLockAlways, ThreadUnlock, TRUE, and xxxSendMessage().

Referenced by xxxSendOpenStatusNotify().

02467 { 02468 PWND pwndUI; 02469 LRESULT lRet = 0L; 02470 TL tl; 02471 BOOL fAttached = FALSE; 02472 02473 CheckCritIn(); 02474 02475 if (ptiIme != PtiCurrent()) { 02476 fAttached = TRUE; 02477 KeAttachProcess(&ptiIme->ppi->Process->Pcb); 02478 } 02479 02480 try { 02481 pwndUI = RevalidateHwnd(ProbeAndReadStructure(pimeui, IMEUI).hwndUI); 02482 } except (W32ExceptionHandler(FALSE, RIP_WARNING)) { 02483 pwndUI = NULL; 02484 } 02485 02486 if (pwndUI != NULL){ 02487 try { 02488 ProbeAndReadUlong((PULONG)&pimeui->nCntInIMEProc); 02489 InterlockedIncrement(&pimeui->nCntInIMEProc); // Mark to avoid recursion. 02490 } except (W32ExceptionHandler(FALSE, RIP_WARNING)) { 02491 goto skip_it; 02492 } 02493 if (fAttached) { 02494 KeDetachProcess(); 02495 } 02496 02497 ThreadLockAlways(pwndUI, &tl); 02498 RIPMSG3(RIP_VERBOSE, "Sending message UI pwnd=%#p, msg:%x to wParam=%#p", pwndUI, message, wParam); 02499 lRet = xxxSendMessage(pwndUI, message, wParam, lParam); 02500 ThreadUnlock(&tl); 02501 02502 if (fAttached) { 02503 KeAttachProcess(&ptiIme->ppi->Process->Pcb); 02504 } 02505 try { 02506 InterlockedDecrement(&pimeui->nCntInIMEProc); // Mark to avoid recursion. 02507 } except (W32ExceptionHandler(FALSE, RIP_WARNING)) { 02508 } 02509 } 02510 skip_it: 02511 if (fAttached) { 02512 KeDetachProcess(); 02513 } 02514 02515 return lRet; 02516 }

VOID xxxSendOpenStatusNotify PTHREADINFO  ptiIme,
PIMEUI  pimeui,
PWND  pwndApp,
BOOL  fOpen
 

Definition at line 2518 of file ntimm.c.

References GETPTI, tagWND::hImc, L, NULL, ThreadLockAlways, ThreadUnlock, VER40, VOID(), xxxSendMessage(), and xxxSendMessageToUI().

Referenced by xxxNotifyImeShowStatus().

02523 { 02524 WPARAM wParam = fOpen ? IMN_OPENSTATUSWINDOW : IMN_CLOSESTATUSWINDOW; 02525 02526 UserAssert(GETPTI(pwndApp)); 02527 02528 if (GETPTI(pwndApp)->dwExpWinVer >= VER40 && pwndApp->hImc != NULL) { 02529 TL tl; 02530 ThreadLockAlways(pwndApp, &tl); 02531 RIPMSG2(RIP_VERBOSE, "Sending %s to pwnd=%#p", 02532 fOpen ? "IMN_OPENSTATUSWINDOW" : "IMN_CLOSESTATUSWINDOW", 02533 pwndApp); 02534 xxxSendMessage(pwndApp, WM_IME_NOTIFY, wParam, 0L); 02535 ThreadUnlock(&tl); 02536 } 02537 else { 02538 xxxSendMessageToUI(ptiIme, pimeui, WM_IME_NOTIFY, wParam, 0L); 02539 } 02540 02541 return; 02542 }

BOOL xxxSetIMEShowStatus IN BOOL  fShow  ) 
 

Definition at line 2606 of file ntimm.c.

References BOOL, CheckCritIn, CreateProfileUserName(), FALSE, FreeProfileUserName(), GETPTI, gfIMEShowStatus, gpqForeground, IMESHOWSTATUS_NOTINITIALIZED, IS_IME_ENABLED, NULL, PMAP_INPUTMETHOD, tagTHREADINFO::spwndDefaultIme, tagQ::spwndFocus, ThreadLockAlways, ThreadUnlock, tagTHREADINFO::TIF_flags, TIF_INCLEANUP, TRUE, UpdateWinIniInt(), and xxxNotifyImeShowStatus().

Referenced by xxxSystemParametersInfo().

02607 { 02608 CheckCritIn(); 02609 02610 UserAssert(fShow == FALSE || fShow == TRUE); 02611 02612 if (gfIMEShowStatus == fShow) { 02613 return TRUE; 02614 } 02615 02616 if (gfIMEShowStatus == IMESHOWSTATUS_NOTINITIALIZED) { 02617 /* 02618 * Called for the first time after logon. 02619 * No need to write the value to the registry. 02620 */ 02621 gfIMEShowStatus = fShow; 02622 } 02623 else { 02624 /* 02625 * We need to save the new fShow status to the registry. 02626 */ 02627 TL tlName; 02628 PUNICODE_STRING pProfileUserName; 02629 BOOL fOK = FALSE; 02630 02631 pProfileUserName = CreateProfileUserName(&tlName); 02632 if (pProfileUserName) { 02633 UserAssert(pProfileUserName != NULL); 02634 fOK = UpdateWinIniInt(pProfileUserName, PMAP_INPUTMETHOD, STR_SHOWIMESTATUS, fShow); 02635 FreeProfileUserName(pProfileUserName, &tlName); 02636 } 02637 if (!fOK) { 02638 return FALSE; 02639 } 02640 gfIMEShowStatus = fShow; 02641 } 02642 02643 /* 02644 * If IME is not enabled, further processing is not needed 02645 */ 02646 if (!IS_IME_ENABLED()) { 02647 return TRUE; 02648 } 02649 02650 /* 02651 * Let the current active IME window know the change. 02652 */ 02653 if (gpqForeground && gpqForeground->spwndFocus) { 02654 PTHREADINFO ptiFocus = GETPTI(gpqForeground->spwndFocus); 02655 TL tl; 02656 02657 UserAssert(ptiFocus); 02658 02659 if (ptiFocus->spwndDefaultIme && !(ptiFocus->TIF_flags & TIF_INCLEANUP)) { 02660 ThreadLockAlways(ptiFocus->spwndDefaultIme, &tl); 02661 xxxNotifyImeShowStatus(ptiFocus->spwndDefaultIme); 02662 ThreadUnlock(&tl); 02663 } 02664 } 02665 02666 return TRUE; 02667 }


Variable Documentation

CONST WCHAR wszDefaultIme[] = L"Default IME" [static]
 

Definition at line 16 of file ntimm.c.

Referenced by xxxCreateDefaultImeWindow().


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