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