push 52cba0a224aad01bcbdb26d79e43229ba950650e
[wine/hacks.git] / dlls / msctf / threadmgr.c
blobc91e5361072b09b46994a33edf07f61686c867b9
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 /* const ITfThreadMgrExVtbl *ThreadMgrExVtbl; */
75 /* const ITfConfigureSystemKeystrokeFeedVtbl *ConfigureSystemKeystrokeFeedVtbl; */
76 /* const ITfLangBarItemMgrVtbl *LangBarItemMgrVtbl; */
77 /* const ITfUIElementMgrVtbl *UIElementMgrVtbl; */
78 /* const ITfSourceSingleVtbl *SourceSingleVtbl; */
79 LONG refCount;
81 const ITfThreadMgrEventSinkVtbl *ThreadMgrEventSinkVtbl; /* internal */
83 ITfDocumentMgr *focus;
84 LONG activationCount;
86 ITfKeyEventSink *forgroundKeyEventSink;
87 CLSID forgroundTextService;
89 struct list CurrentPreservedKeys;
91 /* kept as separate lists to reduce unnecessary iterations */
92 struct list ActiveLanguageProfileNotifySink;
93 struct list DisplayAttributeNotifySink;
94 struct list KeyTraceEventSink;
95 struct list PreservedKeyNotifySink;
96 struct list ThreadFocusSink;
97 struct list ThreadMgrEventSink;
98 } ThreadMgr;
100 static inline ThreadMgr *impl_from_ITfSourceVtbl(ITfSource *iface)
102 return (ThreadMgr *)((char *)iface - FIELD_OFFSET(ThreadMgr,SourceVtbl));
105 static inline ThreadMgr *impl_from_ITfKeystrokeMgrVtbl(ITfKeystrokeMgr *iface)
107 return (ThreadMgr *)((char *)iface - FIELD_OFFSET(ThreadMgr,KeystrokeMgrVtbl));
110 static inline ThreadMgr *impl_from_ITfMessagePumpVtbl(ITfMessagePump *iface)
112 return (ThreadMgr *)((char *)iface - FIELD_OFFSET(ThreadMgr,MessagePumpVtbl));
115 static inline ThreadMgr *impl_from_ITfClientIdVtbl(ITfClientId *iface)
117 return (ThreadMgr *)((char *)iface - FIELD_OFFSET(ThreadMgr,ClientIdVtbl));
120 static inline ThreadMgr *impl_from_ITfThreadMgrEventSink(ITfThreadMgrEventSink *iface)
122 return (ThreadMgr *)((char *)iface - FIELD_OFFSET(ThreadMgr,ThreadMgrEventSinkVtbl));
125 static void free_sink(ThreadMgrSink *sink)
127 IUnknown_Release(sink->interfaces.pIUnknown);
128 HeapFree(GetProcessHeap(),0,sink);
131 static void ThreadMgr_Destructor(ThreadMgr *This)
133 struct list *cursor, *cursor2;
135 TlsSetValue(tlsIndex,NULL);
136 TRACE("destroying %p\n", This);
137 if (This->focus)
138 ITfDocumentMgr_Release(This->focus);
140 /* free sinks */
141 LIST_FOR_EACH_SAFE(cursor, cursor2, &This->ActiveLanguageProfileNotifySink)
143 ThreadMgrSink* sink = LIST_ENTRY(cursor,ThreadMgrSink,entry);
144 list_remove(cursor);
145 free_sink(sink);
147 LIST_FOR_EACH_SAFE(cursor, cursor2, &This->DisplayAttributeNotifySink)
149 ThreadMgrSink* sink = LIST_ENTRY(cursor,ThreadMgrSink,entry);
150 list_remove(cursor);
151 free_sink(sink);
153 LIST_FOR_EACH_SAFE(cursor, cursor2, &This->KeyTraceEventSink)
155 ThreadMgrSink* sink = LIST_ENTRY(cursor,ThreadMgrSink,entry);
156 list_remove(cursor);
157 free_sink(sink);
159 LIST_FOR_EACH_SAFE(cursor, cursor2, &This->PreservedKeyNotifySink)
161 ThreadMgrSink* sink = LIST_ENTRY(cursor,ThreadMgrSink,entry);
162 list_remove(cursor);
163 free_sink(sink);
165 LIST_FOR_EACH_SAFE(cursor, cursor2, &This->ThreadFocusSink)
167 ThreadMgrSink* sink = LIST_ENTRY(cursor,ThreadMgrSink,entry);
168 list_remove(cursor);
169 free_sink(sink);
171 LIST_FOR_EACH_SAFE(cursor, cursor2, &This->ThreadMgrEventSink)
173 ThreadMgrSink* sink = LIST_ENTRY(cursor,ThreadMgrSink,entry);
174 list_remove(cursor);
175 free_sink(sink);
178 LIST_FOR_EACH_SAFE(cursor, cursor2, &This->CurrentPreservedKeys)
180 PreservedKey* key = LIST_ENTRY(cursor,PreservedKey,entry);
181 list_remove(cursor);
182 HeapFree(GetProcessHeap(),0,key->description);
183 HeapFree(GetProcessHeap(),0,key);
186 HeapFree(GetProcessHeap(),0,This);
189 static HRESULT WINAPI ThreadMgr_QueryInterface(ITfThreadMgr *iface, REFIID iid, LPVOID *ppvOut)
191 ThreadMgr *This = (ThreadMgr *)iface;
192 *ppvOut = NULL;
194 if (IsEqualIID(iid, &IID_IUnknown) || IsEqualIID(iid, &IID_ITfThreadMgr))
196 *ppvOut = This;
198 else if (IsEqualIID(iid, &IID_ITfSource))
200 *ppvOut = &This->SourceVtbl;
202 else if (IsEqualIID(iid, &IID_ITfKeystrokeMgr))
204 *ppvOut = &This->KeystrokeMgrVtbl;
206 else if (IsEqualIID(iid, &IID_ITfMessagePump))
208 *ppvOut = &This->MessagePumpVtbl;
210 else if (IsEqualIID(iid, &IID_ITfClientId))
212 *ppvOut = &This->ClientIdVtbl;
215 if (*ppvOut)
217 IUnknown_AddRef(iface);
218 return S_OK;
221 WARN("unsupported interface: %s\n", debugstr_guid(iid));
222 return E_NOINTERFACE;
225 static ULONG WINAPI ThreadMgr_AddRef(ITfThreadMgr *iface)
227 ThreadMgr *This = (ThreadMgr *)iface;
228 return InterlockedIncrement(&This->refCount);
231 static ULONG WINAPI ThreadMgr_Release(ITfThreadMgr *iface)
233 ThreadMgr *This = (ThreadMgr *)iface;
234 ULONG ret;
236 ret = InterlockedDecrement(&This->refCount);
237 if (ret == 0)
238 ThreadMgr_Destructor(This);
239 return ret;
242 /*****************************************************
243 * ITfThreadMgr functions
244 *****************************************************/
246 static HRESULT WINAPI ThreadMgr_fnActivate( ITfThreadMgr* iface, TfClientId *ptid)
248 ThreadMgr *This = (ThreadMgr *)iface;
250 TRACE("(%p) %p\n",This, ptid);
252 if (!ptid)
253 return E_INVALIDARG;
255 if (!processId)
257 GUID guid;
258 CoCreateGuid(&guid);
259 ITfClientId_GetClientId((ITfClientId*)&This->ClientIdVtbl,&guid,&processId);
262 activate_textservices(iface);
263 This->activationCount++;
264 *ptid = processId;
265 return S_OK;
268 static HRESULT WINAPI ThreadMgr_fnDeactivate( ITfThreadMgr* iface)
270 ThreadMgr *This = (ThreadMgr *)iface;
271 TRACE("(%p)\n",This);
273 if (This->activationCount == 0)
274 return E_UNEXPECTED;
276 This->activationCount --;
278 if (This->activationCount == 0)
280 if (This->focus)
282 ITfThreadMgrEventSink_OnSetFocus((ITfThreadMgrEventSink*)&This->ThreadMgrEventSinkVtbl, 0, This->focus);
283 ITfDocumentMgr_Release(This->focus);
284 This->focus = 0;
288 deactivate_textservices();
290 return S_OK;
293 static HRESULT WINAPI ThreadMgr_CreateDocumentMgr( ITfThreadMgr* iface, ITfDocumentMgr
294 **ppdim)
296 ThreadMgr *This = (ThreadMgr *)iface;
297 TRACE("(%p)\n",iface);
298 return DocumentMgr_Constructor((ITfThreadMgrEventSink*)&This->ThreadMgrEventSinkVtbl, ppdim);
301 static HRESULT WINAPI ThreadMgr_EnumDocumentMgrs( ITfThreadMgr* iface, IEnumTfDocumentMgrs
302 **ppEnum)
304 ThreadMgr *This = (ThreadMgr *)iface;
305 FIXME("STUB:(%p)\n",This);
306 return E_NOTIMPL;
309 static HRESULT WINAPI ThreadMgr_GetFocus( ITfThreadMgr* iface, ITfDocumentMgr
310 **ppdimFocus)
312 ThreadMgr *This = (ThreadMgr *)iface;
313 TRACE("(%p)\n",This);
315 if (!ppdimFocus)
316 return E_INVALIDARG;
318 *ppdimFocus = This->focus;
320 TRACE("->%p\n",This->focus);
322 if (This->focus == NULL)
323 return S_FALSE;
325 ITfDocumentMgr_AddRef(This->focus);
327 return S_OK;
330 static HRESULT WINAPI ThreadMgr_SetFocus( ITfThreadMgr* iface, ITfDocumentMgr *pdimFocus)
332 ITfDocumentMgr *check;
333 ThreadMgr *This = (ThreadMgr *)iface;
335 TRACE("(%p) %p\n",This,pdimFocus);
337 if (!pdimFocus || FAILED(IUnknown_QueryInterface(pdimFocus,&IID_ITfDocumentMgr,(LPVOID*) &check)))
338 return E_INVALIDARG;
340 ITfThreadMgrEventSink_OnSetFocus((ITfThreadMgrEventSink*)&This->ThreadMgrEventSinkVtbl, check, This->focus);
342 if (This->focus)
343 ITfDocumentMgr_Release(This->focus);
345 This->focus = check;
346 return S_OK;
349 static HRESULT WINAPI ThreadMgr_AssociateFocus( ITfThreadMgr* iface, HWND hwnd,
350 ITfDocumentMgr *pdimNew, ITfDocumentMgr **ppdimPrev)
352 ThreadMgr *This = (ThreadMgr *)iface;
353 FIXME("STUB:(%p)\n",This);
354 return E_NOTIMPL;
357 static HRESULT WINAPI ThreadMgr_IsThreadFocus( ITfThreadMgr* iface, BOOL *pfThreadFocus)
359 ThreadMgr *This = (ThreadMgr *)iface;
360 FIXME("STUB:(%p)\n",This);
361 return E_NOTIMPL;
364 static HRESULT WINAPI ThreadMgr_GetFunctionProvider( ITfThreadMgr* iface, REFCLSID clsid,
365 ITfFunctionProvider **ppFuncProv)
367 ThreadMgr *This = (ThreadMgr *)iface;
368 FIXME("STUB:(%p)\n",This);
369 return E_NOTIMPL;
372 static HRESULT WINAPI ThreadMgr_EnumFunctionProviders( ITfThreadMgr* iface,
373 IEnumTfFunctionProviders **ppEnum)
375 ThreadMgr *This = (ThreadMgr *)iface;
376 FIXME("STUB:(%p)\n",This);
377 return E_NOTIMPL;
380 static HRESULT WINAPI ThreadMgr_GetGlobalCompartment( ITfThreadMgr* iface,
381 ITfCompartmentMgr **ppCompMgr)
383 ThreadMgr *This = (ThreadMgr *)iface;
384 FIXME("STUB:(%p)\n",This);
385 return E_NOTIMPL;
388 static const ITfThreadMgrVtbl ThreadMgr_ThreadMgrVtbl =
390 ThreadMgr_QueryInterface,
391 ThreadMgr_AddRef,
392 ThreadMgr_Release,
394 ThreadMgr_fnActivate,
395 ThreadMgr_fnDeactivate,
396 ThreadMgr_CreateDocumentMgr,
397 ThreadMgr_EnumDocumentMgrs,
398 ThreadMgr_GetFocus,
399 ThreadMgr_SetFocus,
400 ThreadMgr_AssociateFocus,
401 ThreadMgr_IsThreadFocus,
402 ThreadMgr_GetFunctionProvider,
403 ThreadMgr_EnumFunctionProviders,
404 ThreadMgr_GetGlobalCompartment
408 static HRESULT WINAPI Source_QueryInterface(ITfSource *iface, REFIID iid, LPVOID *ppvOut)
410 ThreadMgr *This = impl_from_ITfSourceVtbl(iface);
411 return ThreadMgr_QueryInterface((ITfThreadMgr *)This, iid, *ppvOut);
414 static ULONG WINAPI Source_AddRef(ITfSource *iface)
416 ThreadMgr *This = impl_from_ITfSourceVtbl(iface);
417 return ThreadMgr_AddRef((ITfThreadMgr*)This);
420 static ULONG WINAPI Source_Release(ITfSource *iface)
422 ThreadMgr *This = impl_from_ITfSourceVtbl(iface);
423 return ThreadMgr_Release((ITfThreadMgr *)This);
426 /*****************************************************
427 * ITfSource functions
428 *****************************************************/
429 static WINAPI HRESULT ThreadMgrSource_AdviseSink(ITfSource *iface,
430 REFIID riid, IUnknown *punk, DWORD *pdwCookie)
432 ThreadMgrSink *tms;
433 ThreadMgr *This = impl_from_ITfSourceVtbl(iface);
435 TRACE("(%p) %s %p %p\n",This,debugstr_guid(riid),punk,pdwCookie);
437 if (!riid || !punk || !pdwCookie)
438 return E_INVALIDARG;
440 if (IsEqualIID(riid, &IID_ITfThreadMgrEventSink))
442 tms = HeapAlloc(GetProcessHeap(),0,sizeof(ThreadMgrSink));
443 if (!tms)
444 return E_OUTOFMEMORY;
445 if (!SUCCEEDED(IUnknown_QueryInterface(punk, riid, (LPVOID*)&tms->interfaces.pITfThreadMgrEventSink)))
447 HeapFree(GetProcessHeap(),0,tms);
448 return CONNECT_E_CANNOTCONNECT;
450 list_add_head(&This->ThreadMgrEventSink,&tms->entry);
451 *pdwCookie = generate_Cookie(COOKIE_MAGIC_TMSINK, tms);
453 else
455 FIXME("(%p) Unhandled Sink: %s\n",This,debugstr_guid(riid));
456 return E_NOTIMPL;
459 TRACE("cookie %x\n",*pdwCookie);
461 return S_OK;
464 static WINAPI HRESULT ThreadMgrSource_UnadviseSink(ITfSource *iface, DWORD pdwCookie)
466 ThreadMgrSink *sink;
467 ThreadMgr *This = impl_from_ITfSourceVtbl(iface);
469 TRACE("(%p) %x\n",This,pdwCookie);
471 if (get_Cookie_magic(pdwCookie)!=COOKIE_MAGIC_TMSINK)
472 return E_INVALIDARG;
474 sink = (ThreadMgrSink*)remove_Cookie(pdwCookie);
475 if (!sink)
476 return CONNECT_E_NOCONNECTION;
478 list_remove(&sink->entry);
479 free_sink(sink);
481 return S_OK;
484 static const ITfSourceVtbl ThreadMgr_SourceVtbl =
486 Source_QueryInterface,
487 Source_AddRef,
488 Source_Release,
490 ThreadMgrSource_AdviseSink,
491 ThreadMgrSource_UnadviseSink,
494 /*****************************************************
495 * ITfKeystrokeMgr functions
496 *****************************************************/
498 static HRESULT WINAPI KeystrokeMgr_QueryInterface(ITfKeystrokeMgr *iface, REFIID iid, LPVOID *ppvOut)
500 ThreadMgr *This = impl_from_ITfKeystrokeMgrVtbl(iface);
501 return ThreadMgr_QueryInterface((ITfThreadMgr *)This, iid, *ppvOut);
504 static ULONG WINAPI KeystrokeMgr_AddRef(ITfKeystrokeMgr *iface)
506 ThreadMgr *This = impl_from_ITfKeystrokeMgrVtbl(iface);
507 return ThreadMgr_AddRef((ITfThreadMgr*)This);
510 static ULONG WINAPI KeystrokeMgr_Release(ITfKeystrokeMgr *iface)
512 ThreadMgr *This = impl_from_ITfKeystrokeMgrVtbl(iface);
513 return ThreadMgr_Release((ITfThreadMgr *)This);
516 static HRESULT WINAPI KeystrokeMgr_AdviseKeyEventSink(ITfKeystrokeMgr *iface,
517 TfClientId tid, ITfKeyEventSink *pSink, BOOL fForeground)
519 ThreadMgr *This = impl_from_ITfKeystrokeMgrVtbl(iface);
520 CLSID textservice;
521 ITfKeyEventSink *check = NULL;
523 TRACE("(%p) %x %p %i\n",This,tid,pSink,fForeground);
525 if (!tid || !pSink)
526 return E_INVALIDARG;
528 textservice = get_textservice_clsid(tid);
529 if (IsEqualCLSID(&GUID_NULL,&textservice))
530 return E_INVALIDARG;
532 get_textservice_sink(tid, &IID_ITfKeyEventSink, (IUnknown**)&check);
533 if (check != NULL)
534 return CONNECT_E_ADVISELIMIT;
536 if (FAILED(IUnknown_QueryInterface(pSink,&IID_ITfKeyEventSink,(LPVOID*) &check)))
537 return E_INVALIDARG;
539 set_textservice_sink(tid, &IID_ITfKeyEventSink, (IUnknown*)check);
541 if (fForeground)
543 if (This->forgroundKeyEventSink)
545 ITfKeyEventSink_OnSetFocus(This->forgroundKeyEventSink, FALSE);
546 ITfKeyEventSink_Release(This->forgroundKeyEventSink);
548 ITfKeyEventSink_AddRef(check);
549 ITfKeyEventSink_OnSetFocus(check, TRUE);
550 This->forgroundKeyEventSink = check;
551 This->forgroundTextService = textservice;
553 return S_OK;
556 static HRESULT WINAPI KeystrokeMgr_UnadviseKeyEventSink(ITfKeystrokeMgr *iface,
557 TfClientId tid)
559 ThreadMgr *This = impl_from_ITfKeystrokeMgrVtbl(iface);
560 CLSID textservice;
561 ITfKeyEventSink *check = NULL;
562 TRACE("(%p) %x\n",This,tid);
564 if (!tid)
565 return E_INVALIDARG;
567 textservice = get_textservice_clsid(tid);
568 if (IsEqualCLSID(&GUID_NULL,&textservice))
569 return E_INVALIDARG;
571 get_textservice_sink(tid, &IID_ITfKeyEventSink, (IUnknown**)&check);
573 if (!check)
574 return CONNECT_E_NOCONNECTION;
576 set_textservice_sink(tid, &IID_ITfKeyEventSink, NULL);
577 ITfKeyEventSink_Release(check);
579 if (This->forgroundKeyEventSink == check)
581 ITfKeyEventSink_Release(This->forgroundKeyEventSink);
582 This->forgroundKeyEventSink = NULL;
583 This->forgroundTextService = GUID_NULL;
585 return S_OK;
588 static HRESULT WINAPI KeystrokeMgr_GetForeground(ITfKeystrokeMgr *iface,
589 CLSID *pclsid)
591 ThreadMgr *This = impl_from_ITfKeystrokeMgrVtbl(iface);
592 TRACE("(%p) %p\n",This,pclsid);
593 if (!pclsid)
594 return E_INVALIDARG;
596 if (IsEqualCLSID(&This->forgroundTextService,&GUID_NULL))
597 return S_FALSE;
599 *pclsid = This->forgroundTextService;
600 return S_OK;
603 static HRESULT WINAPI KeystrokeMgr_TestKeyDown(ITfKeystrokeMgr *iface,
604 WPARAM wParam, LPARAM lParam, BOOL *pfEaten)
606 ThreadMgr *This = impl_from_ITfKeystrokeMgrVtbl(iface);
607 FIXME("STUB:(%p)\n",This);
608 return E_NOTIMPL;
611 static HRESULT WINAPI KeystrokeMgr_TestKeyUp(ITfKeystrokeMgr *iface,
612 WPARAM wParam, LPARAM lParam, BOOL *pfEaten)
614 ThreadMgr *This = impl_from_ITfKeystrokeMgrVtbl(iface);
615 FIXME("STUB:(%p)\n",This);
616 return E_NOTIMPL;
619 static HRESULT WINAPI KeystrokeMgr_KeyDown(ITfKeystrokeMgr *iface,
620 WPARAM wParam, LPARAM lParam, BOOL *pfEaten)
622 ThreadMgr *This = impl_from_ITfKeystrokeMgrVtbl(iface);
623 FIXME("STUB:(%p)\n",This);
624 return E_NOTIMPL;
627 static HRESULT WINAPI KeystrokeMgr_KeyUp(ITfKeystrokeMgr *iface,
628 WPARAM wParam, LPARAM lParam, BOOL *pfEaten)
630 ThreadMgr *This = impl_from_ITfKeystrokeMgrVtbl(iface);
631 FIXME("STUB:(%p)\n",This);
632 return E_NOTIMPL;
635 static HRESULT WINAPI KeystrokeMgr_GetPreservedKey(ITfKeystrokeMgr *iface,
636 ITfContext *pic, const TF_PRESERVEDKEY *pprekey, GUID *pguid)
638 ThreadMgr *This = impl_from_ITfKeystrokeMgrVtbl(iface);
639 FIXME("STUB:(%p)\n",This);
640 return E_NOTIMPL;
643 static HRESULT WINAPI KeystrokeMgr_IsPreservedKey(ITfKeystrokeMgr *iface,
644 REFGUID rguid, const TF_PRESERVEDKEY *pprekey, BOOL *pfRegistered)
646 ThreadMgr *This = impl_from_ITfKeystrokeMgrVtbl(iface);
647 struct list *cursor;
649 TRACE("(%p) %s (%x %x) %p\n",This,debugstr_guid(rguid), (pprekey)?pprekey->uVKey:0, (pprekey)?pprekey->uModifiers:0, pfRegistered);
651 if (!rguid || !pprekey || !pfRegistered)
652 return E_INVALIDARG;
654 LIST_FOR_EACH(cursor, &This->CurrentPreservedKeys)
656 PreservedKey* key = LIST_ENTRY(cursor,PreservedKey,entry);
657 if (IsEqualGUID(rguid,&key->guid) && pprekey->uVKey == key->prekey.uVKey && pprekey->uModifiers == key->prekey.uModifiers)
659 *pfRegistered = TRUE;
660 return S_OK;
664 *pfRegistered = FALSE;
665 return S_FALSE;
668 static HRESULT WINAPI KeystrokeMgr_PreserveKey(ITfKeystrokeMgr *iface,
669 TfClientId tid, REFGUID rguid, const TF_PRESERVEDKEY *prekey,
670 const WCHAR *pchDesc, ULONG cchDesc)
672 ThreadMgr *This = impl_from_ITfKeystrokeMgrVtbl(iface);
673 struct list *cursor;
674 PreservedKey *newkey;
676 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));
678 if (!tid || ! rguid || !prekey || (cchDesc && !pchDesc))
679 return E_INVALIDARG;
681 LIST_FOR_EACH(cursor, &This->CurrentPreservedKeys)
683 PreservedKey* key = LIST_ENTRY(cursor,PreservedKey,entry);
684 if (IsEqualGUID(rguid,&key->guid) && prekey->uVKey == key->prekey.uVKey && prekey->uModifiers == key->prekey.uModifiers)
685 return TF_E_ALREADY_EXISTS;
688 newkey = HeapAlloc(GetProcessHeap(),0,sizeof(PreservedKey));
689 if (!newkey)
690 return E_OUTOFMEMORY;
692 newkey->guid = *rguid;
693 newkey->prekey = *prekey;
694 newkey->tid = tid;
695 if (cchDesc)
697 newkey->description = HeapAlloc(GetProcessHeap(),0,cchDesc * sizeof(WCHAR));
698 if (!newkey->description)
700 HeapFree(GetProcessHeap(),0,newkey);
701 return E_OUTOFMEMORY;
703 memcpy(newkey->description, pchDesc, cchDesc*sizeof(WCHAR));
706 list_add_head(&This->CurrentPreservedKeys,&newkey->entry);
708 return S_OK;
711 static HRESULT WINAPI KeystrokeMgr_UnpreserveKey(ITfKeystrokeMgr *iface,
712 REFGUID rguid, const TF_PRESERVEDKEY *pprekey)
714 ThreadMgr *This = impl_from_ITfKeystrokeMgrVtbl(iface);
715 PreservedKey* key = NULL;
716 struct list *cursor;
717 TRACE("(%p) %s (%x %x)\n",This,debugstr_guid(rguid),(pprekey)?pprekey->uVKey:0, (pprekey)?pprekey->uModifiers:0);
719 if (!pprekey || !rguid)
720 return E_INVALIDARG;
722 LIST_FOR_EACH(cursor, &This->CurrentPreservedKeys)
724 key = LIST_ENTRY(cursor,PreservedKey,entry);
725 if (IsEqualGUID(rguid,&key->guid) && pprekey->uVKey == key->prekey.uVKey && pprekey->uModifiers == key->prekey.uModifiers)
726 break;
727 key = NULL;
730 if (!key)
731 return CONNECT_E_NOCONNECTION;
733 list_remove(&key->entry);
734 HeapFree(GetProcessHeap(),0,key->description);
735 HeapFree(GetProcessHeap(),0,key);
737 return S_OK;
740 static HRESULT WINAPI KeystrokeMgr_SetPreservedKeyDescription(ITfKeystrokeMgr *iface,
741 REFGUID rguid, const WCHAR *pchDesc, ULONG cchDesc)
743 ThreadMgr *This = impl_from_ITfKeystrokeMgrVtbl(iface);
744 FIXME("STUB:(%p)\n",This);
745 return E_NOTIMPL;
748 static HRESULT WINAPI KeystrokeMgr_GetPreservedKeyDescription(ITfKeystrokeMgr *iface,
749 REFGUID rguid, BSTR *pbstrDesc)
751 ThreadMgr *This = impl_from_ITfKeystrokeMgrVtbl(iface);
752 FIXME("STUB:(%p)\n",This);
753 return E_NOTIMPL;
756 static HRESULT WINAPI KeystrokeMgr_SimulatePreservedKey(ITfKeystrokeMgr *iface,
757 ITfContext *pic, REFGUID rguid, BOOL *pfEaten)
759 ThreadMgr *This = impl_from_ITfKeystrokeMgrVtbl(iface);
760 FIXME("STUB:(%p)\n",This);
761 return E_NOTIMPL;
764 static const ITfKeystrokeMgrVtbl ThreadMgr_KeystrokeMgrVtbl =
766 KeystrokeMgr_QueryInterface,
767 KeystrokeMgr_AddRef,
768 KeystrokeMgr_Release,
770 KeystrokeMgr_AdviseKeyEventSink,
771 KeystrokeMgr_UnadviseKeyEventSink,
772 KeystrokeMgr_GetForeground,
773 KeystrokeMgr_TestKeyDown,
774 KeystrokeMgr_TestKeyUp,
775 KeystrokeMgr_KeyDown,
776 KeystrokeMgr_KeyUp,
777 KeystrokeMgr_GetPreservedKey,
778 KeystrokeMgr_IsPreservedKey,
779 KeystrokeMgr_PreserveKey,
780 KeystrokeMgr_UnpreserveKey,
781 KeystrokeMgr_SetPreservedKeyDescription,
782 KeystrokeMgr_GetPreservedKeyDescription,
783 KeystrokeMgr_SimulatePreservedKey
786 /*****************************************************
787 * ITfMessagePump functions
788 *****************************************************/
790 static HRESULT WINAPI MessagePump_QueryInterface(ITfMessagePump *iface, REFIID iid, LPVOID *ppvOut)
792 ThreadMgr *This = impl_from_ITfMessagePumpVtbl(iface);
793 return ThreadMgr_QueryInterface((ITfThreadMgr *)This, iid, *ppvOut);
796 static ULONG WINAPI MessagePump_AddRef(ITfMessagePump *iface)
798 ThreadMgr *This = impl_from_ITfMessagePumpVtbl(iface);
799 return ThreadMgr_AddRef((ITfThreadMgr*)This);
802 static ULONG WINAPI MessagePump_Release(ITfMessagePump *iface)
804 ThreadMgr *This = impl_from_ITfMessagePumpVtbl(iface);
805 return ThreadMgr_Release((ITfThreadMgr *)This);
808 static HRESULT WINAPI MessagePump_PeekMessageA(ITfMessagePump *iface,
809 LPMSG pMsg, HWND hwnd, UINT wMsgFilterMin, UINT wMsgFilterMax,
810 UINT wRemoveMsg, BOOL *pfResult)
812 if (!pfResult)
813 return E_INVALIDARG;
814 *pfResult = PeekMessageA(pMsg, hwnd, wMsgFilterMin, wMsgFilterMax, wRemoveMsg);
815 return S_OK;
818 static HRESULT WINAPI MessagePump_GetMessageA(ITfMessagePump *iface,
819 LPMSG pMsg, HWND hwnd, UINT wMsgFilterMin, UINT wMsgFilterMax,
820 BOOL *pfResult)
822 if (!pfResult)
823 return E_INVALIDARG;
824 *pfResult = GetMessageA(pMsg, hwnd, wMsgFilterMin, wMsgFilterMax);
825 return S_OK;
828 static HRESULT WINAPI MessagePump_PeekMessageW(ITfMessagePump *iface,
829 LPMSG pMsg, HWND hwnd, UINT wMsgFilterMin, UINT wMsgFilterMax,
830 UINT wRemoveMsg, BOOL *pfResult)
832 if (!pfResult)
833 return E_INVALIDARG;
834 *pfResult = PeekMessageW(pMsg, hwnd, wMsgFilterMin, wMsgFilterMax, wRemoveMsg);
835 return S_OK;
838 static HRESULT WINAPI MessagePump_GetMessageW(ITfMessagePump *iface,
839 LPMSG pMsg, HWND hwnd, UINT wMsgFilterMin, UINT wMsgFilterMax,
840 BOOL *pfResult)
842 if (!pfResult)
843 return E_INVALIDARG;
844 *pfResult = GetMessageW(pMsg, hwnd, wMsgFilterMin, wMsgFilterMax);
845 return S_OK;
848 static const ITfMessagePumpVtbl ThreadMgr_MessagePumpVtbl =
850 MessagePump_QueryInterface,
851 MessagePump_AddRef,
852 MessagePump_Release,
854 MessagePump_PeekMessageA,
855 MessagePump_GetMessageA,
856 MessagePump_PeekMessageW,
857 MessagePump_GetMessageW
860 /*****************************************************
861 * ITfClientId functions
862 *****************************************************/
864 static HRESULT WINAPI ClientId_QueryInterface(ITfClientId *iface, REFIID iid, LPVOID *ppvOut)
866 ThreadMgr *This = impl_from_ITfClientIdVtbl(iface);
867 return ThreadMgr_QueryInterface((ITfThreadMgr *)This, iid, *ppvOut);
870 static ULONG WINAPI ClientId_AddRef(ITfClientId *iface)
872 ThreadMgr *This = impl_from_ITfClientIdVtbl(iface);
873 return ThreadMgr_AddRef((ITfThreadMgr*)This);
876 static ULONG WINAPI ClientId_Release(ITfClientId *iface)
878 ThreadMgr *This = impl_from_ITfClientIdVtbl(iface);
879 return ThreadMgr_Release((ITfThreadMgr *)This);
882 static HRESULT WINAPI ClientId_GetClientId(ITfClientId *iface,
883 REFCLSID rclsid, TfClientId *ptid)
886 HRESULT hr;
887 ITfCategoryMgr *catmgr;
888 ThreadMgr *This = impl_from_ITfClientIdVtbl(iface);
890 TRACE("(%p) %s\n",This,debugstr_guid(rclsid));
892 CategoryMgr_Constructor(NULL,(IUnknown**)&catmgr);
893 hr = ITfCategoryMgr_RegisterGUID(catmgr,rclsid,ptid);
894 ITfCategoryMgr_Release(catmgr);
896 return hr;
899 static const ITfClientIdVtbl ThreadMgr_ClientIdVtbl =
901 ClientId_QueryInterface,
902 ClientId_AddRef,
903 ClientId_Release,
905 ClientId_GetClientId
908 /*****************************************************
909 * ITfThreadMgrEventSink functions (internal)
910 *****************************************************/
911 static HRESULT WINAPI ThreadMgrEventSink_QueryInterface(ITfThreadMgrEventSink *iface, REFIID iid, LPVOID *ppvOut)
913 ThreadMgr *This = impl_from_ITfThreadMgrEventSink(iface);
914 return ThreadMgr_QueryInterface((ITfThreadMgr *)This, iid, *ppvOut);
917 static ULONG WINAPI ThreadMgrEventSink_AddRef(ITfThreadMgrEventSink *iface)
919 ThreadMgr *This = impl_from_ITfThreadMgrEventSink(iface);
920 return ThreadMgr_AddRef((ITfThreadMgr*)This);
923 static ULONG WINAPI ThreadMgrEventSink_Release(ITfThreadMgrEventSink *iface)
925 ThreadMgr *This = impl_from_ITfThreadMgrEventSink(iface);
926 return ThreadMgr_Release((ITfThreadMgr *)This);
930 static WINAPI HRESULT ThreadMgrEventSink_OnInitDocumentMgr(
931 ITfThreadMgrEventSink *iface,ITfDocumentMgr *pdim)
933 struct list *cursor;
934 ThreadMgr *This = impl_from_ITfThreadMgrEventSink(iface);
936 TRACE("(%p) %p\n",This,pdim);
938 LIST_FOR_EACH(cursor, &This->ThreadMgrEventSink)
940 ThreadMgrSink* sink = LIST_ENTRY(cursor,ThreadMgrSink,entry);
941 ITfThreadMgrEventSink_OnInitDocumentMgr(sink->interfaces.pITfThreadMgrEventSink,pdim);
944 return S_OK;
947 static WINAPI HRESULT ThreadMgrEventSink_OnUninitDocumentMgr(
948 ITfThreadMgrEventSink *iface, ITfDocumentMgr *pdim)
950 struct list *cursor;
951 ThreadMgr *This = impl_from_ITfThreadMgrEventSink(iface);
953 TRACE("(%p) %p\n",This,pdim);
955 LIST_FOR_EACH(cursor, &This->ThreadMgrEventSink)
957 ThreadMgrSink* sink = LIST_ENTRY(cursor,ThreadMgrSink,entry);
958 ITfThreadMgrEventSink_OnUninitDocumentMgr(sink->interfaces.pITfThreadMgrEventSink,pdim);
961 return S_OK;
964 static WINAPI HRESULT ThreadMgrEventSink_OnSetFocus(
965 ITfThreadMgrEventSink *iface, ITfDocumentMgr *pdimFocus,
966 ITfDocumentMgr *pdimPrevFocus)
968 struct list *cursor;
969 ThreadMgr *This = impl_from_ITfThreadMgrEventSink(iface);
971 TRACE("(%p) %p %p\n",This,pdimFocus, pdimPrevFocus);
973 LIST_FOR_EACH(cursor, &This->ThreadMgrEventSink)
975 ThreadMgrSink* sink = LIST_ENTRY(cursor,ThreadMgrSink,entry);
976 ITfThreadMgrEventSink_OnSetFocus(sink->interfaces.pITfThreadMgrEventSink, pdimFocus, pdimPrevFocus);
979 return S_OK;
982 static WINAPI HRESULT ThreadMgrEventSink_OnPushContext(
983 ITfThreadMgrEventSink *iface, ITfContext *pic)
985 struct list *cursor;
986 ThreadMgr *This = impl_from_ITfThreadMgrEventSink(iface);
988 TRACE("(%p) %p\n",This,pic);
990 LIST_FOR_EACH(cursor, &This->ThreadMgrEventSink)
992 ThreadMgrSink* sink = LIST_ENTRY(cursor,ThreadMgrSink,entry);
993 ITfThreadMgrEventSink_OnPushContext(sink->interfaces.pITfThreadMgrEventSink,pic);
996 return S_OK;
999 static WINAPI HRESULT ThreadMgrEventSink_OnPopContext(
1000 ITfThreadMgrEventSink *iface, ITfContext *pic)
1002 struct list *cursor;
1003 ThreadMgr *This = impl_from_ITfThreadMgrEventSink(iface);
1005 TRACE("(%p) %p\n",This,pic);
1007 LIST_FOR_EACH(cursor, &This->ThreadMgrEventSink)
1009 ThreadMgrSink* sink = LIST_ENTRY(cursor,ThreadMgrSink,entry);
1010 ITfThreadMgrEventSink_OnPopContext(sink->interfaces.pITfThreadMgrEventSink,pic);
1013 return S_OK;
1016 static const ITfThreadMgrEventSinkVtbl ThreadMgr_ThreadMgrEventSinkVtbl =
1018 ThreadMgrEventSink_QueryInterface,
1019 ThreadMgrEventSink_AddRef,
1020 ThreadMgrEventSink_Release,
1022 ThreadMgrEventSink_OnInitDocumentMgr,
1023 ThreadMgrEventSink_OnUninitDocumentMgr,
1024 ThreadMgrEventSink_OnSetFocus,
1025 ThreadMgrEventSink_OnPushContext,
1026 ThreadMgrEventSink_OnPopContext
1029 HRESULT ThreadMgr_Constructor(IUnknown *pUnkOuter, IUnknown **ppOut)
1031 ThreadMgr *This;
1032 if (pUnkOuter)
1033 return CLASS_E_NOAGGREGATION;
1035 /* Only 1 ThreadMgr is created per thread */
1036 This = TlsGetValue(tlsIndex);
1037 if (This)
1039 ThreadMgr_AddRef((ITfThreadMgr*)This);
1040 *ppOut = (IUnknown*)This;
1041 return S_OK;
1044 This = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(ThreadMgr));
1045 if (This == NULL)
1046 return E_OUTOFMEMORY;
1048 This->ThreadMgrVtbl= &ThreadMgr_ThreadMgrVtbl;
1049 This->SourceVtbl = &ThreadMgr_SourceVtbl;
1050 This->KeystrokeMgrVtbl= &ThreadMgr_KeystrokeMgrVtbl;
1051 This->MessagePumpVtbl= &ThreadMgr_MessagePumpVtbl;
1052 This->ClientIdVtbl = &ThreadMgr_ClientIdVtbl;
1053 This->ThreadMgrEventSinkVtbl = &ThreadMgr_ThreadMgrEventSinkVtbl;
1054 This->refCount = 1;
1055 TlsSetValue(tlsIndex,This);
1057 list_init(&This->CurrentPreservedKeys);
1059 list_init(&This->ActiveLanguageProfileNotifySink);
1060 list_init(&This->DisplayAttributeNotifySink);
1061 list_init(&This->KeyTraceEventSink);
1062 list_init(&This->PreservedKeyNotifySink);
1063 list_init(&This->ThreadFocusSink);
1064 list_init(&This->ThreadMgrEventSink);
1066 TRACE("returning %p\n", This);
1067 *ppOut = (IUnknown *)This;
1068 return S_OK;