msctf: Implement ITfKeystrokeMgr::PreserveKey.
[wine/multimedia.git] / dlls / msctf / threadmgr.c
blob5580410f164314b35d803082a5f15fb03ed698e7
1 /*
2 * ITfThreadMgr implementation
4 * Copyright 2008 Aric Stewart, CodeWeavers
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.
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.
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
21 #include "config.h"
23 #include <stdarg.h>
25 #define COBJMACROS
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"
37 #include "wine/unicode.h"
38 #include "wine/list.h"
40 #include "msctf.h"
41 #include "msctf_internal.h"
43 WINE_DEFAULT_DEBUG_CHANNEL(msctf);
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;
59 typedef struct tagPreservedKey
61 struct list entry;
62 GUID guid;
63 TF_PRESERVEDKEY prekey;
64 LPWSTR description;
65 TfClientId tid;
66 } PreservedKey;
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 LONG refCount;
76 const ITfThreadMgrEventSinkVtbl *ThreadMgrEventSinkVtbl; /* internal */
78 ITfDocumentMgr *focus;
80 struct list CurrentPreservedKeys;
82 /* kept as separate lists to reduce unnecessary iterations */
83 struct list ActiveLanguageProfileNotifySink;
84 struct list DisplayAttributeNotifySink;
85 struct list KeyTraceEventSink;
86 struct list PreservedKeyNotifySink;
87 struct list ThreadFocusSink;
88 struct list ThreadMgrEventSink;
89 } ThreadMgr;
91 static inline ThreadMgr *impl_from_ITfSourceVtbl(ITfSource *iface)
93 return (ThreadMgr *)((char *)iface - FIELD_OFFSET(ThreadMgr,SourceVtbl));
96 static inline ThreadMgr *impl_from_ITfKeystrokeMgrVtbl(ITfKeystrokeMgr *iface)
98 return (ThreadMgr *)((char *)iface - FIELD_OFFSET(ThreadMgr,KeystrokeMgrVtbl));
101 static inline ThreadMgr *impl_from_ITfMessagePumpVtbl(ITfMessagePump *iface)
103 return (ThreadMgr *)((char *)iface - FIELD_OFFSET(ThreadMgr,MessagePumpVtbl));
106 static inline ThreadMgr *impl_from_ITfClientIdVtbl(ITfClientId *iface)
108 return (ThreadMgr *)((char *)iface - FIELD_OFFSET(ThreadMgr,ClientIdVtbl));
111 static inline ThreadMgr *impl_from_ITfThreadMgrEventSink(ITfThreadMgrEventSink *iface)
113 return (ThreadMgr *)((char *)iface - FIELD_OFFSET(ThreadMgr,ThreadMgrEventSinkVtbl));
116 static void free_sink(ThreadMgrSink *sink)
118 IUnknown_Release(sink->interfaces.pIUnknown);
119 HeapFree(GetProcessHeap(),0,sink);
122 static void ThreadMgr_Destructor(ThreadMgr *This)
124 struct list *cursor, *cursor2;
126 TlsSetValue(tlsIndex,NULL);
127 TRACE("destroying %p\n", This);
128 if (This->focus)
129 ITfDocumentMgr_Release(This->focus);
131 /* free sinks */
132 LIST_FOR_EACH_SAFE(cursor, cursor2, &This->ActiveLanguageProfileNotifySink)
134 ThreadMgrSink* sink = LIST_ENTRY(cursor,ThreadMgrSink,entry);
135 list_remove(cursor);
136 free_sink(sink);
138 LIST_FOR_EACH_SAFE(cursor, cursor2, &This->DisplayAttributeNotifySink)
140 ThreadMgrSink* sink = LIST_ENTRY(cursor,ThreadMgrSink,entry);
141 list_remove(cursor);
142 free_sink(sink);
144 LIST_FOR_EACH_SAFE(cursor, cursor2, &This->KeyTraceEventSink)
146 ThreadMgrSink* sink = LIST_ENTRY(cursor,ThreadMgrSink,entry);
147 list_remove(cursor);
148 free_sink(sink);
150 LIST_FOR_EACH_SAFE(cursor, cursor2, &This->PreservedKeyNotifySink)
152 ThreadMgrSink* sink = LIST_ENTRY(cursor,ThreadMgrSink,entry);
153 list_remove(cursor);
154 free_sink(sink);
156 LIST_FOR_EACH_SAFE(cursor, cursor2, &This->ThreadFocusSink)
158 ThreadMgrSink* sink = LIST_ENTRY(cursor,ThreadMgrSink,entry);
159 list_remove(cursor);
160 free_sink(sink);
162 LIST_FOR_EACH_SAFE(cursor, cursor2, &This->ThreadMgrEventSink)
164 ThreadMgrSink* sink = LIST_ENTRY(cursor,ThreadMgrSink,entry);
165 list_remove(cursor);
166 free_sink(sink);
169 LIST_FOR_EACH_SAFE(cursor, cursor2, &This->CurrentPreservedKeys)
171 PreservedKey* key = LIST_ENTRY(cursor,PreservedKey,entry);
172 list_remove(cursor);
173 HeapFree(GetProcessHeap(),0,key->description);
174 HeapFree(GetProcessHeap(),0,key);
177 HeapFree(GetProcessHeap(),0,This);
180 static HRESULT WINAPI ThreadMgr_QueryInterface(ITfThreadMgr *iface, REFIID iid, LPVOID *ppvOut)
182 ThreadMgr *This = (ThreadMgr *)iface;
183 *ppvOut = NULL;
185 if (IsEqualIID(iid, &IID_IUnknown) || IsEqualIID(iid, &IID_ITfThreadMgr))
187 *ppvOut = This;
189 else if (IsEqualIID(iid, &IID_ITfSource))
191 *ppvOut = &This->SourceVtbl;
193 else if (IsEqualIID(iid, &IID_ITfKeystrokeMgr))
195 *ppvOut = &This->KeystrokeMgrVtbl;
197 else if (IsEqualIID(iid, &IID_ITfMessagePump))
199 *ppvOut = &This->MessagePumpVtbl;
201 else if (IsEqualIID(iid, &IID_ITfClientId))
203 *ppvOut = &This->ClientIdVtbl;
206 if (*ppvOut)
208 IUnknown_AddRef(iface);
209 return S_OK;
212 WARN("unsupported interface: %s\n", debugstr_guid(iid));
213 return E_NOINTERFACE;
216 static ULONG WINAPI ThreadMgr_AddRef(ITfThreadMgr *iface)
218 ThreadMgr *This = (ThreadMgr *)iface;
219 return InterlockedIncrement(&This->refCount);
222 static ULONG WINAPI ThreadMgr_Release(ITfThreadMgr *iface)
224 ThreadMgr *This = (ThreadMgr *)iface;
225 ULONG ret;
227 ret = InterlockedDecrement(&This->refCount);
228 if (ret == 0)
229 ThreadMgr_Destructor(This);
230 return ret;
233 /*****************************************************
234 * ITfThreadMgr functions
235 *****************************************************/
237 static HRESULT WINAPI ThreadMgr_fnActivate( ITfThreadMgr* iface, TfClientId *ptid)
239 ThreadMgr *This = (ThreadMgr *)iface;
240 FIXME("STUB:(%p)\n",This);
241 return E_NOTIMPL;
244 static HRESULT WINAPI ThreadMgr_fnDeactivate( ITfThreadMgr* iface)
246 ThreadMgr *This = (ThreadMgr *)iface;
247 FIXME("STUB:(%p)\n",This);
249 if (This->focus)
251 ITfThreadMgrEventSink_OnSetFocus((ITfThreadMgrEventSink*)&This->ThreadMgrEventSinkVtbl, 0, This->focus);
252 ITfDocumentMgr_Release(This->focus);
253 This->focus = 0;
256 return E_NOTIMPL;
259 static HRESULT WINAPI ThreadMgr_CreateDocumentMgr( ITfThreadMgr* iface, ITfDocumentMgr
260 **ppdim)
262 ThreadMgr *This = (ThreadMgr *)iface;
263 TRACE("(%p)\n",iface);
264 return DocumentMgr_Constructor((ITfThreadMgrEventSink*)&This->ThreadMgrEventSinkVtbl, ppdim);
267 static HRESULT WINAPI ThreadMgr_EnumDocumentMgrs( ITfThreadMgr* iface, IEnumTfDocumentMgrs
268 **ppEnum)
270 ThreadMgr *This = (ThreadMgr *)iface;
271 FIXME("STUB:(%p)\n",This);
272 return E_NOTIMPL;
275 static HRESULT WINAPI ThreadMgr_GetFocus( ITfThreadMgr* iface, ITfDocumentMgr
276 **ppdimFocus)
278 ThreadMgr *This = (ThreadMgr *)iface;
279 TRACE("(%p)\n",This);
281 if (!ppdimFocus)
282 return E_INVALIDARG;
284 *ppdimFocus = This->focus;
286 TRACE("->%p\n",This->focus);
288 if (This->focus == NULL)
289 return S_FALSE;
291 ITfDocumentMgr_AddRef(This->focus);
293 return S_OK;
296 static HRESULT WINAPI ThreadMgr_SetFocus( ITfThreadMgr* iface, ITfDocumentMgr *pdimFocus)
298 ITfDocumentMgr *check;
299 ThreadMgr *This = (ThreadMgr *)iface;
301 TRACE("(%p) %p\n",This,pdimFocus);
303 if (!pdimFocus || FAILED(IUnknown_QueryInterface(pdimFocus,&IID_ITfDocumentMgr,(LPVOID*) &check)))
304 return E_INVALIDARG;
306 ITfThreadMgrEventSink_OnSetFocus((ITfThreadMgrEventSink*)&This->ThreadMgrEventSinkVtbl, check, This->focus);
308 if (This->focus)
309 ITfDocumentMgr_Release(This->focus);
311 This->focus = check;
312 return S_OK;
315 static HRESULT WINAPI ThreadMgr_AssociateFocus( ITfThreadMgr* iface, HWND hwnd,
316 ITfDocumentMgr *pdimNew, ITfDocumentMgr **ppdimPrev)
318 ThreadMgr *This = (ThreadMgr *)iface;
319 FIXME("STUB:(%p)\n",This);
320 return E_NOTIMPL;
323 static HRESULT WINAPI ThreadMgr_IsThreadFocus( ITfThreadMgr* iface, BOOL *pfThreadFocus)
325 ThreadMgr *This = (ThreadMgr *)iface;
326 FIXME("STUB:(%p)\n",This);
327 return E_NOTIMPL;
330 static HRESULT WINAPI ThreadMgr_GetFunctionProvider( ITfThreadMgr* iface, REFCLSID clsid,
331 ITfFunctionProvider **ppFuncProv)
333 ThreadMgr *This = (ThreadMgr *)iface;
334 FIXME("STUB:(%p)\n",This);
335 return E_NOTIMPL;
338 static HRESULT WINAPI ThreadMgr_EnumFunctionProviders( ITfThreadMgr* iface,
339 IEnumTfFunctionProviders **ppEnum)
341 ThreadMgr *This = (ThreadMgr *)iface;
342 FIXME("STUB:(%p)\n",This);
343 return E_NOTIMPL;
346 static HRESULT WINAPI ThreadMgr_GetGlobalCompartment( ITfThreadMgr* iface,
347 ITfCompartmentMgr **ppCompMgr)
349 ThreadMgr *This = (ThreadMgr *)iface;
350 FIXME("STUB:(%p)\n",This);
351 return E_NOTIMPL;
354 static const ITfThreadMgrVtbl ThreadMgr_ThreadMgrVtbl =
356 ThreadMgr_QueryInterface,
357 ThreadMgr_AddRef,
358 ThreadMgr_Release,
360 ThreadMgr_fnActivate,
361 ThreadMgr_fnDeactivate,
362 ThreadMgr_CreateDocumentMgr,
363 ThreadMgr_EnumDocumentMgrs,
364 ThreadMgr_GetFocus,
365 ThreadMgr_SetFocus,
366 ThreadMgr_AssociateFocus,
367 ThreadMgr_IsThreadFocus,
368 ThreadMgr_GetFunctionProvider,
369 ThreadMgr_EnumFunctionProviders,
370 ThreadMgr_GetGlobalCompartment
374 static HRESULT WINAPI Source_QueryInterface(ITfSource *iface, REFIID iid, LPVOID *ppvOut)
376 ThreadMgr *This = impl_from_ITfSourceVtbl(iface);
377 return ThreadMgr_QueryInterface((ITfThreadMgr *)This, iid, *ppvOut);
380 static ULONG WINAPI Source_AddRef(ITfSource *iface)
382 ThreadMgr *This = impl_from_ITfSourceVtbl(iface);
383 return ThreadMgr_AddRef((ITfThreadMgr*)This);
386 static ULONG WINAPI Source_Release(ITfSource *iface)
388 ThreadMgr *This = impl_from_ITfSourceVtbl(iface);
389 return ThreadMgr_Release((ITfThreadMgr *)This);
392 /*****************************************************
393 * ITfSource functions
394 *****************************************************/
395 static WINAPI HRESULT ThreadMgrSource_AdviseSink(ITfSource *iface,
396 REFIID riid, IUnknown *punk, DWORD *pdwCookie)
398 ThreadMgrSink *tms;
399 ThreadMgr *This = impl_from_ITfSourceVtbl(iface);
401 TRACE("(%p) %s %p %p\n",This,debugstr_guid(riid),punk,pdwCookie);
403 if (!riid || !punk || !pdwCookie)
404 return E_INVALIDARG;
406 if (IsEqualIID(riid, &IID_ITfThreadMgrEventSink))
408 tms = HeapAlloc(GetProcessHeap(),0,sizeof(ThreadMgrSink));
409 if (!tms)
410 return E_OUTOFMEMORY;
411 if (!SUCCEEDED(IUnknown_QueryInterface(punk, riid, (LPVOID*)&tms->interfaces.pITfThreadMgrEventSink)))
413 HeapFree(GetProcessHeap(),0,tms);
414 return CONNECT_E_CANNOTCONNECT;
416 list_add_head(&This->ThreadMgrEventSink,&tms->entry);
417 *pdwCookie = generate_Cookie(COOKIE_MAGIC_TMSINK, tms);
419 else
421 FIXME("(%p) Unhandled Sink: %s\n",This,debugstr_guid(riid));
422 return E_NOTIMPL;
425 TRACE("cookie %x\n",*pdwCookie);
427 return S_OK;
430 static WINAPI HRESULT ThreadMgrSource_UnadviseSink(ITfSource *iface, DWORD pdwCookie)
432 ThreadMgrSink *sink;
433 ThreadMgr *This = impl_from_ITfSourceVtbl(iface);
435 TRACE("(%p) %x\n",This,pdwCookie);
437 if (get_Cookie_magic(pdwCookie)!=COOKIE_MAGIC_TMSINK)
438 return E_INVALIDARG;
440 sink = (ThreadMgrSink*)remove_Cookie(pdwCookie);
441 if (!sink)
442 return CONNECT_E_NOCONNECTION;
444 list_remove(&sink->entry);
445 free_sink(sink);
447 return S_OK;
450 static const ITfSourceVtbl ThreadMgr_SourceVtbl =
452 Source_QueryInterface,
453 Source_AddRef,
454 Source_Release,
456 ThreadMgrSource_AdviseSink,
457 ThreadMgrSource_UnadviseSink,
460 /*****************************************************
461 * ITfKeystrokeMgr functions
462 *****************************************************/
464 static HRESULT WINAPI KeystrokeMgr_QueryInterface(ITfKeystrokeMgr *iface, REFIID iid, LPVOID *ppvOut)
466 ThreadMgr *This = impl_from_ITfKeystrokeMgrVtbl(iface);
467 return ThreadMgr_QueryInterface((ITfThreadMgr *)This, iid, *ppvOut);
470 static ULONG WINAPI KeystrokeMgr_AddRef(ITfKeystrokeMgr *iface)
472 ThreadMgr *This = impl_from_ITfKeystrokeMgrVtbl(iface);
473 return ThreadMgr_AddRef((ITfThreadMgr*)This);
476 static ULONG WINAPI KeystrokeMgr_Release(ITfKeystrokeMgr *iface)
478 ThreadMgr *This = impl_from_ITfKeystrokeMgrVtbl(iface);
479 return ThreadMgr_Release((ITfThreadMgr *)This);
482 static HRESULT WINAPI KeystrokeMgr_AdviseKeyEventSink(ITfKeystrokeMgr *iface,
483 TfClientId tid, ITfKeyEventSink *pSink, BOOL fForeground)
485 ThreadMgr *This = impl_from_ITfKeystrokeMgrVtbl(iface);
486 FIXME("STUB:(%p)\n",This);
487 return E_NOTIMPL;
490 static HRESULT WINAPI KeystrokeMgr_UnadviseKeyEventSink(ITfKeystrokeMgr *iface,
491 TfClientId tid)
493 ThreadMgr *This = impl_from_ITfKeystrokeMgrVtbl(iface);
494 FIXME("STUB:(%p)\n",This);
495 return E_NOTIMPL;
498 static HRESULT WINAPI KeystrokeMgr_GetForeground(ITfKeystrokeMgr *iface,
499 CLSID *pclsid)
501 ThreadMgr *This = impl_from_ITfKeystrokeMgrVtbl(iface);
502 FIXME("STUB:(%p)\n",This);
503 return E_NOTIMPL;
506 static HRESULT WINAPI KeystrokeMgr_TestKeyDown(ITfKeystrokeMgr *iface,
507 WPARAM wParam, LPARAM lParam, BOOL *pfEaten)
509 ThreadMgr *This = impl_from_ITfKeystrokeMgrVtbl(iface);
510 FIXME("STUB:(%p)\n",This);
511 return E_NOTIMPL;
514 static HRESULT WINAPI KeystrokeMgr_TestKeyUp(ITfKeystrokeMgr *iface,
515 WPARAM wParam, LPARAM lParam, BOOL *pfEaten)
517 ThreadMgr *This = impl_from_ITfKeystrokeMgrVtbl(iface);
518 FIXME("STUB:(%p)\n",This);
519 return E_NOTIMPL;
522 static HRESULT WINAPI KeystrokeMgr_KeyDown(ITfKeystrokeMgr *iface,
523 WPARAM wParam, LPARAM lParam, BOOL *pfEaten)
525 ThreadMgr *This = impl_from_ITfKeystrokeMgrVtbl(iface);
526 FIXME("STUB:(%p)\n",This);
527 return E_NOTIMPL;
530 static HRESULT WINAPI KeystrokeMgr_KeyUp(ITfKeystrokeMgr *iface,
531 WPARAM wParam, LPARAM lParam, BOOL *pfEaten)
533 ThreadMgr *This = impl_from_ITfKeystrokeMgrVtbl(iface);
534 FIXME("STUB:(%p)\n",This);
535 return E_NOTIMPL;
538 static HRESULT WINAPI KeystrokeMgr_GetPreservedKey(ITfKeystrokeMgr *iface,
539 ITfContext *pic, const TF_PRESERVEDKEY *pprekey, GUID *pguid)
541 ThreadMgr *This = impl_from_ITfKeystrokeMgrVtbl(iface);
542 FIXME("STUB:(%p)\n",This);
543 return E_NOTIMPL;
546 static HRESULT WINAPI KeystrokeMgr_IsPreservedKey(ITfKeystrokeMgr *iface,
547 REFGUID rguid, const TF_PRESERVEDKEY *pprekey, BOOL *pfRegistered)
549 ThreadMgr *This = impl_from_ITfKeystrokeMgrVtbl(iface);
550 FIXME("STUB:(%p)\n",This);
551 return E_NOTIMPL;
554 static HRESULT WINAPI KeystrokeMgr_PreserveKey(ITfKeystrokeMgr *iface,
555 TfClientId tid, REFGUID rguid, const TF_PRESERVEDKEY *prekey,
556 const WCHAR *pchDesc, ULONG cchDesc)
558 ThreadMgr *This = impl_from_ITfKeystrokeMgrVtbl(iface);
559 struct list *cursor;
560 PreservedKey *newkey;
562 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));
564 if (!tid || ! rguid || !prekey || (cchDesc && !pchDesc))
565 return E_INVALIDARG;
567 LIST_FOR_EACH(cursor, &This->CurrentPreservedKeys)
569 PreservedKey* key = LIST_ENTRY(cursor,PreservedKey,entry);
570 if (IsEqualGUID(rguid,&key->guid) && prekey->uVKey == key->prekey.uVKey && prekey->uModifiers == key->prekey.uModifiers)
571 return TF_E_ALREADY_EXISTS;
574 newkey = HeapAlloc(GetProcessHeap(),0,sizeof(PreservedKey));
575 if (!newkey)
576 return E_OUTOFMEMORY;
578 newkey->guid = *rguid;
579 newkey->prekey = *prekey;
580 newkey->tid = tid;
581 if (cchDesc)
583 newkey->description = HeapAlloc(GetProcessHeap(),0,cchDesc * sizeof(WCHAR));
584 if (!newkey->description)
586 HeapFree(GetProcessHeap(),0,newkey);
587 return E_OUTOFMEMORY;
589 memcpy(newkey->description, pchDesc, cchDesc*sizeof(WCHAR));
592 list_add_head(&This->CurrentPreservedKeys,&newkey->entry);
594 return S_OK;
597 static HRESULT WINAPI KeystrokeMgr_UnpreserveKey(ITfKeystrokeMgr *iface,
598 REFGUID rguid, const TF_PRESERVEDKEY *pprekey)
600 ThreadMgr *This = impl_from_ITfKeystrokeMgrVtbl(iface);
601 FIXME("STUB:(%p)\n",This);
602 return E_NOTIMPL;
605 static HRESULT WINAPI KeystrokeMgr_SetPreservedKeyDescription(ITfKeystrokeMgr *iface,
606 REFGUID rguid, const WCHAR *pchDesc, ULONG cchDesc)
608 ThreadMgr *This = impl_from_ITfKeystrokeMgrVtbl(iface);
609 FIXME("STUB:(%p)\n",This);
610 return E_NOTIMPL;
613 static HRESULT WINAPI KeystrokeMgr_GetPreservedKeyDescription(ITfKeystrokeMgr *iface,
614 REFGUID rguid, BSTR *pbstrDesc)
616 ThreadMgr *This = impl_from_ITfKeystrokeMgrVtbl(iface);
617 FIXME("STUB:(%p)\n",This);
618 return E_NOTIMPL;
621 static HRESULT WINAPI KeystrokeMgr_SimulatePreservedKey(ITfKeystrokeMgr *iface,
622 ITfContext *pic, REFGUID rguid, BOOL *pfEaten)
624 ThreadMgr *This = impl_from_ITfKeystrokeMgrVtbl(iface);
625 FIXME("STUB:(%p)\n",This);
626 return E_NOTIMPL;
629 static const ITfKeystrokeMgrVtbl ThreadMgr_KeystrokeMgrVtbl =
631 KeystrokeMgr_QueryInterface,
632 KeystrokeMgr_AddRef,
633 KeystrokeMgr_Release,
635 KeystrokeMgr_AdviseKeyEventSink,
636 KeystrokeMgr_UnadviseKeyEventSink,
637 KeystrokeMgr_GetForeground,
638 KeystrokeMgr_TestKeyDown,
639 KeystrokeMgr_TestKeyUp,
640 KeystrokeMgr_KeyDown,
641 KeystrokeMgr_KeyUp,
642 KeystrokeMgr_GetPreservedKey,
643 KeystrokeMgr_IsPreservedKey,
644 KeystrokeMgr_PreserveKey,
645 KeystrokeMgr_UnpreserveKey,
646 KeystrokeMgr_SetPreservedKeyDescription,
647 KeystrokeMgr_GetPreservedKeyDescription,
648 KeystrokeMgr_SimulatePreservedKey
651 /*****************************************************
652 * ITfMessagePump functions
653 *****************************************************/
655 static HRESULT WINAPI MessagePump_QueryInterface(ITfMessagePump *iface, REFIID iid, LPVOID *ppvOut)
657 ThreadMgr *This = impl_from_ITfMessagePumpVtbl(iface);
658 return ThreadMgr_QueryInterface((ITfThreadMgr *)This, iid, *ppvOut);
661 static ULONG WINAPI MessagePump_AddRef(ITfMessagePump *iface)
663 ThreadMgr *This = impl_from_ITfMessagePumpVtbl(iface);
664 return ThreadMgr_AddRef((ITfThreadMgr*)This);
667 static ULONG WINAPI MessagePump_Release(ITfMessagePump *iface)
669 ThreadMgr *This = impl_from_ITfMessagePumpVtbl(iface);
670 return ThreadMgr_Release((ITfThreadMgr *)This);
673 static HRESULT WINAPI MessagePump_PeekMessageA(ITfMessagePump *iface,
674 LPMSG pMsg, HWND hwnd, UINT wMsgFilterMin, UINT wMsgFilterMax,
675 UINT wRemoveMsg, BOOL *pfResult)
677 if (!pfResult)
678 return E_INVALIDARG;
679 *pfResult = PeekMessageA(pMsg, hwnd, wMsgFilterMin, wMsgFilterMax, wRemoveMsg);
680 return S_OK;
683 static HRESULT WINAPI MessagePump_GetMessageA(ITfMessagePump *iface,
684 LPMSG pMsg, HWND hwnd, UINT wMsgFilterMin, UINT wMsgFilterMax,
685 BOOL *pfResult)
687 if (!pfResult)
688 return E_INVALIDARG;
689 *pfResult = GetMessageA(pMsg, hwnd, wMsgFilterMin, wMsgFilterMax);
690 return S_OK;
693 static HRESULT WINAPI MessagePump_PeekMessageW(ITfMessagePump *iface,
694 LPMSG pMsg, HWND hwnd, UINT wMsgFilterMin, UINT wMsgFilterMax,
695 UINT wRemoveMsg, BOOL *pfResult)
697 if (!pfResult)
698 return E_INVALIDARG;
699 *pfResult = PeekMessageW(pMsg, hwnd, wMsgFilterMin, wMsgFilterMax, wRemoveMsg);
700 return S_OK;
703 static HRESULT WINAPI MessagePump_GetMessageW(ITfMessagePump *iface,
704 LPMSG pMsg, HWND hwnd, UINT wMsgFilterMin, UINT wMsgFilterMax,
705 BOOL *pfResult)
707 if (!pfResult)
708 return E_INVALIDARG;
709 *pfResult = GetMessageW(pMsg, hwnd, wMsgFilterMin, wMsgFilterMax);
710 return S_OK;
713 static const ITfMessagePumpVtbl ThreadMgr_MessagePumpVtbl =
715 MessagePump_QueryInterface,
716 MessagePump_AddRef,
717 MessagePump_Release,
719 MessagePump_PeekMessageA,
720 MessagePump_GetMessageA,
721 MessagePump_PeekMessageW,
722 MessagePump_GetMessageW
725 /*****************************************************
726 * ITfClientId functions
727 *****************************************************/
729 static HRESULT WINAPI ClientId_QueryInterface(ITfClientId *iface, REFIID iid, LPVOID *ppvOut)
731 ThreadMgr *This = impl_from_ITfClientIdVtbl(iface);
732 return ThreadMgr_QueryInterface((ITfThreadMgr *)This, iid, *ppvOut);
735 static ULONG WINAPI ClientId_AddRef(ITfClientId *iface)
737 ThreadMgr *This = impl_from_ITfClientIdVtbl(iface);
738 return ThreadMgr_AddRef((ITfThreadMgr*)This);
741 static ULONG WINAPI ClientId_Release(ITfClientId *iface)
743 ThreadMgr *This = impl_from_ITfClientIdVtbl(iface);
744 return ThreadMgr_Release((ITfThreadMgr *)This);
747 static HRESULT WINAPI ClientId_GetClientId(ITfClientId *iface,
748 REFCLSID rclsid, TfClientId *ptid)
751 HRESULT hr;
752 ITfCategoryMgr *catmgr;
753 ThreadMgr *This = impl_from_ITfClientIdVtbl(iface);
755 TRACE("(%p) %s\n",This,debugstr_guid(rclsid));
757 CategoryMgr_Constructor(NULL,(IUnknown**)&catmgr);
758 hr = ITfCategoryMgr_RegisterGUID(catmgr,rclsid,ptid);
759 ITfCategoryMgr_Release(catmgr);
761 return hr;
764 static const ITfClientIdVtbl ThreadMgr_ClientIdVtbl =
766 ClientId_QueryInterface,
767 ClientId_AddRef,
768 ClientId_Release,
770 ClientId_GetClientId
773 /*****************************************************
774 * ITfThreadMgrEventSink functions (internal)
775 *****************************************************/
776 static HRESULT WINAPI ThreadMgrEventSink_QueryInterface(ITfThreadMgrEventSink *iface, REFIID iid, LPVOID *ppvOut)
778 ThreadMgr *This = impl_from_ITfThreadMgrEventSink(iface);
779 return ThreadMgr_QueryInterface((ITfThreadMgr *)This, iid, *ppvOut);
782 static ULONG WINAPI ThreadMgrEventSink_AddRef(ITfThreadMgrEventSink *iface)
784 ThreadMgr *This = impl_from_ITfThreadMgrEventSink(iface);
785 return ThreadMgr_AddRef((ITfThreadMgr*)This);
788 static ULONG WINAPI ThreadMgrEventSink_Release(ITfThreadMgrEventSink *iface)
790 ThreadMgr *This = impl_from_ITfThreadMgrEventSink(iface);
791 return ThreadMgr_Release((ITfThreadMgr *)This);
795 static WINAPI HRESULT ThreadMgrEventSink_OnInitDocumentMgr(
796 ITfThreadMgrEventSink *iface,ITfDocumentMgr *pdim)
798 struct list *cursor;
799 ThreadMgr *This = impl_from_ITfThreadMgrEventSink(iface);
801 TRACE("(%p) %p\n",This,pdim);
803 LIST_FOR_EACH(cursor, &This->ThreadMgrEventSink)
805 ThreadMgrSink* sink = LIST_ENTRY(cursor,ThreadMgrSink,entry);
806 ITfThreadMgrEventSink_OnInitDocumentMgr(sink->interfaces.pITfThreadMgrEventSink,pdim);
809 return S_OK;
812 static WINAPI HRESULT ThreadMgrEventSink_OnUninitDocumentMgr(
813 ITfThreadMgrEventSink *iface, ITfDocumentMgr *pdim)
815 struct list *cursor;
816 ThreadMgr *This = impl_from_ITfThreadMgrEventSink(iface);
818 TRACE("(%p) %p\n",This,pdim);
820 LIST_FOR_EACH(cursor, &This->ThreadMgrEventSink)
822 ThreadMgrSink* sink = LIST_ENTRY(cursor,ThreadMgrSink,entry);
823 ITfThreadMgrEventSink_OnUninitDocumentMgr(sink->interfaces.pITfThreadMgrEventSink,pdim);
826 return S_OK;
829 static WINAPI HRESULT ThreadMgrEventSink_OnSetFocus(
830 ITfThreadMgrEventSink *iface, ITfDocumentMgr *pdimFocus,
831 ITfDocumentMgr *pdimPrevFocus)
833 struct list *cursor;
834 ThreadMgr *This = impl_from_ITfThreadMgrEventSink(iface);
836 TRACE("(%p) %p %p\n",This,pdimFocus, pdimPrevFocus);
838 LIST_FOR_EACH(cursor, &This->ThreadMgrEventSink)
840 ThreadMgrSink* sink = LIST_ENTRY(cursor,ThreadMgrSink,entry);
841 ITfThreadMgrEventSink_OnSetFocus(sink->interfaces.pITfThreadMgrEventSink, pdimFocus, pdimPrevFocus);
844 return S_OK;
847 static WINAPI HRESULT ThreadMgrEventSink_OnPushContext(
848 ITfThreadMgrEventSink *iface, ITfContext *pic)
850 struct list *cursor;
851 ThreadMgr *This = impl_from_ITfThreadMgrEventSink(iface);
853 TRACE("(%p) %p\n",This,pic);
855 LIST_FOR_EACH(cursor, &This->ThreadMgrEventSink)
857 ThreadMgrSink* sink = LIST_ENTRY(cursor,ThreadMgrSink,entry);
858 ITfThreadMgrEventSink_OnPushContext(sink->interfaces.pITfThreadMgrEventSink,pic);
861 return S_OK;
864 static WINAPI HRESULT ThreadMgrEventSink_OnPopContext(
865 ITfThreadMgrEventSink *iface, ITfContext *pic)
867 struct list *cursor;
868 ThreadMgr *This = impl_from_ITfThreadMgrEventSink(iface);
870 TRACE("(%p) %p\n",This,pic);
872 LIST_FOR_EACH(cursor, &This->ThreadMgrEventSink)
874 ThreadMgrSink* sink = LIST_ENTRY(cursor,ThreadMgrSink,entry);
875 ITfThreadMgrEventSink_OnPopContext(sink->interfaces.pITfThreadMgrEventSink,pic);
878 return S_OK;
881 static const ITfThreadMgrEventSinkVtbl ThreadMgr_ThreadMgrEventSinkVtbl =
883 ThreadMgrEventSink_QueryInterface,
884 ThreadMgrEventSink_AddRef,
885 ThreadMgrEventSink_Release,
887 ThreadMgrEventSink_OnInitDocumentMgr,
888 ThreadMgrEventSink_OnUninitDocumentMgr,
889 ThreadMgrEventSink_OnSetFocus,
890 ThreadMgrEventSink_OnPushContext,
891 ThreadMgrEventSink_OnPopContext
894 HRESULT ThreadMgr_Constructor(IUnknown *pUnkOuter, IUnknown **ppOut)
896 ThreadMgr *This;
897 if (pUnkOuter)
898 return CLASS_E_NOAGGREGATION;
900 /* Only 1 ThreadMgr is created per thread */
901 This = TlsGetValue(tlsIndex);
902 if (This)
904 ThreadMgr_AddRef((ITfThreadMgr*)This);
905 *ppOut = (IUnknown*)This;
906 return S_OK;
909 This = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(ThreadMgr));
910 if (This == NULL)
911 return E_OUTOFMEMORY;
913 This->ThreadMgrVtbl= &ThreadMgr_ThreadMgrVtbl;
914 This->SourceVtbl = &ThreadMgr_SourceVtbl;
915 This->KeystrokeMgrVtbl= &ThreadMgr_KeystrokeMgrVtbl;
916 This->MessagePumpVtbl= &ThreadMgr_MessagePumpVtbl;
917 This->ClientIdVtbl = &ThreadMgr_ClientIdVtbl;
918 This->ThreadMgrEventSinkVtbl = &ThreadMgr_ThreadMgrEventSinkVtbl;
919 This->refCount = 1;
920 TlsSetValue(tlsIndex,This);
922 list_init(&This->CurrentPreservedKeys);
924 list_init(&This->ActiveLanguageProfileNotifySink);
925 list_init(&This->DisplayAttributeNotifySink);
926 list_init(&This->KeyTraceEventSink);
927 list_init(&This->PreservedKeyNotifySink);
928 list_init(&This->ThreadFocusSink);
929 list_init(&This->ThreadMgrEventSink);
931 TRACE("returning %p\n", This);
932 *ppOut = (IUnknown *)This;
933 return S_OK;