2 * ITfThreadMgr implementation
4 * Copyright 2008 Aric Stewart, CodeWeavers
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
27 #include "wine/debug.h"
37 #include "wine/unicode.h"
38 #include "wine/list.h"
41 #include "msctf_internal.h"
43 WINE_DEFAULT_DEBUG_CHANNEL(msctf);
45 typedef struct tagThreadMgrSink {
50 /* ITfActiveLanguageProfileNotifySink *pITfActiveLanguageProfileNotifySink; */
51 /* ITfDisplayAttributeNotifySink *pITfDisplayAttributeNotifySink; */
52 /* ITfKeyTraceEventSink *pITfKeyTraceEventSink; */
53 /* ITfPreservedKeyNotifySink *pITfPreservedKeyNotifySink; */
54 /* ITfThreadFocusSink *pITfThreadFocusSink; */
55 ITfThreadMgrEventSink *pITfThreadMgrEventSink;
59 typedef struct tagPreservedKey
63 TF_PRESERVEDKEY prekey;
68 typedef struct tagDocumentMgrs
71 ITfDocumentMgr *docmgr;
74 typedef struct tagAssociatedWindow
78 ITfDocumentMgr *docmgr;
81 typedef struct tagACLMulti {
82 const ITfThreadMgrVtbl *ThreadMgrVtbl;
83 const ITfSourceVtbl *SourceVtbl;
84 const ITfKeystrokeMgrVtbl *KeystrokeMgrVtbl;
85 const ITfMessagePumpVtbl *MessagePumpVtbl;
86 const ITfClientIdVtbl *ClientIdVtbl;
87 /* const ITfThreadMgrExVtbl *ThreadMgrExVtbl; */
88 /* const ITfConfigureSystemKeystrokeFeedVtbl *ConfigureSystemKeystrokeFeedVtbl; */
89 /* const ITfLangBarItemMgrVtbl *LangBarItemMgrVtbl; */
90 /* const ITfUIElementMgrVtbl *UIElementMgrVtbl; */
91 const ITfSourceSingleVtbl *SourceSingleVtbl;
95 ITfCompartmentMgr *CompartmentMgr;
97 const ITfThreadMgrEventSinkVtbl *ThreadMgrEventSinkVtbl; /* internal */
99 ITfDocumentMgr *focus;
100 LONG activationCount;
102 ITfKeyEventSink *forgroundKeyEventSink;
103 CLSID forgroundTextService;
105 struct list CurrentPreservedKeys;
106 struct list CreatedDocumentMgrs;
108 struct list AssociatedFocusWindows;
111 /* kept as separate lists to reduce unnecessary iterations */
112 struct list ActiveLanguageProfileNotifySink;
113 struct list DisplayAttributeNotifySink;
114 struct list KeyTraceEventSink;
115 struct list PreservedKeyNotifySink;
116 struct list ThreadFocusSink;
117 struct list ThreadMgrEventSink;
120 typedef struct tagEnumTfDocumentMgr {
121 const IEnumTfDocumentMgrsVtbl *Vtbl;
128 static HRESULT EnumTfDocumentMgr_Constructor(struct list* head, IEnumTfDocumentMgrs **ppOut);
130 static inline ThreadMgr *impl_from_ITfSourceVtbl(ITfSource *iface)
132 return (ThreadMgr *)((char *)iface - FIELD_OFFSET(ThreadMgr,SourceVtbl));
135 static inline ThreadMgr *impl_from_ITfKeystrokeMgrVtbl(ITfKeystrokeMgr *iface)
137 return (ThreadMgr *)((char *)iface - FIELD_OFFSET(ThreadMgr,KeystrokeMgrVtbl));
140 static inline ThreadMgr *impl_from_ITfMessagePumpVtbl(ITfMessagePump *iface)
142 return (ThreadMgr *)((char *)iface - FIELD_OFFSET(ThreadMgr,MessagePumpVtbl));
145 static inline ThreadMgr *impl_from_ITfClientIdVtbl(ITfClientId *iface)
147 return (ThreadMgr *)((char *)iface - FIELD_OFFSET(ThreadMgr,ClientIdVtbl));
150 static inline ThreadMgr *impl_from_ITfThreadMgrEventSink(ITfThreadMgrEventSink *iface)
152 return (ThreadMgr *)((char *)iface - FIELD_OFFSET(ThreadMgr,ThreadMgrEventSinkVtbl));
155 static inline ThreadMgr *impl_from_ITfSourceSingleVtbl(ITfSourceSingle* iface)
158 return (ThreadMgr *)((char *)iface - FIELD_OFFSET(ThreadMgr,SourceSingleVtbl));
161 static void free_sink(ThreadMgrSink *sink)
163 IUnknown_Release(sink->interfaces.pIUnknown);
164 HeapFree(GetProcessHeap(),0,sink);
167 static void ThreadMgr_Destructor(ThreadMgr *This)
169 struct list *cursor, *cursor2;
171 /* unhook right away */
173 UnhookWindowsHookEx(This->focusHook);
175 TlsSetValue(tlsIndex,NULL);
176 TRACE("destroying %p\n", This);
178 ITfDocumentMgr_Release(This->focus);
181 LIST_FOR_EACH_SAFE(cursor, cursor2, &This->ActiveLanguageProfileNotifySink)
183 ThreadMgrSink* sink = LIST_ENTRY(cursor,ThreadMgrSink,entry);
187 LIST_FOR_EACH_SAFE(cursor, cursor2, &This->DisplayAttributeNotifySink)
189 ThreadMgrSink* sink = LIST_ENTRY(cursor,ThreadMgrSink,entry);
193 LIST_FOR_EACH_SAFE(cursor, cursor2, &This->KeyTraceEventSink)
195 ThreadMgrSink* sink = LIST_ENTRY(cursor,ThreadMgrSink,entry);
199 LIST_FOR_EACH_SAFE(cursor, cursor2, &This->PreservedKeyNotifySink)
201 ThreadMgrSink* sink = LIST_ENTRY(cursor,ThreadMgrSink,entry);
205 LIST_FOR_EACH_SAFE(cursor, cursor2, &This->ThreadFocusSink)
207 ThreadMgrSink* sink = LIST_ENTRY(cursor,ThreadMgrSink,entry);
211 LIST_FOR_EACH_SAFE(cursor, cursor2, &This->ThreadMgrEventSink)
213 ThreadMgrSink* sink = LIST_ENTRY(cursor,ThreadMgrSink,entry);
218 LIST_FOR_EACH_SAFE(cursor, cursor2, &This->CurrentPreservedKeys)
220 PreservedKey* key = LIST_ENTRY(cursor,PreservedKey,entry);
222 HeapFree(GetProcessHeap(),0,key->description);
223 HeapFree(GetProcessHeap(),0,key);
226 LIST_FOR_EACH_SAFE(cursor, cursor2, &This->CreatedDocumentMgrs)
228 DocumentMgrEntry *mgr = LIST_ENTRY(cursor,DocumentMgrEntry,entry);
230 FIXME("Left Over ITfDocumentMgr. Should we do something with it?\n");
231 HeapFree(GetProcessHeap(),0,mgr);
234 LIST_FOR_EACH_SAFE(cursor, cursor2, &This->AssociatedFocusWindows)
236 AssociatedWindow *wnd = LIST_ENTRY(cursor,AssociatedWindow,entry);
238 HeapFree(GetProcessHeap(),0,wnd);
241 CompartmentMgr_Destructor(This->CompartmentMgr);
243 HeapFree(GetProcessHeap(),0,This);
246 static HRESULT WINAPI ThreadMgr_QueryInterface(ITfThreadMgr *iface, REFIID iid, LPVOID *ppvOut)
248 ThreadMgr *This = (ThreadMgr *)iface;
251 if (IsEqualIID(iid, &IID_IUnknown) || IsEqualIID(iid, &IID_ITfThreadMgr))
255 else if (IsEqualIID(iid, &IID_ITfSource))
257 *ppvOut = &This->SourceVtbl;
259 else if (IsEqualIID(iid, &IID_ITfKeystrokeMgr))
261 *ppvOut = &This->KeystrokeMgrVtbl;
263 else if (IsEqualIID(iid, &IID_ITfMessagePump))
265 *ppvOut = &This->MessagePumpVtbl;
267 else if (IsEqualIID(iid, &IID_ITfClientId))
269 *ppvOut = &This->ClientIdVtbl;
271 else if (IsEqualIID(iid, &IID_ITfCompartmentMgr))
273 *ppvOut = This->CompartmentMgr;
275 else if (IsEqualIID(iid, &IID_ITfSourceSingle))
277 *ppvOut = &This->SourceSingleVtbl;
282 IUnknown_AddRef(iface);
286 WARN("unsupported interface: %s\n", debugstr_guid(iid));
287 return E_NOINTERFACE;
290 static ULONG WINAPI ThreadMgr_AddRef(ITfThreadMgr *iface)
292 ThreadMgr *This = (ThreadMgr *)iface;
293 return InterlockedIncrement(&This->refCount);
296 static ULONG WINAPI ThreadMgr_Release(ITfThreadMgr *iface)
298 ThreadMgr *This = (ThreadMgr *)iface;
301 ret = InterlockedDecrement(&This->refCount);
303 ThreadMgr_Destructor(This);
307 /*****************************************************
308 * ITfThreadMgr functions
309 *****************************************************/
311 static HRESULT WINAPI ThreadMgr_fnActivate( ITfThreadMgr* iface, TfClientId *ptid)
313 ThreadMgr *This = (ThreadMgr *)iface;
315 TRACE("(%p) %p\n",This, ptid);
324 ITfClientId_GetClientId((ITfClientId*)&This->ClientIdVtbl,&guid,&processId);
327 activate_textservices(iface);
328 This->activationCount++;
333 static HRESULT WINAPI ThreadMgr_fnDeactivate( ITfThreadMgr* iface)
335 ThreadMgr *This = (ThreadMgr *)iface;
336 TRACE("(%p)\n",This);
338 if (This->activationCount == 0)
341 This->activationCount --;
343 if (This->activationCount == 0)
347 ITfThreadMgrEventSink_OnSetFocus((ITfThreadMgrEventSink*)&This->ThreadMgrEventSinkVtbl, 0, This->focus);
348 ITfDocumentMgr_Release(This->focus);
353 deactivate_textservices();
358 static HRESULT WINAPI ThreadMgr_CreateDocumentMgr( ITfThreadMgr* iface, ITfDocumentMgr
361 ThreadMgr *This = (ThreadMgr *)iface;
362 DocumentMgrEntry *mgrentry;
365 TRACE("(%p)\n",iface);
366 mgrentry = HeapAlloc(GetProcessHeap(),0,sizeof(DocumentMgrEntry));
367 if (mgrentry == NULL)
368 return E_OUTOFMEMORY;
370 hr = DocumentMgr_Constructor((ITfThreadMgrEventSink*)&This->ThreadMgrEventSinkVtbl, ppdim);
374 mgrentry->docmgr = *ppdim;
375 list_add_head(&This->CreatedDocumentMgrs,&mgrentry->entry);
378 HeapFree(GetProcessHeap(),0,mgrentry);
383 static HRESULT WINAPI ThreadMgr_EnumDocumentMgrs( ITfThreadMgr* iface, IEnumTfDocumentMgrs
386 ThreadMgr *This = (ThreadMgr *)iface;
387 TRACE("(%p) %p\n",This,ppEnum);
392 return EnumTfDocumentMgr_Constructor(&This->CreatedDocumentMgrs, ppEnum);
395 static HRESULT WINAPI ThreadMgr_GetFocus( ITfThreadMgr* iface, ITfDocumentMgr
398 ThreadMgr *This = (ThreadMgr *)iface;
399 TRACE("(%p)\n",This);
404 *ppdimFocus = This->focus;
406 TRACE("->%p\n",This->focus);
408 if (This->focus == NULL)
411 ITfDocumentMgr_AddRef(This->focus);
416 static HRESULT WINAPI ThreadMgr_SetFocus( ITfThreadMgr* iface, ITfDocumentMgr *pdimFocus)
418 ITfDocumentMgr *check;
419 ThreadMgr *This = (ThreadMgr *)iface;
421 TRACE("(%p) %p\n",This,pdimFocus);
425 else if (FAILED(IUnknown_QueryInterface(pdimFocus,&IID_ITfDocumentMgr,(LPVOID*) &check)))
428 ITfThreadMgrEventSink_OnSetFocus((ITfThreadMgrEventSink*)&This->ThreadMgrEventSinkVtbl, check, This->focus);
431 ITfDocumentMgr_Release(This->focus);
437 static LRESULT CALLBACK ThreadFocusHookProc(int nCode, WPARAM wParam, LPARAM lParam)
441 This = TlsGetValue(tlsIndex);
444 ERR("Hook proc but no ThreadMgr for this thread. Serious Error\n");
447 if (!This->focusHook)
449 ERR("Hook proc but no ThreadMgr focus Hook. Serious Error\n");
453 if (nCode == HCBT_SETFOCUS) /* focus change within our thread */
457 LIST_FOR_EACH(cursor, &This->AssociatedFocusWindows)
459 AssociatedWindow *wnd = LIST_ENTRY(cursor,AssociatedWindow,entry);
460 if (wnd->hwnd == (HWND)wParam)
462 TRACE("Triggering Associated window focus\n");
463 if (This->focus != wnd->docmgr)
464 ThreadMgr_SetFocus((ITfThreadMgr*)This, wnd->docmgr);
470 return CallNextHookEx(This->focusHook, nCode, wParam, lParam);
473 static HRESULT SetupWindowsHook(ThreadMgr *This)
475 if (!This->focusHook)
477 This->focusHook = SetWindowsHookExW(WH_CBT, ThreadFocusHookProc, 0,
478 GetCurrentThreadId());
479 if (!This->focusHook)
481 ERR("Unable to set focus hook\n");
489 static HRESULT WINAPI ThreadMgr_AssociateFocus( ITfThreadMgr* iface, HWND hwnd,
490 ITfDocumentMgr *pdimNew, ITfDocumentMgr **ppdimPrev)
492 struct list *cursor, *cursor2;
493 ThreadMgr *This = (ThreadMgr *)iface;
494 AssociatedWindow *wnd;
496 TRACE("(%p) %p %p %p\n",This,hwnd,pdimNew,ppdimPrev);
503 LIST_FOR_EACH_SAFE(cursor, cursor2, &This->AssociatedFocusWindows)
505 wnd = LIST_ENTRY(cursor,AssociatedWindow,entry);
506 if (wnd->hwnd == hwnd)
509 ITfDocumentMgr_AddRef(wnd->docmgr);
510 *ppdimPrev = wnd->docmgr;
511 wnd->docmgr = pdimNew;
512 if (GetFocus() == hwnd)
513 ThreadMgr_SetFocus(iface,pdimNew);
518 wnd = HeapAlloc(GetProcessHeap(),0,sizeof(AssociatedWindow));
520 wnd->docmgr = pdimNew;
521 list_add_head(&This->AssociatedFocusWindows,&wnd->entry);
523 if (GetFocus() == hwnd)
524 ThreadMgr_SetFocus(iface,pdimNew);
526 SetupWindowsHook(This);
531 static HRESULT WINAPI ThreadMgr_IsThreadFocus( ITfThreadMgr* iface, BOOL *pfThreadFocus)
534 ThreadMgr *This = (ThreadMgr *)iface;
535 TRACE("(%p) %p\n",This,pfThreadFocus);
537 *pfThreadFocus = (focus == NULL);
541 static HRESULT WINAPI ThreadMgr_GetFunctionProvider( ITfThreadMgr* iface, REFCLSID clsid,
542 ITfFunctionProvider **ppFuncProv)
544 ThreadMgr *This = (ThreadMgr *)iface;
545 FIXME("STUB:(%p)\n",This);
549 static HRESULT WINAPI ThreadMgr_EnumFunctionProviders( ITfThreadMgr* iface,
550 IEnumTfFunctionProviders **ppEnum)
552 ThreadMgr *This = (ThreadMgr *)iface;
553 FIXME("STUB:(%p)\n",This);
557 static HRESULT WINAPI ThreadMgr_GetGlobalCompartment( ITfThreadMgr* iface,
558 ITfCompartmentMgr **ppCompMgr)
560 ThreadMgr *This = (ThreadMgr *)iface;
562 TRACE("(%p) %p\n",This, ppCompMgr);
567 if (!globalCompartmentMgr)
569 hr = CompartmentMgr_Constructor(NULL,&IID_ITfCompartmentMgr,(IUnknown**)&globalCompartmentMgr);
574 ITfCompartmentMgr_AddRef(globalCompartmentMgr);
575 *ppCompMgr = globalCompartmentMgr;
579 static const ITfThreadMgrVtbl ThreadMgr_ThreadMgrVtbl =
581 ThreadMgr_QueryInterface,
585 ThreadMgr_fnActivate,
586 ThreadMgr_fnDeactivate,
587 ThreadMgr_CreateDocumentMgr,
588 ThreadMgr_EnumDocumentMgrs,
591 ThreadMgr_AssociateFocus,
592 ThreadMgr_IsThreadFocus,
593 ThreadMgr_GetFunctionProvider,
594 ThreadMgr_EnumFunctionProviders,
595 ThreadMgr_GetGlobalCompartment
599 static HRESULT WINAPI Source_QueryInterface(ITfSource *iface, REFIID iid, LPVOID *ppvOut)
601 ThreadMgr *This = impl_from_ITfSourceVtbl(iface);
602 return ThreadMgr_QueryInterface((ITfThreadMgr *)This, iid, *ppvOut);
605 static ULONG WINAPI Source_AddRef(ITfSource *iface)
607 ThreadMgr *This = impl_from_ITfSourceVtbl(iface);
608 return ThreadMgr_AddRef((ITfThreadMgr*)This);
611 static ULONG WINAPI Source_Release(ITfSource *iface)
613 ThreadMgr *This = impl_from_ITfSourceVtbl(iface);
614 return ThreadMgr_Release((ITfThreadMgr *)This);
617 /*****************************************************
618 * ITfSource functions
619 *****************************************************/
620 static HRESULT WINAPI ThreadMgrSource_AdviseSink(ITfSource *iface,
621 REFIID riid, IUnknown *punk, DWORD *pdwCookie)
624 ThreadMgr *This = impl_from_ITfSourceVtbl(iface);
626 TRACE("(%p) %s %p %p\n",This,debugstr_guid(riid),punk,pdwCookie);
628 if (!riid || !punk || !pdwCookie)
631 if (IsEqualIID(riid, &IID_ITfThreadMgrEventSink))
633 tms = HeapAlloc(GetProcessHeap(),0,sizeof(ThreadMgrSink));
635 return E_OUTOFMEMORY;
636 if (FAILED(IUnknown_QueryInterface(punk, riid, (LPVOID *)&tms->interfaces.pITfThreadMgrEventSink)))
638 HeapFree(GetProcessHeap(),0,tms);
639 return CONNECT_E_CANNOTCONNECT;
641 list_add_head(&This->ThreadMgrEventSink,&tms->entry);
642 *pdwCookie = generate_Cookie(COOKIE_MAGIC_TMSINK, tms);
646 FIXME("(%p) Unhandled Sink: %s\n",This,debugstr_guid(riid));
650 TRACE("cookie %x\n",*pdwCookie);
655 static HRESULT WINAPI ThreadMgrSource_UnadviseSink(ITfSource *iface, DWORD pdwCookie)
658 ThreadMgr *This = impl_from_ITfSourceVtbl(iface);
660 TRACE("(%p) %x\n",This,pdwCookie);
662 if (get_Cookie_magic(pdwCookie)!=COOKIE_MAGIC_TMSINK)
665 sink = (ThreadMgrSink*)remove_Cookie(pdwCookie);
667 return CONNECT_E_NOCONNECTION;
669 list_remove(&sink->entry);
675 static const ITfSourceVtbl ThreadMgr_SourceVtbl =
677 Source_QueryInterface,
681 ThreadMgrSource_AdviseSink,
682 ThreadMgrSource_UnadviseSink,
685 /*****************************************************
686 * ITfKeystrokeMgr functions
687 *****************************************************/
689 static HRESULT WINAPI KeystrokeMgr_QueryInterface(ITfKeystrokeMgr *iface, REFIID iid, LPVOID *ppvOut)
691 ThreadMgr *This = impl_from_ITfKeystrokeMgrVtbl(iface);
692 return ThreadMgr_QueryInterface((ITfThreadMgr *)This, iid, *ppvOut);
695 static ULONG WINAPI KeystrokeMgr_AddRef(ITfKeystrokeMgr *iface)
697 ThreadMgr *This = impl_from_ITfKeystrokeMgrVtbl(iface);
698 return ThreadMgr_AddRef((ITfThreadMgr*)This);
701 static ULONG WINAPI KeystrokeMgr_Release(ITfKeystrokeMgr *iface)
703 ThreadMgr *This = impl_from_ITfKeystrokeMgrVtbl(iface);
704 return ThreadMgr_Release((ITfThreadMgr *)This);
707 static HRESULT WINAPI KeystrokeMgr_AdviseKeyEventSink(ITfKeystrokeMgr *iface,
708 TfClientId tid, ITfKeyEventSink *pSink, BOOL fForeground)
710 ThreadMgr *This = impl_from_ITfKeystrokeMgrVtbl(iface);
712 ITfKeyEventSink *check = NULL;
714 TRACE("(%p) %x %p %i\n",This,tid,pSink,fForeground);
719 textservice = get_textservice_clsid(tid);
720 if (IsEqualCLSID(&GUID_NULL,&textservice))
723 get_textservice_sink(tid, &IID_ITfKeyEventSink, (IUnknown**)&check);
725 return CONNECT_E_ADVISELIMIT;
727 if (FAILED(IUnknown_QueryInterface(pSink,&IID_ITfKeyEventSink,(LPVOID*) &check)))
730 set_textservice_sink(tid, &IID_ITfKeyEventSink, (IUnknown*)check);
734 if (This->forgroundKeyEventSink)
736 ITfKeyEventSink_OnSetFocus(This->forgroundKeyEventSink, FALSE);
737 ITfKeyEventSink_Release(This->forgroundKeyEventSink);
739 ITfKeyEventSink_AddRef(check);
740 ITfKeyEventSink_OnSetFocus(check, TRUE);
741 This->forgroundKeyEventSink = check;
742 This->forgroundTextService = textservice;
747 static HRESULT WINAPI KeystrokeMgr_UnadviseKeyEventSink(ITfKeystrokeMgr *iface,
750 ThreadMgr *This = impl_from_ITfKeystrokeMgrVtbl(iface);
752 ITfKeyEventSink *check = NULL;
753 TRACE("(%p) %x\n",This,tid);
758 textservice = get_textservice_clsid(tid);
759 if (IsEqualCLSID(&GUID_NULL,&textservice))
762 get_textservice_sink(tid, &IID_ITfKeyEventSink, (IUnknown**)&check);
765 return CONNECT_E_NOCONNECTION;
767 set_textservice_sink(tid, &IID_ITfKeyEventSink, NULL);
768 ITfKeyEventSink_Release(check);
770 if (This->forgroundKeyEventSink == check)
772 ITfKeyEventSink_Release(This->forgroundKeyEventSink);
773 This->forgroundKeyEventSink = NULL;
774 This->forgroundTextService = GUID_NULL;
779 static HRESULT WINAPI KeystrokeMgr_GetForeground(ITfKeystrokeMgr *iface,
782 ThreadMgr *This = impl_from_ITfKeystrokeMgrVtbl(iface);
783 TRACE("(%p) %p\n",This,pclsid);
787 if (IsEqualCLSID(&This->forgroundTextService,&GUID_NULL))
790 *pclsid = This->forgroundTextService;
794 static HRESULT WINAPI KeystrokeMgr_TestKeyDown(ITfKeystrokeMgr *iface,
795 WPARAM wParam, LPARAM lParam, BOOL *pfEaten)
797 ThreadMgr *This = impl_from_ITfKeystrokeMgrVtbl(iface);
798 FIXME("STUB:(%p)\n",This);
802 static HRESULT WINAPI KeystrokeMgr_TestKeyUp(ITfKeystrokeMgr *iface,
803 WPARAM wParam, LPARAM lParam, BOOL *pfEaten)
805 ThreadMgr *This = impl_from_ITfKeystrokeMgrVtbl(iface);
806 FIXME("STUB:(%p)\n",This);
810 static HRESULT WINAPI KeystrokeMgr_KeyDown(ITfKeystrokeMgr *iface,
811 WPARAM wParam, LPARAM lParam, BOOL *pfEaten)
813 ThreadMgr *This = impl_from_ITfKeystrokeMgrVtbl(iface);
814 FIXME("STUB:(%p)\n",This);
818 static HRESULT WINAPI KeystrokeMgr_KeyUp(ITfKeystrokeMgr *iface,
819 WPARAM wParam, LPARAM lParam, BOOL *pfEaten)
821 ThreadMgr *This = impl_from_ITfKeystrokeMgrVtbl(iface);
822 FIXME("STUB:(%p)\n",This);
826 static HRESULT WINAPI KeystrokeMgr_GetPreservedKey(ITfKeystrokeMgr *iface,
827 ITfContext *pic, const TF_PRESERVEDKEY *pprekey, GUID *pguid)
829 ThreadMgr *This = impl_from_ITfKeystrokeMgrVtbl(iface);
830 FIXME("STUB:(%p)\n",This);
834 static HRESULT WINAPI KeystrokeMgr_IsPreservedKey(ITfKeystrokeMgr *iface,
835 REFGUID rguid, const TF_PRESERVEDKEY *pprekey, BOOL *pfRegistered)
837 ThreadMgr *This = impl_from_ITfKeystrokeMgrVtbl(iface);
840 TRACE("(%p) %s (%x %x) %p\n",This,debugstr_guid(rguid), (pprekey)?pprekey->uVKey:0, (pprekey)?pprekey->uModifiers:0, pfRegistered);
842 if (!rguid || !pprekey || !pfRegistered)
845 LIST_FOR_EACH(cursor, &This->CurrentPreservedKeys)
847 PreservedKey* key = LIST_ENTRY(cursor,PreservedKey,entry);
848 if (IsEqualGUID(rguid,&key->guid) && pprekey->uVKey == key->prekey.uVKey && pprekey->uModifiers == key->prekey.uModifiers)
850 *pfRegistered = TRUE;
855 *pfRegistered = FALSE;
859 static HRESULT WINAPI KeystrokeMgr_PreserveKey(ITfKeystrokeMgr *iface,
860 TfClientId tid, REFGUID rguid, const TF_PRESERVEDKEY *prekey,
861 const WCHAR *pchDesc, ULONG cchDesc)
863 ThreadMgr *This = impl_from_ITfKeystrokeMgrVtbl(iface);
865 PreservedKey *newkey;
867 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));
869 if (!tid || ! rguid || !prekey || (cchDesc && !pchDesc))
872 LIST_FOR_EACH(cursor, &This->CurrentPreservedKeys)
874 PreservedKey* key = LIST_ENTRY(cursor,PreservedKey,entry);
875 if (IsEqualGUID(rguid,&key->guid) && prekey->uVKey == key->prekey.uVKey && prekey->uModifiers == key->prekey.uModifiers)
876 return TF_E_ALREADY_EXISTS;
879 newkey = HeapAlloc(GetProcessHeap(),0,sizeof(PreservedKey));
881 return E_OUTOFMEMORY;
883 newkey->guid = *rguid;
884 newkey->prekey = *prekey;
886 newkey->description = NULL;
889 newkey->description = HeapAlloc(GetProcessHeap(),0,cchDesc * sizeof(WCHAR));
890 if (!newkey->description)
892 HeapFree(GetProcessHeap(),0,newkey);
893 return E_OUTOFMEMORY;
895 memcpy(newkey->description, pchDesc, cchDesc*sizeof(WCHAR));
898 list_add_head(&This->CurrentPreservedKeys,&newkey->entry);
903 static HRESULT WINAPI KeystrokeMgr_UnpreserveKey(ITfKeystrokeMgr *iface,
904 REFGUID rguid, const TF_PRESERVEDKEY *pprekey)
906 ThreadMgr *This = impl_from_ITfKeystrokeMgrVtbl(iface);
907 PreservedKey* key = NULL;
909 TRACE("(%p) %s (%x %x)\n",This,debugstr_guid(rguid),(pprekey)?pprekey->uVKey:0, (pprekey)?pprekey->uModifiers:0);
911 if (!pprekey || !rguid)
914 LIST_FOR_EACH(cursor, &This->CurrentPreservedKeys)
916 key = LIST_ENTRY(cursor,PreservedKey,entry);
917 if (IsEqualGUID(rguid,&key->guid) && pprekey->uVKey == key->prekey.uVKey && pprekey->uModifiers == key->prekey.uModifiers)
923 return CONNECT_E_NOCONNECTION;
925 list_remove(&key->entry);
926 HeapFree(GetProcessHeap(),0,key->description);
927 HeapFree(GetProcessHeap(),0,key);
932 static HRESULT WINAPI KeystrokeMgr_SetPreservedKeyDescription(ITfKeystrokeMgr *iface,
933 REFGUID rguid, const WCHAR *pchDesc, ULONG cchDesc)
935 ThreadMgr *This = impl_from_ITfKeystrokeMgrVtbl(iface);
936 FIXME("STUB:(%p)\n",This);
940 static HRESULT WINAPI KeystrokeMgr_GetPreservedKeyDescription(ITfKeystrokeMgr *iface,
941 REFGUID rguid, BSTR *pbstrDesc)
943 ThreadMgr *This = impl_from_ITfKeystrokeMgrVtbl(iface);
944 FIXME("STUB:(%p)\n",This);
948 static HRESULT WINAPI KeystrokeMgr_SimulatePreservedKey(ITfKeystrokeMgr *iface,
949 ITfContext *pic, REFGUID rguid, BOOL *pfEaten)
951 ThreadMgr *This = impl_from_ITfKeystrokeMgrVtbl(iface);
952 FIXME("STUB:(%p)\n",This);
956 static const ITfKeystrokeMgrVtbl ThreadMgr_KeystrokeMgrVtbl =
958 KeystrokeMgr_QueryInterface,
960 KeystrokeMgr_Release,
962 KeystrokeMgr_AdviseKeyEventSink,
963 KeystrokeMgr_UnadviseKeyEventSink,
964 KeystrokeMgr_GetForeground,
965 KeystrokeMgr_TestKeyDown,
966 KeystrokeMgr_TestKeyUp,
967 KeystrokeMgr_KeyDown,
969 KeystrokeMgr_GetPreservedKey,
970 KeystrokeMgr_IsPreservedKey,
971 KeystrokeMgr_PreserveKey,
972 KeystrokeMgr_UnpreserveKey,
973 KeystrokeMgr_SetPreservedKeyDescription,
974 KeystrokeMgr_GetPreservedKeyDescription,
975 KeystrokeMgr_SimulatePreservedKey
978 /*****************************************************
979 * ITfMessagePump functions
980 *****************************************************/
982 static HRESULT WINAPI MessagePump_QueryInterface(ITfMessagePump *iface, REFIID iid, LPVOID *ppvOut)
984 ThreadMgr *This = impl_from_ITfMessagePumpVtbl(iface);
985 return ThreadMgr_QueryInterface((ITfThreadMgr *)This, iid, *ppvOut);
988 static ULONG WINAPI MessagePump_AddRef(ITfMessagePump *iface)
990 ThreadMgr *This = impl_from_ITfMessagePumpVtbl(iface);
991 return ThreadMgr_AddRef((ITfThreadMgr*)This);
994 static ULONG WINAPI MessagePump_Release(ITfMessagePump *iface)
996 ThreadMgr *This = impl_from_ITfMessagePumpVtbl(iface);
997 return ThreadMgr_Release((ITfThreadMgr *)This);
1000 static HRESULT WINAPI MessagePump_PeekMessageA(ITfMessagePump *iface,
1001 LPMSG pMsg, HWND hwnd, UINT wMsgFilterMin, UINT wMsgFilterMax,
1002 UINT wRemoveMsg, BOOL *pfResult)
1005 return E_INVALIDARG;
1006 *pfResult = PeekMessageA(pMsg, hwnd, wMsgFilterMin, wMsgFilterMax, wRemoveMsg);
1010 static HRESULT WINAPI MessagePump_GetMessageA(ITfMessagePump *iface,
1011 LPMSG pMsg, HWND hwnd, UINT wMsgFilterMin, UINT wMsgFilterMax,
1015 return E_INVALIDARG;
1016 *pfResult = GetMessageA(pMsg, hwnd, wMsgFilterMin, wMsgFilterMax);
1020 static HRESULT WINAPI MessagePump_PeekMessageW(ITfMessagePump *iface,
1021 LPMSG pMsg, HWND hwnd, UINT wMsgFilterMin, UINT wMsgFilterMax,
1022 UINT wRemoveMsg, BOOL *pfResult)
1025 return E_INVALIDARG;
1026 *pfResult = PeekMessageW(pMsg, hwnd, wMsgFilterMin, wMsgFilterMax, wRemoveMsg);
1030 static HRESULT WINAPI MessagePump_GetMessageW(ITfMessagePump *iface,
1031 LPMSG pMsg, HWND hwnd, UINT wMsgFilterMin, UINT wMsgFilterMax,
1035 return E_INVALIDARG;
1036 *pfResult = GetMessageW(pMsg, hwnd, wMsgFilterMin, wMsgFilterMax);
1040 static const ITfMessagePumpVtbl ThreadMgr_MessagePumpVtbl =
1042 MessagePump_QueryInterface,
1044 MessagePump_Release,
1046 MessagePump_PeekMessageA,
1047 MessagePump_GetMessageA,
1048 MessagePump_PeekMessageW,
1049 MessagePump_GetMessageW
1052 /*****************************************************
1053 * ITfClientId functions
1054 *****************************************************/
1056 static HRESULT WINAPI ClientId_QueryInterface(ITfClientId *iface, REFIID iid, LPVOID *ppvOut)
1058 ThreadMgr *This = impl_from_ITfClientIdVtbl(iface);
1059 return ThreadMgr_QueryInterface((ITfThreadMgr *)This, iid, *ppvOut);
1062 static ULONG WINAPI ClientId_AddRef(ITfClientId *iface)
1064 ThreadMgr *This = impl_from_ITfClientIdVtbl(iface);
1065 return ThreadMgr_AddRef((ITfThreadMgr*)This);
1068 static ULONG WINAPI ClientId_Release(ITfClientId *iface)
1070 ThreadMgr *This = impl_from_ITfClientIdVtbl(iface);
1071 return ThreadMgr_Release((ITfThreadMgr *)This);
1074 static HRESULT WINAPI ClientId_GetClientId(ITfClientId *iface,
1075 REFCLSID rclsid, TfClientId *ptid)
1079 ITfCategoryMgr *catmgr;
1080 ThreadMgr *This = impl_from_ITfClientIdVtbl(iface);
1082 TRACE("(%p) %s\n",This,debugstr_guid(rclsid));
1084 CategoryMgr_Constructor(NULL,(IUnknown**)&catmgr);
1085 hr = ITfCategoryMgr_RegisterGUID(catmgr,rclsid,ptid);
1086 ITfCategoryMgr_Release(catmgr);
1091 static const ITfClientIdVtbl ThreadMgr_ClientIdVtbl =
1093 ClientId_QueryInterface,
1097 ClientId_GetClientId
1100 /*****************************************************
1101 * ITfThreadMgrEventSink functions (internal)
1102 *****************************************************/
1103 static HRESULT WINAPI ThreadMgrEventSink_QueryInterface(ITfThreadMgrEventSink *iface, REFIID iid, LPVOID *ppvOut)
1105 ThreadMgr *This = impl_from_ITfThreadMgrEventSink(iface);
1106 return ThreadMgr_QueryInterface((ITfThreadMgr *)This, iid, *ppvOut);
1109 static ULONG WINAPI ThreadMgrEventSink_AddRef(ITfThreadMgrEventSink *iface)
1111 ThreadMgr *This = impl_from_ITfThreadMgrEventSink(iface);
1112 return ThreadMgr_AddRef((ITfThreadMgr*)This);
1115 static ULONG WINAPI ThreadMgrEventSink_Release(ITfThreadMgrEventSink *iface)
1117 ThreadMgr *This = impl_from_ITfThreadMgrEventSink(iface);
1118 return ThreadMgr_Release((ITfThreadMgr *)This);
1122 static HRESULT WINAPI ThreadMgrEventSink_OnInitDocumentMgr(
1123 ITfThreadMgrEventSink *iface,ITfDocumentMgr *pdim)
1125 struct list *cursor;
1126 ThreadMgr *This = impl_from_ITfThreadMgrEventSink(iface);
1128 TRACE("(%p) %p\n",This,pdim);
1130 LIST_FOR_EACH(cursor, &This->ThreadMgrEventSink)
1132 ThreadMgrSink* sink = LIST_ENTRY(cursor,ThreadMgrSink,entry);
1133 ITfThreadMgrEventSink_OnInitDocumentMgr(sink->interfaces.pITfThreadMgrEventSink,pdim);
1139 static HRESULT WINAPI ThreadMgrEventSink_OnUninitDocumentMgr(
1140 ITfThreadMgrEventSink *iface, ITfDocumentMgr *pdim)
1142 struct list *cursor;
1143 ThreadMgr *This = impl_from_ITfThreadMgrEventSink(iface);
1145 TRACE("(%p) %p\n",This,pdim);
1147 LIST_FOR_EACH(cursor, &This->ThreadMgrEventSink)
1149 ThreadMgrSink* sink = LIST_ENTRY(cursor,ThreadMgrSink,entry);
1150 ITfThreadMgrEventSink_OnUninitDocumentMgr(sink->interfaces.pITfThreadMgrEventSink,pdim);
1156 static HRESULT WINAPI ThreadMgrEventSink_OnSetFocus(
1157 ITfThreadMgrEventSink *iface, ITfDocumentMgr *pdimFocus,
1158 ITfDocumentMgr *pdimPrevFocus)
1160 struct list *cursor;
1161 ThreadMgr *This = impl_from_ITfThreadMgrEventSink(iface);
1163 TRACE("(%p) %p %p\n",This,pdimFocus, pdimPrevFocus);
1165 LIST_FOR_EACH(cursor, &This->ThreadMgrEventSink)
1167 ThreadMgrSink* sink = LIST_ENTRY(cursor,ThreadMgrSink,entry);
1168 ITfThreadMgrEventSink_OnSetFocus(sink->interfaces.pITfThreadMgrEventSink, pdimFocus, pdimPrevFocus);
1174 static HRESULT WINAPI ThreadMgrEventSink_OnPushContext(
1175 ITfThreadMgrEventSink *iface, ITfContext *pic)
1177 struct list *cursor;
1178 ThreadMgr *This = impl_from_ITfThreadMgrEventSink(iface);
1180 TRACE("(%p) %p\n",This,pic);
1182 LIST_FOR_EACH(cursor, &This->ThreadMgrEventSink)
1184 ThreadMgrSink* sink = LIST_ENTRY(cursor,ThreadMgrSink,entry);
1185 ITfThreadMgrEventSink_OnPushContext(sink->interfaces.pITfThreadMgrEventSink,pic);
1191 static HRESULT WINAPI ThreadMgrEventSink_OnPopContext(
1192 ITfThreadMgrEventSink *iface, ITfContext *pic)
1194 struct list *cursor;
1195 ThreadMgr *This = impl_from_ITfThreadMgrEventSink(iface);
1197 TRACE("(%p) %p\n",This,pic);
1199 LIST_FOR_EACH(cursor, &This->ThreadMgrEventSink)
1201 ThreadMgrSink* sink = LIST_ENTRY(cursor,ThreadMgrSink,entry);
1202 ITfThreadMgrEventSink_OnPopContext(sink->interfaces.pITfThreadMgrEventSink,pic);
1208 static const ITfThreadMgrEventSinkVtbl ThreadMgr_ThreadMgrEventSinkVtbl =
1210 ThreadMgrEventSink_QueryInterface,
1211 ThreadMgrEventSink_AddRef,
1212 ThreadMgrEventSink_Release,
1214 ThreadMgrEventSink_OnInitDocumentMgr,
1215 ThreadMgrEventSink_OnUninitDocumentMgr,
1216 ThreadMgrEventSink_OnSetFocus,
1217 ThreadMgrEventSink_OnPushContext,
1218 ThreadMgrEventSink_OnPopContext
1221 /*****************************************************
1222 * ITfSourceSingle functions
1223 *****************************************************/
1224 static HRESULT WINAPI ThreadMgrSourceSingle_QueryInterface(ITfSourceSingle *iface, REFIID iid, LPVOID *ppvOut)
1226 ThreadMgr *This = impl_from_ITfSourceSingleVtbl(iface);
1227 return ThreadMgr_QueryInterface((ITfThreadMgr *)This, iid, *ppvOut);
1230 static ULONG WINAPI ThreadMgrSourceSingle_AddRef(ITfSourceSingle *iface)
1232 ThreadMgr *This = impl_from_ITfSourceSingleVtbl(iface);
1233 return ThreadMgr_AddRef((ITfThreadMgr *)This);
1236 static ULONG WINAPI ThreadMgrSourceSingle_Release(ITfSourceSingle *iface)
1238 ThreadMgr *This = impl_from_ITfSourceSingleVtbl(iface);
1239 return ThreadMgr_Release((ITfThreadMgr *)This);
1242 static HRESULT WINAPI ThreadMgrSourceSingle_AdviseSingleSink( ITfSourceSingle *iface,
1243 TfClientId tid, REFIID riid, IUnknown *punk)
1245 ThreadMgr *This = impl_from_ITfSourceSingleVtbl(iface);
1246 FIXME("STUB:(%p) %i %s %p\n",This, tid, debugstr_guid(riid),punk);
1250 static HRESULT WINAPI ThreadMgrSourceSingle_UnadviseSingleSink( ITfSourceSingle *iface,
1251 TfClientId tid, REFIID riid)
1253 ThreadMgr *This = impl_from_ITfSourceSingleVtbl(iface);
1254 FIXME("STUB:(%p) %i %s\n",This, tid, debugstr_guid(riid));
1258 static const ITfSourceSingleVtbl ThreadMgr_SourceSingleVtbl =
1260 ThreadMgrSourceSingle_QueryInterface,
1261 ThreadMgrSourceSingle_AddRef,
1262 ThreadMgrSourceSingle_Release,
1264 ThreadMgrSourceSingle_AdviseSingleSink,
1265 ThreadMgrSourceSingle_UnadviseSingleSink,
1268 HRESULT ThreadMgr_Constructor(IUnknown *pUnkOuter, IUnknown **ppOut)
1272 return CLASS_E_NOAGGREGATION;
1274 /* Only 1 ThreadMgr is created per thread */
1275 This = TlsGetValue(tlsIndex);
1278 ThreadMgr_AddRef((ITfThreadMgr*)This);
1279 *ppOut = (IUnknown*)This;
1283 This = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(ThreadMgr));
1285 return E_OUTOFMEMORY;
1287 This->ThreadMgrVtbl= &ThreadMgr_ThreadMgrVtbl;
1288 This->SourceVtbl = &ThreadMgr_SourceVtbl;
1289 This->KeystrokeMgrVtbl= &ThreadMgr_KeystrokeMgrVtbl;
1290 This->MessagePumpVtbl= &ThreadMgr_MessagePumpVtbl;
1291 This->ClientIdVtbl = &ThreadMgr_ClientIdVtbl;
1292 This->ThreadMgrEventSinkVtbl = &ThreadMgr_ThreadMgrEventSinkVtbl;
1293 This->SourceSingleVtbl = &ThreadMgr_SourceSingleVtbl;
1295 TlsSetValue(tlsIndex,This);
1297 CompartmentMgr_Constructor((IUnknown*)This, &IID_IUnknown, (IUnknown**)&This->CompartmentMgr);
1299 list_init(&This->CurrentPreservedKeys);
1300 list_init(&This->CreatedDocumentMgrs);
1301 list_init(&This->AssociatedFocusWindows);
1303 list_init(&This->ActiveLanguageProfileNotifySink);
1304 list_init(&This->DisplayAttributeNotifySink);
1305 list_init(&This->KeyTraceEventSink);
1306 list_init(&This->PreservedKeyNotifySink);
1307 list_init(&This->ThreadFocusSink);
1308 list_init(&This->ThreadMgrEventSink);
1310 TRACE("returning %p\n", This);
1311 *ppOut = (IUnknown *)This;
1315 /**************************************************
1316 * IEnumTfDocumentMgrs implementation
1317 **************************************************/
1318 static void EnumTfDocumentMgr_Destructor(EnumTfDocumentMgr *This)
1320 TRACE("destroying %p\n", This);
1321 HeapFree(GetProcessHeap(),0,This);
1324 static HRESULT WINAPI EnumTfDocumentMgr_QueryInterface(IEnumTfDocumentMgrs *iface, REFIID iid, LPVOID *ppvOut)
1326 EnumTfDocumentMgr *This = (EnumTfDocumentMgr *)iface;
1329 if (IsEqualIID(iid, &IID_IUnknown) || IsEqualIID(iid, &IID_IEnumTfDocumentMgrs))
1336 IUnknown_AddRef(iface);
1340 WARN("unsupported interface: %s\n", debugstr_guid(iid));
1341 return E_NOINTERFACE;
1344 static ULONG WINAPI EnumTfDocumentMgr_AddRef(IEnumTfDocumentMgrs *iface)
1346 EnumTfDocumentMgr *This = (EnumTfDocumentMgr*)iface;
1347 return InterlockedIncrement(&This->refCount);
1350 static ULONG WINAPI EnumTfDocumentMgr_Release(IEnumTfDocumentMgrs *iface)
1352 EnumTfDocumentMgr *This = (EnumTfDocumentMgr *)iface;
1355 ret = InterlockedDecrement(&This->refCount);
1357 EnumTfDocumentMgr_Destructor(This);
1361 static HRESULT WINAPI EnumTfDocumentMgr_Next(IEnumTfDocumentMgrs *iface,
1362 ULONG ulCount, ITfDocumentMgr **rgDocumentMgr, ULONG *pcFetched)
1364 EnumTfDocumentMgr *This = (EnumTfDocumentMgr *)iface;
1367 TRACE("(%p)\n",This);
1369 if (rgDocumentMgr == NULL) return E_POINTER;
1371 while (fetched < ulCount)
1373 DocumentMgrEntry *mgrentry;
1374 if (This->index == NULL)
1377 mgrentry = LIST_ENTRY(This->index,DocumentMgrEntry,entry);
1378 if (mgrentry == NULL)
1381 *rgDocumentMgr = mgrentry->docmgr;
1382 ITfDocumentMgr_AddRef(*rgDocumentMgr);
1384 This->index = list_next(This->head, This->index);
1389 if (pcFetched) *pcFetched = fetched;
1390 return fetched == ulCount ? S_OK : S_FALSE;
1393 static HRESULT WINAPI EnumTfDocumentMgr_Skip( IEnumTfDocumentMgrs* iface, ULONG celt)
1396 EnumTfDocumentMgr *This = (EnumTfDocumentMgr *)iface;
1397 TRACE("(%p)\n",This);
1398 for(i = 0; i < celt && This->index != NULL; i++)
1399 This->index = list_next(This->head, This->index);
1403 static HRESULT WINAPI EnumTfDocumentMgr_Reset( IEnumTfDocumentMgrs* iface)
1405 EnumTfDocumentMgr *This = (EnumTfDocumentMgr *)iface;
1406 TRACE("(%p)\n",This);
1407 This->index = list_head(This->head);
1411 static HRESULT WINAPI EnumTfDocumentMgr_Clone( IEnumTfDocumentMgrs *iface,
1412 IEnumTfDocumentMgrs **ppenum)
1414 EnumTfDocumentMgr *This = (EnumTfDocumentMgr *)iface;
1417 TRACE("(%p)\n",This);
1419 if (ppenum == NULL) return E_POINTER;
1421 res = EnumTfDocumentMgr_Constructor(This->head, ppenum);
1424 EnumTfDocumentMgr *new_This = (EnumTfDocumentMgr *)*ppenum;
1425 new_This->index = This->index;
1430 static const IEnumTfDocumentMgrsVtbl IEnumTfDocumentMgrs_Vtbl ={
1431 EnumTfDocumentMgr_QueryInterface,
1432 EnumTfDocumentMgr_AddRef,
1433 EnumTfDocumentMgr_Release,
1435 EnumTfDocumentMgr_Clone,
1436 EnumTfDocumentMgr_Next,
1437 EnumTfDocumentMgr_Reset,
1438 EnumTfDocumentMgr_Skip
1441 static HRESULT EnumTfDocumentMgr_Constructor(struct list* head, IEnumTfDocumentMgrs **ppOut)
1443 EnumTfDocumentMgr *This;
1445 This = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(EnumTfDocumentMgr));
1447 return E_OUTOFMEMORY;
1449 This->Vtbl= &IEnumTfDocumentMgrs_Vtbl;
1452 This->index = list_head(This->head);
1454 TRACE("returning %p\n", This);
1455 *ppOut = (IEnumTfDocumentMgrs*)This;
1459 void ThreadMgr_OnDocumentMgrDestruction(ITfThreadMgr *tm, ITfDocumentMgr *mgr)
1461 ThreadMgr *This = (ThreadMgr *)tm;
1462 struct list *cursor;
1463 LIST_FOR_EACH(cursor, &This->CreatedDocumentMgrs)
1465 DocumentMgrEntry *mgrentry = LIST_ENTRY(cursor,DocumentMgrEntry,entry);
1466 if (mgrentry->docmgr == mgr)
1468 list_remove(cursor);
1469 HeapFree(GetProcessHeap(),0,mgrentry);
1473 FIXME("ITfDocumentMgr %p not found in this thread\n",mgr);