msctf/tests: Correct wine_todo handling in sinks.
[wine] / dlls / msctf / threadmgr.c
1 /*
2  *  ITfThreadMgr implementation
3  *
4  *  Copyright 2008 Aric Stewart, CodeWeavers
5  *
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.
10  *
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.
15  *
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
19  */
20
21 #include "config.h"
22
23 #include <stdarg.h>
24
25 #define COBJMACROS
26
27 #include "wine/debug.h"
28 #include "windef.h"
29 #include "winbase.h"
30 #include "winreg.h"
31 #include "winuser.h"
32 #include "shlwapi.h"
33 #include "winerror.h"
34 #include "objbase.h"
35 #include "olectl.h"
36
37 #include "wine/unicode.h"
38 #include "wine/list.h"
39
40 #include "msctf.h"
41 #include "msctf_internal.h"
42
43 WINE_DEFAULT_DEBUG_CHANNEL(msctf);
44
45 typedef struct tagThreadMgrSink {
46     struct list         entry;
47     union {
48         /* ThreadMgr Sinks */
49         IUnknown            *pIUnknown;
50         /* ITfActiveLanguageProfileNotifySink *pITfActiveLanguageProfileNotifySink; */
51         /* ITfDisplayAttributeNotifySink *pITfDisplayAttributeNotifySink; */
52         /* ITfKeyTraceEventSink *pITfKeyTraceEventSink; */
53         /* ITfPreservedKeyNotifySink *pITfPreservedKeyNotifySink; */
54         /* ITfThreadFocusSink *pITfThreadFocusSink; */
55         ITfThreadMgrEventSink *pITfThreadMgrEventSink;
56     } interfaces;
57 } ThreadMgrSink;
58
59 typedef struct tagPreservedKey
60 {
61     struct list     entry;
62     GUID            guid;
63     TF_PRESERVEDKEY prekey;
64     LPWSTR          description;
65     TfClientId      tid;
66 } PreservedKey;
67
68 typedef struct tagDocumentMgrs
69 {
70     struct list     entry;
71     ITfDocumentMgr  *docmgr;
72 } DocumentMgrEntry;
73
74 typedef struct tagAssociatedWindow
75 {
76     struct list     entry;
77     HWND            hwnd;
78     ITfDocumentMgr  *docmgr;
79 } AssociatedWindow;
80
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;
92     LONG refCount;
93
94     /* Aggregation */
95     ITfCompartmentMgr  *CompartmentMgr;
96
97     const ITfThreadMgrEventSinkVtbl *ThreadMgrEventSinkVtbl; /* internal */
98
99     ITfDocumentMgr *focus;
100     LONG activationCount;
101
102     ITfKeyEventSink *forgroundKeyEventSink;
103     CLSID forgroundTextService;
104
105     struct list CurrentPreservedKeys;
106     struct list CreatedDocumentMgrs;
107
108     struct list AssociatedFocusWindows;
109     HHOOK  focusHook;
110
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;
118 } ThreadMgr;
119
120 typedef struct tagEnumTfDocumentMgr {
121     const IEnumTfDocumentMgrsVtbl *Vtbl;
122     LONG refCount;
123
124     struct list *index;
125     struct list *head;
126 } EnumTfDocumentMgr;
127
128 static HRESULT EnumTfDocumentMgr_Constructor(struct list* head, IEnumTfDocumentMgrs **ppOut);
129 LRESULT CALLBACK ThreadFocusHookProc(int nCode, WPARAM wParam, LPARAM lParam);
130
131 static inline ThreadMgr *impl_from_ITfSourceVtbl(ITfSource *iface)
132 {
133     return (ThreadMgr *)((char *)iface - FIELD_OFFSET(ThreadMgr,SourceVtbl));
134 }
135
136 static inline ThreadMgr *impl_from_ITfKeystrokeMgrVtbl(ITfKeystrokeMgr *iface)
137 {
138     return (ThreadMgr *)((char *)iface - FIELD_OFFSET(ThreadMgr,KeystrokeMgrVtbl));
139 }
140
141 static inline ThreadMgr *impl_from_ITfMessagePumpVtbl(ITfMessagePump *iface)
142 {
143     return (ThreadMgr *)((char *)iface - FIELD_OFFSET(ThreadMgr,MessagePumpVtbl));
144 }
145
146 static inline ThreadMgr *impl_from_ITfClientIdVtbl(ITfClientId *iface)
147 {
148     return (ThreadMgr *)((char *)iface - FIELD_OFFSET(ThreadMgr,ClientIdVtbl));
149 }
150
151 static inline ThreadMgr *impl_from_ITfThreadMgrEventSink(ITfThreadMgrEventSink *iface)
152 {
153     return (ThreadMgr *)((char *)iface - FIELD_OFFSET(ThreadMgr,ThreadMgrEventSinkVtbl));
154 }
155
156 static inline ThreadMgr *impl_from_ITfSourceSingleVtbl(ITfSourceSingle* iface)
157
158 {
159     return (ThreadMgr *)((char *)iface - FIELD_OFFSET(ThreadMgr,SourceSingleVtbl));
160 }
161
162 static HRESULT SetupWindowsHook(ThreadMgr *This)
163 {
164     if (!This->focusHook)
165     {
166         This->focusHook = SetWindowsHookExW(WH_CBT, ThreadFocusHookProc, 0,
167                              GetCurrentThreadId());
168         if (!This->focusHook)
169         {
170             ERR("Unable to set focus hook\n");
171             return E_FAIL;
172         }
173         return S_OK;
174     }
175     return S_FALSE;
176 }
177
178 static void free_sink(ThreadMgrSink *sink)
179 {
180         IUnknown_Release(sink->interfaces.pIUnknown);
181         HeapFree(GetProcessHeap(),0,sink);
182 }
183
184 static void ThreadMgr_Destructor(ThreadMgr *This)
185 {
186     struct list *cursor, *cursor2;
187
188     /* unhook right away */
189     if (This->focusHook)
190         UnhookWindowsHookEx(This->focusHook);
191
192     TlsSetValue(tlsIndex,NULL);
193     TRACE("destroying %p\n", This);
194     if (This->focus)
195         ITfDocumentMgr_Release(This->focus);
196
197     /* free sinks */
198     LIST_FOR_EACH_SAFE(cursor, cursor2, &This->ActiveLanguageProfileNotifySink)
199     {
200         ThreadMgrSink* sink = LIST_ENTRY(cursor,ThreadMgrSink,entry);
201         list_remove(cursor);
202         free_sink(sink);
203     }
204     LIST_FOR_EACH_SAFE(cursor, cursor2, &This->DisplayAttributeNotifySink)
205     {
206         ThreadMgrSink* sink = LIST_ENTRY(cursor,ThreadMgrSink,entry);
207         list_remove(cursor);
208         free_sink(sink);
209     }
210     LIST_FOR_EACH_SAFE(cursor, cursor2, &This->KeyTraceEventSink)
211     {
212         ThreadMgrSink* sink = LIST_ENTRY(cursor,ThreadMgrSink,entry);
213         list_remove(cursor);
214         free_sink(sink);
215     }
216     LIST_FOR_EACH_SAFE(cursor, cursor2, &This->PreservedKeyNotifySink)
217     {
218         ThreadMgrSink* sink = LIST_ENTRY(cursor,ThreadMgrSink,entry);
219         list_remove(cursor);
220         free_sink(sink);
221     }
222     LIST_FOR_EACH_SAFE(cursor, cursor2, &This->ThreadFocusSink)
223     {
224         ThreadMgrSink* sink = LIST_ENTRY(cursor,ThreadMgrSink,entry);
225         list_remove(cursor);
226         free_sink(sink);
227     }
228     LIST_FOR_EACH_SAFE(cursor, cursor2, &This->ThreadMgrEventSink)
229     {
230         ThreadMgrSink* sink = LIST_ENTRY(cursor,ThreadMgrSink,entry);
231         list_remove(cursor);
232         free_sink(sink);
233     }
234
235     LIST_FOR_EACH_SAFE(cursor, cursor2, &This->CurrentPreservedKeys)
236     {
237         PreservedKey* key = LIST_ENTRY(cursor,PreservedKey,entry);
238         list_remove(cursor);
239         HeapFree(GetProcessHeap(),0,key->description);
240         HeapFree(GetProcessHeap(),0,key);
241     }
242
243     LIST_FOR_EACH_SAFE(cursor, cursor2, &This->CreatedDocumentMgrs)
244     {
245         DocumentMgrEntry *mgr = LIST_ENTRY(cursor,DocumentMgrEntry,entry);
246         list_remove(cursor);
247         FIXME("Left Over ITfDocumentMgr.  Should we do something with it?\n");
248         HeapFree(GetProcessHeap(),0,mgr);
249     }
250
251     LIST_FOR_EACH_SAFE(cursor, cursor2, &This->AssociatedFocusWindows)
252     {
253         AssociatedWindow *wnd = LIST_ENTRY(cursor,AssociatedWindow,entry);
254         list_remove(cursor);
255         HeapFree(GetProcessHeap(),0,wnd);
256     }
257
258     CompartmentMgr_Destructor(This->CompartmentMgr);
259
260     HeapFree(GetProcessHeap(),0,This);
261 }
262
263 static HRESULT WINAPI ThreadMgr_QueryInterface(ITfThreadMgr *iface, REFIID iid, LPVOID *ppvOut)
264 {
265     ThreadMgr *This = (ThreadMgr *)iface;
266     *ppvOut = NULL;
267
268     if (IsEqualIID(iid, &IID_IUnknown) || IsEqualIID(iid, &IID_ITfThreadMgr))
269     {
270         *ppvOut = This;
271     }
272     else if (IsEqualIID(iid, &IID_ITfSource))
273     {
274         *ppvOut = &This->SourceVtbl;
275     }
276     else if (IsEqualIID(iid, &IID_ITfKeystrokeMgr))
277     {
278         *ppvOut = &This->KeystrokeMgrVtbl;
279     }
280     else if (IsEqualIID(iid, &IID_ITfMessagePump))
281     {
282         *ppvOut = &This->MessagePumpVtbl;
283     }
284     else if (IsEqualIID(iid, &IID_ITfClientId))
285     {
286         *ppvOut = &This->ClientIdVtbl;
287     }
288     else if (IsEqualIID(iid, &IID_ITfCompartmentMgr))
289     {
290         *ppvOut = This->CompartmentMgr;
291     }
292     else if (IsEqualIID(iid, &IID_ITfSourceSingle))
293     {
294         *ppvOut = &This->SourceSingleVtbl;
295     }
296
297     if (*ppvOut)
298     {
299         IUnknown_AddRef(iface);
300         return S_OK;
301     }
302
303     WARN("unsupported interface: %s\n", debugstr_guid(iid));
304     return E_NOINTERFACE;
305 }
306
307 static ULONG WINAPI ThreadMgr_AddRef(ITfThreadMgr *iface)
308 {
309     ThreadMgr *This = (ThreadMgr *)iface;
310     return InterlockedIncrement(&This->refCount);
311 }
312
313 static ULONG WINAPI ThreadMgr_Release(ITfThreadMgr *iface)
314 {
315     ThreadMgr *This = (ThreadMgr *)iface;
316     ULONG ret;
317
318     ret = InterlockedDecrement(&This->refCount);
319     if (ret == 0)
320         ThreadMgr_Destructor(This);
321     return ret;
322 }
323
324 /*****************************************************
325  * ITfThreadMgr functions
326  *****************************************************/
327
328 static HRESULT WINAPI ThreadMgr_fnActivate( ITfThreadMgr* iface, TfClientId *ptid)
329 {
330     ThreadMgr *This = (ThreadMgr *)iface;
331
332     TRACE("(%p) %p\n",This, ptid);
333
334     if (!ptid)
335         return E_INVALIDARG;
336
337     if (!processId)
338     {
339         GUID guid;
340         CoCreateGuid(&guid);
341         ITfClientId_GetClientId((ITfClientId*)&This->ClientIdVtbl,&guid,&processId);
342     }
343
344     activate_textservices(iface);
345     This->activationCount++;
346     *ptid = processId;
347     return S_OK;
348 }
349
350 static HRESULT WINAPI ThreadMgr_fnDeactivate( ITfThreadMgr* iface)
351 {
352     ThreadMgr *This = (ThreadMgr *)iface;
353     TRACE("(%p)\n",This);
354
355     if (This->activationCount == 0)
356         return E_UNEXPECTED;
357
358     This->activationCount --;
359
360     if (This->activationCount == 0)
361     {
362         if (This->focus)
363         {
364             ITfThreadMgrEventSink_OnSetFocus((ITfThreadMgrEventSink*)&This->ThreadMgrEventSinkVtbl, 0, This->focus);
365             ITfDocumentMgr_Release(This->focus);
366             This->focus = 0;
367         }
368     }
369
370     deactivate_textservices();
371
372     return S_OK;
373 }
374
375 static HRESULT WINAPI ThreadMgr_CreateDocumentMgr( ITfThreadMgr* iface, ITfDocumentMgr
376 **ppdim)
377 {
378     ThreadMgr *This = (ThreadMgr *)iface;
379     DocumentMgrEntry *mgrentry;
380     HRESULT hr;
381
382     TRACE("(%p)\n",iface);
383     mgrentry = HeapAlloc(GetProcessHeap(),0,sizeof(DocumentMgrEntry));
384     if (mgrentry == NULL)
385         return E_OUTOFMEMORY;
386
387     hr = DocumentMgr_Constructor((ITfThreadMgrEventSink*)&This->ThreadMgrEventSinkVtbl, ppdim);
388
389     if (SUCCEEDED(hr))
390     {
391         mgrentry->docmgr = *ppdim;
392         list_add_head(&This->CreatedDocumentMgrs,&mgrentry->entry);
393     }
394     else
395         HeapFree(GetProcessHeap(),0,mgrentry);
396
397     return hr;
398 }
399
400 static HRESULT WINAPI ThreadMgr_EnumDocumentMgrs( ITfThreadMgr* iface, IEnumTfDocumentMgrs
401 **ppEnum)
402 {
403     ThreadMgr *This = (ThreadMgr *)iface;
404     TRACE("(%p) %p\n",This,ppEnum);
405
406     if (!ppEnum)
407         return E_INVALIDARG;
408
409     return EnumTfDocumentMgr_Constructor(&This->CreatedDocumentMgrs, ppEnum);
410 }
411
412 static HRESULT WINAPI ThreadMgr_GetFocus( ITfThreadMgr* iface, ITfDocumentMgr
413 **ppdimFocus)
414 {
415     ThreadMgr *This = (ThreadMgr *)iface;
416     TRACE("(%p)\n",This);
417
418     if (!ppdimFocus)
419         return E_INVALIDARG;
420
421     *ppdimFocus = This->focus;
422
423     TRACE("->%p\n",This->focus);
424
425     if (This->focus == NULL)
426         return S_FALSE;
427
428     ITfDocumentMgr_AddRef(This->focus);
429
430     return S_OK;
431 }
432
433 static HRESULT WINAPI ThreadMgr_SetFocus( ITfThreadMgr* iface, ITfDocumentMgr *pdimFocus)
434 {
435     ITfDocumentMgr *check;
436     ThreadMgr *This = (ThreadMgr *)iface;
437
438     TRACE("(%p) %p\n",This,pdimFocus);
439
440     if (!pdimFocus)
441         check = NULL;
442     else if (FAILED(IUnknown_QueryInterface(pdimFocus,&IID_ITfDocumentMgr,(LPVOID*) &check)))
443         return E_INVALIDARG;
444
445     ITfThreadMgrEventSink_OnSetFocus((ITfThreadMgrEventSink*)&This->ThreadMgrEventSinkVtbl, check, This->focus);
446
447     if (This->focus)
448         ITfDocumentMgr_Release(This->focus);
449
450     This->focus = check;
451     return S_OK;
452 }
453
454 static HRESULT WINAPI ThreadMgr_AssociateFocus( ITfThreadMgr* iface, HWND hwnd,
455 ITfDocumentMgr *pdimNew, ITfDocumentMgr **ppdimPrev)
456 {
457     struct list *cursor, *cursor2;
458     ThreadMgr *This = (ThreadMgr *)iface;
459     AssociatedWindow *wnd;
460
461     TRACE("(%p) %p %p %p\n",This,hwnd,pdimNew,ppdimPrev);
462
463     if (!ppdimPrev)
464         return E_INVALIDARG;
465
466     *ppdimPrev = NULL;
467
468     LIST_FOR_EACH_SAFE(cursor, cursor2, &This->AssociatedFocusWindows)
469     {
470         wnd = LIST_ENTRY(cursor,AssociatedWindow,entry);
471         if (wnd->hwnd == hwnd)
472         {
473             if (wnd->docmgr)
474                 ITfDocumentMgr_AddRef(wnd->docmgr);
475             *ppdimPrev = wnd->docmgr;
476             wnd->docmgr = pdimNew;
477             if (GetFocus() == hwnd)
478                 ThreadMgr_SetFocus(iface,pdimNew);
479             return S_OK;
480         }
481     }
482
483     wnd = HeapAlloc(GetProcessHeap(),0,sizeof(AssociatedWindow));
484     wnd->hwnd = hwnd;
485     wnd->docmgr = pdimNew;
486     list_add_head(&This->AssociatedFocusWindows,&wnd->entry);
487
488     if (GetFocus() == hwnd)
489         ThreadMgr_SetFocus(iface,pdimNew);
490
491     SetupWindowsHook(This);
492
493     return S_OK;
494 }
495
496 static HRESULT WINAPI ThreadMgr_IsThreadFocus( ITfThreadMgr* iface, BOOL *pfThreadFocus)
497 {
498     HWND focus;
499     ThreadMgr *This = (ThreadMgr *)iface;
500     TRACE("(%p) %p\n",This,pfThreadFocus);
501     focus = GetFocus();
502     *pfThreadFocus = (focus == NULL);
503     return S_OK;
504 }
505
506 static HRESULT WINAPI ThreadMgr_GetFunctionProvider( ITfThreadMgr* iface, REFCLSID clsid,
507 ITfFunctionProvider **ppFuncProv)
508 {
509     ThreadMgr *This = (ThreadMgr *)iface;
510     FIXME("STUB:(%p)\n",This);
511     return E_NOTIMPL;
512 }
513
514 static HRESULT WINAPI ThreadMgr_EnumFunctionProviders( ITfThreadMgr* iface,
515 IEnumTfFunctionProviders **ppEnum)
516 {
517     ThreadMgr *This = (ThreadMgr *)iface;
518     FIXME("STUB:(%p)\n",This);
519     return E_NOTIMPL;
520 }
521
522 static HRESULT WINAPI ThreadMgr_GetGlobalCompartment( ITfThreadMgr* iface,
523 ITfCompartmentMgr **ppCompMgr)
524 {
525     ThreadMgr *This = (ThreadMgr *)iface;
526     HRESULT hr;
527     TRACE("(%p) %p\n",This, ppCompMgr);
528
529     if (!ppCompMgr)
530         return E_INVALIDARG;
531
532     if (!globalCompartmentMgr)
533     {
534         hr = CompartmentMgr_Constructor(NULL,&IID_ITfCompartmentMgr,(IUnknown**)&globalCompartmentMgr);
535         if (FAILED(hr))
536             return hr;
537     }
538
539     ITfCompartmentMgr_AddRef(globalCompartmentMgr);
540     *ppCompMgr = globalCompartmentMgr;
541     return S_OK;
542 }
543
544 static const ITfThreadMgrVtbl ThreadMgr_ThreadMgrVtbl =
545 {
546     ThreadMgr_QueryInterface,
547     ThreadMgr_AddRef,
548     ThreadMgr_Release,
549
550     ThreadMgr_fnActivate,
551     ThreadMgr_fnDeactivate,
552     ThreadMgr_CreateDocumentMgr,
553     ThreadMgr_EnumDocumentMgrs,
554     ThreadMgr_GetFocus,
555     ThreadMgr_SetFocus,
556     ThreadMgr_AssociateFocus,
557     ThreadMgr_IsThreadFocus,
558     ThreadMgr_GetFunctionProvider,
559     ThreadMgr_EnumFunctionProviders,
560     ThreadMgr_GetGlobalCompartment
561 };
562
563
564 static HRESULT WINAPI Source_QueryInterface(ITfSource *iface, REFIID iid, LPVOID *ppvOut)
565 {
566     ThreadMgr *This = impl_from_ITfSourceVtbl(iface);
567     return ThreadMgr_QueryInterface((ITfThreadMgr *)This, iid, *ppvOut);
568 }
569
570 static ULONG WINAPI Source_AddRef(ITfSource *iface)
571 {
572     ThreadMgr *This = impl_from_ITfSourceVtbl(iface);
573     return ThreadMgr_AddRef((ITfThreadMgr*)This);
574 }
575
576 static ULONG WINAPI Source_Release(ITfSource *iface)
577 {
578     ThreadMgr *This = impl_from_ITfSourceVtbl(iface);
579     return ThreadMgr_Release((ITfThreadMgr *)This);
580 }
581
582 /*****************************************************
583  * ITfSource functions
584  *****************************************************/
585 static WINAPI HRESULT ThreadMgrSource_AdviseSink(ITfSource *iface,
586         REFIID riid, IUnknown *punk, DWORD *pdwCookie)
587 {
588     ThreadMgrSink *tms;
589     ThreadMgr *This = impl_from_ITfSourceVtbl(iface);
590
591     TRACE("(%p) %s %p %p\n",This,debugstr_guid(riid),punk,pdwCookie);
592
593     if (!riid || !punk || !pdwCookie)
594         return E_INVALIDARG;
595
596     if (IsEqualIID(riid, &IID_ITfThreadMgrEventSink))
597     {
598         tms = HeapAlloc(GetProcessHeap(),0,sizeof(ThreadMgrSink));
599         if (!tms)
600             return E_OUTOFMEMORY;
601         if (FAILED(IUnknown_QueryInterface(punk, riid, (LPVOID *)&tms->interfaces.pITfThreadMgrEventSink)))
602         {
603             HeapFree(GetProcessHeap(),0,tms);
604             return CONNECT_E_CANNOTCONNECT;
605         }
606         list_add_head(&This->ThreadMgrEventSink,&tms->entry);
607         *pdwCookie = generate_Cookie(COOKIE_MAGIC_TMSINK, tms);
608     }
609     else
610     {
611         FIXME("(%p) Unhandled Sink: %s\n",This,debugstr_guid(riid));
612         return E_NOTIMPL;
613     }
614
615     TRACE("cookie %x\n",*pdwCookie);
616
617     return S_OK;
618 }
619
620 static WINAPI HRESULT ThreadMgrSource_UnadviseSink(ITfSource *iface, DWORD pdwCookie)
621 {
622     ThreadMgrSink *sink;
623     ThreadMgr *This = impl_from_ITfSourceVtbl(iface);
624
625     TRACE("(%p) %x\n",This,pdwCookie);
626
627     if (get_Cookie_magic(pdwCookie)!=COOKIE_MAGIC_TMSINK)
628         return E_INVALIDARG;
629
630     sink = (ThreadMgrSink*)remove_Cookie(pdwCookie);
631     if (!sink)
632         return CONNECT_E_NOCONNECTION;
633
634     list_remove(&sink->entry);
635     free_sink(sink);
636
637     return S_OK;
638 }
639
640 static const ITfSourceVtbl ThreadMgr_SourceVtbl =
641 {
642     Source_QueryInterface,
643     Source_AddRef,
644     Source_Release,
645
646     ThreadMgrSource_AdviseSink,
647     ThreadMgrSource_UnadviseSink,
648 };
649
650 /*****************************************************
651  * ITfKeystrokeMgr functions
652  *****************************************************/
653
654 static HRESULT WINAPI KeystrokeMgr_QueryInterface(ITfKeystrokeMgr *iface, REFIID iid, LPVOID *ppvOut)
655 {
656     ThreadMgr *This = impl_from_ITfKeystrokeMgrVtbl(iface);
657     return ThreadMgr_QueryInterface((ITfThreadMgr *)This, iid, *ppvOut);
658 }
659
660 static ULONG WINAPI KeystrokeMgr_AddRef(ITfKeystrokeMgr *iface)
661 {
662     ThreadMgr *This = impl_from_ITfKeystrokeMgrVtbl(iface);
663     return ThreadMgr_AddRef((ITfThreadMgr*)This);
664 }
665
666 static ULONG WINAPI KeystrokeMgr_Release(ITfKeystrokeMgr *iface)
667 {
668     ThreadMgr *This = impl_from_ITfKeystrokeMgrVtbl(iface);
669     return ThreadMgr_Release((ITfThreadMgr *)This);
670 }
671
672 static HRESULT WINAPI KeystrokeMgr_AdviseKeyEventSink(ITfKeystrokeMgr *iface,
673         TfClientId tid, ITfKeyEventSink *pSink, BOOL fForeground)
674 {
675     ThreadMgr *This = impl_from_ITfKeystrokeMgrVtbl(iface);
676     CLSID textservice;
677     ITfKeyEventSink *check = NULL;
678
679     TRACE("(%p) %x %p %i\n",This,tid,pSink,fForeground);
680
681     if (!tid || !pSink)
682         return E_INVALIDARG;
683
684     textservice = get_textservice_clsid(tid);
685     if (IsEqualCLSID(&GUID_NULL,&textservice))
686         return E_INVALIDARG;
687
688     get_textservice_sink(tid, &IID_ITfKeyEventSink, (IUnknown**)&check);
689     if (check != NULL)
690         return CONNECT_E_ADVISELIMIT;
691
692     if (FAILED(IUnknown_QueryInterface(pSink,&IID_ITfKeyEventSink,(LPVOID*) &check)))
693         return E_INVALIDARG;
694
695     set_textservice_sink(tid, &IID_ITfKeyEventSink, (IUnknown*)check);
696
697     if (fForeground)
698     {
699         if (This->forgroundKeyEventSink)
700         {
701             ITfKeyEventSink_OnSetFocus(This->forgroundKeyEventSink, FALSE);
702             ITfKeyEventSink_Release(This->forgroundKeyEventSink);
703         }
704         ITfKeyEventSink_AddRef(check);
705         ITfKeyEventSink_OnSetFocus(check, TRUE);
706         This->forgroundKeyEventSink = check;
707         This->forgroundTextService = textservice;
708     }
709     return S_OK;
710 }
711
712 static HRESULT WINAPI KeystrokeMgr_UnadviseKeyEventSink(ITfKeystrokeMgr *iface,
713         TfClientId tid)
714 {
715     ThreadMgr *This = impl_from_ITfKeystrokeMgrVtbl(iface);
716     CLSID textservice;
717     ITfKeyEventSink *check = NULL;
718     TRACE("(%p) %x\n",This,tid);
719
720     if (!tid)
721         return E_INVALIDARG;
722
723     textservice = get_textservice_clsid(tid);
724     if (IsEqualCLSID(&GUID_NULL,&textservice))
725         return E_INVALIDARG;
726
727     get_textservice_sink(tid, &IID_ITfKeyEventSink, (IUnknown**)&check);
728
729     if (!check)
730         return CONNECT_E_NOCONNECTION;
731
732     set_textservice_sink(tid, &IID_ITfKeyEventSink, NULL);
733     ITfKeyEventSink_Release(check);
734
735     if (This->forgroundKeyEventSink == check)
736     {
737         ITfKeyEventSink_Release(This->forgroundKeyEventSink);
738         This->forgroundKeyEventSink = NULL;
739         This->forgroundTextService = GUID_NULL;
740     }
741     return S_OK;
742 }
743
744 static HRESULT WINAPI KeystrokeMgr_GetForeground(ITfKeystrokeMgr *iface,
745         CLSID *pclsid)
746 {
747     ThreadMgr *This = impl_from_ITfKeystrokeMgrVtbl(iface);
748     TRACE("(%p) %p\n",This,pclsid);
749     if (!pclsid)
750         return E_INVALIDARG;
751
752     if (IsEqualCLSID(&This->forgroundTextService,&GUID_NULL))
753         return S_FALSE;
754
755     *pclsid = This->forgroundTextService;
756     return S_OK;
757 }
758
759 static HRESULT WINAPI KeystrokeMgr_TestKeyDown(ITfKeystrokeMgr *iface,
760         WPARAM wParam, LPARAM lParam, BOOL *pfEaten)
761 {
762     ThreadMgr *This = impl_from_ITfKeystrokeMgrVtbl(iface);
763     FIXME("STUB:(%p)\n",This);
764     return E_NOTIMPL;
765 }
766
767 static HRESULT WINAPI KeystrokeMgr_TestKeyUp(ITfKeystrokeMgr *iface,
768         WPARAM wParam, LPARAM lParam, BOOL *pfEaten)
769 {
770     ThreadMgr *This = impl_from_ITfKeystrokeMgrVtbl(iface);
771     FIXME("STUB:(%p)\n",This);
772     return E_NOTIMPL;
773 }
774
775 static HRESULT WINAPI KeystrokeMgr_KeyDown(ITfKeystrokeMgr *iface,
776         WPARAM wParam, LPARAM lParam, BOOL *pfEaten)
777 {
778     ThreadMgr *This = impl_from_ITfKeystrokeMgrVtbl(iface);
779     FIXME("STUB:(%p)\n",This);
780     return E_NOTIMPL;
781 }
782
783 static HRESULT WINAPI KeystrokeMgr_KeyUp(ITfKeystrokeMgr *iface,
784         WPARAM wParam, LPARAM lParam, BOOL *pfEaten)
785 {
786     ThreadMgr *This = impl_from_ITfKeystrokeMgrVtbl(iface);
787     FIXME("STUB:(%p)\n",This);
788     return E_NOTIMPL;
789 }
790
791 static HRESULT WINAPI KeystrokeMgr_GetPreservedKey(ITfKeystrokeMgr *iface,
792         ITfContext *pic, const TF_PRESERVEDKEY *pprekey, GUID *pguid)
793 {
794     ThreadMgr *This = impl_from_ITfKeystrokeMgrVtbl(iface);
795     FIXME("STUB:(%p)\n",This);
796     return E_NOTIMPL;
797 }
798
799 static HRESULT WINAPI KeystrokeMgr_IsPreservedKey(ITfKeystrokeMgr *iface,
800         REFGUID rguid, const TF_PRESERVEDKEY *pprekey, BOOL *pfRegistered)
801 {
802     ThreadMgr *This = impl_from_ITfKeystrokeMgrVtbl(iface);
803     struct list *cursor;
804
805     TRACE("(%p) %s (%x %x) %p\n",This,debugstr_guid(rguid), (pprekey)?pprekey->uVKey:0, (pprekey)?pprekey->uModifiers:0, pfRegistered);
806
807     if (!rguid || !pprekey || !pfRegistered)
808         return E_INVALIDARG;
809
810     LIST_FOR_EACH(cursor, &This->CurrentPreservedKeys)
811     {
812         PreservedKey* key = LIST_ENTRY(cursor,PreservedKey,entry);
813         if (IsEqualGUID(rguid,&key->guid) && pprekey->uVKey == key->prekey.uVKey && pprekey->uModifiers == key->prekey.uModifiers)
814         {
815             *pfRegistered = TRUE;
816             return S_OK;
817         }
818     }
819
820     *pfRegistered = FALSE;
821     return S_FALSE;
822 }
823
824 static HRESULT WINAPI KeystrokeMgr_PreserveKey(ITfKeystrokeMgr *iface,
825         TfClientId tid, REFGUID rguid, const TF_PRESERVEDKEY *prekey,
826         const WCHAR *pchDesc, ULONG cchDesc)
827 {
828     ThreadMgr *This = impl_from_ITfKeystrokeMgrVtbl(iface);
829     struct list *cursor;
830     PreservedKey *newkey;
831
832     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));
833
834     if (!tid || ! rguid || !prekey || (cchDesc && !pchDesc))
835         return E_INVALIDARG;
836
837     LIST_FOR_EACH(cursor, &This->CurrentPreservedKeys)
838     {
839         PreservedKey* key = LIST_ENTRY(cursor,PreservedKey,entry);
840         if (IsEqualGUID(rguid,&key->guid) && prekey->uVKey == key->prekey.uVKey && prekey->uModifiers == key->prekey.uModifiers)
841             return TF_E_ALREADY_EXISTS;
842     }
843
844     newkey = HeapAlloc(GetProcessHeap(),0,sizeof(PreservedKey));
845     if (!newkey)
846         return E_OUTOFMEMORY;
847
848     newkey->guid  = *rguid;
849     newkey->prekey = *prekey;
850     newkey->tid = tid;
851     if (cchDesc)
852     {
853         newkey->description = HeapAlloc(GetProcessHeap(),0,cchDesc * sizeof(WCHAR));
854         if (!newkey->description)
855         {
856             HeapFree(GetProcessHeap(),0,newkey);
857             return E_OUTOFMEMORY;
858         }
859         memcpy(newkey->description, pchDesc, cchDesc*sizeof(WCHAR));
860     }
861
862     list_add_head(&This->CurrentPreservedKeys,&newkey->entry);
863
864     return S_OK;
865 }
866
867 static HRESULT WINAPI KeystrokeMgr_UnpreserveKey(ITfKeystrokeMgr *iface,
868         REFGUID rguid, const TF_PRESERVEDKEY *pprekey)
869 {
870     ThreadMgr *This = impl_from_ITfKeystrokeMgrVtbl(iface);
871     PreservedKey* key = NULL;
872     struct list *cursor;
873     TRACE("(%p) %s (%x %x)\n",This,debugstr_guid(rguid),(pprekey)?pprekey->uVKey:0, (pprekey)?pprekey->uModifiers:0);
874
875     if (!pprekey || !rguid)
876         return E_INVALIDARG;
877
878     LIST_FOR_EACH(cursor, &This->CurrentPreservedKeys)
879     {
880         key = LIST_ENTRY(cursor,PreservedKey,entry);
881         if (IsEqualGUID(rguid,&key->guid) && pprekey->uVKey == key->prekey.uVKey && pprekey->uModifiers == key->prekey.uModifiers)
882             break;
883         key = NULL;
884     }
885
886     if (!key)
887         return CONNECT_E_NOCONNECTION;
888
889     list_remove(&key->entry);
890     HeapFree(GetProcessHeap(),0,key->description);
891     HeapFree(GetProcessHeap(),0,key);
892
893     return S_OK;
894 }
895
896 static HRESULT WINAPI KeystrokeMgr_SetPreservedKeyDescription(ITfKeystrokeMgr *iface,
897         REFGUID rguid, const WCHAR *pchDesc, ULONG cchDesc)
898 {
899     ThreadMgr *This = impl_from_ITfKeystrokeMgrVtbl(iface);
900     FIXME("STUB:(%p)\n",This);
901     return E_NOTIMPL;
902 }
903
904 static HRESULT WINAPI KeystrokeMgr_GetPreservedKeyDescription(ITfKeystrokeMgr *iface,
905         REFGUID rguid, BSTR *pbstrDesc)
906 {
907     ThreadMgr *This = impl_from_ITfKeystrokeMgrVtbl(iface);
908     FIXME("STUB:(%p)\n",This);
909     return E_NOTIMPL;
910 }
911
912 static HRESULT WINAPI KeystrokeMgr_SimulatePreservedKey(ITfKeystrokeMgr *iface,
913         ITfContext *pic, REFGUID rguid, BOOL *pfEaten)
914 {
915     ThreadMgr *This = impl_from_ITfKeystrokeMgrVtbl(iface);
916     FIXME("STUB:(%p)\n",This);
917     return E_NOTIMPL;
918 }
919
920 static const ITfKeystrokeMgrVtbl ThreadMgr_KeystrokeMgrVtbl =
921 {
922     KeystrokeMgr_QueryInterface,
923     KeystrokeMgr_AddRef,
924     KeystrokeMgr_Release,
925
926     KeystrokeMgr_AdviseKeyEventSink,
927     KeystrokeMgr_UnadviseKeyEventSink,
928     KeystrokeMgr_GetForeground,
929     KeystrokeMgr_TestKeyDown,
930     KeystrokeMgr_TestKeyUp,
931     KeystrokeMgr_KeyDown,
932     KeystrokeMgr_KeyUp,
933     KeystrokeMgr_GetPreservedKey,
934     KeystrokeMgr_IsPreservedKey,
935     KeystrokeMgr_PreserveKey,
936     KeystrokeMgr_UnpreserveKey,
937     KeystrokeMgr_SetPreservedKeyDescription,
938     KeystrokeMgr_GetPreservedKeyDescription,
939     KeystrokeMgr_SimulatePreservedKey
940 };
941
942 /*****************************************************
943  * ITfMessagePump functions
944  *****************************************************/
945
946 static HRESULT WINAPI MessagePump_QueryInterface(ITfMessagePump *iface, REFIID iid, LPVOID *ppvOut)
947 {
948     ThreadMgr *This = impl_from_ITfMessagePumpVtbl(iface);
949     return ThreadMgr_QueryInterface((ITfThreadMgr *)This, iid, *ppvOut);
950 }
951
952 static ULONG WINAPI MessagePump_AddRef(ITfMessagePump *iface)
953 {
954     ThreadMgr *This = impl_from_ITfMessagePumpVtbl(iface);
955     return ThreadMgr_AddRef((ITfThreadMgr*)This);
956 }
957
958 static ULONG WINAPI MessagePump_Release(ITfMessagePump *iface)
959 {
960     ThreadMgr *This = impl_from_ITfMessagePumpVtbl(iface);
961     return ThreadMgr_Release((ITfThreadMgr *)This);
962 }
963
964 static HRESULT WINAPI MessagePump_PeekMessageA(ITfMessagePump *iface,
965         LPMSG pMsg, HWND hwnd, UINT wMsgFilterMin, UINT wMsgFilterMax,
966         UINT wRemoveMsg, BOOL *pfResult)
967 {
968     if (!pfResult)
969         return E_INVALIDARG;
970     *pfResult = PeekMessageA(pMsg, hwnd, wMsgFilterMin, wMsgFilterMax, wRemoveMsg);
971     return S_OK;
972 }
973
974 static HRESULT WINAPI MessagePump_GetMessageA(ITfMessagePump *iface,
975         LPMSG pMsg, HWND hwnd, UINT wMsgFilterMin, UINT wMsgFilterMax,
976         BOOL *pfResult)
977 {
978     if (!pfResult)
979         return E_INVALIDARG;
980     *pfResult = GetMessageA(pMsg, hwnd, wMsgFilterMin, wMsgFilterMax);
981     return S_OK;
982 }
983
984 static HRESULT WINAPI MessagePump_PeekMessageW(ITfMessagePump *iface,
985         LPMSG pMsg, HWND hwnd, UINT wMsgFilterMin, UINT wMsgFilterMax,
986         UINT wRemoveMsg, BOOL *pfResult)
987 {
988     if (!pfResult)
989         return E_INVALIDARG;
990     *pfResult = PeekMessageW(pMsg, hwnd, wMsgFilterMin, wMsgFilterMax, wRemoveMsg);
991     return S_OK;
992 }
993
994 static HRESULT WINAPI MessagePump_GetMessageW(ITfMessagePump *iface,
995         LPMSG pMsg, HWND hwnd, UINT wMsgFilterMin, UINT wMsgFilterMax,
996         BOOL *pfResult)
997 {
998     if (!pfResult)
999         return E_INVALIDARG;
1000     *pfResult = GetMessageW(pMsg, hwnd, wMsgFilterMin, wMsgFilterMax);
1001     return S_OK;
1002 }
1003
1004 static const ITfMessagePumpVtbl ThreadMgr_MessagePumpVtbl =
1005 {
1006     MessagePump_QueryInterface,
1007     MessagePump_AddRef,
1008     MessagePump_Release,
1009
1010     MessagePump_PeekMessageA,
1011     MessagePump_GetMessageA,
1012     MessagePump_PeekMessageW,
1013     MessagePump_GetMessageW
1014 };
1015
1016 /*****************************************************
1017  * ITfClientId functions
1018  *****************************************************/
1019
1020 static HRESULT WINAPI ClientId_QueryInterface(ITfClientId *iface, REFIID iid, LPVOID *ppvOut)
1021 {
1022     ThreadMgr *This = impl_from_ITfClientIdVtbl(iface);
1023     return ThreadMgr_QueryInterface((ITfThreadMgr *)This, iid, *ppvOut);
1024 }
1025
1026 static ULONG WINAPI ClientId_AddRef(ITfClientId *iface)
1027 {
1028     ThreadMgr *This = impl_from_ITfClientIdVtbl(iface);
1029     return ThreadMgr_AddRef((ITfThreadMgr*)This);
1030 }
1031
1032 static ULONG WINAPI ClientId_Release(ITfClientId *iface)
1033 {
1034     ThreadMgr *This = impl_from_ITfClientIdVtbl(iface);
1035     return ThreadMgr_Release((ITfThreadMgr *)This);
1036 }
1037
1038 static HRESULT WINAPI ClientId_GetClientId(ITfClientId *iface,
1039     REFCLSID rclsid, TfClientId *ptid)
1040
1041 {
1042     HRESULT hr;
1043     ITfCategoryMgr *catmgr;
1044     ThreadMgr *This = impl_from_ITfClientIdVtbl(iface);
1045
1046     TRACE("(%p) %s\n",This,debugstr_guid(rclsid));
1047
1048     CategoryMgr_Constructor(NULL,(IUnknown**)&catmgr);
1049     hr = ITfCategoryMgr_RegisterGUID(catmgr,rclsid,ptid);
1050     ITfCategoryMgr_Release(catmgr);
1051
1052     return hr;
1053 }
1054
1055 static const ITfClientIdVtbl ThreadMgr_ClientIdVtbl =
1056 {
1057     ClientId_QueryInterface,
1058     ClientId_AddRef,
1059     ClientId_Release,
1060
1061     ClientId_GetClientId
1062 };
1063
1064 /*****************************************************
1065  * ITfThreadMgrEventSink functions  (internal)
1066  *****************************************************/
1067 static HRESULT WINAPI ThreadMgrEventSink_QueryInterface(ITfThreadMgrEventSink *iface, REFIID iid, LPVOID *ppvOut)
1068 {
1069     ThreadMgr *This = impl_from_ITfThreadMgrEventSink(iface);
1070     return ThreadMgr_QueryInterface((ITfThreadMgr *)This, iid, *ppvOut);
1071 }
1072
1073 static ULONG WINAPI ThreadMgrEventSink_AddRef(ITfThreadMgrEventSink *iface)
1074 {
1075     ThreadMgr *This = impl_from_ITfThreadMgrEventSink(iface);
1076     return ThreadMgr_AddRef((ITfThreadMgr*)This);
1077 }
1078
1079 static ULONG WINAPI ThreadMgrEventSink_Release(ITfThreadMgrEventSink *iface)
1080 {
1081     ThreadMgr *This = impl_from_ITfThreadMgrEventSink(iface);
1082     return ThreadMgr_Release((ITfThreadMgr *)This);
1083 }
1084
1085
1086 static WINAPI HRESULT ThreadMgrEventSink_OnInitDocumentMgr(
1087         ITfThreadMgrEventSink *iface,ITfDocumentMgr *pdim)
1088 {
1089     struct list *cursor;
1090     ThreadMgr *This = impl_from_ITfThreadMgrEventSink(iface);
1091
1092     TRACE("(%p) %p\n",This,pdim);
1093
1094     LIST_FOR_EACH(cursor, &This->ThreadMgrEventSink)
1095     {
1096         ThreadMgrSink* sink = LIST_ENTRY(cursor,ThreadMgrSink,entry);
1097         ITfThreadMgrEventSink_OnInitDocumentMgr(sink->interfaces.pITfThreadMgrEventSink,pdim);
1098     }
1099
1100     return S_OK;
1101 }
1102
1103 static WINAPI HRESULT ThreadMgrEventSink_OnUninitDocumentMgr(
1104         ITfThreadMgrEventSink *iface, ITfDocumentMgr *pdim)
1105 {
1106     struct list *cursor;
1107     ThreadMgr *This = impl_from_ITfThreadMgrEventSink(iface);
1108
1109     TRACE("(%p) %p\n",This,pdim);
1110
1111     LIST_FOR_EACH(cursor, &This->ThreadMgrEventSink)
1112     {
1113         ThreadMgrSink* sink = LIST_ENTRY(cursor,ThreadMgrSink,entry);
1114         ITfThreadMgrEventSink_OnUninitDocumentMgr(sink->interfaces.pITfThreadMgrEventSink,pdim);
1115     }
1116
1117     return S_OK;
1118 }
1119
1120 static WINAPI HRESULT ThreadMgrEventSink_OnSetFocus(
1121         ITfThreadMgrEventSink *iface, ITfDocumentMgr *pdimFocus,
1122         ITfDocumentMgr *pdimPrevFocus)
1123 {
1124     struct list *cursor;
1125     ThreadMgr *This = impl_from_ITfThreadMgrEventSink(iface);
1126
1127     TRACE("(%p) %p %p\n",This,pdimFocus, pdimPrevFocus);
1128
1129     LIST_FOR_EACH(cursor, &This->ThreadMgrEventSink)
1130     {
1131         ThreadMgrSink* sink = LIST_ENTRY(cursor,ThreadMgrSink,entry);
1132         ITfThreadMgrEventSink_OnSetFocus(sink->interfaces.pITfThreadMgrEventSink, pdimFocus, pdimPrevFocus);
1133     }
1134
1135     return S_OK;
1136 }
1137
1138 static WINAPI HRESULT ThreadMgrEventSink_OnPushContext(
1139         ITfThreadMgrEventSink *iface, ITfContext *pic)
1140 {
1141     struct list *cursor;
1142     ThreadMgr *This = impl_from_ITfThreadMgrEventSink(iface);
1143
1144     TRACE("(%p) %p\n",This,pic);
1145
1146     LIST_FOR_EACH(cursor, &This->ThreadMgrEventSink)
1147     {
1148         ThreadMgrSink* sink = LIST_ENTRY(cursor,ThreadMgrSink,entry);
1149         ITfThreadMgrEventSink_OnPushContext(sink->interfaces.pITfThreadMgrEventSink,pic);
1150     }
1151
1152     return S_OK;
1153 }
1154
1155 static WINAPI HRESULT ThreadMgrEventSink_OnPopContext(
1156         ITfThreadMgrEventSink *iface, ITfContext *pic)
1157 {
1158     struct list *cursor;
1159     ThreadMgr *This = impl_from_ITfThreadMgrEventSink(iface);
1160
1161     TRACE("(%p) %p\n",This,pic);
1162
1163     LIST_FOR_EACH(cursor, &This->ThreadMgrEventSink)
1164     {
1165         ThreadMgrSink* sink = LIST_ENTRY(cursor,ThreadMgrSink,entry);
1166         ITfThreadMgrEventSink_OnPopContext(sink->interfaces.pITfThreadMgrEventSink,pic);
1167     }
1168
1169     return S_OK;
1170 }
1171
1172 static const ITfThreadMgrEventSinkVtbl ThreadMgr_ThreadMgrEventSinkVtbl =
1173 {
1174     ThreadMgrEventSink_QueryInterface,
1175     ThreadMgrEventSink_AddRef,
1176     ThreadMgrEventSink_Release,
1177
1178     ThreadMgrEventSink_OnInitDocumentMgr,
1179     ThreadMgrEventSink_OnUninitDocumentMgr,
1180     ThreadMgrEventSink_OnSetFocus,
1181     ThreadMgrEventSink_OnPushContext,
1182     ThreadMgrEventSink_OnPopContext
1183 };
1184
1185 /*****************************************************
1186  * ITfSourceSingle functions
1187  *****************************************************/
1188 static HRESULT WINAPI ThreadMgrSourceSingle_QueryInterface(ITfSourceSingle *iface, REFIID iid, LPVOID *ppvOut)
1189 {
1190     ThreadMgr *This = impl_from_ITfSourceSingleVtbl(iface);
1191     return ThreadMgr_QueryInterface((ITfThreadMgr *)This, iid, *ppvOut);
1192 }
1193
1194 static ULONG WINAPI ThreadMgrSourceSingle_AddRef(ITfSourceSingle *iface)
1195 {
1196     ThreadMgr *This = impl_from_ITfSourceSingleVtbl(iface);
1197     return ThreadMgr_AddRef((ITfThreadMgr *)This);
1198 }
1199
1200 static ULONG WINAPI ThreadMgrSourceSingle_Release(ITfSourceSingle *iface)
1201 {
1202     ThreadMgr *This = impl_from_ITfSourceSingleVtbl(iface);
1203     return ThreadMgr_Release((ITfThreadMgr *)This);
1204 }
1205
1206 static WINAPI HRESULT ThreadMgrSourceSingle_AdviseSingleSink( ITfSourceSingle *iface,
1207     TfClientId tid, REFIID riid, IUnknown *punk)
1208 {
1209     ThreadMgr *This = impl_from_ITfSourceSingleVtbl(iface);
1210     FIXME("STUB:(%p) %i %s %p\n",This, tid, debugstr_guid(riid),punk);
1211     return E_NOTIMPL;
1212 }
1213
1214 static WINAPI HRESULT ThreadMgrSourceSingle_UnadviseSingleSink( ITfSourceSingle *iface,
1215     TfClientId tid, REFIID riid)
1216 {
1217     ThreadMgr *This = impl_from_ITfSourceSingleVtbl(iface);
1218     FIXME("STUB:(%p) %i %s\n",This, tid, debugstr_guid(riid));
1219     return E_NOTIMPL;
1220 }
1221
1222 static const ITfSourceSingleVtbl ThreadMgr_SourceSingleVtbl =
1223 {
1224     ThreadMgrSourceSingle_QueryInterface,
1225     ThreadMgrSourceSingle_AddRef,
1226     ThreadMgrSourceSingle_Release,
1227
1228     ThreadMgrSourceSingle_AdviseSingleSink,
1229     ThreadMgrSourceSingle_UnadviseSingleSink,
1230 };
1231
1232 HRESULT ThreadMgr_Constructor(IUnknown *pUnkOuter, IUnknown **ppOut)
1233 {
1234     ThreadMgr *This;
1235     if (pUnkOuter)
1236         return CLASS_E_NOAGGREGATION;
1237
1238     /* Only 1 ThreadMgr is created per thread */
1239     This = TlsGetValue(tlsIndex);
1240     if (This)
1241     {
1242         ThreadMgr_AddRef((ITfThreadMgr*)This);
1243         *ppOut = (IUnknown*)This;
1244         return S_OK;
1245     }
1246
1247     This = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(ThreadMgr));
1248     if (This == NULL)
1249         return E_OUTOFMEMORY;
1250
1251     This->ThreadMgrVtbl= &ThreadMgr_ThreadMgrVtbl;
1252     This->SourceVtbl = &ThreadMgr_SourceVtbl;
1253     This->KeystrokeMgrVtbl= &ThreadMgr_KeystrokeMgrVtbl;
1254     This->MessagePumpVtbl= &ThreadMgr_MessagePumpVtbl;
1255     This->ClientIdVtbl = &ThreadMgr_ClientIdVtbl;
1256     This->ThreadMgrEventSinkVtbl = &ThreadMgr_ThreadMgrEventSinkVtbl;
1257     This->SourceSingleVtbl = &ThreadMgr_SourceSingleVtbl;
1258     This->refCount = 1;
1259     TlsSetValue(tlsIndex,This);
1260
1261     CompartmentMgr_Constructor((IUnknown*)This, &IID_IUnknown, (IUnknown**)&This->CompartmentMgr);
1262
1263     list_init(&This->CurrentPreservedKeys);
1264     list_init(&This->CreatedDocumentMgrs);
1265     list_init(&This->AssociatedFocusWindows);
1266
1267     list_init(&This->ActiveLanguageProfileNotifySink);
1268     list_init(&This->DisplayAttributeNotifySink);
1269     list_init(&This->KeyTraceEventSink);
1270     list_init(&This->PreservedKeyNotifySink);
1271     list_init(&This->ThreadFocusSink);
1272     list_init(&This->ThreadMgrEventSink);
1273
1274     TRACE("returning %p\n", This);
1275     *ppOut = (IUnknown *)This;
1276     return S_OK;
1277 }
1278
1279 /**************************************************
1280  * IEnumTfDocumentMgrs implementaion
1281  **************************************************/
1282 static void EnumTfDocumentMgr_Destructor(EnumTfDocumentMgr *This)
1283 {
1284     TRACE("destroying %p\n", This);
1285     HeapFree(GetProcessHeap(),0,This);
1286 }
1287
1288 static HRESULT WINAPI EnumTfDocumentMgr_QueryInterface(IEnumTfDocumentMgrs *iface, REFIID iid, LPVOID *ppvOut)
1289 {
1290     EnumTfDocumentMgr *This = (EnumTfDocumentMgr *)iface;
1291     *ppvOut = NULL;
1292
1293     if (IsEqualIID(iid, &IID_IUnknown) || IsEqualIID(iid, &IID_IEnumTfDocumentMgrs))
1294     {
1295         *ppvOut = This;
1296     }
1297
1298     if (*ppvOut)
1299     {
1300         IUnknown_AddRef(iface);
1301         return S_OK;
1302     }
1303
1304     WARN("unsupported interface: %s\n", debugstr_guid(iid));
1305     return E_NOINTERFACE;
1306 }
1307
1308 static ULONG WINAPI EnumTfDocumentMgr_AddRef(IEnumTfDocumentMgrs *iface)
1309 {
1310     EnumTfDocumentMgr *This = (EnumTfDocumentMgr*)iface;
1311     return InterlockedIncrement(&This->refCount);
1312 }
1313
1314 static ULONG WINAPI EnumTfDocumentMgr_Release(IEnumTfDocumentMgrs *iface)
1315 {
1316     EnumTfDocumentMgr *This = (EnumTfDocumentMgr *)iface;
1317     ULONG ret;
1318
1319     ret = InterlockedDecrement(&This->refCount);
1320     if (ret == 0)
1321         EnumTfDocumentMgr_Destructor(This);
1322     return ret;
1323 }
1324
1325 static HRESULT WINAPI EnumTfDocumentMgr_Next(IEnumTfDocumentMgrs *iface,
1326     ULONG ulCount, ITfDocumentMgr **rgDocumentMgr, ULONG *pcFetched)
1327 {
1328     EnumTfDocumentMgr *This = (EnumTfDocumentMgr *)iface;
1329     ULONG fetched = 0;
1330
1331     TRACE("(%p)\n",This);
1332
1333     if (rgDocumentMgr == NULL) return E_POINTER;
1334
1335     while (fetched < ulCount)
1336     {
1337         DocumentMgrEntry *mgrentry;
1338         if (This->index == NULL)
1339             break;
1340
1341         mgrentry = LIST_ENTRY(This->index,DocumentMgrEntry,entry);
1342         if (mgrentry == NULL)
1343             break;
1344
1345         *rgDocumentMgr = mgrentry->docmgr;
1346         ITfDocumentMgr_AddRef(*rgDocumentMgr);
1347
1348         This->index = list_next(This->head, This->index);
1349         ++fetched;
1350         ++rgDocumentMgr;
1351     }
1352
1353     if (pcFetched) *pcFetched = fetched;
1354     return fetched == ulCount ? S_OK : S_FALSE;
1355 }
1356
1357 static HRESULT WINAPI EnumTfDocumentMgr_Skip( IEnumTfDocumentMgrs* iface, ULONG celt)
1358 {
1359     INT i;
1360     EnumTfDocumentMgr *This = (EnumTfDocumentMgr *)iface;
1361     TRACE("(%p)\n",This);
1362     for(i = 0; i < celt && This->index != NULL; i++)
1363         This->index = list_next(This->head, This->index);
1364     return S_OK;
1365 }
1366
1367 static HRESULT WINAPI EnumTfDocumentMgr_Reset( IEnumTfDocumentMgrs* iface)
1368 {
1369     EnumTfDocumentMgr *This = (EnumTfDocumentMgr *)iface;
1370     TRACE("(%p)\n",This);
1371     This->index = list_head(This->head);
1372     return S_OK;
1373 }
1374
1375 static HRESULT WINAPI EnumTfDocumentMgr_Clone( IEnumTfDocumentMgrs *iface,
1376     IEnumTfDocumentMgrs **ppenum)
1377 {
1378     EnumTfDocumentMgr *This = (EnumTfDocumentMgr *)iface;
1379     HRESULT res;
1380
1381     TRACE("(%p)\n",This);
1382
1383     if (ppenum == NULL) return E_POINTER;
1384
1385     res = EnumTfDocumentMgr_Constructor(This->head, ppenum);
1386     if (SUCCEEDED(res))
1387     {
1388         EnumTfDocumentMgr *new_This = (EnumTfDocumentMgr *)*ppenum;
1389         new_This->index = This->index;
1390     }
1391     return res;
1392 }
1393
1394 static const IEnumTfDocumentMgrsVtbl IEnumTfDocumentMgrs_Vtbl ={
1395     EnumTfDocumentMgr_QueryInterface,
1396     EnumTfDocumentMgr_AddRef,
1397     EnumTfDocumentMgr_Release,
1398
1399     EnumTfDocumentMgr_Clone,
1400     EnumTfDocumentMgr_Next,
1401     EnumTfDocumentMgr_Reset,
1402     EnumTfDocumentMgr_Skip
1403 };
1404
1405 static HRESULT EnumTfDocumentMgr_Constructor(struct list* head, IEnumTfDocumentMgrs **ppOut)
1406 {
1407     EnumTfDocumentMgr *This;
1408
1409     This = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(EnumTfDocumentMgr));
1410     if (This == NULL)
1411         return E_OUTOFMEMORY;
1412
1413     This->Vtbl= &IEnumTfDocumentMgrs_Vtbl;
1414     This->refCount = 1;
1415     This->head = head;
1416     This->index = list_head(This->head);
1417
1418     TRACE("returning %p\n", This);
1419     *ppOut = (IEnumTfDocumentMgrs*)This;
1420     return S_OK;
1421 }
1422
1423 void ThreadMgr_OnDocumentMgrDestruction(ITfThreadMgr *tm, ITfDocumentMgr *mgr)
1424 {
1425     ThreadMgr *This = (ThreadMgr *)tm;
1426     struct list *cursor;
1427     LIST_FOR_EACH(cursor, &This->CreatedDocumentMgrs)
1428     {
1429         DocumentMgrEntry *mgrentry = LIST_ENTRY(cursor,DocumentMgrEntry,entry);
1430         if (mgrentry->docmgr == mgr)
1431         {
1432             list_remove(cursor);
1433             HeapFree(GetProcessHeap(),0,mgrentry);
1434             return;
1435         }
1436     }
1437     FIXME("ITfDocumenMgr %p not found in this thread\n",mgr);
1438 }
1439
1440 LRESULT CALLBACK ThreadFocusHookProc(int nCode, WPARAM wParam, LPARAM lParam)
1441 {
1442     ThreadMgr *This;
1443
1444     This = TlsGetValue(tlsIndex);
1445     if (!This)
1446     {
1447         ERR("Hook proc but no ThreadMgr for this thread. Serious Error\n");
1448         return 0;
1449     }
1450     if (!This->focusHook)
1451     {
1452         ERR("Hook proc but no ThreadMgr focus Hook. Serious Error\n");
1453         return 0;
1454     }
1455
1456     if (nCode == HCBT_SETFOCUS) /* focus change within our thread */
1457     {
1458         struct list *cursor;
1459
1460         LIST_FOR_EACH(cursor, &This->AssociatedFocusWindows)
1461         {
1462             AssociatedWindow *wnd = LIST_ENTRY(cursor,AssociatedWindow,entry);
1463             if (wnd->hwnd == (HWND)wParam)
1464             {
1465                 TRACE("Triggering Associated window focus\n");
1466                 if (This->focus != wnd->docmgr)
1467                     ThreadMgr_SetFocus((ITfThreadMgr*)This, wnd->docmgr);
1468                 break;
1469             }
1470         }
1471     }
1472
1473     return CallNextHookEx(This->focusHook, nCode, wParam, lParam);
1474 }