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