Reactos
0
fork

Configure Feed

Select the types of activity you want to include in your feed.

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