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