1 /* 2 * PROJECT: ReactOS msctfime.ime 3 * LICENSE: LGPL-2.1-or-later (https://spdx.org/licenses/LGPL-2.1-or-later) 4 * PURPOSE: Supporting IME interface of Text Input Processors (TIPs) 5 * COPYRIGHT: Copyright 2023 Katayama Hirofumi MZ <katayama.hirofumi.mz@gmail.com> 6 */ 7 8 #include "msctfime.h" 9 10 WINE_DEFAULT_DEBUG_CHANNEL(msctfime); 11 12 HINSTANCE g_hInst = NULL; /* The instance of this module */ 13 BOOL g_bWinLogon = FALSE; 14 DWORD g_dwOSInfo = 0; 15 BOOL gfTFInitLib = FALSE; 16 CRITICAL_SECTION g_csLock; 17 18 DEFINE_GUID(GUID_COMPARTMENT_CTFIME_DIMFLAGS, 0xA94C5FD2, 0xC471, 0x4031, 0x95, 0x46, 0x70, 0x9C, 0x17, 0x30, 0x0C, 0xB9); 19 20 EXTERN_C void __cxa_pure_virtual(void) 21 { 22 ERR("__cxa_pure_virtual\n"); 23 } 24 25 UINT WM_MSIME_SERVICE = 0; 26 UINT WM_MSIME_UIREADY = 0; 27 UINT WM_MSIME_RECONVERTREQUEST = 0; 28 UINT WM_MSIME_RECONVERT = 0; 29 UINT WM_MSIME_DOCUMENTFEED = 0; 30 UINT WM_MSIME_QUERYPOSITION = 0; 31 UINT WM_MSIME_MODEBIAS = 0; 32 UINT WM_MSIME_SHOWIMEPAD = 0; 33 UINT WM_MSIME_MOUSE = 0; 34 UINT WM_MSIME_KEYMAP = 0; 35 36 /** 37 * @implemented 38 */ 39 BOOL IsMsImeMessage(UINT uMsg) 40 { 41 return (uMsg == WM_MSIME_SERVICE || 42 uMsg == WM_MSIME_UIREADY || 43 uMsg == WM_MSIME_RECONVERTREQUEST || 44 uMsg == WM_MSIME_RECONVERT || 45 uMsg == WM_MSIME_DOCUMENTFEED || 46 uMsg == WM_MSIME_QUERYPOSITION || 47 uMsg == WM_MSIME_MODEBIAS || 48 uMsg == WM_MSIME_SHOWIMEPAD || 49 uMsg == WM_MSIME_MOUSE || 50 uMsg == WM_MSIME_KEYMAP); 51 } 52 53 /** 54 * @implemented 55 */ 56 BOOL RegisterMSIMEMessage(VOID) 57 { 58 WM_MSIME_SERVICE = RegisterWindowMessageW(L"MSIMEService"); 59 WM_MSIME_UIREADY = RegisterWindowMessageW(L"MSIMEUIReady"); 60 WM_MSIME_RECONVERTREQUEST = RegisterWindowMessageW(L"MSIMEReconvertRequest"); 61 WM_MSIME_RECONVERT = RegisterWindowMessageW(L"MSIMEReconvert"); 62 WM_MSIME_DOCUMENTFEED = RegisterWindowMessageW(L"MSIMEDocumentFeed"); 63 WM_MSIME_QUERYPOSITION = RegisterWindowMessageW(L"MSIMEQueryPosition"); 64 WM_MSIME_MODEBIAS = RegisterWindowMessageW(L"MSIMEModeBias"); 65 WM_MSIME_SHOWIMEPAD = RegisterWindowMessageW(L"MSIMEShowImePad"); 66 WM_MSIME_MOUSE = RegisterWindowMessageW(L"MSIMEMouseOperation"); 67 WM_MSIME_KEYMAP = RegisterWindowMessageW(L"MSIMEKeyMap"); 68 return (WM_MSIME_SERVICE && 69 WM_MSIME_UIREADY && 70 WM_MSIME_RECONVERTREQUEST && 71 WM_MSIME_RECONVERT && 72 WM_MSIME_DOCUMENTFEED && 73 WM_MSIME_QUERYPOSITION && 74 WM_MSIME_MODEBIAS && 75 WM_MSIME_SHOWIMEPAD && 76 WM_MSIME_MOUSE && 77 WM_MSIME_KEYMAP); 78 } 79 80 typedef BOOLEAN (WINAPI *FN_DllShutDownInProgress)(VOID); 81 82 EXTERN_C BOOLEAN WINAPI 83 DllShutDownInProgress(VOID) 84 { 85 HMODULE hNTDLL; 86 static FN_DllShutDownInProgress s_fnDllShutDownInProgress = NULL; 87 88 if (s_fnDllShutDownInProgress) 89 return s_fnDllShutDownInProgress(); 90 91 hNTDLL = cicGetSystemModuleHandle(L"ntdll.dll", FALSE); 92 s_fnDllShutDownInProgress = 93 (FN_DllShutDownInProgress)GetProcAddress(hNTDLL, "RtlDllShutdownInProgress"); 94 if (!s_fnDllShutDownInProgress) 95 return FALSE; 96 97 return s_fnDllShutDownInProgress(); 98 } 99 100 static BOOL 101 IsInteractiveUserLogon(VOID) 102 { 103 BOOL bOK, IsMember = FALSE; 104 PSID pSid; 105 SID_IDENTIFIER_AUTHORITY IdentAuth = { SECURITY_NT_AUTHORITY }; 106 107 if (!AllocateAndInitializeSid(&IdentAuth, 1, SECURITY_INTERACTIVE_RID, 108 0, 0, 0, 0, 0, 0, 0, &pSid)) 109 { 110 ERR("Error: %ld\n", GetLastError()); 111 return FALSE; 112 } 113 114 bOK = CheckTokenMembership(NULL, pSid, &IsMember); 115 116 if (pSid) 117 FreeSid(pSid); 118 119 return bOK && IsMember; 120 } 121 122 typedef struct LIBTHREAD 123 { 124 IUnknown *m_pUnknown1; 125 ITfDisplayAttributeMgr *m_pDisplayAttrMgr; 126 } LIBTHREAD, *PLIBTHREAD; 127 128 HRESULT InitDisplayAttrbuteLib(PLIBTHREAD pLibThread) 129 { 130 if (!pLibThread) 131 return E_FAIL; 132 133 if (pLibThread->m_pDisplayAttrMgr) 134 { 135 pLibThread->m_pDisplayAttrMgr->Release(); 136 pLibThread->m_pDisplayAttrMgr = NULL; 137 } 138 139 //FIXME 140 return E_NOTIMPL; 141 } 142 143 HRESULT UninitDisplayAttrbuteLib(PLIBTHREAD pLibThread) 144 { 145 if (!pLibThread) 146 return E_FAIL; 147 148 if (pLibThread->m_pDisplayAttrMgr) 149 { 150 pLibThread->m_pDisplayAttrMgr->Release(); 151 pLibThread->m_pDisplayAttrMgr = NULL; 152 } 153 154 return S_OK; 155 } 156 157 void TFUninitLib_Thread(PLIBTHREAD pLibThread) 158 { 159 if (!pLibThread) 160 return; 161 162 if (pLibThread->m_pUnknown1) 163 { 164 pLibThread->m_pUnknown1->Release(); 165 pLibThread->m_pUnknown1 = NULL; 166 } 167 if (pLibThread->m_pDisplayAttrMgr) 168 { 169 pLibThread->m_pDisplayAttrMgr->Release(); 170 pLibThread->m_pDisplayAttrMgr = NULL; 171 } 172 } 173 174 /*********************************************************************** 175 * Compartment 176 */ 177 178 /** 179 * @implemented 180 */ 181 HRESULT 182 GetCompartment( 183 IUnknown *pUnknown, 184 REFGUID rguid, 185 ITfCompartment **ppComp, 186 BOOL bThread) 187 { 188 *ppComp = NULL; 189 190 ITfThreadMgr *pThreadMgr = NULL; 191 ITfCompartmentMgr *pCompMgr = NULL; 192 193 HRESULT hr; 194 if (bThread) 195 { 196 hr = pUnknown->QueryInterface(IID_ITfThreadMgr, (void **)&pThreadMgr); 197 if (FAILED(hr)) 198 return hr; 199 200 hr = pThreadMgr->GetGlobalCompartment(&pCompMgr); 201 } 202 else 203 { 204 hr = pUnknown->QueryInterface(IID_ITfCompartmentMgr, (void **)&pCompMgr); 205 } 206 207 if (SUCCEEDED(hr)) 208 { 209 hr = E_FAIL; 210 if (pCompMgr) 211 { 212 hr = pCompMgr->GetCompartment(rguid, ppComp); 213 pCompMgr->Release(); 214 } 215 } 216 217 if (pThreadMgr) 218 pThreadMgr->Release(); 219 220 return hr; 221 } 222 223 /** 224 * @implemented 225 */ 226 HRESULT 227 SetCompartmentDWORD( 228 TfEditCookie cookie, 229 IUnknown *pUnknown, 230 REFGUID rguid, 231 DWORD dwValue, 232 BOOL bThread) 233 { 234 ITfCompartment *pComp = NULL; 235 HRESULT hr = GetCompartment(pUnknown, rguid, &pComp, bThread); 236 if (FAILED(hr)) 237 return hr; 238 239 VARIANT vari; 240 V_I4(&vari) = dwValue; 241 V_VT(&vari) = VT_I4; 242 hr = pComp->SetValue(cookie, &vari); 243 244 pComp->Release(); 245 return hr; 246 } 247 248 /** 249 * @implemented 250 */ 251 HRESULT 252 GetCompartmentDWORD( 253 IUnknown *pUnknown, 254 REFGUID rguid, 255 LPDWORD pdwValue, 256 BOOL bThread) 257 { 258 *pdwValue = 0; 259 260 ITfCompartment *pComp = NULL; 261 HRESULT hr = GetCompartment(pUnknown, rguid, &pComp, bThread); 262 if (FAILED(hr)) 263 return hr; 264 265 VARIANT vari; 266 hr = pComp->GetValue(&vari); 267 if (hr == S_OK) 268 *pdwValue = V_I4(&vari); 269 270 pComp->Release(); 271 return hr; 272 } 273 274 /** 275 * @implemented 276 */ 277 HRESULT 278 SetCompartmentUnknown( 279 TfEditCookie cookie, 280 IUnknown *pUnknown, 281 REFGUID rguid, 282 IUnknown *punkValue) 283 { 284 ITfCompartment *pComp = NULL; 285 HRESULT hr = GetCompartment(pUnknown, rguid, &pComp, FALSE); 286 if (FAILED(hr)) 287 return hr; 288 289 VARIANT vari; 290 V_UNKNOWN(&vari) = punkValue; 291 V_VT(&vari) = VT_UNKNOWN; 292 hr = pComp->SetValue(cookie, &vari); 293 294 pComp->Release(); 295 return hr; 296 } 297 298 /** 299 * @implemented 300 */ 301 HRESULT 302 ClearCompartment( 303 TfClientId tid, 304 IUnknown *pUnknown, 305 REFGUID rguid, 306 BOOL bThread) 307 { 308 ITfCompartmentMgr *pCompMgr = NULL; 309 ITfThreadMgr *pThreadMgr = NULL; 310 311 HRESULT hr; 312 if (bThread) 313 { 314 hr = pUnknown->QueryInterface(IID_ITfThreadMgr, (void **)&pThreadMgr); 315 if (FAILED(hr)) 316 return hr; 317 318 hr = pThreadMgr->GetGlobalCompartment(&pCompMgr); 319 } 320 else 321 { 322 hr = pUnknown->QueryInterface(IID_ITfCompartmentMgr, (void **)&pCompMgr); 323 } 324 325 if (SUCCEEDED(hr)) 326 { 327 hr = E_FAIL; 328 if (pCompMgr) 329 { 330 hr = pCompMgr->ClearCompartment(tid, rguid); 331 pCompMgr->Release(); 332 } 333 } 334 335 if (pThreadMgr) 336 pThreadMgr->Release(); 337 338 return hr; 339 } 340 341 typedef struct CESMAP 342 { 343 ITfCompartment *m_pComp; 344 DWORD m_dwCookie; 345 } CESMAP, *PCESMAP; 346 347 typedef INT (CALLBACK *FN_EVENTSINK)(LPVOID, REFGUID); 348 349 class CCompartmentEventSink : public ITfCompartmentEventSink 350 { 351 CicArray<CESMAP> m_array; 352 LONG m_cRefs; 353 FN_EVENTSINK m_fnEventSink; 354 LPVOID m_pUserData; 355 356 public: 357 CCompartmentEventSink(FN_EVENTSINK fnEventSink, LPVOID pUserData); 358 virtual ~CCompartmentEventSink(); 359 360 HRESULT _Advise(IUnknown *pUnknown, REFGUID rguid, BOOL bThread); 361 HRESULT _Unadvise(); 362 363 // IUnknown interface 364 STDMETHODIMP QueryInterface(REFIID riid, LPVOID* ppvObj) override; 365 STDMETHODIMP_(ULONG) AddRef() override; 366 STDMETHODIMP_(ULONG) Release() override; 367 368 // ITfCompartmentEventSink interface 369 STDMETHODIMP OnChange(REFGUID rguid) override; 370 }; 371 372 /** 373 * @implemented 374 */ 375 CCompartmentEventSink::CCompartmentEventSink(FN_EVENTSINK fnEventSink, LPVOID pUserData) 376 : m_array() 377 , m_cRefs(1) 378 , m_fnEventSink(fnEventSink) 379 , m_pUserData(pUserData) 380 { 381 } 382 383 /** 384 * @implemented 385 */ 386 CCompartmentEventSink::~CCompartmentEventSink() 387 { 388 } 389 390 /** 391 * @implemented 392 */ 393 STDMETHODIMP CCompartmentEventSink::QueryInterface(REFIID riid, LPVOID* ppvObj) 394 { 395 if (IsEqualIID(riid, IID_IUnknown) || IsEqualIID(riid, IID_ITfCompartmentEventSink)) 396 { 397 *ppvObj = this; 398 AddRef(); 399 return S_OK; 400 } 401 402 *ppvObj = NULL; 403 return E_NOINTERFACE; 404 } 405 406 /** 407 * @implemented 408 */ 409 STDMETHODIMP_(ULONG) CCompartmentEventSink::AddRef() 410 { 411 return ::InterlockedIncrement(&m_cRefs); 412 } 413 414 /** 415 * @implemented 416 */ 417 STDMETHODIMP_(ULONG) CCompartmentEventSink::Release() 418 { 419 if (::InterlockedDecrement(&m_cRefs) == 0) 420 { 421 delete this; 422 return 0; 423 } 424 return m_cRefs; 425 } 426 427 /** 428 * @implemented 429 */ 430 STDMETHODIMP CCompartmentEventSink::OnChange(REFGUID rguid) 431 { 432 return m_fnEventSink(m_pUserData, rguid); 433 } 434 435 /** 436 * @implemented 437 */ 438 HRESULT 439 CCompartmentEventSink::_Advise(IUnknown *pUnknown, REFGUID rguid, BOOL bThread) 440 { 441 CESMAP *pCesMap = m_array.Append(1); 442 if (!pCesMap) 443 return E_OUTOFMEMORY; 444 445 ITfSource *pSource = NULL; 446 447 HRESULT hr = GetCompartment(pUnknown, rguid, &pCesMap->m_pComp, bThread); 448 if (FAILED(hr)) 449 { 450 hr = pCesMap->m_pComp->QueryInterface(IID_ITfSource, (void **)&pSource); 451 if (FAILED(hr)) 452 { 453 hr = pSource->AdviseSink(IID_ITfCompartmentEventSink, this, &pCesMap->m_dwCookie); 454 if (FAILED(hr)) 455 { 456 if (pCesMap->m_pComp) 457 { 458 pCesMap->m_pComp->Release(); 459 pCesMap->m_pComp = NULL; 460 } 461 m_array.Remove(m_array.size() - 1, 1); 462 } 463 else 464 { 465 hr = S_OK; 466 } 467 } 468 } 469 470 if (pSource) 471 pSource->Release(); 472 473 return hr; 474 } 475 476 /** 477 * @implemented 478 */ 479 HRESULT CCompartmentEventSink::_Unadvise() 480 { 481 CESMAP *pCesMap = m_array.data(); 482 size_t cItems = m_array.size(); 483 if (!cItems) 484 return S_OK; 485 486 do 487 { 488 ITfSource *pSource = NULL; 489 HRESULT hr = pCesMap->m_pComp->QueryInterface(IID_ITfSource, (void **)&pSource); 490 if (SUCCEEDED(hr)) 491 pSource->UnadviseSink(pCesMap->m_dwCookie); 492 493 if (pCesMap->m_pComp) 494 { 495 pCesMap->m_pComp->Release(); 496 pCesMap->m_pComp = NULL; 497 } 498 499 if (pSource) 500 pSource->Release(); 501 502 ++pCesMap; 503 --cItems; 504 } while (cItems); 505 506 return S_OK; 507 } 508 509 /*********************************************************************** 510 * CicInputContext 511 */ 512 513 class CInputContextOwnerCallBack; 514 515 /* FIXME */ 516 class CicInputContext 517 : public ITfCleanupContextSink 518 , public ITfContextOwnerCompositionSink 519 , public ITfCompositionSink 520 { 521 public: 522 DWORD m_dw[2]; 523 LONG m_cRefs; 524 HIMC m_hIMC; 525 ITfDocumentMgr *m_pDocumentMgr; 526 ITfContext *m_pContext; 527 DWORD m_dw0_0[1]; 528 CInputContextOwnerCallBack *m_pICOwnerCallback; 529 DWORD m_dw0; 530 CCompartmentEventSink *m_pCompEventSink1; 531 CCompartmentEventSink *m_pCompEventSink2; 532 DWORD m_dw0_5[4]; 533 DWORD m_dw1[2]; 534 DWORD m_dwQueryPos; 535 DWORD m_dw1_5[1]; 536 GUID m_guid; 537 DWORD m_dw2[19]; 538 WORD m_cGuidAtoms; 539 WORD m_padding; 540 DWORD m_adwGuidAtoms[256]; 541 DWORD m_dw3[19]; 542 543 public: 544 CicInputContext(TfClientId cliendId, LIBTHREAD *pLibThread, HIMC hIMC); 545 virtual ~CicInputContext() 546 { 547 } 548 549 // IUnknown interface 550 STDMETHODIMP QueryInterface(REFIID riid, LPVOID* ppvObj) override; 551 STDMETHODIMP_(ULONG) AddRef() override; 552 STDMETHODIMP_(ULONG) Release() override; 553 554 // ITfCleanupContextSink interface 555 STDMETHODIMP OnCleanupContext(TfEditCookie ecWrite, ITfContext *pic) override; 556 557 // ITfContextOwnerCompositionSink interface 558 STDMETHODIMP OnStartComposition(ITfCompositionView *pComposition, BOOL *pfOk) override; 559 STDMETHODIMP OnUpdateComposition(ITfCompositionView *pComposition, ITfRange *pRangeNew) override; 560 STDMETHODIMP OnEndComposition(ITfCompositionView *pComposition) override; 561 562 // ITfCompositionSink interface 563 STDMETHODIMP OnCompositionTerminated(TfEditCookie ecWrite, ITfComposition *pComposition) override; 564 565 HRESULT 566 GetGuidAtom( 567 _Inout_ IMCLock& imcLock, 568 _In_ BYTE iAtom, 569 _Out_opt_ LPDWORD pdwGuidAtom); 570 571 HRESULT CreateInputContext(ITfThreadMgr *pThreadMgr, IMCLock& imcLock); 572 HRESULT DestroyInputContext(); 573 }; 574 575 /** 576 * @unimplemented 577 */ 578 CicInputContext::CicInputContext(TfClientId cliendId, LIBTHREAD *pLibThread, HIMC hIMC) 579 { 580 m_hIMC = hIMC; 581 m_guid = GUID_NULL; 582 m_dwQueryPos = 0; 583 m_cRefs = 1; 584 } 585 586 /** 587 * @unimplemented 588 */ 589 STDMETHODIMP CicInputContext::QueryInterface(REFIID riid, LPVOID* ppvObj) 590 { 591 *ppvObj = NULL; 592 593 if (IsEqualIID(riid, IID_ITfContextOwnerCompositionSink)) 594 { 595 *ppvObj = (ITfContextOwnerCompositionSink*)this; 596 AddRef(); 597 return S_OK; 598 } 599 if (IsEqualIID(riid, IID_IUnknown)) 600 { 601 *ppvObj = this; 602 AddRef(); 603 return S_OK; 604 } 605 606 return E_NOINTERFACE; 607 } 608 609 /** 610 * @implemented 611 */ 612 STDMETHODIMP_(ULONG) CicInputContext::AddRef() 613 { 614 return ::InterlockedIncrement(&m_cRefs); 615 } 616 617 /** 618 * @implemented 619 */ 620 STDMETHODIMP_(ULONG) CicInputContext::Release() 621 { 622 if (::InterlockedDecrement(&m_cRefs) == 0) 623 { 624 delete this; 625 return 0; 626 } 627 return m_cRefs; 628 } 629 630 /** 631 * @unimplemented 632 */ 633 STDMETHODIMP 634 CicInputContext::OnStartComposition( 635 ITfCompositionView *pComposition, 636 BOOL *pfOk) 637 { 638 return E_NOTIMPL; 639 } 640 641 /** 642 * @unimplemented 643 */ 644 STDMETHODIMP 645 CicInputContext::OnUpdateComposition( 646 ITfCompositionView *pComposition, 647 ITfRange *pRangeNew) 648 { 649 return E_NOTIMPL; 650 } 651 652 /** 653 * @unimplemented 654 */ 655 STDMETHODIMP 656 CicInputContext::OnEndComposition( 657 ITfCompositionView *pComposition) 658 { 659 return E_NOTIMPL; 660 } 661 662 /** 663 * @implemented 664 */ 665 HRESULT 666 CicInputContext::GetGuidAtom( 667 _Inout_ IMCLock& imcLock, 668 _In_ BYTE iAtom, 669 _Out_opt_ LPDWORD pdwGuidAtom) 670 { 671 IMCCLock<CTFIMECONTEXT> imeContext(imcLock.get().hCompStr); 672 HRESULT hr = imeContext.m_hr; 673 if (!imeContext) 674 hr = E_FAIL; 675 if (FAILED(hr)) 676 return hr; 677 678 hr = E_FAIL; 679 if (iAtom < m_cGuidAtoms) 680 { 681 *pdwGuidAtom = m_adwGuidAtoms[iAtom]; 682 hr = S_OK; 683 } 684 685 return hr; 686 } 687 688 /** 689 * @unimplemented 690 */ 691 HRESULT 692 CicInputContext::CreateInputContext(ITfThreadMgr *pThreadMgr, IMCLock& imcLock) 693 { 694 //FIXME 695 return E_NOTIMPL; 696 } 697 698 /** 699 * @unimplemented 700 */ 701 HRESULT 702 CicInputContext::DestroyInputContext() 703 { 704 // FIXME 705 return E_NOTIMPL; 706 } 707 708 /** 709 * @implemented 710 */ 711 STDMETHODIMP 712 CicInputContext::OnCompositionTerminated(TfEditCookie ecWrite, ITfComposition *pComposition) 713 { 714 return S_OK; 715 } 716 717 /** 718 * @implemented 719 */ 720 HRESULT 721 Inquire( 722 _Out_ LPIMEINFO lpIMEInfo, 723 _Out_ LPWSTR lpszWndClass, 724 _In_ DWORD dwSystemInfoFlags, 725 _In_ HKL hKL) 726 { 727 if (!lpIMEInfo) 728 return E_OUTOFMEMORY; 729 730 StringCchCopyW(lpszWndClass, 64, L"MSCTFIME UI"); 731 lpIMEInfo->dwPrivateDataSize = 0; 732 733 switch (LOWORD(hKL)) // Language ID 734 { 735 case MAKELANGID(LANG_JAPANESE, SUBLANG_DEFAULT): // Japanese 736 { 737 lpIMEInfo->fdwProperty = IME_PROP_COMPLETE_ON_UNSELECT | IME_PROP_SPECIAL_UI | 738 IME_PROP_AT_CARET | IME_PROP_NEED_ALTKEY | 739 IME_PROP_KBD_CHAR_FIRST; 740 lpIMEInfo->fdwConversionCaps = IME_CMODE_FULLSHAPE | IME_CMODE_KATAKANA | 741 IME_CMODE_NATIVE; 742 lpIMEInfo->fdwSentenceCaps = IME_SMODE_CONVERSATION | IME_SMODE_PLAURALCLAUSE; 743 lpIMEInfo->fdwSelectCaps = SELECT_CAP_SENTENCE | SELECT_CAP_CONVERSION; 744 lpIMEInfo->fdwSCSCaps = SCS_CAP_SETRECONVERTSTRING | SCS_CAP_MAKEREAD | 745 SCS_CAP_COMPSTR; 746 lpIMEInfo->fdwUICaps = UI_CAP_ROT90; 747 break; 748 } 749 case MAKELANGID(LANG_KOREAN, SUBLANG_DEFAULT): // Korean 750 { 751 lpIMEInfo->fdwProperty = IME_PROP_COMPLETE_ON_UNSELECT | IME_PROP_SPECIAL_UI | 752 IME_PROP_AT_CARET | IME_PROP_NEED_ALTKEY | 753 IME_PROP_KBD_CHAR_FIRST; 754 lpIMEInfo->fdwConversionCaps = IME_CMODE_FULLSHAPE | IME_CMODE_NATIVE; 755 lpIMEInfo->fdwSentenceCaps = 0; 756 lpIMEInfo->fdwSCSCaps = SCS_CAP_SETRECONVERTSTRING | SCS_CAP_COMPSTR; 757 lpIMEInfo->fdwSelectCaps = SELECT_CAP_CONVERSION; 758 lpIMEInfo->fdwUICaps = UI_CAP_ROT90; 759 break; 760 } 761 case MAKELANGID(LANG_CHINESE, SUBLANG_CHINESE_SIMPLIFIED): // Simplified Chinese 762 case MAKELANGID(LANG_CHINESE, SUBLANG_CHINESE_TRADITIONAL): // Traditional Chinese 763 { 764 lpIMEInfo->fdwProperty = IME_PROP_SPECIAL_UI | IME_PROP_AT_CARET | 765 IME_PROP_NEED_ALTKEY | IME_PROP_KBD_CHAR_FIRST; 766 lpIMEInfo->fdwConversionCaps = IME_CMODE_FULLSHAPE | IME_CMODE_NATIVE; 767 lpIMEInfo->fdwSentenceCaps = SELECT_CAP_CONVERSION; 768 lpIMEInfo->fdwSelectCaps = 0; 769 lpIMEInfo->fdwSCSCaps = SCS_CAP_SETRECONVERTSTRING | SCS_CAP_MAKEREAD | 770 SCS_CAP_COMPSTR; 771 lpIMEInfo->fdwUICaps = UI_CAP_ROT90; 772 break; 773 } 774 default: // Otherwise 775 { 776 lpIMEInfo->fdwProperty = IME_PROP_UNICODE | IME_PROP_AT_CARET; 777 lpIMEInfo->fdwConversionCaps = 0; 778 lpIMEInfo->fdwSentenceCaps = 0; 779 lpIMEInfo->fdwSCSCaps = 0; 780 lpIMEInfo->fdwUICaps = 0; 781 lpIMEInfo->fdwSelectCaps = 0; 782 break; 783 } 784 } 785 786 return S_OK; 787 } 788 789 DEFINE_GUID(IID_ITfSysHookSink, 0x495388DA, 0x21A5, 0x4852, 0x8B, 0xB1, 0xED, 0x2F, 0x29, 0xDA, 0x8D, 0x60); 790 791 struct ITfSysHookSink : IUnknown 792 { 793 STDMETHOD(OnPreFocusDIM)(HWND hwnd) = 0; 794 STDMETHOD(OnSysKeyboardProc)(UINT, LONG) = 0; 795 STDMETHOD(OnSysShellProc)(INT, UINT, LONG) = 0; 796 }; 797 798 class TLS; 799 800 typedef INT (CALLBACK *FN_INITDOCMGR)(UINT, ITfDocumentMgr *, ITfDocumentMgr *, LPVOID); 801 typedef INT (CALLBACK *FN_PUSHPOP)(UINT, ITfContext *, LPVOID); 802 803 class CThreadMgrEventSink : public ITfThreadMgrEventSink 804 { 805 protected: 806 ITfThreadMgr *m_pThreadMgr; 807 DWORD m_dwCookie; 808 FN_INITDOCMGR m_fnInit; 809 FN_PUSHPOP m_fnPushPop; 810 DWORD m_dw; 811 LPVOID m_pCallbackPV; 812 LONG m_cRefs; 813 814 public: 815 CThreadMgrEventSink( 816 FN_INITDOCMGR fnInit, 817 FN_PUSHPOP fnPushPop = NULL, 818 LPVOID pvCallbackPV = NULL); 819 virtual ~CThreadMgrEventSink() { } 820 821 void SetCallbackPV(LPVOID pv); 822 HRESULT _Advise(ITfThreadMgr *pThreadMgr); 823 HRESULT _Unadvise(); 824 825 // IUnknown interface 826 STDMETHODIMP QueryInterface(REFIID riid, LPVOID* ppvObj) override; 827 STDMETHODIMP_(ULONG) AddRef() override; 828 STDMETHODIMP_(ULONG) Release() override; 829 830 // ITfThreadMgrEventSink interface 831 STDMETHODIMP OnInitDocumentMgr(ITfDocumentMgr *pdim) override; 832 STDMETHODIMP OnUninitDocumentMgr(ITfDocumentMgr *pdim) override; 833 STDMETHODIMP OnSetFocus(ITfDocumentMgr *pdimFocus, ITfDocumentMgr *pdimPrevFocus) override; 834 STDMETHODIMP OnPushContext(ITfContext *pic) override; 835 STDMETHODIMP OnPopContext(ITfContext *pic) override; 836 837 static INT CALLBACK DIMCallback( 838 UINT nCode, 839 ITfDocumentMgr *pDocMgr1, 840 ITfDocumentMgr *pDocMgr2, 841 LPVOID pUserData); 842 }; 843 844 /** 845 * @implemented 846 */ 847 CThreadMgrEventSink::CThreadMgrEventSink( 848 FN_INITDOCMGR fnInit, 849 FN_PUSHPOP fnPushPop, 850 LPVOID pvCallbackPV) 851 { 852 m_fnInit = fnInit; 853 m_fnPushPop = fnPushPop; 854 m_pCallbackPV = pvCallbackPV; 855 m_cRefs = 1; 856 } 857 858 /** 859 * @implemented 860 */ 861 STDMETHODIMP CThreadMgrEventSink::QueryInterface(REFIID riid, LPVOID* ppvObj) 862 { 863 if (IsEqualIID(riid, IID_IUnknown) || IsEqualIID(riid, IID_ITfThreadMgrEventSink)) 864 { 865 *ppvObj = this; 866 AddRef(); 867 return S_OK; 868 } 869 *ppvObj = NULL; 870 return E_NOINTERFACE; 871 } 872 873 /** 874 * @implemented 875 */ 876 STDMETHODIMP_(ULONG) CThreadMgrEventSink::AddRef() 877 { 878 return ::InterlockedIncrement(&m_cRefs); 879 } 880 881 /** 882 * @implemented 883 */ 884 STDMETHODIMP_(ULONG) CThreadMgrEventSink::Release() 885 { 886 if (::InterlockedDecrement(&m_cRefs) == 0) 887 { 888 delete this; 889 return 0; 890 } 891 return m_cRefs; 892 } 893 894 INT CALLBACK 895 CThreadMgrEventSink::DIMCallback( 896 UINT nCode, 897 ITfDocumentMgr *pDocMgr1, 898 ITfDocumentMgr *pDocMgr2, 899 LPVOID pUserData) 900 { 901 return E_NOTIMPL; 902 } 903 904 STDMETHODIMP CThreadMgrEventSink::OnInitDocumentMgr(ITfDocumentMgr *pdim) 905 { 906 if (!m_fnInit) 907 return S_OK; 908 return m_fnInit(0, pdim, NULL, m_pCallbackPV); 909 } 910 911 STDMETHODIMP CThreadMgrEventSink::OnUninitDocumentMgr(ITfDocumentMgr *pdim) 912 { 913 if (!m_fnInit) 914 return S_OK; 915 return m_fnInit(1, pdim, NULL, m_pCallbackPV); 916 } 917 918 STDMETHODIMP 919 CThreadMgrEventSink::OnSetFocus(ITfDocumentMgr *pdimFocus, ITfDocumentMgr *pdimPrevFocus) 920 { 921 if (!m_fnInit) 922 return S_OK; 923 return m_fnInit(2, pdimFocus, pdimPrevFocus, m_pCallbackPV); 924 } 925 926 STDMETHODIMP CThreadMgrEventSink::OnPushContext(ITfContext *pic) 927 { 928 if (!m_fnPushPop) 929 return S_OK; 930 return m_fnPushPop(3, pic, m_pCallbackPV); 931 } 932 933 STDMETHODIMP CThreadMgrEventSink::OnPopContext(ITfContext *pic) 934 { 935 if (!m_fnPushPop) 936 return S_OK; 937 return m_fnPushPop(4, pic, m_pCallbackPV); 938 } 939 940 void CThreadMgrEventSink::SetCallbackPV(LPVOID pv) 941 { 942 if (!m_pCallbackPV) 943 m_pCallbackPV = pv; 944 } 945 946 HRESULT CThreadMgrEventSink::_Advise(ITfThreadMgr *pThreadMgr) 947 { 948 m_pThreadMgr = NULL; 949 950 HRESULT hr = E_FAIL; 951 ITfSource *pSource = NULL; 952 if (pThreadMgr->QueryInterface(IID_ITfSource, (void **)&pSource) == S_OK && 953 pSource->AdviseSink(IID_ITfThreadMgrEventSink, this, &m_dwCookie) == S_OK) 954 { 955 m_pThreadMgr = pThreadMgr; 956 pThreadMgr->AddRef(); 957 hr = S_OK; 958 } 959 960 if (pSource) 961 pSource->Release(); 962 963 return hr; 964 } 965 966 HRESULT CThreadMgrEventSink::_Unadvise() 967 { 968 HRESULT hr = E_FAIL; 969 ITfSource *pSource = NULL; 970 971 if (m_pThreadMgr) 972 { 973 if (m_pThreadMgr->QueryInterface(IID_ITfSource, (void **)&pSource) == S_OK && 974 pSource->UnadviseSink(m_dwCookie) == S_OK) 975 { 976 hr = S_OK; 977 } 978 979 if (pSource) 980 pSource->Release(); 981 } 982 983 if (m_pThreadMgr) 984 { 985 m_pThreadMgr->Release(); 986 m_pThreadMgr = NULL; 987 } 988 989 return hr; 990 } 991 992 /* FIXME */ 993 class CFunctionProvider : public IUnknown 994 { 995 public: 996 CFunctionProvider(TfClientId clientId) 997 { 998 } 999 1000 // IUnknown interface 1001 STDMETHODIMP QueryInterface(REFIID riid, LPVOID* ppvObj) override; 1002 STDMETHODIMP_(ULONG) AddRef() override; 1003 STDMETHODIMP_(ULONG) Release() override; 1004 }; 1005 1006 /** 1007 * @unimplemented 1008 */ 1009 STDMETHODIMP CFunctionProvider::QueryInterface(REFIID riid, LPVOID* ppvObj) 1010 { 1011 return E_NOTIMPL; 1012 } 1013 1014 /** 1015 * @unimplemented 1016 */ 1017 STDMETHODIMP_(ULONG) CFunctionProvider::AddRef() 1018 { 1019 return 1; 1020 } 1021 1022 /** 1023 * @unimplemented 1024 */ 1025 STDMETHODIMP_(ULONG) CFunctionProvider::Release() 1026 { 1027 return 0; 1028 } 1029 1030 /* FIXME */ 1031 class CicBridge : public ITfSysHookSink 1032 { 1033 protected: 1034 LONG m_cRefs; 1035 DWORD m_dwImmxInit; 1036 DWORD m_dw[2]; 1037 DWORD m_cActivateLocks; 1038 ITfKeystrokeMgr *m_pKeystrokeMgr; 1039 ITfDocumentMgr *m_pDocMgr; 1040 CThreadMgrEventSink *m_pThreadMgrEventSink; 1041 TfClientId m_cliendId; 1042 LIBTHREAD m_LibThread; 1043 DWORD m_dw21; 1044 1045 static BOOL CALLBACK EnumCreateInputContextCallback(HIMC hIMC, LPARAM lParam); 1046 static BOOL CALLBACK EnumDestroyInputContextCallback(HIMC hIMC, LPARAM lParam); 1047 1048 public: 1049 CicBridge(); 1050 virtual ~CicBridge(); 1051 1052 // IUnknown interface 1053 STDMETHODIMP QueryInterface(REFIID riid, LPVOID* ppvObj) override; 1054 STDMETHODIMP_(ULONG) AddRef() override; 1055 STDMETHODIMP_(ULONG) Release() override; 1056 1057 // ITfSysHookSink interface 1058 STDMETHODIMP OnPreFocusDIM(HWND hwnd) override; 1059 STDMETHODIMP OnSysKeyboardProc(UINT, LONG) override; 1060 STDMETHODIMP OnSysShellProc(INT, UINT, LONG) override; 1061 1062 HRESULT InitIMMX(TLS *pTLS); 1063 BOOL UnInitIMMX(TLS *pTLS); 1064 HRESULT ActivateIMMX(TLS *pTLS, ITfThreadMgr *pThreadMgr); 1065 HRESULT DeactivateIMMX(TLS *pTLS, ITfThreadMgr *pThreadMgr); 1066 1067 HRESULT CreateInputContext(TLS *pTLS, HIMC hIMC); 1068 HRESULT DestroyInputContext(TLS *pTLS, HIMC hIMC); 1069 1070 void PostTransMsg(HWND hWnd, INT cTransMsgs, LPTRANSMSG pTransMsgs); 1071 void GetDocumentManager(IMCCLock<CTFIMECONTEXT>& imeContext); 1072 1073 HRESULT ConfigureGeneral(TLS* pTLS, ITfThreadMgr *pThreadMgr, HKL hKL, HWND hWnd); 1074 HRESULT ConfigureRegisterWord(TLS* pTLS, ITfThreadMgr *pThreadMgr, HKL hKL, HWND hWnd, LPVOID lpData); 1075 }; 1076 1077 class CActiveLanguageProfileNotifySink : public ITfActiveLanguageProfileNotifySink 1078 { 1079 protected: 1080 typedef INT (CALLBACK *FN_COMPARE)(REFGUID rguid1, REFGUID rguid2, BOOL fActivated, LPVOID pUserData); 1081 LONG m_cRefs; 1082 ITfThreadMgr *m_pThreadMgr; 1083 DWORD m_dwConnection; 1084 FN_COMPARE m_fnCompare; 1085 LPVOID m_pUserData; 1086 1087 public: 1088 CActiveLanguageProfileNotifySink(FN_COMPARE fnCompare, void *pUserData); 1089 virtual ~CActiveLanguageProfileNotifySink(); 1090 1091 HRESULT _Advise(ITfThreadMgr *pThreadMgr); 1092 HRESULT _Unadvise(); 1093 1094 // IUnknown interface 1095 STDMETHODIMP QueryInterface(REFIID riid, LPVOID* ppvObj) override; 1096 STDMETHODIMP_(ULONG) AddRef() override; 1097 STDMETHODIMP_(ULONG) Release() override; 1098 1099 // ITfActiveLanguageProfileNotifySink interface 1100 STDMETHODIMP 1101 OnActivated( 1102 REFCLSID clsid, 1103 REFGUID guidProfile, 1104 BOOL fActivated) override; 1105 }; 1106 1107 /** 1108 * @implemented 1109 */ 1110 CActiveLanguageProfileNotifySink::CActiveLanguageProfileNotifySink( 1111 FN_COMPARE fnCompare, 1112 void *pUserData) 1113 { 1114 m_dwConnection = (DWORD)-1; 1115 m_fnCompare = fnCompare; 1116 m_cRefs = 1; 1117 m_pUserData = pUserData; 1118 } 1119 1120 /** 1121 * @implemented 1122 */ 1123 CActiveLanguageProfileNotifySink::~CActiveLanguageProfileNotifySink() 1124 { 1125 } 1126 1127 /** 1128 * @implemented 1129 */ 1130 STDMETHODIMP CActiveLanguageProfileNotifySink::QueryInterface(REFIID riid, LPVOID* ppvObj) 1131 { 1132 if (IsEqualIID(riid, IID_IUnknown) || IsEqualIID(riid, IID_ITfActiveLanguageProfileNotifySink)) 1133 { 1134 *ppvObj = this; 1135 AddRef(); 1136 return S_OK; 1137 } 1138 *ppvObj = NULL; 1139 return E_NOINTERFACE; 1140 } 1141 1142 /** 1143 * @implemented 1144 */ 1145 STDMETHODIMP_(ULONG) CActiveLanguageProfileNotifySink::AddRef() 1146 { 1147 return ::InterlockedIncrement(&m_cRefs); 1148 } 1149 1150 /** 1151 * @implemented 1152 */ 1153 STDMETHODIMP_(ULONG) CActiveLanguageProfileNotifySink::Release() 1154 { 1155 if (::InterlockedDecrement(&m_cRefs) == 0) 1156 { 1157 delete this; 1158 return 0; 1159 } 1160 return m_cRefs; 1161 } 1162 1163 /** 1164 * @implemented 1165 */ 1166 STDMETHODIMP 1167 CActiveLanguageProfileNotifySink::OnActivated( 1168 REFCLSID clsid, 1169 REFGUID guidProfile, 1170 BOOL fActivated) 1171 { 1172 if (!m_fnCompare) 1173 return 0; 1174 1175 return m_fnCompare(clsid, guidProfile, fActivated, m_pUserData); 1176 } 1177 1178 /** 1179 * @implemented 1180 */ 1181 HRESULT 1182 CActiveLanguageProfileNotifySink::_Advise( 1183 ITfThreadMgr *pThreadMgr) 1184 { 1185 m_pThreadMgr = NULL; 1186 1187 ITfSource *pSource = NULL; 1188 HRESULT hr = pThreadMgr->QueryInterface(IID_ITfSource, (void **)&pSource); 1189 if (FAILED(hr)) 1190 return E_FAIL; 1191 1192 hr = pSource->AdviseSink(IID_ITfActiveLanguageProfileNotifySink, this, &m_dwConnection); 1193 if (SUCCEEDED(hr)) 1194 { 1195 m_pThreadMgr = pThreadMgr; 1196 pThreadMgr->AddRef(); 1197 hr = S_OK; 1198 } 1199 else 1200 { 1201 hr = E_FAIL; 1202 } 1203 1204 if (pSource) 1205 pSource->Release(); 1206 1207 return hr; 1208 } 1209 1210 /** 1211 * @implemented 1212 */ 1213 HRESULT 1214 CActiveLanguageProfileNotifySink::_Unadvise() 1215 { 1216 if (!m_pThreadMgr) 1217 return E_FAIL; 1218 1219 ITfSource *pSource = NULL; 1220 HRESULT hr = m_pThreadMgr->QueryInterface(IID_ITfSource, (void **)&pSource); 1221 if (SUCCEEDED(hr)) 1222 { 1223 hr = pSource->UnadviseSink(m_dwConnection); 1224 if (SUCCEEDED(hr)) 1225 hr = S_OK; 1226 } 1227 1228 if (pSource) 1229 pSource->Release(); 1230 1231 if (m_pThreadMgr) 1232 { 1233 m_pThreadMgr->Release(); 1234 m_pThreadMgr = NULL; 1235 } 1236 1237 return hr; 1238 } 1239 1240 /* FIXME */ 1241 class CicProfile : public IUnknown 1242 { 1243 protected: 1244 ITfInputProcessorProfiles *m_pIPProfiles; 1245 CActiveLanguageProfileNotifySink *m_pActiveLanguageProfileNotifySink; 1246 LANGID m_LangID1; 1247 WORD m_padding1; 1248 DWORD m_dwFlags; 1249 UINT m_nCodePage; 1250 LANGID m_LangID2; 1251 WORD m_padding2; 1252 DWORD m_dw3[1]; 1253 LONG m_cRefs; 1254 1255 static INT CALLBACK 1256 ActiveLanguageProfileNotifySinkCallback( 1257 REFGUID rguid1, 1258 REFGUID rguid2, 1259 BOOL fActivated, 1260 LPVOID pUserData); 1261 1262 public: 1263 CicProfile(); 1264 virtual ~CicProfile(); 1265 1266 // IUnknown interface 1267 STDMETHODIMP QueryInterface(REFIID riid, LPVOID* ppvObj) override; 1268 STDMETHODIMP_(ULONG) AddRef() override; 1269 STDMETHODIMP_(ULONG) Release() override; 1270 1271 HRESULT GetActiveLanguageProfile(HKL hKL, REFGUID rguid, TF_LANGUAGEPROFILE *pProfile); 1272 HRESULT GetLangId(LANGID *pLangID); 1273 HRESULT GetCodePageA(UINT *puCodePage); 1274 1275 HRESULT InitProfileInstance(TLS *pTLS); 1276 }; 1277 1278 /** 1279 * @implemented 1280 */ 1281 CicProfile::CicProfile() 1282 { 1283 m_dwFlags &= 0xFFFFFFF0; 1284 m_cRefs = 1; 1285 m_pIPProfiles = NULL; 1286 m_pActiveLanguageProfileNotifySink = NULL; 1287 m_LangID1 = 0; 1288 m_nCodePage = CP_ACP; 1289 m_LangID2 = 0; 1290 m_dw3[0] = 0; 1291 } 1292 1293 /** 1294 * @implemented 1295 */ 1296 CicProfile::~CicProfile() 1297 { 1298 if (m_pIPProfiles) 1299 { 1300 if (m_LangID1) 1301 m_pIPProfiles->ChangeCurrentLanguage(m_LangID1); 1302 1303 m_pIPProfiles->Release(); 1304 m_pIPProfiles = NULL; 1305 } 1306 1307 if (m_pActiveLanguageProfileNotifySink) 1308 { 1309 m_pActiveLanguageProfileNotifySink->_Unadvise(); 1310 m_pActiveLanguageProfileNotifySink->Release(); 1311 m_pActiveLanguageProfileNotifySink = NULL; 1312 } 1313 } 1314 1315 /** 1316 * @implemented 1317 */ 1318 STDMETHODIMP CicProfile::QueryInterface(REFIID riid, LPVOID* ppvObj) 1319 { 1320 *ppvObj = NULL; 1321 return E_NOINTERFACE; 1322 } 1323 1324 /** 1325 * @implemented 1326 */ 1327 STDMETHODIMP_(ULONG) CicProfile::AddRef() 1328 { 1329 return ::InterlockedIncrement(&m_cRefs); 1330 } 1331 1332 /** 1333 * @implemented 1334 */ 1335 STDMETHODIMP_(ULONG) CicProfile::Release() 1336 { 1337 if (::InterlockedDecrement(&m_cRefs) == 0) 1338 { 1339 delete this; 1340 return 0; 1341 } 1342 return m_cRefs; 1343 } 1344 1345 /** 1346 * @implemented 1347 */ 1348 INT CALLBACK 1349 CicProfile::ActiveLanguageProfileNotifySinkCallback( 1350 REFGUID rguid1, 1351 REFGUID rguid2, 1352 BOOL fActivated, 1353 LPVOID pUserData) 1354 { 1355 CicProfile *pThis = (CicProfile *)pUserData; 1356 pThis->m_dwFlags &= ~0xE; 1357 return 0; 1358 } 1359 1360 /** 1361 * @implemented 1362 */ 1363 HRESULT CicProfile::GetCodePageA(UINT *puCodePage) 1364 { 1365 if (!puCodePage) 1366 return E_INVALIDARG; 1367 1368 if (m_dwFlags & 2) 1369 { 1370 *puCodePage = m_nCodePage; 1371 return S_OK; 1372 } 1373 1374 *puCodePage = 0; 1375 1376 LANGID LangID; 1377 HRESULT hr = GetLangId(&LangID); 1378 if (FAILED(hr)) 1379 return E_FAIL; 1380 1381 WCHAR szBuff[12]; 1382 INT cch = ::GetLocaleInfoW(LangID, LOCALE_IDEFAULTANSICODEPAGE, szBuff, _countof(szBuff)); 1383 if (cch) 1384 { 1385 szBuff[cch] = 0; 1386 m_nCodePage = *puCodePage = wcstoul(szBuff, NULL, 10); 1387 m_dwFlags |= 2; 1388 } 1389 1390 return S_OK; 1391 } 1392 1393 /** 1394 * @implemented 1395 */ 1396 HRESULT CicProfile::GetLangId(LANGID *pLangID) 1397 { 1398 *pLangID = 0; 1399 1400 if (!m_pIPProfiles) 1401 return E_FAIL; 1402 1403 if (m_dwFlags & 4) 1404 { 1405 *pLangID = m_LangID2; 1406 return S_OK; 1407 } 1408 1409 HRESULT hr = m_pIPProfiles->GetCurrentLanguage(pLangID); 1410 if (SUCCEEDED(hr)) 1411 { 1412 m_dwFlags |= 4; 1413 m_LangID2 = *pLangID; 1414 } 1415 1416 return hr; 1417 } 1418 1419 class TLS 1420 { 1421 public: 1422 static DWORD s_dwTlsIndex; 1423 1424 DWORD m_dwSystemInfoFlags; 1425 CicBridge *m_pBridge; 1426 CicProfile *m_pProfile; 1427 ITfThreadMgr *m_pThreadMgr; 1428 DWORD m_dwFlags1; 1429 DWORD m_dwFlags2; 1430 DWORD m_dwUnknown2[2]; 1431 DWORD m_dwNowOpening; 1432 DWORD m_NonEAComposition; 1433 DWORD m_cWnds; 1434 1435 /** 1436 * @implemented 1437 */ 1438 static BOOL Initialize() 1439 { 1440 s_dwTlsIndex = ::TlsAlloc(); 1441 return s_dwTlsIndex != (DWORD)-1; 1442 } 1443 1444 /** 1445 * @implemented 1446 */ 1447 static VOID Uninitialize() 1448 { 1449 if (s_dwTlsIndex != (DWORD)-1) 1450 { 1451 ::TlsFree(s_dwTlsIndex); 1452 s_dwTlsIndex = (DWORD)-1; 1453 } 1454 } 1455 1456 /** 1457 * @implemented 1458 */ 1459 static TLS* GetTLS() 1460 { 1461 if (s_dwTlsIndex == (DWORD)-1) 1462 return NULL; 1463 1464 return InternalAllocateTLS(); 1465 } 1466 1467 /** 1468 * @implemented 1469 */ 1470 static TLS* PeekTLS() 1471 { 1472 return (TLS*)::TlsGetValue(TLS::s_dwTlsIndex); 1473 } 1474 1475 static TLS* InternalAllocateTLS(); 1476 static BOOL InternalDestroyTLS(); 1477 1478 }; 1479 1480 DWORD TLS::s_dwTlsIndex = (DWORD)-1; 1481 1482 /** 1483 * @implemented 1484 */ 1485 TLS* TLS::InternalAllocateTLS() 1486 { 1487 TLS *pTLS = TLS::PeekTLS(); 1488 if (pTLS) 1489 return pTLS; 1490 1491 if (DllShutDownInProgress()) 1492 return NULL; 1493 1494 pTLS = (TLS *)cicMemAllocClear(sizeof(TLS)); 1495 if (!pTLS) 1496 return NULL; 1497 1498 if (!::TlsSetValue(s_dwTlsIndex, pTLS)) 1499 { 1500 cicMemFree(pTLS); 1501 return NULL; 1502 } 1503 1504 pTLS->m_dwUnknown2[0] |= 1; 1505 pTLS->m_dwUnknown2[2] |= 1; 1506 return pTLS; 1507 } 1508 1509 /** 1510 * @implemented 1511 */ 1512 BOOL TLS::InternalDestroyTLS() 1513 { 1514 TLS *pTLS = TLS::PeekTLS(); 1515 if (!pTLS) 1516 return FALSE; 1517 1518 if (pTLS->m_pBridge) 1519 pTLS->m_pBridge->Release(); 1520 if (pTLS->m_pProfile) 1521 pTLS->m_pProfile->Release(); 1522 if (pTLS->m_pThreadMgr) 1523 pTLS->m_pThreadMgr->Release(); 1524 1525 cicMemFree(pTLS); 1526 ::TlsSetValue(s_dwTlsIndex, NULL); 1527 return TRUE; 1528 } 1529 1530 /** 1531 * @implemented 1532 */ 1533 HRESULT 1534 CicProfile::InitProfileInstance(TLS *pTLS) 1535 { 1536 HRESULT hr = TF_CreateInputProcessorProfiles(&m_pIPProfiles); 1537 if (FAILED(hr)) 1538 return hr; 1539 1540 if (!m_pActiveLanguageProfileNotifySink) 1541 { 1542 CActiveLanguageProfileNotifySink *pSink = 1543 new CActiveLanguageProfileNotifySink( 1544 CicProfile::ActiveLanguageProfileNotifySinkCallback, this); 1545 if (!pSink) 1546 { 1547 m_pIPProfiles->Release(); 1548 m_pIPProfiles = NULL; 1549 return E_FAIL; 1550 } 1551 m_pActiveLanguageProfileNotifySink = pSink; 1552 } 1553 1554 if (pTLS->m_pThreadMgr) 1555 m_pActiveLanguageProfileNotifySink->_Advise(pTLS->m_pThreadMgr); 1556 1557 return hr; 1558 } 1559 1560 /** 1561 * @implemented 1562 */ 1563 STDMETHODIMP CicInputContext::OnCleanupContext(TfEditCookie ecWrite, ITfContext *pic) 1564 { 1565 TLS *pTLS = TLS::PeekTLS(); 1566 if (!pTLS || !pTLS->m_pProfile) 1567 return E_OUTOFMEMORY; 1568 1569 LANGID LangID; 1570 pTLS->m_pProfile->GetLangId(&LangID); 1571 1572 IMEINFO IMEInfo; 1573 WCHAR szPath[MAX_PATH]; 1574 if (Inquire(&IMEInfo, szPath, 0, (HKL)UlongToHandle(LangID)) != S_OK) 1575 return E_FAIL; 1576 1577 ITfProperty *pProp = NULL; 1578 if (!(IMEInfo.fdwProperty & IME_PROP_COMPLETE_ON_UNSELECT)) 1579 return S_OK; 1580 1581 HRESULT hr = pic->GetProperty(GUID_PROP_COMPOSING, &pProp); 1582 if (FAILED(hr)) 1583 return S_OK; 1584 1585 IEnumTfRanges *pRanges = NULL; 1586 hr = pProp->EnumRanges(ecWrite, &pRanges, NULL); 1587 if (SUCCEEDED(hr)) 1588 { 1589 ITfRange *pRange = NULL; 1590 while (pRanges->Next(1, &pRange, 0) == S_OK) 1591 { 1592 VARIANT vari; 1593 V_VT(&vari) = VT_EMPTY; 1594 pProp->GetValue(ecWrite, pRange, &vari); 1595 if (V_VT(&vari) == VT_I4) 1596 { 1597 if (V_I4(&vari)) 1598 pProp->Clear(ecWrite, pRange); 1599 } 1600 pRange->Release(); 1601 pRange = NULL; 1602 } 1603 pRanges->Release(); 1604 } 1605 pProp->Release(); 1606 1607 return S_OK; 1608 } 1609 1610 /*********************************************************************** 1611 * CicBridge 1612 */ 1613 1614 CicBridge::CicBridge() 1615 { 1616 m_dwImmxInit &= ~1; 1617 m_dw[0] &= ~1; 1618 m_dw[1] &= ~1; 1619 m_dw21 &= ~1; 1620 m_pKeystrokeMgr = NULL; 1621 m_pDocMgr = NULL; 1622 m_pThreadMgrEventSink = NULL; 1623 m_cliendId = 0; 1624 m_cRefs = 1; 1625 } 1626 1627 /** 1628 * @implemented 1629 */ 1630 STDMETHODIMP CicBridge::QueryInterface(REFIID riid, LPVOID* ppvObj) 1631 { 1632 *ppvObj = NULL; 1633 1634 if (!IsEqualIID(riid, IID_ITfSysHookSink)) 1635 return E_NOINTERFACE; 1636 1637 *ppvObj = this; 1638 AddRef(); 1639 1640 return S_OK; 1641 } 1642 1643 /** 1644 * @implemented 1645 */ 1646 STDMETHODIMP_(ULONG) CicBridge::AddRef() 1647 { 1648 return ::InterlockedIncrement(&m_cRefs); 1649 } 1650 1651 /** 1652 * @implemented 1653 */ 1654 STDMETHODIMP_(ULONG) CicBridge::Release() 1655 { 1656 if (::InterlockedDecrement(&m_cRefs) == 0) 1657 { 1658 delete this; 1659 return 0; 1660 } 1661 return m_cRefs; 1662 } 1663 1664 /** 1665 * @implemented 1666 */ 1667 CicBridge::~CicBridge() 1668 { 1669 TLS *pTLS = TLS::PeekTLS(); 1670 if (!pTLS || !pTLS->m_pThreadMgr) 1671 return; 1672 1673 if (SUCCEEDED(DeactivateIMMX(pTLS, pTLS->m_pThreadMgr))) 1674 UnInitIMMX(pTLS); 1675 } 1676 1677 void CicBridge::GetDocumentManager(IMCCLock<CTFIMECONTEXT>& imeContext) 1678 { 1679 CicInputContext *pCicIC = imeContext.get().m_pCicIC; 1680 if (pCicIC) 1681 { 1682 m_pDocMgr = pCicIC->m_pDocumentMgr; 1683 m_pDocMgr->AddRef(); 1684 } 1685 else 1686 { 1687 m_pDocMgr->Release(); 1688 m_pDocMgr = NULL; 1689 } 1690 } 1691 1692 /** 1693 * @unimplemented 1694 */ 1695 HRESULT CicBridge::CreateInputContext(TLS *pTLS, HIMC hIMC) 1696 { 1697 IMCLock imcLock(hIMC); 1698 HRESULT hr = imcLock.m_hr; 1699 if (!imcLock) 1700 hr = E_FAIL; 1701 if (FAILED(hr)) 1702 return hr; 1703 1704 if (!imcLock.get().hCtfImeContext) 1705 { 1706 HIMCC hCtfImeContext = ImmCreateIMCC(sizeof(CTFIMECONTEXT)); 1707 if (!hCtfImeContext) 1708 return E_OUTOFMEMORY; 1709 imcLock.get().hCtfImeContext = hCtfImeContext; 1710 } 1711 1712 IMCCLock<CTFIMECONTEXT> imeContext(imcLock.get().hCtfImeContext); 1713 CicInputContext *pCicIC = imeContext.get().m_pCicIC; 1714 if (!pCicIC) 1715 { 1716 pCicIC = new CicInputContext(m_cliendId, &m_LibThread, hIMC); 1717 if (!pCicIC) 1718 { 1719 imeContext.unlock(); 1720 imcLock.unlock(); 1721 DestroyInputContext(pTLS, hIMC); 1722 return E_OUTOFMEMORY; 1723 } 1724 1725 if (!pTLS->m_pThreadMgr) 1726 { 1727 pCicIC->Release(); 1728 imeContext.unlock(); 1729 imcLock.unlock(); 1730 DestroyInputContext(pTLS, hIMC); 1731 return E_NOINTERFACE; 1732 } 1733 1734 imeContext.get().m_pCicIC = pCicIC; 1735 } 1736 1737 hr = pCicIC->CreateInputContext(pTLS->m_pThreadMgr, imcLock); 1738 if (FAILED(hr)) 1739 { 1740 pCicIC->Release(); 1741 imeContext.get().m_pCicIC = NULL; 1742 } 1743 else 1744 { 1745 if (imcLock.get().hWnd && imcLock.get().hWnd == ::GetFocus()) 1746 { 1747 GetDocumentManager(imeContext); 1748 //FIXME 1749 } 1750 } 1751 1752 return E_NOTIMPL; 1753 } 1754 1755 /** 1756 * @implemented 1757 */ 1758 HRESULT CicBridge::DestroyInputContext(TLS *pTLS, HIMC hIMC) 1759 { 1760 IMCLock imcLock(hIMC); 1761 HRESULT hr = imcLock.m_hr; 1762 if (!imcLock) 1763 hr = E_FAIL; 1764 if (FAILED(hr)) 1765 return hr; 1766 1767 hr = E_FAIL; 1768 IMCCLock<CTFIMECONTEXT> imeContext(imcLock.get().hCtfImeContext); 1769 if (imeContext) 1770 hr = imeContext.m_hr; 1771 1772 if (SUCCEEDED(hr) && !(imeContext.get().m_dwCicFlags & 1)) 1773 { 1774 imeContext.get().m_dwCicFlags |= 1; 1775 1776 CicInputContext *pCicIC = imeContext.get().m_pCicIC; 1777 if (pCicIC) 1778 { 1779 imeContext.get().m_pCicIC = NULL; 1780 hr = pCicIC->DestroyInputContext(); 1781 pCicIC->Release(); 1782 imeContext.get().m_pCicIC = NULL; 1783 } 1784 } 1785 1786 if (imcLock.get().hCtfImeContext) 1787 { 1788 ImmDestroyIMCC(imcLock.get().hCtfImeContext); 1789 imcLock.get().hCtfImeContext = NULL; 1790 hr = S_OK; 1791 } 1792 1793 return hr; 1794 } 1795 1796 typedef struct ENUM_CREATE_DESTROY_IC 1797 { 1798 TLS *m_pTLS; 1799 CicBridge *m_pBridge; 1800 } ENUM_CREATE_DESTROY_IC, *PENUM_CREATE_DESTROY_IC; 1801 1802 BOOL CALLBACK CicBridge::EnumCreateInputContextCallback(HIMC hIMC, LPARAM lParam) 1803 { 1804 PENUM_CREATE_DESTROY_IC pData = (PENUM_CREATE_DESTROY_IC)lParam; 1805 pData->m_pBridge->CreateInputContext(pData->m_pTLS, hIMC); 1806 return TRUE; 1807 } 1808 1809 BOOL CALLBACK CicBridge::EnumDestroyInputContextCallback(HIMC hIMC, LPARAM lParam) 1810 { 1811 PENUM_CREATE_DESTROY_IC pData = (PENUM_CREATE_DESTROY_IC)lParam; 1812 pData->m_pBridge->DestroyInputContext(pData->m_pTLS, hIMC); 1813 return TRUE; 1814 } 1815 1816 /** 1817 * @unimplemented 1818 */ 1819 HRESULT CicBridge::ActivateIMMX(TLS *pTLS, ITfThreadMgr *pThreadMgr) 1820 { 1821 //FIXME 1822 1823 if (m_cActivateLocks++ != 0) 1824 return S_OK; 1825 1826 ITfSourceSingle *pSource = NULL; 1827 HRESULT hr = pThreadMgr->QueryInterface(IID_ITfSourceSingle, (void**)&pSource); 1828 if (FAILED(hr)) 1829 { 1830 DeactivateIMMX(pTLS, pThreadMgr); 1831 return hr; 1832 } 1833 1834 CFunctionProvider *pProvider = new CFunctionProvider(m_cliendId); 1835 if (!pProvider) 1836 { 1837 hr = E_FAIL; 1838 goto Finish; 1839 } 1840 1841 pSource->AdviseSingleSink(m_cliendId, IID_ITfFunctionProvider, pProvider); 1842 pProvider->Release(); 1843 1844 if (!m_pDocMgr) 1845 { 1846 hr = pThreadMgr->CreateDocumentMgr(&m_pDocMgr); 1847 if (FAILED(hr)) 1848 { 1849 hr = E_FAIL; 1850 goto Finish; 1851 } 1852 1853 SetCompartmentDWORD(m_cliendId, m_pDocMgr, GUID_COMPARTMENT_CTFIME_DIMFLAGS, TRUE, FALSE); 1854 } 1855 1856 //FIXME 1857 1858 hr = S_OK; 1859 if (pTLS->m_dwUnknown2[1] & 1) 1860 { 1861 ENUM_CREATE_DESTROY_IC Data = { pTLS, this }; 1862 ImmEnumInputContext(0, CicBridge::EnumCreateInputContextCallback, (LPARAM)&Data); 1863 } 1864 1865 Finish: 1866 if (FAILED(hr)) 1867 DeactivateIMMX(pTLS, pThreadMgr); 1868 1869 if (pSource) 1870 pSource->Release(); 1871 1872 return hr; 1873 } 1874 1875 /** 1876 * @unimplemented 1877 */ 1878 HRESULT CicBridge::DeactivateIMMX(TLS *pTLS, ITfThreadMgr *pThreadMgr) 1879 { 1880 if (m_dw[1] & 1) 1881 return TRUE; 1882 1883 m_dw[1] |= 1; 1884 1885 if (m_cliendId) 1886 { 1887 ENUM_CREATE_DESTROY_IC Data = { pTLS, this }; 1888 ImmEnumInputContext(0, CicBridge::EnumDestroyInputContextCallback, (LPARAM)&Data); 1889 pTLS->m_dwUnknown2[1] |= 1u; 1890 1891 ITfSourceSingle *pSource = NULL; 1892 if (pThreadMgr->QueryInterface(IID_ITfSourceSingle, (void **)&pSource) == S_OK) 1893 pSource->UnadviseSingleSink(m_cliendId, IID_ITfFunctionProvider); 1894 1895 m_cliendId = 0; 1896 1897 while (m_cActivateLocks > 0) 1898 { 1899 --m_cActivateLocks; 1900 pThreadMgr->Deactivate(); 1901 } 1902 1903 if (pSource) 1904 pSource->Release(); 1905 } 1906 1907 if (m_pDocMgr) 1908 { 1909 m_pDocMgr->Release(); 1910 m_pDocMgr = NULL; 1911 } 1912 1913 //FIXME 1914 1915 m_dw[1] &= ~1; 1916 1917 return S_OK; 1918 } 1919 1920 /** 1921 * @implemented 1922 */ 1923 HRESULT CicBridge::InitIMMX(TLS *pTLS) 1924 { 1925 if (m_dwImmxInit & 1) 1926 return S_OK; 1927 1928 HRESULT hr; 1929 if (!pTLS->m_pThreadMgr) 1930 { 1931 hr = TF_CreateThreadMgr(&pTLS->m_pThreadMgr); 1932 if (FAILED(hr)) 1933 return E_FAIL; 1934 1935 hr = pTLS->m_pThreadMgr->QueryInterface(IID_ITfThreadMgr, (void **)&pTLS->m_pThreadMgr); 1936 if (FAILED(hr)) 1937 { 1938 pTLS->m_pThreadMgr->Release(); 1939 pTLS->m_pThreadMgr = NULL; 1940 return E_FAIL; 1941 } 1942 } 1943 1944 if (!m_pThreadMgrEventSink) 1945 { 1946 m_pThreadMgrEventSink = 1947 new CThreadMgrEventSink(CThreadMgrEventSink::DIMCallback, NULL, NULL); 1948 if (!m_pThreadMgrEventSink) 1949 { 1950 UnInitIMMX(pTLS); 1951 return E_FAIL; 1952 } 1953 } 1954 1955 m_pThreadMgrEventSink->SetCallbackPV(m_pThreadMgrEventSink); 1956 m_pThreadMgrEventSink->_Advise(pTLS->m_pThreadMgr); 1957 1958 if (!pTLS->m_pProfile) 1959 { 1960 pTLS->m_pProfile = new CicProfile(); 1961 if (!pTLS->m_pProfile) 1962 return E_OUTOFMEMORY; 1963 hr = pTLS->m_pProfile->InitProfileInstance(pTLS); 1964 if (FAILED(hr)) 1965 { 1966 UnInitIMMX(pTLS); 1967 return E_FAIL; 1968 } 1969 } 1970 1971 hr = pTLS->m_pThreadMgr->QueryInterface(IID_ITfKeystrokeMgr, (void **)&m_pKeystrokeMgr); 1972 if (FAILED(hr)) 1973 { 1974 UnInitIMMX(pTLS); 1975 return E_FAIL; 1976 } 1977 1978 hr = InitDisplayAttrbuteLib(&m_LibThread); 1979 if (FAILED(hr)) 1980 { 1981 UnInitIMMX(pTLS); 1982 return E_FAIL; 1983 } 1984 1985 m_dwImmxInit |= 1; 1986 return S_OK; 1987 } 1988 1989 /** 1990 * @implemented 1991 */ 1992 BOOL CicBridge::UnInitIMMX(TLS *pTLS) 1993 { 1994 UninitDisplayAttrbuteLib(&m_LibThread); 1995 TFUninitLib_Thread(&m_LibThread); 1996 1997 if (m_pKeystrokeMgr) 1998 { 1999 m_pKeystrokeMgr->Release(); 2000 m_pKeystrokeMgr = NULL; 2001 } 2002 2003 if (pTLS->m_pProfile) 2004 { 2005 pTLS->m_pProfile->Release(); 2006 pTLS->m_pProfile = NULL; 2007 } 2008 2009 if (m_pThreadMgrEventSink) 2010 { 2011 m_pThreadMgrEventSink->_Unadvise(); 2012 m_pThreadMgrEventSink->Release(); 2013 m_pThreadMgrEventSink = NULL; 2014 } 2015 2016 if (pTLS->m_pThreadMgr) 2017 { 2018 pTLS->m_pThreadMgr->Release(); 2019 pTLS->m_pThreadMgr = NULL; 2020 } 2021 2022 m_dwImmxInit &= ~1; 2023 return TRUE; 2024 } 2025 2026 /** 2027 * @implemented 2028 */ 2029 STDMETHODIMP CicBridge::OnPreFocusDIM(HWND hwnd) 2030 { 2031 return S_OK; 2032 } 2033 2034 /** 2035 * @unimplemented 2036 */ 2037 STDMETHODIMP CicBridge::OnSysKeyboardProc(UINT, LONG) 2038 { 2039 return E_NOTIMPL; 2040 } 2041 2042 /** 2043 * @implemented 2044 */ 2045 STDMETHODIMP CicBridge::OnSysShellProc(INT, UINT, LONG) 2046 { 2047 return S_OK; 2048 } 2049 2050 /** 2051 * @implemented 2052 */ 2053 void CicBridge::PostTransMsg(HWND hWnd, INT cTransMsgs, LPTRANSMSG pTransMsgs) 2054 { 2055 for (INT i = 0; i < cTransMsgs; ++i, ++pTransMsgs) 2056 { 2057 ::PostMessageW(hWnd, pTransMsgs->message, pTransMsgs->wParam, pTransMsgs->lParam); 2058 } 2059 } 2060 2061 /** 2062 * @implemented 2063 */ 2064 HRESULT 2065 CicBridge::ConfigureGeneral( 2066 TLS* pTLS, 2067 ITfThreadMgr *pThreadMgr, 2068 HKL hKL, 2069 HWND hWnd) 2070 { 2071 CicProfile *pProfile = pTLS->m_pProfile; 2072 if (!pProfile) 2073 return E_OUTOFMEMORY; 2074 2075 TF_LANGUAGEPROFILE profile; 2076 HRESULT hr = pProfile->GetActiveLanguageProfile(hKL, GUID_TFCAT_TIP_KEYBOARD, &profile); 2077 if (FAILED(hr)) 2078 return hr; 2079 2080 ITfFunctionProvider *pProvider = NULL; 2081 hr = pThreadMgr->GetFunctionProvider(profile.clsid, &pProvider); 2082 if (FAILED(hr)) 2083 return hr; 2084 2085 ITfFnConfigure *pFnConfigure = NULL; 2086 hr = pProvider->GetFunction(GUID_NULL, IID_ITfFnConfigure, (IUnknown**)&pFnConfigure); 2087 if (FAILED(hr)) 2088 { 2089 pProvider->Release(); 2090 return hr; 2091 } 2092 2093 hr = pFnConfigure->Show(hWnd, profile.langid, profile.guidProfile); 2094 2095 pFnConfigure->Release(); 2096 pProvider->Release(); 2097 return hr; 2098 } 2099 2100 /** 2101 * @implemented 2102 */ 2103 HRESULT 2104 CicBridge::ConfigureRegisterWord( 2105 TLS* pTLS, 2106 ITfThreadMgr *pThreadMgr, 2107 HKL hKL, 2108 HWND hWnd, 2109 LPVOID lpData) 2110 { 2111 CicProfile *pProfile = pTLS->m_pProfile; 2112 if (!pProfile) 2113 return E_OUTOFMEMORY; 2114 2115 TF_LANGUAGEPROFILE profile; 2116 HRESULT hr = pProfile->GetActiveLanguageProfile(hKL, GUID_TFCAT_TIP_KEYBOARD, &profile); 2117 if (FAILED(hr)) 2118 return hr; 2119 2120 ITfFunctionProvider *pProvider = NULL; 2121 hr = pThreadMgr->GetFunctionProvider(profile.clsid, &pProvider); 2122 if (FAILED(hr)) 2123 return hr; 2124 2125 ITfFnConfigureRegisterWord *pFunction = NULL; 2126 hr = pProvider->GetFunction(GUID_NULL, IID_ITfFnConfigureRegisterWord, (IUnknown**)&pFunction); 2127 if (FAILED(hr)) 2128 { 2129 pProvider->Release(); 2130 return hr; 2131 } 2132 2133 REGISTERWORDW* pRegWord = (REGISTERWORDW*)lpData; 2134 if (pRegWord) 2135 { 2136 if (pRegWord->lpWord) 2137 { 2138 hr = E_OUTOFMEMORY; 2139 BSTR bstrWord = SysAllocString(pRegWord->lpWord); 2140 if (bstrWord) 2141 { 2142 hr = pFunction->Show(hWnd, profile.langid, profile.guidProfile, bstrWord); 2143 SysFreeString(bstrWord); 2144 } 2145 } 2146 else 2147 { 2148 hr = pFunction->Show(hWnd, profile.langid, profile.guidProfile, NULL); 2149 } 2150 } 2151 2152 pProvider->Release(); 2153 pFunction->Release(); 2154 return hr; 2155 } 2156 2157 /*********************************************************************** 2158 * CicProfile 2159 */ 2160 2161 /** 2162 * @unimplemented 2163 */ 2164 HRESULT 2165 CicProfile::GetActiveLanguageProfile( 2166 HKL hKL, 2167 REFGUID rguid, 2168 TF_LANGUAGEPROFILE *pProfile) 2169 { 2170 return E_NOTIMPL; 2171 } 2172 2173 /*********************************************************************** 2174 * ImeInquire (MSCTFIME.@) 2175 * 2176 * MSCTFIME's ImeInquire does nothing. 2177 * 2178 * @implemented 2179 * @see CtfImeInquireExW 2180 */ 2181 EXTERN_C 2182 BOOL WINAPI 2183 ImeInquire( 2184 _Out_ LPIMEINFO lpIMEInfo, 2185 _Out_ LPWSTR lpszWndClass, 2186 _In_ DWORD dwSystemInfoFlags) 2187 { 2188 TRACE("(%p, %p, 0x%lX)\n", lpIMEInfo, lpszWndClass, dwSystemInfoFlags); 2189 return FALSE; 2190 } 2191 2192 /*********************************************************************** 2193 * ImeConversionList (MSCTFIME.@) 2194 * 2195 * MSCTFIME's ImeConversionList does nothing. 2196 * 2197 * @implemented 2198 * @see ImmGetConversionListW 2199 */ 2200 EXTERN_C DWORD WINAPI 2201 ImeConversionList( 2202 _In_ HIMC hIMC, 2203 _In_ LPCWSTR lpSrc, 2204 _Out_ LPCANDIDATELIST lpDst, 2205 _In_ DWORD dwBufLen, 2206 _In_ UINT uFlag) 2207 { 2208 TRACE("(%p, %s, %p, 0x%lX, %u)\n", hIMC, debugstr_w(lpSrc), lpDst, dwBufLen, uFlag); 2209 return 0; 2210 } 2211 2212 /*********************************************************************** 2213 * ImeRegisterWord (MSCTFIME.@) 2214 * 2215 * MSCTFIME's ImeRegisterWord does nothing. 2216 * 2217 * @implemented 2218 * @see ImeUnregisterWord 2219 */ 2220 EXTERN_C BOOL WINAPI 2221 ImeRegisterWord( 2222 _In_ LPCWSTR lpszReading, 2223 _In_ DWORD dwStyle, 2224 _In_ LPCWSTR lpszString) 2225 { 2226 TRACE("(%s, 0x%lX, %s)\n", debugstr_w(lpszReading), dwStyle, debugstr_w(lpszString)); 2227 return FALSE; 2228 } 2229 2230 /*********************************************************************** 2231 * ImeUnregisterWord (MSCTFIME.@) 2232 * 2233 * MSCTFIME's ImeUnregisterWord does nothing. 2234 * 2235 * @implemented 2236 * @see ImeRegisterWord 2237 */ 2238 EXTERN_C BOOL WINAPI 2239 ImeUnregisterWord( 2240 _In_ LPCWSTR lpszReading, 2241 _In_ DWORD dwStyle, 2242 _In_ LPCWSTR lpszString) 2243 { 2244 TRACE("(%s, 0x%lX, %s)\n", debugstr_w(lpszReading), dwStyle, debugstr_w(lpszString)); 2245 return FALSE; 2246 } 2247 2248 /*********************************************************************** 2249 * ImeGetRegisterWordStyle (MSCTFIME.@) 2250 * 2251 * MSCTFIME's ImeGetRegisterWordStyle does nothing. 2252 * 2253 * @implemented 2254 * @see ImeRegisterWord 2255 */ 2256 EXTERN_C UINT WINAPI 2257 ImeGetRegisterWordStyle( 2258 _In_ UINT nItem, 2259 _Out_ LPSTYLEBUFW lpStyleBuf) 2260 { 2261 TRACE("(%u, %p)\n", nItem, lpStyleBuf); 2262 return 0; 2263 } 2264 2265 /*********************************************************************** 2266 * ImeEnumRegisterWord (MSCTFIME.@) 2267 * 2268 * MSCTFIME's ImeEnumRegisterWord does nothing. 2269 * 2270 * @implemented 2271 * @see ImeRegisterWord 2272 */ 2273 EXTERN_C UINT WINAPI 2274 ImeEnumRegisterWord( 2275 _In_ REGISTERWORDENUMPROCW lpfnEnumProc, 2276 _In_opt_ LPCWSTR lpszReading, 2277 _In_ DWORD dwStyle, 2278 _In_opt_ LPCWSTR lpszString, 2279 _In_opt_ LPVOID lpData) 2280 { 2281 TRACE("(%p, %s, %lu, %s, %p)\n", lpfnEnumProc, debugstr_w(lpszReading), 2282 dwStyle, debugstr_w(lpszString), lpData); 2283 return 0; 2284 } 2285 2286 EXTERN_C BOOL WINAPI 2287 ImeConfigure( 2288 _In_ HKL hKL, 2289 _In_ HWND hWnd, 2290 _In_ DWORD dwMode, 2291 _Inout_opt_ LPVOID lpData) 2292 { 2293 TRACE("(%p, %p, %lu, %p)\n", hKL, hWnd, dwMode, lpData); 2294 2295 TLS *pTLS = TLS::GetTLS(); 2296 if (!pTLS || !pTLS->m_pBridge || !pTLS->m_pThreadMgr) 2297 return FALSE; 2298 2299 CicBridge *pBridge = pTLS->m_pBridge; 2300 ITfThreadMgr *pThreadMgr = pTLS->m_pThreadMgr; 2301 2302 if (dwMode & 1) 2303 return (pBridge->ConfigureGeneral(pTLS, pThreadMgr, hKL, hWnd) == S_OK); 2304 2305 if (dwMode & 2) 2306 return (pBridge->ConfigureRegisterWord(pTLS, pThreadMgr, hKL, hWnd, lpData) == S_OK); 2307 2308 return FALSE; 2309 } 2310 2311 /*********************************************************************** 2312 * ImeDestroy (MSCTFIME.@) 2313 * 2314 * @implemented 2315 */ 2316 EXTERN_C BOOL WINAPI 2317 ImeDestroy( 2318 _In_ UINT uReserved) 2319 { 2320 TRACE("(%u)\n", uReserved); 2321 2322 TLS *pTLS = TLS::PeekTLS(); 2323 if (pTLS) 2324 return FALSE; 2325 2326 if (!pTLS->m_pBridge || !pTLS->m_pThreadMgr) 2327 return FALSE; 2328 2329 if (pTLS->m_dwSystemInfoFlags & IME_SYSINFO_WINLOGON) 2330 return TRUE; 2331 2332 if (pTLS->m_pBridge->DeactivateIMMX(pTLS, pTLS->m_pThreadMgr) != S_OK) 2333 return FALSE; 2334 2335 return pTLS->m_pBridge->UnInitIMMX(pTLS); 2336 } 2337 2338 /*********************************************************************** 2339 * ImeEscape (MSCTFIME.@) 2340 * 2341 * MSCTFIME's ImeEscape does nothing. 2342 * 2343 * @implemented 2344 * @see CtfImeEscapeEx 2345 */ 2346 EXTERN_C LRESULT WINAPI 2347 ImeEscape( 2348 _In_ HIMC hIMC, 2349 _In_ UINT uEscape, 2350 _Inout_opt_ LPVOID lpData) 2351 { 2352 TRACE("(%p, %u, %p)\n", hIMC, uEscape, lpData); 2353 return 0; 2354 } 2355 2356 EXTERN_C BOOL WINAPI 2357 ImeProcessKey( 2358 _In_ HIMC hIMC, 2359 _In_ UINT uVirKey, 2360 _In_ LPARAM lParam, 2361 _In_ CONST LPBYTE lpbKeyState) 2362 { 2363 FIXME("stub:(%p, %u, %p, lpbKeyState)\n", hIMC, uVirKey, lParam, lpbKeyState); 2364 return FALSE; 2365 } 2366 2367 /*********************************************************************** 2368 * ImeSelect (MSCTFIME.@) 2369 * 2370 * MSCTFIME's ImeSelect does nothing. 2371 * 2372 * @implemented 2373 * @see CtfImeSelectEx 2374 */ 2375 EXTERN_C BOOL WINAPI 2376 ImeSelect( 2377 _In_ HIMC hIMC, 2378 _In_ BOOL fSelect) 2379 { 2380 TRACE("(%p, %u)\n", hIMC, fSelect); 2381 return FALSE; 2382 } 2383 2384 /*********************************************************************** 2385 * ImeSetActiveContext (MSCTFIME.@) 2386 * 2387 * MSCTFIME's ImeSetActiveContext does nothing. 2388 * 2389 * @implemented 2390 * @see CtfImeSetActiveContextAlways 2391 */ 2392 EXTERN_C BOOL WINAPI 2393 ImeSetActiveContext( 2394 _In_ HIMC hIMC, 2395 _In_ BOOL fFlag) 2396 { 2397 TRACE("(%p, %u)\n", hIMC, fFlag); 2398 return FALSE; 2399 } 2400 2401 EXTERN_C UINT WINAPI 2402 ImeToAsciiEx( 2403 _In_ UINT uVirKey, 2404 _In_ UINT uScanCode, 2405 _In_ CONST LPBYTE lpbKeyState, 2406 _Out_ LPTRANSMSGLIST lpTransMsgList, 2407 _In_ UINT fuState, 2408 _In_ HIMC hIMC) 2409 { 2410 FIXME("stub:(%u, %u, %p, %p, %u, %p)\n", uVirKey, uScanCode, lpbKeyState, lpTransMsgList, 2411 fuState, hIMC); 2412 return 0; 2413 } 2414 2415 EXTERN_C BOOL WINAPI 2416 NotifyIME( 2417 _In_ HIMC hIMC, 2418 _In_ DWORD dwAction, 2419 _In_ DWORD dwIndex, 2420 _In_ DWORD_PTR dwValue) 2421 { 2422 FIXME("stub:(%p, 0x%lX, 0x%lX, %p)\n", hIMC, dwAction, dwIndex, dwValue); 2423 return FALSE; 2424 } 2425 2426 EXTERN_C BOOL WINAPI 2427 ImeSetCompositionString( 2428 _In_ HIMC hIMC, 2429 _In_ DWORD dwIndex, 2430 _In_opt_ LPCVOID lpComp, 2431 _In_ DWORD dwCompLen, 2432 _In_opt_ LPCVOID lpRead, 2433 _In_ DWORD dwReadLen) 2434 { 2435 FIXME("stub:(%p, 0x%lX, %p, 0x%lX, %p, 0x%lX)\n", hIMC, dwIndex, lpComp, dwCompLen, 2436 lpRead, dwReadLen); 2437 return FALSE; 2438 } 2439 2440 EXTERN_C DWORD WINAPI 2441 ImeGetImeMenuItems( 2442 _In_ HIMC hIMC, 2443 _In_ DWORD dwFlags, 2444 _In_ DWORD dwType, 2445 _Inout_opt_ LPIMEMENUITEMINFOW lpImeParentMenu, 2446 _Inout_opt_ LPIMEMENUITEMINFOW lpImeMenu, 2447 _In_ DWORD dwSize) 2448 { 2449 FIXME("stub:(%p, 0x%lX, 0x%lX, %p, %p, 0x%lX)\n", hIMC, dwFlags, dwType, lpImeParentMenu, 2450 lpImeMenu, dwSize); 2451 return 0; 2452 } 2453 2454 /*********************************************************************** 2455 * CtfImeInquireExW (MSCTFIME.@) 2456 * 2457 * @implemented 2458 */ 2459 EXTERN_C HRESULT WINAPI 2460 CtfImeInquireExW( 2461 _Out_ LPIMEINFO lpIMEInfo, 2462 _Out_ LPWSTR lpszWndClass, 2463 _In_ DWORD dwSystemInfoFlags, 2464 _In_ HKL hKL) 2465 { 2466 TRACE("(%p, %p, 0x%lX, %p)\n", lpIMEInfo, lpszWndClass, dwSystemInfoFlags, hKL); 2467 2468 TLS *pTLS = TLS::GetTLS(); 2469 if (!pTLS) 2470 return E_OUTOFMEMORY; 2471 2472 if (!IsInteractiveUserLogon()) 2473 { 2474 dwSystemInfoFlags |= IME_SYSINFO_WINLOGON; 2475 g_bWinLogon = TRUE; 2476 } 2477 2478 pTLS->m_dwSystemInfoFlags = dwSystemInfoFlags; 2479 2480 return Inquire(lpIMEInfo, lpszWndClass, dwSystemInfoFlags, hKL); 2481 } 2482 2483 EXTERN_C BOOL WINAPI 2484 CtfImeSelectEx( 2485 _In_ HIMC hIMC, 2486 _In_ BOOL fSelect, 2487 _In_ HKL hKL) 2488 { 2489 FIXME("stub:(%p, %d, %p)\n", hIMC, fSelect, hKL); 2490 return FALSE; 2491 } 2492 2493 EXTERN_C LRESULT WINAPI 2494 CtfImeEscapeEx( 2495 _In_ HIMC hIMC, 2496 _In_ UINT uSubFunc, 2497 _Inout_opt_ LPVOID lpData, 2498 _In_ HKL hKL) 2499 { 2500 FIXME("stub:(%p, %u, %p, %p)\n", hIMC, uSubFunc, lpData, hKL); 2501 return 0; 2502 } 2503 2504 /*********************************************************************** 2505 * CtfImeGetGuidAtom (MSCTFIME.@) 2506 * 2507 * @implemented 2508 */ 2509 EXTERN_C HRESULT WINAPI 2510 CtfImeGetGuidAtom( 2511 _In_ HIMC hIMC, 2512 _In_ DWORD dwUnknown, 2513 _Out_opt_ LPDWORD pdwGuidAtom) 2514 { 2515 TRACE("(%p, 0x%lX, %p)\n", hIMC, dwUnknown, pdwGuidAtom); 2516 2517 IMCLock imcLock(hIMC); 2518 2519 HRESULT hr = imcLock.m_hr; 2520 if (!imcLock) 2521 hr = E_FAIL; 2522 if (FAILED(hr)) 2523 return hr; 2524 2525 IMCCLock<CTFIMECONTEXT> imccLock(imcLock.get().hCtfImeContext); 2526 hr = imccLock.m_hr; 2527 if (!imccLock) 2528 hr = E_FAIL; 2529 if (FAILED(hr)) 2530 return hr; 2531 2532 if (!imccLock.get().m_pCicIC) 2533 return E_OUTOFMEMORY; 2534 2535 hr = imccLock.get().m_pCicIC->GetGuidAtom(imcLock, dwUnknown, pdwGuidAtom); 2536 return hr; 2537 } 2538 2539 /*********************************************************************** 2540 * CtfImeIsGuidMapEnable (MSCTFIME.@) 2541 * 2542 * @implemented 2543 */ 2544 EXTERN_C BOOL WINAPI 2545 CtfImeIsGuidMapEnable( 2546 _In_ HIMC hIMC) 2547 { 2548 TRACE("(%p)\n", hIMC); 2549 2550 BOOL ret = FALSE; 2551 HRESULT hr; 2552 IMCLock imcLock(hIMC); 2553 2554 hr = imcLock.m_hr; 2555 if (!imcLock) 2556 hr = E_FAIL; 2557 if (SUCCEEDED(hr)) 2558 ret = !!(imcLock.get().fdwInit & INIT_GUIDMAP); 2559 2560 return ret; 2561 } 2562 2563 /*********************************************************************** 2564 * CtfImeCreateThreadMgr (MSCTFIME.@) 2565 * 2566 * @implemented 2567 */ 2568 EXTERN_C HRESULT WINAPI 2569 CtfImeCreateThreadMgr(VOID) 2570 { 2571 TRACE("()\n"); 2572 2573 TLS *pTLS = TLS::GetTLS(); 2574 if (!pTLS) 2575 return E_OUTOFMEMORY; 2576 2577 if (!pTLS->m_pBridge) 2578 { 2579 pTLS->m_pBridge = new CicBridge(); 2580 if (!pTLS->m_pBridge) 2581 return E_OUTOFMEMORY; 2582 } 2583 2584 HRESULT hr = S_OK; 2585 if (!g_bWinLogon && !(pTLS->m_dwSystemInfoFlags & IME_SYSINFO_WINLOGON)) 2586 { 2587 hr = pTLS->m_pBridge->InitIMMX(pTLS); 2588 if (SUCCEEDED(hr)) 2589 { 2590 if (!pTLS->m_pThreadMgr) 2591 return E_OUTOFMEMORY; 2592 2593 hr = pTLS->m_pBridge->ActivateIMMX(pTLS, pTLS->m_pThreadMgr); 2594 if (FAILED(hr)) 2595 pTLS->m_pBridge->UnInitIMMX(pTLS); 2596 } 2597 } 2598 2599 return hr; 2600 } 2601 2602 2603 /*********************************************************************** 2604 * CtfImeDestroyThreadMgr (MSCTFIME.@) 2605 * 2606 * @implemented 2607 */ 2608 EXTERN_C HRESULT WINAPI 2609 CtfImeDestroyThreadMgr(VOID) 2610 { 2611 TRACE("()\n"); 2612 2613 TLS *pTLS = TLS::PeekTLS(); 2614 if (!pTLS) 2615 return E_OUTOFMEMORY; 2616 2617 if (pTLS->m_pBridge) 2618 { 2619 pTLS->m_pBridge = new CicBridge(); 2620 if (!pTLS->m_pBridge) 2621 return E_OUTOFMEMORY; 2622 } 2623 2624 if (!pTLS->m_pThreadMgr) 2625 return E_OUTOFMEMORY; 2626 2627 if (pTLS->m_dwSystemInfoFlags & IME_SYSINFO_WINLOGON) 2628 return S_OK; 2629 2630 HRESULT hr = pTLS->m_pBridge->DeactivateIMMX(pTLS, pTLS->m_pThreadMgr); 2631 if (hr == S_OK) 2632 pTLS->m_pBridge->UnInitIMMX(pTLS); 2633 2634 return hr; 2635 } 2636 2637 EXTERN_C HRESULT WINAPI 2638 CtfImeCreateInputContext( 2639 _In_ HIMC hIMC) 2640 { 2641 return E_NOTIMPL; 2642 } 2643 2644 /*********************************************************************** 2645 * CtfImeDestroyInputContext (MSCTFIME.@) 2646 * 2647 * @implemented 2648 */ 2649 EXTERN_C HRESULT WINAPI 2650 CtfImeDestroyInputContext( 2651 _In_ HIMC hIMC) 2652 { 2653 TRACE("(%p)\n", hIMC); 2654 2655 TLS *pTLS = TLS::PeekTLS(); 2656 if (!pTLS || !pTLS->m_pBridge) 2657 return E_OUTOFMEMORY; 2658 2659 return pTLS->m_pBridge->DestroyInputContext(pTLS, hIMC); 2660 } 2661 2662 EXTERN_C HRESULT WINAPI 2663 CtfImeSetActiveContextAlways( 2664 _In_ HIMC hIMC, 2665 _In_ BOOL fActive, 2666 _In_ HWND hWnd, 2667 _In_ HKL hKL) 2668 { 2669 FIXME("stub:(%p, %d, %p, %p)\n", hIMC, fActive, hWnd, hKL); 2670 return E_NOTIMPL; 2671 } 2672 2673 EXTERN_C HRESULT WINAPI 2674 CtfImeProcessCicHotkey( 2675 _In_ HIMC hIMC, 2676 _In_ UINT vKey, 2677 _In_ LPARAM lParam) 2678 { 2679 FIXME("stub:(%p, %u, %p)\n", hIMC, vKey, lParam); 2680 return E_NOTIMPL; 2681 } 2682 2683 /*********************************************************************** 2684 * CtfImeDispatchDefImeMessage (MSCTFIME.@) 2685 * 2686 * @implemented 2687 */ 2688 EXTERN_C LRESULT WINAPI 2689 CtfImeDispatchDefImeMessage( 2690 _In_ HWND hWnd, 2691 _In_ UINT uMsg, 2692 _In_ WPARAM wParam, 2693 _In_ LPARAM lParam) 2694 { 2695 TRACE("(%p, %u, %p, %p)\n", hWnd, uMsg, wParam, lParam); 2696 2697 TLS *pTLS = TLS::GetTLS(); 2698 if (pTLS) 2699 { 2700 if (uMsg == WM_CREATE) 2701 ++pTLS->m_cWnds; 2702 else if (uMsg == WM_DESTROY) 2703 --pTLS->m_cWnds; 2704 } 2705 2706 if (!IsMsImeMessage(uMsg)) 2707 return 0; 2708 2709 HKL hKL = GetKeyboardLayout(0); 2710 if (IS_IME_HKL(hKL)) 2711 return 0; 2712 2713 HWND hImeWnd = (HWND)SendMessageW(hWnd, WM_IME_NOTIFY, 0x17, 0); 2714 if (!IsWindow(hImeWnd)) 2715 return 0; 2716 2717 return SendMessageW(hImeWnd, uMsg, wParam, lParam); 2718 } 2719 2720 EXTERN_C BOOL WINAPI 2721 CtfImeIsIME( 2722 _In_ HKL hKL) 2723 { 2724 FIXME("stub:(%p)\n", hKL); 2725 return FALSE; 2726 } 2727 2728 /** 2729 * @implemented 2730 */ 2731 EXTERN_C HRESULT WINAPI 2732 CtfImeThreadDetach(VOID) 2733 { 2734 ImeDestroy(0); 2735 return S_OK; 2736 } 2737 2738 /** 2739 * @unimplemented 2740 */ 2741 EXTERN_C LRESULT CALLBACK 2742 UIWndProc( 2743 _In_ HWND hWnd, 2744 _In_ UINT uMsg, 2745 _In_ WPARAM wParam, 2746 _In_ LPARAM lParam) 2747 { 2748 if (uMsg == WM_CREATE) 2749 { 2750 FIXME("stub\n"); 2751 return -1; 2752 } 2753 return 0; 2754 } 2755 2756 /** 2757 * @unimplemented 2758 */ 2759 BOOL RegisterImeClass(VOID) 2760 { 2761 WNDCLASSEXW wcx; 2762 2763 if (!GetClassInfoExW(g_hInst, L"MSCTFIME UI", &wcx)) 2764 { 2765 ZeroMemory(&wcx, sizeof(wcx)); 2766 wcx.cbSize = sizeof(WNDCLASSEXW); 2767 wcx.cbWndExtra = sizeof(DWORD) * 2; 2768 wcx.hIcon = LoadIconW(0, (LPCWSTR)IDC_ARROW); 2769 wcx.hInstance = g_hInst; 2770 wcx.hCursor = LoadCursorW(NULL, (LPCWSTR)IDC_ARROW); 2771 wcx.hbrBackground = (HBRUSH)GetStockObject(NULL_BRUSH); 2772 wcx.style = CS_IME | CS_GLOBALCLASS; 2773 wcx.lpfnWndProc = UIWndProc; 2774 wcx.lpszClassName = L"MSCTFIME UI"; 2775 if (!RegisterClassExW(&wcx)) 2776 return FALSE; 2777 } 2778 2779 if (!GetClassInfoExW(g_hInst, L"MSCTFIME Composition", &wcx)) 2780 { 2781 ZeroMemory(&wcx, sizeof(wcx)); 2782 wcx.cbSize = sizeof(WNDCLASSEXW); 2783 wcx.cbWndExtra = sizeof(DWORD); 2784 wcx.hIcon = NULL; 2785 wcx.hInstance = g_hInst; 2786 wcx.hCursor = LoadCursorW(NULL, (LPCWSTR)IDC_IBEAM); 2787 wcx.hbrBackground = (HBRUSH)GetStockObject(NULL_BRUSH); 2788 wcx.style = CS_IME | CS_HREDRAW | CS_VREDRAW; 2789 //wcx.lpfnWndProc = UIComposition::CompWndProc; // FIXME 2790 wcx.lpszClassName = L"MSCTFIME Composition"; 2791 if (!RegisterClassExW(&wcx)) 2792 return FALSE; 2793 } 2794 2795 return TRUE; 2796 } 2797 2798 /** 2799 * @implemented 2800 */ 2801 VOID UnregisterImeClass(VOID) 2802 { 2803 WNDCLASSEXW wcx; 2804 2805 GetClassInfoExW(g_hInst, L"MSCTFIME UI", &wcx); 2806 UnregisterClassW(L"MSCTFIME UI", g_hInst); 2807 DestroyIcon(wcx.hIcon); 2808 DestroyIcon(wcx.hIconSm); 2809 2810 GetClassInfoExW(g_hInst, L"MSCTFIME Composition", &wcx); 2811 UnregisterClassW(L"MSCTFIME Composition", g_hInst); 2812 DestroyIcon(wcx.hIcon); 2813 DestroyIcon(wcx.hIconSm); 2814 } 2815 2816 /** 2817 * @implemented 2818 */ 2819 BOOL AttachIME(VOID) 2820 { 2821 return RegisterImeClass() && RegisterMSIMEMessage(); 2822 } 2823 2824 /** 2825 * @implemented 2826 */ 2827 VOID DetachIME(VOID) 2828 { 2829 UnregisterImeClass(); 2830 } 2831 2832 /** 2833 * @unimplemented 2834 */ 2835 BOOL ProcessAttach(HINSTANCE hinstDLL) 2836 { 2837 g_hInst = hinstDLL; 2838 2839 InitializeCriticalSectionAndSpinCount(&g_csLock, 0); 2840 2841 if (!TLS::Initialize()) 2842 return FALSE; 2843 2844 g_dwOSInfo = cicGetOSInfo(); 2845 2846 // FIXME 2847 2848 gfTFInitLib = TRUE; 2849 return AttachIME(); 2850 } 2851 2852 /** 2853 * @unimplemented 2854 */ 2855 VOID ProcessDetach(HINSTANCE hinstDLL) 2856 { 2857 // FIXME 2858 2859 if (gfTFInitLib) 2860 DetachIME(); 2861 2862 DeleteCriticalSection(&g_csLock); 2863 TLS::InternalDestroyTLS(); 2864 TLS::Uninitialize(); 2865 2866 // FIXME 2867 } 2868 2869 /** 2870 * @implemented 2871 */ 2872 EXTERN_C BOOL WINAPI 2873 DllMain( 2874 _In_ HINSTANCE hinstDLL, 2875 _In_ DWORD dwReason, 2876 _Inout_opt_ LPVOID lpvReserved) 2877 { 2878 switch (dwReason) 2879 { 2880 case DLL_PROCESS_ATTACH: 2881 { 2882 TRACE("(%p, %lu, %p)\n", hinstDLL, dwReason, lpvReserved); 2883 if (!ProcessAttach(hinstDLL)) 2884 { 2885 ProcessDetach(hinstDLL); 2886 return FALSE; 2887 } 2888 break; 2889 } 2890 case DLL_PROCESS_DETACH: 2891 { 2892 ProcessDetach(hinstDLL); 2893 break; 2894 } 2895 case DLL_THREAD_DETACH: 2896 { 2897 TF_DllDetachInOther(); 2898 CtfImeThreadDetach(); 2899 TLS::InternalDestroyTLS(); 2900 break; 2901 } 2902 } 2903 return TRUE; 2904 } 2905