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
21 #include "msctf_internal.h"
23 typedef struct tagThreadMgrSink
{
28 /* ITfActiveLanguageProfileNotifySink *pITfActiveLanguageProfileNotifySink; */
29 /* ITfDisplayAttributeNotifySink *pITfDisplayAttributeNotifySink; */
30 /* ITfKeyTraceEventSink *pITfKeyTraceEventSink; */
31 /* ITfPreservedKeyNotifySink *pITfPreservedKeyNotifySink; */
32 /* ITfThreadFocusSink *pITfThreadFocusSink; */
33 ITfThreadMgrEventSink
*pITfThreadMgrEventSink
;
37 typedef struct tagPreservedKey
41 TF_PRESERVEDKEY prekey
;
46 typedef struct tagDocumentMgrs
49 ITfDocumentMgr
*docmgr
;
52 typedef struct tagAssociatedWindow
56 ITfDocumentMgr
*docmgr
;
59 typedef struct tagACLMulti
{
60 const ITfThreadMgrVtbl
*ThreadMgrVtbl
;
61 const ITfSourceVtbl
*SourceVtbl
;
62 const ITfKeystrokeMgrVtbl
*KeystrokeMgrVtbl
;
63 const ITfMessagePumpVtbl
*MessagePumpVtbl
;
64 const ITfClientIdVtbl
*ClientIdVtbl
;
65 /* const ITfThreadMgrExVtbl *ThreadMgrExVtbl; */
66 /* const ITfConfigureSystemKeystrokeFeedVtbl *ConfigureSystemKeystrokeFeedVtbl; */
67 /* const ITfLangBarItemMgrVtbl *LangBarItemMgrVtbl; */
68 /* const ITfUIElementMgrVtbl *UIElementMgrVtbl; */
69 const ITfSourceSingleVtbl
*SourceSingleVtbl
;
73 ITfCompartmentMgr
*CompartmentMgr
;
75 const ITfThreadMgrEventSinkVtbl
*ThreadMgrEventSinkVtbl
; /* internal */
77 ITfDocumentMgr
*focus
;
80 ITfKeyEventSink
*forgroundKeyEventSink
;
81 CLSID forgroundTextService
;
83 struct list CurrentPreservedKeys
;
84 struct list CreatedDocumentMgrs
;
86 struct list AssociatedFocusWindows
;
89 /* kept as separate lists to reduce unnecessary iterations */
90 struct list ActiveLanguageProfileNotifySink
;
91 struct list DisplayAttributeNotifySink
;
92 struct list KeyTraceEventSink
;
93 struct list PreservedKeyNotifySink
;
94 struct list ThreadFocusSink
;
95 struct list ThreadMgrEventSink
;
98 typedef struct tagEnumTfDocumentMgr
{
99 const IEnumTfDocumentMgrsVtbl
*Vtbl
;
106 static HRESULT
EnumTfDocumentMgr_Constructor(struct list
* head
, IEnumTfDocumentMgrs
**ppOut
);
108 static inline ThreadMgr
*impl_from_ITfSourceVtbl(ITfSource
*iface
)
110 return (ThreadMgr
*)((char *)iface
- FIELD_OFFSET(ThreadMgr
,SourceVtbl
));
113 static inline ThreadMgr
*impl_from_ITfKeystrokeMgrVtbl(ITfKeystrokeMgr
*iface
)
115 return (ThreadMgr
*)((char *)iface
- FIELD_OFFSET(ThreadMgr
,KeystrokeMgrVtbl
));
118 static inline ThreadMgr
*impl_from_ITfMessagePumpVtbl(ITfMessagePump
*iface
)
120 return (ThreadMgr
*)((char *)iface
- FIELD_OFFSET(ThreadMgr
,MessagePumpVtbl
));
123 static inline ThreadMgr
*impl_from_ITfClientIdVtbl(ITfClientId
*iface
)
125 return (ThreadMgr
*)((char *)iface
- FIELD_OFFSET(ThreadMgr
,ClientIdVtbl
));
128 static inline ThreadMgr
*impl_from_ITfThreadMgrEventSink(ITfThreadMgrEventSink
*iface
)
130 return (ThreadMgr
*)((char *)iface
- FIELD_OFFSET(ThreadMgr
,ThreadMgrEventSinkVtbl
));
133 static inline ThreadMgr
*impl_from_ITfSourceSingleVtbl(ITfSourceSingle
* iface
)
136 return (ThreadMgr
*)((char *)iface
- FIELD_OFFSET(ThreadMgr
,SourceSingleVtbl
));
139 static void free_sink(ThreadMgrSink
*sink
)
141 IUnknown_Release(sink
->interfaces
.pIUnknown
);
142 HeapFree(GetProcessHeap(),0,sink
);
145 static void ThreadMgr_Destructor(ThreadMgr
*This
)
147 struct list
*cursor
, *cursor2
;
149 /* unhook right away */
151 UnhookWindowsHookEx(This
->focusHook
);
153 TlsSetValue(tlsIndex
,NULL
);
154 TRACE("destroying %p\n", This
);
156 ITfDocumentMgr_Release(This
->focus
);
159 LIST_FOR_EACH_SAFE(cursor
, cursor2
, &This
->ActiveLanguageProfileNotifySink
)
161 ThreadMgrSink
* sink
= LIST_ENTRY(cursor
,ThreadMgrSink
,entry
);
165 LIST_FOR_EACH_SAFE(cursor
, cursor2
, &This
->DisplayAttributeNotifySink
)
167 ThreadMgrSink
* sink
= LIST_ENTRY(cursor
,ThreadMgrSink
,entry
);
171 LIST_FOR_EACH_SAFE(cursor
, cursor2
, &This
->KeyTraceEventSink
)
173 ThreadMgrSink
* sink
= LIST_ENTRY(cursor
,ThreadMgrSink
,entry
);
177 LIST_FOR_EACH_SAFE(cursor
, cursor2
, &This
->PreservedKeyNotifySink
)
179 ThreadMgrSink
* sink
= LIST_ENTRY(cursor
,ThreadMgrSink
,entry
);
183 LIST_FOR_EACH_SAFE(cursor
, cursor2
, &This
->ThreadFocusSink
)
185 ThreadMgrSink
* sink
= LIST_ENTRY(cursor
,ThreadMgrSink
,entry
);
189 LIST_FOR_EACH_SAFE(cursor
, cursor2
, &This
->ThreadMgrEventSink
)
191 ThreadMgrSink
* sink
= LIST_ENTRY(cursor
,ThreadMgrSink
,entry
);
196 LIST_FOR_EACH_SAFE(cursor
, cursor2
, &This
->CurrentPreservedKeys
)
198 PreservedKey
* key
= LIST_ENTRY(cursor
,PreservedKey
,entry
);
200 HeapFree(GetProcessHeap(),0,key
->description
);
201 HeapFree(GetProcessHeap(),0,key
);
204 LIST_FOR_EACH_SAFE(cursor
, cursor2
, &This
->CreatedDocumentMgrs
)
206 DocumentMgrEntry
*mgr
= LIST_ENTRY(cursor
,DocumentMgrEntry
,entry
);
208 FIXME("Left Over ITfDocumentMgr. Should we do something with it?\n");
209 HeapFree(GetProcessHeap(),0,mgr
);
212 LIST_FOR_EACH_SAFE(cursor
, cursor2
, &This
->AssociatedFocusWindows
)
214 AssociatedWindow
*wnd
= LIST_ENTRY(cursor
,AssociatedWindow
,entry
);
216 HeapFree(GetProcessHeap(),0,wnd
);
219 CompartmentMgr_Destructor(This
->CompartmentMgr
);
221 HeapFree(GetProcessHeap(),0,This
);
224 static HRESULT WINAPI
ThreadMgr_QueryInterface(ITfThreadMgr
*iface
, REFIID iid
, LPVOID
*ppvOut
)
226 ThreadMgr
*This
= (ThreadMgr
*)iface
;
229 if (IsEqualIID(iid
, &IID_IUnknown
) || IsEqualIID(iid
, &IID_ITfThreadMgr
))
233 else if (IsEqualIID(iid
, &IID_ITfSource
))
235 *ppvOut
= &This
->SourceVtbl
;
237 else if (IsEqualIID(iid
, &IID_ITfKeystrokeMgr
))
239 *ppvOut
= &This
->KeystrokeMgrVtbl
;
241 else if (IsEqualIID(iid
, &IID_ITfMessagePump
))
243 *ppvOut
= &This
->MessagePumpVtbl
;
245 else if (IsEqualIID(iid
, &IID_ITfClientId
))
247 *ppvOut
= &This
->ClientIdVtbl
;
249 else if (IsEqualIID(iid
, &IID_ITfCompartmentMgr
))
251 *ppvOut
= This
->CompartmentMgr
;
253 else if (IsEqualIID(iid
, &IID_ITfSourceSingle
))
255 *ppvOut
= &This
->SourceSingleVtbl
;
260 ITfThreadMgr_AddRef(iface
);
264 WARN("unsupported interface: %s\n", debugstr_guid(iid
));
265 return E_NOINTERFACE
;
268 static ULONG WINAPI
ThreadMgr_AddRef(ITfThreadMgr
*iface
)
270 ThreadMgr
*This
= (ThreadMgr
*)iface
;
271 return InterlockedIncrement(&This
->refCount
);
274 static ULONG WINAPI
ThreadMgr_Release(ITfThreadMgr
*iface
)
276 ThreadMgr
*This
= (ThreadMgr
*)iface
;
279 ret
= InterlockedDecrement(&This
->refCount
);
281 ThreadMgr_Destructor(This
);
285 /*****************************************************
286 * ITfThreadMgr functions
287 *****************************************************/
289 static HRESULT WINAPI
ThreadMgr_fnActivate( ITfThreadMgr
* iface
, TfClientId
*ptid
)
291 ThreadMgr
*This
= (ThreadMgr
*)iface
;
293 TRACE("(%p) %p\n",This
, ptid
);
302 ITfClientId_GetClientId((ITfClientId
*)&This
->ClientIdVtbl
,&guid
,&processId
);
305 activate_textservices(iface
);
306 This
->activationCount
++;
311 static HRESULT WINAPI
ThreadMgr_fnDeactivate( ITfThreadMgr
* iface
)
313 ThreadMgr
*This
= (ThreadMgr
*)iface
;
314 TRACE("(%p)\n",This
);
316 if (This
->activationCount
== 0)
319 This
->activationCount
--;
321 if (This
->activationCount
== 0)
325 ITfThreadMgrEventSink_OnSetFocus((ITfThreadMgrEventSink
*)&This
->ThreadMgrEventSinkVtbl
, 0, This
->focus
);
326 ITfDocumentMgr_Release(This
->focus
);
331 deactivate_textservices();
336 static HRESULT WINAPI
ThreadMgr_CreateDocumentMgr( ITfThreadMgr
* iface
, ITfDocumentMgr
339 ThreadMgr
*This
= (ThreadMgr
*)iface
;
340 DocumentMgrEntry
*mgrentry
;
343 TRACE("(%p)\n",iface
);
344 mgrentry
= HeapAlloc(GetProcessHeap(),0,sizeof(DocumentMgrEntry
));
345 if (mgrentry
== NULL
)
346 return E_OUTOFMEMORY
;
348 hr
= DocumentMgr_Constructor((ITfThreadMgrEventSink
*)&This
->ThreadMgrEventSinkVtbl
, ppdim
);
352 mgrentry
->docmgr
= *ppdim
;
353 list_add_head(&This
->CreatedDocumentMgrs
,&mgrentry
->entry
);
356 HeapFree(GetProcessHeap(),0,mgrentry
);
361 static HRESULT WINAPI
ThreadMgr_EnumDocumentMgrs( ITfThreadMgr
* iface
, IEnumTfDocumentMgrs
364 ThreadMgr
*This
= (ThreadMgr
*)iface
;
365 TRACE("(%p) %p\n",This
,ppEnum
);
370 return EnumTfDocumentMgr_Constructor(&This
->CreatedDocumentMgrs
, ppEnum
);
373 static HRESULT WINAPI
ThreadMgr_GetFocus( ITfThreadMgr
* iface
, ITfDocumentMgr
376 ThreadMgr
*This
= (ThreadMgr
*)iface
;
377 TRACE("(%p)\n",This
);
382 *ppdimFocus
= This
->focus
;
384 TRACE("->%p\n",This
->focus
);
386 if (This
->focus
== NULL
)
389 ITfDocumentMgr_AddRef(This
->focus
);
394 static HRESULT WINAPI
ThreadMgr_SetFocus( ITfThreadMgr
* iface
, ITfDocumentMgr
*pdimFocus
)
396 ITfDocumentMgr
*check
;
397 ThreadMgr
*This
= (ThreadMgr
*)iface
;
399 TRACE("(%p) %p\n",This
,pdimFocus
);
403 else if (FAILED(ITfDocumentMgr_QueryInterface(pdimFocus
,&IID_ITfDocumentMgr
,(LPVOID
*) &check
)))
406 ITfThreadMgrEventSink_OnSetFocus((ITfThreadMgrEventSink
*)&This
->ThreadMgrEventSinkVtbl
, check
, This
->focus
);
409 ITfDocumentMgr_Release(This
->focus
);
415 static LRESULT CALLBACK
ThreadFocusHookProc(int nCode
, WPARAM wParam
, LPARAM lParam
)
419 This
= TlsGetValue(tlsIndex
);
422 ERR("Hook proc but no ThreadMgr for this thread. Serious Error\n");
425 if (!This
->focusHook
)
427 ERR("Hook proc but no ThreadMgr focus Hook. Serious Error\n");
431 if (nCode
== HCBT_SETFOCUS
) /* focus change within our thread */
435 LIST_FOR_EACH(cursor
, &This
->AssociatedFocusWindows
)
437 AssociatedWindow
*wnd
= LIST_ENTRY(cursor
,AssociatedWindow
,entry
);
438 if (wnd
->hwnd
== (HWND
)wParam
)
440 TRACE("Triggering Associated window focus\n");
441 if (This
->focus
!= wnd
->docmgr
)
442 ThreadMgr_SetFocus((ITfThreadMgr
*)This
, wnd
->docmgr
);
448 return CallNextHookEx(This
->focusHook
, nCode
, wParam
, lParam
);
451 static HRESULT
SetupWindowsHook(ThreadMgr
*This
)
453 if (!This
->focusHook
)
455 This
->focusHook
= SetWindowsHookExW(WH_CBT
, ThreadFocusHookProc
, 0,
456 GetCurrentThreadId());
457 if (!This
->focusHook
)
459 ERR("Unable to set focus hook\n");
467 static HRESULT WINAPI
ThreadMgr_AssociateFocus( ITfThreadMgr
* iface
, HWND hwnd
,
468 ITfDocumentMgr
*pdimNew
, ITfDocumentMgr
**ppdimPrev
)
470 struct list
*cursor
, *cursor2
;
471 ThreadMgr
*This
= (ThreadMgr
*)iface
;
472 AssociatedWindow
*wnd
;
474 TRACE("(%p) %p %p %p\n",This
,hwnd
,pdimNew
,ppdimPrev
);
481 LIST_FOR_EACH_SAFE(cursor
, cursor2
, &This
->AssociatedFocusWindows
)
483 wnd
= LIST_ENTRY(cursor
,AssociatedWindow
,entry
);
484 if (wnd
->hwnd
== hwnd
)
487 ITfDocumentMgr_AddRef(wnd
->docmgr
);
488 *ppdimPrev
= wnd
->docmgr
;
489 wnd
->docmgr
= pdimNew
;
490 if (GetFocus() == hwnd
)
491 ThreadMgr_SetFocus(iface
,pdimNew
);
496 wnd
= HeapAlloc(GetProcessHeap(),0,sizeof(AssociatedWindow
));
498 wnd
->docmgr
= pdimNew
;
499 list_add_head(&This
->AssociatedFocusWindows
,&wnd
->entry
);
501 if (GetFocus() == hwnd
)
502 ThreadMgr_SetFocus(iface
,pdimNew
);
504 SetupWindowsHook(This
);
509 static HRESULT WINAPI
ThreadMgr_IsThreadFocus( ITfThreadMgr
* iface
, BOOL
*pfThreadFocus
)
512 ThreadMgr
*This
= (ThreadMgr
*)iface
;
513 TRACE("(%p) %p\n",This
,pfThreadFocus
);
515 *pfThreadFocus
= (focus
== NULL
);
519 static HRESULT WINAPI
ThreadMgr_GetFunctionProvider( ITfThreadMgr
* iface
, REFCLSID clsid
,
520 ITfFunctionProvider
**ppFuncProv
)
522 ThreadMgr
*This
= (ThreadMgr
*)iface
;
523 FIXME("STUB:(%p)\n",This
);
527 static HRESULT WINAPI
ThreadMgr_EnumFunctionProviders( ITfThreadMgr
* iface
,
528 IEnumTfFunctionProviders
**ppEnum
)
530 ThreadMgr
*This
= (ThreadMgr
*)iface
;
531 FIXME("STUB:(%p)\n",This
);
535 static HRESULT WINAPI
ThreadMgr_GetGlobalCompartment( ITfThreadMgr
* iface
,
536 ITfCompartmentMgr
**ppCompMgr
)
538 ThreadMgr
*This
= (ThreadMgr
*)iface
;
540 TRACE("(%p) %p\n",This
, ppCompMgr
);
545 if (!globalCompartmentMgr
)
547 hr
= CompartmentMgr_Constructor(NULL
,&IID_ITfCompartmentMgr
,(IUnknown
**)&globalCompartmentMgr
);
552 ITfCompartmentMgr_AddRef(globalCompartmentMgr
);
553 *ppCompMgr
= globalCompartmentMgr
;
557 static const ITfThreadMgrVtbl ThreadMgr_ThreadMgrVtbl
=
559 ThreadMgr_QueryInterface
,
563 ThreadMgr_fnActivate
,
564 ThreadMgr_fnDeactivate
,
565 ThreadMgr_CreateDocumentMgr
,
566 ThreadMgr_EnumDocumentMgrs
,
569 ThreadMgr_AssociateFocus
,
570 ThreadMgr_IsThreadFocus
,
571 ThreadMgr_GetFunctionProvider
,
572 ThreadMgr_EnumFunctionProviders
,
573 ThreadMgr_GetGlobalCompartment
577 static HRESULT WINAPI
Source_QueryInterface(ITfSource
*iface
, REFIID iid
, LPVOID
*ppvOut
)
579 ThreadMgr
*This
= impl_from_ITfSourceVtbl(iface
);
580 return ThreadMgr_QueryInterface((ITfThreadMgr
*)This
, iid
, *ppvOut
);
583 static ULONG WINAPI
Source_AddRef(ITfSource
*iface
)
585 ThreadMgr
*This
= impl_from_ITfSourceVtbl(iface
);
586 return ThreadMgr_AddRef((ITfThreadMgr
*)This
);
589 static ULONG WINAPI
Source_Release(ITfSource
*iface
)
591 ThreadMgr
*This
= impl_from_ITfSourceVtbl(iface
);
592 return ThreadMgr_Release((ITfThreadMgr
*)This
);
595 /*****************************************************
596 * ITfSource functions
597 *****************************************************/
598 static HRESULT WINAPI
ThreadMgrSource_AdviseSink(ITfSource
*iface
,
599 REFIID riid
, IUnknown
*punk
, DWORD
*pdwCookie
)
602 ThreadMgr
*This
= impl_from_ITfSourceVtbl(iface
);
604 TRACE("(%p) %s %p %p\n",This
,debugstr_guid(riid
),punk
,pdwCookie
);
606 if (!riid
|| !punk
|| !pdwCookie
)
609 if (IsEqualIID(riid
, &IID_ITfThreadMgrEventSink
))
611 tms
= HeapAlloc(GetProcessHeap(),0,sizeof(ThreadMgrSink
));
613 return E_OUTOFMEMORY
;
614 if (FAILED(IUnknown_QueryInterface(punk
, riid
, (LPVOID
*)&tms
->interfaces
.pITfThreadMgrEventSink
)))
616 HeapFree(GetProcessHeap(),0,tms
);
617 return CONNECT_E_CANNOTCONNECT
;
619 list_add_head(&This
->ThreadMgrEventSink
,&tms
->entry
);
620 *pdwCookie
= generate_Cookie(COOKIE_MAGIC_TMSINK
, tms
);
624 FIXME("(%p) Unhandled Sink: %s\n",This
,debugstr_guid(riid
));
628 TRACE("cookie %x\n",*pdwCookie
);
633 static HRESULT WINAPI
ThreadMgrSource_UnadviseSink(ITfSource
*iface
, DWORD pdwCookie
)
636 ThreadMgr
*This
= impl_from_ITfSourceVtbl(iface
);
638 TRACE("(%p) %x\n",This
,pdwCookie
);
640 if (get_Cookie_magic(pdwCookie
)!=COOKIE_MAGIC_TMSINK
)
643 sink
= remove_Cookie(pdwCookie
);
645 return CONNECT_E_NOCONNECTION
;
647 list_remove(&sink
->entry
);
653 static const ITfSourceVtbl ThreadMgr_SourceVtbl
=
655 Source_QueryInterface
,
659 ThreadMgrSource_AdviseSink
,
660 ThreadMgrSource_UnadviseSink
,
663 /*****************************************************
664 * ITfKeystrokeMgr functions
665 *****************************************************/
667 static HRESULT WINAPI
KeystrokeMgr_QueryInterface(ITfKeystrokeMgr
*iface
, REFIID iid
, LPVOID
*ppvOut
)
669 ThreadMgr
*This
= impl_from_ITfKeystrokeMgrVtbl(iface
);
670 return ThreadMgr_QueryInterface((ITfThreadMgr
*)This
, iid
, *ppvOut
);
673 static ULONG WINAPI
KeystrokeMgr_AddRef(ITfKeystrokeMgr
*iface
)
675 ThreadMgr
*This
= impl_from_ITfKeystrokeMgrVtbl(iface
);
676 return ThreadMgr_AddRef((ITfThreadMgr
*)This
);
679 static ULONG WINAPI
KeystrokeMgr_Release(ITfKeystrokeMgr
*iface
)
681 ThreadMgr
*This
= impl_from_ITfKeystrokeMgrVtbl(iface
);
682 return ThreadMgr_Release((ITfThreadMgr
*)This
);
685 static HRESULT WINAPI
KeystrokeMgr_AdviseKeyEventSink(ITfKeystrokeMgr
*iface
,
686 TfClientId tid
, ITfKeyEventSink
*pSink
, BOOL fForeground
)
688 ThreadMgr
*This
= impl_from_ITfKeystrokeMgrVtbl(iface
);
690 ITfKeyEventSink
*check
= NULL
;
692 TRACE("(%p) %x %p %i\n",This
,tid
,pSink
,fForeground
);
697 textservice
= get_textservice_clsid(tid
);
698 if (IsEqualCLSID(&GUID_NULL
,&textservice
))
701 get_textservice_sink(tid
, &IID_ITfKeyEventSink
, (IUnknown
**)&check
);
703 return CONNECT_E_ADVISELIMIT
;
705 if (FAILED(ITfKeyEventSink_QueryInterface(pSink
,&IID_ITfKeyEventSink
,(LPVOID
*) &check
)))
708 set_textservice_sink(tid
, &IID_ITfKeyEventSink
, (IUnknown
*)check
);
712 if (This
->forgroundKeyEventSink
)
714 ITfKeyEventSink_OnSetFocus(This
->forgroundKeyEventSink
, FALSE
);
715 ITfKeyEventSink_Release(This
->forgroundKeyEventSink
);
717 ITfKeyEventSink_AddRef(check
);
718 ITfKeyEventSink_OnSetFocus(check
, TRUE
);
719 This
->forgroundKeyEventSink
= check
;
720 This
->forgroundTextService
= textservice
;
725 static HRESULT WINAPI
KeystrokeMgr_UnadviseKeyEventSink(ITfKeystrokeMgr
*iface
,
728 ThreadMgr
*This
= impl_from_ITfKeystrokeMgrVtbl(iface
);
730 ITfKeyEventSink
*check
= NULL
;
731 TRACE("(%p) %x\n",This
,tid
);
736 textservice
= get_textservice_clsid(tid
);
737 if (IsEqualCLSID(&GUID_NULL
,&textservice
))
740 get_textservice_sink(tid
, &IID_ITfKeyEventSink
, (IUnknown
**)&check
);
743 return CONNECT_E_NOCONNECTION
;
745 set_textservice_sink(tid
, &IID_ITfKeyEventSink
, NULL
);
746 ITfKeyEventSink_Release(check
);
748 if (This
->forgroundKeyEventSink
== check
)
750 ITfKeyEventSink_Release(This
->forgroundKeyEventSink
);
751 This
->forgroundKeyEventSink
= NULL
;
752 This
->forgroundTextService
= GUID_NULL
;
757 static HRESULT WINAPI
KeystrokeMgr_GetForeground(ITfKeystrokeMgr
*iface
,
760 ThreadMgr
*This
= impl_from_ITfKeystrokeMgrVtbl(iface
);
761 TRACE("(%p) %p\n",This
,pclsid
);
765 if (IsEqualCLSID(&This
->forgroundTextService
,&GUID_NULL
))
768 *pclsid
= This
->forgroundTextService
;
772 static HRESULT WINAPI
KeystrokeMgr_TestKeyDown(ITfKeystrokeMgr
*iface
,
773 WPARAM wParam
, LPARAM lParam
, BOOL
*pfEaten
)
775 ThreadMgr
*This
= impl_from_ITfKeystrokeMgrVtbl(iface
);
776 FIXME("STUB:(%p)\n",This
);
780 static HRESULT WINAPI
KeystrokeMgr_TestKeyUp(ITfKeystrokeMgr
*iface
,
781 WPARAM wParam
, LPARAM lParam
, BOOL
*pfEaten
)
783 ThreadMgr
*This
= impl_from_ITfKeystrokeMgrVtbl(iface
);
784 FIXME("STUB:(%p)\n",This
);
788 static HRESULT WINAPI
KeystrokeMgr_KeyDown(ITfKeystrokeMgr
*iface
,
789 WPARAM wParam
, LPARAM lParam
, BOOL
*pfEaten
)
791 ThreadMgr
*This
= impl_from_ITfKeystrokeMgrVtbl(iface
);
792 FIXME("STUB:(%p)\n",This
);
796 static HRESULT WINAPI
KeystrokeMgr_KeyUp(ITfKeystrokeMgr
*iface
,
797 WPARAM wParam
, LPARAM lParam
, BOOL
*pfEaten
)
799 ThreadMgr
*This
= impl_from_ITfKeystrokeMgrVtbl(iface
);
800 FIXME("STUB:(%p)\n",This
);
804 static HRESULT WINAPI
KeystrokeMgr_GetPreservedKey(ITfKeystrokeMgr
*iface
,
805 ITfContext
*pic
, const TF_PRESERVEDKEY
*pprekey
, GUID
*pguid
)
807 ThreadMgr
*This
= impl_from_ITfKeystrokeMgrVtbl(iface
);
808 FIXME("STUB:(%p)\n",This
);
812 static HRESULT WINAPI
KeystrokeMgr_IsPreservedKey(ITfKeystrokeMgr
*iface
,
813 REFGUID rguid
, const TF_PRESERVEDKEY
*pprekey
, BOOL
*pfRegistered
)
815 ThreadMgr
*This
= impl_from_ITfKeystrokeMgrVtbl(iface
);
818 TRACE("(%p) %s (%x %x) %p\n",This
,debugstr_guid(rguid
), (pprekey
)?pprekey
->uVKey
:0, (pprekey
)?pprekey
->uModifiers
:0, pfRegistered
);
820 if (!rguid
|| !pprekey
|| !pfRegistered
)
823 LIST_FOR_EACH(cursor
, &This
->CurrentPreservedKeys
)
825 PreservedKey
* key
= LIST_ENTRY(cursor
,PreservedKey
,entry
);
826 if (IsEqualGUID(rguid
,&key
->guid
) && pprekey
->uVKey
== key
->prekey
.uVKey
&& pprekey
->uModifiers
== key
->prekey
.uModifiers
)
828 *pfRegistered
= TRUE
;
833 *pfRegistered
= FALSE
;
837 static HRESULT WINAPI
KeystrokeMgr_PreserveKey(ITfKeystrokeMgr
*iface
,
838 TfClientId tid
, REFGUID rguid
, const TF_PRESERVEDKEY
*prekey
,
839 const WCHAR
*pchDesc
, ULONG cchDesc
)
841 ThreadMgr
*This
= impl_from_ITfKeystrokeMgrVtbl(iface
);
843 PreservedKey
*newkey
;
845 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
));
847 if (!tid
|| ! rguid
|| !prekey
|| (cchDesc
&& !pchDesc
))
850 LIST_FOR_EACH(cursor
, &This
->CurrentPreservedKeys
)
852 PreservedKey
* key
= LIST_ENTRY(cursor
,PreservedKey
,entry
);
853 if (IsEqualGUID(rguid
,&key
->guid
) && prekey
->uVKey
== key
->prekey
.uVKey
&& prekey
->uModifiers
== key
->prekey
.uModifiers
)
854 return TF_E_ALREADY_EXISTS
;
857 newkey
= HeapAlloc(GetProcessHeap(),0,sizeof(PreservedKey
));
859 return E_OUTOFMEMORY
;
861 newkey
->guid
= *rguid
;
862 newkey
->prekey
= *prekey
;
864 newkey
->description
= NULL
;
867 newkey
->description
= HeapAlloc(GetProcessHeap(),0,cchDesc
* sizeof(WCHAR
));
868 if (!newkey
->description
)
870 HeapFree(GetProcessHeap(),0,newkey
);
871 return E_OUTOFMEMORY
;
873 memcpy(newkey
->description
, pchDesc
, cchDesc
*sizeof(WCHAR
));
876 list_add_head(&This
->CurrentPreservedKeys
,&newkey
->entry
);
881 static HRESULT WINAPI
KeystrokeMgr_UnpreserveKey(ITfKeystrokeMgr
*iface
,
882 REFGUID rguid
, const TF_PRESERVEDKEY
*pprekey
)
884 ThreadMgr
*This
= impl_from_ITfKeystrokeMgrVtbl(iface
);
885 PreservedKey
* key
= NULL
;
887 TRACE("(%p) %s (%x %x)\n",This
,debugstr_guid(rguid
),(pprekey
)?pprekey
->uVKey
:0, (pprekey
)?pprekey
->uModifiers
:0);
889 if (!pprekey
|| !rguid
)
892 LIST_FOR_EACH(cursor
, &This
->CurrentPreservedKeys
)
894 key
= LIST_ENTRY(cursor
,PreservedKey
,entry
);
895 if (IsEqualGUID(rguid
,&key
->guid
) && pprekey
->uVKey
== key
->prekey
.uVKey
&& pprekey
->uModifiers
== key
->prekey
.uModifiers
)
901 return CONNECT_E_NOCONNECTION
;
903 list_remove(&key
->entry
);
904 HeapFree(GetProcessHeap(),0,key
->description
);
905 HeapFree(GetProcessHeap(),0,key
);
910 static HRESULT WINAPI
KeystrokeMgr_SetPreservedKeyDescription(ITfKeystrokeMgr
*iface
,
911 REFGUID rguid
, const WCHAR
*pchDesc
, ULONG cchDesc
)
913 ThreadMgr
*This
= impl_from_ITfKeystrokeMgrVtbl(iface
);
914 FIXME("STUB:(%p)\n",This
);
918 static HRESULT WINAPI
KeystrokeMgr_GetPreservedKeyDescription(ITfKeystrokeMgr
*iface
,
919 REFGUID rguid
, BSTR
*pbstrDesc
)
921 ThreadMgr
*This
= impl_from_ITfKeystrokeMgrVtbl(iface
);
922 FIXME("STUB:(%p)\n",This
);
926 static HRESULT WINAPI
KeystrokeMgr_SimulatePreservedKey(ITfKeystrokeMgr
*iface
,
927 ITfContext
*pic
, REFGUID rguid
, BOOL
*pfEaten
)
929 ThreadMgr
*This
= impl_from_ITfKeystrokeMgrVtbl(iface
);
930 FIXME("STUB:(%p)\n",This
);
934 static const ITfKeystrokeMgrVtbl ThreadMgr_KeystrokeMgrVtbl
=
936 KeystrokeMgr_QueryInterface
,
938 KeystrokeMgr_Release
,
940 KeystrokeMgr_AdviseKeyEventSink
,
941 KeystrokeMgr_UnadviseKeyEventSink
,
942 KeystrokeMgr_GetForeground
,
943 KeystrokeMgr_TestKeyDown
,
944 KeystrokeMgr_TestKeyUp
,
945 KeystrokeMgr_KeyDown
,
947 KeystrokeMgr_GetPreservedKey
,
948 KeystrokeMgr_IsPreservedKey
,
949 KeystrokeMgr_PreserveKey
,
950 KeystrokeMgr_UnpreserveKey
,
951 KeystrokeMgr_SetPreservedKeyDescription
,
952 KeystrokeMgr_GetPreservedKeyDescription
,
953 KeystrokeMgr_SimulatePreservedKey
956 /*****************************************************
957 * ITfMessagePump functions
958 *****************************************************/
960 static HRESULT WINAPI
MessagePump_QueryInterface(ITfMessagePump
*iface
, REFIID iid
, LPVOID
*ppvOut
)
962 ThreadMgr
*This
= impl_from_ITfMessagePumpVtbl(iface
);
963 return ThreadMgr_QueryInterface((ITfThreadMgr
*)This
, iid
, *ppvOut
);
966 static ULONG WINAPI
MessagePump_AddRef(ITfMessagePump
*iface
)
968 ThreadMgr
*This
= impl_from_ITfMessagePumpVtbl(iface
);
969 return ThreadMgr_AddRef((ITfThreadMgr
*)This
);
972 static ULONG WINAPI
MessagePump_Release(ITfMessagePump
*iface
)
974 ThreadMgr
*This
= impl_from_ITfMessagePumpVtbl(iface
);
975 return ThreadMgr_Release((ITfThreadMgr
*)This
);
978 static HRESULT WINAPI
MessagePump_PeekMessageA(ITfMessagePump
*iface
,
979 LPMSG pMsg
, HWND hwnd
, UINT wMsgFilterMin
, UINT wMsgFilterMax
,
980 UINT wRemoveMsg
, BOOL
*pfResult
)
984 *pfResult
= PeekMessageA(pMsg
, hwnd
, wMsgFilterMin
, wMsgFilterMax
, wRemoveMsg
);
988 static HRESULT WINAPI
MessagePump_GetMessageA(ITfMessagePump
*iface
,
989 LPMSG pMsg
, HWND hwnd
, UINT wMsgFilterMin
, UINT wMsgFilterMax
,
994 *pfResult
= GetMessageA(pMsg
, hwnd
, wMsgFilterMin
, wMsgFilterMax
);
998 static HRESULT WINAPI
MessagePump_PeekMessageW(ITfMessagePump
*iface
,
999 LPMSG pMsg
, HWND hwnd
, UINT wMsgFilterMin
, UINT wMsgFilterMax
,
1000 UINT wRemoveMsg
, BOOL
*pfResult
)
1003 return E_INVALIDARG
;
1004 *pfResult
= PeekMessageW(pMsg
, hwnd
, wMsgFilterMin
, wMsgFilterMax
, wRemoveMsg
);
1008 static HRESULT WINAPI
MessagePump_GetMessageW(ITfMessagePump
*iface
,
1009 LPMSG pMsg
, HWND hwnd
, UINT wMsgFilterMin
, UINT wMsgFilterMax
,
1013 return E_INVALIDARG
;
1014 *pfResult
= GetMessageW(pMsg
, hwnd
, wMsgFilterMin
, wMsgFilterMax
);
1018 static const ITfMessagePumpVtbl ThreadMgr_MessagePumpVtbl
=
1020 MessagePump_QueryInterface
,
1022 MessagePump_Release
,
1024 MessagePump_PeekMessageA
,
1025 MessagePump_GetMessageA
,
1026 MessagePump_PeekMessageW
,
1027 MessagePump_GetMessageW
1030 /*****************************************************
1031 * ITfClientId functions
1032 *****************************************************/
1034 static HRESULT WINAPI
ClientId_QueryInterface(ITfClientId
*iface
, REFIID iid
, LPVOID
*ppvOut
)
1036 ThreadMgr
*This
= impl_from_ITfClientIdVtbl(iface
);
1037 return ThreadMgr_QueryInterface((ITfThreadMgr
*)This
, iid
, *ppvOut
);
1040 static ULONG WINAPI
ClientId_AddRef(ITfClientId
*iface
)
1042 ThreadMgr
*This
= impl_from_ITfClientIdVtbl(iface
);
1043 return ThreadMgr_AddRef((ITfThreadMgr
*)This
);
1046 static ULONG WINAPI
ClientId_Release(ITfClientId
*iface
)
1048 ThreadMgr
*This
= impl_from_ITfClientIdVtbl(iface
);
1049 return ThreadMgr_Release((ITfThreadMgr
*)This
);
1052 static HRESULT WINAPI
ClientId_GetClientId(ITfClientId
*iface
,
1053 REFCLSID rclsid
, TfClientId
*ptid
)
1057 ITfCategoryMgr
*catmgr
;
1058 ThreadMgr
*This
= impl_from_ITfClientIdVtbl(iface
);
1060 TRACE("(%p) %s\n",This
,debugstr_guid(rclsid
));
1062 CategoryMgr_Constructor(NULL
,(IUnknown
**)&catmgr
);
1063 hr
= ITfCategoryMgr_RegisterGUID(catmgr
,rclsid
,ptid
);
1064 ITfCategoryMgr_Release(catmgr
);
1069 static const ITfClientIdVtbl ThreadMgr_ClientIdVtbl
=
1071 ClientId_QueryInterface
,
1075 ClientId_GetClientId
1078 /*****************************************************
1079 * ITfThreadMgrEventSink functions (internal)
1080 *****************************************************/
1081 static HRESULT WINAPI
ThreadMgrEventSink_QueryInterface(ITfThreadMgrEventSink
*iface
, REFIID iid
, LPVOID
*ppvOut
)
1083 ThreadMgr
*This
= impl_from_ITfThreadMgrEventSink(iface
);
1084 return ThreadMgr_QueryInterface((ITfThreadMgr
*)This
, iid
, *ppvOut
);
1087 static ULONG WINAPI
ThreadMgrEventSink_AddRef(ITfThreadMgrEventSink
*iface
)
1089 ThreadMgr
*This
= impl_from_ITfThreadMgrEventSink(iface
);
1090 return ThreadMgr_AddRef((ITfThreadMgr
*)This
);
1093 static ULONG WINAPI
ThreadMgrEventSink_Release(ITfThreadMgrEventSink
*iface
)
1095 ThreadMgr
*This
= impl_from_ITfThreadMgrEventSink(iface
);
1096 return ThreadMgr_Release((ITfThreadMgr
*)This
);
1100 static HRESULT WINAPI
ThreadMgrEventSink_OnInitDocumentMgr(
1101 ITfThreadMgrEventSink
*iface
,ITfDocumentMgr
*pdim
)
1103 struct list
*cursor
;
1104 ThreadMgr
*This
= impl_from_ITfThreadMgrEventSink(iface
);
1106 TRACE("(%p) %p\n",This
,pdim
);
1108 LIST_FOR_EACH(cursor
, &This
->ThreadMgrEventSink
)
1110 ThreadMgrSink
* sink
= LIST_ENTRY(cursor
,ThreadMgrSink
,entry
);
1111 ITfThreadMgrEventSink_OnInitDocumentMgr(sink
->interfaces
.pITfThreadMgrEventSink
,pdim
);
1117 static HRESULT WINAPI
ThreadMgrEventSink_OnUninitDocumentMgr(
1118 ITfThreadMgrEventSink
*iface
, ITfDocumentMgr
*pdim
)
1120 struct list
*cursor
;
1121 ThreadMgr
*This
= impl_from_ITfThreadMgrEventSink(iface
);
1123 TRACE("(%p) %p\n",This
,pdim
);
1125 LIST_FOR_EACH(cursor
, &This
->ThreadMgrEventSink
)
1127 ThreadMgrSink
* sink
= LIST_ENTRY(cursor
,ThreadMgrSink
,entry
);
1128 ITfThreadMgrEventSink_OnUninitDocumentMgr(sink
->interfaces
.pITfThreadMgrEventSink
,pdim
);
1134 static HRESULT WINAPI
ThreadMgrEventSink_OnSetFocus(
1135 ITfThreadMgrEventSink
*iface
, ITfDocumentMgr
*pdimFocus
,
1136 ITfDocumentMgr
*pdimPrevFocus
)
1138 struct list
*cursor
;
1139 ThreadMgr
*This
= impl_from_ITfThreadMgrEventSink(iface
);
1141 TRACE("(%p) %p %p\n",This
,pdimFocus
, pdimPrevFocus
);
1143 LIST_FOR_EACH(cursor
, &This
->ThreadMgrEventSink
)
1145 ThreadMgrSink
* sink
= LIST_ENTRY(cursor
,ThreadMgrSink
,entry
);
1146 ITfThreadMgrEventSink_OnSetFocus(sink
->interfaces
.pITfThreadMgrEventSink
, pdimFocus
, pdimPrevFocus
);
1152 static HRESULT WINAPI
ThreadMgrEventSink_OnPushContext(
1153 ITfThreadMgrEventSink
*iface
, ITfContext
*pic
)
1155 struct list
*cursor
;
1156 ThreadMgr
*This
= impl_from_ITfThreadMgrEventSink(iface
);
1158 TRACE("(%p) %p\n",This
,pic
);
1160 LIST_FOR_EACH(cursor
, &This
->ThreadMgrEventSink
)
1162 ThreadMgrSink
* sink
= LIST_ENTRY(cursor
,ThreadMgrSink
,entry
);
1163 ITfThreadMgrEventSink_OnPushContext(sink
->interfaces
.pITfThreadMgrEventSink
,pic
);
1169 static HRESULT WINAPI
ThreadMgrEventSink_OnPopContext(
1170 ITfThreadMgrEventSink
*iface
, ITfContext
*pic
)
1172 struct list
*cursor
;
1173 ThreadMgr
*This
= impl_from_ITfThreadMgrEventSink(iface
);
1175 TRACE("(%p) %p\n",This
,pic
);
1177 LIST_FOR_EACH(cursor
, &This
->ThreadMgrEventSink
)
1179 ThreadMgrSink
* sink
= LIST_ENTRY(cursor
,ThreadMgrSink
,entry
);
1180 ITfThreadMgrEventSink_OnPopContext(sink
->interfaces
.pITfThreadMgrEventSink
,pic
);
1186 static const ITfThreadMgrEventSinkVtbl ThreadMgr_ThreadMgrEventSinkVtbl
=
1188 ThreadMgrEventSink_QueryInterface
,
1189 ThreadMgrEventSink_AddRef
,
1190 ThreadMgrEventSink_Release
,
1192 ThreadMgrEventSink_OnInitDocumentMgr
,
1193 ThreadMgrEventSink_OnUninitDocumentMgr
,
1194 ThreadMgrEventSink_OnSetFocus
,
1195 ThreadMgrEventSink_OnPushContext
,
1196 ThreadMgrEventSink_OnPopContext
1199 /*****************************************************
1200 * ITfSourceSingle functions
1201 *****************************************************/
1202 static HRESULT WINAPI
ThreadMgrSourceSingle_QueryInterface(ITfSourceSingle
*iface
, REFIID iid
, LPVOID
*ppvOut
)
1204 ThreadMgr
*This
= impl_from_ITfSourceSingleVtbl(iface
);
1205 return ThreadMgr_QueryInterface((ITfThreadMgr
*)This
, iid
, *ppvOut
);
1208 static ULONG WINAPI
ThreadMgrSourceSingle_AddRef(ITfSourceSingle
*iface
)
1210 ThreadMgr
*This
= impl_from_ITfSourceSingleVtbl(iface
);
1211 return ThreadMgr_AddRef((ITfThreadMgr
*)This
);
1214 static ULONG WINAPI
ThreadMgrSourceSingle_Release(ITfSourceSingle
*iface
)
1216 ThreadMgr
*This
= impl_from_ITfSourceSingleVtbl(iface
);
1217 return ThreadMgr_Release((ITfThreadMgr
*)This
);
1220 static HRESULT WINAPI
ThreadMgrSourceSingle_AdviseSingleSink( ITfSourceSingle
*iface
,
1221 TfClientId tid
, REFIID riid
, IUnknown
*punk
)
1223 ThreadMgr
*This
= impl_from_ITfSourceSingleVtbl(iface
);
1224 FIXME("STUB:(%p) %i %s %p\n",This
, tid
, debugstr_guid(riid
),punk
);
1228 static HRESULT WINAPI
ThreadMgrSourceSingle_UnadviseSingleSink( ITfSourceSingle
*iface
,
1229 TfClientId tid
, REFIID riid
)
1231 ThreadMgr
*This
= impl_from_ITfSourceSingleVtbl(iface
);
1232 FIXME("STUB:(%p) %i %s\n",This
, tid
, debugstr_guid(riid
));
1236 static const ITfSourceSingleVtbl ThreadMgr_SourceSingleVtbl
=
1238 ThreadMgrSourceSingle_QueryInterface
,
1239 ThreadMgrSourceSingle_AddRef
,
1240 ThreadMgrSourceSingle_Release
,
1242 ThreadMgrSourceSingle_AdviseSingleSink
,
1243 ThreadMgrSourceSingle_UnadviseSingleSink
,
1246 HRESULT
ThreadMgr_Constructor(IUnknown
*pUnkOuter
, IUnknown
**ppOut
)
1250 return CLASS_E_NOAGGREGATION
;
1252 /* Only 1 ThreadMgr is created per thread */
1253 This
= TlsGetValue(tlsIndex
);
1256 ThreadMgr_AddRef((ITfThreadMgr
*)This
);
1257 *ppOut
= (IUnknown
*)This
;
1261 This
= HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY
,sizeof(ThreadMgr
));
1263 return E_OUTOFMEMORY
;
1265 This
->ThreadMgrVtbl
= &ThreadMgr_ThreadMgrVtbl
;
1266 This
->SourceVtbl
= &ThreadMgr_SourceVtbl
;
1267 This
->KeystrokeMgrVtbl
= &ThreadMgr_KeystrokeMgrVtbl
;
1268 This
->MessagePumpVtbl
= &ThreadMgr_MessagePumpVtbl
;
1269 This
->ClientIdVtbl
= &ThreadMgr_ClientIdVtbl
;
1270 This
->ThreadMgrEventSinkVtbl
= &ThreadMgr_ThreadMgrEventSinkVtbl
;
1271 This
->SourceSingleVtbl
= &ThreadMgr_SourceSingleVtbl
;
1273 TlsSetValue(tlsIndex
,This
);
1275 CompartmentMgr_Constructor((IUnknown
*)This
, &IID_IUnknown
, (IUnknown
**)&This
->CompartmentMgr
);
1277 list_init(&This
->CurrentPreservedKeys
);
1278 list_init(&This
->CreatedDocumentMgrs
);
1279 list_init(&This
->AssociatedFocusWindows
);
1281 list_init(&This
->ActiveLanguageProfileNotifySink
);
1282 list_init(&This
->DisplayAttributeNotifySink
);
1283 list_init(&This
->KeyTraceEventSink
);
1284 list_init(&This
->PreservedKeyNotifySink
);
1285 list_init(&This
->ThreadFocusSink
);
1286 list_init(&This
->ThreadMgrEventSink
);
1288 TRACE("returning %p\n", This
);
1289 *ppOut
= (IUnknown
*)This
;
1293 /**************************************************
1294 * IEnumTfDocumentMgrs implementation
1295 **************************************************/
1296 static void EnumTfDocumentMgr_Destructor(EnumTfDocumentMgr
*This
)
1298 TRACE("destroying %p\n", This
);
1299 HeapFree(GetProcessHeap(),0,This
);
1302 static HRESULT WINAPI
EnumTfDocumentMgr_QueryInterface(IEnumTfDocumentMgrs
*iface
, REFIID iid
, LPVOID
*ppvOut
)
1304 EnumTfDocumentMgr
*This
= (EnumTfDocumentMgr
*)iface
;
1307 if (IsEqualIID(iid
, &IID_IUnknown
) || IsEqualIID(iid
, &IID_IEnumTfDocumentMgrs
))
1314 IEnumTfDocumentMgrs_AddRef(iface
);
1318 WARN("unsupported interface: %s\n", debugstr_guid(iid
));
1319 return E_NOINTERFACE
;
1322 static ULONG WINAPI
EnumTfDocumentMgr_AddRef(IEnumTfDocumentMgrs
*iface
)
1324 EnumTfDocumentMgr
*This
= (EnumTfDocumentMgr
*)iface
;
1325 return InterlockedIncrement(&This
->refCount
);
1328 static ULONG WINAPI
EnumTfDocumentMgr_Release(IEnumTfDocumentMgrs
*iface
)
1330 EnumTfDocumentMgr
*This
= (EnumTfDocumentMgr
*)iface
;
1333 ret
= InterlockedDecrement(&This
->refCount
);
1335 EnumTfDocumentMgr_Destructor(This
);
1339 static HRESULT WINAPI
EnumTfDocumentMgr_Next(IEnumTfDocumentMgrs
*iface
,
1340 ULONG ulCount
, ITfDocumentMgr
**rgDocumentMgr
, ULONG
*pcFetched
)
1342 EnumTfDocumentMgr
*This
= (EnumTfDocumentMgr
*)iface
;
1345 TRACE("(%p)\n",This
);
1347 if (rgDocumentMgr
== NULL
) return E_POINTER
;
1349 while (fetched
< ulCount
)
1351 DocumentMgrEntry
*mgrentry
;
1352 if (This
->index
== NULL
)
1355 mgrentry
= LIST_ENTRY(This
->index
,DocumentMgrEntry
,entry
);
1356 if (mgrentry
== NULL
)
1359 *rgDocumentMgr
= mgrentry
->docmgr
;
1360 ITfDocumentMgr_AddRef(*rgDocumentMgr
);
1362 This
->index
= list_next(This
->head
, This
->index
);
1367 if (pcFetched
) *pcFetched
= fetched
;
1368 return fetched
== ulCount
? S_OK
: S_FALSE
;
1371 static HRESULT WINAPI
EnumTfDocumentMgr_Skip( IEnumTfDocumentMgrs
* iface
, ULONG celt
)
1374 EnumTfDocumentMgr
*This
= (EnumTfDocumentMgr
*)iface
;
1375 TRACE("(%p)\n",This
);
1376 for(i
= 0; i
< celt
&& This
->index
!= NULL
; i
++)
1377 This
->index
= list_next(This
->head
, This
->index
);
1381 static HRESULT WINAPI
EnumTfDocumentMgr_Reset( IEnumTfDocumentMgrs
* iface
)
1383 EnumTfDocumentMgr
*This
= (EnumTfDocumentMgr
*)iface
;
1384 TRACE("(%p)\n",This
);
1385 This
->index
= list_head(This
->head
);
1389 static HRESULT WINAPI
EnumTfDocumentMgr_Clone( IEnumTfDocumentMgrs
*iface
,
1390 IEnumTfDocumentMgrs
**ppenum
)
1392 EnumTfDocumentMgr
*This
= (EnumTfDocumentMgr
*)iface
;
1395 TRACE("(%p)\n",This
);
1397 if (ppenum
== NULL
) return E_POINTER
;
1399 res
= EnumTfDocumentMgr_Constructor(This
->head
, ppenum
);
1402 EnumTfDocumentMgr
*new_This
= (EnumTfDocumentMgr
*)*ppenum
;
1403 new_This
->index
= This
->index
;
1408 static const IEnumTfDocumentMgrsVtbl IEnumTfDocumentMgrs_Vtbl
={
1409 EnumTfDocumentMgr_QueryInterface
,
1410 EnumTfDocumentMgr_AddRef
,
1411 EnumTfDocumentMgr_Release
,
1413 EnumTfDocumentMgr_Clone
,
1414 EnumTfDocumentMgr_Next
,
1415 EnumTfDocumentMgr_Reset
,
1416 EnumTfDocumentMgr_Skip
1419 static HRESULT
EnumTfDocumentMgr_Constructor(struct list
* head
, IEnumTfDocumentMgrs
**ppOut
)
1421 EnumTfDocumentMgr
*This
;
1423 This
= HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY
,sizeof(EnumTfDocumentMgr
));
1425 return E_OUTOFMEMORY
;
1427 This
->Vtbl
= &IEnumTfDocumentMgrs_Vtbl
;
1430 This
->index
= list_head(This
->head
);
1432 TRACE("returning %p\n", This
);
1433 *ppOut
= (IEnumTfDocumentMgrs
*)This
;
1437 void ThreadMgr_OnDocumentMgrDestruction(ITfThreadMgr
*tm
, ITfDocumentMgr
*mgr
)
1439 ThreadMgr
*This
= (ThreadMgr
*)tm
;
1440 struct list
*cursor
;
1441 LIST_FOR_EACH(cursor
, &This
->CreatedDocumentMgrs
)
1443 DocumentMgrEntry
*mgrentry
= LIST_ENTRY(cursor
,DocumentMgrEntry
,entry
);
1444 if (mgrentry
->docmgr
== mgr
)
1446 list_remove(cursor
);
1447 HeapFree(GetProcessHeap(),0,mgrentry
);
1451 FIXME("ITfDocumentMgr %p not found in this thread\n",mgr
);