1 /* 2 * PROJECT: ReactOS IMM32 3 * LICENSE: LGPL-2.1-or-later (https://spdx.org/licenses/LGPL-2.1-or-later) 4 * PURPOSE: Implementing IMM CTF (Collaborative Translation Framework) 5 * COPYRIGHT: Copyright 2022-2023 Katayama Hirofumi MZ <katayama.hirofumi.mz@gmail.com> 6 */ 7 8 #include "precomp.h" 9 #include <ndk/ldrfuncs.h> /* for RtlDllShutdownInProgress */ 10 #include <msctf.h> /* for ITfLangBarMgr */ 11 #include <objidl.h> /* for IInitializeSpy */ 12 #include <compat_undoc.h> /* for BaseCheckAppcompatCache */ 13 14 WINE_DEFAULT_DEBUG_CHANNEL(imm); 15 16 static BOOL Imm32InsideLoaderLock(VOID) 17 { 18 return NtCurrentTeb()->ProcessEnvironmentBlock->LoaderLock->OwningThread == 19 NtCurrentTeb()->ClientId.UniqueThread; 20 } 21 22 static BOOL 23 Imm32IsInteractiveUserLogon(VOID) 24 { 25 BOOL bOK, IsMember = FALSE; 26 PSID pSid; 27 SID_IDENTIFIER_AUTHORITY IdentAuth = { SECURITY_NT_AUTHORITY }; 28 29 if (!AllocateAndInitializeSid(&IdentAuth, 1, SECURITY_INTERACTIVE_RID, 30 0, 0, 0, 0, 0, 0, 0, &pSid)) 31 { 32 ERR("Error: %ld\n", GetLastError()); 33 return FALSE; 34 } 35 36 bOK = CheckTokenMembership(NULL, pSid, &IsMember); 37 38 if (pSid) 39 FreeSid(pSid); 40 41 return bOK && IsMember; 42 } 43 44 static BOOL 45 Imm32IsRunningInMsoobe(VOID) 46 { 47 LPWSTR pchFilePart = NULL; 48 WCHAR Buffer[MAX_PATH], FileName[MAX_PATH]; 49 50 if (!GetModuleFileNameW(NULL, FileName, _countof(FileName))) 51 return FALSE; 52 53 GetFullPathNameW(FileName, _countof(Buffer), Buffer, &pchFilePart); 54 if (!pchFilePart) 55 return FALSE; 56 57 return lstrcmpiW(pchFilePart, L"msoobe.exe") == 0; 58 } 59 60 static BOOL 61 Imm32IsCUASEnabledInRegistry(VOID) 62 { 63 HKEY hKey; 64 LSTATUS error; 65 DWORD dwType, dwData, cbData; 66 67 error = RegOpenKeyW(HKEY_LOCAL_MACHINE, L"Software\\Microsoft\\CTF\\SystemShared", &hKey); 68 if (error != ERROR_SUCCESS) 69 return FALSE; 70 71 dwData = 0; 72 cbData = sizeof(dwData); 73 error = RegQueryValueExW(hKey, L"CUAS", NULL, &dwType, (LPBYTE)&dwData, &cbData); 74 RegCloseKey(hKey); 75 76 if (error != ERROR_SUCCESS || dwType != REG_DWORD) 77 return FALSE; 78 79 return !!dwData; 80 } 81 82 BOOL 83 Imm32GetFn( 84 _Inout_opt_ FARPROC *ppfn, 85 _Inout_ HINSTANCE *phinstDLL, 86 _In_ LPCWSTR pszDllName, 87 _In_ LPCSTR pszFuncName) 88 { 89 WCHAR szPath[MAX_PATH]; 90 91 if (*ppfn) 92 return TRUE; 93 94 if (*phinstDLL == NULL) 95 { 96 Imm32GetSystemLibraryPath(szPath, _countof(szPath), pszDllName); 97 *phinstDLL = LoadLibraryExW(szPath, NULL, 0); 98 if (*phinstDLL == NULL) 99 return FALSE; 100 } 101 102 *ppfn = (FARPROC)GetProcAddress(*phinstDLL, pszFuncName); 103 return *ppfn != NULL; 104 } 105 106 #define IMM32_GET_FN(ppfn, phinstDLL, dll_name, func_name) \ 107 Imm32GetFn((FARPROC*)(ppfn), (phinstDLL), (dll_name), #func_name) 108 109 /*********************************************************************** 110 * OLE32.DLL 111 */ 112 113 HINSTANCE g_hOle32 = NULL; 114 115 #define OLE32_FN(name) g_pfnOLE32_##name 116 117 typedef HRESULT (WINAPI *FN_CoInitializeEx)(LPVOID, DWORD); 118 typedef VOID (WINAPI *FN_CoUninitialize)(VOID); 119 typedef HRESULT (WINAPI *FN_CoRegisterInitializeSpy)(IInitializeSpy*, ULARGE_INTEGER*); 120 typedef HRESULT (WINAPI *FN_CoRevokeInitializeSpy)(ULARGE_INTEGER); 121 122 FN_CoInitializeEx OLE32_FN(CoInitializeEx) = NULL; 123 FN_CoUninitialize OLE32_FN(CoUninitialize) = NULL; 124 FN_CoRegisterInitializeSpy OLE32_FN(CoRegisterInitializeSpy) = NULL; 125 FN_CoRevokeInitializeSpy OLE32_FN(CoRevokeInitializeSpy) = NULL; 126 127 #define Imm32GetOle32Fn(func_name) \ 128 IMM32_GET_FN(&OLE32_FN(func_name), &g_hOle32, L"ole32.dll", #func_name) 129 130 HRESULT Imm32CoInitializeEx(VOID) 131 { 132 if (!Imm32GetOle32Fn(CoInitializeEx)) 133 return E_FAIL; 134 135 return OLE32_FN(CoInitializeEx)(NULL, COINIT_APARTMENTTHREADED); 136 } 137 138 VOID Imm32CoUninitialize(VOID) 139 { 140 if (!Imm32GetOle32Fn(CoUninitialize)) 141 return; 142 143 OLE32_FN(CoUninitialize)(); 144 } 145 146 HRESULT Imm32CoRegisterInitializeSpy(IInitializeSpy* spy, ULARGE_INTEGER* cookie) 147 { 148 if (!Imm32GetOle32Fn(CoRegisterInitializeSpy)) 149 return E_FAIL; 150 151 return OLE32_FN(CoRegisterInitializeSpy)(spy, cookie); 152 } 153 154 HRESULT Imm32CoRevokeInitializeSpy(ULARGE_INTEGER cookie) 155 { 156 if (!Imm32GetOle32Fn(CoRevokeInitializeSpy)) 157 return E_FAIL; 158 159 return OLE32_FN(CoRevokeInitializeSpy)(cookie); 160 } 161 162 /*********************************************************************** 163 * MSCTF.DLL 164 */ 165 166 HINSTANCE g_hMsctf = NULL; 167 168 #define MSCTF_FN(name) g_pfnMSCTF_##name 169 170 typedef HRESULT (WINAPI *FN_TF_CreateLangBarMgr)(ITfLangBarMgr**); 171 typedef VOID (WINAPI *FN_TF_InvalidAssemblyListCacheIfExist)(VOID); 172 173 FN_TF_CreateLangBarMgr MSCTF_FN(TF_CreateLangBarMgr) = NULL; 174 FN_TF_InvalidAssemblyListCacheIfExist MSCTF_FN(TF_InvalidAssemblyListCacheIfExist) = NULL; 175 176 #define Imm32GetMsctfFn(func_name) \ 177 IMM32_GET_FN(&MSCTF_FN(func_name), &g_hMsctf, L"msctf.dll", #func_name) 178 179 HRESULT Imm32TF_CreateLangBarMgr(_Inout_ ITfLangBarMgr **ppBarMgr) 180 { 181 TRACE("TF_CreateLangBarMgr(%p)\n", ppBarMgr); 182 183 if (!Imm32GetMsctfFn(TF_CreateLangBarMgr)) 184 return E_FAIL; 185 186 return MSCTF_FN(TF_CreateLangBarMgr)(ppBarMgr); 187 } 188 189 VOID Imm32TF_InvalidAssemblyListCacheIfExist(VOID) 190 { 191 TRACE("TF_InvalidAssemblyListCacheIfExist()\n"); 192 193 if (!Imm32GetMsctfFn(TF_InvalidAssemblyListCacheIfExist)) 194 return; 195 196 MSCTF_FN(TF_InvalidAssemblyListCacheIfExist)(); 197 } 198 199 /*********************************************************************** 200 * CTF (Collaborative Translation Framework) IME support 201 */ 202 203 /* "Active IMM" compatibility flags */ 204 DWORD g_aimm_compat_flags = 0; 205 206 /* Disable CUAS? */ 207 BOOL g_disable_CUAS_flag = FALSE; 208 209 /* The instance of the CTF IME file */ 210 HINSTANCE g_hCtfIme = NULL; 211 212 /* Define the function types (FN_...) for CTF IME functions */ 213 #undef DEFINE_CTF_IME_FN 214 #define DEFINE_CTF_IME_FN(func_name, ret_type, params) \ 215 typedef ret_type (WINAPI *FN_##func_name)params; 216 #include <CtfImeTable.h> 217 218 /* Define the global variables (g_pfn...) for CTF IME functions */ 219 #undef DEFINE_CTF_IME_FN 220 #define DEFINE_CTF_IME_FN(func_name, ret_type, params) \ 221 FN_##func_name g_pfn##func_name = NULL; 222 #include <CtfImeTable.h> 223 224 /* The macro that gets the variable name from the CTF IME function name */ 225 #define CTF_IME_FN(func_name) g_pfn##func_name 226 227 /* The type of ApphelpCheckIME function in apphelp.dll */ 228 typedef BOOL (WINAPI *FN_ApphelpCheckIME)(_In_z_ LPCWSTR AppName); 229 230 /*********************************************************************** 231 * This function checks whether the app's IME is disabled by application 232 * compatibility patcher. 233 */ 234 BOOL 235 Imm32CheckAndApplyAppCompat( 236 _In_ ULONG dwReason, 237 _In_z_ LPCWSTR pszAppName) 238 { 239 HINSTANCE hinstApphelp; 240 FN_ApphelpCheckIME pApphelpCheckIME; 241 242 /* Query the application compatibility patcher */ 243 if (BaseCheckAppcompatCache(pszAppName, INVALID_HANDLE_VALUE, NULL, &dwReason)) 244 return TRUE; /* The app's IME is not disabled */ 245 246 /* Load apphelp.dll if necessary */ 247 hinstApphelp = GetModuleHandleW(L"apphelp.dll"); 248 if (!hinstApphelp) 249 { 250 hinstApphelp = LoadLibraryW(L"apphelp.dll"); 251 if (!hinstApphelp) 252 return TRUE; /* There is no apphelp.dll. The app's IME is not disabled */ 253 } 254 255 /* Is ApphelpCheckIME implemented? */ 256 pApphelpCheckIME = (FN_ApphelpCheckIME)GetProcAddress(hinstApphelp, "ApphelpCheckIME"); 257 if (!pApphelpCheckIME) 258 return TRUE; /* Not implemented. The app's IME is not disabled */ 259 260 /* Is the app's IME disabled or not? */ 261 return pApphelpCheckIME(pszAppName); 262 } 263 264 /*********************************************************************** 265 * TLS (Thread-Local Storage) 266 * 267 * See: TlsAlloc 268 */ 269 270 DWORD g_dwTLSIndex = -1; 271 272 /* IMM Thread-Local Storage (TLS) data */ 273 typedef struct IMMTLSDATA 274 { 275 IInitializeSpy *pSpy; /* CoInitialize Spy */ 276 DWORD dwUnknown1; 277 ULARGE_INTEGER uliCookie; /* Spy requires a cookie for revoking */ 278 BOOL bDoCount; /* Is it counting? */ 279 DWORD dwSkipCount; /* The skipped count */ 280 BOOL bUninitializing; /* Is it uninitializing? */ 281 DWORD dwUnknown2; 282 } IMMTLSDATA, *PIMMTLSDATA; 283 284 static VOID 285 Imm32InitTLS(VOID) 286 { 287 RtlEnterCriticalSection(&gcsImeDpi); 288 289 if (g_dwTLSIndex == -1) 290 g_dwTLSIndex = TlsAlloc(); 291 292 RtlLeaveCriticalSection(&gcsImeDpi); 293 } 294 295 static IMMTLSDATA* 296 Imm32AllocateTLS(VOID) 297 { 298 IMMTLSDATA *pData; 299 300 if (g_dwTLSIndex == -1) 301 return NULL; 302 303 pData = (IMMTLSDATA*)TlsGetValue(g_dwTLSIndex); 304 if (pData) 305 return pData; 306 307 pData = (IMMTLSDATA*)ImmLocalAlloc(HEAP_ZERO_MEMORY, sizeof(IMMTLSDATA)); 308 if (IS_NULL_UNEXPECTEDLY(pData)) 309 return NULL; 310 311 if (IS_FALSE_UNEXPECTEDLY(TlsSetValue(g_dwTLSIndex, pData))) 312 { 313 ImmLocalFree(pData); 314 return NULL; 315 } 316 317 return pData; 318 } 319 320 static IMMTLSDATA* 321 Imm32GetTLS(VOID) 322 { 323 if (g_dwTLSIndex == -1) 324 return NULL; 325 326 return (IMMTLSDATA*)TlsGetValue(g_dwTLSIndex); 327 } 328 329 /* Get */ 330 static DWORD 331 Imm32GetCoInitCountSkip(VOID) 332 { 333 IMMTLSDATA *pData = Imm32GetTLS(); 334 if (!pData) 335 return 0; 336 return pData->dwSkipCount; 337 } 338 339 /* Increment */ 340 static DWORD 341 Imm32IncCoInitCountSkip(VOID) 342 { 343 IMMTLSDATA *pData; 344 DWORD dwOldSkipCount; 345 346 pData = Imm32GetTLS(); 347 if (!pData) 348 return 0; 349 350 dwOldSkipCount = pData->dwSkipCount; 351 if (pData->bDoCount) 352 pData->dwSkipCount = dwOldSkipCount + 1; 353 354 return dwOldSkipCount; 355 } 356 357 /* Decrement */ 358 static DWORD 359 Imm32DecCoInitCountSkip(VOID) 360 { 361 DWORD dwSkipCount; 362 IMMTLSDATA *pData; 363 364 pData = Imm32GetTLS();; 365 if (!pData) 366 return 0; 367 368 dwSkipCount = pData->dwSkipCount; 369 if (pData->bDoCount) 370 { 371 if (dwSkipCount) 372 pData->dwSkipCount = dwSkipCount - 1; 373 } 374 375 return dwSkipCount; 376 } 377 378 /*********************************************************************** 379 * CtfImmEnterCoInitCountSkipMode (IMM32.@) 380 */ 381 VOID WINAPI CtfImmEnterCoInitCountSkipMode(VOID) 382 { 383 IMMTLSDATA *pData; 384 385 TRACE("()\n"); 386 387 pData = Imm32GetTLS(); 388 if (pData) 389 ++(pData->bDoCount); 390 } 391 392 /*********************************************************************** 393 * CtfImmLeaveCoInitCountSkipMode (IMM32.@) 394 */ 395 BOOL WINAPI CtfImmLeaveCoInitCountSkipMode(VOID) 396 { 397 IMMTLSDATA *pData; 398 399 TRACE("()\n"); 400 401 pData = Imm32GetTLS(); 402 if (!pData || !pData->bDoCount) 403 return FALSE; 404 405 --(pData->bDoCount); 406 return TRUE; 407 } 408 409 /*********************************************************************** 410 * ISPY (I am not spy!) 411 * 412 * ISPY watches CoInitialize[Ex] / CoUninitialize to manage COM initialization status. 413 */ 414 415 typedef struct ISPY 416 { 417 const IInitializeSpyVtbl *m_pSpyVtbl; 418 LONG m_cRefs; 419 } ISPY, *PISPY; 420 421 static STDMETHODIMP 422 ISPY_QueryInterface( 423 _Inout_ IInitializeSpy *pThis, 424 _In_ REFIID riid, 425 _Inout_ LPVOID *ppvObj) 426 { 427 ISPY *pSpy = (ISPY*)pThis; 428 429 if (!ppvObj) 430 return E_INVALIDARG; 431 432 *ppvObj = NULL; 433 434 if (!IsEqualIID(riid, &IID_IUnknown) && !IsEqualIID(riid, &IID_IInitializeSpy)) 435 return E_NOINTERFACE; 436 437 ++(pSpy->m_cRefs); 438 *ppvObj = pSpy; 439 return S_OK; 440 } 441 442 static STDMETHODIMP_(ULONG) 443 ISPY_AddRef( 444 _Inout_ IInitializeSpy *pThis) 445 { 446 ISPY *pSpy = (ISPY*)pThis; 447 return ++pSpy->m_cRefs; 448 } 449 450 static STDMETHODIMP_(ULONG) 451 ISPY_Release( 452 _Inout_ IInitializeSpy *pThis) 453 { 454 ISPY *pSpy = (ISPY*)pThis; 455 if (--pSpy->m_cRefs == 0) 456 { 457 ImmLocalFree(pSpy); 458 return 0; 459 } 460 return pSpy->m_cRefs; 461 } 462 463 /* 464 * (Pre/Post)(Initialize/Uninitialize) will be automatically called from OLE32 465 * as the results of watching. 466 */ 467 468 static STDMETHODIMP 469 ISPY_PreInitialize( 470 _Inout_ IInitializeSpy *pThis, 471 _In_ DWORD dwCoInit, 472 _In_ DWORD dwCurThreadAptRefs) 473 { 474 DWORD cCount; 475 476 UNREFERENCED_PARAMETER(pThis); 477 478 cCount = Imm32IncCoInitCountSkip(); 479 if (!dwCoInit && 480 (dwCurThreadAptRefs == cCount + 1) && 481 (GetWin32ClientInfo()->CI_flags & CI_CTFCOINIT)) 482 { 483 Imm32ActivateOrDeactivateTIM(FALSE); 484 CtfImmCoUninitialize(); 485 } 486 487 return S_OK; 488 } 489 490 static STDMETHODIMP 491 ISPY_PostInitialize( 492 _Inout_ IInitializeSpy *pThis, 493 _In_ HRESULT hrCoInit, 494 _In_ DWORD dwCoInit, 495 _In_ DWORD dwNewThreadAptRefs) 496 { 497 DWORD CoInitCountSkip; 498 499 UNREFERENCED_PARAMETER(pThis); 500 UNREFERENCED_PARAMETER(dwCoInit); 501 502 CoInitCountSkip = Imm32GetCoInitCountSkip(); 503 504 if ((hrCoInit != S_FALSE) || 505 (dwNewThreadAptRefs != CoInitCountSkip + 2) || 506 !(GetWin32ClientInfo()->CI_flags & CI_CTFCOINIT)) 507 { 508 return hrCoInit; 509 } 510 511 return S_OK; 512 } 513 514 static STDMETHODIMP 515 ISPY_PreUninitialize( 516 _Inout_ IInitializeSpy *pThis, 517 _In_ DWORD dwCurThreadAptRefs) 518 { 519 UNREFERENCED_PARAMETER(pThis); 520 521 if (dwCurThreadAptRefs == 1 && 522 !RtlDllShutdownInProgress() && 523 !Imm32InsideLoaderLock() && 524 (GetWin32ClientInfo()->CI_flags & CI_CTFCOINIT)) 525 { 526 IMMTLSDATA *pData = Imm32GetTLS(); 527 if (pData && !pData->bUninitializing) 528 Imm32CoInitializeEx(); 529 } 530 531 return S_OK; 532 } 533 534 static STDMETHODIMP 535 ISPY_PostUninitialize( 536 _In_ IInitializeSpy *pThis, 537 _In_ DWORD dwNewThreadAptRefs) 538 { 539 UNREFERENCED_PARAMETER(pThis); 540 UNREFERENCED_PARAMETER(dwNewThreadAptRefs); 541 Imm32DecCoInitCountSkip(); 542 return S_OK; 543 } 544 545 static const IInitializeSpyVtbl g_vtblISPY = 546 { 547 ISPY_QueryInterface, 548 ISPY_AddRef, 549 ISPY_Release, 550 ISPY_PreInitialize, 551 ISPY_PostInitialize, 552 ISPY_PreUninitialize, 553 ISPY_PostUninitialize, 554 }; 555 556 static ISPY* 557 Imm32AllocIMMISPY(VOID) 558 { 559 ISPY *pSpy = (ISPY*)ImmLocalAlloc(0, sizeof(ISPY)); 560 if (!pSpy) 561 return NULL; 562 563 pSpy->m_pSpyVtbl = &g_vtblISPY; 564 pSpy->m_cRefs = 1; 565 return pSpy; 566 } 567 568 #define Imm32DeleteIMMISPY(pSpy) ImmLocalFree(pSpy) 569 570 /*********************************************************************** 571 * CtfImmCoInitialize (Not exported) 572 */ 573 HRESULT 574 CtfImmCoInitialize(VOID) 575 { 576 HRESULT hr; 577 IMMTLSDATA *pData; 578 ISPY *pSpy; 579 580 if (GetWin32ClientInfo()->CI_flags & CI_CTFCOINIT) 581 return S_OK; /* Already initialized */ 582 583 hr = Imm32CoInitializeEx(); 584 if (FAILED_UNEXPECTEDLY(hr)) 585 return hr; /* CoInitializeEx failed */ 586 587 GetWin32ClientInfo()->CI_flags |= CI_CTFCOINIT; 588 Imm32InitTLS(); 589 590 pData = Imm32AllocateTLS(); 591 if (!pData || pData->pSpy) 592 return S_OK; /* Cannot allocate or already it has a spy */ 593 594 pSpy = Imm32AllocIMMISPY(); 595 pData->pSpy = (IInitializeSpy*)pSpy; 596 if (IS_NULL_UNEXPECTEDLY(pSpy)) 597 return S_OK; /* Cannot allocate a spy */ 598 599 if (FAILED_UNEXPECTEDLY(Imm32CoRegisterInitializeSpy(pData->pSpy, &pData->uliCookie))) 600 { 601 /* Failed to register the spy */ 602 Imm32DeleteIMMISPY(pData->pSpy); 603 pData->pSpy = NULL; 604 pData->uliCookie.QuadPart = 0; 605 } 606 607 return S_OK; 608 } 609 610 /*********************************************************************** 611 * CtfImmCoUninitialize (IMM32.@) 612 */ 613 VOID WINAPI 614 CtfImmCoUninitialize(VOID) 615 { 616 IMMTLSDATA *pData; 617 618 if (!(GetWin32ClientInfo()->CI_flags & CI_CTFCOINIT)) 619 return; /* Not CoInitialize'd */ 620 621 pData = Imm32GetTLS(); 622 if (pData) 623 { 624 pData->bUninitializing = TRUE; 625 Imm32CoUninitialize(); /* Do CoUninitialize */ 626 pData->bUninitializing = FALSE; 627 628 GetWin32ClientInfo()->CI_flags &= ~CI_CTFCOINIT; 629 } 630 631 pData = Imm32AllocateTLS(); 632 if (!pData || !pData->pSpy) 633 return; /* There were no spy */ 634 635 /* Our work is done. We don't need spies like you anymore. */ 636 Imm32CoRevokeInitializeSpy(pData->uliCookie); 637 ISPY_Release(pData->pSpy); 638 pData->pSpy = NULL; 639 pData->uliCookie.QuadPart = 0; 640 } 641 642 /*********************************************************************** 643 * This function loads the CTF IME file if necessary and establishes 644 * communication with the CTF IME. 645 */ 646 HINSTANCE 647 Imm32LoadCtfIme(VOID) 648 { 649 BOOL bSuccess = FALSE; 650 IMEINFOEX ImeInfoEx; 651 WCHAR szImeFile[MAX_PATH]; 652 653 /* Lock the IME interface */ 654 RtlEnterCriticalSection(&gcsImeDpi); 655 656 do 657 { 658 if (g_hCtfIme) /* Already loaded? */ 659 { 660 bSuccess = TRUE; 661 break; 662 } 663 664 /* 665 * NOTE: (HKL)0x04090409 is English US keyboard (default). 666 * The Cicero keyboard logically uses English US keyboard. 667 */ 668 if (!ImmLoadLayout((HKL)ULongToHandle(0x04090409), &ImeInfoEx)) 669 break; 670 671 /* Build a path string in system32. The installed IME file must be in system32. */ 672 Imm32GetSystemLibraryPath(szImeFile, _countof(szImeFile), ImeInfoEx.wszImeFile); 673 674 /* Is the CTF IME disabled by app compatibility patcher? */ 675 if (!Imm32CheckAndApplyAppCompat(0, szImeFile)) 676 break; /* This IME is disabled */ 677 678 /* Load a CTF IME file */ 679 g_hCtfIme = LoadLibraryW(szImeFile); 680 if (!g_hCtfIme) 681 break; 682 683 /* Assume success */ 684 bSuccess = TRUE; 685 686 /* Retrieve the CTF IME functions */ 687 #undef DEFINE_CTF_IME_FN 688 #define DEFINE_CTF_IME_FN(func_name, ret_type, params) \ 689 CTF_IME_FN(func_name) = (FN_##func_name)GetProcAddress(g_hCtfIme, #func_name); \ 690 if (!CTF_IME_FN(func_name)) \ 691 { \ 692 bSuccess = FALSE; /* Failed */ \ 693 break; \ 694 } 695 #include <CtfImeTable.h> 696 } while (0); 697 698 /* Unload the CTF IME if failed */ 699 if (!bSuccess) 700 { 701 /* Set NULL to the function pointers */ 702 #undef DEFINE_CTF_IME_FN 703 #define DEFINE_CTF_IME_FN(func_name, ret_type, params) CTF_IME_FN(func_name) = NULL; 704 #include <CtfImeTable.h> 705 706 if (g_hCtfIme) 707 { 708 FreeLibrary(g_hCtfIme); 709 g_hCtfIme = NULL; 710 } 711 } 712 713 /* Unlock the IME interface */ 714 RtlLeaveCriticalSection(&gcsImeDpi); 715 716 return g_hCtfIme; 717 } 718 719 /*********************************************************************** 720 * This function calls the same name function of the CTF IME side. 721 */ 722 HRESULT 723 CtfImeCreateThreadMgr(VOID) 724 { 725 TRACE("()\n"); 726 727 if (!Imm32LoadCtfIme()) 728 return E_FAIL; 729 730 return CTF_IME_FN(CtfImeCreateThreadMgr)(); 731 } 732 733 /*********************************************************************** 734 * This function calls the same name function of the CTF IME side. 735 */ 736 BOOL 737 CtfImeProcessCicHotkey(_In_ HIMC hIMC, _In_ UINT vKey, _In_ LPARAM lParam) 738 { 739 TRACE("(%p, %u, %p)\n", hIMC, vKey, lParam); 740 741 if (!Imm32LoadCtfIme()) 742 return FALSE; 743 744 return CTF_IME_FN(CtfImeProcessCicHotkey)(hIMC, vKey, lParam); 745 } 746 747 /*********************************************************************** 748 * This function calls the same name function of the CTF IME side. 749 */ 750 HRESULT 751 CtfImeDestroyThreadMgr(VOID) 752 { 753 TRACE("()\n"); 754 755 if (!Imm32LoadCtfIme()) 756 return E_FAIL; 757 758 return CTF_IME_FN(CtfImeDestroyThreadMgr)(); 759 } 760 761 /*********************************************************************** 762 * CtfAImmIsIME (IMM32.@) 763 * 764 * @return TRUE if CTF IME or IMM IME is enabled. 765 */ 766 BOOL WINAPI 767 CtfAImmIsIME(_In_ HKL hKL) 768 { 769 TRACE("(%p)\n", hKL); 770 if (!Imm32LoadCtfIme()) 771 return ImmIsIME(hKL); 772 return CTF_IME_FN(CtfImeIsIME)(hKL); 773 } 774 775 /*********************************************************************** 776 * CtfImmIsCiceroStartedInThread (IMM32.@) 777 * 778 * @return TRUE if Cicero is started in the current thread. 779 */ 780 BOOL WINAPI 781 CtfImmIsCiceroStartedInThread(VOID) 782 { 783 TRACE("()\n"); 784 return !!(GetWin32ClientInfo()->CI_flags & CI_CICERO_STARTED); 785 } 786 787 /*********************************************************************** 788 * CtfImmSetCiceroStartInThread (IMM32.@) 789 */ 790 VOID WINAPI CtfImmSetCiceroStartInThread(_In_ BOOL bStarted) 791 { 792 TRACE("(%d)\n", bStarted); 793 if (bStarted) 794 GetWin32ClientInfo()->CI_flags |= CI_CICERO_STARTED; 795 else 796 GetWin32ClientInfo()->CI_flags &= ~CI_CICERO_STARTED; 797 } 798 799 /*********************************************************************** 800 * CtfImmSetAppCompatFlags (IMM32.@) 801 * 802 * Sets the application compatibility flags. 803 */ 804 VOID WINAPI 805 CtfImmSetAppCompatFlags(_In_ DWORD dwFlags) 806 { 807 TRACE("(0x%08X)\n", dwFlags); 808 if (!(dwFlags & 0xF0FFFFFF)) 809 g_aimm_compat_flags = dwFlags; 810 } 811 812 /*********************************************************************** 813 * This function calls the same name function of the CTF IME side. 814 */ 815 HRESULT 816 CtfImeCreateInputContext( 817 _In_ HIMC hIMC) 818 { 819 TRACE("(%p)\n", hIMC); 820 821 if (!Imm32LoadCtfIme()) 822 return E_FAIL; 823 824 return CTF_IME_FN(CtfImeCreateInputContext)(hIMC); 825 } 826 827 /*********************************************************************** 828 * This function calls the same name function of the CTF IME side. 829 */ 830 HRESULT 831 CtfImeDestroyInputContext(_In_ HIMC hIMC) 832 { 833 TRACE("(%p)\n", hIMC); 834 835 if (!Imm32LoadCtfIme()) 836 return E_FAIL; 837 838 return CTF_IME_FN(CtfImeDestroyInputContext)(hIMC); 839 } 840 841 /*********************************************************************** 842 * This function calls the same name function of the CTF IME side. 843 */ 844 HRESULT 845 CtfImeSetActiveContextAlways( 846 _In_ HIMC hIMC, 847 _In_ BOOL fActive, 848 _In_ HWND hWnd, 849 _In_ HKL hKL) 850 { 851 TRACE("(%p, %d, %p, %p)\n", hIMC, fActive, hWnd, hKL); 852 853 if (!Imm32LoadCtfIme()) 854 return E_FAIL; 855 856 return CTF_IME_FN(CtfImeSetActiveContextAlways)(hIMC, fActive, hWnd, hKL); 857 } 858 859 /*********************************************************************** 860 * The callback function to activate CTF IMEs. Used in CtfAImmActivate. 861 */ 862 static BOOL CALLBACK 863 Imm32EnumCreateCtfICProc( 864 _In_ HIMC hIMC, 865 _In_ LPARAM lParam) 866 { 867 UNREFERENCED_PARAMETER(lParam); 868 CtfImeCreateInputContext(hIMC); 869 return TRUE; /* Continue */ 870 } 871 872 /*********************************************************************** 873 * Thread Input Manager (TIM) 874 */ 875 876 static BOOL 877 Imm32IsTIMDisabledInRegistry(VOID) 878 { 879 DWORD dwData, cbData; 880 HKEY hKey; 881 LSTATUS error; 882 883 error = RegOpenKeyW(HKEY_CURRENT_USER, L"SOFTWARE\\Microsoft\\CTF", &hKey); 884 if (error != ERROR_SUCCESS) 885 return FALSE; 886 887 dwData = 0; 888 cbData = sizeof(dwData); 889 RegQueryValueExW(hKey, L"Disable Thread Input Manager", NULL, NULL, (LPBYTE)&dwData, &cbData); 890 RegCloseKey(hKey); 891 return !!dwData; 892 } 893 894 HRESULT 895 Imm32ActivateOrDeactivateTIM( 896 _In_ BOOL bCreate) 897 { 898 HRESULT hr = S_OK; 899 900 if (!IS_CICERO_MODE() || IS_16BIT_MODE() || 901 !(GetWin32ClientInfo()->CI_flags & CI_CTFCOINIT)) 902 { 903 return S_OK; /* No need to activate/de-activate TIM */ 904 } 905 906 if (bCreate) 907 { 908 if (!(GetWin32ClientInfo()->CI_flags & CI_CTFTIM)) 909 { 910 hr = CtfImeCreateThreadMgr(); 911 if (SUCCEEDED(hr)) 912 GetWin32ClientInfo()->CI_flags |= CI_CTFTIM; 913 } 914 } 915 else /* Destroy */ 916 { 917 if (GetWin32ClientInfo()->CI_flags & CI_CTFTIM) 918 { 919 hr = CtfImeDestroyThreadMgr(); 920 if (SUCCEEDED(hr)) 921 GetWin32ClientInfo()->CI_flags &= ~CI_CTFTIM; 922 } 923 } 924 925 return hr; 926 } 927 928 HRESULT 929 CtfImmTIMDestroyInputContext( 930 _In_ HIMC hIMC) 931 { 932 if (!IS_CICERO_MODE() || (GetWin32ClientInfo()->dwCompatFlags2 & 2)) 933 return E_NOINTERFACE; 934 935 return CtfImeDestroyInputContext(hIMC); 936 } 937 938 HRESULT 939 CtfImmTIMCreateInputContext( 940 _In_ HIMC hIMC) 941 { 942 PCLIENTIMC pClientImc; 943 DWORD_PTR dwImeThreadId, dwCurrentThreadId; 944 HRESULT hr = S_FALSE; 945 946 TRACE("(%p)\n", hIMC); 947 948 pClientImc = ImmLockClientImc(hIMC); 949 if (!pClientImc) 950 return E_FAIL; 951 952 if (GetWin32ClientInfo()->CI_flags & CI_AIMMACTIVATED) 953 { 954 if (!pClientImc->bCtfIme) 955 { 956 dwImeThreadId = NtUserQueryInputContext(hIMC, QIC_INPUTTHREADID); 957 dwCurrentThreadId = GetCurrentThreadId(); 958 if (dwImeThreadId == dwCurrentThreadId) 959 { 960 pClientImc->bCtfIme = TRUE; 961 hr = CtfImeCreateInputContext(hIMC); 962 if (FAILED_UNEXPECTEDLY(hr)) 963 pClientImc->bCtfIme = FALSE; 964 } 965 } 966 } 967 else 968 { 969 if (!(GetWin32ClientInfo()->CI_flags & CI_CTFTIM)) 970 return S_OK; 971 972 if (!pClientImc->bCtfIme) 973 { 974 dwImeThreadId = NtUserQueryInputContext(hIMC, QIC_INPUTTHREADID); 975 dwCurrentThreadId = GetCurrentThreadId(); 976 if ((dwImeThreadId == dwCurrentThreadId) && IS_CICERO_MODE() && !IS_16BIT_MODE()) 977 { 978 pClientImc->bCtfIme = TRUE; 979 hr = CtfImeCreateInputContext(hIMC); 980 if (FAILED_UNEXPECTEDLY(hr)) 981 pClientImc->bCtfIme = FALSE; 982 } 983 } 984 } 985 986 ImmUnlockClientImc(pClientImc); 987 return hr; 988 } 989 990 /*********************************************************************** 991 * CtfImmLastEnabledWndDestroy (IMM32.@) 992 * 993 * Same as Imm32ActivateOrDeactivateTIM but its naming is improper. 994 */ 995 HRESULT WINAPI 996 CtfImmLastEnabledWndDestroy( 997 _In_ BOOL bCreate) 998 { 999 TRACE("(%d)\n", bCreate); 1000 return Imm32ActivateOrDeactivateTIM(bCreate); 1001 } 1002 1003 /*********************************************************************** 1004 * CtfAImmActivate (IMM32.@) 1005 * 1006 * This function activates "Active IMM" (AIMM) and TSF. 1007 */ 1008 HRESULT WINAPI 1009 CtfAImmActivate( 1010 _Out_opt_ HINSTANCE *phinstCtfIme) 1011 { 1012 HRESULT hr; 1013 HINSTANCE hinstCtfIme; 1014 1015 TRACE("(%p)\n", phinstCtfIme); 1016 1017 /* Load a CTF IME file if necessary */ 1018 hinstCtfIme = Imm32LoadCtfIme(); 1019 1020 /* Create a thread manager of the CTF IME */ 1021 hr = CtfImeCreateThreadMgr(); 1022 if (hr == S_OK) 1023 { 1024 /* Update CI_... flags of the thread client info */ 1025 GetWin32ClientInfo()->CI_flags |= CI_AIMMACTIVATED; /* Activate AIMM */ 1026 GetWin32ClientInfo()->CI_flags &= ~CI_TSFDISABLED; /* Enable TSF */ 1027 1028 /* Create the CTF input contexts */ 1029 ImmEnumInputContext(0, Imm32EnumCreateCtfICProc, 0); 1030 } 1031 1032 if (phinstCtfIme) 1033 *phinstCtfIme = hinstCtfIme; 1034 1035 return hr; 1036 } 1037 1038 /*********************************************************************** 1039 * CtfAImmDeactivate (IMM32.@) 1040 * 1041 * This function de-activates "Active IMM" (AIMM) and TSF. 1042 */ 1043 HRESULT WINAPI 1044 CtfAImmDeactivate( 1045 _In_ BOOL bDestroy) 1046 { 1047 HRESULT hr; 1048 1049 if (!bDestroy) 1050 return E_FAIL; 1051 1052 hr = CtfImeDestroyThreadMgr(); 1053 if (hr == S_OK) 1054 { 1055 GetWin32ClientInfo()->CI_flags &= ~CI_AIMMACTIVATED; /* Deactivate AIMM */ 1056 GetWin32ClientInfo()->CI_flags |= CI_TSFDISABLED; /* Disable TSF */ 1057 } 1058 1059 return hr; 1060 } 1061 1062 /*********************************************************************** 1063 * CtfImmIsCiceroEnabled (IMM32.@) 1064 * 1065 * @return TRUE if Cicero is enabled. 1066 */ 1067 BOOL WINAPI 1068 CtfImmIsCiceroEnabled(VOID) 1069 { 1070 return IS_CICERO_MODE(); 1071 } 1072 1073 /*********************************************************************** 1074 * CtfImmIsTextFrameServiceDisabled (IMM32.@) 1075 * 1076 * @return TRUE if TSF is disabled. 1077 */ 1078 BOOL WINAPI 1079 CtfImmIsTextFrameServiceDisabled(VOID) 1080 { 1081 return !!(GetWin32ClientInfo()->CI_flags & CI_TSFDISABLED); 1082 } 1083 1084 /*********************************************************************** 1085 * ImmDisableTextFrameService (IMM32.@) 1086 */ 1087 BOOL WINAPI 1088 ImmDisableTextFrameService(_In_ DWORD dwThreadId) 1089 { 1090 HRESULT hr = S_OK; 1091 1092 TRACE("(0x%lX)\n", dwThreadId); 1093 1094 if (dwThreadId == -1) 1095 g_disable_CUAS_flag = TRUE; 1096 1097 if ((dwThreadId && !g_disable_CUAS_flag) || (GetWin32ClientInfo()->CI_flags & CI_TSFDISABLED)) 1098 return TRUE; 1099 1100 GetWin32ClientInfo()->CI_flags |= CI_TSFDISABLED; 1101 1102 if (IS_CICERO_MODE() && !IS_16BIT_MODE() && 1103 (GetWin32ClientInfo()->CI_flags & CI_CTFCOINIT) && 1104 (GetWin32ClientInfo()->CI_flags & CI_CTFTIM)) 1105 { 1106 hr = CtfImeDestroyThreadMgr(); 1107 if (SUCCEEDED(hr)) 1108 { 1109 GetWin32ClientInfo()->CI_flags &= ~CI_CTFTIM; 1110 CtfImmCoUninitialize(); 1111 } 1112 } 1113 1114 return hr == S_OK; 1115 } 1116 1117 /*********************************************************************** 1118 * CtfImmTIMActivate (IMM32.@) 1119 * 1120 * Activates Thread Input Manager (TIM) in the thread. 1121 */ 1122 HRESULT WINAPI 1123 CtfImmTIMActivate(_In_ HKL hKL) 1124 { 1125 HRESULT hr = S_OK; 1126 1127 TRACE("(%p)\n", hKL); 1128 1129 if (g_disable_CUAS_flag) 1130 { 1131 TRACE("g_disable_CUAS_flag\n"); 1132 GetWin32ClientInfo()->CI_flags |= CI_TSFDISABLED; 1133 return FALSE; 1134 } 1135 1136 if (GetWin32ClientInfo()->CI_flags & CI_TSFDISABLED) 1137 { 1138 TRACE("CI_TSFDISABLED\n"); 1139 return FALSE; 1140 } 1141 1142 if (Imm32IsTIMDisabledInRegistry()) 1143 { 1144 TRACE("TIM is disabled in registry\n"); 1145 GetWin32ClientInfo()->CI_flags |= CI_TSFDISABLED; 1146 return FALSE; 1147 } 1148 1149 if (!Imm32IsInteractiveUserLogon() || Imm32IsRunningInMsoobe()) 1150 { 1151 TRACE("TIM is disabled due to LOGON or MSOBE\n"); 1152 return FALSE; 1153 } 1154 1155 if (!Imm32IsCUASEnabledInRegistry()) 1156 { 1157 TRACE("CUAS is disabled in registry\n"); 1158 GetWin32ClientInfo()->CI_flags |= CI_TSFDISABLED; 1159 return FALSE; 1160 } 1161 1162 if (NtCurrentTeb()->ProcessEnvironmentBlock->AppCompatFlags.LowPart & 0x100) 1163 { 1164 TRACE("CUAS is disabled by AppCompatFlags\n"); 1165 GetWin32ClientInfo()->CI_flags |= CI_TSFDISABLED; 1166 return FALSE; 1167 } 1168 1169 if (RtlIsThreadWithinLoaderCallout() || Imm32InsideLoaderLock()) 1170 { 1171 TRACE("TIM is disabled by Loader\n"); 1172 return FALSE; 1173 } 1174 1175 if (!IS_CICERO_MODE() || IS_16BIT_MODE()) 1176 { 1177 TRACE("TIM is disabled because CICERO mode is unset\n"); 1178 return FALSE; 1179 } 1180 1181 if (IS_IME_HKL(hKL)) 1182 hKL = (HKL)UlongToHandle(MAKELONG(LOWORD(hKL), LOWORD(hKL))); 1183 1184 if (!ImmLoadIME(hKL)) 1185 Imm32TF_InvalidAssemblyListCacheIfExist(); 1186 1187 CtfImmCoInitialize(); 1188 1189 if ((GetWin32ClientInfo()->CI_flags & CI_CTFCOINIT) && 1190 !(GetWin32ClientInfo()->CI_flags & CI_CTFTIM)) 1191 { 1192 hr = CtfImeCreateThreadMgr(); 1193 if (SUCCEEDED(hr)) 1194 GetWin32ClientInfo()->CI_flags |= CI_CTFTIM; 1195 } 1196 1197 return hr; 1198 } 1199 1200 /*********************************************************************** 1201 * Setting language band 1202 */ 1203 1204 typedef struct IMM_DELAY_SET_LANG_BAND 1205 { 1206 HWND hWnd; 1207 BOOL fSet; 1208 } IMM_DELAY_SET_LANG_BAND, *PIMM_DELAY_SET_LANG_BAND; 1209 1210 /* Sends a message to set the language band with delay. */ 1211 static DWORD APIENTRY Imm32DelaySetLangBandProc(LPVOID arg) 1212 { 1213 HWND hwndDefIME; 1214 WPARAM wParam; 1215 DWORD_PTR lResult; 1216 PIMM_DELAY_SET_LANG_BAND pSetBand = arg; 1217 1218 Sleep(3000); /* Delay 3 seconds! */ 1219 1220 hwndDefIME = ImmGetDefaultIMEWnd(pSetBand->hWnd); 1221 if (hwndDefIME) 1222 { 1223 wParam = (pSetBand->fSet ? IMS_SETLANGBAND : IMS_UNSETLANGBAND); 1224 SendMessageTimeoutW(hwndDefIME, WM_IME_SYSTEM, wParam, (LPARAM)pSetBand->hWnd, 1225 SMTO_BLOCK | SMTO_ABORTIFHUNG, 5000, &lResult); 1226 } 1227 ImmLocalFree(pSetBand); 1228 return FALSE; 1229 } 1230 1231 /* Updates the language band. */ 1232 LRESULT 1233 CtfImmSetLangBand( 1234 _In_ HWND hWnd, 1235 _In_ BOOL fSet) 1236 { 1237 HANDLE hThread; 1238 PWND pWnd = NULL; 1239 PIMM_DELAY_SET_LANG_BAND pSetBand; 1240 DWORD_PTR lResult = 0; 1241 1242 if (hWnd && gpsi) 1243 pWnd = ValidateHwndNoErr(hWnd); 1244 1245 if (IS_NULL_UNEXPECTEDLY(pWnd)) 1246 return 0; 1247 1248 if (pWnd->state2 & WNDS2_WMCREATEMSGPROCESSED) 1249 { 1250 SendMessageTimeoutW(hWnd, WM_USER + 0x105, 0, fSet, SMTO_BLOCK | SMTO_ABORTIFHUNG, 1251 5000, &lResult); 1252 return lResult; 1253 } 1254 1255 pSetBand = ImmLocalAlloc(0, sizeof(IMM_DELAY_SET_LANG_BAND)); 1256 if (IS_NULL_UNEXPECTEDLY(pSetBand)) 1257 return 0; 1258 1259 pSetBand->hWnd = hWnd; 1260 pSetBand->fSet = fSet; 1261 1262 hThread = CreateThread(NULL, 0, Imm32DelaySetLangBandProc, pSetBand, 0, NULL); 1263 if (hThread) 1264 CloseHandle(hThread); 1265 return 0; 1266 } 1267 1268 /*********************************************************************** 1269 * CtfImmGenerateMessage (IMM32.@) 1270 */ 1271 BOOL WINAPI 1272 CtfImmGenerateMessage( 1273 _In_ HIMC hIMC, 1274 _In_ BOOL bSend) 1275 { 1276 DWORD_PTR dwImeThreadId, dwCurrentThreadId; 1277 PCLIENTIMC pClientImc; 1278 BOOL bUnicode; 1279 LPINPUTCONTEXT pIC; 1280 DWORD iMsg, dwNumMsgBuf; 1281 LPTRANSMSG pOldTransMsg, pNewTransMsg; 1282 SIZE_T cbTransMsg; 1283 1284 TRACE("(%p, %d)\n", hIMC, bSend); 1285 1286 dwImeThreadId = NtUserQueryInputContext(hIMC, QIC_INPUTTHREADID); 1287 dwCurrentThreadId = GetCurrentThreadId(); 1288 if (dwImeThreadId != dwCurrentThreadId) 1289 { 1290 ERR("%p vs %p\n", dwImeThreadId, dwCurrentThreadId); 1291 return FALSE; 1292 } 1293 1294 pClientImc = ImmLockClientImc(hIMC); 1295 if (IS_NULL_UNEXPECTEDLY(pClientImc)) 1296 return FALSE; 1297 1298 bUnicode = !!(pClientImc->dwFlags & CLIENTIMC_WIDE); 1299 ImmUnlockClientImc(pClientImc); 1300 1301 pIC = (LPINPUTCONTEXT)ImmLockIMC(hIMC); 1302 if (IS_NULL_UNEXPECTEDLY(pIC)) 1303 return FALSE; 1304 1305 dwNumMsgBuf = pIC->dwNumMsgBuf; 1306 pOldTransMsg = (LPTRANSMSG)ImmLockIMCC(pIC->hMsgBuf); 1307 if (IS_NULL_UNEXPECTEDLY(pOldTransMsg)) 1308 { 1309 pIC->dwNumMsgBuf = 0; 1310 ImmUnlockIMC(hIMC); 1311 return TRUE; 1312 } 1313 1314 cbTransMsg = sizeof(TRANSMSG) * dwNumMsgBuf; 1315 pNewTransMsg = (PTRANSMSG)ImmLocalAlloc(0, cbTransMsg); 1316 if (IS_NULL_UNEXPECTEDLY(pNewTransMsg)) 1317 { 1318 ImmUnlockIMCC(pIC->hMsgBuf); 1319 pIC->dwNumMsgBuf = 0; 1320 ImmUnlockIMC(hIMC); 1321 return TRUE; 1322 } 1323 1324 RtlCopyMemory(pNewTransMsg, pOldTransMsg, cbTransMsg); 1325 1326 for (iMsg = 0; iMsg < dwNumMsgBuf; ++iMsg) 1327 { 1328 HWND hWnd = pIC->hWnd; 1329 UINT uMsg = pNewTransMsg[iMsg].message; 1330 WPARAM wParam = pNewTransMsg[iMsg].wParam; 1331 LPARAM lParam = pNewTransMsg[iMsg].lParam; 1332 if (bSend) 1333 { 1334 if (bUnicode) 1335 SendMessageW(hWnd, uMsg, wParam, lParam); 1336 else 1337 SendMessageA(hWnd, uMsg, wParam, lParam); 1338 } 1339 else 1340 { 1341 if (bUnicode) 1342 PostMessageW(hWnd, uMsg, wParam, lParam); 1343 else 1344 PostMessageA(hWnd, uMsg, wParam, lParam); 1345 } 1346 } 1347 1348 ImmLocalFree(pNewTransMsg); 1349 ImmUnlockIMCC(pIC->hMsgBuf); 1350 pIC->dwNumMsgBuf = 0; /* Processed */ 1351 ImmUnlockIMC(hIMC); 1352 1353 return TRUE; 1354 } 1355 1356 /*********************************************************************** 1357 * CtfImmHideToolbarWnd (IMM32.@) 1358 * 1359 * Used with CtfImmRestoreToolbarWnd. 1360 */ 1361 DWORD WINAPI 1362 CtfImmHideToolbarWnd(VOID) 1363 { 1364 ITfLangBarMgr *pBarMgr; 1365 DWORD dwShowFlags = 0; 1366 BOOL bShown; 1367 1368 TRACE("()\n"); 1369 1370 if (FAILED(Imm32TF_CreateLangBarMgr(&pBarMgr))) 1371 return dwShowFlags; 1372 1373 if (SUCCEEDED(pBarMgr->lpVtbl->GetShowFloatingStatus(pBarMgr, &dwShowFlags))) 1374 { 1375 bShown = !(dwShowFlags & 0x800); 1376 dwShowFlags &= 0xF; 1377 if (bShown) 1378 pBarMgr->lpVtbl->ShowFloating(pBarMgr, 8); 1379 } 1380 1381 pBarMgr->lpVtbl->Release(pBarMgr); 1382 return dwShowFlags; 1383 } 1384 1385 /*********************************************************************** 1386 * CtfImmRestoreToolbarWnd (IMM32.@) 1387 * 1388 * Used with CtfImmHideToolbarWnd. 1389 */ 1390 VOID WINAPI 1391 CtfImmRestoreToolbarWnd( 1392 _In_ LPVOID pUnused, 1393 _In_ DWORD dwShowFlags) 1394 { 1395 HRESULT hr; 1396 ITfLangBarMgr *pBarMgr; 1397 1398 UNREFERENCED_PARAMETER(pUnused); 1399 1400 TRACE("(%p, 0x%X)\n", pUnused, dwShowFlags); 1401 1402 hr = Imm32TF_CreateLangBarMgr(&pBarMgr); 1403 if (FAILED_UNEXPECTEDLY(hr)) 1404 return; 1405 1406 if (dwShowFlags) 1407 pBarMgr->lpVtbl->ShowFloating(pBarMgr, dwShowFlags); 1408 1409 pBarMgr->lpVtbl->Release(pBarMgr); 1410 } 1411 1412 /*********************************************************************** 1413 * CtfImmDispatchDefImeMessage (IMM32.@) 1414 */ 1415 LRESULT WINAPI 1416 CtfImmDispatchDefImeMessage( 1417 _In_ HWND hWnd, 1418 _In_ UINT uMsg, 1419 _In_ WPARAM wParam, 1420 _In_ LPARAM lParam) 1421 { 1422 TRACE("(%p, %u, %p, %p)\n", hWnd, uMsg, wParam, lParam); 1423 1424 if (RtlDllShutdownInProgress() || Imm32InsideLoaderLock() || !Imm32LoadCtfIme()) 1425 return 0; 1426 1427 return CTF_IME_FN(CtfImeDispatchDefImeMessage)(hWnd, uMsg, wParam, lParam); 1428 } 1429 1430 /*********************************************************************** 1431 * CtfImmIsGuidMapEnable (IMM32.@) 1432 */ 1433 BOOL WINAPI 1434 CtfImmIsGuidMapEnable( 1435 _In_ HIMC hIMC) 1436 { 1437 DWORD dwThreadId; 1438 HKL hKL; 1439 PIMEDPI pImeDpi; 1440 BOOL ret = FALSE; 1441 1442 TRACE("(%p)\n", hIMC); 1443 1444 if (!IS_CICERO_MODE() || IS_16BIT_MODE()) 1445 return ret; 1446 1447 dwThreadId = (DWORD)NtUserQueryInputContext(hIMC, QIC_INPUTTHREADID); 1448 hKL = GetKeyboardLayout(dwThreadId); 1449 1450 if (IS_IME_HKL(hKL)) 1451 return ret; 1452 1453 pImeDpi = Imm32FindOrLoadImeDpi(hKL); 1454 if (IS_NULL_UNEXPECTEDLY(pImeDpi)) 1455 return ret; 1456 1457 ret = pImeDpi->CtfImeIsGuidMapEnable(hIMC); 1458 1459 ImmUnlockImeDpi(pImeDpi); 1460 return ret; 1461 } 1462 1463 /*********************************************************************** 1464 * CtfImmGetGuidAtom (IMM32.@) 1465 */ 1466 HRESULT WINAPI 1467 CtfImmGetGuidAtom( 1468 _In_ HIMC hIMC, 1469 _In_ DWORD dwUnknown, 1470 _Out_ LPDWORD pdwGuidAtom) 1471 { 1472 HRESULT hr = E_FAIL; 1473 PIMEDPI pImeDpi; 1474 DWORD dwThreadId; 1475 HKL hKL; 1476 1477 TRACE("(%p, 0xlX, %p)\n", hIMC, dwUnknown, pdwGuidAtom); 1478 1479 *pdwGuidAtom = 0; 1480 1481 if (!IS_CICERO_MODE() || IS_16BIT_MODE()) 1482 return hr; 1483 1484 dwThreadId = (DWORD)NtUserQueryInputContext(hIMC, QIC_INPUTTHREADID); 1485 hKL = GetKeyboardLayout(dwThreadId); 1486 if (IS_IME_HKL(hKL)) 1487 return S_OK; 1488 1489 pImeDpi = Imm32FindOrLoadImeDpi(hKL); 1490 if (IS_NULL_UNEXPECTEDLY(pImeDpi)) 1491 return hr; 1492 1493 hr = pImeDpi->CtfImeGetGuidAtom(hIMC, dwUnknown, pdwGuidAtom); 1494 1495 ImmUnlockImeDpi(pImeDpi); 1496 return hr; 1497 } 1498