00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
#include "precomp.h"
00013
#pragma hdrstop
00014
00015
00016 static CONST WCHAR
wszDefaultIme[] =
L"Default IME";
00017
00018
#if DBG
00019
BOOL CheckOwnerCirculate(
PWND pwnd)
00020 {
00021
PWND pwndT = pwnd->
spwndOwner;
00022
00023
while (pwndT) {
00024 UserAssert(pwndT->
spwndOwner != pwnd);
00025 pwndT = pwndT->
spwndOwner;
00026 }
00027
return TRUE;
00028 }
00029
#endif
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040 PIMC CreateInputContext(
00041 ULONG_PTR dwClientImcData)
00042 {
00043
PTHREADINFO ptiCurrent;
00044
PIMC pImc;
00045
PDESKTOP pdesk =
NULL;
00046
00047 ptiCurrent =
PtiCurrentShared();
00048
00049
00050
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
00059
00060
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
00070
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
00091
00092
00093
00094 UserAssert(ptiCurrent->
spDefaultImc ==
NULL);
00095
Lock(&ptiCurrent->
spDefaultImc, pImc);
00096 pImc->
pImcNext =
NULL;
00097 }
00098
else {
00099
00100
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 }
00111
00112
00113
00114
00115
00116
00117
00118
00119
00120
00121
00122 BOOL DestroyInputContext(
00123 IN
PIMC pImc)
00124 {
00125
PTHREADINFO ptiImcOwner;
00126
PBWL pbwl;
00127
PWND pwnd;
00128 HWND *phwnd;
00129
PHE phe;
00130
00131 ptiImcOwner =
GETPTI(pImc);
00132
00133
00134
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
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
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
00162
00163
if ((pwnd =
RevalidateHwnd(*phwnd)) ==
NULL)
00164
continue;
00165
00166
00167
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
00180
00181
00182
if (!(phe->
bFlags &
HANDLEF_DESTROY))
00183
HMDestroyUnlockedObject(phe);
00184
00185
return TRUE;
00186 }
00187
00188
00189
00190
00191
00192
00193
00194
00195
00196
00197
00198 VOID FreeInputContext(
00199 IN
PIMC pImc)
00200 {
00201
PIMC pImcT;
00202
00203
00204
00205
00206
00207
if (!
HMMarkObjectDestroy((PVOID)pImc))
00208
return;
00209
00210
00211
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
00223
00224
HMFreeObject((PVOID)pImc);
00225
00226
return;
00227 }
00228
00229
00230
00231
00232
00233
00234
00235
00236
00237
00238
00239 BOOL UpdateInputContext(
00240 IN
PIMC pImc,
00241 IN UPDATEINPUTCONTEXTCLASS UpdateType,
00242 IN ULONG_PTR UpdateValue)
00243 {
00244
PTHREADINFO ptiCurrent, ptiImcOwner;
00245
00246 ptiCurrent =
PtiCurrent();
00247 ptiImcOwner =
GETPTI(pImc);
00248
00249
00250
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 }
00278
00279
00280
00281
00282
00283
00284
00285
00286
00287
00288
00289 HIMC
AssociateInputContext(
00290 IN
PWND pWnd,
00291 IN
PIMC pImc)
00292 {
00293 HIMC hImcRet = pWnd->hImc;
00294 pWnd->hImc = (HIMC)
PtoH(pImc);
00295
00296
return hImcRet;
00297 }
00298
00299 AIC_STATUS AssociateInputContextEx(
00300 IN
PWND pWnd,
00301 IN
PIMC pImc,
00302 IN DWORD dwFlag)
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
00313
00314 pImc = ptiWnd->
spDefaultImc;
00315
00316 }
else if (pImc !=
NULL &&
GETPTI(pImc) != ptiWnd) {
00317
00318
00319
00320
00321 RIPERR0(ERROR_ACCESS_DENIED, RIP_WARNING,
00322
"AssociateInputContextEx: pwnd not of Imc pti");
00323
return AIC_ERROR;
00324 }
00325
00326
00327
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
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
00346
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
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
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 }
00394
00395
00396
00397
00398
00399
00400
00401
00402
00403
00404
00405 VOID xxxFocusSetInputContext(
00406 IN
PWND pWnd,
00407 IN BOOL fActivate,
00408 IN BOOL fQueueMsg)
00409 {
00410
PTHREADINFO pti;
00411
PWND pwndDefaultIme;
00412
TL tlpwndDefaultIme;
00413
00414
CheckLock(pWnd);
00415
00416 pti =
GETPTI(pWnd);
00417
00418
00419
00420
00421
00422
00423
if (
TestCF(pWnd,
CFIME) ||
00424 (pWnd->pcls->atomClassName ==
gpsi->
atomSysClass[
ICLS_IME]))
00425
return;
00426
00427
00428
00429
00430
if ((pwndDefaultIme = pti->
spwndDefaultIme) ==
NULL)
00431
return;
00432
00433
00434
00435
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, 1
L, 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 }
00464
00465
00466
00467
00468
00469
00470
00471
00472
00473
00474
00475 UINT BuildHimcList(
00476
PTHREADINFO pti,
00477 UINT cHimcMax,
00478 HIMC *ccxphimcFirst)
00479 {
00480
PIMC pImcT;
00481
UINT i = 0;
00482
00483
if (pti ==
NULL) {
00484
00485
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
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 }
00520
00521
00522
00523
00524
00525
00526
00527
00528
00529
00530
00531 PWND xxxCreateDefaultImeWindow(
00532 IN
PWND pwnd,
00533 IN ATOM atomT,
00534 IN HANDLE hInst)
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
00547
00548
00549 UserAssert(!(ptiCurrent->
TIF_flags &
TIF_DISABLEIME));
00550 UserAssert(!
TestWF(pwnd,
WFSERVERSIDEPROC));
00551
00552
00553
00554
00555
00556
if (ptiCurrent->
spDefaultImc ==
NULL &&
00557 ptiCurrent->pEThread->Cid.UniqueProcess ==
gpidLogon)
00558
CreateInputContext(0);
00559
00560
00561
00562
00563
00564
if (ptiCurrent->
spDefaultImc ==
NULL)
00565
return (
PWND)
NULL;
00566
00567
00568
00569
00570
if (atomT ==
gpsi->
atomSysClass[
ICLS_IME] ||
TestCF(pwnd,
CFIME))
00571
return (
PWND)
NULL;
00572
00573
00574
00575
00576
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
00587
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 }
00631
00632
00633
00634
00635
00636
00637
00638
00639
00640
00641
00642
00643
00644
00645
00646 BOOL xxxImmActivateThreadsLayout(
00647
PTHREADINFO pti,
00648
PTLBLOCK ptlBlockPrev,
00649
PKL pkl)
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
00662
00663
00664
00665
00666
for (ptiT = pti; ptiT !=
NULL; ptiT = ptiT->
ptiSibling) {
00667
00668
00669
00670
00671
if (ptiT->
spklActive == pkl || (ptiT->
TIF_flags &
TIF_INCLEANUP))
00672
continue;
00673
00674 UserAssert(ptiT->
pClientInfo !=
NULL);
00675 UserAssert(ptiT->
ppi ==
PpiCurrent());
00676
00677
if (ptiT->
spwndDefaultIme ==
NULL) {
00678
00679
00680
00681
00682
00683
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
00706
00707
if (ptlBlockPrev ==
NULL && ptiT ==
NULL && cThreads == 0)
00708
return FALSE;
00709
00710
00711
00712
00713
00714
if (ptiT !=
NULL && ptiT->ptiSibling !=
NULL) {
00715 tlBlock.
ptlBlockPrev = ptlBlockPrev;
00716
return xxxImmActivateThreadsLayout(ptiT->ptiSibling, &tlBlock, pkl);
00717 }
00718
00719
00720
00721
00722
00723
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 }
00748
00749 VOID xxxImmActivateAndUnloadThreadsLayout(
00750 IN
PTHREADINFO *ptiList,
00751 IN UINT nEntries,
00752 IN
PTLBLOCK ptlBlockPrev,
00753
PKL pklCurrent,
00754 DWORD dwHklReplace)
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
00769
00770
00771
00772
00773
for (i = 0, cThreads = 0; i < (
INT)nEntries; i++) {
00774
DWORD dwFlags = 0;
00775
00776
00777
00778
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
00792
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
00814
00815
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++;
00834
break;
00835 }
00836 }
00837 }
00838
00839
00840
00841
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
00852
00853
00854
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
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
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
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 }
00911
00912
00913
00914
00915
00916
00917
00918
00919
00920
00921 VOID xxxImmActivateLayout(
00922 IN
PTHREADINFO pti,
00923 IN
PKL pkl)
00924 {
00925
TL tlpwndDefaultIme;
00926
PTHREADINFO ptiCurrent;
00927
00928
CheckLock(pkl);
00929
00930
00931
00932
00933
if (pti->spklActive == pkl)
00934
return;
00935
00936
if (pti->spwndDefaultIme ==
NULL) {
00937
00938
00939
00940
00941
Lock(&pti->spklActive, pkl);
00942
return;
00943 }
00944
00945 ptiCurrent =
PtiCurrentShared();
00946
00947
00948
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 }
00959
00960
00961 VOID xxxImmUnloadThreadsLayout(
00962 IN
PTHREADINFO *ptiList,
00963 IN UINT nEntries,
00964 IN
PTLBLOCK ptlBlockPrev,
00965 IN DWORD dwFlag)
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
00977
00978
00979
00980
00981
for (i = 0, cThreads = 0; i < (
INT)nEntries; i++) {
00982
00983
00984
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))
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++;
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
01024
01025
01026
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
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 }
01067
01068
01069
01070 VOID xxxImmUnloadLayout(
01071 IN
PTHREADINFO pti,
01072 IN DWORD dwFlag)
01073 {
01074
TL tlpwndDefaultIme;
01075
PTHREADINFO ptiCurrent;
01076 ULONG_PTR dwResult;
01077 LRESULT r;
01078
01079
01080
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 }
01108
01109
01110
01111
01112
01113
01114
01115
01116
01117
01118 PIMEINFOEX xxxImmLoadLayout(
01119 IN HKL hKL)
01120 {
01121
PIMEINFOEX piiex;
01122
PTHREADINFO ptiCurrent;
01123
TL tlPool;
01124
01125
01126
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
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 }
01155
01156
01157
01158
01159
01160
01161
01162
01163
01164
01165
01166 BOOL GetImeInfoEx(
01167
PWINDOWSTATION pwinsta,
01168
PIMEINFOEX piiex,
01169 IMEINFOEXCLASS SearchType)
01170 {
01171
PKL pkl, pklFirst;
01172
01173
01174
01175
01176
01177
01178
01179
01180
01181
if (pwinsta ==
NULL) {
01182
return FALSE;
01183 }
01184
01185
01186
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 }
01226
01227
01228
01229
01230
01231
01232
01233
01234
01235
01236
01237 BOOL SetImeInfoEx(
01238
PWINDOWSTATION pwinsta,
01239
PIMEINFOEX piiex)
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
01256
01257
if (pkl->
piiex ==
NULL)
01258
return FALSE;
01259
01260
01261
01262
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 }
01276
01277
01278
01279
01280
01281
01282
01283
01284
01285
01286 DWORD xxxImmProcessKey(
01287 IN
PQ pq,
01288 IN
PWND pwnd,
01289 IN UINT message,
01290 IN WPARAM wParam,
01291 IN LPARAM lParam)
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
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
01317
01318
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
01339
01340
if (dwHotKeyID >= IME_HOTKEY_DSWITCH_FIRST && dwHotKeyID <= IME_HOTKEY_DSWITCH_LAST) {
01341 UserAssert(hklTarget !=
NULL);
01342
if (pkl->
hkl != hklTarget) {
01343
01344
01345
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
01360
01361
01362
return 0;
01363 }
01364
01365
if ( dwHotKeyID != IME_INVALID_HOTKEY ) {
01366
01367
01368
01369
01370
goto ProcessKeyCallClient;
01371 }
01372
01373
01374
01375
01376
01377
if ( pkl->
piiex ==
NULL ) {
01378
return dwReturn;
01379 }
01380
01381
01382
01383
01384 pImc =
HtoP(pwnd->hImc);
01385
if ( pImc ==
NULL ) {
01386
return dwReturn;
01387 }
01388
01389
#ifdef LATER
01390
01391
01392
01393
01394
01395
01396
01397
01398
01399
01400
01401
01402
01403
01404
if ( (piix->ImeInfo.fdwProperty & IME_PROP_NO_KEYS_ON_CLOSE) &&
01405 (!pimc->fdwState & IMC_OPEN) &&
01406 uVKey != VK_SHIFT &&
01407 uVKey != VK_CONTROL &&
01408 uVKey != VK_CAPITAL &&
01409 uVKey != VK_KANA &&
01410 uVKey != VK_NUMLOCK &&
01411 uVKey != VK_SCROLL )
01412 {
01413
01414
if( !(pimc->fdwConvMode & IME_CMODE_HANJACONVERT) ) {
01415
return dwReturn;
01416 }
01417 }
01418
#endif
01419
01420
01421
01422
01423
if ( lParam & 0x80000000 &&
01424 pkl->
piiex->
ImeInfo.fdwProperty & IME_PROP_IGNORE_UPKEYS )
01425 {
01426
return dwReturn;
01427 }
01428
01429
01430
01431
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
01445
01446
if ( uVKey != VK_MENU && uVKey != VK_F10 && !fDBERoman ) {
01447
return dwReturn;
01448 }
01449 }
01450
01451
01452
01453
01454
if ( !(pkl->
piiex->
ImeInfo.fdwProperty & IME_PROP_NEED_ALTKEY) ) {
01455
01456
01457
01458
01459
01460
if ( ! fDBERoman &&
01461 (uVKey == VK_MENU || (lParam & 0x20000000))
01462 )
01463 {
01464
return dwReturn;
01465 }
01466 }
01467
01468
01469
01470
01471
01472 ProcessKeyCallClient:
01473
01474
if ((uVKey & 0xff) == VK_PACKET) {
01475
01476
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
01488
01489
if (
GetAppImeCompatFlags(
GETPTI(pwnd)) & IMECOMPAT_HYDRACLIENT) {
01490 dwReturn &= ~
IPHK_HOTKEY;
01491 }
01492
return dwReturn;
01493 }
01494
01495
01496
01497
01498
01499
01500
01501
01502
01503 BOOL ImeCanDestroyDefIME(
01504
PWND pwndDefaultIme,
01505
PWND pwndDestroy)
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
01524
01525
01526
01527
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
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
01554
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
01569
01570
01571
if (pwndDefaultIme->
spwndOwner ==
NULL ||
01572 pwndDestroy == pwndDefaultIme->
spwndOwner) {
01573
01574
01575
Unlock(&pwndDefaultIme->
spwndOwner);
01576
01577
01578
01579
01580
return TRUE;
01581 }
01582
01583
return FALSE;
01584 }
01585
01586
01587
01588
01589
01590
01591
01592
01593
01594 BOOL IsChildSameThread(
01595
PWND pwndParent,
01596
PWND pwndChild)
01597 {
01598
PWND pwnd;
01599
PTHREADINFO ptiChild =
GETPTI(pwndChild);
01600
01601
for (pwnd = pwndParent->
spwndChild; pwnd; pwnd = pwnd->
spwndNext) {
01602
01603
01604
01605
01606
if (!
TestwndChild(pwnd)) {
01607
PWND pwndOwner = pwnd;
01608
BOOL fFoundOwner =
FALSE;
01609
01610
01611
01612
01613
if (pwnd->
pcls->
atomClassName ==
gpsi->
atomSysClass[
ICLS_MENU])
01614
continue;
01615
01616
while (pwndOwner !=
NULL) {
01617
01618
01619
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
01636
01637
if (pwnd == pwndChild)
01638
continue;
01639
01640
01641
01642
01643
if (
GETPTI(pwnd) == ptiChild) {
01644
PWND pwndT = pwnd;
01645
BOOL fFoundImeWnd =
FALSE;
01646
01647
01648
01649
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 }
01678
01679
01680
01681
01682
01683
01684
01685
01686
01687 BOOL ImeCanDestroyDefIMEforChild(
01688
PWND pwndDefaultIme,
01689
PWND pwndDestroy)
01690 {
01691
PWND pwnd;
01692
PIMEUI pimeui;
01693
01694 pimeui = ((
PIMEWND)pwndDefaultIme)->pimeui;
01695
01696
01697
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
01711
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
01727
01728
01729
return TRUE;
01730 }
01731
01732
01733
01734
01735
01736
01737
01738
01739
01740 VOID ImeCheckTopmost(
01741
PWND pwndIme)
01742 {
01743
if (pwndIme->
spwndOwner) {
01744
PWND pwndInsertBeforeThis;
01745
01746
01747
01748
01749
01750
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 }
01761
01762
01763
01764
01765
01766
01767
01768
01769
01770 VOID ImeSetFutureOwner(
01771
PWND pwndIme,
01772
PWND pwndOrgOwner)
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
01784
01785
while ((pwndOwner = pwnd->
spwndOwner) !=
NULL &&
01786
GETPTI(pwndOwner) == ptiImeWnd)
01787 pwnd = pwndOwner;
01788
01789
01790
01791
01792
if (
TestWF(pwnd,
WFBOTTOMMOST) && !
TestWF(pwndOrgOwner,
WFBOTTOMMOST))
01793 pwnd = pwndOrgOwner;
01794
01795
01796
01797
01798
01799
if (
TestCF(pwnd,
CFIME) ||
01800 pwnd->
pcls->
atomClassName ==
gpsi->
atomSysClass[
ICLS_IME])
01801 pwnd = pwndOrgOwner;
01802
01803
01804
01805
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
01821
01822
01823
if (
TestCF(pwndT,
CFIME) ||
01824 pwndT->
pcls->
atomClassName ==
gpsi->
atomSysClass[
ICLS_IME])
01825
continue;
01826
01827
01828
if (
TestWF(pwndT,
WFINDESTROY))
01829
continue;
01830
01831
01832
01833
01834
01835
01836
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 }
01853
01854
01855
01856
01857
01858
01859
01860
01861
01862 VOID ImeSetTopmostChild(
01863
PWND pwndParent,
01864 BOOL fMakeTopmost)
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 }
01881
01882
01883
01884
01885
01886
01887
01888
01889
01890
01891 PWND GetLastTopMostWindowNoIME(
PWND pwndRoot)
01892 {
01893
PWND pwndT =
_GetDesktopWindow();
01894
PWND pwndRet =
NULL;
01895
01896
01897
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
01915
01916 pwndT = pwndT->
spwndChild;
01917
01918
01919
01920
01921
while (
TestWF(pwndT,
WEFTOPMOST)) {
01922
PWND pwndOwner = pwndT;
01923
BOOL fOwned =
FALSE;
01924
01925
01926
01927
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
01943
01944 pwndT = pwndT->
spwndNext;
01945 UserAssert(pwndT->spwndParent ==
_GetDesktopWindow());
01946 }
01947
01948
return pwndRet;
01949 }
01950
01951
01952
#if DBG
01953
void ImeCheckSetTopmostLink(
PWND pwnd,
PWND pwndInsFirst,
PWND pwndIns)
01954 {
01955
PWND pwndDebT0 = pwndInsFirst;
01956
BOOL fFound =
FALSE;
01957
01958
if (pwndDebT0) {
01959
while (pwndDebT0 && (pwndDebT0 != pwndIns)) {
01960
if (pwndDebT0 == pwnd)
01961 fFound =
TRUE;
01962
01963 pwndDebT0 = pwndDebT0->
spwndNext;
01964 }
01965
01966
if (pwndDebT0 ==
NULL) {
01967 RIPMSG3(RIP_ERROR,
"pwndIns(%#p) is upper that pwndInsFirst(%#p) pwnd is (%#p)", pwndIns, pwndInsFirst, pwnd);
01968 }
else if (fFound) {
01969 RIPMSG3(RIP_ERROR,
"pwnd(%#p) is between pwndInsFirst(%#p) and pwndIns(%#p)", pwnd, pwndInsFirst, pwndIns);
01970 }
01971 }
else if (pwndIns) {
01972 pwndDebT0 = pwnd->
spwndParent->
spwndChild;
01973
01974
while (pwndDebT0 && (pwndDebT0 != pwndIns)) {
01975
if (pwndDebT0 == pwnd)
01976 fFound =
TRUE;
01977
01978 pwndDebT0 = pwndDebT0->
spwndNext;
01979 }
01980
01981
if (fFound) {
01982 RIPMSG3(RIP_ERROR,
"pwnd(%#p) is between TOPLEVEL pwndInsFirst(%#p) and pwndIns(%#p)", pwnd, pwndInsFirst, pwndIns);
01983 }
01984 }
01985 }
01986
#endif
01987
01988
01989
01990
01991
01992
01993
01994
01995 VOID ImeSetTopmost(
01996
PWND pwndRootIme,
01997 BOOL fMakeTopmost,
01998
PWND pwndInsertBefore)
01999 {
02000
PWND pwndParent = pwndRootIme->
spwndParent;
02001
PWND pwndInsert =
PWND_TOP;
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
02014
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
02052
02053
02054
02055
while (pwnd !=
NULL) {
02056
02057
02058
02059
02060
PWND pwndNext = pwnd->
spwndNext;
02061
02062
02063
02064
02065
if (
GETPTI(pwnd) !=
GETPTI(pwndRootIme))
02066
goto ist_next;
02067
02068
02069
02070
02071
if (!
TestCF(pwnd,
CFIME) &&
02072 pwnd->
pcls->
atomClassName !=
gpsi->
atomSysClass[
ICLS_IME])
02073
goto ist_next;
02074
02075
02076
02077
02078
if (pwnd == pwndInsert)
02079
goto ist_next;
02080
02081 pwndT = pwnd;
02082
while (pwndT !=
NULL) {
02083
if (pwndT == pwndRootIme) {
02084
02085
02086
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
02105
02106
02107 UserAssert(pwndParent->
spwndChild == pwndNext || !
TestWF(pwndParent->
spwndChild,
WEFTOPMOST));
02108 }
02109
else if (pwndInsert->spwndNext !=
NULL) {
02110
02111
02112
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;
02126 }
02127 pwndT = pwndT->
spwndOwner;
02128 }
02129 ist_next:
02130 pwnd = pwndNext;
02131
02132
02133
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 }
02144
02145
02146
02147
02148
02149
02150
02151
02152
02153
02154 PSOFTKBDDATA
ProbeAndCaptureSoftKbdData(
02155 PSOFTKBDDATA Source)
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 }
02192
02193
02194
02195
02196 VOID SetConvMode(
PTHREADINFO pti, DWORD dwConversion )
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 }
02286
02287
02288
02289
02290
02291
02292
02293
02294
02295 VOID xxxNotifyIMEStatus(
02296 IN
PWND pwnd,
02297 IN DWORD dwOpen,
02298 IN DWORD dwConversion )
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
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
02324
02325
SetConvMode(pti, dwOpen ? dwConversion : 0);
02326 }
02327
02328
02329
02330
02331
02332
02333
02334
02335
02336
02337
02338
02339
02340
02341
02342
02343
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
02356
02357
NlsKbdSendIMENotification(dwOpen,dwConversion);
02358 }
02359 }
02360 }
02361 }
02362
02363
02364
02365
02366
02367
02368
02369
02370
02371
02372
02373
02374
02375 BOOL xxxCheckImeShowStatus(
PWND pwndIme,
PTHREADINFO pti)
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
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
02397
02398
02399
if (pwndT ==
NULL || (pwndIme == pwndT)) {
02400
continue;
02401 }
02402
02403
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
02418
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, 0
L);
02450
ThreadUnlock(&tl);
02451 }
02452
02453 }
02454 }
02455 }
02456
FreeHwndList(pbwl);
02457 }
02458
return fRet;
02459 }
02460
02461 LRESULT
xxxSendMessageToUI(
02462
PTHREADINFO ptiIme,
02463
PIMEUI pimeui,
02464 UINT message,
02465 WPARAM wParam,
02466 LPARAM lParam)
02467 {
02468
PWND pwndUI;
02469 LRESULT lRet = 0
L;
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);
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);
02507 } except (W32ExceptionHandler(
FALSE, RIP_WARNING)) {
02508 }
02509 }
02510 skip_it:
02511
if (fAttached) {
02512
KeDetachProcess();
02513 }
02514
02515
return lRet;
02516 }
02517
02518 VOID xxxSendOpenStatusNotify(
02519
PTHREADINFO ptiIme,
02520
PIMEUI pimeui,
02521
PWND pwndApp,
02522 BOOL fOpen)
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, 0
L);
02535
ThreadUnlock(&tl);
02536 }
02537
else {
02538
xxxSendMessageToUI(ptiIme, pimeui, WM_IME_NOTIFY, wParam, 0
L);
02539 }
02540
02541
return;
02542 }
02543
02544 VOID xxxNotifyImeShowStatus(
PWND pwndIme)
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
02592
if (!
TestWF(pwndIme,
WFINDESTROY)) {
02593
xxxCheckImeShowStatus(pwndIme,
NULL);
02594 }
02595 }
02596
02597
02598
02599
02600
02601
02602
02603
02604
02605
02606 BOOL xxxSetIMEShowStatus(IN BOOL fShow)
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
02619
02620
02621
gfIMEShowStatus = fShow;
02622 }
02623
else {
02624
02625
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
02645
02646
if (!
IS_IME_ENABLED()) {
02647
return TRUE;
02648 }
02649
02650
02651
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 }
02668
02669
02670
02671
02672
02673
02674
02675
02676
02677
02678
02679 VOID xxxBroadcastImeShowStatusChange(
PWND pwndIme, BOOL fShow)
02680 {
02681
CheckCritIn();
02682
02683
gfIMEShowStatus = !!fShow;
02684
xxxNotifyImeShowStatus(pwndIme);
02685 }
02686
02687
02688
02689
02690
02691
02692
02693
02694 VOID xxxCheckImeShowStatusInThread(
PWND pwndIme)
02695 {
02696
if (
IS_IME_ENABLED()) {
02697 UserAssert(pwndIme);
02698
02699
if (!
TestWF(pwndIme,
WFINDESTROY)) {
02700
xxxCheckImeShowStatus(pwndIme,
GETPTI(pwndIme));
02701 }
02702 }
02703 }
02704
02705 BOOL _GetIMEShowStatus(VOID)
02706 {
02707
return gfIMEShowStatus !=
FALSE;
02708 }
02709