Reactos
at master 1398 lines 37 kB view raw
1/* 2 * PROJECT: ReactOS CTF 3 * LICENSE: LGPL-2.0-or-later (https://spdx.org/licenses/LGPL-2.0-or-later) 4 * PURPOSE: ITfThreadMgr implementation 5 * COPYRIGHT: Copyright 2008 Aric Stewart, CodeWeavers 6 * Copyright 2025 Katayama Hirofumi MZ <katayama.hirofumi.mz@gmail.com> 7 */ 8 9#include "precomp.h" 10 11#include <wine/debug.h> 12WINE_DEFAULT_DEBUG_CHANNEL(msctf); 13 14//////////////////////////////////////////////////////////////////////////// 15 16typedef struct tagPreservedKey 17{ 18 struct list entry; 19 GUID guid; 20 TF_PRESERVEDKEY prekey; 21 LPWSTR description; 22 TfClientId tid; 23} PreservedKey; 24 25typedef struct tagDocumentMgrs 26{ 27 struct list entry; 28 ITfDocumentMgr *docmgr; 29} DocumentMgrEntry; 30 31typedef struct tagAssociatedWindow 32{ 33 struct list entry; 34 HWND hwnd; 35 ITfDocumentMgr *docmgr; 36} AssociatedWindow; 37 38//////////////////////////////////////////////////////////////////////////// 39 40class CThreadMgr 41 : public ITfThreadMgrEx 42 , public ITfSource 43 , public ITfKeystrokeMgr 44 , public ITfMessagePump 45 , public ITfClientId 46 // , public ITfConfigureSystemKeystrokeFeed 47 // , public ITfLangBarItemMgr 48 , public ITfUIElementMgr 49 , public ITfSourceSingle 50 , public ITfThreadMgrEventSink 51{ 52public: 53 CThreadMgr(); 54 virtual ~CThreadMgr(); 55 56 static HRESULT CreateInstance(IUnknown *pUnkOuter, CThreadMgr **ppOut); 57 void OnDocumentMgrDestruction(ITfDocumentMgr *mgr); 58 59 // ** IUnknown methods ** 60 STDMETHODIMP QueryInterface(REFIID iid, LPVOID *ppvObject) override; 61 STDMETHODIMP_(ULONG) AddRef() override; 62 STDMETHODIMP_(ULONG) Release() override; 63 64 // ** ITfThreadMgr methods ** 65 STDMETHODIMP Activate(_Out_ TfClientId *ptid) override; 66 STDMETHODIMP Deactivate() override; 67 STDMETHODIMP CreateDocumentMgr(_Out_ ITfDocumentMgr **ppdim) override; 68 STDMETHODIMP EnumDocumentMgrs(_Out_ IEnumTfDocumentMgrs **ppEnum) override; 69 STDMETHODIMP GetFocus(_Out_ ITfDocumentMgr **ppdimFocus) override; 70 STDMETHODIMP SetFocus(_In_ ITfDocumentMgr *pdimFocus) override; 71 STDMETHODIMP AssociateFocus( 72 _In_ HWND hwnd, 73 _In_ ITfDocumentMgr *pdimNew, 74 _Out_ ITfDocumentMgr **ppdimPrev) override; 75 STDMETHODIMP IsThreadFocus(_Out_ BOOL *pfThreadFocus) override; 76 STDMETHODIMP GetFunctionProvider( 77 _In_ REFCLSID clsid, 78 _Out_ ITfFunctionProvider **ppFuncProv) override; 79 STDMETHODIMP EnumFunctionProviders(_Out_ IEnumTfFunctionProviders **ppEnum) override; 80 STDMETHODIMP GetGlobalCompartment(_Out_ ITfCompartmentMgr **ppCompMgr) override; 81 82 // ** ITfThreadMgrEx methods ** 83 STDMETHODIMP ActivateEx( 84 _Out_ TfClientId *id, 85 _In_ DWORD flags) override; 86 STDMETHODIMP GetActiveFlags(_Out_ DWORD *flags) override; 87 88 // ** ITfSource methods ** 89 STDMETHODIMP AdviseSink( 90 _In_ REFIID riid, 91 _In_ IUnknown *punk, 92 _Out_ DWORD *pdwCookie) override; 93 STDMETHODIMP UnadviseSink(_In_ DWORD dwCookie) override; 94 95 // ** ITfKeystrokeMgr methods ** 96 STDMETHODIMP AdviseKeyEventSink( 97 _In_ TfClientId tid, 98 _In_ ITfKeyEventSink *pSink, 99 _In_ BOOL fForeground) override; 100 STDMETHODIMP UnadviseKeyEventSink(_In_ TfClientId tid) override; 101 STDMETHODIMP GetForeground(_Out_ CLSID *pclsid) override; 102 STDMETHODIMP TestKeyDown( 103 _In_ WPARAM wParam, 104 _In_ LPARAM lParam, 105 _Out_ BOOL *pfEaten) override; 106 STDMETHODIMP TestKeyUp( 107 _In_ WPARAM wParam, 108 _In_ LPARAM lParam, 109 _Out_ BOOL *pfEaten) override; 110 STDMETHODIMP KeyDown( 111 _In_ WPARAM wParam, 112 _In_ LPARAM lParam, 113 _Out_ BOOL *pfEaten) override; 114 STDMETHODIMP KeyUp( 115 _In_ WPARAM wParam, 116 _In_ LPARAM lParam, 117 _Out_ BOOL *pfEaten) override; 118 STDMETHODIMP GetPreservedKey( 119 _In_ ITfContext *pic, 120 _In_ const TF_PRESERVEDKEY *pprekey, 121 _Out_ GUID *pguid) override; 122 STDMETHODIMP IsPreservedKey( 123 _In_ REFGUID rguid, 124 _In_ const TF_PRESERVEDKEY *pprekey, 125 _Out_ BOOL *pfRegistered) override; 126 STDMETHODIMP PreserveKey( 127 _In_ TfClientId tid, 128 _In_ REFGUID rguid, 129 _In_ const TF_PRESERVEDKEY *prekey, 130 _In_ const WCHAR *pchDesc, 131 _In_ ULONG cchDesc) override; 132 STDMETHODIMP UnpreserveKey( 133 _In_ REFGUID rguid, 134 _In_ const TF_PRESERVEDKEY *pprekey) override; 135 STDMETHODIMP SetPreservedKeyDescription( 136 _In_ REFGUID rguid, 137 _In_ const WCHAR *pchDesc, 138 _In_ ULONG cchDesc) override; 139 STDMETHODIMP GetPreservedKeyDescription( 140 _In_ REFGUID rguid, 141 _Out_ BSTR *pbstrDesc) override; 142 STDMETHODIMP SimulatePreservedKey( 143 _In_ ITfContext *pic, 144 _In_ REFGUID rguid, 145 _Out_ BOOL *pfEaten) override; 146 147 // ** ITfMessagePump methods ** 148 STDMETHODIMP PeekMessageA( 149 _Out_ LPMSG pMsg, 150 _In_ HWND hwnd, 151 _In_ UINT wMsgFilterMin, 152 _In_ UINT wMsgFilterMax, 153 _In_ UINT wRemoveMsg, 154 _Out_ BOOL *pfResult) override; 155 STDMETHODIMP GetMessageA( 156 _Out_ LPMSG pMsg, 157 _In_ HWND hwnd, 158 _In_ UINT wMsgFilterMin, 159 _In_ UINT wMsgFilterMax, 160 _Out_ BOOL *pfResult) override; 161 STDMETHODIMP PeekMessageW( 162 _Out_ LPMSG pMsg, 163 _In_ HWND hwnd, 164 _In_ UINT wMsgFilterMin, 165 _In_ UINT wMsgFilterMax, 166 _In_ UINT wRemoveMsg, 167 _Out_ BOOL *pfResult) override; 168 STDMETHODIMP GetMessageW( 169 _Out_ LPMSG pMsg, 170 _In_ HWND hwnd, 171 _In_ UINT wMsgFilterMin, 172 _In_ UINT wMsgFilterMax, 173 _Out_ BOOL *pfResult) override; 174 175 // ** ITfClientId methods ** 176 STDMETHODIMP GetClientId( 177 _In_ REFCLSID rclsid, 178 _Out_ TfClientId *ptid) override; 179 180 // ** ITfUIElementMgr methods ** 181 STDMETHODIMP BeginUIElement( 182 _In_ ITfUIElement *element, 183 _Inout_ BOOL *show, 184 _Out_ DWORD *id) override; 185 STDMETHODIMP UpdateUIElement(_In_ DWORD id) override; 186 STDMETHODIMP EndUIElement(_In_ DWORD id) override; 187 STDMETHODIMP GetUIElement( 188 _In_ DWORD id, 189 _Out_ ITfUIElement **element) override; 190 STDMETHODIMP EnumUIElements(_Out_ IEnumTfUIElements **enum_elements) override; 191 192 // ** ITfSourceSingle methods ** 193 STDMETHODIMP AdviseSingleSink( 194 _In_ TfClientId tid, 195 _In_ REFIID riid, 196 _In_ IUnknown *punk) override; 197 STDMETHODIMP UnadviseSingleSink( 198 _In_ TfClientId tid, 199 _In_ REFIID riid) override; 200 201 // ** ITfThreadMgrEventSink methods ** 202 STDMETHODIMP OnInitDocumentMgr(_In_ ITfDocumentMgr *pdim) override; 203 STDMETHODIMP OnUninitDocumentMgr(_In_ ITfDocumentMgr *pdim) override; 204 STDMETHODIMP OnSetFocus( 205 _In_ ITfDocumentMgr *pdimFocus, 206 _In_ ITfDocumentMgr *pdimPrevFocus) override; 207 STDMETHODIMP OnPushContext(_In_ ITfContext *pic) override; 208 STDMETHODIMP OnPopContext(_In_ ITfContext *pic) override; 209 210protected: 211 LONG m_cRefs; 212 213 /* Aggregation */ 214 ITfCompartmentMgr *m_CompartmentMgr; 215 216 ITfDocumentMgr *m_focus; 217 LONG m_activationCount; 218 219 ITfKeyEventSink *m_foregroundKeyEventSink; 220 CLSID m_foregroundTextService; 221 222 struct list m_CurrentPreservedKeys; 223 struct list m_CreatedDocumentMgrs; 224 225 struct list m_AssociatedFocusWindows; 226 HHOOK m_focusHook; 227 228 /* kept as separate lists to reduce unnecessary iterations */ 229 struct list m_ActiveLanguageProfileNotifySink; 230 struct list m_DisplayAttributeNotifySink; 231 struct list m_KeyTraceEventSink; 232 struct list m_PreservedKeyNotifySink; 233 struct list m_ThreadFocusSink; 234 struct list m_ThreadMgrEventSink; 235 struct list m_UIElementSink; 236 struct list m_InputProcessorProfileActivationSink; 237 238 static LRESULT CALLBACK ThreadFocusHookProc(INT nCode, WPARAM wParam, LPARAM lParam); 239 LRESULT _ThreadFocusHookProc(INT nCode, WPARAM wParam, LPARAM lParam); 240 241 HRESULT SetupWindowsHook(); 242}; 243 244//////////////////////////////////////////////////////////////////////////// 245 246class CEnumTfDocumentMgr 247 : public IEnumTfDocumentMgrs 248{ 249public: 250 CEnumTfDocumentMgr(); 251 virtual ~CEnumTfDocumentMgr(); 252 253 static HRESULT CreateInstance(struct list* head, CEnumTfDocumentMgr **ppOut); 254 255 // ** IUnknown methods ** 256 STDMETHODIMP QueryInterface(REFIID iid, LPVOID *ppvObject) override; 257 STDMETHODIMP_(ULONG) AddRef() override; 258 STDMETHODIMP_(ULONG) Release() override; 259 260 // ** IEnumTfDocumentMgrs methods ** 261 STDMETHODIMP Clone(_Out_ IEnumTfDocumentMgrs **ppEnum) override; 262 STDMETHODIMP Next( 263 _In_ ULONG ulCount, 264 _Out_ ITfDocumentMgr **rgDocumentMgr, 265 _Out_ ULONG *pcFetched) override; 266 STDMETHODIMP Reset() override; 267 STDMETHODIMP Skip(_In_ ULONG ulCount) override; 268 269protected: 270 LONG m_cRefs; 271 struct list *m_index; 272 struct list *m_head; 273}; 274 275//////////////////////////////////////////////////////////////////////////// 276 277CThreadMgr::CThreadMgr() 278 : m_cRefs(1) 279 , m_CompartmentMgr(NULL) 280 , m_focus(NULL) 281 , m_activationCount(0) 282 , m_foregroundKeyEventSink(NULL) 283{ 284 m_foregroundTextService = GUID_NULL; 285 286 list_init(&m_CurrentPreservedKeys); 287 list_init(&m_CreatedDocumentMgrs); 288 289 list_init(&m_AssociatedFocusWindows); 290 m_focusHook = NULL; 291 292 /* kept as separate lists to reduce unnecessary iterations */ 293 list_init(&m_ActiveLanguageProfileNotifySink); 294 list_init(&m_DisplayAttributeNotifySink); 295 list_init(&m_KeyTraceEventSink); 296 list_init(&m_PreservedKeyNotifySink); 297 list_init(&m_ThreadFocusSink); 298 list_init(&m_ThreadMgrEventSink); 299 list_init(&m_UIElementSink); 300 list_init(&m_InputProcessorProfileActivationSink); 301} 302 303CThreadMgr::~CThreadMgr() 304{ 305 struct list *cursor, *cursor2; 306 307 /* unhook right away */ 308 if (m_focusHook) 309 UnhookWindowsHookEx(m_focusHook); 310 311 TlsSetValue(g_dwTLSIndex, NULL); 312 TRACE("destroying %p\n", this); 313 314 if (m_focus) 315 m_focus->Release(); 316 317 free_sinks(&m_ActiveLanguageProfileNotifySink); 318 free_sinks(&m_DisplayAttributeNotifySink); 319 free_sinks(&m_KeyTraceEventSink); 320 free_sinks(&m_PreservedKeyNotifySink); 321 free_sinks(&m_ThreadFocusSink); 322 free_sinks(&m_ThreadMgrEventSink); 323 free_sinks(&m_UIElementSink); 324 free_sinks(&m_InputProcessorProfileActivationSink); 325 326 LIST_FOR_EACH_SAFE(cursor, cursor2, &m_CurrentPreservedKeys) 327 { 328 PreservedKey* key = LIST_ENTRY(cursor, PreservedKey, entry); 329 list_remove(cursor); 330 cicMemFree(key->description); 331 cicMemFree(key); 332 } 333 334 LIST_FOR_EACH_SAFE(cursor, cursor2, &m_CreatedDocumentMgrs) 335 { 336 DocumentMgrEntry *mgr = LIST_ENTRY(cursor, DocumentMgrEntry, entry); 337 list_remove(cursor); 338 FIXME("Left Over ITfDocumentMgr. Should we do something with it?\n"); 339 cicMemFree(mgr); 340 } 341 342 LIST_FOR_EACH_SAFE(cursor, cursor2, &m_AssociatedFocusWindows) 343 { 344 AssociatedWindow *wnd = LIST_ENTRY(cursor, AssociatedWindow, entry); 345 list_remove(cursor); 346 cicMemFree(wnd); 347 } 348 349 m_CompartmentMgr->Release(); 350} 351 352STDMETHODIMP CThreadMgr::QueryInterface(REFIID iid, LPVOID *ppvObject) 353{ 354 *ppvObject = NULL; 355 356 IUnknown *pUnk = NULL; 357 if (iid == IID_IUnknown || iid == IID_ITfThreadMgr || iid == IID_ITfThreadMgrEx) 358 pUnk = static_cast<ITfThreadMgrEx *>(this); 359 else if (iid == IID_ITfSource) 360 pUnk = static_cast<ITfSource *>(this); 361 else if (iid == IID_ITfKeystrokeMgr) 362 pUnk = static_cast<ITfKeystrokeMgr *>(this); 363 else if (iid == IID_ITfMessagePump) 364 pUnk = static_cast<ITfMessagePump *>(this); 365 else if (iid == IID_ITfClientId) 366 pUnk = static_cast<ITfClientId *>(this); 367 else if (iid == IID_ITfCompartmentMgr) 368 pUnk = m_CompartmentMgr; 369 else if (iid == IID_ITfUIElementMgr) 370 pUnk = static_cast<ITfUIElementMgr *>(this); 371 else if (iid == IID_ITfSourceSingle) 372 pUnk = static_cast<ITfSourceSingle *>(this); 373 374 if (pUnk) 375 { 376 *ppvObject = pUnk; 377 pUnk->AddRef(); 378 return S_OK; 379 } 380 381 WARN("unsupported interface: %s\n", debugstr_guid(&iid)); 382 return E_NOINTERFACE; 383} 384 385STDMETHODIMP_(ULONG) CThreadMgr::AddRef() 386{ 387 return ::InterlockedIncrement(&m_cRefs); 388} 389 390STDMETHODIMP_(ULONG) CThreadMgr::Release() 391{ 392 ULONG ret = ::InterlockedDecrement(&m_cRefs); 393 if (!ret) 394 delete this; 395 return ret; 396} 397 398STDMETHODIMP CThreadMgr::Activate(_Out_ TfClientId *ptid) 399{ 400 TRACE("(%p) %p\n", this, ptid); 401 return ActivateEx(ptid, 0); 402} 403 404STDMETHODIMP CThreadMgr::Deactivate() 405{ 406 TRACE("(%p)\n", this); 407 408 if (m_activationCount == 0) 409 return E_UNEXPECTED; 410 411 --m_activationCount; 412 413 if (m_activationCount == 0) 414 { 415 if (m_focus) 416 { 417 OnSetFocus(NULL, m_focus); 418 m_focus->Release(); 419 m_focus = NULL; 420 } 421 } 422 423 deactivate_textservices(); 424 return S_OK; 425} 426 427STDMETHODIMP CThreadMgr::CreateDocumentMgr(_Out_ ITfDocumentMgr **ppdim) 428{ 429 TRACE("(%p)\n", this); 430 431 if (!ppdim) 432 return E_INVALIDARG; 433 434 DocumentMgrEntry *mgrentry = (DocumentMgrEntry *)cicMemAlloc(sizeof(DocumentMgrEntry)); 435 if (!mgrentry) 436 return E_OUTOFMEMORY; 437 438 HRESULT hr = DocumentMgr_Constructor(this, ppdim); 439 if (SUCCEEDED(hr)) 440 { 441 mgrentry->docmgr = *ppdim; 442 list_add_head(&m_CreatedDocumentMgrs, &mgrentry->entry); 443 } 444 else 445 { 446 cicMemFree(mgrentry); 447 } 448 449 return hr; 450} 451 452STDMETHODIMP CThreadMgr::EnumDocumentMgrs(_Out_ IEnumTfDocumentMgrs **ppEnum) 453{ 454 TRACE("(%p) %p\n", this, ppEnum); 455 456 if (!ppEnum) 457 return E_INVALIDARG; 458 459 return CEnumTfDocumentMgr::CreateInstance(&m_CreatedDocumentMgrs, (CEnumTfDocumentMgr **)ppEnum); 460} 461 462STDMETHODIMP CThreadMgr::GetFocus(_Out_ ITfDocumentMgr **ppdimFocus) 463{ 464 TRACE("(%p)\n", this); 465 466 if (!ppdimFocus) 467 return E_INVALIDARG; 468 469 *ppdimFocus = m_focus; 470 471 TRACE("->%p\n", m_focus); 472 473 if (!m_focus) 474 return S_FALSE; 475 476 m_focus->AddRef(); 477 return S_OK; 478} 479 480STDMETHODIMP CThreadMgr::SetFocus(_In_ ITfDocumentMgr *pdimFocus) 481{ 482 ITfDocumentMgr *check; 483 484 TRACE("(%p) %p\n", this, pdimFocus); 485 486 if (!pdimFocus) 487 check = NULL; 488 else if (FAILED(pdimFocus->QueryInterface(IID_ITfDocumentMgr, (LPVOID*)&check))) 489 return E_INVALIDARG; 490 491 OnSetFocus(check, m_focus); 492 493 if (m_focus) 494 m_focus->Release(); 495 496 m_focus = check; 497 return S_OK; 498} 499 500LRESULT CThreadMgr::_ThreadFocusHookProc(INT nCode, WPARAM wParam, LPARAM lParam) 501{ 502 if (!m_focusHook) 503 { 504 ERR("Hook proc but no ThreadMgr focus Hook. Serious Error\n"); 505 return 0; 506 } 507 508 if (nCode == HCBT_SETFOCUS) /* focus change within our thread */ 509 { 510 struct list *cursor; 511 512 LIST_FOR_EACH(cursor, &m_AssociatedFocusWindows) 513 { 514 AssociatedWindow *wnd = LIST_ENTRY(cursor, AssociatedWindow, entry); 515 if (wnd->hwnd == (HWND)wParam) 516 { 517 TRACE("Triggering Associated window focus\n"); 518 if (m_focus != wnd->docmgr) 519 SetFocus(wnd->docmgr); 520 break; 521 } 522 } 523 } 524 525 return CallNextHookEx(m_focusHook, nCode, wParam, lParam); 526} 527 528LRESULT CALLBACK CThreadMgr::ThreadFocusHookProc(INT nCode, WPARAM wParam, LPARAM lParam) 529{ 530 CThreadMgr *This = (CThreadMgr *)TlsGetValue(g_dwTLSIndex); 531 if (!This) 532 { 533 ERR("Hook proc but no ThreadMgr for this thread. Serious Error\n"); 534 return 0; 535 } 536 return This->_ThreadFocusHookProc(nCode, wParam, lParam); 537} 538 539HRESULT CThreadMgr::SetupWindowsHook() 540{ 541 if (!m_focusHook) 542 { 543 m_focusHook = SetWindowsHookExW(WH_CBT, ThreadFocusHookProc, 0, GetCurrentThreadId()); 544 if (!m_focusHook) 545 { 546 ERR("Unable to set focus hook\n"); 547 return E_FAIL; 548 } 549 return S_OK; 550 } 551 return S_FALSE; 552} 553 554STDMETHODIMP CThreadMgr::AssociateFocus( 555 _In_ HWND hwnd, 556 _In_ ITfDocumentMgr *pdimNew, 557 _Out_ ITfDocumentMgr **ppdimPrev) 558{ 559 struct list *cursor, *cursor2; 560 AssociatedWindow *wnd; 561 562 TRACE("(%p) %p %p %p\n", this, hwnd, pdimNew, ppdimPrev); 563 564 if (!ppdimPrev) 565 return E_INVALIDARG; 566 567 *ppdimPrev = NULL; 568 569 LIST_FOR_EACH_SAFE(cursor, cursor2, &m_AssociatedFocusWindows) 570 { 571 wnd = LIST_ENTRY(cursor, AssociatedWindow, entry); 572 if (wnd->hwnd == hwnd) 573 { 574 if (wnd->docmgr) 575 wnd->docmgr->AddRef(); 576 *ppdimPrev = wnd->docmgr; 577 wnd->docmgr = pdimNew; 578 if (::GetFocus() == hwnd) 579 SetFocus(pdimNew); 580 return S_OK; 581 } 582 } 583 584 wnd = (AssociatedWindow *)cicMemAlloc(sizeof(AssociatedWindow)); 585 wnd->hwnd = hwnd; 586 wnd->docmgr = pdimNew; 587 list_add_head(&m_AssociatedFocusWindows, &wnd->entry); 588 589 if (::GetFocus() == hwnd) 590 SetFocus(pdimNew); 591 592 this->SetupWindowsHook(); 593 return S_OK; 594} 595 596STDMETHODIMP CThreadMgr::IsThreadFocus(_Out_ BOOL *pfThreadFocus) 597{ 598 TRACE("(%p) %p\n", this, pfThreadFocus); 599 600 if (!pfThreadFocus) 601 return E_INVALIDARG; 602 603 HWND focus = ::GetFocus(); 604 *pfThreadFocus = !focus; 605 return S_OK; 606} 607 608STDMETHODIMP CThreadMgr::GetFunctionProvider( 609 _In_ REFCLSID clsid, 610 _Out_ ITfFunctionProvider **ppFuncProv) 611{ 612 FIXME("STUB:(%p)\n", this); 613 return E_NOTIMPL; 614} 615 616STDMETHODIMP CThreadMgr::EnumFunctionProviders(_Out_ IEnumTfFunctionProviders **ppEnum) 617{ 618 FIXME("STUB:(%p)\n", this); 619 return E_NOTIMPL; 620} 621 622STDMETHODIMP CThreadMgr::GetGlobalCompartment(_Out_ ITfCompartmentMgr **ppCompMgr) 623{ 624 HRESULT hr; 625 TRACE("(%p) %p\n", this, ppCompMgr); 626 627 if (!ppCompMgr) 628 return E_INVALIDARG; 629 630 if (!g_globalCompartmentMgr) 631 { 632 hr = CompartmentMgr_Constructor(NULL, IID_ITfCompartmentMgr, (IUnknown **)&g_globalCompartmentMgr); 633 if (FAILED(hr)) 634 return hr; 635 } 636 637 g_globalCompartmentMgr->AddRef(); 638 *ppCompMgr = g_globalCompartmentMgr; 639 return S_OK; 640} 641 642STDMETHODIMP CThreadMgr::ActivateEx( 643 _Out_ TfClientId *id, 644 _In_ DWORD flags) 645{ 646 TRACE("(%p) %p, %#x\n", this, id, flags); 647 648 if (!id) 649 return E_INVALIDARG; 650 651 if (flags) 652 FIXME("Unimplemented flags %#x\n", flags); 653 654 if (!g_processId) 655 { 656 GUID guid; 657 CoCreateGuid(&guid); 658 GetClientId(guid, &g_processId); 659 } 660 661 activate_textservices(this); 662 ++m_activationCount; 663 *id = g_processId; 664 return S_OK; 665} 666 667STDMETHODIMP CThreadMgr::GetActiveFlags(_Out_ DWORD *flags) 668{ 669 FIXME("STUB:(%p)\n", this); 670 return E_NOTIMPL; 671} 672 673STDMETHODIMP CThreadMgr::AdviseSink( 674 _In_ REFIID riid, 675 _In_ IUnknown *punk, 676 _Out_ DWORD *pdwCookie) 677{ 678 TRACE("(%p) %s %p %p\n", this, debugstr_guid(&riid), punk, pdwCookie); 679 680 if (cicIsNullPtr(&riid) || !punk || !pdwCookie) 681 return E_INVALIDARG; 682 683 if (riid == IID_ITfThreadMgrEventSink) 684 return advise_sink(&m_ThreadMgrEventSink, IID_ITfThreadMgrEventSink, COOKIE_MAGIC_TMSINK, punk, pdwCookie); 685 686 if (riid == IID_ITfThreadFocusSink) 687 { 688 WARN("semi-stub for ITfThreadFocusSink: sink won't be used.\n"); 689 return advise_sink(&m_ThreadFocusSink, IID_ITfThreadFocusSink, COOKIE_MAGIC_THREADFOCUSSINK, punk, pdwCookie); 690 } 691 692 if (riid == IID_ITfActiveLanguageProfileNotifySink) 693 { 694 WARN("semi-stub for ITfActiveLanguageProfileNotifySink: sink won't be used.\n"); 695 return advise_sink(&m_ActiveLanguageProfileNotifySink, IID_ITfActiveLanguageProfileNotifySink, 696 COOKIE_MAGIC_ACTIVELANGSINK, punk, pdwCookie); 697 } 698 699 if (riid == IID_ITfKeyTraceEventSink) 700 { 701 WARN("semi-stub for ITfKeyTraceEventSink: sink won't be used.\n"); 702 return advise_sink(&m_KeyTraceEventSink, IID_ITfKeyTraceEventSink, 703 COOKIE_MAGIC_KEYTRACESINK, punk, pdwCookie); 704 } 705 706 if (riid == IID_ITfUIElementSink) 707 { 708 WARN("semi-stub for ITfUIElementSink: sink won't be used.\n"); 709 return advise_sink(&m_UIElementSink, IID_ITfUIElementSink, 710 COOKIE_MAGIC_UIELEMENTSINK, punk, pdwCookie); 711 } 712 713 if (riid == IID_ITfInputProcessorProfileActivationSink) 714 { 715 WARN("semi-stub for ITfInputProcessorProfileActivationSink: sink won't be used.\n"); 716 return advise_sink(&m_InputProcessorProfileActivationSink, IID_ITfInputProcessorProfileActivationSink, 717 COOKIE_MAGIC_INPUTPROCESSORPROFILEACTIVATIONSINK, punk, pdwCookie); 718 } 719 720 FIXME("(%p) Unhandled Sink: %s\n", this, debugstr_guid(&riid)); 721 return E_NOTIMPL; 722} 723 724STDMETHODIMP CThreadMgr::UnadviseSink(_In_ DWORD dwCookie) 725{ 726 DWORD magic; 727 728 TRACE("(%p) %x\n", this, dwCookie); 729 730 magic = get_Cookie_magic(dwCookie); 731 if (magic != COOKIE_MAGIC_TMSINK && 732 magic != COOKIE_MAGIC_THREADFOCUSSINK && 733 magic != COOKIE_MAGIC_KEYTRACESINK && 734 magic != COOKIE_MAGIC_UIELEMENTSINK && 735 magic != COOKIE_MAGIC_INPUTPROCESSORPROFILEACTIVATIONSINK) 736 { 737 return E_INVALIDARG; 738 } 739 740 return unadvise_sink(dwCookie); 741} 742 743STDMETHODIMP CThreadMgr::AdviseKeyEventSink( 744 _In_ TfClientId tid, 745 _In_ ITfKeyEventSink *pSink, 746 _In_ BOOL fForeground) 747{ 748 CLSID textservice; 749 ITfKeyEventSink *check = NULL; 750 751 TRACE("(%p) %x %p %i\n", this, tid, pSink, fForeground); 752 753 if (!tid || !pSink) 754 return E_INVALIDARG; 755 756 textservice = get_textservice_clsid(tid); 757 if (GUID_NULL == textservice) 758 return E_INVALIDARG; 759 760 get_textservice_sink(tid, IID_ITfKeyEventSink, (IUnknown **)&check); 761 if (check) 762 return CONNECT_E_ADVISELIMIT; 763 764 if (FAILED(pSink->QueryInterface(IID_ITfKeyEventSink, (LPVOID*)&check))) 765 return E_INVALIDARG; 766 767 set_textservice_sink(tid, IID_ITfKeyEventSink, check); 768 769 if (fForeground) 770 { 771 if (m_foregroundKeyEventSink) 772 { 773 m_foregroundKeyEventSink->OnSetFocus(FALSE); 774 m_foregroundKeyEventSink->Release(); 775 } 776 check->AddRef(); 777 check->OnSetFocus(TRUE); 778 m_foregroundKeyEventSink = check; 779 m_foregroundTextService = textservice; 780 } 781 return S_OK; 782} 783 784STDMETHODIMP CThreadMgr::UnadviseKeyEventSink(_In_ TfClientId tid) 785{ 786 CLSID textservice; 787 ITfKeyEventSink *check = NULL; 788 TRACE("(%p) %x\n", this, tid); 789 790 if (!tid) 791 return E_INVALIDARG; 792 793 textservice = get_textservice_clsid(tid); 794 if (GUID_NULL == textservice) 795 return E_INVALIDARG; 796 797 get_textservice_sink(tid, IID_ITfKeyEventSink, (IUnknown **)&check); 798 799 if (!check) 800 return CONNECT_E_NOCONNECTION; 801 802 set_textservice_sink(tid, IID_ITfKeyEventSink, NULL); 803 check->Release(); 804 805 if (m_foregroundKeyEventSink == check) 806 { 807 m_foregroundKeyEventSink->Release(); 808 m_foregroundKeyEventSink = NULL; 809 m_foregroundTextService = GUID_NULL; 810 } 811 return S_OK; 812} 813 814STDMETHODIMP CThreadMgr::GetForeground(_Out_ CLSID *pclsid) 815{ 816 TRACE("(%p) %p\n", this, pclsid); 817 if (!pclsid) 818 return E_INVALIDARG; 819 820 if (m_foregroundTextService == GUID_NULL) 821 return S_FALSE; 822 823 *pclsid = m_foregroundTextService; 824 return S_OK; 825} 826 827STDMETHODIMP CThreadMgr::TestKeyDown( 828 _In_ WPARAM wParam, 829 _In_ LPARAM lParam, 830 _Out_ BOOL *pfEaten) 831{ 832 FIXME("STUB:(%p)\n", this); 833 if (!pfEaten) 834 return E_INVALIDARG; 835 *pfEaten = FALSE; 836 return S_OK; 837} 838 839STDMETHODIMP CThreadMgr::TestKeyUp( 840 _In_ WPARAM wParam, 841 _In_ LPARAM lParam, 842 _Out_ BOOL *pfEaten) 843{ 844 FIXME("STUB:(%p)\n", this); 845 if (!pfEaten) 846 return E_INVALIDARG; 847 *pfEaten = FALSE; 848 return S_OK; 849} 850 851STDMETHODIMP CThreadMgr::KeyDown( 852 _In_ WPARAM wParam, 853 _In_ LPARAM lParam, 854 _Out_ BOOL *pfEaten) 855{ 856 FIXME("STUB:(%p)\n", this); 857 if (!pfEaten) 858 return E_INVALIDARG; 859 *pfEaten = FALSE; 860 return E_NOTIMPL; 861} 862 863STDMETHODIMP CThreadMgr::KeyUp( 864 _In_ WPARAM wParam, 865 _In_ LPARAM lParam, 866 _Out_ BOOL *pfEaten) 867{ 868 FIXME("STUB:(%p)\n", this); 869 if (!pfEaten) 870 return E_INVALIDARG; 871 *pfEaten = FALSE; 872 return E_NOTIMPL; 873} 874 875STDMETHODIMP CThreadMgr::GetPreservedKey( 876 _In_ ITfContext *pic, 877 _In_ const TF_PRESERVEDKEY *pprekey, 878 _Out_ GUID *pguid) 879{ 880 FIXME("STUB:(%p)\n", this); 881 return E_NOTIMPL; 882} 883 884STDMETHODIMP CThreadMgr::IsPreservedKey( 885 _In_ REFGUID rguid, 886 _In_ const TF_PRESERVEDKEY *pprekey, 887 _Out_ BOOL *pfRegistered) 888{ 889 struct list *cursor; 890 891 TRACE("(%p) %s (%x %x) %p\n", this, debugstr_guid(&rguid), (pprekey ? pprekey->uVKey : 0), (pprekey ? pprekey->uModifiers : 0), pfRegistered); 892 893 if (cicIsNullPtr(&rguid) || !pprekey || !pfRegistered) 894 return E_INVALIDARG; 895 896 LIST_FOR_EACH(cursor, &m_CurrentPreservedKeys) 897 { 898 PreservedKey* key = LIST_ENTRY(cursor, PreservedKey, entry); 899 if (rguid == key->guid && pprekey->uVKey == key->prekey.uVKey && pprekey->uModifiers == key->prekey.uModifiers) 900 { 901 *pfRegistered = TRUE; 902 return S_OK; 903 } 904 } 905 906 *pfRegistered = FALSE; 907 return S_FALSE; 908} 909 910STDMETHODIMP CThreadMgr::PreserveKey( 911 _In_ TfClientId tid, 912 _In_ REFGUID rguid, 913 _In_ const TF_PRESERVEDKEY *prekey, 914 _In_ const WCHAR *pchDesc, 915 _In_ ULONG cchDesc) 916{ 917 struct list *cursor; 918 919 TRACE("(%p) %x %s (%x,%x) %s\n", this, tid, debugstr_guid(&rguid), (prekey ? prekey->uVKey : 0), (prekey ? prekey->uModifiers : 0), debugstr_wn(pchDesc, cchDesc)); 920 921 if (!tid || cicIsNullPtr(&rguid) || !prekey || (cchDesc && !pchDesc)) 922 return E_INVALIDARG; 923 924 LIST_FOR_EACH(cursor, &m_CurrentPreservedKeys) 925 { 926 PreservedKey* key = LIST_ENTRY(cursor, PreservedKey, entry); 927 if (rguid == key->guid && prekey->uVKey == key->prekey.uVKey && prekey->uModifiers == key->prekey.uModifiers) 928 return TF_E_ALREADY_EXISTS; 929 } 930 931 PreservedKey *newkey = (PreservedKey *)cicMemAlloc(sizeof(PreservedKey)); 932 if (!newkey) 933 return E_OUTOFMEMORY; 934 935 newkey->guid = rguid; 936 newkey->prekey = *prekey; 937 newkey->tid = tid; 938 newkey->description = NULL; 939 if (cchDesc) 940 { 941 newkey->description = (LPWSTR)cicMemAlloc((cchDesc + 1) * sizeof(WCHAR)); 942 if (!newkey->description) 943 { 944 cicMemFree(newkey); 945 return E_OUTOFMEMORY; 946 } 947 CopyMemory(newkey->description, pchDesc, cchDesc * sizeof(WCHAR)); 948 newkey->description[cchDesc] = UNICODE_NULL; 949 } 950 951 list_add_head(&m_CurrentPreservedKeys, &newkey->entry); 952 return S_OK; 953} 954 955STDMETHODIMP CThreadMgr::UnpreserveKey( 956 _In_ REFGUID rguid, 957 _In_ const TF_PRESERVEDKEY *pprekey) 958{ 959 PreservedKey* key = NULL; 960 struct list *cursor; 961 TRACE("(%p) %s (%x %x)\n", this, debugstr_guid(&rguid), (pprekey ? pprekey->uVKey : 0), (pprekey ? pprekey->uModifiers : 0)); 962 963 if (!pprekey || cicIsNullPtr(&rguid)) 964 return E_INVALIDARG; 965 966 LIST_FOR_EACH(cursor, &m_CurrentPreservedKeys) 967 { 968 key = LIST_ENTRY(cursor, PreservedKey, entry); 969 if (rguid == key->guid && pprekey->uVKey == key->prekey.uVKey && pprekey->uModifiers == key->prekey.uModifiers) 970 break; 971 key = NULL; 972 } 973 974 if (!key) 975 return CONNECT_E_NOCONNECTION; 976 977 list_remove(&key->entry); 978 cicMemFree(key->description); 979 cicMemFree(key); 980 981 return S_OK; 982} 983 984STDMETHODIMP CThreadMgr::SetPreservedKeyDescription( 985 _In_ REFGUID rguid, 986 _In_ const WCHAR *pchDesc, 987 _In_ ULONG cchDesc) 988{ 989 FIXME("STUB:(%p)\n", this); 990 return E_NOTIMPL; 991} 992 993STDMETHODIMP CThreadMgr::GetPreservedKeyDescription( 994 _In_ REFGUID rguid, 995 _Out_ BSTR *pbstrDesc) 996{ 997 FIXME("STUB:(%p)\n", this); 998 return E_NOTIMPL; 999} 1000 1001STDMETHODIMP CThreadMgr::SimulatePreservedKey( 1002 _In_ ITfContext *pic, 1003 _In_ REFGUID rguid, 1004 _Out_ BOOL *pfEaten) 1005{ 1006 FIXME("STUB:(%p)\n", this); 1007 if (!pfEaten) 1008 return E_INVALIDARG; 1009 *pfEaten = FALSE; 1010 return E_NOTIMPL; 1011} 1012 1013STDMETHODIMP CThreadMgr::PeekMessageA( 1014 _Out_ LPMSG pMsg, 1015 _In_ HWND hwnd, 1016 _In_ UINT wMsgFilterMin, 1017 _In_ UINT wMsgFilterMax, 1018 _In_ UINT wRemoveMsg, 1019 _Out_ BOOL *pfResult) 1020{ 1021 if (!pfResult) 1022 return E_INVALIDARG; 1023 *pfResult = ::PeekMessageA(pMsg, hwnd, wMsgFilterMin, wMsgFilterMax, wRemoveMsg); 1024 return S_OK; 1025} 1026 1027STDMETHODIMP CThreadMgr::GetMessageA( 1028 _Out_ LPMSG pMsg, 1029 _In_ HWND hwnd, 1030 _In_ UINT wMsgFilterMin, 1031 _In_ UINT wMsgFilterMax, 1032 _Out_ BOOL *pfResult) 1033{ 1034 if (!pfResult) 1035 return E_INVALIDARG; 1036 *pfResult = ::GetMessageA(pMsg, hwnd, wMsgFilterMin, wMsgFilterMax); 1037 return S_OK; 1038} 1039 1040STDMETHODIMP CThreadMgr::PeekMessageW( 1041 _Out_ LPMSG pMsg, 1042 _In_ HWND hwnd, 1043 _In_ UINT wMsgFilterMin, 1044 _In_ UINT wMsgFilterMax, 1045 _In_ UINT wRemoveMsg, 1046 _Out_ BOOL *pfResult) 1047{ 1048 if (!pfResult) 1049 return E_INVALIDARG; 1050 *pfResult = ::PeekMessageW(pMsg, hwnd, wMsgFilterMin, wMsgFilterMax, wRemoveMsg); 1051 return S_OK; 1052} 1053 1054STDMETHODIMP CThreadMgr::GetMessageW( 1055 _Out_ LPMSG pMsg, 1056 _In_ HWND hwnd, 1057 _In_ UINT wMsgFilterMin, 1058 _In_ UINT wMsgFilterMax, 1059 _Out_ BOOL *pfResult) 1060{ 1061 if (!pfResult) 1062 return E_INVALIDARG; 1063 *pfResult = ::GetMessageW(pMsg, hwnd, wMsgFilterMin, wMsgFilterMax); 1064 return S_OK; 1065} 1066 1067STDMETHODIMP CThreadMgr::GetClientId( 1068 _In_ REFCLSID rclsid, 1069 _Out_ TfClientId *ptid) 1070{ 1071 HRESULT hr; 1072 ITfCategoryMgr *catmgr; 1073 1074 TRACE("(%p) %s\n", this, debugstr_guid(&rclsid)); 1075 1076 CategoryMgr_Constructor(NULL, (IUnknown **)&catmgr); 1077 hr = catmgr->RegisterGUID(rclsid, ptid); 1078 catmgr->Release(); 1079 1080 return hr; 1081} 1082 1083STDMETHODIMP CThreadMgr::OnInitDocumentMgr(_In_ ITfDocumentMgr *pdim) 1084{ 1085 ITfThreadMgrEventSink *sink; 1086 struct list *cursor; 1087 1088 TRACE("(%p) %p\n", this, pdim); 1089 1090 SINK_FOR_EACH(cursor, &m_ThreadMgrEventSink, ITfThreadMgrEventSink, sink) 1091 { 1092 sink->OnInitDocumentMgr(pdim); 1093 } 1094 1095 return S_OK; 1096} 1097 1098STDMETHODIMP CThreadMgr::OnUninitDocumentMgr(_In_ ITfDocumentMgr *pdim) 1099{ 1100 ITfThreadMgrEventSink *sink; 1101 struct list *cursor; 1102 1103 TRACE("(%p) %p\n", this, pdim); 1104 1105 SINK_FOR_EACH(cursor, &m_ThreadMgrEventSink, ITfThreadMgrEventSink, sink) 1106 { 1107 sink->OnUninitDocumentMgr(pdim); 1108 } 1109 1110 return S_OK; 1111} 1112 1113STDMETHODIMP CThreadMgr::OnSetFocus( 1114 _In_ ITfDocumentMgr *pdimFocus, 1115 _In_ ITfDocumentMgr *pdimPrevFocus) 1116{ 1117 ITfThreadMgrEventSink *sink; 1118 struct list *cursor; 1119 1120 TRACE("(%p) %p %p\n", this, pdimFocus, pdimPrevFocus); 1121 1122 SINK_FOR_EACH(cursor, &m_ThreadMgrEventSink, ITfThreadMgrEventSink, sink) 1123 { 1124 sink->OnSetFocus(pdimFocus, pdimPrevFocus); 1125 } 1126 1127 return S_OK; 1128} 1129 1130STDMETHODIMP CThreadMgr::OnPushContext(_In_ ITfContext *pic) 1131{ 1132 ITfThreadMgrEventSink *sink; 1133 struct list *cursor; 1134 1135 TRACE("(%p) %p\n", this, pic); 1136 1137 SINK_FOR_EACH(cursor, &m_ThreadMgrEventSink, ITfThreadMgrEventSink, sink) 1138 { 1139 sink->OnPushContext(pic); 1140 } 1141 1142 return S_OK; 1143} 1144 1145STDMETHODIMP CThreadMgr::OnPopContext(_In_ ITfContext *pic) 1146{ 1147 ITfThreadMgrEventSink *sink; 1148 struct list *cursor; 1149 1150 TRACE("(%p) %p\n", this, pic); 1151 1152 SINK_FOR_EACH(cursor, &m_ThreadMgrEventSink, ITfThreadMgrEventSink, sink) 1153 { 1154 sink->OnPopContext(pic); 1155 } 1156 1157 return S_OK; 1158} 1159 1160STDMETHODIMP CThreadMgr::BeginUIElement( 1161 _In_ ITfUIElement *element, 1162 _Inout_ BOOL *show, 1163 _Out_ DWORD *id) 1164{ 1165 FIXME("STUB:(%p)\n", this); 1166 return E_NOTIMPL; 1167} 1168 1169STDMETHODIMP CThreadMgr::UpdateUIElement(_In_ DWORD id) 1170{ 1171 FIXME("STUB:(%p)\n", this); 1172 return E_NOTIMPL; 1173} 1174 1175STDMETHODIMP CThreadMgr::EndUIElement(_In_ DWORD id) 1176{ 1177 FIXME("STUB:(%p)\n", this); 1178 return E_NOTIMPL; 1179} 1180 1181STDMETHODIMP CThreadMgr::GetUIElement( 1182 _In_ DWORD id, 1183 _Out_ ITfUIElement **element) 1184{ 1185 FIXME("STUB:(%p)\n", this); 1186 return E_NOTIMPL; 1187} 1188 1189STDMETHODIMP CThreadMgr::EnumUIElements(_Out_ IEnumTfUIElements **enum_elements) 1190{ 1191 FIXME("STUB:(%p)\n", this); 1192 return E_NOTIMPL; 1193} 1194 1195STDMETHODIMP CThreadMgr::AdviseSingleSink( 1196 _In_ TfClientId tid, 1197 _In_ REFIID riid, 1198 _In_ IUnknown *punk) 1199{ 1200 FIXME("STUB:(%p) %i %s %p\n", this, tid, debugstr_guid(&riid), punk); 1201 return E_NOTIMPL; 1202} 1203 1204STDMETHODIMP CThreadMgr::UnadviseSingleSink( 1205 _In_ TfClientId tid, 1206 _In_ REFIID riid) 1207{ 1208 FIXME("STUB:(%p) %i %s\n", this, tid, debugstr_guid(&riid)); 1209 return E_NOTIMPL; 1210} 1211 1212HRESULT CThreadMgr::CreateInstance(IUnknown *pUnkOuter, CThreadMgr **ppOut) 1213{ 1214 if (pUnkOuter) 1215 return CLASS_E_NOAGGREGATION; 1216 1217 /* Only 1 ThreadMgr is created per thread */ 1218 CThreadMgr *This = (CThreadMgr *)TlsGetValue(g_dwTLSIndex); 1219 if (This) 1220 { 1221 This->AddRef(); 1222 *ppOut = This; 1223 return S_OK; 1224 } 1225 1226 This = new(cicNoThrow) CThreadMgr(); 1227 if (!This) 1228 return E_OUTOFMEMORY; 1229 1230 TlsSetValue(g_dwTLSIndex, This); 1231 1232 ITfCompartmentMgr *pCompMgr = NULL; 1233 CompartmentMgr_Constructor(static_cast<ITfThreadMgrEx *>(This), IID_IUnknown, (IUnknown **)&pCompMgr); 1234 This->m_CompartmentMgr = pCompMgr; 1235 1236 TRACE("returning %p\n", This); 1237 *ppOut = This; 1238 return S_OK; 1239} 1240 1241void CThreadMgr::OnDocumentMgrDestruction(ITfDocumentMgr *mgr) 1242{ 1243 struct list *cursor; 1244 LIST_FOR_EACH(cursor, &m_CreatedDocumentMgrs) 1245 { 1246 DocumentMgrEntry *mgrentry = LIST_ENTRY(cursor, DocumentMgrEntry, entry); 1247 if (mgrentry->docmgr == mgr) 1248 { 1249 list_remove(cursor); 1250 cicMemFree(mgrentry); 1251 return; 1252 } 1253 } 1254 FIXME("ITfDocumentMgr %p not found in this thread\n", mgr); 1255} 1256 1257//////////////////////////////////////////////////////////////////////////// 1258 1259CEnumTfDocumentMgr::CEnumTfDocumentMgr() 1260 : m_cRefs(1) 1261 , m_index(NULL) 1262 , m_head(NULL) 1263{ 1264} 1265 1266CEnumTfDocumentMgr::~CEnumTfDocumentMgr() 1267{ 1268 TRACE("destroying %p\n", this); 1269} 1270 1271STDMETHODIMP CEnumTfDocumentMgr::QueryInterface(REFIID iid, LPVOID *ppvObject) 1272{ 1273 *ppvObject = NULL; 1274 1275 if (iid == IID_IUnknown || iid == IID_IEnumTfDocumentMgrs) 1276 *ppvObject = static_cast<IEnumTfDocumentMgrs *>(this); 1277 1278 if (*ppvObject) 1279 { 1280 AddRef(); 1281 return S_OK; 1282 } 1283 1284 WARN("unsupported interface: %s\n", debugstr_guid(&iid)); 1285 return E_NOINTERFACE; 1286} 1287 1288STDMETHODIMP_(ULONG) CEnumTfDocumentMgr::AddRef() 1289{ 1290 return InterlockedIncrement(&m_cRefs); 1291} 1292 1293STDMETHODIMP_(ULONG) CEnumTfDocumentMgr::Release() 1294{ 1295 ULONG ret = InterlockedDecrement(&m_cRefs); 1296 if (!ret) 1297 delete this; 1298 return ret; 1299} 1300 1301STDMETHODIMP CEnumTfDocumentMgr::Clone(_Out_ IEnumTfDocumentMgrs **ppEnum) 1302{ 1303 TRACE("(%p)\n", this); 1304 1305 if (!ppEnum) 1306 return E_POINTER; 1307 1308 *ppEnum = NULL; 1309 1310 CEnumTfDocumentMgr *cloned; 1311 HRESULT hr = CEnumTfDocumentMgr::CreateInstance(m_head, &cloned); 1312 if (SUCCEEDED(hr)) 1313 { 1314 *ppEnum = static_cast<IEnumTfDocumentMgrs *>(cloned); 1315 cloned->m_index = m_index; 1316 } 1317 1318 return hr; 1319} 1320 1321STDMETHODIMP CEnumTfDocumentMgr::Next( 1322 _In_ ULONG ulCount, 1323 _Out_ ITfDocumentMgr **rgDocumentMgr, 1324 _Out_ ULONG *pcFetched) 1325{ 1326 ULONG fetched = 0; 1327 1328 TRACE("(%p)\n", this); 1329 1330 if (!rgDocumentMgr) 1331 return E_POINTER; 1332 1333 while (fetched < ulCount) 1334 { 1335 DocumentMgrEntry *mgrentry; 1336 if (!m_index) 1337 break; 1338 1339 mgrentry = LIST_ENTRY(m_index, DocumentMgrEntry, entry); 1340 if (!mgrentry) 1341 break; 1342 1343 *rgDocumentMgr = mgrentry->docmgr; 1344 (*rgDocumentMgr)->AddRef(); 1345 1346 m_index = list_next(m_head, m_index); 1347 ++fetched; 1348 ++rgDocumentMgr; 1349 } 1350 1351 if (pcFetched) 1352 *pcFetched = fetched; 1353 return fetched == ulCount ? S_OK : S_FALSE; 1354} 1355 1356STDMETHODIMP CEnumTfDocumentMgr::Reset() 1357{ 1358 TRACE("(%p)\n", this); 1359 m_index = list_head(m_head); 1360 return S_OK; 1361} 1362 1363STDMETHODIMP CEnumTfDocumentMgr::Skip(_In_ ULONG ulCount) 1364{ 1365 TRACE("(%p)\n", this); 1366 for (ULONG i = 0; i < ulCount && m_index; ++i) 1367 m_index = list_next(m_head, m_index); 1368 return S_OK; 1369} 1370 1371HRESULT CEnumTfDocumentMgr::CreateInstance(struct list* head, CEnumTfDocumentMgr **ppOut) 1372{ 1373 CEnumTfDocumentMgr *This = new(cicNoThrow) CEnumTfDocumentMgr(); 1374 if (!This) 1375 return E_OUTOFMEMORY; 1376 1377 This->m_head = head; 1378 This->m_index = list_head(This->m_head); 1379 1380 *ppOut = This; 1381 TRACE("returning %p\n", *ppOut); 1382 return S_OK; 1383} 1384 1385//////////////////////////////////////////////////////////////////////////// 1386 1387EXTERN_C 1388HRESULT ThreadMgr_Constructor(IUnknown *pUnkOuter, IUnknown **ppOut) 1389{ 1390 return CThreadMgr::CreateInstance(pUnkOuter, (CThreadMgr **)ppOut); 1391} 1392 1393EXTERN_C 1394void ThreadMgr_OnDocumentMgrDestruction(ITfThreadMgr *iface, ITfDocumentMgr *mgr) 1395{ 1396 CThreadMgr *This = static_cast<CThreadMgr *>(iface); 1397 This->OnDocumentMgrDestruction(mgr); 1398}