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