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