mapi32/tests: Don't run tests if ScInitMapiUtil() fails.
[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     HWND focus;
369     ThreadMgr *This = (ThreadMgr *)iface;
370     TRACE("(%p) %p\n",This,pfThreadFocus);
371     focus = GetFocus();
372     *pfThreadFocus = (focus == NULL);
373     return S_OK;
374 }
375
376 static HRESULT WINAPI ThreadMgr_GetFunctionProvider( ITfThreadMgr* iface, REFCLSID clsid,
377 ITfFunctionProvider **ppFuncProv)
378 {
379     ThreadMgr *This = (ThreadMgr *)iface;
380     FIXME("STUB:(%p)\n",This);
381     return E_NOTIMPL;
382 }
383
384 static HRESULT WINAPI ThreadMgr_EnumFunctionProviders( ITfThreadMgr* iface,
385 IEnumTfFunctionProviders **ppEnum)
386 {
387     ThreadMgr *This = (ThreadMgr *)iface;
388     FIXME("STUB:(%p)\n",This);
389     return E_NOTIMPL;
390 }
391
392 static HRESULT WINAPI ThreadMgr_GetGlobalCompartment( ITfThreadMgr* iface,
393 ITfCompartmentMgr **ppCompMgr)
394 {
395     ThreadMgr *This = (ThreadMgr *)iface;
396     HRESULT hr;
397     TRACE("(%p) %p\n",This, ppCompMgr);
398
399     if (!ppCompMgr)
400         return E_INVALIDARG;
401
402     if (!globalCompartmentMgr)
403     {
404         hr = CompartmentMgr_Constructor(NULL,&IID_ITfCompartmentMgr,(IUnknown**)&globalCompartmentMgr);
405         if (FAILED(hr))
406             return hr;
407     }
408
409     ITfCompartmentMgr_AddRef(globalCompartmentMgr);
410     *ppCompMgr = globalCompartmentMgr;
411     return S_OK;
412 }
413
414 static const ITfThreadMgrVtbl ThreadMgr_ThreadMgrVtbl =
415 {
416     ThreadMgr_QueryInterface,
417     ThreadMgr_AddRef,
418     ThreadMgr_Release,
419
420     ThreadMgr_fnActivate,
421     ThreadMgr_fnDeactivate,
422     ThreadMgr_CreateDocumentMgr,
423     ThreadMgr_EnumDocumentMgrs,
424     ThreadMgr_GetFocus,
425     ThreadMgr_SetFocus,
426     ThreadMgr_AssociateFocus,
427     ThreadMgr_IsThreadFocus,
428     ThreadMgr_GetFunctionProvider,
429     ThreadMgr_EnumFunctionProviders,
430     ThreadMgr_GetGlobalCompartment
431 };
432
433
434 static HRESULT WINAPI Source_QueryInterface(ITfSource *iface, REFIID iid, LPVOID *ppvOut)
435 {
436     ThreadMgr *This = impl_from_ITfSourceVtbl(iface);
437     return ThreadMgr_QueryInterface((ITfThreadMgr *)This, iid, *ppvOut);
438 }
439
440 static ULONG WINAPI Source_AddRef(ITfSource *iface)
441 {
442     ThreadMgr *This = impl_from_ITfSourceVtbl(iface);
443     return ThreadMgr_AddRef((ITfThreadMgr*)This);
444 }
445
446 static ULONG WINAPI Source_Release(ITfSource *iface)
447 {
448     ThreadMgr *This = impl_from_ITfSourceVtbl(iface);
449     return ThreadMgr_Release((ITfThreadMgr *)This);
450 }
451
452 /*****************************************************
453  * ITfSource functions
454  *****************************************************/
455 static WINAPI HRESULT ThreadMgrSource_AdviseSink(ITfSource *iface,
456         REFIID riid, IUnknown *punk, DWORD *pdwCookie)
457 {
458     ThreadMgrSink *tms;
459     ThreadMgr *This = impl_from_ITfSourceVtbl(iface);
460
461     TRACE("(%p) %s %p %p\n",This,debugstr_guid(riid),punk,pdwCookie);
462
463     if (!riid || !punk || !pdwCookie)
464         return E_INVALIDARG;
465
466     if (IsEqualIID(riid, &IID_ITfThreadMgrEventSink))
467     {
468         tms = HeapAlloc(GetProcessHeap(),0,sizeof(ThreadMgrSink));
469         if (!tms)
470             return E_OUTOFMEMORY;
471         if (FAILED(IUnknown_QueryInterface(punk, riid, (LPVOID *)&tms->interfaces.pITfThreadMgrEventSink)))
472         {
473             HeapFree(GetProcessHeap(),0,tms);
474             return CONNECT_E_CANNOTCONNECT;
475         }
476         list_add_head(&This->ThreadMgrEventSink,&tms->entry);
477         *pdwCookie = generate_Cookie(COOKIE_MAGIC_TMSINK, tms);
478     }
479     else
480     {
481         FIXME("(%p) Unhandled Sink: %s\n",This,debugstr_guid(riid));
482         return E_NOTIMPL;
483     }
484
485     TRACE("cookie %x\n",*pdwCookie);
486
487     return S_OK;
488 }
489
490 static WINAPI HRESULT ThreadMgrSource_UnadviseSink(ITfSource *iface, DWORD pdwCookie)
491 {
492     ThreadMgrSink *sink;
493     ThreadMgr *This = impl_from_ITfSourceVtbl(iface);
494
495     TRACE("(%p) %x\n",This,pdwCookie);
496
497     if (get_Cookie_magic(pdwCookie)!=COOKIE_MAGIC_TMSINK)
498         return E_INVALIDARG;
499
500     sink = (ThreadMgrSink*)remove_Cookie(pdwCookie);
501     if (!sink)
502         return CONNECT_E_NOCONNECTION;
503
504     list_remove(&sink->entry);
505     free_sink(sink);
506
507     return S_OK;
508 }
509
510 static const ITfSourceVtbl ThreadMgr_SourceVtbl =
511 {
512     Source_QueryInterface,
513     Source_AddRef,
514     Source_Release,
515
516     ThreadMgrSource_AdviseSink,
517     ThreadMgrSource_UnadviseSink,
518 };
519
520 /*****************************************************
521  * ITfKeystrokeMgr functions
522  *****************************************************/
523
524 static HRESULT WINAPI KeystrokeMgr_QueryInterface(ITfKeystrokeMgr *iface, REFIID iid, LPVOID *ppvOut)
525 {
526     ThreadMgr *This = impl_from_ITfKeystrokeMgrVtbl(iface);
527     return ThreadMgr_QueryInterface((ITfThreadMgr *)This, iid, *ppvOut);
528 }
529
530 static ULONG WINAPI KeystrokeMgr_AddRef(ITfKeystrokeMgr *iface)
531 {
532     ThreadMgr *This = impl_from_ITfKeystrokeMgrVtbl(iface);
533     return ThreadMgr_AddRef((ITfThreadMgr*)This);
534 }
535
536 static ULONG WINAPI KeystrokeMgr_Release(ITfKeystrokeMgr *iface)
537 {
538     ThreadMgr *This = impl_from_ITfKeystrokeMgrVtbl(iface);
539     return ThreadMgr_Release((ITfThreadMgr *)This);
540 }
541
542 static HRESULT WINAPI KeystrokeMgr_AdviseKeyEventSink(ITfKeystrokeMgr *iface,
543         TfClientId tid, ITfKeyEventSink *pSink, BOOL fForeground)
544 {
545     ThreadMgr *This = impl_from_ITfKeystrokeMgrVtbl(iface);
546     CLSID textservice;
547     ITfKeyEventSink *check = NULL;
548
549     TRACE("(%p) %x %p %i\n",This,tid,pSink,fForeground);
550
551     if (!tid || !pSink)
552         return E_INVALIDARG;
553
554     textservice = get_textservice_clsid(tid);
555     if (IsEqualCLSID(&GUID_NULL,&textservice))
556         return E_INVALIDARG;
557
558     get_textservice_sink(tid, &IID_ITfKeyEventSink, (IUnknown**)&check);
559     if (check != NULL)
560         return CONNECT_E_ADVISELIMIT;
561
562     if (FAILED(IUnknown_QueryInterface(pSink,&IID_ITfKeyEventSink,(LPVOID*) &check)))
563         return E_INVALIDARG;
564
565     set_textservice_sink(tid, &IID_ITfKeyEventSink, (IUnknown*)check);
566
567     if (fForeground)
568     {
569         if (This->forgroundKeyEventSink)
570         {
571             ITfKeyEventSink_OnSetFocus(This->forgroundKeyEventSink, FALSE);
572             ITfKeyEventSink_Release(This->forgroundKeyEventSink);
573         }
574         ITfKeyEventSink_AddRef(check);
575         ITfKeyEventSink_OnSetFocus(check, TRUE);
576         This->forgroundKeyEventSink = check;
577         This->forgroundTextService = textservice;
578     }
579     return S_OK;
580 }
581
582 static HRESULT WINAPI KeystrokeMgr_UnadviseKeyEventSink(ITfKeystrokeMgr *iface,
583         TfClientId tid)
584 {
585     ThreadMgr *This = impl_from_ITfKeystrokeMgrVtbl(iface);
586     CLSID textservice;
587     ITfKeyEventSink *check = NULL;
588     TRACE("(%p) %x\n",This,tid);
589
590     if (!tid)
591         return E_INVALIDARG;
592
593     textservice = get_textservice_clsid(tid);
594     if (IsEqualCLSID(&GUID_NULL,&textservice))
595         return E_INVALIDARG;
596
597     get_textservice_sink(tid, &IID_ITfKeyEventSink, (IUnknown**)&check);
598
599     if (!check)
600         return CONNECT_E_NOCONNECTION;
601
602     set_textservice_sink(tid, &IID_ITfKeyEventSink, NULL);
603     ITfKeyEventSink_Release(check);
604
605     if (This->forgroundKeyEventSink == check)
606     {
607         ITfKeyEventSink_Release(This->forgroundKeyEventSink);
608         This->forgroundKeyEventSink = NULL;
609         This->forgroundTextService = GUID_NULL;
610     }
611     return S_OK;
612 }
613
614 static HRESULT WINAPI KeystrokeMgr_GetForeground(ITfKeystrokeMgr *iface,
615         CLSID *pclsid)
616 {
617     ThreadMgr *This = impl_from_ITfKeystrokeMgrVtbl(iface);
618     TRACE("(%p) %p\n",This,pclsid);
619     if (!pclsid)
620         return E_INVALIDARG;
621
622     if (IsEqualCLSID(&This->forgroundTextService,&GUID_NULL))
623         return S_FALSE;
624
625     *pclsid = This->forgroundTextService;
626     return S_OK;
627 }
628
629 static HRESULT WINAPI KeystrokeMgr_TestKeyDown(ITfKeystrokeMgr *iface,
630         WPARAM wParam, LPARAM lParam, BOOL *pfEaten)
631 {
632     ThreadMgr *This = impl_from_ITfKeystrokeMgrVtbl(iface);
633     FIXME("STUB:(%p)\n",This);
634     return E_NOTIMPL;
635 }
636
637 static HRESULT WINAPI KeystrokeMgr_TestKeyUp(ITfKeystrokeMgr *iface,
638         WPARAM wParam, LPARAM lParam, BOOL *pfEaten)
639 {
640     ThreadMgr *This = impl_from_ITfKeystrokeMgrVtbl(iface);
641     FIXME("STUB:(%p)\n",This);
642     return E_NOTIMPL;
643 }
644
645 static HRESULT WINAPI KeystrokeMgr_KeyDown(ITfKeystrokeMgr *iface,
646         WPARAM wParam, LPARAM lParam, BOOL *pfEaten)
647 {
648     ThreadMgr *This = impl_from_ITfKeystrokeMgrVtbl(iface);
649     FIXME("STUB:(%p)\n",This);
650     return E_NOTIMPL;
651 }
652
653 static HRESULT WINAPI KeystrokeMgr_KeyUp(ITfKeystrokeMgr *iface,
654         WPARAM wParam, LPARAM lParam, BOOL *pfEaten)
655 {
656     ThreadMgr *This = impl_from_ITfKeystrokeMgrVtbl(iface);
657     FIXME("STUB:(%p)\n",This);
658     return E_NOTIMPL;
659 }
660
661 static HRESULT WINAPI KeystrokeMgr_GetPreservedKey(ITfKeystrokeMgr *iface,
662         ITfContext *pic, const TF_PRESERVEDKEY *pprekey, GUID *pguid)
663 {
664     ThreadMgr *This = impl_from_ITfKeystrokeMgrVtbl(iface);
665     FIXME("STUB:(%p)\n",This);
666     return E_NOTIMPL;
667 }
668
669 static HRESULT WINAPI KeystrokeMgr_IsPreservedKey(ITfKeystrokeMgr *iface,
670         REFGUID rguid, const TF_PRESERVEDKEY *pprekey, BOOL *pfRegistered)
671 {
672     ThreadMgr *This = impl_from_ITfKeystrokeMgrVtbl(iface);
673     struct list *cursor;
674
675     TRACE("(%p) %s (%x %x) %p\n",This,debugstr_guid(rguid), (pprekey)?pprekey->uVKey:0, (pprekey)?pprekey->uModifiers:0, pfRegistered);
676
677     if (!rguid || !pprekey || !pfRegistered)
678         return E_INVALIDARG;
679
680     LIST_FOR_EACH(cursor, &This->CurrentPreservedKeys)
681     {
682         PreservedKey* key = LIST_ENTRY(cursor,PreservedKey,entry);
683         if (IsEqualGUID(rguid,&key->guid) && pprekey->uVKey == key->prekey.uVKey && pprekey->uModifiers == key->prekey.uModifiers)
684         {
685             *pfRegistered = TRUE;
686             return S_OK;
687         }
688     }
689
690     *pfRegistered = FALSE;
691     return S_FALSE;
692 }
693
694 static HRESULT WINAPI KeystrokeMgr_PreserveKey(ITfKeystrokeMgr *iface,
695         TfClientId tid, REFGUID rguid, const TF_PRESERVEDKEY *prekey,
696         const WCHAR *pchDesc, ULONG cchDesc)
697 {
698     ThreadMgr *This = impl_from_ITfKeystrokeMgrVtbl(iface);
699     struct list *cursor;
700     PreservedKey *newkey;
701
702     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));
703
704     if (!tid || ! rguid || !prekey || (cchDesc && !pchDesc))
705         return E_INVALIDARG;
706
707     LIST_FOR_EACH(cursor, &This->CurrentPreservedKeys)
708     {
709         PreservedKey* key = LIST_ENTRY(cursor,PreservedKey,entry);
710         if (IsEqualGUID(rguid,&key->guid) && prekey->uVKey == key->prekey.uVKey && prekey->uModifiers == key->prekey.uModifiers)
711             return TF_E_ALREADY_EXISTS;
712     }
713
714     newkey = HeapAlloc(GetProcessHeap(),0,sizeof(PreservedKey));
715     if (!newkey)
716         return E_OUTOFMEMORY;
717
718     newkey->guid  = *rguid;
719     newkey->prekey = *prekey;
720     newkey->tid = tid;
721     if (cchDesc)
722     {
723         newkey->description = HeapAlloc(GetProcessHeap(),0,cchDesc * sizeof(WCHAR));
724         if (!newkey->description)
725         {
726             HeapFree(GetProcessHeap(),0,newkey);
727             return E_OUTOFMEMORY;
728         }
729         memcpy(newkey->description, pchDesc, cchDesc*sizeof(WCHAR));
730     }
731
732     list_add_head(&This->CurrentPreservedKeys,&newkey->entry);
733
734     return S_OK;
735 }
736
737 static HRESULT WINAPI KeystrokeMgr_UnpreserveKey(ITfKeystrokeMgr *iface,
738         REFGUID rguid, const TF_PRESERVEDKEY *pprekey)
739 {
740     ThreadMgr *This = impl_from_ITfKeystrokeMgrVtbl(iface);
741     PreservedKey* key = NULL;
742     struct list *cursor;
743     TRACE("(%p) %s (%x %x)\n",This,debugstr_guid(rguid),(pprekey)?pprekey->uVKey:0, (pprekey)?pprekey->uModifiers:0);
744
745     if (!pprekey || !rguid)
746         return E_INVALIDARG;
747
748     LIST_FOR_EACH(cursor, &This->CurrentPreservedKeys)
749     {
750         key = LIST_ENTRY(cursor,PreservedKey,entry);
751         if (IsEqualGUID(rguid,&key->guid) && pprekey->uVKey == key->prekey.uVKey && pprekey->uModifiers == key->prekey.uModifiers)
752             break;
753         key = NULL;
754     }
755
756     if (!key)
757         return CONNECT_E_NOCONNECTION;
758
759     list_remove(&key->entry);
760     HeapFree(GetProcessHeap(),0,key->description);
761     HeapFree(GetProcessHeap(),0,key);
762
763     return S_OK;
764 }
765
766 static HRESULT WINAPI KeystrokeMgr_SetPreservedKeyDescription(ITfKeystrokeMgr *iface,
767         REFGUID rguid, const WCHAR *pchDesc, ULONG cchDesc)
768 {
769     ThreadMgr *This = impl_from_ITfKeystrokeMgrVtbl(iface);
770     FIXME("STUB:(%p)\n",This);
771     return E_NOTIMPL;
772 }
773
774 static HRESULT WINAPI KeystrokeMgr_GetPreservedKeyDescription(ITfKeystrokeMgr *iface,
775         REFGUID rguid, BSTR *pbstrDesc)
776 {
777     ThreadMgr *This = impl_from_ITfKeystrokeMgrVtbl(iface);
778     FIXME("STUB:(%p)\n",This);
779     return E_NOTIMPL;
780 }
781
782 static HRESULT WINAPI KeystrokeMgr_SimulatePreservedKey(ITfKeystrokeMgr *iface,
783         ITfContext *pic, REFGUID rguid, BOOL *pfEaten)
784 {
785     ThreadMgr *This = impl_from_ITfKeystrokeMgrVtbl(iface);
786     FIXME("STUB:(%p)\n",This);
787     return E_NOTIMPL;
788 }
789
790 static const ITfKeystrokeMgrVtbl ThreadMgr_KeystrokeMgrVtbl =
791 {
792     KeystrokeMgr_QueryInterface,
793     KeystrokeMgr_AddRef,
794     KeystrokeMgr_Release,
795
796     KeystrokeMgr_AdviseKeyEventSink,
797     KeystrokeMgr_UnadviseKeyEventSink,
798     KeystrokeMgr_GetForeground,
799     KeystrokeMgr_TestKeyDown,
800     KeystrokeMgr_TestKeyUp,
801     KeystrokeMgr_KeyDown,
802     KeystrokeMgr_KeyUp,
803     KeystrokeMgr_GetPreservedKey,
804     KeystrokeMgr_IsPreservedKey,
805     KeystrokeMgr_PreserveKey,
806     KeystrokeMgr_UnpreserveKey,
807     KeystrokeMgr_SetPreservedKeyDescription,
808     KeystrokeMgr_GetPreservedKeyDescription,
809     KeystrokeMgr_SimulatePreservedKey
810 };
811
812 /*****************************************************
813  * ITfMessagePump functions
814  *****************************************************/
815
816 static HRESULT WINAPI MessagePump_QueryInterface(ITfMessagePump *iface, REFIID iid, LPVOID *ppvOut)
817 {
818     ThreadMgr *This = impl_from_ITfMessagePumpVtbl(iface);
819     return ThreadMgr_QueryInterface((ITfThreadMgr *)This, iid, *ppvOut);
820 }
821
822 static ULONG WINAPI MessagePump_AddRef(ITfMessagePump *iface)
823 {
824     ThreadMgr *This = impl_from_ITfMessagePumpVtbl(iface);
825     return ThreadMgr_AddRef((ITfThreadMgr*)This);
826 }
827
828 static ULONG WINAPI MessagePump_Release(ITfMessagePump *iface)
829 {
830     ThreadMgr *This = impl_from_ITfMessagePumpVtbl(iface);
831     return ThreadMgr_Release((ITfThreadMgr *)This);
832 }
833
834 static HRESULT WINAPI MessagePump_PeekMessageA(ITfMessagePump *iface,
835         LPMSG pMsg, HWND hwnd, UINT wMsgFilterMin, UINT wMsgFilterMax,
836         UINT wRemoveMsg, BOOL *pfResult)
837 {
838     if (!pfResult)
839         return E_INVALIDARG;
840     *pfResult = PeekMessageA(pMsg, hwnd, wMsgFilterMin, wMsgFilterMax, wRemoveMsg);
841     return S_OK;
842 }
843
844 static HRESULT WINAPI MessagePump_GetMessageA(ITfMessagePump *iface,
845         LPMSG pMsg, HWND hwnd, UINT wMsgFilterMin, UINT wMsgFilterMax,
846         BOOL *pfResult)
847 {
848     if (!pfResult)
849         return E_INVALIDARG;
850     *pfResult = GetMessageA(pMsg, hwnd, wMsgFilterMin, wMsgFilterMax);
851     return S_OK;
852 }
853
854 static HRESULT WINAPI MessagePump_PeekMessageW(ITfMessagePump *iface,
855         LPMSG pMsg, HWND hwnd, UINT wMsgFilterMin, UINT wMsgFilterMax,
856         UINT wRemoveMsg, BOOL *pfResult)
857 {
858     if (!pfResult)
859         return E_INVALIDARG;
860     *pfResult = PeekMessageW(pMsg, hwnd, wMsgFilterMin, wMsgFilterMax, wRemoveMsg);
861     return S_OK;
862 }
863
864 static HRESULT WINAPI MessagePump_GetMessageW(ITfMessagePump *iface,
865         LPMSG pMsg, HWND hwnd, UINT wMsgFilterMin, UINT wMsgFilterMax,
866         BOOL *pfResult)
867 {
868     if (!pfResult)
869         return E_INVALIDARG;
870     *pfResult = GetMessageW(pMsg, hwnd, wMsgFilterMin, wMsgFilterMax);
871     return S_OK;
872 }
873
874 static const ITfMessagePumpVtbl ThreadMgr_MessagePumpVtbl =
875 {
876     MessagePump_QueryInterface,
877     MessagePump_AddRef,
878     MessagePump_Release,
879
880     MessagePump_PeekMessageA,
881     MessagePump_GetMessageA,
882     MessagePump_PeekMessageW,
883     MessagePump_GetMessageW
884 };
885
886 /*****************************************************
887  * ITfClientId functions
888  *****************************************************/
889
890 static HRESULT WINAPI ClientId_QueryInterface(ITfClientId *iface, REFIID iid, LPVOID *ppvOut)
891 {
892     ThreadMgr *This = impl_from_ITfClientIdVtbl(iface);
893     return ThreadMgr_QueryInterface((ITfThreadMgr *)This, iid, *ppvOut);
894 }
895
896 static ULONG WINAPI ClientId_AddRef(ITfClientId *iface)
897 {
898     ThreadMgr *This = impl_from_ITfClientIdVtbl(iface);
899     return ThreadMgr_AddRef((ITfThreadMgr*)This);
900 }
901
902 static ULONG WINAPI ClientId_Release(ITfClientId *iface)
903 {
904     ThreadMgr *This = impl_from_ITfClientIdVtbl(iface);
905     return ThreadMgr_Release((ITfThreadMgr *)This);
906 }
907
908 static HRESULT WINAPI ClientId_GetClientId(ITfClientId *iface,
909     REFCLSID rclsid, TfClientId *ptid)
910
911 {
912     HRESULT hr;
913     ITfCategoryMgr *catmgr;
914     ThreadMgr *This = impl_from_ITfClientIdVtbl(iface);
915
916     TRACE("(%p) %s\n",This,debugstr_guid(rclsid));
917
918     CategoryMgr_Constructor(NULL,(IUnknown**)&catmgr);
919     hr = ITfCategoryMgr_RegisterGUID(catmgr,rclsid,ptid);
920     ITfCategoryMgr_Release(catmgr);
921
922     return hr;
923 }
924
925 static const ITfClientIdVtbl ThreadMgr_ClientIdVtbl =
926 {
927     ClientId_QueryInterface,
928     ClientId_AddRef,
929     ClientId_Release,
930
931     ClientId_GetClientId
932 };
933
934 /*****************************************************
935  * ITfThreadMgrEventSink functions  (internal)
936  *****************************************************/
937 static HRESULT WINAPI ThreadMgrEventSink_QueryInterface(ITfThreadMgrEventSink *iface, REFIID iid, LPVOID *ppvOut)
938 {
939     ThreadMgr *This = impl_from_ITfThreadMgrEventSink(iface);
940     return ThreadMgr_QueryInterface((ITfThreadMgr *)This, iid, *ppvOut);
941 }
942
943 static ULONG WINAPI ThreadMgrEventSink_AddRef(ITfThreadMgrEventSink *iface)
944 {
945     ThreadMgr *This = impl_from_ITfThreadMgrEventSink(iface);
946     return ThreadMgr_AddRef((ITfThreadMgr*)This);
947 }
948
949 static ULONG WINAPI ThreadMgrEventSink_Release(ITfThreadMgrEventSink *iface)
950 {
951     ThreadMgr *This = impl_from_ITfThreadMgrEventSink(iface);
952     return ThreadMgr_Release((ITfThreadMgr *)This);
953 }
954
955
956 static WINAPI HRESULT ThreadMgrEventSink_OnInitDocumentMgr(
957         ITfThreadMgrEventSink *iface,ITfDocumentMgr *pdim)
958 {
959     struct list *cursor;
960     ThreadMgr *This = impl_from_ITfThreadMgrEventSink(iface);
961
962     TRACE("(%p) %p\n",This,pdim);
963
964     LIST_FOR_EACH(cursor, &This->ThreadMgrEventSink)
965     {
966         ThreadMgrSink* sink = LIST_ENTRY(cursor,ThreadMgrSink,entry);
967         ITfThreadMgrEventSink_OnInitDocumentMgr(sink->interfaces.pITfThreadMgrEventSink,pdim);
968     }
969
970     return S_OK;
971 }
972
973 static WINAPI HRESULT ThreadMgrEventSink_OnUninitDocumentMgr(
974         ITfThreadMgrEventSink *iface, ITfDocumentMgr *pdim)
975 {
976     struct list *cursor;
977     ThreadMgr *This = impl_from_ITfThreadMgrEventSink(iface);
978
979     TRACE("(%p) %p\n",This,pdim);
980
981     LIST_FOR_EACH(cursor, &This->ThreadMgrEventSink)
982     {
983         ThreadMgrSink* sink = LIST_ENTRY(cursor,ThreadMgrSink,entry);
984         ITfThreadMgrEventSink_OnUninitDocumentMgr(sink->interfaces.pITfThreadMgrEventSink,pdim);
985     }
986
987     return S_OK;
988 }
989
990 static WINAPI HRESULT ThreadMgrEventSink_OnSetFocus(
991         ITfThreadMgrEventSink *iface, ITfDocumentMgr *pdimFocus,
992         ITfDocumentMgr *pdimPrevFocus)
993 {
994     struct list *cursor;
995     ThreadMgr *This = impl_from_ITfThreadMgrEventSink(iface);
996
997     TRACE("(%p) %p %p\n",This,pdimFocus, pdimPrevFocus);
998
999     LIST_FOR_EACH(cursor, &This->ThreadMgrEventSink)
1000     {
1001         ThreadMgrSink* sink = LIST_ENTRY(cursor,ThreadMgrSink,entry);
1002         ITfThreadMgrEventSink_OnSetFocus(sink->interfaces.pITfThreadMgrEventSink, pdimFocus, pdimPrevFocus);
1003     }
1004
1005     return S_OK;
1006 }
1007
1008 static WINAPI HRESULT ThreadMgrEventSink_OnPushContext(
1009         ITfThreadMgrEventSink *iface, ITfContext *pic)
1010 {
1011     struct list *cursor;
1012     ThreadMgr *This = impl_from_ITfThreadMgrEventSink(iface);
1013
1014     TRACE("(%p) %p\n",This,pic);
1015
1016     LIST_FOR_EACH(cursor, &This->ThreadMgrEventSink)
1017     {
1018         ThreadMgrSink* sink = LIST_ENTRY(cursor,ThreadMgrSink,entry);
1019         ITfThreadMgrEventSink_OnPushContext(sink->interfaces.pITfThreadMgrEventSink,pic);
1020     }
1021
1022     return S_OK;
1023 }
1024
1025 static WINAPI HRESULT ThreadMgrEventSink_OnPopContext(
1026         ITfThreadMgrEventSink *iface, ITfContext *pic)
1027 {
1028     struct list *cursor;
1029     ThreadMgr *This = impl_from_ITfThreadMgrEventSink(iface);
1030
1031     TRACE("(%p) %p\n",This,pic);
1032
1033     LIST_FOR_EACH(cursor, &This->ThreadMgrEventSink)
1034     {
1035         ThreadMgrSink* sink = LIST_ENTRY(cursor,ThreadMgrSink,entry);
1036         ITfThreadMgrEventSink_OnPopContext(sink->interfaces.pITfThreadMgrEventSink,pic);
1037     }
1038
1039     return S_OK;
1040 }
1041
1042 static const ITfThreadMgrEventSinkVtbl ThreadMgr_ThreadMgrEventSinkVtbl =
1043 {
1044     ThreadMgrEventSink_QueryInterface,
1045     ThreadMgrEventSink_AddRef,
1046     ThreadMgrEventSink_Release,
1047
1048     ThreadMgrEventSink_OnInitDocumentMgr,
1049     ThreadMgrEventSink_OnUninitDocumentMgr,
1050     ThreadMgrEventSink_OnSetFocus,
1051     ThreadMgrEventSink_OnPushContext,
1052     ThreadMgrEventSink_OnPopContext
1053 };
1054
1055 HRESULT ThreadMgr_Constructor(IUnknown *pUnkOuter, IUnknown **ppOut)
1056 {
1057     ThreadMgr *This;
1058     if (pUnkOuter)
1059         return CLASS_E_NOAGGREGATION;
1060
1061     /* Only 1 ThreadMgr is created per thread */
1062     This = TlsGetValue(tlsIndex);
1063     if (This)
1064     {
1065         ThreadMgr_AddRef((ITfThreadMgr*)This);
1066         *ppOut = (IUnknown*)This;
1067         return S_OK;
1068     }
1069
1070     This = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(ThreadMgr));
1071     if (This == NULL)
1072         return E_OUTOFMEMORY;
1073
1074     This->ThreadMgrVtbl= &ThreadMgr_ThreadMgrVtbl;
1075     This->SourceVtbl = &ThreadMgr_SourceVtbl;
1076     This->KeystrokeMgrVtbl= &ThreadMgr_KeystrokeMgrVtbl;
1077     This->MessagePumpVtbl= &ThreadMgr_MessagePumpVtbl;
1078     This->ClientIdVtbl = &ThreadMgr_ClientIdVtbl;
1079     This->ThreadMgrEventSinkVtbl = &ThreadMgr_ThreadMgrEventSinkVtbl;
1080     This->refCount = 1;
1081     TlsSetValue(tlsIndex,This);
1082
1083     CompartmentMgr_Constructor((IUnknown*)This, &IID_IUnknown, (IUnknown**)&This->CompartmentMgr);
1084
1085     list_init(&This->CurrentPreservedKeys);
1086
1087     list_init(&This->ActiveLanguageProfileNotifySink);
1088     list_init(&This->DisplayAttributeNotifySink);
1089     list_init(&This->KeyTraceEventSink);
1090     list_init(&This->PreservedKeyNotifySink);
1091     list_init(&This->ThreadFocusSink);
1092     list_init(&This->ThreadMgrEventSink);
1093
1094     TRACE("returning %p\n", This);
1095     *ppOut = (IUnknown *)This;
1096     return S_OK;
1097 }