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