1 /* 2 * PROJECT: ReactOS IMM32 3 * LICENSE: LGPL-2.1-or-later (https://spdx.org/licenses/LGPL-2.1-or-later) 4 * PURPOSE: Implementing Far-Eastern languages input 5 * COPYRIGHT: Copyright 1998 Patrik Stridvall 6 * Copyright 2002, 2003, 2007 CodeWeavers, Aric Stewart 7 * Copyright 2017 James Tabor <james.tabor@reactos.org> 8 * Copyright 2018 Amine Khaldi <amine.khaldi@reactos.org> 9 * Copyright 2020-2022 Katayama Hirofumi MZ <katayama.hirofumi.mz@gmail.com> 10 */ 11 12 #include "precomp.h" 13 #include <ndk/exfuncs.h> 14 15 WINE_DEFAULT_DEBUG_CHANNEL(imm); 16 17 HMODULE ghImm32Inst = NULL; /* The IMM32 instance */ 18 PSERVERINFO gpsi = NULL; 19 SHAREDINFO gSharedInfo = { NULL }; 20 BYTE gfImmInitialized = FALSE; /* Is IMM32 initialized? */ 21 ULONG_PTR gHighestUserAddress = 0; 22 23 static BOOL APIENTRY ImmInitializeGlobals(HMODULE hMod) 24 { 25 NTSTATUS status; 26 SYSTEM_BASIC_INFORMATION SysInfo; 27 28 if (hMod) 29 ghImm32Inst = hMod; 30 31 if (gfImmInitialized) 32 return TRUE; 33 34 status = RtlInitializeCriticalSection(&gcsImeDpi); 35 if (NT_ERROR(status)) 36 { 37 ERR("\n"); 38 return FALSE; 39 } 40 41 status = NtQuerySystemInformation(SystemBasicInformation, &SysInfo, sizeof(SysInfo), NULL); 42 if (NT_ERROR(status)) 43 { 44 ERR("\n"); 45 return FALSE; 46 } 47 gHighestUserAddress = SysInfo.MaximumUserModeAddress; 48 49 gfImmInitialized = TRUE; 50 return TRUE; 51 } 52 53 /*********************************************************************** 54 * ImmRegisterClient(IMM32.@) 55 * ( Undocumented, called from user32.dll ) 56 */ 57 BOOL WINAPI ImmRegisterClient(PSHAREDINFO ptr, HINSTANCE hMod) 58 { 59 gSharedInfo = *ptr; 60 gpsi = gSharedInfo.psi; 61 return ImmInitializeGlobals(hMod); 62 } 63 64 /*********************************************************************** 65 * ImmLoadLayout (IMM32.@) 66 */ 67 BOOL WINAPI ImmLoadLayout(HKL hKL, PIMEINFOEX pImeInfoEx) 68 { 69 DWORD cbData, dwType; 70 HKEY hKey; 71 LSTATUS error; 72 WCHAR szLayout[MAX_PATH]; 73 LPCWSTR pszSubKey; 74 75 TRACE("(%p, %p)\n", hKL, pImeInfoEx); 76 77 /* Choose a key */ 78 if (IS_IME_HKL(hKL) || !IS_CICERO_MODE() || IS_16BIT_MODE()) /* Non-Cicero? */ 79 { 80 StringCchPrintfW(szLayout, _countof(szLayout), L"%s\\%08lX", 81 REGKEY_KEYBOARD_LAYOUTS, HandleToUlong(hKL)); 82 pszSubKey = szLayout; 83 } 84 else /* Cicero */ 85 { 86 pszSubKey = L"Software\\Microsoft\\Windows NT\\CurrentVersion\\IMM"; 87 } 88 89 /* Open the key */ 90 error = RegOpenKeyExW(HKEY_LOCAL_MACHINE, pszSubKey, 0, KEY_READ, &hKey); 91 if (IS_ERROR_UNEXPECTEDLY(error)) 92 return FALSE; 93 94 /* Load "IME File" value */ 95 cbData = sizeof(pImeInfoEx->wszImeFile); 96 error = RegQueryValueExW(hKey, L"IME File", NULL, &dwType, 97 (LPBYTE)pImeInfoEx->wszImeFile, &cbData); 98 99 /* Avoid buffer overrun */ 100 pImeInfoEx->wszImeFile[_countof(pImeInfoEx->wszImeFile) - 1] = UNICODE_NULL; 101 102 RegCloseKey(hKey); 103 104 if (error != ERROR_SUCCESS || dwType != REG_SZ) 105 return FALSE; /* Failed */ 106 107 pImeInfoEx->hkl = hKL; 108 pImeInfoEx->fLoadFlag = 0; 109 return Imm32LoadImeVerInfo(pImeInfoEx); 110 } 111 112 /*********************************************************************** 113 * ImmFreeLayout (IMM32.@) 114 * 115 * NOTE: HKL_SWITCH_TO_NON_IME and HKL_RELEASE_IME are special values for hKL. 116 */ 117 BOOL WINAPI ImmFreeLayout(HKL hKL) 118 { 119 WCHAR szKBD[KL_NAMELENGTH]; 120 UINT iKL, cKLs; 121 HKL hOldKL, *pList; 122 PIMEDPI pImeDpi; 123 LANGID LangID; 124 125 TRACE("(%p)\n", hKL); 126 127 hOldKL = GetKeyboardLayout(0); 128 129 if (hKL == HKL_SWITCH_TO_NON_IME) 130 { 131 if (!IS_IME_HKL(hOldKL)) 132 return TRUE; 133 134 LangID = LANGIDFROMLCID(GetSystemDefaultLCID()); 135 136 cKLs = GetKeyboardLayoutList(0, NULL); 137 if (cKLs) 138 { 139 pList = ImmLocalAlloc(0, cKLs * sizeof(HKL)); 140 if (IS_NULL_UNEXPECTEDLY(pList)) 141 return FALSE; 142 143 cKLs = GetKeyboardLayoutList(cKLs, pList); 144 for (iKL = 0; iKL < cKLs; ++iKL) 145 { 146 if (!IS_IME_HKL(pList[iKL])) 147 { 148 LangID = LOWORD(pList[iKL]); 149 break; 150 } 151 } 152 153 ImmLocalFree(pList); 154 } 155 156 StringCchPrintfW(szKBD, _countof(szKBD), L"%08X", LangID); 157 if (!LoadKeyboardLayoutW(szKBD, KLF_ACTIVATE)) 158 { 159 WARN("Default to English US\n"); 160 LoadKeyboardLayoutW(L"00000409", KLF_ACTIVATE | 0x200); 161 } 162 } 163 else if (hKL == HKL_RELEASE_IME) 164 { 165 RtlEnterCriticalSection(&gcsImeDpi); 166 Retry: 167 for (pImeDpi = gpImeDpiList; pImeDpi; pImeDpi = pImeDpi->pNext) 168 { 169 if (Imm32ReleaseIME(pImeDpi->hKL)) 170 goto Retry; 171 } 172 RtlLeaveCriticalSection(&gcsImeDpi); 173 } 174 else 175 { 176 if (IS_IME_HKL(hKL) && hKL != hOldKL) 177 Imm32ReleaseIME(hKL); 178 } 179 180 return TRUE; 181 } 182 183 VOID APIENTRY Imm32SelectInputContext(HKL hNewKL, HKL hOldKL, HIMC hIMC) 184 { 185 PCLIENTIMC pClientImc; 186 LPINPUTCONTEXTDX pIC; 187 LPGUIDELINE pGL; 188 LPCANDIDATEINFO pCI; 189 LPCOMPOSITIONSTRING pCS; 190 LOGFONTA LogFontA; 191 LOGFONTW LogFontW; 192 BOOL fOldOpen, bIsNewHKLIme = TRUE, bIsOldHKLIme = TRUE, bClientWide, bNewDpiWide; 193 DWORD cbNewPrivate = 0, cbOldPrivate = 0, dwOldConversion, dwOldSentence, dwSize, dwNewSize; 194 PIMEDPI pNewImeDpi = NULL, pOldImeDpi = NULL; 195 HANDLE hPrivate; 196 PIME_STATE pNewState = NULL, pOldState = NULL; 197 198 pClientImc = ImmLockClientImc(hIMC); 199 if (IS_NULL_UNEXPECTEDLY(pClientImc)) 200 return; 201 202 pNewImeDpi = ImmLockImeDpi(hNewKL); 203 204 if (hNewKL != hOldKL) 205 pOldImeDpi = ImmLockImeDpi(hOldKL); 206 207 if (pNewImeDpi) 208 { 209 cbNewPrivate = pNewImeDpi->ImeInfo.dwPrivateDataSize; 210 pClientImc->uCodePage = pNewImeDpi->uCodePage; 211 } 212 else 213 { 214 pClientImc->uCodePage = CP_ACP; 215 } 216 217 if (pOldImeDpi) 218 cbOldPrivate = pOldImeDpi->ImeInfo.dwPrivateDataSize; 219 220 cbNewPrivate = max(cbNewPrivate, sizeof(DWORD)); 221 cbOldPrivate = max(cbOldPrivate, sizeof(DWORD)); 222 223 if (pClientImc->hKL == hOldKL) 224 { 225 if (pOldImeDpi) 226 { 227 if (IS_IME_HKL(hOldKL)) 228 pOldImeDpi->ImeSelect(hIMC, FALSE); 229 else if (IS_CICERO_MODE() && !IS_16BIT_MODE()) 230 pOldImeDpi->CtfImeSelectEx(hIMC, FALSE, hOldKL); 231 } 232 pClientImc->hKL = NULL; 233 } 234 235 if (CtfImmIsTextFrameServiceDisabled() && IS_CICERO_MODE() && !IS_16BIT_MODE()) 236 { 237 bIsNewHKLIme = IS_IME_HKL(hNewKL); 238 bIsOldHKLIme = IS_IME_HKL(hOldKL); 239 } 240 241 pIC = (LPINPUTCONTEXTDX)Imm32InternalLockIMC(hIMC, FALSE); 242 if (!pIC) 243 { 244 if (pNewImeDpi) 245 { 246 if (IS_IME_HKL(hNewKL)) 247 pNewImeDpi->ImeSelect(hIMC, TRUE); 248 else if (IS_CICERO_MODE() && !IS_16BIT_MODE()) 249 pNewImeDpi->CtfImeSelectEx(hIMC, TRUE, hNewKL); 250 251 pClientImc->hKL = hNewKL; 252 } 253 } 254 else 255 { 256 dwOldConversion = pIC->fdwConversion; 257 dwOldSentence = pIC->fdwSentence; 258 fOldOpen = pIC->fOpen; 259 260 if (pNewImeDpi) 261 { 262 bClientWide = (pClientImc->dwFlags & CLIENTIMC_WIDE); 263 bNewDpiWide = ImeDpi_IsUnicode(pNewImeDpi); 264 if (bClientWide && !bNewDpiWide) 265 { 266 if (pIC->fdwInit & INIT_LOGFONT) 267 { 268 LogFontWideToAnsi(&pIC->lfFont.W, &LogFontA); 269 pIC->lfFont.A = LogFontA; 270 } 271 pClientImc->dwFlags &= ~CLIENTIMC_WIDE; 272 } 273 else if (!bClientWide && bNewDpiWide) 274 { 275 if (pIC->fdwInit & INIT_LOGFONT) 276 { 277 LogFontAnsiToWide(&pIC->lfFont.A, &LogFontW); 278 pIC->lfFont.W = LogFontW; 279 } 280 pClientImc->dwFlags |= CLIENTIMC_WIDE; 281 } 282 } 283 284 if (cbOldPrivate != cbNewPrivate) 285 { 286 hPrivate = ImmReSizeIMCC(pIC->hPrivate, cbNewPrivate); 287 if (!hPrivate) 288 { 289 ImmDestroyIMCC(pIC->hPrivate); 290 hPrivate = ImmCreateIMCC(cbNewPrivate); 291 } 292 pIC->hPrivate = hPrivate; 293 } 294 295 #define MAX_IMCC_SIZE 0x1000 296 dwSize = ImmGetIMCCSize(pIC->hMsgBuf); 297 if (ImmGetIMCCLockCount(pIC->hMsgBuf) || dwSize > MAX_IMCC_SIZE) 298 { 299 ImmDestroyIMCC(pIC->hMsgBuf); 300 pIC->hMsgBuf = ImmCreateIMCC(sizeof(UINT)); 301 pIC->dwNumMsgBuf = 0; 302 } 303 304 dwSize = ImmGetIMCCSize(pIC->hGuideLine); 305 dwNewSize = sizeof(GUIDELINE); 306 if (ImmGetIMCCLockCount(pIC->hGuideLine) || 307 dwSize < dwNewSize || dwSize > MAX_IMCC_SIZE) 308 { 309 ImmDestroyIMCC(pIC->hGuideLine); 310 pIC->hGuideLine = ImmCreateIMCC(dwNewSize); 311 pGL = ImmLockIMCC(pIC->hGuideLine); 312 if (pGL) 313 { 314 pGL->dwSize = dwNewSize; 315 ImmUnlockIMCC(pIC->hGuideLine); 316 } 317 } 318 319 dwSize = ImmGetIMCCSize(pIC->hCandInfo); 320 dwNewSize = sizeof(CANDIDATEINFO); 321 if (ImmGetIMCCLockCount(pIC->hCandInfo) || 322 dwSize < dwNewSize || dwSize > MAX_IMCC_SIZE) 323 { 324 ImmDestroyIMCC(pIC->hCandInfo); 325 pIC->hCandInfo = ImmCreateIMCC(dwNewSize); 326 pCI = ImmLockIMCC(pIC->hCandInfo); 327 if (pCI) 328 { 329 pCI->dwSize = dwNewSize; 330 ImmUnlockIMCC(pIC->hCandInfo); 331 } 332 } 333 334 dwSize = ImmGetIMCCSize(pIC->hCompStr); 335 dwNewSize = sizeof(COMPOSITIONSTRING); 336 if (ImmGetIMCCLockCount(pIC->hCompStr) || 337 dwSize < dwNewSize || dwSize > MAX_IMCC_SIZE) 338 { 339 ImmDestroyIMCC(pIC->hCompStr); 340 pIC->hCompStr = ImmCreateIMCC(dwNewSize); 341 pCS = ImmLockIMCC(pIC->hCompStr); 342 if (pCS) 343 { 344 pCS->dwSize = dwNewSize; 345 ImmUnlockIMCC(pIC->hCompStr); 346 } 347 } 348 #undef MAX_IMCC_SIZE 349 350 if (pOldImeDpi && bIsOldHKLIme) 351 { 352 pOldState = Imm32FetchImeState(pIC, hOldKL); 353 if (pOldState) 354 Imm32SaveImeStateSentence(pIC, pOldState, hOldKL); 355 } 356 357 if (pNewImeDpi && bIsNewHKLIme) 358 pNewState = Imm32FetchImeState(pIC, hNewKL); 359 360 if (pOldState != pNewState) 361 { 362 if (pOldState) 363 { 364 pOldState->fOpen = !!pIC->fOpen; 365 pOldState->dwConversion = pIC->fdwConversion; 366 pOldState->dwConversion &= ~IME_CMODE_EUDC; 367 pOldState->dwSentence = pIC->fdwSentence; 368 pOldState->dwInit = pIC->fdwInit; 369 } 370 371 if (pNewState) 372 { 373 if (pIC->dwChange & INPUTCONTEXTDX_CHANGE_FORCE_OPEN) 374 { 375 pIC->dwChange &= ~INPUTCONTEXTDX_CHANGE_FORCE_OPEN; 376 pIC->fOpen = TRUE; 377 } 378 else 379 { 380 pIC->fOpen = pNewState->fOpen; 381 } 382 383 pIC->fdwConversion = pNewState->dwConversion; 384 pIC->fdwConversion &= ~IME_CMODE_EUDC; 385 pIC->fdwSentence = pNewState->dwSentence; 386 pIC->fdwInit = pNewState->dwInit; 387 } 388 } 389 390 if (pNewState) 391 Imm32LoadImeStateSentence(pIC, pNewState, hNewKL); 392 393 if (pNewImeDpi) 394 { 395 if (IS_IME_HKL(hNewKL)) 396 pNewImeDpi->ImeSelect(hIMC, TRUE); 397 else if (IS_CICERO_MODE() && !IS_16BIT_MODE()) 398 pNewImeDpi->CtfImeSelectEx(hIMC, TRUE, hNewKL); 399 400 pClientImc->hKL = hNewKL; 401 } 402 403 pIC->dwChange = 0; 404 if (pIC->fOpen != fOldOpen) 405 pIC->dwChange |= INPUTCONTEXTDX_CHANGE_OPEN; 406 if (pIC->fdwConversion != dwOldConversion) 407 pIC->dwChange |= INPUTCONTEXTDX_CHANGE_CONVERSION; 408 if (pIC->fdwSentence != dwOldSentence) 409 pIC->dwChange |= INPUTCONTEXTDX_CHANGE_SENTENCE; 410 411 ImmUnlockIMC(hIMC); 412 } 413 414 ImmUnlockImeDpi(pOldImeDpi); 415 ImmUnlockImeDpi(pNewImeDpi); 416 ImmUnlockClientImc(pClientImc); 417 } 418 419 typedef struct SELECT_LAYOUT 420 { 421 HKL hNewKL; 422 HKL hOldKL; 423 } SELECT_LAYOUT, *LPSELECT_LAYOUT; 424 425 // Win: SelectContextProc 426 static BOOL CALLBACK Imm32SelectContextProc(HIMC hIMC, LPARAM lParam) 427 { 428 LPSELECT_LAYOUT pSelect = (LPSELECT_LAYOUT)lParam; 429 Imm32SelectInputContext(pSelect->hNewKL, pSelect->hOldKL, hIMC); 430 return TRUE; 431 } 432 433 // Win: NotifyIMEProc 434 static BOOL CALLBACK Imm32NotifyIMEProc(HIMC hIMC, LPARAM lParam) 435 { 436 ImmNotifyIME(hIMC, NI_COMPOSITIONSTR, (DWORD)lParam, 0); 437 return TRUE; 438 } 439 440 /*********************************************************************** 441 * ImmActivateLayout (IMM32.@) 442 */ 443 BOOL WINAPI ImmActivateLayout(HKL hKL) 444 { 445 PIMEDPI pImeDpi; 446 HKL hOldKL; 447 LPARAM lParam; 448 HWND hwndDefIME = NULL; 449 SELECT_LAYOUT SelectLayout; 450 451 hOldKL = GetKeyboardLayout(0); 452 453 if (hOldKL == hKL && !(GetWin32ClientInfo()->CI_flags & CI_IMMACTIVATE)) 454 return TRUE; 455 456 ImmLoadIME(hKL); 457 458 if (hOldKL != hKL) 459 { 460 pImeDpi = ImmLockImeDpi(hOldKL); 461 if (pImeDpi) 462 { 463 if (pImeDpi->ImeInfo.fdwProperty & IME_PROP_COMPLETE_ON_UNSELECT) 464 lParam = CPS_COMPLETE; 465 else 466 lParam = CPS_CANCEL; 467 ImmUnlockImeDpi(pImeDpi); 468 469 ImmEnumInputContext(0, Imm32NotifyIMEProc, lParam); 470 } 471 472 hwndDefIME = ImmGetDefaultIMEWnd(NULL); 473 if (IsWindow(hwndDefIME)) 474 SendMessageW(hwndDefIME, WM_IME_SELECT, FALSE, (LPARAM)hOldKL); 475 476 NtUserSetThreadLayoutHandles(hKL, hOldKL); 477 } 478 479 SelectLayout.hNewKL = hKL; 480 SelectLayout.hOldKL = hOldKL; 481 ImmEnumInputContext(0, Imm32SelectContextProc, (LPARAM)&SelectLayout); 482 483 if (IsWindow(hwndDefIME)) 484 SendMessageW(hwndDefIME, WM_IME_SELECT, TRUE, (LPARAM)hKL); 485 486 return TRUE; 487 } 488 489 /*********************************************************************** 490 * ImmAssociateContext (IMM32.@) 491 */ 492 HIMC WINAPI ImmAssociateContext(HWND hWnd, HIMC hIMC) 493 { 494 PWND pWnd; 495 HWND hwndFocus; 496 DWORD dwValue; 497 HIMC hOldIMC; 498 499 TRACE("(%p, %p)\n", hWnd, hIMC); 500 501 if (!IS_IMM_MODE()) 502 { 503 TRACE("\n"); 504 return NULL; 505 } 506 507 pWnd = ValidateHwnd(hWnd); 508 if (IS_NULL_UNEXPECTEDLY(pWnd)) 509 return NULL; 510 511 if (hIMC && IS_CROSS_THREAD_HIMC(hIMC)) 512 return NULL; 513 514 hOldIMC = pWnd->hImc; 515 if (hOldIMC == hIMC) 516 return hIMC; 517 518 dwValue = NtUserAssociateInputContext(hWnd, hIMC, 0); 519 switch (dwValue) 520 { 521 case 0: 522 return hOldIMC; 523 524 case 1: 525 hwndFocus = (HWND)NtUserQueryWindow(hWnd, QUERY_WINDOW_FOCUS); 526 if (hwndFocus == hWnd) 527 { 528 ImmSetActiveContext(hWnd, hOldIMC, FALSE); 529 ImmSetActiveContext(hWnd, hIMC, TRUE); 530 } 531 return hOldIMC; 532 533 default: 534 return NULL; 535 } 536 } 537 538 /*********************************************************************** 539 * ImmAssociateContextEx (IMM32.@) 540 */ 541 BOOL WINAPI ImmAssociateContextEx(HWND hWnd, HIMC hIMC, DWORD dwFlags) 542 { 543 HWND hwndFocus; 544 PWND pFocusWnd; 545 HIMC hOldIMC = NULL; 546 DWORD dwValue; 547 548 TRACE("(%p, %p, 0x%lX)\n", hWnd, hIMC, dwFlags); 549 550 if (!IS_IMM_MODE()) 551 { 552 TRACE("\n"); 553 return FALSE; 554 } 555 556 if (hIMC && !(dwFlags & IACE_DEFAULT) && IS_CROSS_THREAD_HIMC(hIMC)) 557 return FALSE; 558 559 hwndFocus = (HWND)NtUserQueryWindow(hWnd, QUERY_WINDOW_FOCUS); 560 pFocusWnd = ValidateHwnd(hwndFocus); 561 if (pFocusWnd) 562 hOldIMC = pFocusWnd->hImc; 563 564 dwValue = NtUserAssociateInputContext(hWnd, hIMC, dwFlags); 565 switch (dwValue) 566 { 567 case 0: 568 return TRUE; 569 570 case 1: 571 pFocusWnd = ValidateHwnd(hwndFocus); 572 if (pFocusWnd) 573 { 574 hIMC = pFocusWnd->hImc; 575 if (hIMC != hOldIMC) 576 { 577 ImmSetActiveContext(hwndFocus, hOldIMC, FALSE); 578 ImmSetActiveContext(hwndFocus, hIMC, TRUE); 579 } 580 } 581 return TRUE; 582 583 default: 584 return FALSE; 585 } 586 } 587 588 /*********************************************************************** 589 * ImmCreateContext (IMM32.@) 590 */ 591 HIMC WINAPI ImmCreateContext(void) 592 { 593 PCLIENTIMC pClientImc; 594 HIMC hIMC; 595 596 TRACE("()\n"); 597 598 if (!IS_IMM_MODE()) 599 { 600 TRACE("\n"); 601 return NULL; 602 } 603 604 pClientImc = ImmLocalAlloc(HEAP_ZERO_MEMORY, sizeof(CLIENTIMC)); 605 if (IS_NULL_UNEXPECTEDLY(pClientImc)) 606 return NULL; 607 608 hIMC = NtUserCreateInputContext((ULONG_PTR)pClientImc); 609 if (IS_NULL_UNEXPECTEDLY(hIMC)) 610 { 611 ImmLocalFree(pClientImc); 612 return NULL; 613 } 614 615 RtlInitializeCriticalSection(&pClientImc->cs); 616 617 pClientImc->dwCompatFlags = (DWORD)NtUserGetThreadState(THREADSTATE_IMECOMPATFLAGS); 618 619 return hIMC; 620 } 621 622 // Win: DestroyImeModeSaver 623 static VOID APIENTRY Imm32DestroyImeModeSaver(LPINPUTCONTEXTDX pIC) 624 { 625 PIME_STATE pState, pNext; 626 PIME_SUBSTATE pSubState, pSubNext; 627 628 for (pState = pIC->pState; pState; pState = pNext) 629 { 630 pNext = pState->pNext; 631 632 for (pSubState = pState->pSubState; pSubState; pSubState = pSubNext) 633 { 634 pSubNext = pSubState->pNext; 635 ImmLocalFree(pSubState); 636 } 637 638 ImmLocalFree(pState); 639 } 640 641 pIC->pState = NULL; 642 } 643 644 // Win: DestroyInputContext 645 BOOL APIENTRY Imm32DestroyInputContext(HIMC hIMC, HKL hKL, BOOL bKeep) 646 { 647 PIMEDPI pImeDpi; 648 LPINPUTCONTEXTDX pIC; 649 PCLIENTIMC pClientImc; 650 PIMC pIMC; 651 652 if (hIMC == NULL) 653 return FALSE; 654 655 if (!IS_IMM_MODE()) 656 { 657 TRACE("\n"); 658 return FALSE; 659 } 660 661 pIMC = ValidateHandle(hIMC, TYPE_INPUTCONTEXT); 662 if (IS_NULL_UNEXPECTEDLY(pIMC)) 663 return FALSE; 664 665 if (pIMC->head.pti != Imm32CurrentPti()) 666 { 667 ERR("Thread mismatch\n"); 668 return FALSE; 669 } 670 671 pClientImc = (PCLIENTIMC)pIMC->dwClientImcData; 672 if (pClientImc == NULL) 673 { 674 TRACE("pClientImc == NULL\n"); 675 goto Finish; 676 } 677 678 if ((pClientImc->dwFlags & CLIENTIMC_UNKNOWN2) && !bKeep) 679 { 680 ERR("Can't destroy for CLIENTIMC_UNKNOWN2\n"); 681 return FALSE; 682 } 683 684 if (pClientImc->dwFlags & CLIENTIMC_DESTROY) 685 return TRUE; 686 687 InterlockedIncrement(&pClientImc->cLockObj); 688 689 if (IS_NULL_UNEXPECTEDLY(pClientImc->hInputContext)) 690 goto Quit; 691 692 pIC = (LPINPUTCONTEXTDX)ImmLockIMC(hIMC); 693 if (IS_NULL_UNEXPECTEDLY(pIC)) 694 { 695 ImmUnlockClientImc(pClientImc); 696 return FALSE; 697 } 698 699 CtfImmTIMDestroyInputContext(hIMC); 700 701 if (pClientImc->hKL == hKL) 702 { 703 pImeDpi = ImmLockImeDpi(hKL); 704 if (pImeDpi) 705 { 706 if (IS_IME_HKL(hKL)) 707 pImeDpi->ImeSelect(hIMC, FALSE); 708 else if (IS_CICERO_MODE() && !IS_16BIT_MODE()) 709 pImeDpi->CtfImeSelectEx(hIMC, FALSE, hKL); 710 711 ImmUnlockImeDpi(pImeDpi); 712 } 713 714 pClientImc->hKL = NULL; 715 } 716 717 ImmDestroyIMCC(pIC->hPrivate); 718 ImmDestroyIMCC(pIC->hMsgBuf); 719 ImmDestroyIMCC(pIC->hGuideLine); 720 ImmDestroyIMCC(pIC->hCandInfo); 721 ImmDestroyIMCC(pIC->hCompStr); 722 Imm32DestroyImeModeSaver(pIC); 723 ImmUnlockIMC(hIMC); 724 725 Quit: 726 pClientImc->dwFlags |= CLIENTIMC_DESTROY; 727 ImmUnlockClientImc(pClientImc); 728 729 Finish: 730 if (bKeep) 731 return TRUE; 732 return NtUserDestroyInputContext(hIMC); 733 } 734 735 // NOTE: Windows does recursive call ImmLockIMC here but we don't do so. 736 // Win: BOOL CreateInputContext(HIMC hIMC, HKL hKL, BOOL fSelect) 737 BOOL APIENTRY 738 Imm32CreateInputContext(HIMC hIMC, LPINPUTCONTEXT pIC, PCLIENTIMC pClientImc, HKL hKL, BOOL fSelect) 739 { 740 DWORD dwIndex, cbPrivate; 741 PIMEDPI pImeDpi = NULL; 742 LPCOMPOSITIONSTRING pCS; 743 LPCANDIDATEINFO pCI; 744 LPGUIDELINE pGL; 745 746 /* Create IC components */ 747 pIC->hCompStr = ImmCreateIMCC(sizeof(COMPOSITIONSTRING)); 748 pIC->hCandInfo = ImmCreateIMCC(sizeof(CANDIDATEINFO)); 749 pIC->hGuideLine = ImmCreateIMCC(sizeof(GUIDELINE)); 750 pIC->hMsgBuf = ImmCreateIMCC(sizeof(UINT)); 751 if (IS_NULL_UNEXPECTEDLY(pIC->hCompStr) || 752 IS_NULL_UNEXPECTEDLY(pIC->hCandInfo) || 753 IS_NULL_UNEXPECTEDLY(pIC->hGuideLine) || 754 IS_NULL_UNEXPECTEDLY(pIC->hMsgBuf)) 755 { 756 goto Fail; 757 } 758 759 /* Initialize IC components */ 760 pCS = ImmLockIMCC(pIC->hCompStr); 761 if (IS_NULL_UNEXPECTEDLY(pCS)) 762 goto Fail; 763 pCS->dwSize = sizeof(COMPOSITIONSTRING); 764 ImmUnlockIMCC(pIC->hCompStr); 765 766 pCI = ImmLockIMCC(pIC->hCandInfo); 767 if (IS_NULL_UNEXPECTEDLY(pCI)) 768 goto Fail; 769 pCI->dwSize = sizeof(CANDIDATEINFO); 770 ImmUnlockIMCC(pIC->hCandInfo); 771 772 pGL = ImmLockIMCC(pIC->hGuideLine); 773 if (IS_NULL_UNEXPECTEDLY(pGL)) 774 goto Fail; 775 pGL->dwSize = sizeof(GUIDELINE); 776 ImmUnlockIMCC(pIC->hGuideLine); 777 778 pIC->dwNumMsgBuf = 0; 779 pIC->fOpen = FALSE; 780 pIC->fdwConversion = pIC->fdwSentence = 0; 781 782 for (dwIndex = 0; dwIndex < MAX_CANDIDATEFORM; ++dwIndex) 783 pIC->cfCandForm[dwIndex].dwIndex = IMM_INVALID_CANDFORM; 784 785 /* Get private data size */ 786 pImeDpi = ImmLockImeDpi(hKL); 787 if (!pImeDpi) 788 { 789 cbPrivate = sizeof(DWORD); 790 } 791 else 792 { 793 /* Update CLIENTIMC */ 794 pClientImc->uCodePage = pImeDpi->uCodePage; 795 if (ImeDpi_IsUnicode(pImeDpi)) 796 pClientImc->dwFlags |= CLIENTIMC_WIDE; 797 798 cbPrivate = pImeDpi->ImeInfo.dwPrivateDataSize; 799 } 800 801 /* Create private data */ 802 pIC->hPrivate = ImmCreateIMCC(cbPrivate); 803 if (IS_NULL_UNEXPECTEDLY(pIC->hPrivate)) 804 goto Fail; 805 806 CtfImmTIMCreateInputContext(hIMC); 807 808 if (pImeDpi) 809 { 810 /* Select the IME */ 811 if (fSelect) 812 { 813 if (IS_IME_HKL(hKL)) 814 pImeDpi->ImeSelect(hIMC, TRUE); 815 else if (IS_CICERO_MODE() && !IS_16BIT_MODE()) 816 pImeDpi->CtfImeSelectEx(hIMC, TRUE, hKL); 817 } 818 819 /* Set HKL */ 820 pClientImc->hKL = hKL; 821 822 ImmUnlockImeDpi(pImeDpi); 823 } 824 825 return TRUE; 826 827 Fail: 828 if (pImeDpi) 829 ImmUnlockImeDpi(pImeDpi); 830 831 pIC->hMsgBuf = ImmDestroyIMCC(pIC->hMsgBuf); 832 pIC->hGuideLine = ImmDestroyIMCC(pIC->hGuideLine); 833 pIC->hCandInfo = ImmDestroyIMCC(pIC->hCandInfo); 834 pIC->hCompStr = ImmDestroyIMCC(pIC->hCompStr); 835 return FALSE; 836 } 837 838 LPINPUTCONTEXT APIENTRY Imm32InternalLockIMC(HIMC hIMC, BOOL fSelect) 839 { 840 HANDLE hIC; 841 LPINPUTCONTEXT pIC = NULL; 842 PCLIENTIMC pClientImc; 843 WORD LangID; 844 DWORD dwThreadId; 845 HKL hOldKL, hNewKL; 846 PIMEDPI pImeDpi = NULL; 847 848 pClientImc = ImmLockClientImc(hIMC); 849 if (!pClientImc) 850 return NULL; 851 852 RtlEnterCriticalSection(&pClientImc->cs); 853 854 if (pClientImc->hInputContext) 855 { 856 pIC = LocalLock(pClientImc->hInputContext); 857 if (IS_NULL_UNEXPECTEDLY(pIC)) 858 goto Failure; 859 860 CtfImmTIMCreateInputContext(hIMC); 861 goto Success; 862 } 863 864 dwThreadId = (DWORD)NtUserQueryInputContext(hIMC, QIC_INPUTTHREADID); 865 if (dwThreadId == GetCurrentThreadId() && IS_CICERO_MODE() && !IS_16BIT_MODE()) 866 { 867 hOldKL = GetKeyboardLayout(0); 868 LangID = LOWORD(hOldKL); 869 hNewKL = UlongToHandle(MAKELONG(LangID, LangID)); 870 871 pImeDpi = Imm32FindOrLoadImeDpi(hNewKL); 872 if (pImeDpi) 873 { 874 CtfImmTIMActivate(hNewKL); 875 } 876 } 877 878 if (!NtUserQueryInputContext(hIMC, QIC_DEFAULTWINDOWIME)) 879 { 880 ERR("No default IME window\n"); 881 goto Failure; 882 } 883 884 hIC = LocalAlloc(LHND, sizeof(INPUTCONTEXTDX)); 885 pIC = LocalLock(hIC); 886 if (IS_NULL_UNEXPECTEDLY(pIC)) 887 { 888 LocalFree(hIC); 889 goto Failure; 890 } 891 pClientImc->hInputContext = hIC; 892 893 hNewKL = GetKeyboardLayout(dwThreadId); 894 if (!Imm32CreateInputContext(hIMC, pIC, pClientImc, hNewKL, fSelect)) 895 { 896 LocalUnlock(hIC); 897 pClientImc->hInputContext = LocalFree(hIC); 898 goto Failure; 899 } 900 901 Success: 902 RtlLeaveCriticalSection(&pClientImc->cs); 903 InterlockedIncrement(&pClientImc->cLockObj); 904 ImmUnlockClientImc(pClientImc); 905 return pIC; 906 907 Failure: 908 RtlLeaveCriticalSection(&pClientImc->cs); 909 ImmUnlockClientImc(pClientImc); 910 return NULL; 911 } 912 913 /*********************************************************************** 914 * ImmDestroyContext (IMM32.@) 915 */ 916 BOOL WINAPI ImmDestroyContext(HIMC hIMC) 917 { 918 HKL hKL; 919 920 TRACE("(%p)\n", hIMC); 921 922 if (!IS_IMM_MODE()) 923 { 924 TRACE("\n"); 925 return FALSE; 926 } 927 928 if (IS_CROSS_THREAD_HIMC(hIMC)) 929 return FALSE; 930 931 hKL = GetKeyboardLayout(0); 932 return Imm32DestroyInputContext(hIMC, hKL, FALSE); 933 } 934 935 /*********************************************************************** 936 * ImmLockClientImc (IMM32.@) 937 */ 938 PCLIENTIMC WINAPI ImmLockClientImc(HIMC hImc) 939 { 940 PIMC pIMC; 941 PCLIENTIMC pClientImc; 942 943 TRACE("(%p)\n", hImc); 944 945 if (IS_NULL_UNEXPECTEDLY(hImc)) 946 return NULL; 947 948 pIMC = ValidateHandle(hImc, TYPE_INPUTCONTEXT); 949 if (!pIMC || !Imm32CheckImcProcess(pIMC)) 950 return NULL; 951 952 pClientImc = (PCLIENTIMC)pIMC->dwClientImcData; 953 if (pClientImc) 954 { 955 if (pClientImc->dwFlags & CLIENTIMC_DESTROY) 956 return NULL; 957 goto Finish; 958 } 959 960 pClientImc = ImmLocalAlloc(HEAP_ZERO_MEMORY, sizeof(CLIENTIMC)); 961 if (IS_NULL_UNEXPECTEDLY(pClientImc)) 962 return NULL; 963 964 RtlInitializeCriticalSection(&pClientImc->cs); 965 pClientImc->dwCompatFlags = (DWORD)NtUserGetThreadState(THREADSTATE_IMECOMPATFLAGS); 966 967 if (!NtUserUpdateInputContext(hImc, UIC_CLIENTIMCDATA, (DWORD_PTR)pClientImc)) 968 { 969 ERR("\n"); 970 ImmLocalFree(pClientImc); 971 return NULL; 972 } 973 974 pClientImc->dwFlags |= CLIENTIMC_UNKNOWN2; 975 976 Finish: 977 InterlockedIncrement(&pClientImc->cLockObj); 978 return pClientImc; 979 } 980 981 /*********************************************************************** 982 * ImmUnlockClientImc (IMM32.@) 983 */ 984 VOID WINAPI ImmUnlockClientImc(PCLIENTIMC pClientImc) 985 { 986 LONG cLocks; 987 HANDLE hInputContext; 988 989 TRACE("(%p)\n", pClientImc); 990 991 cLocks = InterlockedDecrement(&pClientImc->cLockObj); 992 if (cLocks != 0 || !(pClientImc->dwFlags & CLIENTIMC_DESTROY)) 993 return; 994 995 hInputContext = pClientImc->hInputContext; 996 if (hInputContext) 997 LocalFree(hInputContext); 998 999 RtlDeleteCriticalSection(&pClientImc->cs); 1000 ImmLocalFree(pClientImc); 1001 } 1002 1003 // Win: ImmGetSaveContext 1004 static HIMC APIENTRY ImmGetSaveContext(HWND hWnd, DWORD dwContextFlags) 1005 { 1006 HIMC hIMC; 1007 PCLIENTIMC pClientImc; 1008 PWND pWnd; 1009 1010 if (!IS_IMM_MODE()) 1011 { 1012 TRACE("Not IMM mode.\n"); 1013 return NULL; 1014 } 1015 1016 if (!hWnd) 1017 { 1018 hIMC = (HIMC)NtUserGetThreadState(THREADSTATE_DEFAULTINPUTCONTEXT); 1019 goto Quit; 1020 } 1021 1022 pWnd = ValidateHwnd(hWnd); 1023 if (IS_NULL_UNEXPECTEDLY(pWnd) || IS_CROSS_PROCESS_HWND(hWnd)) 1024 return NULL; 1025 1026 hIMC = pWnd->hImc; 1027 if (!hIMC && (dwContextFlags & 1)) 1028 hIMC = (HIMC)NtUserQueryWindow(hWnd, QUERY_WINDOW_DEFAULT_ICONTEXT); 1029 1030 Quit: 1031 pClientImc = ImmLockClientImc(hIMC); 1032 if (IS_NULL_UNEXPECTEDLY(pClientImc)) 1033 return NULL; 1034 1035 if ((dwContextFlags & 2) && (pClientImc->dwFlags & CLIENTIMC_DISABLEIME)) 1036 hIMC = NULL; 1037 1038 ImmUnlockClientImc(pClientImc); 1039 return hIMC; 1040 } 1041 1042 /*********************************************************************** 1043 * ImmGetContext (IMM32.@) 1044 */ 1045 HIMC WINAPI ImmGetContext(HWND hWnd) 1046 { 1047 TRACE("(%p)\n", hWnd); 1048 if (IS_NULL_UNEXPECTEDLY(hWnd)) 1049 return NULL; 1050 return ImmGetSaveContext(hWnd, 2); 1051 } 1052 1053 /*********************************************************************** 1054 * ImmLockIMC(IMM32.@) 1055 * 1056 * NOTE: This is not ImmLockIMCC. Don't confuse. 1057 */ 1058 LPINPUTCONTEXT WINAPI ImmLockIMC(HIMC hIMC) 1059 { 1060 TRACE("(%p)\n", hIMC); 1061 return Imm32InternalLockIMC(hIMC, TRUE); 1062 } 1063 1064 /*********************************************************************** 1065 * ImmUnlockIMC(IMM32.@) 1066 */ 1067 BOOL WINAPI ImmUnlockIMC(HIMC hIMC) 1068 { 1069 PCLIENTIMC pClientImc; 1070 1071 pClientImc = ImmLockClientImc(hIMC); 1072 if (IS_NULL_UNEXPECTEDLY(pClientImc)) 1073 return FALSE; 1074 1075 if (pClientImc->hInputContext) 1076 LocalUnlock(pClientImc->hInputContext); 1077 1078 InterlockedDecrement(&pClientImc->cLockObj); 1079 ImmUnlockClientImc(pClientImc); 1080 return TRUE; 1081 } 1082 1083 /*********************************************************************** 1084 * ImmReleaseContext (IMM32.@) 1085 */ 1086 BOOL WINAPI ImmReleaseContext(HWND hWnd, HIMC hIMC) 1087 { 1088 TRACE("(%p, %p)\n", hWnd, hIMC); 1089 UNREFERENCED_PARAMETER(hWnd); 1090 UNREFERENCED_PARAMETER(hIMC); 1091 return TRUE; // Do nothing. This is correct. 1092 } 1093 1094 /*********************************************************************** 1095 * ImmEnumInputContext(IMM32.@) 1096 */ 1097 BOOL WINAPI ImmEnumInputContext(DWORD dwThreadId, IMCENUMPROC lpfn, LPARAM lParam) 1098 { 1099 HIMC *phList; 1100 DWORD dwIndex, dwCount; 1101 BOOL ret = TRUE; 1102 HIMC hIMC; 1103 1104 TRACE("(%lu, %p, %p)\n", dwThreadId, lpfn, lParam); 1105 1106 dwCount = Imm32BuildHimcList(dwThreadId, &phList); 1107 if (IS_ZERO_UNEXPECTEDLY(dwCount)) 1108 return FALSE; 1109 1110 for (dwIndex = 0; dwIndex < dwCount; ++dwIndex) 1111 { 1112 hIMC = phList[dwIndex]; 1113 ret = (*lpfn)(hIMC, lParam); 1114 if (!ret) 1115 break; 1116 } 1117 1118 ImmLocalFree(phList); 1119 return ret; 1120 } 1121 1122 /*********************************************************************** 1123 * ImmSetActiveContext(IMM32.@) 1124 */ 1125 BOOL WINAPI ImmSetActiveContext(HWND hWnd, HIMC hIMC, BOOL fActive) 1126 { 1127 PCLIENTIMC pClientImc; 1128 LPINPUTCONTEXTDX pIC; 1129 PIMEDPI pImeDpi; 1130 HIMC hOldIMC; 1131 HKL hKL; 1132 BOOL fOpen = FALSE; 1133 DWORD dwConversion = 0, dwShowFlags = ISC_SHOWUIALL; 1134 HWND hwndDefIME; 1135 1136 TRACE("(%p, %p, %d)\n", hWnd, hIMC, fActive); 1137 1138 if (!IS_IMM_MODE()) 1139 { 1140 TRACE("\n"); 1141 return FALSE; 1142 } 1143 1144 pClientImc = ImmLockClientImc(hIMC); 1145 1146 if (!fActive) 1147 { 1148 if (pClientImc) 1149 pClientImc->dwFlags &= ~CLIENTIMC_ACTIVE; 1150 } 1151 else if (hIMC) 1152 { 1153 if (IS_NULL_UNEXPECTEDLY(pClientImc)) 1154 return FALSE; 1155 1156 pIC = (LPINPUTCONTEXTDX)ImmLockIMC(hIMC); 1157 if (IS_NULL_UNEXPECTEDLY(pIC)) 1158 { 1159 ImmUnlockClientImc(pClientImc); 1160 return FALSE; 1161 } 1162 1163 pIC->hWnd = hWnd; 1164 pClientImc->dwFlags |= CLIENTIMC_ACTIVE; 1165 1166 if (pIC->dwUIFlags & 2) 1167 dwShowFlags = (ISC_SHOWUIGUIDELINE | ISC_SHOWUIALLCANDIDATEWINDOW); 1168 1169 fOpen = pIC->fOpen; 1170 dwConversion = pIC->fdwConversion; 1171 1172 ImmUnlockIMC(hIMC); 1173 } 1174 else 1175 { 1176 hOldIMC = ImmGetSaveContext(hWnd, 1); 1177 pIC = (LPINPUTCONTEXTDX)ImmLockIMC(hOldIMC); 1178 if (pIC) 1179 { 1180 pIC->hWnd = hWnd; 1181 ImmUnlockIMC(hOldIMC); 1182 } 1183 } 1184 1185 hKL = GetKeyboardLayout(0); 1186 if (IS_CICERO_MODE() && !IS_16BIT_MODE()) 1187 { 1188 CtfImeSetActiveContextAlways(hIMC, fActive, hWnd, hKL); 1189 hKL = GetKeyboardLayout(0); 1190 } 1191 1192 pImeDpi = ImmLockImeDpi(hKL); 1193 if (pImeDpi) 1194 { 1195 if (IS_IME_HKL(hKL)) 1196 pImeDpi->ImeSetActiveContext(hIMC, fActive); 1197 ImmUnlockImeDpi(pImeDpi); 1198 } 1199 1200 if (IsWindow(hWnd)) 1201 { 1202 SendMessageW(hWnd, WM_IME_SETCONTEXT, fActive, dwShowFlags); 1203 if (fActive) 1204 NtUserNotifyIMEStatus(hWnd, fOpen, dwConversion); 1205 } 1206 else if (!fActive) 1207 { 1208 hwndDefIME = ImmGetDefaultIMEWnd(NULL); 1209 if (hwndDefIME) 1210 SendMessageW(hwndDefIME, WM_IME_SETCONTEXT, 0, dwShowFlags); 1211 } 1212 1213 if (pClientImc) 1214 ImmUnlockClientImc(pClientImc); 1215 1216 return TRUE; 1217 } 1218 1219 /*********************************************************************** 1220 * ImmWINNLSGetEnableStatus (IMM32.@) 1221 */ 1222 1223 BOOL WINAPI ImmWINNLSGetEnableStatus(HWND hWnd) 1224 { 1225 if (!Imm32IsSystemJapaneseOrKorean()) 1226 { 1227 SetLastError(ERROR_CALL_NOT_IMPLEMENTED); 1228 return FALSE; 1229 } 1230 1231 return !!ImmGetSaveContext(hWnd, 2); 1232 } 1233 1234 /*********************************************************************** 1235 * ImmSetActiveContextConsoleIME(IMM32.@) 1236 */ 1237 BOOL WINAPI ImmSetActiveContextConsoleIME(HWND hwnd, BOOL fFlag) 1238 { 1239 HIMC hIMC; 1240 TRACE("(%p, %d)\n", hwnd, fFlag); 1241 1242 hIMC = ImmGetContext(hwnd); 1243 if (IS_NULL_UNEXPECTEDLY(hIMC)) 1244 return FALSE; 1245 return ImmSetActiveContext(hwnd, hIMC, fFlag); 1246 } 1247 1248 /*********************************************************************** 1249 * GetKeyboardLayoutCP (IMM32.@) 1250 */ 1251 UINT WINAPI GetKeyboardLayoutCP(_In_ LANGID wLangId) 1252 { 1253 WCHAR szText[8]; 1254 static LANGID s_wKeyboardLangIdCache = 0; 1255 static UINT s_uKeyboardLayoutCPCache = 0; 1256 1257 TRACE("(%u)\n", wLangId); 1258 1259 if (wLangId == s_wKeyboardLangIdCache) 1260 return s_uKeyboardLayoutCPCache; 1261 1262 if (!GetLocaleInfoW(wLangId, LOCALE_IDEFAULTANSICODEPAGE, szText, _countof(szText))) 1263 return 0; 1264 1265 s_wKeyboardLangIdCache = wLangId; 1266 szText[_countof(szText) - 1] = UNICODE_NULL; /* Avoid buffer overrun */ 1267 s_uKeyboardLayoutCPCache = wcstol(szText, NULL, 10); 1268 return s_uKeyboardLayoutCPCache; 1269 } 1270 1271 #ifndef NDEBUG 1272 VOID APIENTRY Imm32UnitTest(VOID) 1273 { 1274 if (0) 1275 { 1276 DWORD dwValue; 1277 WCHAR szText[64]; 1278 1279 Imm32StrToUInt(L"123", &dwValue, 10); 1280 ASSERT(dwValue == 123); 1281 Imm32StrToUInt(L"100", &dwValue, 16); 1282 ASSERT(dwValue == 0x100); 1283 1284 Imm32UIntToStr(123, 10, szText, _countof(szText)); 1285 ASSERT(lstrcmpW(szText, L"123") == 0); 1286 Imm32UIntToStr(0x100, 16, szText, _countof(szText)); 1287 ASSERT(lstrcmpW(szText, L"100") == 0); 1288 } 1289 } 1290 #endif 1291 1292 BOOL WINAPI User32InitializeImmEntryTable(DWORD); 1293 1294 BOOL 1295 WINAPI 1296 ImmDllInitialize( 1297 _In_ HINSTANCE hDll, 1298 _In_ ULONG dwReason, 1299 _In_opt_ PVOID pReserved) 1300 { 1301 HKL hKL; 1302 HIMC hIMC; 1303 1304 TRACE("(%p, 0x%X, %p)\n", hDll, dwReason, pReserved); 1305 1306 switch (dwReason) 1307 { 1308 case DLL_PROCESS_ATTACH: 1309 if (!ImmInitializeGlobals(hDll)) 1310 { 1311 ERR("ImmInitializeGlobals failed\n"); 1312 return FALSE; 1313 } 1314 if (!User32InitializeImmEntryTable(IMM_INIT_MAGIC)) 1315 { 1316 ERR("User32InitializeImmEntryTable failed\n"); 1317 return FALSE; 1318 } 1319 #ifndef NDEBUG 1320 Imm32UnitTest(); 1321 #endif 1322 break; 1323 1324 case DLL_THREAD_ATTACH: 1325 break; 1326 1327 case DLL_THREAD_DETACH: 1328 if (!IS_IMM_MODE() || NtCurrentTeb()->Win32ThreadInfo == NULL) 1329 return TRUE; 1330 1331 hKL = GetKeyboardLayout(0); 1332 hIMC = (HIMC)NtUserGetThreadState(THREADSTATE_DEFAULTINPUTCONTEXT); 1333 Imm32DestroyInputContext(hIMC, hKL, TRUE); 1334 break; 1335 1336 case DLL_PROCESS_DETACH: 1337 RtlDeleteCriticalSection(&gcsImeDpi); 1338 TRACE("imm32.dll is unloaded\n"); 1339 break; 1340 } 1341 1342 return TRUE; 1343 } 1344