push e1d8a1293d44015bb0894687d02c5c53339996f7
[wine/hacks.git] / dlls / msctf / threadmgr.c
blobb10910709bc3702e9c83ac44c53aa18f7bad7ee6
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 /* Aggregation */
82 ITfCompartmentMgr *CompartmentMgr;
84 const ITfThreadMgrEventSinkVtbl *ThreadMgrEventSinkVtbl; /* internal */
86 ITfDocumentMgr *focus;
87 LONG activationCount;
89 ITfKeyEventSink *forgroundKeyEventSink;
90 CLSID forgroundTextService;
92 struct list CurrentPreservedKeys;
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;
103 static inline ThreadMgr *impl_from_ITfSourceVtbl(ITfSource *iface)
105 return (ThreadMgr *)((char *)iface - FIELD_OFFSET(ThreadMgr,SourceVtbl));
108 static inline ThreadMgr *impl_from_ITfKeystrokeMgrVtbl(ITfKeystrokeMgr *iface)
110 return (ThreadMgr *)((char *)iface - FIELD_OFFSET(ThreadMgr,KeystrokeMgrVtbl));
113 static inline ThreadMgr *impl_from_ITfMessagePumpVtbl(ITfMessagePump *iface)
115 return (ThreadMgr *)((char *)iface - FIELD_OFFSET(ThreadMgr,MessagePumpVtbl));
118 static inline ThreadMgr *impl_from_ITfClientIdVtbl(ITfClientId *iface)
120 return (ThreadMgr *)((char *)iface - FIELD_OFFSET(ThreadMgr,ClientIdVtbl));
123 static inline ThreadMgr *impl_from_ITfThreadMgrEventSink(ITfThreadMgrEventSink *iface)
125 return (ThreadMgr *)((char *)iface - FIELD_OFFSET(ThreadMgr,ThreadMgrEventSinkVtbl));
128 static void free_sink(ThreadMgrSink *sink)
130 IUnknown_Release(sink->interfaces.pIUnknown);
131 HeapFree(GetProcessHeap(),0,sink);
134 static void ThreadMgr_Destructor(ThreadMgr *This)
136 struct list *cursor, *cursor2;
138 TlsSetValue(tlsIndex,NULL);
139 TRACE("destroying %p\n", This);
140 if (This->focus)
141 ITfDocumentMgr_Release(This->focus);
143 /* free sinks */
144 LIST_FOR_EACH_SAFE(cursor, cursor2, &This->ActiveLanguageProfileNotifySink)
146 ThreadMgrSink* sink = LIST_ENTRY(cursor,ThreadMgrSink,entry);
147 list_remove(cursor);
148 free_sink(sink);
150 LIST_FOR_EACH_SAFE(cursor, cursor2, &This->DisplayAttributeNotifySink)
152 ThreadMgrSink* sink = LIST_ENTRY(cursor,ThreadMgrSink,entry);
153 list_remove(cursor);
154 free_sink(sink);
156 LIST_FOR_EACH_SAFE(cursor, cursor2, &This->KeyTraceEventSink)
158 ThreadMgrSink* sink = LIST_ENTRY(cursor,ThreadMgrSink,entry);
159 list_remove(cursor);
160 free_sink(sink);
162 LIST_FOR_EACH_SAFE(cursor, cursor2, &This->PreservedKeyNotifySink)
164 ThreadMgrSink* sink = LIST_ENTRY(cursor,ThreadMgrSink,entry);
165 list_remove(cursor);
166 free_sink(sink);
168 LIST_FOR_EACH_SAFE(cursor, cursor2, &This->ThreadFocusSink)
170 ThreadMgrSink* sink = LIST_ENTRY(cursor,ThreadMgrSink,entry);
171 list_remove(cursor);
172 free_sink(sink);
174 LIST_FOR_EACH_SAFE(cursor, cursor2, &This->ThreadMgrEventSink)
176 ThreadMgrSink* sink = LIST_ENTRY(cursor,ThreadMgrSink,entry);
177 list_remove(cursor);
178 free_sink(sink);
181 LIST_FOR_EACH_SAFE(cursor, cursor2, &This->CurrentPreservedKeys)
183 PreservedKey* key = LIST_ENTRY(cursor,PreservedKey,entry);
184 list_remove(cursor);
185 HeapFree(GetProcessHeap(),0,key->description);
186 HeapFree(GetProcessHeap(),0,key);
189 CompartmentMgr_Destructor(This->CompartmentMgr);
191 HeapFree(GetProcessHeap(),0,This);
194 static HRESULT WINAPI ThreadMgr_QueryInterface(ITfThreadMgr *iface, REFIID iid, LPVOID *ppvOut)
196 ThreadMgr *This = (ThreadMgr *)iface;
197 *ppvOut = NULL;
199 if (IsEqualIID(iid, &IID_IUnknown) || IsEqualIID(iid, &IID_ITfThreadMgr))
201 *ppvOut = This;
203 else if (IsEqualIID(iid, &IID_ITfSource))
205 *ppvOut = &This->SourceVtbl;
207 else if (IsEqualIID(iid, &IID_ITfKeystrokeMgr))
209 *ppvOut = &This->KeystrokeMgrVtbl;
211 else if (IsEqualIID(iid, &IID_ITfMessagePump))
213 *ppvOut = &This->MessagePumpVtbl;
215 else if (IsEqualIID(iid, &IID_ITfClientId))
217 *ppvOut = &This->ClientIdVtbl;
219 else if (IsEqualIID(iid, &IID_ITfCompartmentMgr))
221 *ppvOut = This->CompartmentMgr;
224 if (*ppvOut)
226 IUnknown_AddRef(iface);
227 return S_OK;
230 WARN("unsupported interface: %s\n", debugstr_guid(iid));
231 return E_NOINTERFACE;
234 static ULONG WINAPI ThreadMgr_AddRef(ITfThreadMgr *iface)
236 ThreadMgr *This = (ThreadMgr *)iface;
237 return InterlockedIncrement(&This->refCount);
240 static ULONG WINAPI ThreadMgr_Release(ITfThreadMgr *iface)
242 ThreadMgr *This = (ThreadMgr *)iface;
243 ULONG ret;
245 ret = InterlockedDecrement(&This->refCount);
246 if (ret == 0)
247 ThreadMgr_Destructor(This);
248 return ret;
251 /*****************************************************
252 * ITfThreadMgr functions
253 *****************************************************/
255 static HRESULT WINAPI ThreadMgr_fnActivate( ITfThreadMgr* iface, TfClientId *ptid)
257 ThreadMgr *This = (ThreadMgr *)iface;
259 TRACE("(%p) %p\n",This, ptid);
261 if (!ptid)
262 return E_INVALIDARG;
264 if (!processId)
266 GUID guid;
267 CoCreateGuid(&guid);
268 ITfClientId_GetClientId((ITfClientId*)&This->ClientIdVtbl,&guid,&processId);
271 activate_textservices(iface);
272 This->activationCount++;
273 *ptid = processId;
274 return S_OK;
277 static HRESULT WINAPI ThreadMgr_fnDeactivate( ITfThreadMgr* iface)
279 ThreadMgr *This = (ThreadMgr *)iface;
280 TRACE("(%p)\n",This);
282 if (This->activationCount == 0)
283 return E_UNEXPECTED;
285 This->activationCount --;
287 if (This->activationCount == 0)
289 if (This->focus)
291 ITfThreadMgrEventSink_OnSetFocus((ITfThreadMgrEventSink*)&This->ThreadMgrEventSinkVtbl, 0, This->focus);
292 ITfDocumentMgr_Release(This->focus);
293 This->focus = 0;
297 deactivate_textservices();
299 return S_OK;
302 static HRESULT WINAPI ThreadMgr_CreateDocumentMgr( ITfThreadMgr* iface, ITfDocumentMgr
303 **ppdim)
305 ThreadMgr *This = (ThreadMgr *)iface;
306 TRACE("(%p)\n",iface);
307 return DocumentMgr_Constructor((ITfThreadMgrEventSink*)&This->ThreadMgrEventSinkVtbl, ppdim);
310 static HRESULT WINAPI ThreadMgr_EnumDocumentMgrs( ITfThreadMgr* iface, IEnumTfDocumentMgrs
311 **ppEnum)
313 ThreadMgr *This = (ThreadMgr *)iface;
314 FIXME("STUB:(%p)\n",This);
315 return E_NOTIMPL;
318 static HRESULT WINAPI ThreadMgr_GetFocus( ITfThreadMgr* iface, ITfDocumentMgr
319 **ppdimFocus)
321 ThreadMgr *This = (ThreadMgr *)iface;
322 TRACE("(%p)\n",This);
324 if (!ppdimFocus)
325 return E_INVALIDARG;
327 *ppdimFocus = This->focus;
329 TRACE("->%p\n",This->focus);
331 if (This->focus == NULL)
332 return S_FALSE;
334 ITfDocumentMgr_AddRef(This->focus);
336 return S_OK;
339 static HRESULT WINAPI ThreadMgr_SetFocus( ITfThreadMgr* iface, ITfDocumentMgr *pdimFocus)
341 ITfDocumentMgr *check;
342 ThreadMgr *This = (ThreadMgr *)iface;
344 TRACE("(%p) %p\n",This,pdimFocus);
346 if (!pdimFocus || FAILED(IUnknown_QueryInterface(pdimFocus,&IID_ITfDocumentMgr,(LPVOID*) &check)))
347 return E_INVALIDARG;
349 ITfThreadMgrEventSink_OnSetFocus((ITfThreadMgrEventSink*)&This->ThreadMgrEventSinkVtbl, check, This->focus);
351 if (This->focus)
352 ITfDocumentMgr_Release(This->focus);
354 This->focus = check;
355 return S_OK;
358 static HRESULT WINAPI ThreadMgr_AssociateFocus( ITfThreadMgr* iface, HWND hwnd,
359 ITfDocumentMgr *pdimNew, ITfDocumentMgr **ppdimPrev)
361 ThreadMgr *This = (ThreadMgr *)iface;
362 FIXME("STUB:(%p)\n",This);
363 return E_NOTIMPL;
366 static HRESULT WINAPI ThreadMgr_IsThreadFocus( ITfThreadMgr* iface, BOOL *pfThreadFocus)
368 HWND focus;
369 ThreadMgr *This = (ThreadMgr *)iface;
370 TRACE("(%p) %p\n",This,pfThreadFocus);
371 focus = GetFocus();
372 *pfThreadFocus = (focus == NULL);
373 return S_OK;
376 static HRESULT WINAPI ThreadMgr_GetFunctionProvider( ITfThreadMgr* iface, REFCLSID clsid,
377 ITfFunctionProvider **ppFuncProv)
379 ThreadMgr *This = (ThreadMgr *)iface;
380 FIXME("STUB:(%p)\n",This);
381 return E_NOTIMPL;
384 static HRESULT WINAPI ThreadMgr_EnumFunctionProviders( ITfThreadMgr* iface,
385 IEnumTfFunctionProviders **ppEnum)
387 ThreadMgr *This = (ThreadMgr *)iface;
388 FIXME("STUB:(%p)\n",This);
389 return E_NOTIMPL;
392 static HRESULT WINAPI ThreadMgr_GetGlobalCompartment( ITfThreadMgr* iface,
393 ITfCompartmentMgr **ppCompMgr)
395 ThreadMgr *This = (ThreadMgr *)iface;
396 HRESULT hr;
397 TRACE("(%p) %p\n",This, ppCompMgr);
399 if (!ppCompMgr)
400 return E_INVALIDARG;
402 if (!globalCompartmentMgr)
404 hr = CompartmentMgr_Constructor(NULL,&IID_ITfCompartmentMgr,(IUnknown**)&globalCompartmentMgr);
405 if (FAILED(hr))
406 return hr;
409 ITfCompartmentMgr_AddRef(globalCompartmentMgr);
410 *ppCompMgr = globalCompartmentMgr;
411 return S_OK;
414 static const ITfThreadMgrVtbl ThreadMgr_ThreadMgrVtbl =
416 ThreadMgr_QueryInterface,
417 ThreadMgr_AddRef,
418 ThreadMgr_Release,
420 ThreadMgr_fnActivate,
421 ThreadMgr_fnDeactivate,
422 ThreadMgr_CreateDocumentMgr,
423 ThreadMgr_EnumDocumentMgrs,
424 ThreadMgr_GetFocus,
425 ThreadMgr_SetFocus,
426 ThreadMgr_AssociateFocus,
427 ThreadMgr_IsThreadFocus,
428 ThreadMgr_GetFunctionProvider,
429 ThreadMgr_EnumFunctionProviders,
430 ThreadMgr_GetGlobalCompartment
434 static HRESULT WINAPI Source_QueryInterface(ITfSource *iface, REFIID iid, LPVOID *ppvOut)
436 ThreadMgr *This = impl_from_ITfSourceVtbl(iface);
437 return ThreadMgr_QueryInterface((ITfThreadMgr *)This, iid, *ppvOut);
440 static ULONG WINAPI Source_AddRef(ITfSource *iface)
442 ThreadMgr *This = impl_from_ITfSourceVtbl(iface);
443 return ThreadMgr_AddRef((ITfThreadMgr*)This);
446 static ULONG WINAPI Source_Release(ITfSource *iface)
448 ThreadMgr *This = impl_from_ITfSourceVtbl(iface);
449 return ThreadMgr_Release((ITfThreadMgr *)This);
452 /*****************************************************
453 * ITfSource functions
454 *****************************************************/
455 static WINAPI HRESULT ThreadMgrSource_AdviseSink(ITfSource *iface,
456 REFIID riid, IUnknown *punk, DWORD *pdwCookie)
458 ThreadMgrSink *tms;
459 ThreadMgr *This = impl_from_ITfSourceVtbl(iface);
461 TRACE("(%p) %s %p %p\n",This,debugstr_guid(riid),punk,pdwCookie);
463 if (!riid || !punk || !pdwCookie)
464 return E_INVALIDARG;
466 if (IsEqualIID(riid, &IID_ITfThreadMgrEventSink))
468 tms = HeapAlloc(GetProcessHeap(),0,sizeof(ThreadMgrSink));
469 if (!tms)
470 return E_OUTOFMEMORY;
471 if (FAILED(IUnknown_QueryInterface(punk, riid, (LPVOID *)&tms->interfaces.pITfThreadMgrEventSink)))
473 HeapFree(GetProcessHeap(),0,tms);
474 return CONNECT_E_CANNOTCONNECT;
476 list_add_head(&This->ThreadMgrEventSink,&tms->entry);
477 *pdwCookie = generate_Cookie(COOKIE_MAGIC_TMSINK, tms);
479 else
481 FIXME("(%p) Unhandled Sink: %s\n",This,debugstr_guid(riid));
482 return E_NOTIMPL;
485 TRACE("cookie %x\n",*pdwCookie);
487 return S_OK;
490 static WINAPI HRESULT ThreadMgrSource_UnadviseSink(ITfSource *iface, DWORD pdwCookie)
492 ThreadMgrSink *sink;
493 ThreadMgr *This = impl_from_ITfSourceVtbl(iface);
495 TRACE("(%p) %x\n",This,pdwCookie);
497 if (get_Cookie_magic(pdwCookie)!=COOKIE_MAGIC_TMSINK)
498 return E_INVALIDARG;
500 sink = (ThreadMgrSink*)remove_Cookie(pdwCookie);
501 if (!sink)
502 return CONNECT_E_NOCONNECTION;
504 list_remove(&sink->entry);
505 free_sink(sink);
507 return S_OK;
510 static const ITfSourceVtbl ThreadMgr_SourceVtbl =
512 Source_QueryInterface,
513 Source_AddRef,
514 Source_Release,
516 ThreadMgrSource_AdviseSink,
517 ThreadMgrSource_UnadviseSink,
520 /*****************************************************
521 * ITfKeystrokeMgr functions
522 *****************************************************/
524 static HRESULT WINAPI KeystrokeMgr_QueryInterface(ITfKeystrokeMgr *iface, REFIID iid, LPVOID *ppvOut)
526 ThreadMgr *This = impl_from_ITfKeystrokeMgrVtbl(iface);
527 return ThreadMgr_QueryInterface((ITfThreadMgr *)This, iid, *ppvOut);
530 static ULONG WINAPI KeystrokeMgr_AddRef(ITfKeystrokeMgr *iface)
532 ThreadMgr *This = impl_from_ITfKeystrokeMgrVtbl(iface);
533 return ThreadMgr_AddRef((ITfThreadMgr*)This);
536 static ULONG WINAPI KeystrokeMgr_Release(ITfKeystrokeMgr *iface)
538 ThreadMgr *This = impl_from_ITfKeystrokeMgrVtbl(iface);
539 return ThreadMgr_Release((ITfThreadMgr *)This);
542 static HRESULT WINAPI KeystrokeMgr_AdviseKeyEventSink(ITfKeystrokeMgr *iface,
543 TfClientId tid, ITfKeyEventSink *pSink, BOOL fForeground)
545 ThreadMgr *This = impl_from_ITfKeystrokeMgrVtbl(iface);
546 CLSID textservice;
547 ITfKeyEventSink *check = NULL;
549 TRACE("(%p) %x %p %i\n",This,tid,pSink,fForeground);
551 if (!tid || !pSink)
552 return E_INVALIDARG;
554 textservice = get_textservice_clsid(tid);
555 if (IsEqualCLSID(&GUID_NULL,&textservice))
556 return E_INVALIDARG;
558 get_textservice_sink(tid, &IID_ITfKeyEventSink, (IUnknown**)&check);
559 if (check != NULL)
560 return CONNECT_E_ADVISELIMIT;
562 if (FAILED(IUnknown_QueryInterface(pSink,&IID_ITfKeyEventSink,(LPVOID*) &check)))
563 return E_INVALIDARG;
565 set_textservice_sink(tid, &IID_ITfKeyEventSink, (IUnknown*)check);
567 if (fForeground)
569 if (This->forgroundKeyEventSink)
571 ITfKeyEventSink_OnSetFocus(This->forgroundKeyEventSink, FALSE);
572 ITfKeyEventSink_Release(This->forgroundKeyEventSink);
574 ITfKeyEventSink_AddRef(check);
575 ITfKeyEventSink_OnSetFocus(check, TRUE);
576 This->forgroundKeyEventSink = check;
577 This->forgroundTextService = textservice;
579 return S_OK;
582 static HRESULT WINAPI KeystrokeMgr_UnadviseKeyEventSink(ITfKeystrokeMgr *iface,
583 TfClientId tid)
585 ThreadMgr *This = impl_from_ITfKeystrokeMgrVtbl(iface);
586 CLSID textservice;
587 ITfKeyEventSink *check = NULL;
588 TRACE("(%p) %x\n",This,tid);
590 if (!tid)
591 return E_INVALIDARG;
593 textservice = get_textservice_clsid(tid);
594 if (IsEqualCLSID(&GUID_NULL,&textservice))
595 return E_INVALIDARG;
597 get_textservice_sink(tid, &IID_ITfKeyEventSink, (IUnknown**)&check);
599 if (!check)
600 return CONNECT_E_NOCONNECTION;
602 set_textservice_sink(tid, &IID_ITfKeyEventSink, NULL);
603 ITfKeyEventSink_Release(check);
605 if (This->forgroundKeyEventSink == check)
607 ITfKeyEventSink_Release(This->forgroundKeyEventSink);
608 This->forgroundKeyEventSink = NULL;
609 This->forgroundTextService = GUID_NULL;
611 return S_OK;
614 static HRESULT WINAPI KeystrokeMgr_GetForeground(ITfKeystrokeMgr *iface,
615 CLSID *pclsid)
617 ThreadMgr *This = impl_from_ITfKeystrokeMgrVtbl(iface);
618 TRACE("(%p) %p\n",This,pclsid);
619 if (!pclsid)
620 return E_INVALIDARG;
622 if (IsEqualCLSID(&This->forgroundTextService,&GUID_NULL))
623 return S_FALSE;
625 *pclsid = This->forgroundTextService;
626 return S_OK;
629 static HRESULT WINAPI KeystrokeMgr_TestKeyDown(ITfKeystrokeMgr *iface,
630 WPARAM wParam, LPARAM lParam, BOOL *pfEaten)
632 ThreadMgr *This = impl_from_ITfKeystrokeMgrVtbl(iface);
633 FIXME("STUB:(%p)\n",This);
634 return E_NOTIMPL;
637 static HRESULT WINAPI KeystrokeMgr_TestKeyUp(ITfKeystrokeMgr *iface,
638 WPARAM wParam, LPARAM lParam, BOOL *pfEaten)
640 ThreadMgr *This = impl_from_ITfKeystrokeMgrVtbl(iface);
641 FIXME("STUB:(%p)\n",This);
642 return E_NOTIMPL;
645 static HRESULT WINAPI KeystrokeMgr_KeyDown(ITfKeystrokeMgr *iface,
646 WPARAM wParam, LPARAM lParam, BOOL *pfEaten)
648 ThreadMgr *This = impl_from_ITfKeystrokeMgrVtbl(iface);
649 FIXME("STUB:(%p)\n",This);
650 return E_NOTIMPL;
653 static HRESULT WINAPI KeystrokeMgr_KeyUp(ITfKeystrokeMgr *iface,
654 WPARAM wParam, LPARAM lParam, BOOL *pfEaten)
656 ThreadMgr *This = impl_from_ITfKeystrokeMgrVtbl(iface);
657 FIXME("STUB:(%p)\n",This);
658 return E_NOTIMPL;
661 static HRESULT WINAPI KeystrokeMgr_GetPreservedKey(ITfKeystrokeMgr *iface,
662 ITfContext *pic, const TF_PRESERVEDKEY *pprekey, GUID *pguid)
664 ThreadMgr *This = impl_from_ITfKeystrokeMgrVtbl(iface);
665 FIXME("STUB:(%p)\n",This);
666 return E_NOTIMPL;
669 static HRESULT WINAPI KeystrokeMgr_IsPreservedKey(ITfKeystrokeMgr *iface,
670 REFGUID rguid, const TF_PRESERVEDKEY *pprekey, BOOL *pfRegistered)
672 ThreadMgr *This = impl_from_ITfKeystrokeMgrVtbl(iface);
673 struct list *cursor;
675 TRACE("(%p) %s (%x %x) %p\n",This,debugstr_guid(rguid), (pprekey)?pprekey->uVKey:0, (pprekey)?pprekey->uModifiers:0, pfRegistered);
677 if (!rguid || !pprekey || !pfRegistered)
678 return E_INVALIDARG;
680 LIST_FOR_EACH(cursor, &This->CurrentPreservedKeys)
682 PreservedKey* key = LIST_ENTRY(cursor,PreservedKey,entry);
683 if (IsEqualGUID(rguid,&key->guid) && pprekey->uVKey == key->prekey.uVKey && pprekey->uModifiers == key->prekey.uModifiers)
685 *pfRegistered = TRUE;
686 return S_OK;
690 *pfRegistered = FALSE;
691 return S_FALSE;
694 static HRESULT WINAPI KeystrokeMgr_PreserveKey(ITfKeystrokeMgr *iface,
695 TfClientId tid, REFGUID rguid, const TF_PRESERVEDKEY *prekey,
696 const WCHAR *pchDesc, ULONG cchDesc)
698 ThreadMgr *This = impl_from_ITfKeystrokeMgrVtbl(iface);
699 struct list *cursor;
700 PreservedKey *newkey;
702 TRACE("(%p) %x %s (%x,%x) %s\n",This,tid, debugstr_guid(rguid),(prekey)?prekey->uVKey:0,(prekey)?prekey->uModifiers:0,debugstr_wn(pchDesc,cchDesc));
704 if (!tid || ! rguid || !prekey || (cchDesc && !pchDesc))
705 return E_INVALIDARG;
707 LIST_FOR_EACH(cursor, &This->CurrentPreservedKeys)
709 PreservedKey* key = LIST_ENTRY(cursor,PreservedKey,entry);
710 if (IsEqualGUID(rguid,&key->guid) && prekey->uVKey == key->prekey.uVKey && prekey->uModifiers == key->prekey.uModifiers)
711 return TF_E_ALREADY_EXISTS;
714 newkey = HeapAlloc(GetProcessHeap(),0,sizeof(PreservedKey));
715 if (!newkey)
716 return E_OUTOFMEMORY;
718 newkey->guid = *rguid;
719 newkey->prekey = *prekey;
720 newkey->tid = tid;
721 if (cchDesc)
723 newkey->description = HeapAlloc(GetProcessHeap(),0,cchDesc * sizeof(WCHAR));
724 if (!newkey->description)
726 HeapFree(GetProcessHeap(),0,newkey);
727 return E_OUTOFMEMORY;
729 memcpy(newkey->description, pchDesc, cchDesc*sizeof(WCHAR));
732 list_add_head(&This->CurrentPreservedKeys,&newkey->entry);
734 return S_OK;
737 static HRESULT WINAPI KeystrokeMgr_UnpreserveKey(ITfKeystrokeMgr *iface,
738 REFGUID rguid, const TF_PRESERVEDKEY *pprekey)
740 ThreadMgr *This = impl_from_ITfKeystrokeMgrVtbl(iface);
741 PreservedKey* key = NULL;
742 struct list *cursor;
743 TRACE("(%p) %s (%x %x)\n",This,debugstr_guid(rguid),(pprekey)?pprekey->uVKey:0, (pprekey)?pprekey->uModifiers:0);
745 if (!pprekey || !rguid)
746 return E_INVALIDARG;
748 LIST_FOR_EACH(cursor, &This->CurrentPreservedKeys)
750 key = LIST_ENTRY(cursor,PreservedKey,entry);
751 if (IsEqualGUID(rguid,&key->guid) && pprekey->uVKey == key->prekey.uVKey && pprekey->uModifiers == key->prekey.uModifiers)
752 break;
753 key = NULL;
756 if (!key)
757 return CONNECT_E_NOCONNECTION;
759 list_remove(&key->entry);
760 HeapFree(GetProcessHeap(),0,key->description);
761 HeapFree(GetProcessHeap(),0,key);
763 return S_OK;
766 static HRESULT WINAPI KeystrokeMgr_SetPreservedKeyDescription(ITfKeystrokeMgr *iface,
767 REFGUID rguid, const WCHAR *pchDesc, ULONG cchDesc)
769 ThreadMgr *This = impl_from_ITfKeystrokeMgrVtbl(iface);
770 FIXME("STUB:(%p)\n",This);
771 return E_NOTIMPL;
774 static HRESULT WINAPI KeystrokeMgr_GetPreservedKeyDescription(ITfKeystrokeMgr *iface,
775 REFGUID rguid, BSTR *pbstrDesc)
777 ThreadMgr *This = impl_from_ITfKeystrokeMgrVtbl(iface);
778 FIXME("STUB:(%p)\n",This);
779 return E_NOTIMPL;
782 static HRESULT WINAPI KeystrokeMgr_SimulatePreservedKey(ITfKeystrokeMgr *iface,
783 ITfContext *pic, REFGUID rguid, BOOL *pfEaten)
785 ThreadMgr *This = impl_from_ITfKeystrokeMgrVtbl(iface);
786 FIXME("STUB:(%p)\n",This);
787 return E_NOTIMPL;
790 static const ITfKeystrokeMgrVtbl ThreadMgr_KeystrokeMgrVtbl =
792 KeystrokeMgr_QueryInterface,
793 KeystrokeMgr_AddRef,
794 KeystrokeMgr_Release,
796 KeystrokeMgr_AdviseKeyEventSink,
797 KeystrokeMgr_UnadviseKeyEventSink,
798 KeystrokeMgr_GetForeground,
799 KeystrokeMgr_TestKeyDown,
800 KeystrokeMgr_TestKeyUp,
801 KeystrokeMgr_KeyDown,
802 KeystrokeMgr_KeyUp,
803 KeystrokeMgr_GetPreservedKey,
804 KeystrokeMgr_IsPreservedKey,
805 KeystrokeMgr_PreserveKey,
806 KeystrokeMgr_UnpreserveKey,
807 KeystrokeMgr_SetPreservedKeyDescription,
808 KeystrokeMgr_GetPreservedKeyDescription,
809 KeystrokeMgr_SimulatePreservedKey
812 /*****************************************************
813 * ITfMessagePump functions
814 *****************************************************/
816 static HRESULT WINAPI MessagePump_QueryInterface(ITfMessagePump *iface, REFIID iid, LPVOID *ppvOut)
818 ThreadMgr *This = impl_from_ITfMessagePumpVtbl(iface);
819 return ThreadMgr_QueryInterface((ITfThreadMgr *)This, iid, *ppvOut);
822 static ULONG WINAPI MessagePump_AddRef(ITfMessagePump *iface)
824 ThreadMgr *This = impl_from_ITfMessagePumpVtbl(iface);
825 return ThreadMgr_AddRef((ITfThreadMgr*)This);
828 static ULONG WINAPI MessagePump_Release(ITfMessagePump *iface)
830 ThreadMgr *This = impl_from_ITfMessagePumpVtbl(iface);
831 return ThreadMgr_Release((ITfThreadMgr *)This);
834 static HRESULT WINAPI MessagePump_PeekMessageA(ITfMessagePump *iface,
835 LPMSG pMsg, HWND hwnd, UINT wMsgFilterMin, UINT wMsgFilterMax,
836 UINT wRemoveMsg, BOOL *pfResult)
838 if (!pfResult)
839 return E_INVALIDARG;
840 *pfResult = PeekMessageA(pMsg, hwnd, wMsgFilterMin, wMsgFilterMax, wRemoveMsg);
841 return S_OK;
844 static HRESULT WINAPI MessagePump_GetMessageA(ITfMessagePump *iface,
845 LPMSG pMsg, HWND hwnd, UINT wMsgFilterMin, UINT wMsgFilterMax,
846 BOOL *pfResult)
848 if (!pfResult)
849 return E_INVALIDARG;
850 *pfResult = GetMessageA(pMsg, hwnd, wMsgFilterMin, wMsgFilterMax);
851 return S_OK;
854 static HRESULT WINAPI MessagePump_PeekMessageW(ITfMessagePump *iface,
855 LPMSG pMsg, HWND hwnd, UINT wMsgFilterMin, UINT wMsgFilterMax,
856 UINT wRemoveMsg, BOOL *pfResult)
858 if (!pfResult)
859 return E_INVALIDARG;
860 *pfResult = PeekMessageW(pMsg, hwnd, wMsgFilterMin, wMsgFilterMax, wRemoveMsg);
861 return S_OK;
864 static HRESULT WINAPI MessagePump_GetMessageW(ITfMessagePump *iface,
865 LPMSG pMsg, HWND hwnd, UINT wMsgFilterMin, UINT wMsgFilterMax,
866 BOOL *pfResult)
868 if (!pfResult)
869 return E_INVALIDARG;
870 *pfResult = GetMessageW(pMsg, hwnd, wMsgFilterMin, wMsgFilterMax);
871 return S_OK;
874 static const ITfMessagePumpVtbl ThreadMgr_MessagePumpVtbl =
876 MessagePump_QueryInterface,
877 MessagePump_AddRef,
878 MessagePump_Release,
880 MessagePump_PeekMessageA,
881 MessagePump_GetMessageA,
882 MessagePump_PeekMessageW,
883 MessagePump_GetMessageW
886 /*****************************************************
887 * ITfClientId functions
888 *****************************************************/
890 static HRESULT WINAPI ClientId_QueryInterface(ITfClientId *iface, REFIID iid, LPVOID *ppvOut)
892 ThreadMgr *This = impl_from_ITfClientIdVtbl(iface);
893 return ThreadMgr_QueryInterface((ITfThreadMgr *)This, iid, *ppvOut);
896 static ULONG WINAPI ClientId_AddRef(ITfClientId *iface)
898 ThreadMgr *This = impl_from_ITfClientIdVtbl(iface);
899 return ThreadMgr_AddRef((ITfThreadMgr*)This);
902 static ULONG WINAPI ClientId_Release(ITfClientId *iface)
904 ThreadMgr *This = impl_from_ITfClientIdVtbl(iface);
905 return ThreadMgr_Release((ITfThreadMgr *)This);
908 static HRESULT WINAPI ClientId_GetClientId(ITfClientId *iface,
909 REFCLSID rclsid, TfClientId *ptid)
912 HRESULT hr;
913 ITfCategoryMgr *catmgr;
914 ThreadMgr *This = impl_from_ITfClientIdVtbl(iface);
916 TRACE("(%p) %s\n",This,debugstr_guid(rclsid));
918 CategoryMgr_Constructor(NULL,(IUnknown**)&catmgr);
919 hr = ITfCategoryMgr_RegisterGUID(catmgr,rclsid,ptid);
920 ITfCategoryMgr_Release(catmgr);
922 return hr;
925 static const ITfClientIdVtbl ThreadMgr_ClientIdVtbl =
927 ClientId_QueryInterface,
928 ClientId_AddRef,
929 ClientId_Release,
931 ClientId_GetClientId
934 /*****************************************************
935 * ITfThreadMgrEventSink functions (internal)
936 *****************************************************/
937 static HRESULT WINAPI ThreadMgrEventSink_QueryInterface(ITfThreadMgrEventSink *iface, REFIID iid, LPVOID *ppvOut)
939 ThreadMgr *This = impl_from_ITfThreadMgrEventSink(iface);
940 return ThreadMgr_QueryInterface((ITfThreadMgr *)This, iid, *ppvOut);
943 static ULONG WINAPI ThreadMgrEventSink_AddRef(ITfThreadMgrEventSink *iface)
945 ThreadMgr *This = impl_from_ITfThreadMgrEventSink(iface);
946 return ThreadMgr_AddRef((ITfThreadMgr*)This);
949 static ULONG WINAPI ThreadMgrEventSink_Release(ITfThreadMgrEventSink *iface)
951 ThreadMgr *This = impl_from_ITfThreadMgrEventSink(iface);
952 return ThreadMgr_Release((ITfThreadMgr *)This);
956 static WINAPI HRESULT ThreadMgrEventSink_OnInitDocumentMgr(
957 ITfThreadMgrEventSink *iface,ITfDocumentMgr *pdim)
959 struct list *cursor;
960 ThreadMgr *This = impl_from_ITfThreadMgrEventSink(iface);
962 TRACE("(%p) %p\n",This,pdim);
964 LIST_FOR_EACH(cursor, &This->ThreadMgrEventSink)
966 ThreadMgrSink* sink = LIST_ENTRY(cursor,ThreadMgrSink,entry);
967 ITfThreadMgrEventSink_OnInitDocumentMgr(sink->interfaces.pITfThreadMgrEventSink,pdim);
970 return S_OK;
973 static WINAPI HRESULT ThreadMgrEventSink_OnUninitDocumentMgr(
974 ITfThreadMgrEventSink *iface, ITfDocumentMgr *pdim)
976 struct list *cursor;
977 ThreadMgr *This = impl_from_ITfThreadMgrEventSink(iface);
979 TRACE("(%p) %p\n",This,pdim);
981 LIST_FOR_EACH(cursor, &This->ThreadMgrEventSink)
983 ThreadMgrSink* sink = LIST_ENTRY(cursor,ThreadMgrSink,entry);
984 ITfThreadMgrEventSink_OnUninitDocumentMgr(sink->interfaces.pITfThreadMgrEventSink,pdim);
987 return S_OK;
990 static WINAPI HRESULT ThreadMgrEventSink_OnSetFocus(
991 ITfThreadMgrEventSink *iface, ITfDocumentMgr *pdimFocus,
992 ITfDocumentMgr *pdimPrevFocus)
994 struct list *cursor;
995 ThreadMgr *This = impl_from_ITfThreadMgrEventSink(iface);
997 TRACE("(%p) %p %p\n",This,pdimFocus, pdimPrevFocus);
999 LIST_FOR_EACH(cursor, &This->ThreadMgrEventSink)
1001 ThreadMgrSink* sink = LIST_ENTRY(cursor,ThreadMgrSink,entry);
1002 ITfThreadMgrEventSink_OnSetFocus(sink->interfaces.pITfThreadMgrEventSink, pdimFocus, pdimPrevFocus);
1005 return S_OK;
1008 static WINAPI HRESULT ThreadMgrEventSink_OnPushContext(
1009 ITfThreadMgrEventSink *iface, ITfContext *pic)
1011 struct list *cursor;
1012 ThreadMgr *This = impl_from_ITfThreadMgrEventSink(iface);
1014 TRACE("(%p) %p\n",This,pic);
1016 LIST_FOR_EACH(cursor, &This->ThreadMgrEventSink)
1018 ThreadMgrSink* sink = LIST_ENTRY(cursor,ThreadMgrSink,entry);
1019 ITfThreadMgrEventSink_OnPushContext(sink->interfaces.pITfThreadMgrEventSink,pic);
1022 return S_OK;
1025 static WINAPI HRESULT ThreadMgrEventSink_OnPopContext(
1026 ITfThreadMgrEventSink *iface, ITfContext *pic)
1028 struct list *cursor;
1029 ThreadMgr *This = impl_from_ITfThreadMgrEventSink(iface);
1031 TRACE("(%p) %p\n",This,pic);
1033 LIST_FOR_EACH(cursor, &This->ThreadMgrEventSink)
1035 ThreadMgrSink* sink = LIST_ENTRY(cursor,ThreadMgrSink,entry);
1036 ITfThreadMgrEventSink_OnPopContext(sink->interfaces.pITfThreadMgrEventSink,pic);
1039 return S_OK;
1042 static const ITfThreadMgrEventSinkVtbl ThreadMgr_ThreadMgrEventSinkVtbl =
1044 ThreadMgrEventSink_QueryInterface,
1045 ThreadMgrEventSink_AddRef,
1046 ThreadMgrEventSink_Release,
1048 ThreadMgrEventSink_OnInitDocumentMgr,
1049 ThreadMgrEventSink_OnUninitDocumentMgr,
1050 ThreadMgrEventSink_OnSetFocus,
1051 ThreadMgrEventSink_OnPushContext,
1052 ThreadMgrEventSink_OnPopContext
1055 HRESULT ThreadMgr_Constructor(IUnknown *pUnkOuter, IUnknown **ppOut)
1057 ThreadMgr *This;
1058 if (pUnkOuter)
1059 return CLASS_E_NOAGGREGATION;
1061 /* Only 1 ThreadMgr is created per thread */
1062 This = TlsGetValue(tlsIndex);
1063 if (This)
1065 ThreadMgr_AddRef((ITfThreadMgr*)This);
1066 *ppOut = (IUnknown*)This;
1067 return S_OK;
1070 This = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(ThreadMgr));
1071 if (This == NULL)
1072 return E_OUTOFMEMORY;
1074 This->ThreadMgrVtbl= &ThreadMgr_ThreadMgrVtbl;
1075 This->SourceVtbl = &ThreadMgr_SourceVtbl;
1076 This->KeystrokeMgrVtbl= &ThreadMgr_KeystrokeMgrVtbl;
1077 This->MessagePumpVtbl= &ThreadMgr_MessagePumpVtbl;
1078 This->ClientIdVtbl = &ThreadMgr_ClientIdVtbl;
1079 This->ThreadMgrEventSinkVtbl = &ThreadMgr_ThreadMgrEventSinkVtbl;
1080 This->refCount = 1;
1081 TlsSetValue(tlsIndex,This);
1083 CompartmentMgr_Constructor((IUnknown*)This, &IID_IUnknown, (IUnknown**)&This->CompartmentMgr);
1085 list_init(&This->CurrentPreservedKeys);
1087 list_init(&This->ActiveLanguageProfileNotifySink);
1088 list_init(&This->DisplayAttributeNotifySink);
1089 list_init(&This->KeyTraceEventSink);
1090 list_init(&This->PreservedKeyNotifySink);
1091 list_init(&This->ThreadFocusSink);
1092 list_init(&This->ThreadMgrEventSink);
1094 TRACE("returning %p\n", This);
1095 *ppOut = (IUnknown *)This;
1096 return S_OK;