msctf: Implement ITfClientId.
[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 tagACLMulti {
60     const ITfThreadMgrVtbl *ThreadMgrVtbl;
61     const ITfSourceVtbl *SourceVtbl;
62     const ITfKeystrokeMgrVtbl *KeystrokeMgrVtbl;
63     const ITfMessagePumpVtbl *MessagePumpVtbl;
64     const ITfClientIdVtbl *ClientIdVtbl;
65     LONG refCount;
66
67     const ITfThreadMgrEventSinkVtbl *ThreadMgrEventSinkVtbl; /* internal */
68
69     ITfDocumentMgr *focus;
70
71     /* kept as separate lists to reduce unnecessary iterations */
72     struct list     ActiveLanguageProfileNotifySink;
73     struct list     DisplayAttributeNotifySink;
74     struct list     KeyTraceEventSink;
75     struct list     PreservedKeyNotifySink;
76     struct list     ThreadFocusSink;
77     struct list     ThreadMgrEventSink;
78 } ThreadMgr;
79
80 static inline ThreadMgr *impl_from_ITfSourceVtbl(ITfSource *iface)
81 {
82     return (ThreadMgr *)((char *)iface - FIELD_OFFSET(ThreadMgr,SourceVtbl));
83 }
84
85 static inline ThreadMgr *impl_from_ITfKeystrokeMgrVtbl(ITfKeystrokeMgr *iface)
86 {
87     return (ThreadMgr *)((char *)iface - FIELD_OFFSET(ThreadMgr,KeystrokeMgrVtbl));
88 }
89
90 static inline ThreadMgr *impl_from_ITfMessagePumpVtbl(ITfMessagePump *iface)
91 {
92     return (ThreadMgr *)((char *)iface - FIELD_OFFSET(ThreadMgr,MessagePumpVtbl));
93 }
94
95 static inline ThreadMgr *impl_from_ITfClientIdVtbl(ITfClientId *iface)
96 {
97     return (ThreadMgr *)((char *)iface - FIELD_OFFSET(ThreadMgr,ClientIdVtbl));
98 }
99
100 static inline ThreadMgr *impl_from_ITfThreadMgrEventSink(ITfThreadMgrEventSink *iface)
101 {
102     return (ThreadMgr *)((char *)iface - FIELD_OFFSET(ThreadMgr,ThreadMgrEventSinkVtbl));
103 }
104
105 static void free_sink(ThreadMgrSink *sink)
106 {
107         IUnknown_Release(sink->interfaces.pIUnknown);
108         HeapFree(GetProcessHeap(),0,sink);
109 }
110
111 static void ThreadMgr_Destructor(ThreadMgr *This)
112 {
113     struct list *cursor, *cursor2;
114
115     TlsSetValue(tlsIndex,NULL);
116     TRACE("destroying %p\n", This);
117     if (This->focus)
118         ITfDocumentMgr_Release(This->focus);
119
120     /* free sinks */
121     LIST_FOR_EACH_SAFE(cursor, cursor2, &This->ActiveLanguageProfileNotifySink)
122     {
123         ThreadMgrSink* sink = LIST_ENTRY(cursor,ThreadMgrSink,entry);
124         list_remove(cursor);
125         free_sink(sink);
126     }
127     LIST_FOR_EACH_SAFE(cursor, cursor2, &This->DisplayAttributeNotifySink)
128     {
129         ThreadMgrSink* sink = LIST_ENTRY(cursor,ThreadMgrSink,entry);
130         list_remove(cursor);
131         free_sink(sink);
132     }
133     LIST_FOR_EACH_SAFE(cursor, cursor2, &This->KeyTraceEventSink)
134     {
135         ThreadMgrSink* sink = LIST_ENTRY(cursor,ThreadMgrSink,entry);
136         list_remove(cursor);
137         free_sink(sink);
138     }
139     LIST_FOR_EACH_SAFE(cursor, cursor2, &This->PreservedKeyNotifySink)
140     {
141         ThreadMgrSink* sink = LIST_ENTRY(cursor,ThreadMgrSink,entry);
142         list_remove(cursor);
143         free_sink(sink);
144     }
145     LIST_FOR_EACH_SAFE(cursor, cursor2, &This->ThreadFocusSink)
146     {
147         ThreadMgrSink* sink = LIST_ENTRY(cursor,ThreadMgrSink,entry);
148         list_remove(cursor);
149         free_sink(sink);
150     }
151     LIST_FOR_EACH_SAFE(cursor, cursor2, &This->ThreadMgrEventSink)
152     {
153         ThreadMgrSink* sink = LIST_ENTRY(cursor,ThreadMgrSink,entry);
154         list_remove(cursor);
155         free_sink(sink);
156     }
157
158     HeapFree(GetProcessHeap(),0,This);
159 }
160
161 static HRESULT WINAPI ThreadMgr_QueryInterface(ITfThreadMgr *iface, REFIID iid, LPVOID *ppvOut)
162 {
163     ThreadMgr *This = (ThreadMgr *)iface;
164     *ppvOut = NULL;
165
166     if (IsEqualIID(iid, &IID_IUnknown) || IsEqualIID(iid, &IID_ITfThreadMgr))
167     {
168         *ppvOut = This;
169     }
170     else if (IsEqualIID(iid, &IID_ITfSource))
171     {
172         *ppvOut = &This->SourceVtbl;
173     }
174     else if (IsEqualIID(iid, &IID_ITfKeystrokeMgr))
175     {
176         *ppvOut = &This->KeystrokeMgrVtbl;
177     }
178     else if (IsEqualIID(iid, &IID_ITfMessagePump))
179     {
180         *ppvOut = &This->MessagePumpVtbl;
181     }
182     else if (IsEqualIID(iid, &IID_ITfClientId))
183     {
184         *ppvOut = &This->ClientIdVtbl;
185     }
186
187     if (*ppvOut)
188     {
189         IUnknown_AddRef(iface);
190         return S_OK;
191     }
192
193     WARN("unsupported interface: %s\n", debugstr_guid(iid));
194     return E_NOINTERFACE;
195 }
196
197 static ULONG WINAPI ThreadMgr_AddRef(ITfThreadMgr *iface)
198 {
199     ThreadMgr *This = (ThreadMgr *)iface;
200     return InterlockedIncrement(&This->refCount);
201 }
202
203 static ULONG WINAPI ThreadMgr_Release(ITfThreadMgr *iface)
204 {
205     ThreadMgr *This = (ThreadMgr *)iface;
206     ULONG ret;
207
208     ret = InterlockedDecrement(&This->refCount);
209     if (ret == 0)
210         ThreadMgr_Destructor(This);
211     return ret;
212 }
213
214 /*****************************************************
215  * ITfThreadMgr functions
216  *****************************************************/
217
218 static HRESULT WINAPI ThreadMgr_fnActivate( ITfThreadMgr* iface, TfClientId *ptid)
219 {
220     ThreadMgr *This = (ThreadMgr *)iface;
221     FIXME("STUB:(%p)\n",This);
222     return E_NOTIMPL;
223 }
224
225 static HRESULT WINAPI ThreadMgr_fnDeactivate( ITfThreadMgr* iface)
226 {
227     ThreadMgr *This = (ThreadMgr *)iface;
228     FIXME("STUB:(%p)\n",This);
229
230     if (This->focus)
231     {
232         ITfThreadMgrEventSink_OnSetFocus((ITfThreadMgrEventSink*)&This->ThreadMgrEventSinkVtbl, 0, This->focus);
233         ITfDocumentMgr_Release(This->focus);
234         This->focus = 0;
235     }
236
237     return E_NOTIMPL;
238 }
239
240 static HRESULT WINAPI ThreadMgr_CreateDocumentMgr( ITfThreadMgr* iface, ITfDocumentMgr
241 **ppdim)
242 {
243     ThreadMgr *This = (ThreadMgr *)iface;
244     TRACE("(%p)\n",iface);
245     return DocumentMgr_Constructor((ITfThreadMgrEventSink*)&This->ThreadMgrEventSinkVtbl, ppdim);
246 }
247
248 static HRESULT WINAPI ThreadMgr_EnumDocumentMgrs( ITfThreadMgr* iface, IEnumTfDocumentMgrs
249 **ppEnum)
250 {
251     ThreadMgr *This = (ThreadMgr *)iface;
252     FIXME("STUB:(%p)\n",This);
253     return E_NOTIMPL;
254 }
255
256 static HRESULT WINAPI ThreadMgr_GetFocus( ITfThreadMgr* iface, ITfDocumentMgr
257 **ppdimFocus)
258 {
259     ThreadMgr *This = (ThreadMgr *)iface;
260     TRACE("(%p)\n",This);
261
262     if (!ppdimFocus)
263         return E_INVALIDARG;
264
265     *ppdimFocus = This->focus;
266
267     TRACE("->%p\n",This->focus);
268
269     if (This->focus == NULL)
270         return S_FALSE;
271
272     ITfDocumentMgr_AddRef(This->focus);
273
274     return S_OK;
275 }
276
277 static HRESULT WINAPI ThreadMgr_SetFocus( ITfThreadMgr* iface, ITfDocumentMgr *pdimFocus)
278 {
279     ITfDocumentMgr *check;
280     ThreadMgr *This = (ThreadMgr *)iface;
281
282     TRACE("(%p) %p\n",This,pdimFocus);
283
284     if (!pdimFocus || FAILED(IUnknown_QueryInterface(pdimFocus,&IID_ITfDocumentMgr,(LPVOID*) &check)))
285         return E_INVALIDARG;
286
287     ITfThreadMgrEventSink_OnSetFocus((ITfThreadMgrEventSink*)&This->ThreadMgrEventSinkVtbl, check, This->focus);
288
289     if (This->focus)
290         ITfDocumentMgr_Release(This->focus);
291
292     This->focus = check;
293     return S_OK;
294 }
295
296 static HRESULT WINAPI ThreadMgr_AssociateFocus( ITfThreadMgr* iface, HWND hwnd,
297 ITfDocumentMgr *pdimNew, ITfDocumentMgr **ppdimPrev)
298 {
299     ThreadMgr *This = (ThreadMgr *)iface;
300     FIXME("STUB:(%p)\n",This);
301     return E_NOTIMPL;
302 }
303
304 static HRESULT WINAPI ThreadMgr_IsThreadFocus( ITfThreadMgr* iface, BOOL *pfThreadFocus)
305 {
306     ThreadMgr *This = (ThreadMgr *)iface;
307     FIXME("STUB:(%p)\n",This);
308     return E_NOTIMPL;
309 }
310
311 static HRESULT WINAPI ThreadMgr_GetFunctionProvider( ITfThreadMgr* iface, REFCLSID clsid,
312 ITfFunctionProvider **ppFuncProv)
313 {
314     ThreadMgr *This = (ThreadMgr *)iface;
315     FIXME("STUB:(%p)\n",This);
316     return E_NOTIMPL;
317 }
318
319 static HRESULT WINAPI ThreadMgr_EnumFunctionProviders( ITfThreadMgr* iface,
320 IEnumTfFunctionProviders **ppEnum)
321 {
322     ThreadMgr *This = (ThreadMgr *)iface;
323     FIXME("STUB:(%p)\n",This);
324     return E_NOTIMPL;
325 }
326
327 static HRESULT WINAPI ThreadMgr_GetGlobalCompartment( ITfThreadMgr* iface,
328 ITfCompartmentMgr **ppCompMgr)
329 {
330     ThreadMgr *This = (ThreadMgr *)iface;
331     FIXME("STUB:(%p)\n",This);
332     return E_NOTIMPL;
333 }
334
335 static const ITfThreadMgrVtbl ThreadMgr_ThreadMgrVtbl =
336 {
337     ThreadMgr_QueryInterface,
338     ThreadMgr_AddRef,
339     ThreadMgr_Release,
340
341     ThreadMgr_fnActivate,
342     ThreadMgr_fnDeactivate,
343     ThreadMgr_CreateDocumentMgr,
344     ThreadMgr_EnumDocumentMgrs,
345     ThreadMgr_GetFocus,
346     ThreadMgr_SetFocus,
347     ThreadMgr_AssociateFocus,
348     ThreadMgr_IsThreadFocus,
349     ThreadMgr_GetFunctionProvider,
350     ThreadMgr_EnumFunctionProviders,
351     ThreadMgr_GetGlobalCompartment
352 };
353
354
355 static HRESULT WINAPI Source_QueryInterface(ITfSource *iface, REFIID iid, LPVOID *ppvOut)
356 {
357     ThreadMgr *This = impl_from_ITfSourceVtbl(iface);
358     return ThreadMgr_QueryInterface((ITfThreadMgr *)This, iid, *ppvOut);
359 }
360
361 static ULONG WINAPI Source_AddRef(ITfSource *iface)
362 {
363     ThreadMgr *This = impl_from_ITfSourceVtbl(iface);
364     return ThreadMgr_AddRef((ITfThreadMgr*)This);
365 }
366
367 static ULONG WINAPI Source_Release(ITfSource *iface)
368 {
369     ThreadMgr *This = impl_from_ITfSourceVtbl(iface);
370     return ThreadMgr_Release((ITfThreadMgr *)This);
371 }
372
373 /*****************************************************
374  * ITfSource functions
375  *****************************************************/
376 static WINAPI HRESULT ThreadMgrSource_AdviseSink(ITfSource *iface,
377         REFIID riid, IUnknown *punk, DWORD *pdwCookie)
378 {
379     ThreadMgrSink *tms;
380     ThreadMgr *This = impl_from_ITfSourceVtbl(iface);
381
382     TRACE("(%p) %s %p %p\n",This,debugstr_guid(riid),punk,pdwCookie);
383
384     if (!riid || !punk || !pdwCookie)
385         return E_INVALIDARG;
386
387     if (IsEqualIID(riid, &IID_ITfThreadMgrEventSink))
388     {
389         tms = HeapAlloc(GetProcessHeap(),0,sizeof(ThreadMgrSink));
390         if (!tms)
391             return E_OUTOFMEMORY;
392         if (!SUCCEEDED(IUnknown_QueryInterface(punk, riid, (LPVOID*)&tms->interfaces.pITfThreadMgrEventSink)))
393         {
394             HeapFree(GetProcessHeap(),0,tms);
395             return CONNECT_E_CANNOTCONNECT;
396         }
397         list_add_head(&This->ThreadMgrEventSink,&tms->entry);
398         *pdwCookie = generate_Cookie(COOKIE_MAGIC_TMSINK, tms);
399     }
400     else
401     {
402         FIXME("(%p) Unhandled Sink: %s\n",This,debugstr_guid(riid));
403         return E_NOTIMPL;
404     }
405
406     TRACE("cookie %x\n",*pdwCookie);
407
408     return S_OK;
409 }
410
411 static WINAPI HRESULT ThreadMgrSource_UnadviseSink(ITfSource *iface, DWORD pdwCookie)
412 {
413     ThreadMgrSink *sink;
414     ThreadMgr *This = impl_from_ITfSourceVtbl(iface);
415
416     TRACE("(%p) %x\n",This,pdwCookie);
417
418     if (get_Cookie_magic(pdwCookie)!=COOKIE_MAGIC_TMSINK)
419         return E_INVALIDARG;
420
421     sink = (ThreadMgrSink*)remove_Cookie(pdwCookie);
422     if (!sink)
423         return CONNECT_E_NOCONNECTION;
424
425     list_remove(&sink->entry);
426     free_sink(sink);
427
428     return S_OK;
429 }
430
431 static const ITfSourceVtbl ThreadMgr_SourceVtbl =
432 {
433     Source_QueryInterface,
434     Source_AddRef,
435     Source_Release,
436
437     ThreadMgrSource_AdviseSink,
438     ThreadMgrSource_UnadviseSink,
439 };
440
441 /*****************************************************
442  * ITfKeystrokeMgr functions
443  *****************************************************/
444
445 static HRESULT WINAPI KeystrokeMgr_QueryInterface(ITfKeystrokeMgr *iface, REFIID iid, LPVOID *ppvOut)
446 {
447     ThreadMgr *This = impl_from_ITfKeystrokeMgrVtbl(iface);
448     return ThreadMgr_QueryInterface((ITfThreadMgr *)This, iid, *ppvOut);
449 }
450
451 static ULONG WINAPI KeystrokeMgr_AddRef(ITfKeystrokeMgr *iface)
452 {
453     ThreadMgr *This = impl_from_ITfKeystrokeMgrVtbl(iface);
454     return ThreadMgr_AddRef((ITfThreadMgr*)This);
455 }
456
457 static ULONG WINAPI KeystrokeMgr_Release(ITfKeystrokeMgr *iface)
458 {
459     ThreadMgr *This = impl_from_ITfKeystrokeMgrVtbl(iface);
460     return ThreadMgr_Release((ITfThreadMgr *)This);
461 }
462
463 static HRESULT WINAPI KeystrokeMgr_AdviseKeyEventSink(ITfKeystrokeMgr *iface,
464         TfClientId tid, ITfKeyEventSink *pSink, BOOL fForeground)
465 {
466     ThreadMgr *This = impl_from_ITfKeystrokeMgrVtbl(iface);
467     FIXME("STUB:(%p)\n",This);
468     return E_NOTIMPL;
469 }
470
471 static HRESULT WINAPI KeystrokeMgr_UnadviseKeyEventSink(ITfKeystrokeMgr *iface,
472         TfClientId tid)
473 {
474     ThreadMgr *This = impl_from_ITfKeystrokeMgrVtbl(iface);
475     FIXME("STUB:(%p)\n",This);
476     return E_NOTIMPL;
477 }
478
479 static HRESULT WINAPI KeystrokeMgr_GetForeground(ITfKeystrokeMgr *iface,
480         CLSID *pclsid)
481 {
482     ThreadMgr *This = impl_from_ITfKeystrokeMgrVtbl(iface);
483     FIXME("STUB:(%p)\n",This);
484     return E_NOTIMPL;
485 }
486
487 static HRESULT WINAPI KeystrokeMgr_TestKeyDown(ITfKeystrokeMgr *iface,
488         WPARAM wParam, LPARAM lParam, BOOL *pfEaten)
489 {
490     ThreadMgr *This = impl_from_ITfKeystrokeMgrVtbl(iface);
491     FIXME("STUB:(%p)\n",This);
492     return E_NOTIMPL;
493 }
494
495 static HRESULT WINAPI KeystrokeMgr_TestKeyUp(ITfKeystrokeMgr *iface,
496         WPARAM wParam, LPARAM lParam, BOOL *pfEaten)
497 {
498     ThreadMgr *This = impl_from_ITfKeystrokeMgrVtbl(iface);
499     FIXME("STUB:(%p)\n",This);
500     return E_NOTIMPL;
501 }
502
503 static HRESULT WINAPI KeystrokeMgr_KeyDown(ITfKeystrokeMgr *iface,
504         WPARAM wParam, LPARAM lParam, BOOL *pfEaten)
505 {
506     ThreadMgr *This = impl_from_ITfKeystrokeMgrVtbl(iface);
507     FIXME("STUB:(%p)\n",This);
508     return E_NOTIMPL;
509 }
510
511 static HRESULT WINAPI KeystrokeMgr_KeyUp(ITfKeystrokeMgr *iface,
512         WPARAM wParam, LPARAM lParam, BOOL *pfEaten)
513 {
514     ThreadMgr *This = impl_from_ITfKeystrokeMgrVtbl(iface);
515     FIXME("STUB:(%p)\n",This);
516     return E_NOTIMPL;
517 }
518
519 static HRESULT WINAPI KeystrokeMgr_GetPreservedKey(ITfKeystrokeMgr *iface,
520         ITfContext *pic, const TF_PRESERVEDKEY *pprekey, GUID *pguid)
521 {
522     ThreadMgr *This = impl_from_ITfKeystrokeMgrVtbl(iface);
523     FIXME("STUB:(%p)\n",This);
524     return E_NOTIMPL;
525 }
526
527 static HRESULT WINAPI KeystrokeMgr_IsPreservedKey(ITfKeystrokeMgr *iface,
528         REFGUID rguid, const TF_PRESERVEDKEY *pprekey, BOOL *pfRegistered)
529 {
530     ThreadMgr *This = impl_from_ITfKeystrokeMgrVtbl(iface);
531     FIXME("STUB:(%p)\n",This);
532     return E_NOTIMPL;
533 }
534
535 static HRESULT WINAPI KeystrokeMgr_PreserveKey(ITfKeystrokeMgr *iface,
536         TfClientId tid, REFGUID rguid, const TF_PRESERVEDKEY *prekey,
537         const WCHAR *pchDesc, ULONG cchDesc)
538 {
539     ThreadMgr *This = impl_from_ITfKeystrokeMgrVtbl(iface);
540     FIXME("STUB:(%p)\n",This);
541     return E_NOTIMPL;
542 }
543
544 static HRESULT WINAPI KeystrokeMgr_UnpreserveKey(ITfKeystrokeMgr *iface,
545         REFGUID rguid, const TF_PRESERVEDKEY *pprekey)
546 {
547     ThreadMgr *This = impl_from_ITfKeystrokeMgrVtbl(iface);
548     FIXME("STUB:(%p)\n",This);
549     return E_NOTIMPL;
550 }
551
552 static HRESULT WINAPI KeystrokeMgr_SetPreservedKeyDescription(ITfKeystrokeMgr *iface,
553         REFGUID rguid, const WCHAR *pchDesc, ULONG cchDesc)
554 {
555     ThreadMgr *This = impl_from_ITfKeystrokeMgrVtbl(iface);
556     FIXME("STUB:(%p)\n",This);
557     return E_NOTIMPL;
558 }
559
560 static HRESULT WINAPI KeystrokeMgr_GetPreservedKeyDescription(ITfKeystrokeMgr *iface,
561         REFGUID rguid, BSTR *pbstrDesc)
562 {
563     ThreadMgr *This = impl_from_ITfKeystrokeMgrVtbl(iface);
564     FIXME("STUB:(%p)\n",This);
565     return E_NOTIMPL;
566 }
567
568 static HRESULT WINAPI KeystrokeMgr_SimulatePreservedKey(ITfKeystrokeMgr *iface,
569         ITfContext *pic, REFGUID rguid, BOOL *pfEaten)
570 {
571     ThreadMgr *This = impl_from_ITfKeystrokeMgrVtbl(iface);
572     FIXME("STUB:(%p)\n",This);
573     return E_NOTIMPL;
574 }
575
576 static const ITfKeystrokeMgrVtbl ThreadMgr_KeystrokeMgrVtbl =
577 {
578     KeystrokeMgr_QueryInterface,
579     KeystrokeMgr_AddRef,
580     KeystrokeMgr_Release,
581
582     KeystrokeMgr_AdviseKeyEventSink,
583     KeystrokeMgr_UnadviseKeyEventSink,
584     KeystrokeMgr_GetForeground,
585     KeystrokeMgr_TestKeyDown,
586     KeystrokeMgr_TestKeyUp,
587     KeystrokeMgr_KeyDown,
588     KeystrokeMgr_KeyUp,
589     KeystrokeMgr_GetPreservedKey,
590     KeystrokeMgr_IsPreservedKey,
591     KeystrokeMgr_PreserveKey,
592     KeystrokeMgr_UnpreserveKey,
593     KeystrokeMgr_SetPreservedKeyDescription,
594     KeystrokeMgr_GetPreservedKeyDescription,
595     KeystrokeMgr_SimulatePreservedKey
596 };
597
598 /*****************************************************
599  * ITfMessagePump functions
600  *****************************************************/
601
602 static HRESULT WINAPI MessagePump_QueryInterface(ITfMessagePump *iface, REFIID iid, LPVOID *ppvOut)
603 {
604     ThreadMgr *This = impl_from_ITfMessagePumpVtbl(iface);
605     return ThreadMgr_QueryInterface((ITfThreadMgr *)This, iid, *ppvOut);
606 }
607
608 static ULONG WINAPI MessagePump_AddRef(ITfMessagePump *iface)
609 {
610     ThreadMgr *This = impl_from_ITfMessagePumpVtbl(iface);
611     return ThreadMgr_AddRef((ITfThreadMgr*)This);
612 }
613
614 static ULONG WINAPI MessagePump_Release(ITfMessagePump *iface)
615 {
616     ThreadMgr *This = impl_from_ITfMessagePumpVtbl(iface);
617     return ThreadMgr_Release((ITfThreadMgr *)This);
618 }
619
620 static HRESULT WINAPI MessagePump_PeekMessageA(ITfMessagePump *iface,
621         LPMSG pMsg, HWND hwnd, UINT wMsgFilterMin, UINT wMsgFilterMax,
622         UINT wRemoveMsg, BOOL *pfResult)
623 {
624     if (!pfResult)
625         return E_INVALIDARG;
626     *pfResult = PeekMessageA(pMsg, hwnd, wMsgFilterMin, wMsgFilterMax, wRemoveMsg);
627     return S_OK;
628 }
629
630 static HRESULT WINAPI MessagePump_GetMessageA(ITfMessagePump *iface,
631         LPMSG pMsg, HWND hwnd, UINT wMsgFilterMin, UINT wMsgFilterMax,
632         BOOL *pfResult)
633 {
634     if (!pfResult)
635         return E_INVALIDARG;
636     *pfResult = GetMessageA(pMsg, hwnd, wMsgFilterMin, wMsgFilterMax);
637     return S_OK;
638 }
639
640 static HRESULT WINAPI MessagePump_PeekMessageW(ITfMessagePump *iface,
641         LPMSG pMsg, HWND hwnd, UINT wMsgFilterMin, UINT wMsgFilterMax,
642         UINT wRemoveMsg, BOOL *pfResult)
643 {
644     if (!pfResult)
645         return E_INVALIDARG;
646     *pfResult = PeekMessageW(pMsg, hwnd, wMsgFilterMin, wMsgFilterMax, wRemoveMsg);
647     return S_OK;
648 }
649
650 static HRESULT WINAPI MessagePump_GetMessageW(ITfMessagePump *iface,
651         LPMSG pMsg, HWND hwnd, UINT wMsgFilterMin, UINT wMsgFilterMax,
652         BOOL *pfResult)
653 {
654     if (!pfResult)
655         return E_INVALIDARG;
656     *pfResult = GetMessageW(pMsg, hwnd, wMsgFilterMin, wMsgFilterMax);
657     return S_OK;
658 }
659
660 static const ITfMessagePumpVtbl ThreadMgr_MessagePumpVtbl =
661 {
662     MessagePump_QueryInterface,
663     MessagePump_AddRef,
664     MessagePump_Release,
665
666     MessagePump_PeekMessageA,
667     MessagePump_GetMessageA,
668     MessagePump_PeekMessageW,
669     MessagePump_GetMessageW
670 };
671
672 /*****************************************************
673  * ITfClientId functions
674  *****************************************************/
675
676 static HRESULT WINAPI ClientId_QueryInterface(ITfClientId *iface, REFIID iid, LPVOID *ppvOut)
677 {
678     ThreadMgr *This = impl_from_ITfClientIdVtbl(iface);
679     return ThreadMgr_QueryInterface((ITfThreadMgr *)This, iid, *ppvOut);
680 }
681
682 static ULONG WINAPI ClientId_AddRef(ITfClientId *iface)
683 {
684     ThreadMgr *This = impl_from_ITfClientIdVtbl(iface);
685     return ThreadMgr_AddRef((ITfThreadMgr*)This);
686 }
687
688 static ULONG WINAPI ClientId_Release(ITfClientId *iface)
689 {
690     ThreadMgr *This = impl_from_ITfClientIdVtbl(iface);
691     return ThreadMgr_Release((ITfThreadMgr *)This);
692 }
693
694 static HRESULT WINAPI ClientId_GetClientId(ITfClientId *iface,
695     REFCLSID rclsid, TfClientId *ptid)
696
697 {
698     HRESULT hr;
699     ITfCategoryMgr *catmgr;
700     ThreadMgr *This = impl_from_ITfClientIdVtbl(iface);
701
702     TRACE("(%p) %s\n",This,debugstr_guid(rclsid));
703
704     CategoryMgr_Constructor(NULL,(IUnknown**)&catmgr);
705     hr = ITfCategoryMgr_RegisterGUID(catmgr,rclsid,ptid);
706     ITfCategoryMgr_Release(catmgr);
707
708     return hr;
709 }
710
711 static const ITfClientIdVtbl ThreadMgr_ClientIdVtbl =
712 {
713     ClientId_QueryInterface,
714     ClientId_AddRef,
715     ClientId_Release,
716
717     ClientId_GetClientId
718 };
719
720 /*****************************************************
721  * ITfThreadMgrEventSink functions  (internal)
722  *****************************************************/
723 static HRESULT WINAPI ThreadMgrEventSink_QueryInterface(ITfThreadMgrEventSink *iface, REFIID iid, LPVOID *ppvOut)
724 {
725     ThreadMgr *This = impl_from_ITfThreadMgrEventSink(iface);
726     return ThreadMgr_QueryInterface((ITfThreadMgr *)This, iid, *ppvOut);
727 }
728
729 static ULONG WINAPI ThreadMgrEventSink_AddRef(ITfThreadMgrEventSink *iface)
730 {
731     ThreadMgr *This = impl_from_ITfThreadMgrEventSink(iface);
732     return ThreadMgr_AddRef((ITfThreadMgr*)This);
733 }
734
735 static ULONG WINAPI ThreadMgrEventSink_Release(ITfThreadMgrEventSink *iface)
736 {
737     ThreadMgr *This = impl_from_ITfThreadMgrEventSink(iface);
738     return ThreadMgr_Release((ITfThreadMgr *)This);
739 }
740
741
742 static WINAPI HRESULT ThreadMgrEventSink_OnInitDocumentMgr(
743         ITfThreadMgrEventSink *iface,ITfDocumentMgr *pdim)
744 {
745     struct list *cursor;
746     ThreadMgr *This = impl_from_ITfThreadMgrEventSink(iface);
747
748     TRACE("(%p) %p\n",This,pdim);
749
750     LIST_FOR_EACH(cursor, &This->ThreadMgrEventSink)
751     {
752         ThreadMgrSink* sink = LIST_ENTRY(cursor,ThreadMgrSink,entry);
753         ITfThreadMgrEventSink_OnInitDocumentMgr(sink->interfaces.pITfThreadMgrEventSink,pdim);
754     }
755
756     return S_OK;
757 }
758
759 static WINAPI HRESULT ThreadMgrEventSink_OnUninitDocumentMgr(
760         ITfThreadMgrEventSink *iface, ITfDocumentMgr *pdim)
761 {
762     struct list *cursor;
763     ThreadMgr *This = impl_from_ITfThreadMgrEventSink(iface);
764
765     TRACE("(%p) %p\n",This,pdim);
766
767     LIST_FOR_EACH(cursor, &This->ThreadMgrEventSink)
768     {
769         ThreadMgrSink* sink = LIST_ENTRY(cursor,ThreadMgrSink,entry);
770         ITfThreadMgrEventSink_OnUninitDocumentMgr(sink->interfaces.pITfThreadMgrEventSink,pdim);
771     }
772
773     return S_OK;
774 }
775
776 static WINAPI HRESULT ThreadMgrEventSink_OnSetFocus(
777         ITfThreadMgrEventSink *iface, ITfDocumentMgr *pdimFocus,
778         ITfDocumentMgr *pdimPrevFocus)
779 {
780     struct list *cursor;
781     ThreadMgr *This = impl_from_ITfThreadMgrEventSink(iface);
782
783     TRACE("(%p) %p %p\n",This,pdimFocus, pdimPrevFocus);
784
785     LIST_FOR_EACH(cursor, &This->ThreadMgrEventSink)
786     {
787         ThreadMgrSink* sink = LIST_ENTRY(cursor,ThreadMgrSink,entry);
788         ITfThreadMgrEventSink_OnSetFocus(sink->interfaces.pITfThreadMgrEventSink, pdimFocus, pdimPrevFocus);
789     }
790
791     return S_OK;
792 }
793
794 static WINAPI HRESULT ThreadMgrEventSink_OnPushContext(
795         ITfThreadMgrEventSink *iface, ITfContext *pic)
796 {
797     struct list *cursor;
798     ThreadMgr *This = impl_from_ITfThreadMgrEventSink(iface);
799
800     TRACE("(%p) %p\n",This,pic);
801
802     LIST_FOR_EACH(cursor, &This->ThreadMgrEventSink)
803     {
804         ThreadMgrSink* sink = LIST_ENTRY(cursor,ThreadMgrSink,entry);
805         ITfThreadMgrEventSink_OnPushContext(sink->interfaces.pITfThreadMgrEventSink,pic);
806     }
807
808     return S_OK;
809 }
810
811 static WINAPI HRESULT ThreadMgrEventSink_OnPopContext(
812         ITfThreadMgrEventSink *iface, ITfContext *pic)
813 {
814     struct list *cursor;
815     ThreadMgr *This = impl_from_ITfThreadMgrEventSink(iface);
816
817     TRACE("(%p) %p\n",This,pic);
818
819     LIST_FOR_EACH(cursor, &This->ThreadMgrEventSink)
820     {
821         ThreadMgrSink* sink = LIST_ENTRY(cursor,ThreadMgrSink,entry);
822         ITfThreadMgrEventSink_OnPopContext(sink->interfaces.pITfThreadMgrEventSink,pic);
823     }
824
825     return S_OK;
826 }
827
828 static const ITfThreadMgrEventSinkVtbl ThreadMgr_ThreadMgrEventSinkVtbl =
829 {
830     ThreadMgrEventSink_QueryInterface,
831     ThreadMgrEventSink_AddRef,
832     ThreadMgrEventSink_Release,
833
834     ThreadMgrEventSink_OnInitDocumentMgr,
835     ThreadMgrEventSink_OnUninitDocumentMgr,
836     ThreadMgrEventSink_OnSetFocus,
837     ThreadMgrEventSink_OnPushContext,
838     ThreadMgrEventSink_OnPopContext
839 };
840
841 HRESULT ThreadMgr_Constructor(IUnknown *pUnkOuter, IUnknown **ppOut)
842 {
843     ThreadMgr *This;
844     if (pUnkOuter)
845         return CLASS_E_NOAGGREGATION;
846
847     /* Only 1 ThreadMgr is created per thread */
848     This = TlsGetValue(tlsIndex);
849     if (This)
850     {
851         ThreadMgr_AddRef((ITfThreadMgr*)This);
852         *ppOut = (IUnknown*)This;
853         return S_OK;
854     }
855
856     This = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(ThreadMgr));
857     if (This == NULL)
858         return E_OUTOFMEMORY;
859
860     This->ThreadMgrVtbl= &ThreadMgr_ThreadMgrVtbl;
861     This->SourceVtbl = &ThreadMgr_SourceVtbl;
862     This->KeystrokeMgrVtbl= &ThreadMgr_KeystrokeMgrVtbl;
863     This->MessagePumpVtbl= &ThreadMgr_MessagePumpVtbl;
864     This->ClientIdVtbl = &ThreadMgr_ClientIdVtbl;
865     This->ThreadMgrEventSinkVtbl = &ThreadMgr_ThreadMgrEventSinkVtbl;
866     This->refCount = 1;
867     TlsSetValue(tlsIndex,This);
868
869     list_init(&This->ActiveLanguageProfileNotifySink);
870     list_init(&This->DisplayAttributeNotifySink);
871     list_init(&This->KeyTraceEventSink);
872     list_init(&This->PreservedKeyNotifySink);
873     list_init(&This->ThreadFocusSink);
874     list_init(&This->ThreadMgrEventSink);
875
876     TRACE("returning %p\n", This);
877     *ppOut = (IUnknown *)This;
878     return S_OK;
879 }