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