00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
#include "precomp.h"
00013
#pragma hdrstop
00014
00015 #define IMCC_ALLOC_TOOLARGE 0x1000
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026 HIMC WINAPI
ImmCreateContext(
void)
00027 {
00028
PCLIENTIMC pClientImc;
00029 HIMC hImc =
NULL_HIMC;
00030
00031
if (!
IS_IME_ENABLED()) {
00032
return NULL_HIMC;
00033 }
00034
00035 pClientImc =
ImmLocalAlloc(HEAP_ZERO_MEMORY,
sizeof(
CLIENTIMC));
00036
00037
if (pClientImc !=
NULL) {
00038
00039 hImc =
NtUserCreateInputContext((ULONG_PTR)pClientImc);
00040
if (hImc ==
NULL_HIMC) {
00041
ImmLocalFree(pClientImc);
00042
return NULL_HIMC;
00043 }
00044
00045
InitImcCrit(pClientImc);
00046 pClientImc->dwImeCompatFlags = (
DWORD)
NtUserGetThreadState(UserThreadStateImeCompatFlags);
00047 }
00048
00049
return hImc;
00050 }
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061 BOOL WINAPI
ImmDestroyContext(
00062 HIMC hImc)
00063 {
00064
if (!
IS_IME_ENABLED()) {
00065
return FALSE;
00066 }
00067
00068
if (
GetInputContextThread(hImc) != GetCurrentThreadId()) {
00069 RIPMSG1(RIP_WARNING,
00070
"ImmDestroyContext: Invalid input context access %lx.", hImc);
00071
return FALSE;
00072 }
00073
00074
return DestroyInputContext(hImc,
GetKeyboardLayout(0),
FALSE);
00075 }
00076
00077
00078
00079
00080
00081
00082
00083
00084
00085
00086 HIMC WINAPI
ImmAssociateContext(
00087 HWND hWnd,
00088 HIMC hImc)
00089 {
00090
PWND pWnd;
00091 HIMC hPrevImc;
00092
AIC_STATUS Status;
00093
00094
00095
if (!
IS_IME_ENABLED()) {
00096
return NULL_HIMC;
00097 }
00098
00099
if ((pWnd =
ValidateHwnd(
hWnd)) == (
PWND)
NULL) {
00100 RIPMSG1(RIP_WARNING,
00101
"ImmAssociateContext: invalid window handle %x",
hWnd);
00102
return NULL_HIMC;
00103 }
00104
00105
00106
00107
if (hImc !=
NULL_HIMC &&
00108
GetInputContextThread(hImc) != GetCurrentThreadId()) {
00109 RIPMSG1(RIP_WARNING,
00110
"ImmAssociateContext: Invalid input context access %lx.", hImc);
00111
return NULL_HIMC;
00112 }
00113
00114
00115
00116
00117
if (pWnd->
hImc == hImc)
00118
return hImc;
00119
00120 hPrevImc = pWnd->
hImc;
00121
00122
Status =
NtUserAssociateInputContext(
hWnd, hImc, 0);
00123
00124
switch (
Status) {
00125
case AIC_FOCUSCONTEXTCHANGED:
00126
if (
IsWndEqual(
NtUserQueryWindow(
hWnd, WindowFocusWindow),
hWnd)) {
00127
ImmSetActiveContext(
hWnd, hPrevImc,
FALSE);
00128
ImmSetActiveContext(
hWnd, hImc,
TRUE);
00129 }
00130
00131
00132
00133
case AIC_SUCCESS:
00134
return hPrevImc;
00135
00136
default:
00137
return NULL_HIMC;
00138 }
00139 }
00140
00141
00142 BOOL WINAPI
ImmAssociateContextEx(
00143 HWND hWnd,
00144 HIMC hImc,
00145 DWORD dwFlag)
00146 {
00147 HWND hWndFocus;
00148
PWND pWndFocus;
00149 HIMC hImcFocusOld;
00150
AIC_STATUS Status;
00151
00152
if (!
IS_IME_ENABLED()) {
00153
return FALSE;
00154 }
00155
00156 hWndFocus =
NtUserQueryWindow(
hWnd, WindowFocusWindow);
00157
00158
if (hImc !=
NULL_HIMC && !(dwFlag & IACE_DEFAULT) &&
00159
GetInputContextThread(hImc) != GetCurrentThreadId()) {
00160 RIPMSG1(RIP_WARNING,
00161
"ImmAssociateContextEx: Invalid input context access %lx.", hImc);
00162
return FALSE;
00163 }
00164
00165
if ((pWndFocus =
ValidateHwnd(hWndFocus)) != (
PWND)
NULL)
00166 hImcFocusOld = pWndFocus->
hImc;
00167
else
00168 hImcFocusOld =
NULL_HIMC;
00169
00170
Status =
NtUserAssociateInputContext(
hWnd, hImc, dwFlag);
00171
00172
switch (
Status) {
00173
case AIC_FOCUSCONTEXTCHANGED:
00174
if ((pWndFocus =
ValidateHwnd(hWndFocus)) != (
PWND)
NULL) {
00175 hImc = pWndFocus->
hImc;
00176
if (hImc != hImcFocusOld) {
00177
ImmSetActiveContext(hWndFocus, hImcFocusOld,
FALSE);
00178
ImmSetActiveContext(hWndFocus, hImc,
TRUE);
00179 };
00180 };
00181
00182
00183
00184
case AIC_SUCCESS:
00185
return TRUE;
00186
00187
default:
00188
return FALSE;
00189 }
00190 }
00191
00192
00193
00194
00195
00196
00197
00198
00199
00200
00201 HIMC WINAPI
ImmGetContext(
00202 HWND hWnd)
00203 {
00204
if (
hWnd ==
NULL ) {
00205 RIPMSG1(RIP_WARNING,
00206
"ImmGetContext: invalid window handle %x",
hWnd);
00207
return NULL_HIMC;
00208 }
00209
00210
00211
00212
00213
return ImmGetSaveContext(
hWnd,
IGSC_WINNLSCHECK );
00214 }
00215
00216
00217
00218
00219
00220
00221
00222
00223
00224
00225 HIMC
ImmGetSaveContext(
00226 HWND hWnd,
00227 DWORD dwFlag)
00228 {
00229 HIMC hRetImc;
00230
PCLIENTIMC pClientImc;
00231
PWND pwnd;
00232
00233
if (!
IS_IME_ENABLED()) {
00234
return NULL_HIMC;
00235 }
00236
00237
if (
hWnd ==
NULL) {
00238
00239
00240
00241 hRetImc = (HIMC)
NtUserGetThreadState(UserThreadStateDefaultInputContext);
00242 }
00243
else {
00244
00245
00246
00247
if ((pwnd =
ValidateHwnd(
hWnd)) == (
PWND)
NULL) {
00248 RIPMSG1(RIP_WARNING,
00249
"ImmGetSaveContext: invalid window handle %x",
hWnd);
00250
return NULL_HIMC;
00251 }
00252
00253
00254
00255
if (!
TestWindowProcess(pwnd)) {
00256 RIPMSG0(RIP_WARNING,
00257
"ImmGetSaveContext: can not get input context of other process");
00258
return NULL_HIMC;
00259 }
00260 hRetImc = pwnd->
hImc;
00261
00262
if (hRetImc ==
NULL_HIMC && (dwFlag &
IGSC_DEFIMCFALLBACK)) {
00263
00264
00265
00266
00267 hRetImc = (HIMC)
NtUserQueryWindow(
hWnd, WindowDefaultInputContext);
00268 }
00269 }
00270
00271 pClientImc =
ImmLockClientImc(hRetImc);
00272
if (pClientImc ==
NULL)
00273
return NULL_HIMC;
00274
00275
if ((dwFlag &
IGSC_WINNLSCHECK) &&
TestICF(pClientImc,
IMCF_WINNLSDISABLE))
00276 hRetImc =
NULL_HIMC;
00277
00278
ImmUnlockClientImc(pClientImc);
00279
00280
return hRetImc;
00281 }
00282
00283
00284
00285
00286
00287
00288
00289
00290
00291
00292 BOOL WINAPI
ImmReleaseContext(
00293 HWND hWnd,
00294 HIMC hImc)
00295 {
00296 UNREFERENCED_PARAMETER(
hWnd);
00297 UNREFERENCED_PARAMETER(hImc);
00298
00299
return TRUE;
00300 }
00301
00302
00303
00304
00305
00306
00307
00308
00309 BOOL ImmSetActiveContext(
00310 HWND hWnd,
00311 HIMC hImc,
00312 BOOL fActivate)
00313 {
00314
PCLIENTIMC pClientImc;
00315 PINPUTCONTEXT pInputContext;
00316
PIMEDPI pImeDpi;
00317
DWORD dwISC;
00318 HIMC hSaveImc;
00319 HWND hDefImeWnd;
00320
DWORD dwOpenStatus = 0;
00321
DWORD dwConversion = 0;
00322
#ifdef DEBUG
00323
PWND pWnd =
ValidateHwnd(
hWnd);
00324
00325
if (pWnd !=
NULL &&
GETPTI(pWnd) !=
PtiCurrent()) {
00326 RIPMSG1(RIP_WARNING,
"hWnd (=%lx) is not of current thread.",
hWnd);
00327 }
00328
#endif
00329
00330
if (!
IS_IME_ENABLED()) {
00331
return FALSE;
00332 }
00333
00334 dwISC = ISC_SHOWUIALL;
00335
00336 pClientImc =
ImmLockClientImc(hImc);
00337
00338
if (!fActivate) {
00339
if (pClientImc !=
NULL)
00340
ClrICF(pClientImc,
IMCF_ACTIVE);
00341
goto NotifySetActive;
00342 }
00343
00344
if (hImc ==
NULL_HIMC) {
00345 hSaveImc =
ImmGetSaveContext(
hWnd,
IGSC_DEFIMCFALLBACK);
00346 pInputContext =
ImmLockIMC(hSaveImc);
00347
if (pInputContext !=
NULL) {
00348 pInputContext->hWnd =
hWnd;
00349
ImmUnlockIMC(hSaveImc);
00350 }
00351
goto NotifySetActive;
00352 }
00353
00354
00355
00356
00357
if (pClientImc ==
NULL)
00358
return FALSE;
00359
00360 pInputContext =
ImmLockIMC(hImc);
00361
if (pInputContext ==
NULL) {
00362
ImmUnlockClientImc(pClientImc);
00363
return FALSE;
00364 }
00365
00366 pInputContext->hWnd =
hWnd;
00367
SetICF(pClientImc,
IMCF_ACTIVE);
00368
00369
#ifdef LATER
00370
00371
#endif
00372
00373
if (pInputContext->fdw31Compat & F31COMPAT_MCWHIDDEN)
00374 dwISC = ISC_SHOWUIALL - ISC_SHOWUICOMPOSITIONWINDOW;
00375
00376 dwOpenStatus = (
DWORD)pInputContext->fOpen;
00377 dwConversion = pInputContext->fdwConversion;
00378
ImmUnlockIMC(hImc);
00379
00380 NotifySetActive:
00381
00382 pImeDpi =
ImmLockImeDpi(
GetKeyboardLayout(0));
00383
if (pImeDpi !=
NULL) {
00384 (*pImeDpi->
pfn.
ImeSetActiveContext)(hImc, fActivate);
00385
ImmUnlockImeDpi(pImeDpi);
00386 }
00387
00388
00389
00390
00391
if (
IsWindow(
hWnd)) {
00392
SendMessage(
hWnd, WM_IME_SETCONTEXT, fActivate, dwISC);
00393
00394
00395
00396
00397
if ( fActivate )
00398
NtUserNotifyIMEStatus(
hWnd, dwOpenStatus, dwConversion );
00399 }
00400
else if (!fActivate) {
00401
00402
00403
00404
00405
if ((hDefImeWnd =
ImmGetDefaultIMEWnd(
NULL)) !=
NULL) {
00406
SendMessage(hDefImeWnd, WM_IME_SETCONTEXT, fActivate, dwISC);
00407 }
00408
else {
00409 RIPMSG0(RIP_WARNING,
00410
"ImmSetActiveContext: can't send WM_IME_SETCONTEXT(FALSE).");
00411 }
00412 }
00413
#ifdef DEBUG
00414
else {
00415 RIPMSG0(RIP_WARNING,
00416
"ImmSetActiveContext: can't send WM_IME_SETCONTEXT(TRUE).");
00417 }
00418
#endif
00419
00420
#ifdef LATER
00421
00422
#endif
00423
00424
if (pClientImc !=
NULL)
00425
ImmUnlockClientImc(pClientImc);
00426
00427
return TRUE;
00428 }
00429
00430
00431
00432
00433
00434
00435
00436 PIMEMODESAVER GetImeModeSaver(
00437 PINPUTCONTEXT pInputContext,
00438 HKL hkl)
00439 {
00440
PIMEMODESAVER pModeSaver;
00441
USHORT langId = PRIMARYLANGID(
HKL_TO_LANGID(hkl));
00442
00443
for (pModeSaver = pInputContext->pImeModeSaver; pModeSaver; pModeSaver = pModeSaver->
next) {
00444
if (pModeSaver->
langId == langId) {
00445
break;
00446 }
00447 }
00448
00449
if (pModeSaver ==
NULL) {
00450 TAGMSG1(DBGTAG_IMM,
"GetImeModeSaver: creating ModeSaver for langId=%04x", langId);
00451 pModeSaver =
ImmLocalAlloc(HEAP_ZERO_MEMORY,
sizeof *pModeSaver);
00452
if (pModeSaver ==
NULL) {
00453 RIPMSG1(RIP_WARNING,
"GetImeModeSaver: failed to create ModeSaver for langId=%04x", langId);
00454
return NULL;
00455 }
00456 pModeSaver->langId = langId;
00457 pModeSaver->next = pInputContext->pImeModeSaver;
00458 pInputContext->pImeModeSaver = pModeSaver;
00459 }
00460
00461
return pModeSaver;
00462 }
00463
00464 VOID DestroyImeModeSaver(
00465 PINPUTCONTEXT pInputContext)
00466 {
00467
PIMEMODESAVER pModeSaver = pInputContext->pImeModeSaver;
00468
00469
00470
00471
00472
while (pModeSaver) {
00473
PIMEMODESAVER pNext = pModeSaver->
next;
00474
PIMEPRIVATEMODESAVER pPrivateModeSaver = pModeSaver->
pImePrivateModeSaver;
00475
00476
00477
00478
00479
while (pPrivateModeSaver) {
00480
PIMEPRIVATEMODESAVER pPrivateNext = pPrivateModeSaver->
next;
00481
ImmLocalFree(pPrivateModeSaver);
00482 pPrivateModeSaver = pPrivateNext;
00483 }
00484
00485
ImmLocalFree(pModeSaver);
00486 pModeSaver = pNext;
00487 }
00488
00489 pInputContext->pImeModeSaver =
NULL;
00490 }
00491
00492 PIMEPRIVATEMODESAVER GetImePrivateModeSaver(
00493
PIMEMODESAVER pImeModeSaver,
00494 HKL hkl)
00495 {
00496
PIMEPRIVATEMODESAVER pPrivateModeSaver;
00497
00498
for (pPrivateModeSaver = pImeModeSaver->
pImePrivateModeSaver; pPrivateModeSaver; pPrivateModeSaver = pPrivateModeSaver->
next) {
00499
if (pPrivateModeSaver->
hkl == hkl) {
00500
break;
00501 }
00502 }
00503
00504
if (pPrivateModeSaver ==
NULL) {
00505 TAGMSG1(DBGTAG_IMM,
"GetImePrivateModeSaver: creating private mode saver for hkl=%08x", hkl);
00506 pPrivateModeSaver =
ImmLocalAlloc(0,
sizeof *pPrivateModeSaver);
00507
if (pPrivateModeSaver ==
NULL) {
00508 RIPMSG1(RIP_WARNING,
"GetImePrivateModeSaver: failed to create PrivateModeSaver for hlk=%08x", hkl);
00509
return NULL;
00510 }
00511 pPrivateModeSaver->hkl = hkl;
00512 pPrivateModeSaver->fdwSentence = 0;
00513 pPrivateModeSaver->next = pImeModeSaver->
pImePrivateModeSaver;
00514 pImeModeSaver->
pImePrivateModeSaver = pPrivateModeSaver;
00515 }
00516
00517
return pPrivateModeSaver;
00518 }
00519
00520 BOOL SavePrivateMode(
00521 PINPUTCONTEXT pInputContext,
00522
PIMEMODESAVER pImeModeSaver,
00523 HKL hkl)
00524 {
00525
PIMEPRIVATEMODESAVER pPrivateModeSaver =
GetImePrivateModeSaver(pImeModeSaver, hkl);
00526
00527
if (pPrivateModeSaver ==
NULL) {
00528
return FALSE;
00529 }
00530
00531
00532
00533
00534 pPrivateModeSaver->
fdwSentence = pInputContext->fdwSentence & 0xffff0000;
00535
return TRUE;
00536 }
00537
00538 BOOL RestorePrivateMode(
00539 PINPUTCONTEXT pInputContext,
00540
PIMEMODESAVER pImeModeSaver,
00541 HKL hkl)
00542 {
00543
PIMEPRIVATEMODESAVER pPrivateModeSaver =
GetImePrivateModeSaver(pImeModeSaver, hkl);
00544
00545
if (pPrivateModeSaver ==
NULL) {
00546
return FALSE;
00547 }
00548
00549
00550
00551
00552
ImmAssert(LOWORD(pPrivateModeSaver->
fdwSentence) == 0);
00553 pInputContext->fdwSentence |= pPrivateModeSaver->
fdwSentence;
00554
return TRUE;
00555 }
00556
00557
00558
00559
00560
00561
00562
00563 BOOL CreateInputContext(
00564 HIMC hImc,
00565 HKL hKL,
00566 BOOL fCanCallImeSelect)
00567 {
00568
PIMEDPI pImeDpi;
00569
PCLIENTIMC pClientImc;
00570
DWORD dwPrivateDataSize;
00571
DWORD fdwInitConvMode = 0;
00572
BOOL fInitOpen =
FALSE;
00573 PINPUTCONTEXT pInputContext;
00574 PCOMPOSITIONSTRING pCompStr;
00575 PCANDIDATEINFO pCandInfo;
00576 PGUIDELINE pGuideLine;
00577
int i;
00578
00579 pInputContext =
ImmLockIMC(hImc);
00580
if (!pInputContext) {
00581 RIPMSG1(RIP_WARNING,
"CreateContext: Lock hIMC %x failure", hImc);
00582
goto CrIMCLockErrOut;
00583 }
00584
00585
00586
00587
00588 pInputContext->hCompStr =
ImmCreateIMCC(
sizeof(COMPOSITIONSTRING));
00589
if (!pInputContext->hCompStr) {
00590 RIPMSG0(RIP_WARNING,
"CreateContext: Create hCompStr failure");
00591
goto CrIMCUnlockIMC;
00592 }
00593
00594 pCompStr = (PCOMPOSITIONSTRING)
ImmLockIMCC(pInputContext->hCompStr);
00595
if (!pCompStr) {
00596 RIPMSG1(RIP_WARNING,
00597
"CreateContext: Lock hCompStr %x failure", pInputContext->hCompStr);
00598
goto CrIMCFreeCompStr;
00599 }
00600
00601 pCompStr->dwSize =
sizeof(COMPOSITIONSTRING);
00602
ImmUnlockIMCC(pInputContext->hCompStr);
00603
00604 pInputContext->hCandInfo =
ImmCreateIMCC(
sizeof(CANDIDATEINFO));
00605
if (!pInputContext->hCandInfo) {
00606 RIPMSG0(RIP_WARNING,
"CreateContext: Create hCandInfo failure");
00607
goto CrIMCFreeCompStr;
00608 }
00609
00610 pCandInfo = (PCANDIDATEINFO)
ImmLockIMCC(pInputContext->hCandInfo);
00611
if (!pCandInfo) {
00612 RIPMSG1(RIP_WARNING,
00613
"CreateContext: Lock hCandInfo %x failure", pInputContext->hCandInfo);
00614
goto CrIMCFreeCandInfo;
00615 }
00616
00617 pCandInfo->dwSize =
sizeof(CANDIDATEINFO);
00618
ImmUnlockIMCC(pInputContext->hCandInfo);
00619
00620 pInputContext->hGuideLine =
ImmCreateIMCC(
sizeof(GUIDELINE));
00621
if (!pInputContext->hGuideLine) {
00622 RIPMSG0(RIP_WARNING,
"CreateContext: Create hGuideLine failure");
00623
goto CrIMCFreeCandInfo;
00624 }
00625
00626 pGuideLine = (PGUIDELINE)
ImmLockIMCC(pInputContext->hGuideLine);
00627
if (!pGuideLine) {
00628 RIPMSG1(RIP_WARNING,
00629
"CreateContext: Lock hGuideLine %x failure", pInputContext->hGuideLine);
00630
goto CrIMCFreeGuideLine;
00631 }
00632
00633 pGuideLine->dwSize =
sizeof(GUIDELINE);
00634
ImmUnlockIMCC(pInputContext->hGuideLine);
00635
00636 pInputContext->hMsgBuf =
ImmCreateIMCC(
sizeof(
UINT));
00637
if (!pInputContext->hMsgBuf) {
00638 RIPMSG0(RIP_WARNING,
"CreateContext: Create hMsgBuf failure");
00639
goto CrIMCFreeGuideLine;
00640 }
00641
00642 pInputContext->dwNumMsgBuf = 0;
00643 pInputContext->fOpen = fInitOpen;
00644 pInputContext->fdwConversion = fdwInitConvMode;
00645 pInputContext->fdwSentence = 0;
00646
00647
for (i = 0; i < 4; i++) {
00648 pInputContext->cfCandForm[i].dwIndex = (
DWORD)(-1);
00649 }
00650
00651 pImeDpi =
ImmLockImeDpi(hKL);
00652
if (pImeDpi !=
NULL) {
00653
if ((pClientImc =
ImmLockClientImc(hImc)) ==
NULL) {
00654 RIPMSG0(RIP_WARNING,
"CreateContext: ImmLockClientImc() failure");
00655
ImmUnlockImeDpi(pImeDpi);
00656
goto CrIMCFreeMsgBuf;
00657 }
00658
00659
00660
00661
00662
if (pImeDpi->
ImeInfo.fdwProperty & IME_PROP_UNICODE)
00663
SetICF(pClientImc,
IMCF_UNICODE);
00664
00665 pClientImc->
dwCodePage =
IMECodePage(pImeDpi);
00666
00667
ImmUnlockClientImc(pClientImc);
00668
00669 dwPrivateDataSize = pImeDpi->
ImeInfo.dwPrivateDataSize;
00670 }
00671
else {
00672 dwPrivateDataSize =
sizeof(
UINT);
00673 }
00674
00675 pInputContext->hPrivate =
ImmCreateIMCC(dwPrivateDataSize);
00676
if (!pInputContext->hPrivate) {
00677 RIPMSG0(RIP_WARNING,
"CreateContext: Create hPrivate failure");
00678
ImmUnlockImeDpi(pImeDpi);
00679
goto CrIMCFreeMsgBuf;
00680 }
00681
00682 pInputContext->pImeModeSaver =
NULL;
00683
00684
if (pImeDpi !=
NULL) {
00685
if (fCanCallImeSelect) {
00686 (*pImeDpi->
pfn.
ImeSelect)(hImc,
TRUE);
00687 }
00688
ImmUnlockImeDpi(pImeDpi);
00689 }
00690
00691
ImmUnlockIMC(hImc);
00692
return TRUE;
00693
00694
00695
00696
00697 CrIMCFreeMsgBuf:
00698
ImmDestroyIMCC(pInputContext->hMsgBuf);
00699 CrIMCFreeGuideLine:
00700
ImmDestroyIMCC(pInputContext->hGuideLine);
00701 CrIMCFreeCandInfo:
00702
ImmDestroyIMCC(pInputContext->hCandInfo);
00703 CrIMCFreeCompStr:
00704
ImmDestroyIMCC(pInputContext->hCompStr);
00705 CrIMCUnlockIMC:
00706
ImmUnlockIMC(hImc);
00707 CrIMCLockErrOut:
00708
return FALSE;
00709 }
00710
00711
00712
00713
00714
00715
00716
00717
00718 BOOL DestroyInputContext(
00719 HIMC hImc,
00720 HKL hKL,
00721 BOOL bTerminate)
00722 {
00723 PINPUTCONTEXT pInputContext;
00724
PIMEDPI pImeDpi;
00725
PIMC pImc;
00726
PCLIENTIMC pClientImc;
00727
00728
if (!
IS_IME_ENABLED()) {
00729
return FALSE;
00730
00731 }
00732
if (hImc ==
NULL_HIMC) {
00733 RIPMSG0(RIP_VERBOSE,
"DestroyInputContext: hImc is NULL.");
00734
return FALSE;
00735 }
00736
00737 pImc =
HMValidateHandle((HANDLE)hImc,
TYPE_INPUTCONTEXT);
00738
00739
00740
00741
00742
if (pImc ==
NULL ||
GETPTI(pImc) !=
PtiCurrent())
00743
return FALSE;
00744
00745
00746
00747
00748
00749
00750
00751
00752 pClientImc = (
PCLIENTIMC)pImc->
dwClientImcData;
00753
00754
if (pClientImc ==
NULL) {
00755
00756
00757
00758
00759
if (bTerminate) {
00760
00761
00762
00763
00764
return TRUE;
00765 }
00766
return NtUserDestroyInputContext(hImc);
00767 }
00768
00769
if (
TestICF(pClientImc,
IMCF_DEFAULTIMC) && !bTerminate) {
00770
00771
00772
00773
00774
return FALSE;
00775 }
00776
00777
if (
TestICF(pClientImc,
IMCF_INDESTROY)) {
00778
00779
00780
00781
return TRUE;
00782 }
00783
00784
00785
00786
00787 InterlockedIncrement(&pClientImc->
cLockObj);
00788
00789
if (pClientImc->
hInputContext !=
NULL) {
00790
00791 pInputContext =
ImmLockIMC(hImc);
00792
if (!pInputContext) {
00793 RIPMSG1(RIP_WARNING,
"DestroyContext: Lock hImc %x failure", hImc);
00794
ImmUnlockClientImc(pClientImc);
00795
return FALSE;
00796 }
00797
00798 pImeDpi =
ImmLockImeDpi(hKL);
00799
if (pImeDpi !=
NULL) {
00800 (*pImeDpi->
pfn.
ImeSelect)(hImc,
FALSE);
00801
ImmUnlockImeDpi(pImeDpi);
00802 }
00803
00804
ImmDestroyIMCC(pInputContext->hPrivate);
00805
ImmDestroyIMCC(pInputContext->hMsgBuf);
00806
ImmDestroyIMCC(pInputContext->hGuideLine);
00807
ImmDestroyIMCC(pInputContext->hCandInfo);
00808
ImmDestroyIMCC(pInputContext->hCompStr);
00809
00810
00811
00812
00813
DestroyImeModeSaver(pInputContext);
00814
00815
ImmUnlockIMC(hImc);
00816 }
00817
00818
SetICF(pClientImc,
IMCF_INDESTROY);
00819
00820
00821
00822
00823
00824
00825
ImmUnlockClientImc(pClientImc);
00826
00827
return (bTerminate) ?
TRUE :
NtUserDestroyInputContext(hImc);
00828 }
00829
00830
00831
00832
00833
00834
00835
00836
00837 VOID SelectInputContext(
00838 HKL hSelKL,
00839 HKL hUnSelKL,
00840 HIMC hImc)
00841 {
00842
PIMEDPI pSelImeDpi, pUnSelImeDpi;
00843
PCLIENTIMC pClientImc;
00844 PINPUTCONTEXT pInputContext;
00845
DWORD dwSelPriv = 0, dwUnSelPriv = 0, dwSize;
00846 HIMCC hImcc;
00847 PCOMPOSITIONSTRING pCompStr;
00848 PCANDIDATEINFO pCandInfo;
00849 PGUIDELINE pGuideLine;
00850 BOOLEAN fLogFontInited;
00851
00852 TAGMSG3(DBGTAG_IMM,
"SelectInputContext: called for sel=%08p unsel=%08p hImc=%08p",
00853 hSelKL, hUnSelKL, hImc);
00854
00855 pClientImc =
ImmLockClientImc(hImc);
00856
if (pClientImc ==
NULL) {
00857 RIPMSG0(RIP_VERBOSE,
"SelectInputContext: cannot lock client Imc. Bailing out.");
00858
return;
00859 }
00860
00861 pSelImeDpi =
ImmLockImeDpi(hSelKL);
00862
00863
if (hSelKL != hUnSelKL) {
00864
00865
00866
00867
00868
00869
00870 pUnSelImeDpi =
ImmLockImeDpi(hUnSelKL);
00871 }
else {
00872 pUnSelImeDpi =
NULL;
00873 }
00874
00875
if (pSelImeDpi !=
NULL) {
00876
00877
00878
00879
00880 dwSelPriv = pSelImeDpi->
ImeInfo.dwPrivateDataSize;
00881
00882
00883
00884
00885 pClientImc->
dwCodePage =
IMECodePage(pSelImeDpi);
00886 }
00887
else {
00888 pClientImc->
dwCodePage = CP_ACP;
00889 }
00890
00891
if (pUnSelImeDpi !=
NULL)
00892 dwUnSelPriv = pUnSelImeDpi->
ImeInfo.dwPrivateDataSize;
00893
00894 dwSelPriv =
max(dwSelPriv,
sizeof(
UINT));
00895 dwUnSelPriv =
max(dwUnSelPriv,
sizeof(
UINT));
00896
00897
00898
00899
00900
if (pUnSelImeDpi !=
NULL)
00901 (*pUnSelImeDpi->
pfn.
ImeSelect)(hImc,
FALSE);
00902
00903
00904
00905
00906
if ((pInputContext =
InternalImmLockIMC(hImc,
FALSE)) !=
NULL) {
00907
DWORD fdwOldConversion = pInputContext->fdwConversion;
00908
DWORD fdwOldSentence = pInputContext->fdwSentence;
00909
BOOL fOldOpen = pInputContext->fOpen;
00910
PIMEMODESAVER pUnSelModeSaver, pSelModeSaver;
00911
const DWORD fdwConvPreserve = IME_CMODE_EUDC;
00912
00913 fLogFontInited = ((pInputContext->fdwInit & INIT_LOGFONT) == INIT_LOGFONT);
00914
00915
if (
TestICF(pClientImc,
IMCF_UNICODE) && pSelImeDpi !=
NULL &&
00916 !(pSelImeDpi->
ImeInfo.fdwProperty & IME_PROP_UNICODE)) {
00917
00918
00919
00920
if (fLogFontInited) {
00921 LOGFONTA LogFontA;
00922
00923
LFontWtoLFontA(&pInputContext->lfFont.W, &LogFontA);
00924 RtlCopyMemory(&pInputContext->lfFont.A, &LogFontA,
sizeof(LOGFONTA));
00925 }
00926
00927
ClrICF(pClientImc,
IMCF_UNICODE);
00928 }
00929
else if (!
TestICF(pClientImc,
IMCF_UNICODE) && pSelImeDpi !=
NULL &&
00930 (pSelImeDpi->
ImeInfo.fdwProperty & IME_PROP_UNICODE)) {
00931
00932
00933
00934
if (fLogFontInited) {
00935 LOGFONTW LogFontW;
00936
00937
LFontAtoLFontW(&pInputContext->lfFont.A, &LogFontW);
00938 RtlCopyMemory(&pInputContext->lfFont.W, &LogFontW,
sizeof(LOGFONTW));
00939 }
00940
00941
SetICF(pClientImc,
IMCF_UNICODE);
00942 }
00943
00944
00945
00946
00947
if (dwUnSelPriv != dwSelPriv) {
00948 hImcc =
ImmReSizeIMCC(pInputContext->hPrivate, dwSelPriv);
00949
if (hImcc) {
00950 pInputContext->hPrivate = hImcc;
00951 }
00952
else {
00953 RIPMSG1(RIP_WARNING,
00954
"SelectContext: resize hPrivate %lX failure",
00955 pInputContext->hPrivate);
00956
ImmDestroyIMCC(pInputContext->hPrivate);
00957 pInputContext->hPrivate =
ImmCreateIMCC(dwSelPriv);
00958 }
00959 }
00960
00961
00962
00963
00964 dwSize =
ImmGetIMCCSize(pInputContext->hMsgBuf);
00965
00966
if (
ImmGetIMCCLockCount(pInputContext->hMsgBuf) != 0 ||
00967 dwSize >
IMCC_ALLOC_TOOLARGE) {
00968
00969 RIPMSG0(RIP_WARNING,
"SelectContext: create new hMsgBuf");
00970
ImmDestroyIMCC(pInputContext->hMsgBuf);
00971 pInputContext->hMsgBuf =
ImmCreateIMCC(
sizeof(
UINT));
00972 pInputContext->dwNumMsgBuf = 0;
00973 }
00974
00975
00976
00977
00978 dwSize =
ImmGetIMCCSize(pInputContext->hGuideLine);
00979
00980
if (
ImmGetIMCCLockCount(pInputContext->hGuideLine) != 0 ||
00981 dwSize < sizeof(GUIDELINE) || dwSize >
IMCC_ALLOC_TOOLARGE) {
00982
00983 RIPMSG0(RIP_WARNING,
"SelectContext: create new hGuideLine");
00984
ImmDestroyIMCC(pInputContext->hGuideLine);
00985 pInputContext->hGuideLine =
ImmCreateIMCC(
sizeof(GUIDELINE));
00986 pGuideLine = (PGUIDELINE)
ImmLockIMCC(pInputContext->hGuideLine);
00987
00988
if (pGuideLine !=
NULL) {
00989 pGuideLine->dwSize =
sizeof(GUIDELINE);
00990
ImmUnlockIMCC(pInputContext->hGuideLine);
00991 }
00992 }
00993
00994
00995
00996
00997 dwSize =
ImmGetIMCCSize(pInputContext->hCandInfo);
00998
00999
if (
ImmGetIMCCLockCount(pInputContext->hCandInfo) != 0 ||
01000 dwSize < sizeof(CANDIDATEINFO) || dwSize >
IMCC_ALLOC_TOOLARGE) {
01001
01002 RIPMSG0(RIP_WARNING,
"SelectContext: create new hCandInfo");
01003
ImmDestroyIMCC(pInputContext->hCandInfo);
01004 pInputContext->hCandInfo =
ImmCreateIMCC(
sizeof(CANDIDATEINFO));
01005 pCandInfo = (PCANDIDATEINFO)
ImmLockIMCC(pInputContext->hCandInfo);
01006
01007
if (pCandInfo !=
NULL) {
01008 pCandInfo->dwSize =
sizeof(CANDIDATEINFO);
01009
ImmUnlockIMCC(pInputContext->hCandInfo);
01010 }
01011 }
01012
01013
01014
01015
01016 dwSize =
ImmGetIMCCSize(pInputContext->hCompStr);
01017
01018
if (
ImmGetIMCCLockCount(pInputContext->hCompStr) != 0 ||
01019 dwSize < sizeof(COMPOSITIONSTRING) || dwSize >
IMCC_ALLOC_TOOLARGE) {
01020
01021 RIPMSG0(RIP_WARNING,
"SelectContext: create new hCompStr");
01022
ImmDestroyIMCC(pInputContext->hCompStr);
01023 pInputContext->hCompStr =
ImmCreateIMCC(
sizeof(COMPOSITIONSTRING));
01024 pCompStr = (PCOMPOSITIONSTRING)
ImmLockIMCC(pInputContext->hCompStr);
01025
01026
if (pCompStr !=
NULL) {
01027 pCompStr->dwSize =
sizeof(COMPOSITIONSTRING);
01028
ImmUnlockIMCC(pInputContext->hCompStr);
01029 }
01030 }
01031
01032
01033
01034
01035
01036
01037
if (pUnSelImeDpi) {
01038
01039
01040
01041 pUnSelModeSaver =
GetImeModeSaver(pInputContext, hUnSelKL);
01042 TAGMSG1(DBGTAG_IMM,
"pUnSelModeSaver=%p", pUnSelModeSaver);
01043
01044
01045
01046
01047
SavePrivateMode(pInputContext, pUnSelModeSaver, hUnSelKL);
01048 }
01049
else {
01050 pUnSelModeSaver =
NULL;
01051 }
01052
01053
if (pSelImeDpi) {
01054
01055
01056
01057 pSelModeSaver =
GetImeModeSaver(pInputContext, hSelKL);
01058 TAGMSG1(DBGTAG_IMM,
"pSelImeDpi. pImeModeSaver=%p", pSelModeSaver);
01059 }
01060
else {
01061 pSelModeSaver =
NULL;
01062 }
01063
01064
01065
01066
01067
01068
if (pUnSelModeSaver != pSelModeSaver) {
01069
01070
01071
01072
if (pUnSelModeSaver) {
01073 pUnSelModeSaver->
fOpen = (pInputContext->fOpen !=
FALSE);
01074
01075
01076
01077
01078 pUnSelModeSaver->
fdwConversion = pInputContext->fdwConversion & ~fdwConvPreserve;
01079
01080 pUnSelModeSaver->
fdwSentence = LOWORD(pInputContext->fdwSentence);
01081 pUnSelModeSaver->
fdwInit = pInputContext->fdwInit;
01082 }
01083
01084
01085
01086
01087
if (pSelModeSaver) {
01088
if (pInputContext->fdwDirty & IMSS_INIT_OPEN) {
01089
01090
01091
01092
01093 pInputContext->fOpen =
TRUE;
01094 pInputContext->fdwDirty &= ~IMSS_INIT_OPEN;
01095 }
else {
01096 pInputContext->fOpen = pSelModeSaver->
fOpen;
01097 }
01098
01099
01100
01101
01102 pInputContext->fdwConversion &= fdwConvPreserve;
01103
ImmAssert((pSelModeSaver->
fdwConversion & fdwConvPreserve) == 0);
01104 pInputContext->fdwConversion |= pSelModeSaver->
fdwConversion & ~fdwConvPreserve;
01105
01106
ImmAssert(HIWORD(pSelModeSaver->
fdwSentence) == 0);
01107 pInputContext->fdwSentence = pSelModeSaver->
fdwSentence;
01108 pInputContext->fdwInit = pSelModeSaver->
fdwInit;
01109 }
01110 }
01111
if (pSelModeSaver) {
01112
01113
01114
01115
RestorePrivateMode(pInputContext, pSelModeSaver, hSelKL);
01116 }
01117
01118
01119
01120
01121
if (pSelImeDpi !=
NULL)
01122 (*pSelImeDpi->
pfn.
ImeSelect)(hImc,
TRUE);
01123
01124
01125
01126
01127
01128 pInputContext->fdwDirty = 0;
01129
if (pInputContext->fOpen != fOldOpen) {
01130 pInputContext->fdwDirty |= IMSS_UPDATE_OPEN;
01131 }
01132
if (pInputContext->fdwConversion != fdwOldConversion) {
01133 pInputContext->fdwDirty |= IMSS_UPDATE_CONVERSION;
01134 }
01135
if (pInputContext->fdwSentence != fdwOldSentence) {
01136 pInputContext->fdwDirty |= IMSS_UPDATE_SENTENCE;
01137 }
01138 TAGMSG4(DBGTAG_IMM,
"fOpen:%d fdwConv:%08x fdwSent:%08x dirty:%02x",
01139 pInputContext->fOpen, pInputContext->fdwConversion, pInputContext->fdwSentence, pInputContext->fdwDirty);
01140
01141
ImmUnlockIMC(hImc);
01142 }
01143
else {
01144
01145
01146
01147
01148
if (pSelImeDpi !=
NULL)
01149 (*pSelImeDpi->
pfn.
ImeSelect)(hImc,
TRUE);
01150 }
01151
01152
ImmUnlockImeDpi(pUnSelImeDpi);
01153
ImmUnlockImeDpi(pSelImeDpi);
01154
ImmUnlockClientImc(pClientImc);
01155 }
01156
01157 BOOL SendNotificationProc(
01158 HIMC hImc,
01159 LPARAM lParam)
01160 {
01161 PINPUTCONTEXT pInputContext =
ImmLockIMC(hImc);
01162
01163 UNREFERENCED_PARAMETER(lParam);
01164
01165
if (pInputContext !=
NULL) {
01166 HWND hwnd = pInputContext->hWnd;
01167
01168
if (
IsWindow(hwnd)) {
01169 TAGMSG2(DBGTAG_IMM,
"SendNotificationProc: updating hImc=%08x dirty=%04x",
01170 hImc, pInputContext->fdwDirty);
01171
01172
if (pInputContext->fdwDirty & IMSS_UPDATE_OPEN) {
01173 SendMessageW(hwnd, WM_IME_NOTIFY, IMN_SETOPENSTATUS, 0);
01174 }
01175
if (pInputContext->fdwDirty & IMSS_UPDATE_CONVERSION) {
01176 SendMessageW(hwnd, WM_IME_NOTIFY, IMN_SETCONVERSIONMODE, 0);
01177 }
01178
if (pInputContext->fdwDirty & (IMSS_UPDATE_OPEN | IMSS_UPDATE_CONVERSION)) {
01179
NtUserNotifyIMEStatus(hwnd, pInputContext->fOpen, pInputContext->fdwConversion);
01180 }
01181
if (pInputContext->fdwDirty & IMSS_UPDATE_SENTENCE) {
01182 SendMessageW(hwnd, WM_IME_NOTIFY, IMN_SETSENTENCEMODE, 0);
01183 }
01184 }
01185 pInputContext->fdwDirty = 0;
01186 }
01187
01188
return TRUE;
01189 }
01190
01191 VOID ImmSendNotification(
01192 BOOL fForProcess)
01193 {
01194
DWORD dwThreadId;
01195
01196
if (fForProcess) {
01197 dwThreadId = -1;
01198 }
else {
01199 dwThreadId = 0;
01200 }
01201
01202
ImmEnumInputContext(dwThreadId, (IMCENUMPROC)
SendNotificationProc, 0);
01203 }
01204
01205
01206
01207
01208
01209
01210
01211 BOOL WINAPI
ImmEnumInputContext(
01212 DWORD idThread,
01213 IMCENUMPROC lpfn,
01214 LPARAM lParam)
01215 {
01216
UINT i;
01217
UINT cHimc;
01218 HIMC *phimcT;
01219 HIMC *phimcFirst;
01220
BOOL fSuccess =
TRUE;
01221
01222
01223
01224
01225
01226
if ((cHimc =
BuildHimcList(idThread, &phimcFirst)) == 0) {
01227
return FALSE;
01228 }
01229
01230
01231
01232
01233
01234
01235 phimcT = phimcFirst;
01236
for (i = 0; i < cHimc; i++) {
01237
if (
RevalidateHimc(*phimcT)) {
01238
if (!(fSuccess = (*lpfn)(*phimcT, lParam)))
01239
break;
01240 }
01241 phimcT++;
01242 }
01243
01244
01245
01246
01247
01248
ImmLocalFree(phimcFirst);
01249
01250
return fSuccess;
01251 }
01252
01253
01254
01255
01256
01257
01258
01259 DWORD BuildHimcList(
01260 DWORD idThread,
01261 HIMC **pphimcFirst)
01262 {
01263
UINT cHimc;
01264 HIMC *phimcFirst;
01265
NTSTATUS Status;
01266
int cTries;
01267
01268
01269
01270
01271 cHimc = 64;
01272 phimcFirst =
ImmLocalAlloc(0, cHimc *
sizeof(HIMC));
01273
if (phimcFirst ==
NULL)
01274
return 0;
01275
01276
Status =
NtUserBuildHimcList(idThread, cHimc, phimcFirst, &cHimc);
01277
01278
01279
01280
01281
01282 cTries = 0;
01283
while (
Status == STATUS_BUFFER_TOO_SMALL) {
01284
ImmLocalFree(phimcFirst);
01285
01286
01287
01288
01289
01290
if (cTries++ == 10)
01291
return 0;
01292
01293 phimcFirst =
ImmLocalAlloc(0, cHimc *
sizeof(HIMC));
01294
if (phimcFirst ==
NULL)
01295
return 0;
01296
01297
Status =
NtUserBuildHimcList(idThread, cHimc, phimcFirst, &cHimc);
01298 }
01299
01300
if (!
NT_SUCCESS(
Status) || cHimc == 0) {
01301
ImmLocalFree(phimcFirst);
01302
return 0;
01303 }
01304
01305 *pphimcFirst = phimcFirst;
01306
01307
return cHimc;
01308 }