msctf: Setup global CompartmentMgr.
[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 tagACLMulti {
69     const ITfThreadMgrVtbl *ThreadMgrVtbl;
70     const ITfSourceVtbl *SourceVtbl;
71     const ITfKeystrokeMgrVtbl *KeystrokeMgrVtbl;
72     const ITfMessagePumpVtbl *MessagePumpVtbl;
73     const ITfClientIdVtbl *ClientIdVtbl;
74     /* const ITfThreadMgrExVtbl *ThreadMgrExVtbl; */
75     /* const ITfConfigureSystemKeystrokeFeedVtbl *ConfigureSystemKeystrokeFeedVtbl; */
76     /* const ITfLangBarItemMgrVtbl *LangBarItemMgrVtbl; */
77     /* const ITfUIElementMgrVtbl *UIElementMgrVtbl; */
78     /* const ITfSourceSingleVtbl *SourceSingleVtbl; */
79     LONG refCount;
80
81     /* Aggregation */
82     ITfCompartmentMgr  *CompartmentMgr;
83
84     const ITfThreadMgrEventSinkVtbl *ThreadMgrEventSinkVtbl; /* internal */
85
86     ITfDocumentMgr *focus;
87     LONG activationCount;
88
89     ITfKeyEventSink *forgroundKeyEventSink;
90     CLSID forgroundTextService;
91
92     struct list CurrentPreservedKeys;
93
94     /* kept as separate lists to reduce unnecessary iterations */
95     struct list     ActiveLanguageProfileNotifySink;
96     struct list     DisplayAttributeNotifySink;
97     struct list     KeyTraceEventSink;
98     struct list     PreservedKeyNotifySink;
99     struct list     ThreadFocusSink;
100     struct list     ThreadMgrEventSink;
101 } ThreadMgr;
102
103 static inline ThreadMgr *impl_from_ITfSourceVtbl(ITfSource *iface)
104 {
105     return (ThreadMgr *)((char *)iface - FIELD_OFFSET(ThreadMgr,SourceVtbl));
106 }
107
108 static inline ThreadMgr *impl_from_ITfKeystrokeMgrVtbl(ITfKeystrokeMgr *iface)
109 {
110     return (ThreadMgr *)((char *)iface - FIELD_OFFSET(ThreadMgr,KeystrokeMgrVtbl));
111 }
112
113 static inline ThreadMgr *impl_from_ITfMessagePumpVtbl(ITfMessagePump *iface)
114 {
115     return (ThreadMgr *)((char *)iface - FIELD_OFFSET(ThreadMgr,MessagePumpVtbl));
116 }
117
118 static inline ThreadMgr *impl_from_ITfClientIdVtbl(ITfClientId *iface)
119 {
120     return (ThreadMgr *)((char *)iface - FIELD_OFFSET(ThreadMgr,ClientIdVtbl));
121 }
122
123 static inline ThreadMgr *impl_from_ITfThreadMgrEventSink(ITfThreadMgrEventSink *iface)
124 {
125     return (ThreadMgr *)((char *)iface - FIELD_OFFSET(ThreadMgr,ThreadMgrEventSinkVtbl));
126 }
127
128 static void free_sink(ThreadMgrSink *sink)
129 {
130         IUnknown_Release(sink->interfaces.pIUnknown);
131         HeapFree(GetProcessHeap(),0,sink);
132 }
133
134 static void ThreadMgr_Destructor(ThreadMgr *This)
135 {
136     struct list *cursor, *cursor2;
137
138     TlsSetValue(tlsIndex,NULL);
139     TRACE("destroying %p\n", This);
140     if (This->focus)
141         ITfDocumentMgr_Release(This->focus);
142
143     /* free sinks */
144     LIST_FOR_EACH_SAFE(cursor, cursor2, &This->ActiveLanguageProfileNotifySink)
145     {
146         ThreadMgrSink* sink = LIST_ENTRY(cursor,ThreadMgrSink,entry);
147         list_remove(cursor);
148         free_sink(sink);
149     }
150     LIST_FOR_EACH_SAFE(cursor, cursor2, &This->DisplayAttributeNotifySink)
151     {
152         ThreadMgrSink* sink = LIST_ENTRY(cursor,ThreadMgrSink,entry);
153         list_remove(cursor);
154         free_sink(sink);
155     }
156     LIST_FOR_EACH_SAFE(cursor, cursor2, &This->KeyTraceEventSink)
157     {
158         ThreadMgrSink* sink = LIST_ENTRY(cursor,ThreadMgrSink,entry);
159         list_remove(cursor);
160         free_sink(sink);
161     }
162     LIST_FOR_EACH_SAFE(cursor, cursor2, &This->PreservedKeyNotifySink)
163     {
164         ThreadMgrSink* sink = LIST_ENTRY(cursor,ThreadMgrSink,entry);
165         list_remove(cursor);
166         free_sink(sink);
167     }
168     LIST_FOR_EACH_SAFE(cursor, cursor2, &This->ThreadFocusSink)
169     {
170         ThreadMgrSink* sink = LIST_ENTRY(cursor,ThreadMgrSink,entry);
171         list_remove(cursor);
172         free_sink(sink);
173     }
174     LIST_FOR_EACH_SAFE(cursor, cursor2, &This->ThreadMgrEventSink)
175     {
176         ThreadMgrSink* sink = LIST_ENTRY(cursor,ThreadMgrSink,entry);
177         list_remove(cursor);
178         free_sink(sink);
179     }
180
181     LIST_FOR_EACH_SAFE(cursor, cursor2, &This->CurrentPreservedKeys)
182     {
183         PreservedKey* key = LIST_ENTRY(cursor,PreservedKey,entry);
184         list_remove(cursor);
185         HeapFree(GetProcessHeap(),0,key->description);
186         HeapFree(GetProcessHeap(),0,key);
187     }
188
189     CompartmentMgr_Destructor(This->CompartmentMgr);
190
191     HeapFree(GetProcessHeap(),0,This);
192 }
193
194 static HRESULT WINAPI ThreadMgr_QueryInterface(ITfThreadMgr *iface, REFIID iid, LPVOID *ppvOut)
195 {
196     ThreadMgr *This = (ThreadMgr *)iface;
197     *ppvOut = NULL;
198
199     if (IsEqualIID(iid, &IID_IUnknown) || IsEqualIID(iid, &IID_ITfThreadMgr))
200     {
201         *ppvOut = This;
202     }
203     else if (IsEqualIID(iid, &IID_ITfSource))
204     {
205         *ppvOut = &This->SourceVtbl;
206     }
207     else if (IsEqualIID(iid, &IID_ITfKeystrokeMgr))
208     {
209         *ppvOut = &This->KeystrokeMgrVtbl;
210     }
211     else if (IsEqualIID(iid, &IID_ITfMessagePump))
212     {
213         *ppvOut = &This->MessagePumpVtbl;
214     }
215     else if (IsEqualIID(iid, &IID_ITfClientId))
216     {
217         *ppvOut = &This->ClientIdVtbl;
218     }
219     else if (IsEqualIID(iid, &IID_ITfCompartmentMgr))
220     {
221         *ppvOut = This->CompartmentMgr;
222     }
223
224     if (*ppvOut)
225     {
226         IUnknown_AddRef(iface);
227         return S_OK;
228     }
229
230     WARN("unsupported interface: %s\n", debugstr_guid(iid));
231     return E_NOINTERFACE;
232 }
233
234 static ULONG WINAPI ThreadMgr_AddRef(ITfThreadMgr *iface)
235 {
236     ThreadMgr *This = (ThreadMgr *)iface;
237     return InterlockedIncrement(&This->refCount);
238 }
239
240 static ULONG WINAPI ThreadMgr_Release(ITfThreadMgr *iface)
241 {
242     ThreadMgr *This = (ThreadMgr *)iface;
243     ULONG ret;
244
245     ret = InterlockedDecrement(&This->refCount);
246     if (ret == 0)
247         ThreadMgr_Destructor(This);
248     return ret;
249 }
250
251 /*****************************************************
252  * ITfThreadMgr functions
253  *****************************************************/
254
255 static HRESULT WINAPI ThreadMgr_fnActivate( ITfThreadMgr* iface, TfClientId *ptid)
256 {
257     ThreadMgr *This = (ThreadMgr *)iface;
258
259     TRACE("(%p) %p\n",This, ptid);
260
261     if (!ptid)
262         return E_INVALIDARG;
263
264     if (!processId)
265     {
266         GUID guid;
267         CoCreateGuid(&guid);
268         ITfClientId_GetClientId((ITfClientId*)&This->ClientIdVtbl,&guid,&processId);
269     }
270
271     activate_textservices(iface);
272     This->activationCount++;
273     *ptid = processId;
274     return S_OK;
275 }
276
277 static HRESULT WINAPI ThreadMgr_fnDeactivate( ITfThreadMgr* iface)
278 {
279     ThreadMgr *This = (ThreadMgr *)iface;
280     TRACE("(%p)\n",This);
281
282     if (This->activationCount == 0)
283         return E_UNEXPECTED;
284
285     This->activationCount --;
286
287     if (This->activationCount == 0)
288     {
289         if (This->focus)
290         {
291             ITfThreadMgrEventSink_OnSetFocus((ITfThreadMgrEventSink*)&This->ThreadMgrEventSinkVtbl, 0, This->focus);
292             ITfDocumentMgr_Release(This->focus);
293             This->focus = 0;
294         }
295     }
296
297     deactivate_textservices();
298
299     return S_OK;
300 }
301
302 static HRESULT WINAPI ThreadMgr_CreateDocumentMgr( ITfThreadMgr* iface, ITfDocumentMgr
303 **ppdim)
304 {
305     ThreadMgr *This = (ThreadMgr *)iface;
306     TRACE("(%p)\n",iface);
307     return DocumentMgr_Constructor((ITfThreadMgrEventSink*)&This->ThreadMgrEventSinkVtbl, ppdim);
308 }
309
310 static HRESULT WINAPI ThreadMgr_EnumDocumentMgrs( ITfThreadMgr* iface, IEnumTfDocumentMgrs
311 **ppEnum)
312 {
313     ThreadMgr *This = (ThreadMgr *)iface;
314     FIXME("STUB:(%p)\n",This);
315     return E_NOTIMPL;
316 }
317
318 static HRESULT WINAPI ThreadMgr_GetFocus( ITfThreadMgr* iface, ITfDocumentMgr
319 **ppdimFocus)
320 {
321     ThreadMgr *This = (ThreadMgr *)iface;
322     TRACE("(%p)\n",This);
323
324     if (!ppdimFocus)
325         return E_INVALIDARG;
326
327     *ppdimFocus = This->focus;
328
329     TRACE("->%p\n",This->focus);
330
331     if (This->focus == NULL)
332         return S_FALSE;
333
334     ITfDocumentMgr_AddRef(This->focus);
335
336     return S_OK;
337 }
338
339 static HRESULT WINAPI ThreadMgr_SetFocus( ITfThreadMgr* iface, ITfDocumentMgr *pdimFocus)
340 {
341     ITfDocumentMgr *check;
342     ThreadMgr *This = (ThreadMgr *)iface;
343
344     TRACE("(%p) %p\n",This,pdimFocus);
345
346     if (!pdimFocus || FAILED(IUnknown_QueryInterface(pdimFocus,&IID_ITfDocumentMgr,(LPVOID*) &check)))
347         return E_INVALIDARG;
348
349     ITfThreadMgrEventSink_OnSetFocus((ITfThreadMgrEventSink*)&This->ThreadMgrEventSinkVtbl, check, This->focus);
350
351     if (This->focus)
352         ITfDocumentMgr_Release(This->focus);
353
354     This->focus = check;
355     return S_OK;
356 }
357
358 static HRESULT WINAPI ThreadMgr_AssociateFocus( ITfThreadMgr* iface, HWND hwnd,
359 ITfDocumentMgr *pdimNew, ITfDocumentMgr **ppdimPrev)
360 {
361     ThreadMgr *This = (ThreadMgr *)iface;
362     FIXME("STUB:(%p)\n",This);
363     return E_NOTIMPL;
364 }
365
366 static HRESULT WINAPI ThreadMgr_IsThreadFocus( ITfThreadMgr* iface, BOOL *pfThreadFocus)
367 {
368     ThreadMgr *This = (ThreadMgr *)iface;
369     FIXME("STUB:(%p)\n",This);
370     return E_NOTIMPL;
371 }
372
373 static HRESULT WINAPI ThreadMgr_GetFunctionProvider( ITfThreadMgr* iface, REFCLSID clsid,
374 ITfFunctionProvider **ppFuncProv)
375 {
376     ThreadMgr *This = (ThreadMgr *)iface;
377     FIXME("STUB:(%p)\n",This);
378     return E_NOTIMPL;
379 }
380
381 static HRESULT WINAPI ThreadMgr_EnumFunctionProviders( ITfThreadMgr* iface,
382 IEnumTfFunctionProviders **ppEnum)
383 {
384     ThreadMgr *This = (ThreadMgr *)iface;
385     FIXME("STUB:(%p)\n",This);
386     return E_NOTIMPL;
387 }
388
389 static HRESULT WINAPI ThreadMgr_GetGlobalCompartment( ITfThreadMgr* iface,
390 ITfCompartmentMgr **ppCompMgr)
391 {
392     ThreadMgr *This = (ThreadMgr *)iface;
393     HRESULT hr;
394     TRACE("(%p) %p\n",This, ppCompMgr);
395
396     if (!ppCompMgr)
397         return E_INVALIDARG;
398
399     if (!globalCompartmentMgr)
400     {
401         hr = CompartmentMgr_Constructor(NULL,&IID_ITfCompartmentMgr,(IUnknown**)&globalCompartmentMgr);
402         if (FAILED(hr))
403             return hr;
404     }
405
406     ITfCompartmentMgr_AddRef(globalCompartmentMgr);
407     *ppCompMgr = globalCompartmentMgr;
408     return S_OK;
409 }
410
411 static const ITfThreadMgrVtbl ThreadMgr_ThreadMgrVtbl =
412 {
413     ThreadMgr_QueryInterface,
414     ThreadMgr_AddRef,
415     ThreadMgr_Release,
416
417     ThreadMgr_fnActivate,
418     ThreadMgr_fnDeactivate,
419     ThreadMgr_CreateDocumentMgr,
420     ThreadMgr_EnumDocumentMgrs,
421     ThreadMgr_GetFocus,
422     ThreadMgr_SetFocus,
423     ThreadMgr_AssociateFocus,
424     ThreadMgr_IsThreadFocus,
425     ThreadMgr_GetFunctionProvider,
426     ThreadMgr_EnumFunctionProviders,
427     ThreadMgr_GetGlobalCompartment
428 };
429
430
431 static HRESULT WINAPI Source_QueryInterface(ITfSource *iface, REFIID iid, LPVOID *ppvOut)
432 {
433     ThreadMgr *This = impl_from_ITfSourceVtbl(iface);
434     return ThreadMgr_QueryInterface((ITfThreadMgr *)This, iid, *ppvOut);
435 }
436
437 static ULONG WINAPI Source_AddRef(ITfSource *iface)
438 {
439     ThreadMgr *This = impl_from_ITfSourceVtbl(iface);
440     return ThreadMgr_AddRef((ITfThreadMgr*)This);
441 }
442
443 static ULONG WINAPI Source_Release(ITfSource *iface)
444 {
445     ThreadMgr *This = impl_from_ITfSourceVtbl(iface);
446     return ThreadMgr_Release((ITfThreadMgr *)This);
447 }
448
449 /*****************************************************
450  * ITfSource functions
451  *****************************************************/
452 static WINAPI HRESULT ThreadMgrSource_AdviseSink(ITfSource *iface,
453         REFIID riid, IUnknown *punk, DWORD *pdwCookie)
454 {
455     ThreadMgrSink *tms;
456     ThreadMgr *This = impl_from_ITfSourceVtbl(iface);
457
458     TRACE("(%p) %s %p %p\n",This,debugstr_guid(riid),punk,pdwCookie);
459
460     if (!riid || !punk || !pdwCookie)
461         return E_INVALIDARG;
462
463     if (IsEqualIID(riid, &IID_ITfThreadMgrEventSink))
464     {
465         tms = HeapAlloc(GetProcessHeap(),0,sizeof(ThreadMgrSink));
466         if (!tms)
467             return E_OUTOFMEMORY;
468         if (FAILED(IUnknown_QueryInterface(punk, riid, (LPVOID *)&tms->interfaces.pITfThreadMgrEventSink)))
469         {
470             HeapFree(GetProcessHeap(),0,tms);
471             return CONNECT_E_CANNOTCONNECT;
472         }
473         list_add_head(&This->ThreadMgrEventSink,&tms->entry);
474         *pdwCookie = generate_Cookie(COOKIE_MAGIC_TMSINK, tms);
475     }
476     else
477     {
478         FIXME("(%p) Unhandled Sink: %s\n",This,debugstr_guid(riid));
479         return E_NOTIMPL;
480     }
481
482     TRACE("cookie %x\n",*pdwCookie);
483
484     return S_OK;
485 }
486
487 static WINAPI HRESULT ThreadMgrSource_UnadviseSink(ITfSource *iface, DWORD pdwCookie)
488 {
489     ThreadMgrSink *sink;
490     ThreadMgr *This = impl_from_ITfSourceVtbl(iface);
491
492     TRACE("(%p) %x\n",This,pdwCookie);
493
494     if (get_Cookie_magic(pdwCookie)!=COOKIE_MAGIC_TMSINK)
495         return E_INVALIDARG;
496
497     sink = (ThreadMgrSink*)remove_Cookie(pdwCookie);
498     if (!sink)
499         return CONNECT_E_NOCONNECTION;
500
501     list_remove(&sink->entry);
502     free_sink(sink);
503
504     return S_OK;
505 }
506
507 static const ITfSourceVtbl ThreadMgr_SourceVtbl =
508 {
509     Source_QueryInterface,
510     Source_AddRef,
511     Source_Release,
512
513     ThreadMgrSource_AdviseSink,
514     ThreadMgrSource_UnadviseSink,
515 };
516
517 /*****************************************************
518  * ITfKeystrokeMgr functions
519  *****************************************************/
520
521 static HRESULT WINAPI KeystrokeMgr_QueryInterface(ITfKeystrokeMgr *iface, REFIID iid, LPVOID *ppvOut)
522 {
523     ThreadMgr *This = impl_from_ITfKeystrokeMgrVtbl(iface);
524     return ThreadMgr_QueryInterface((ITfThreadMgr *)This, iid, *ppvOut);
525 }
526
527 static ULONG WINAPI KeystrokeMgr_AddRef(ITfKeystrokeMgr *iface)
528 {
529     ThreadMgr *This = impl_from_ITfKeystrokeMgrVtbl(iface);
530     return ThreadMgr_AddRef((ITfThreadMgr*)This);
531 }
532
533 static ULONG WINAPI KeystrokeMgr_Release(ITfKeystrokeMgr *iface)
534 {
535     ThreadMgr *This = impl_from_ITfKeystrokeMgrVtbl(iface);
536     return ThreadMgr_Release((ITfThreadMgr *)This);
537 }
538
539 static HRESULT WINAPI KeystrokeMgr_AdviseKeyEventSink(ITfKeystrokeMgr *iface,
540         TfClientId tid, ITfKeyEventSink *pSink, BOOL fForeground)
541 {
542     ThreadMgr *This = impl_from_ITfKeystrokeMgrVtbl(iface);
543     CLSID textservice;
544     ITfKeyEventSink *check = NULL;
545
546     TRACE("(%p) %x %p %i\n",This,tid,pSink,fForeground);
547
548     if (!tid || !pSink)
549         return E_INVALIDARG;
550
551     textservice = get_textservice_clsid(tid);
552     if (IsEqualCLSID(&GUID_NULL,&textservice))
553         return E_INVALIDARG;
554
555     get_textservice_sink(tid, &IID_ITfKeyEventSink, (IUnknown**)&check);
556     if (check != NULL)
557         return CONNECT_E_ADVISELIMIT;
558
559     if (FAILED(IUnknown_QueryInterface(pSink,&IID_ITfKeyEventSink,(LPVOID*) &check)))
560         return E_INVALIDARG;
561
562     set_textservice_sink(tid, &IID_ITfKeyEventSink, (IUnknown*)check);
563
564     if (fForeground)
565     {
566         if (This->forgroundKeyEventSink)
567         {
568             ITfKeyEventSink_OnSetFocus(This->forgroundKeyEventSink, FALSE);
569             ITfKeyEventSink_Release(This->forgroundKeyEventSink);
570         }
571         ITfKeyEventSink_AddRef(check);
572         ITfKeyEventSink_OnSetFocus(check, TRUE);
573         This->forgroundKeyEventSink = check;
574         This->forgroundTextService = textservice;
575     }
576     return S_OK;
577 }
578
579 static HRESULT WINAPI KeystrokeMgr_UnadviseKeyEventSink(ITfKeystrokeMgr *iface,
580         TfClientId tid)
581 {
582     ThreadMgr *This = impl_from_ITfKeystrokeMgrVtbl(iface);
583     CLSID textservice;
584     ITfKeyEventSink *check = NULL;
585     TRACE("(%p) %x\n",This,tid);
586
587     if (!tid)
588         return E_INVALIDARG;
589
590     textservice = get_textservice_clsid(tid);
591     if (IsEqualCLSID(&GUID_NULL,&textservice))
592         return E_INVALIDARG;
593
594     get_textservice_sink(tid, &IID_ITfKeyEventSink, (IUnknown**)&check);
595
596     if (!check)
597         return CONNECT_E_NOCONNECTION;
598
599     set_textservice_sink(tid, &IID_ITfKeyEventSink, NULL);
600     ITfKeyEventSink_Release(check);
601
602     if (This->forgroundKeyEventSink == check)
603     {
604         ITfKeyEventSink_Release(This->forgroundKeyEventSink);
605         This->forgroundKeyEventSink = NULL;
606         This->forgroundTextService = GUID_NULL;
607     }
608     return S_OK;
609 }
610
611 static HRESULT WINAPI KeystrokeMgr_GetForeground(ITfKeystrokeMgr *iface,
612         CLSID *pclsid)
613 {
614     ThreadMgr *This = impl_from_ITfKeystrokeMgrVtbl(iface);
615     TRACE("(%p) %p\n",This,pclsid);
616     if (!pclsid)
617         return E_INVALIDARG;
618
619     if (IsEqualCLSID(&This->forgroundTextService,&GUID_NULL))
620         return S_FALSE;
621
622     *pclsid = This->forgroundTextService;
623     return S_OK;
624 }
625
626 static HRESULT WINAPI KeystrokeMgr_TestKeyDown(ITfKeystrokeMgr *iface,
627         WPARAM wParam, LPARAM lParam, BOOL *pfEaten)
628 {
629     ThreadMgr *This = impl_from_ITfKeystrokeMgrVtbl(iface);
630     FIXME("STUB:(%p)\n",This);
631     return E_NOTIMPL;
632 }
633
634 static HRESULT WINAPI KeystrokeMgr_TestKeyUp(ITfKeystrokeMgr *iface,
635         WPARAM wParam, LPARAM lParam, BOOL *pfEaten)
636 {
637     ThreadMgr *This = impl_from_ITfKeystrokeMgrVtbl(iface);
638     FIXME("STUB:(%p)\n",This);
639     return E_NOTIMPL;
640 }
641
642 static HRESULT WINAPI KeystrokeMgr_KeyDown(ITfKeystrokeMgr *iface,
643         WPARAM wParam, LPARAM lParam, BOOL *pfEaten)
644 {
645     ThreadMgr *This = impl_from_ITfKeystrokeMgrVtbl(iface);
646     FIXME("STUB:(%p)\n",This);
647     return E_NOTIMPL;
648 }
649
650 static HRESULT WINAPI KeystrokeMgr_KeyUp(ITfKeystrokeMgr *iface,
651         WPARAM wParam, LPARAM lParam, BOOL *pfEaten)
652 {
653     ThreadMgr *This = impl_from_ITfKeystrokeMgrVtbl(iface);
654     FIXME("STUB:(%p)\n",This);
655     return E_NOTIMPL;
656 }
657
658 static HRESULT WINAPI KeystrokeMgr_GetPreservedKey(ITfKeystrokeMgr *iface,
659         ITfContext *pic, const TF_PRESERVEDKEY *pprekey, GUID *pguid)
660 {
661     ThreadMgr *This = impl_from_ITfKeystrokeMgrVtbl(iface);
662     FIXME("STUB:(%p)\n",This);
663     return E_NOTIMPL;
664 }
665
666 static HRESULT WINAPI KeystrokeMgr_IsPreservedKey(ITfKeystrokeMgr *iface,
667         REFGUID rguid, const TF_PRESERVEDKEY *pprekey, BOOL *pfRegistered)
668 {
669     ThreadMgr *This = impl_from_ITfKeystrokeMgrVtbl(iface);
670     struct list *cursor;
671
672     TRACE("(%p) %s (%x %x) %p\n",This,debugstr_guid(rguid), (pprekey)?pprekey->uVKey:0, (pprekey)?pprekey->uModifiers:0, pfRegistered);
673
674     if (!rguid || !pprekey || !pfRegistered)
675         return E_INVALIDARG;
676
677     LIST_FOR_EACH(cursor, &This->CurrentPreservedKeys)
678     {
679         PreservedKey* key = LIST_ENTRY(cursor,PreservedKey,entry);
680         if (IsEqualGUID(rguid,&key->guid) && pprekey->uVKey == key->prekey.uVKey && pprekey->uModifiers == key->prekey.uModifiers)
681         {
682             *pfRegistered = TRUE;
683             return S_OK;
684         }
685     }
686
687     *pfRegistered = FALSE;
688     return S_FALSE;
689 }
690
691 static HRESULT WINAPI KeystrokeMgr_PreserveKey(ITfKeystrokeMgr *iface,
692         TfClientId tid, REFGUID rguid, const TF_PRESERVEDKEY *prekey,
693         const WCHAR *pchDesc, ULONG cchDesc)
694 {
695     ThreadMgr *This = impl_from_ITfKeystrokeMgrVtbl(iface);
696     struct list *cursor;
697     PreservedKey *newkey;
698
699     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));
700
701     if (!tid || ! rguid || !prekey || (cchDesc && !pchDesc))
702         return E_INVALIDARG;
703
704     LIST_FOR_EACH(cursor, &This->CurrentPreservedKeys)
705     {
706         PreservedKey* key = LIST_ENTRY(cursor,PreservedKey,entry);
707         if (IsEqualGUID(rguid,&key->guid) && prekey->uVKey == key->prekey.uVKey && prekey->uModifiers == key->prekey.uModifiers)
708             return TF_E_ALREADY_EXISTS;
709     }
710
711     newkey = HeapAlloc(GetProcessHeap(),0,sizeof(PreservedKey));
712     if (!newkey)
713         return E_OUTOFMEMORY;
714
715     newkey->guid  = *rguid;
716     newkey->prekey = *prekey;
717     newkey->tid = tid;
718     if (cchDesc)
719     {
720         newkey->description = HeapAlloc(GetProcessHeap(),0,cchDesc * sizeof(WCHAR));
721         if (!newkey->description)
722         {
723             HeapFree(GetProcessHeap(),0,newkey);
724             return E_OUTOFMEMORY;
725         }
726         memcpy(newkey->description, pchDesc, cchDesc*sizeof(WCHAR));
727     }
728
729     list_add_head(&This->CurrentPreservedKeys,&newkey->entry);
730
731     return S_OK;
732 }
733
734 static HRESULT WINAPI KeystrokeMgr_UnpreserveKey(ITfKeystrokeMgr *iface,
735         REFGUID rguid, const TF_PRESERVEDKEY *pprekey)
736 {
737     ThreadMgr *This = impl_from_ITfKeystrokeMgrVtbl(iface);
738     PreservedKey* key = NULL;
739     struct list *cursor;
740     TRACE("(%p) %s (%x %x)\n",This,debugstr_guid(rguid),(pprekey)?pprekey->uVKey:0, (pprekey)?pprekey->uModifiers:0);
741
742     if (!pprekey || !rguid)
743         return E_INVALIDARG;
744
745     LIST_FOR_EACH(cursor, &This->CurrentPreservedKeys)
746     {
747         key = LIST_ENTRY(cursor,PreservedKey,entry);
748         if (IsEqualGUID(rguid,&key->guid) && pprekey->uVKey == key->prekey.uVKey && pprekey->uModifiers == key->prekey.uModifiers)
749             break;
750         key = NULL;
751     }
752
753     if (!key)
754         return CONNECT_E_NOCONNECTION;
755
756     list_remove(&key->entry);
757     HeapFree(GetProcessHeap(),0,key->description);
758     HeapFree(GetProcessHeap(),0,key);
759
760     return S_OK;
761 }
762
763 static HRESULT WINAPI KeystrokeMgr_SetPreservedKeyDescription(ITfKeystrokeMgr *iface,
764         REFGUID rguid, const WCHAR *pchDesc, ULONG cchDesc)
765 {
766     ThreadMgr *This = impl_from_ITfKeystrokeMgrVtbl(iface);
767     FIXME("STUB:(%p)\n",This);
768     return E_NOTIMPL;
769 }
770
771 static HRESULT WINAPI KeystrokeMgr_GetPreservedKeyDescription(ITfKeystrokeMgr *iface,
772         REFGUID rguid, BSTR *pbstrDesc)
773 {
774     ThreadMgr *This = impl_from_ITfKeystrokeMgrVtbl(iface);
775     FIXME("STUB:(%p)\n",This);
776     return E_NOTIMPL;
777 }
778
779 static HRESULT WINAPI KeystrokeMgr_SimulatePreservedKey(ITfKeystrokeMgr *iface,
780         ITfContext *pic, REFGUID rguid, BOOL *pfEaten)
781 {
782     ThreadMgr *This = impl_from_ITfKeystrokeMgrVtbl(iface);
783     FIXME("STUB:(%p)\n",This);
784     return E_NOTIMPL;
785 }
786
787 static const ITfKeystrokeMgrVtbl ThreadMgr_KeystrokeMgrVtbl =
788 {
789     KeystrokeMgr_QueryInterface,
790     KeystrokeMgr_AddRef,
791     KeystrokeMgr_Release,
792
793     KeystrokeMgr_AdviseKeyEventSink,
794     KeystrokeMgr_UnadviseKeyEventSink,
795     KeystrokeMgr_GetForeground,
796     KeystrokeMgr_TestKeyDown,
797     KeystrokeMgr_TestKeyUp,
798     KeystrokeMgr_KeyDown,
799     KeystrokeMgr_KeyUp,
800     KeystrokeMgr_GetPreservedKey,
801     KeystrokeMgr_IsPreservedKey,
802     KeystrokeMgr_PreserveKey,
803     KeystrokeMgr_UnpreserveKey,
804     KeystrokeMgr_SetPreservedKeyDescription,
805     KeystrokeMgr_GetPreservedKeyDescription,
806     KeystrokeMgr_SimulatePreservedKey
807 };
808
809 /*****************************************************
810  * ITfMessagePump functions
811  *****************************************************/
812
813 static HRESULT WINAPI MessagePump_QueryInterface(ITfMessagePump *iface, REFIID iid, LPVOID *ppvOut)
814 {
815     ThreadMgr *This = impl_from_ITfMessagePumpVtbl(iface);
816     return ThreadMgr_QueryInterface((ITfThreadMgr *)This, iid, *ppvOut);
817 }
818
819 static ULONG WINAPI MessagePump_AddRef(ITfMessagePump *iface)
820 {
821     ThreadMgr *This = impl_from_ITfMessagePumpVtbl(iface);
822     return ThreadMgr_AddRef((ITfThreadMgr*)This);
823 }
824
825 static ULONG WINAPI MessagePump_Release(ITfMessagePump *iface)
826 {
827     ThreadMgr *This = impl_from_ITfMessagePumpVtbl(iface);
828     return ThreadMgr_Release((ITfThreadMgr *)This);
829 }
830
831 static HRESULT WINAPI MessagePump_PeekMessageA(ITfMessagePump *iface,
832         LPMSG pMsg, HWND hwnd, UINT wMsgFilterMin, UINT wMsgFilterMax,
833         UINT wRemoveMsg, BOOL *pfResult)
834 {
835     if (!pfResult)
836         return E_INVALIDARG;
837     *pfResult = PeekMessageA(pMsg, hwnd, wMsgFilterMin, wMsgFilterMax, wRemoveMsg);
838     return S_OK;
839 }
840
841 static HRESULT WINAPI MessagePump_GetMessageA(ITfMessagePump *iface,
842         LPMSG pMsg, HWND hwnd, UINT wMsgFilterMin, UINT wMsgFilterMax,
843         BOOL *pfResult)
844 {
845     if (!pfResult)
846         return E_INVALIDARG;
847     *pfResult = GetMessageA(pMsg, hwnd, wMsgFilterMin, wMsgFilterMax);
848     return S_OK;
849 }
850
851 static HRESULT WINAPI MessagePump_PeekMessageW(ITfMessagePump *iface,
852         LPMSG pMsg, HWND hwnd, UINT wMsgFilterMin, UINT wMsgFilterMax,
853         UINT wRemoveMsg, BOOL *pfResult)
854 {
855     if (!pfResult)
856         return E_INVALIDARG;
857     *pfResult = PeekMessageW(pMsg, hwnd, wMsgFilterMin, wMsgFilterMax, wRemoveMsg);
858     return S_OK;
859 }
860
861 static HRESULT WINAPI MessagePump_GetMessageW(ITfMessagePump *iface,
862         LPMSG pMsg, HWND hwnd, UINT wMsgFilterMin, UINT wMsgFilterMax,
863         BOOL *pfResult)
864 {
865     if (!pfResult)
866         return E_INVALIDARG;
867     *pfResult = GetMessageW(pMsg, hwnd, wMsgFilterMin, wMsgFilterMax);
868     return S_OK;
869 }
870
871 static const ITfMessagePumpVtbl ThreadMgr_MessagePumpVtbl =
872 {
873     MessagePump_QueryInterface,
874     MessagePump_AddRef,
875     MessagePump_Release,
876
877     MessagePump_PeekMessageA,
878     MessagePump_GetMessageA,
879     MessagePump_PeekMessageW,
880     MessagePump_GetMessageW
881 };
882
883 /*****************************************************
884  * ITfClientId functions
885  *****************************************************/
886
887 static HRESULT WINAPI ClientId_QueryInterface(ITfClientId *iface, REFIID iid, LPVOID *ppvOut)
888 {
889     ThreadMgr *This = impl_from_ITfClientIdVtbl(iface);
890     return ThreadMgr_QueryInterface((ITfThreadMgr *)This, iid, *ppvOut);
891 }
892
893 static ULONG WINAPI ClientId_AddRef(ITfClientId *iface)
894 {
895     ThreadMgr *This = impl_from_ITfClientIdVtbl(iface);
896     return ThreadMgr_AddRef((ITfThreadMgr*)This);
897 }
898
899 static ULONG WINAPI ClientId_Release(ITfClientId *iface)
900 {
901     ThreadMgr *This = impl_from_ITfClientIdVtbl(iface);
902     return ThreadMgr_Release((ITfThreadMgr *)This);
903 }
904
905 static HRESULT WINAPI ClientId_GetClientId(ITfClientId *iface,
906     REFCLSID rclsid, TfClientId *ptid)
907
908 {
909     HRESULT hr;
910     ITfCategoryMgr *catmgr;
911     ThreadMgr *This = impl_from_ITfClientIdVtbl(iface);
912
913     TRACE("(%p) %s\n",This,debugstr_guid(rclsid));
914
915     CategoryMgr_Constructor(NULL,(IUnknown**)&catmgr);
916     hr = ITfCategoryMgr_RegisterGUID(catmgr,rclsid,ptid);
917     ITfCategoryMgr_Release(catmgr);
918
919     return hr;
920 }
921
922 static const ITfClientIdVtbl ThreadMgr_ClientIdVtbl =
923 {
924     ClientId_QueryInterface,
925     ClientId_AddRef,
926     ClientId_Release,
927
928     ClientId_GetClientId
929 };
930
931 /*****************************************************
932  * ITfThreadMgrEventSink functions  (internal)
933  *****************************************************/
934 static HRESULT WINAPI ThreadMgrEventSink_QueryInterface(ITfThreadMgrEventSink *iface, REFIID iid, LPVOID *ppvOut)
935 {
936     ThreadMgr *This = impl_from_ITfThreadMgrEventSink(iface);
937     return ThreadMgr_QueryInterface((ITfThreadMgr *)This, iid, *ppvOut);
938 }
939
940 static ULONG WINAPI ThreadMgrEventSink_AddRef(ITfThreadMgrEventSink *iface)
941 {
942     ThreadMgr *This = impl_from_ITfThreadMgrEventSink(iface);
943     return ThreadMgr_AddRef((ITfThreadMgr*)This);
944 }
945
946 static ULONG WINAPI ThreadMgrEventSink_Release(ITfThreadMgrEventSink *iface)
947 {
948     ThreadMgr *This = impl_from_ITfThreadMgrEventSink(iface);
949     return ThreadMgr_Release((ITfThreadMgr *)This);
950 }
951
952
953 static WINAPI HRESULT ThreadMgrEventSink_OnInitDocumentMgr(
954         ITfThreadMgrEventSink *iface,ITfDocumentMgr *pdim)
955 {
956     struct list *cursor;
957     ThreadMgr *This = impl_from_ITfThreadMgrEventSink(iface);
958
959     TRACE("(%p) %p\n",This,pdim);
960
961     LIST_FOR_EACH(cursor, &This->ThreadMgrEventSink)
962     {
963         ThreadMgrSink* sink = LIST_ENTRY(cursor,ThreadMgrSink,entry);
964         ITfThreadMgrEventSink_OnInitDocumentMgr(sink->interfaces.pITfThreadMgrEventSink,pdim);
965     }
966
967     return S_OK;
968 }
969
970 static WINAPI HRESULT ThreadMgrEventSink_OnUninitDocumentMgr(
971         ITfThreadMgrEventSink *iface, ITfDocumentMgr *pdim)
972 {
973     struct list *cursor;
974     ThreadMgr *This = impl_from_ITfThreadMgrEventSink(iface);
975
976     TRACE("(%p) %p\n",This,pdim);
977
978     LIST_FOR_EACH(cursor, &This->ThreadMgrEventSink)
979     {
980         ThreadMgrSink* sink = LIST_ENTRY(cursor,ThreadMgrSink,entry);
981         ITfThreadMgrEventSink_OnUninitDocumentMgr(sink->interfaces.pITfThreadMgrEventSink,pdim);
982     }
983
984     return S_OK;
985 }
986
987 static WINAPI HRESULT ThreadMgrEventSink_OnSetFocus(
988         ITfThreadMgrEventSink *iface, ITfDocumentMgr *pdimFocus,
989         ITfDocumentMgr *pdimPrevFocus)
990 {
991     struct list *cursor;
992     ThreadMgr *This = impl_from_ITfThreadMgrEventSink(iface);
993
994     TRACE("(%p) %p %p\n",This,pdimFocus, pdimPrevFocus);
995
996     LIST_FOR_EACH(cursor, &This->ThreadMgrEventSink)
997     {
998         ThreadMgrSink* sink = LIST_ENTRY(cursor,ThreadMgrSink,entry);
999         ITfThreadMgrEventSink_OnSetFocus(sink->interfaces.pITfThreadMgrEventSink, pdimFocus, pdimPrevFocus);
1000     }
1001
1002     return S_OK;
1003 }
1004
1005 static WINAPI HRESULT ThreadMgrEventSink_OnPushContext(
1006         ITfThreadMgrEventSink *iface, ITfContext *pic)
1007 {
1008     struct list *cursor;
1009     ThreadMgr *This = impl_from_ITfThreadMgrEventSink(iface);
1010
1011     TRACE("(%p) %p\n",This,pic);
1012
1013     LIST_FOR_EACH(cursor, &This->ThreadMgrEventSink)
1014     {
1015         ThreadMgrSink* sink = LIST_ENTRY(cursor,ThreadMgrSink,entry);
1016         ITfThreadMgrEventSink_OnPushContext(sink->interfaces.pITfThreadMgrEventSink,pic);
1017     }
1018
1019     return S_OK;
1020 }
1021
1022 static WINAPI HRESULT ThreadMgrEventSink_OnPopContext(
1023         ITfThreadMgrEventSink *iface, ITfContext *pic)
1024 {
1025     struct list *cursor;
1026     ThreadMgr *This = impl_from_ITfThreadMgrEventSink(iface);
1027
1028     TRACE("(%p) %p\n",This,pic);
1029
1030     LIST_FOR_EACH(cursor, &This->ThreadMgrEventSink)
1031     {
1032         ThreadMgrSink* sink = LIST_ENTRY(cursor,ThreadMgrSink,entry);
1033         ITfThreadMgrEventSink_OnPopContext(sink->interfaces.pITfThreadMgrEventSink,pic);
1034     }
1035
1036     return S_OK;
1037 }
1038
1039 static const ITfThreadMgrEventSinkVtbl ThreadMgr_ThreadMgrEventSinkVtbl =
1040 {
1041     ThreadMgrEventSink_QueryInterface,
1042     ThreadMgrEventSink_AddRef,
1043     ThreadMgrEventSink_Release,
1044
1045     ThreadMgrEventSink_OnInitDocumentMgr,
1046     ThreadMgrEventSink_OnUninitDocumentMgr,
1047     ThreadMgrEventSink_OnSetFocus,
1048     ThreadMgrEventSink_OnPushContext,
1049     ThreadMgrEventSink_OnPopContext
1050 };
1051
1052 HRESULT ThreadMgr_Constructor(IUnknown *pUnkOuter, IUnknown **ppOut)
1053 {
1054     ThreadMgr *This;
1055     if (pUnkOuter)
1056         return CLASS_E_NOAGGREGATION;
1057
1058     /* Only 1 ThreadMgr is created per thread */
1059     This = TlsGetValue(tlsIndex);
1060     if (This)
1061     {
1062         ThreadMgr_AddRef((ITfThreadMgr*)This);
1063         *ppOut = (IUnknown*)This;
1064         return S_OK;
1065     }
1066
1067     This = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(ThreadMgr));
1068     if (This == NULL)
1069         return E_OUTOFMEMORY;
1070
1071     This->ThreadMgrVtbl= &ThreadMgr_ThreadMgrVtbl;
1072     This->SourceVtbl = &ThreadMgr_SourceVtbl;
1073     This->KeystrokeMgrVtbl= &ThreadMgr_KeystrokeMgrVtbl;
1074     This->MessagePumpVtbl= &ThreadMgr_MessagePumpVtbl;
1075     This->ClientIdVtbl = &ThreadMgr_ClientIdVtbl;
1076     This->ThreadMgrEventSinkVtbl = &ThreadMgr_ThreadMgrEventSinkVtbl;
1077     This->refCount = 1;
1078     TlsSetValue(tlsIndex,This);
1079
1080     CompartmentMgr_Constructor((IUnknown*)This, &IID_IUnknown, (IUnknown**)&This->CompartmentMgr);
1081
1082     list_init(&This->CurrentPreservedKeys);
1083
1084     list_init(&This->ActiveLanguageProfileNotifySink);
1085     list_init(&This->DisplayAttributeNotifySink);
1086     list_init(&This->KeyTraceEventSink);
1087     list_init(&This->PreservedKeyNotifySink);
1088     list_init(&This->ThreadFocusSink);
1089     list_init(&This->ThreadMgrEventSink);
1090
1091     TRACE("returning %p\n", This);
1092     *ppOut = (IUnknown *)This;
1093     return S_OK;
1094 }