mfplat: Read queue subscriber within the critical section.
[wine/zf.git] / dlls / msctf / threadmgr.c
blob0e054d4e65495a8f10deb1a75d55f4f507a477ed
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 <stdarg.h>
23 #define COBJMACROS
25 #include "wine/debug.h"
26 #include "windef.h"
27 #include "winbase.h"
28 #include "winreg.h"
29 #include "winuser.h"
30 #include "shlwapi.h"
31 #include "winerror.h"
32 #include "objbase.h"
33 #include "olectl.h"
35 #include "msctf.h"
36 #include "msctf_internal.h"
38 WINE_DEFAULT_DEBUG_CHANNEL(msctf);
40 typedef struct tagPreservedKey
42 struct list entry;
43 GUID guid;
44 TF_PRESERVEDKEY prekey;
45 LPWSTR description;
46 TfClientId tid;
47 } PreservedKey;
49 typedef struct tagDocumentMgrs
51 struct list entry;
52 ITfDocumentMgr *docmgr;
53 } DocumentMgrEntry;
55 typedef struct tagAssociatedWindow
57 struct list entry;
58 HWND hwnd;
59 ITfDocumentMgr *docmgr;
60 } AssociatedWindow;
62 typedef struct tagACLMulti {
63 ITfThreadMgrEx ITfThreadMgrEx_iface;
64 ITfSource ITfSource_iface;
65 ITfKeystrokeMgr ITfKeystrokeMgr_iface;
66 ITfMessagePump ITfMessagePump_iface;
67 ITfClientId ITfClientId_iface;
68 /* const ITfThreadMgrExVtbl *ThreadMgrExVtbl; */
69 /* const ITfConfigureSystemKeystrokeFeedVtbl *ConfigureSystemKeystrokeFeedVtbl; */
70 /* const ITfLangBarItemMgrVtbl *LangBarItemMgrVtbl; */
71 ITfUIElementMgr ITfUIElementMgr_iface;
72 ITfSourceSingle ITfSourceSingle_iface;
73 LONG refCount;
75 /* Aggregation */
76 ITfCompartmentMgr *CompartmentMgr;
78 ITfThreadMgrEventSink ITfThreadMgrEventSink_iface; /* internal */
80 ITfDocumentMgr *focus;
81 LONG activationCount;
83 ITfKeyEventSink *foregroundKeyEventSink;
84 CLSID foregroundTextService;
86 struct list CurrentPreservedKeys;
87 struct list CreatedDocumentMgrs;
89 struct list AssociatedFocusWindows;
90 HHOOK focusHook;
92 /* kept as separate lists to reduce unnecessary iterations */
93 struct list ActiveLanguageProfileNotifySink;
94 struct list DisplayAttributeNotifySink;
95 struct list KeyTraceEventSink;
96 struct list PreservedKeyNotifySink;
97 struct list ThreadFocusSink;
98 struct list ThreadMgrEventSink;
99 struct list UIElementSink;
100 struct list InputProcessorProfileActivationSink;
101 } ThreadMgr;
103 typedef struct tagEnumTfDocumentMgr {
104 IEnumTfDocumentMgrs IEnumTfDocumentMgrs_iface;
105 LONG refCount;
107 struct list *index;
108 struct list *head;
109 } EnumTfDocumentMgr;
111 static HRESULT EnumTfDocumentMgr_Constructor(struct list* head, IEnumTfDocumentMgrs **ppOut);
113 static inline ThreadMgr *impl_from_ITfThreadMgrEx(ITfThreadMgrEx *iface)
115 return CONTAINING_RECORD(iface, ThreadMgr, ITfThreadMgrEx_iface);
118 static inline ThreadMgr *impl_from_ITfSource(ITfSource *iface)
120 return CONTAINING_RECORD(iface, ThreadMgr, ITfSource_iface);
123 static inline ThreadMgr *impl_from_ITfKeystrokeMgr(ITfKeystrokeMgr *iface)
125 return CONTAINING_RECORD(iface, ThreadMgr, ITfKeystrokeMgr_iface);
128 static inline ThreadMgr *impl_from_ITfMessagePump(ITfMessagePump *iface)
130 return CONTAINING_RECORD(iface, ThreadMgr, ITfMessagePump_iface);
133 static inline ThreadMgr *impl_from_ITfClientId(ITfClientId *iface)
135 return CONTAINING_RECORD(iface, ThreadMgr, ITfClientId_iface);
138 static inline ThreadMgr *impl_from_ITfThreadMgrEventSink(ITfThreadMgrEventSink *iface)
140 return CONTAINING_RECORD(iface, ThreadMgr, ITfThreadMgrEventSink_iface);
143 static inline ThreadMgr *impl_from_ITfUIElementMgr(ITfUIElementMgr *iface)
145 return CONTAINING_RECORD(iface, ThreadMgr, ITfUIElementMgr_iface);
148 static inline ThreadMgr *impl_from_ITfSourceSingle(ITfSourceSingle *iface)
150 return CONTAINING_RECORD(iface, ThreadMgr, ITfSourceSingle_iface);
153 static inline EnumTfDocumentMgr *impl_from_IEnumTfDocumentMgrs(IEnumTfDocumentMgrs *iface)
155 return CONTAINING_RECORD(iface, EnumTfDocumentMgr, IEnumTfDocumentMgrs_iface);
158 static void ThreadMgr_Destructor(ThreadMgr *This)
160 struct list *cursor, *cursor2;
162 /* unhook right away */
163 if (This->focusHook)
164 UnhookWindowsHookEx(This->focusHook);
166 TlsSetValue(tlsIndex,NULL);
167 TRACE("destroying %p\n", This);
168 if (This->focus)
169 ITfDocumentMgr_Release(This->focus);
171 free_sinks(&This->ActiveLanguageProfileNotifySink);
172 free_sinks(&This->DisplayAttributeNotifySink);
173 free_sinks(&This->KeyTraceEventSink);
174 free_sinks(&This->PreservedKeyNotifySink);
175 free_sinks(&This->ThreadFocusSink);
176 free_sinks(&This->ThreadMgrEventSink);
177 free_sinks(&This->UIElementSink);
178 free_sinks(&This->InputProcessorProfileActivationSink);
180 LIST_FOR_EACH_SAFE(cursor, cursor2, &This->CurrentPreservedKeys)
182 PreservedKey* key = LIST_ENTRY(cursor,PreservedKey,entry);
183 list_remove(cursor);
184 HeapFree(GetProcessHeap(),0,key->description);
185 HeapFree(GetProcessHeap(),0,key);
188 LIST_FOR_EACH_SAFE(cursor, cursor2, &This->CreatedDocumentMgrs)
190 DocumentMgrEntry *mgr = LIST_ENTRY(cursor,DocumentMgrEntry,entry);
191 list_remove(cursor);
192 FIXME("Left Over ITfDocumentMgr. Should we do something with it?\n");
193 HeapFree(GetProcessHeap(),0,mgr);
196 LIST_FOR_EACH_SAFE(cursor, cursor2, &This->AssociatedFocusWindows)
198 AssociatedWindow *wnd = LIST_ENTRY(cursor,AssociatedWindow,entry);
199 list_remove(cursor);
200 HeapFree(GetProcessHeap(),0,wnd);
203 CompartmentMgr_Destructor(This->CompartmentMgr);
205 HeapFree(GetProcessHeap(),0,This);
208 static HRESULT WINAPI ThreadMgr_QueryInterface(ITfThreadMgrEx *iface, REFIID iid, LPVOID *ppvOut)
210 ThreadMgr *This = impl_from_ITfThreadMgrEx(iface);
211 *ppvOut = NULL;
213 if (IsEqualIID(iid, &IID_IUnknown) || IsEqualIID(iid, &IID_ITfThreadMgr)
214 || IsEqualIID(iid, &IID_ITfThreadMgrEx))
216 *ppvOut = &This->ITfThreadMgrEx_iface;
218 else if (IsEqualIID(iid, &IID_ITfSource))
220 *ppvOut = &This->ITfSource_iface;
222 else if (IsEqualIID(iid, &IID_ITfKeystrokeMgr))
224 *ppvOut = &This->ITfKeystrokeMgr_iface;
226 else if (IsEqualIID(iid, &IID_ITfMessagePump))
228 *ppvOut = &This->ITfMessagePump_iface;
230 else if (IsEqualIID(iid, &IID_ITfClientId))
232 *ppvOut = &This->ITfClientId_iface;
234 else if (IsEqualIID(iid, &IID_ITfCompartmentMgr))
236 *ppvOut = This->CompartmentMgr;
238 else if (IsEqualIID(iid, &IID_ITfUIElementMgr))
240 *ppvOut = &This->ITfUIElementMgr_iface;
242 else if (IsEqualIID(iid, &IID_ITfSourceSingle))
244 *ppvOut = &This->ITfSourceSingle_iface;
247 if (*ppvOut)
249 ITfThreadMgrEx_AddRef(iface);
250 return S_OK;
253 WARN("unsupported interface: %s\n", debugstr_guid(iid));
254 return E_NOINTERFACE;
257 static ULONG WINAPI ThreadMgr_AddRef(ITfThreadMgrEx *iface)
259 ThreadMgr *This = impl_from_ITfThreadMgrEx(iface);
260 return InterlockedIncrement(&This->refCount);
263 static ULONG WINAPI ThreadMgr_Release(ITfThreadMgrEx *iface)
265 ThreadMgr *This = impl_from_ITfThreadMgrEx(iface);
266 ULONG ret;
268 ret = InterlockedDecrement(&This->refCount);
269 if (ret == 0)
270 ThreadMgr_Destructor(This);
271 return ret;
274 /*****************************************************
275 * ITfThreadMgr functions
276 *****************************************************/
278 static HRESULT WINAPI ThreadMgr_Activate(ITfThreadMgrEx *iface, TfClientId *id)
280 ThreadMgr *This = impl_from_ITfThreadMgrEx(iface);
282 TRACE("(%p) %p\n", This, id);
283 return ITfThreadMgrEx_ActivateEx(iface, id, 0);
286 static HRESULT WINAPI ThreadMgr_Deactivate(ITfThreadMgrEx *iface)
288 ThreadMgr *This = impl_from_ITfThreadMgrEx(iface);
289 TRACE("(%p)\n",This);
291 if (This->activationCount == 0)
292 return E_UNEXPECTED;
294 This->activationCount --;
296 if (This->activationCount == 0)
298 if (This->focus)
300 ITfThreadMgrEventSink_OnSetFocus(&This->ITfThreadMgrEventSink_iface, 0, This->focus);
301 ITfDocumentMgr_Release(This->focus);
302 This->focus = 0;
306 deactivate_textservices();
308 return S_OK;
311 static HRESULT WINAPI ThreadMgr_CreateDocumentMgr(ITfThreadMgrEx *iface, ITfDocumentMgr **ppdim)
313 ThreadMgr *This = impl_from_ITfThreadMgrEx(iface);
314 DocumentMgrEntry *mgrentry;
315 HRESULT hr;
317 TRACE("(%p)\n",iface);
318 mgrentry = HeapAlloc(GetProcessHeap(),0,sizeof(DocumentMgrEntry));
319 if (mgrentry == NULL)
320 return E_OUTOFMEMORY;
322 hr = DocumentMgr_Constructor(&This->ITfThreadMgrEventSink_iface, ppdim);
324 if (SUCCEEDED(hr))
326 mgrentry->docmgr = *ppdim;
327 list_add_head(&This->CreatedDocumentMgrs,&mgrentry->entry);
329 else
330 HeapFree(GetProcessHeap(),0,mgrentry);
332 return hr;
335 static HRESULT WINAPI ThreadMgr_EnumDocumentMgrs(ITfThreadMgrEx *iface, IEnumTfDocumentMgrs **ppEnum)
337 ThreadMgr *This = impl_from_ITfThreadMgrEx(iface);
338 TRACE("(%p) %p\n",This,ppEnum);
340 if (!ppEnum)
341 return E_INVALIDARG;
343 return EnumTfDocumentMgr_Constructor(&This->CreatedDocumentMgrs, ppEnum);
346 static HRESULT WINAPI ThreadMgr_GetFocus(ITfThreadMgrEx *iface, ITfDocumentMgr **ppdimFocus)
348 ThreadMgr *This = impl_from_ITfThreadMgrEx(iface);
349 TRACE("(%p)\n",This);
351 if (!ppdimFocus)
352 return E_INVALIDARG;
354 *ppdimFocus = This->focus;
356 TRACE("->%p\n",This->focus);
358 if (This->focus == NULL)
359 return S_FALSE;
361 ITfDocumentMgr_AddRef(This->focus);
363 return S_OK;
366 static HRESULT WINAPI ThreadMgr_SetFocus(ITfThreadMgrEx *iface, ITfDocumentMgr *pdimFocus)
368 ThreadMgr *This = impl_from_ITfThreadMgrEx(iface);
369 ITfDocumentMgr *check;
371 TRACE("(%p) %p\n",This,pdimFocus);
373 if (!pdimFocus)
374 check = NULL;
375 else if (FAILED(ITfDocumentMgr_QueryInterface(pdimFocus,&IID_ITfDocumentMgr,(LPVOID*) &check)))
376 return E_INVALIDARG;
378 ITfThreadMgrEventSink_OnSetFocus(&This->ITfThreadMgrEventSink_iface, check, This->focus);
380 if (This->focus)
381 ITfDocumentMgr_Release(This->focus);
383 This->focus = check;
384 return S_OK;
387 static LRESULT CALLBACK ThreadFocusHookProc(int nCode, WPARAM wParam, LPARAM lParam)
389 ThreadMgr *This;
391 This = TlsGetValue(tlsIndex);
392 if (!This)
394 ERR("Hook proc but no ThreadMgr for this thread. Serious Error\n");
395 return 0;
397 if (!This->focusHook)
399 ERR("Hook proc but no ThreadMgr focus Hook. Serious Error\n");
400 return 0;
403 if (nCode == HCBT_SETFOCUS) /* focus change within our thread */
405 struct list *cursor;
407 LIST_FOR_EACH(cursor, &This->AssociatedFocusWindows)
409 AssociatedWindow *wnd = LIST_ENTRY(cursor,AssociatedWindow,entry);
410 if (wnd->hwnd == (HWND)wParam)
412 TRACE("Triggering Associated window focus\n");
413 if (This->focus != wnd->docmgr)
414 ThreadMgr_SetFocus(&This->ITfThreadMgrEx_iface, wnd->docmgr);
415 break;
420 return CallNextHookEx(This->focusHook, nCode, wParam, lParam);
423 static HRESULT SetupWindowsHook(ThreadMgr *This)
425 if (!This->focusHook)
427 This->focusHook = SetWindowsHookExW(WH_CBT, ThreadFocusHookProc, 0,
428 GetCurrentThreadId());
429 if (!This->focusHook)
431 ERR("Unable to set focus hook\n");
432 return E_FAIL;
434 return S_OK;
436 return S_FALSE;
439 static HRESULT WINAPI ThreadMgr_AssociateFocus(ITfThreadMgrEx *iface, HWND hwnd,
440 ITfDocumentMgr *pdimNew, ITfDocumentMgr **ppdimPrev)
442 ThreadMgr *This = impl_from_ITfThreadMgrEx(iface);
443 struct list *cursor, *cursor2;
444 AssociatedWindow *wnd;
446 TRACE("(%p) %p %p %p\n",This,hwnd,pdimNew,ppdimPrev);
448 if (!ppdimPrev)
449 return E_INVALIDARG;
451 *ppdimPrev = NULL;
453 LIST_FOR_EACH_SAFE(cursor, cursor2, &This->AssociatedFocusWindows)
455 wnd = LIST_ENTRY(cursor,AssociatedWindow,entry);
456 if (wnd->hwnd == hwnd)
458 if (wnd->docmgr)
459 ITfDocumentMgr_AddRef(wnd->docmgr);
460 *ppdimPrev = wnd->docmgr;
461 wnd->docmgr = pdimNew;
462 if (GetFocus() == hwnd)
463 ThreadMgr_SetFocus(iface,pdimNew);
464 return S_OK;
468 wnd = HeapAlloc(GetProcessHeap(),0,sizeof(AssociatedWindow));
469 wnd->hwnd = hwnd;
470 wnd->docmgr = pdimNew;
471 list_add_head(&This->AssociatedFocusWindows,&wnd->entry);
473 if (GetFocus() == hwnd)
474 ThreadMgr_SetFocus(iface,pdimNew);
476 SetupWindowsHook(This);
478 return S_OK;
481 static HRESULT WINAPI ThreadMgr_IsThreadFocus(ITfThreadMgrEx *iface, BOOL *pfThreadFocus)
483 ThreadMgr *This = impl_from_ITfThreadMgrEx(iface);
484 HWND focus;
486 TRACE("(%p) %p\n",This,pfThreadFocus);
487 focus = GetFocus();
488 *pfThreadFocus = (focus == NULL);
489 return S_OK;
492 static HRESULT WINAPI ThreadMgr_GetFunctionProvider(ITfThreadMgrEx *iface, REFCLSID clsid,
493 ITfFunctionProvider **ppFuncProv)
495 ThreadMgr *This = impl_from_ITfThreadMgrEx(iface);
496 FIXME("STUB:(%p)\n",This);
497 return E_NOTIMPL;
500 static HRESULT WINAPI ThreadMgr_EnumFunctionProviders(ITfThreadMgrEx *iface,
501 IEnumTfFunctionProviders **ppEnum)
503 ThreadMgr *This = impl_from_ITfThreadMgrEx(iface);
504 FIXME("STUB:(%p)\n",This);
505 return E_NOTIMPL;
508 static HRESULT WINAPI ThreadMgr_GetGlobalCompartment(ITfThreadMgrEx *iface,
509 ITfCompartmentMgr **ppCompMgr)
511 ThreadMgr *This = impl_from_ITfThreadMgrEx(iface);
512 HRESULT hr;
513 TRACE("(%p) %p\n",This, ppCompMgr);
515 if (!ppCompMgr)
516 return E_INVALIDARG;
518 if (!globalCompartmentMgr)
520 hr = CompartmentMgr_Constructor(NULL,&IID_ITfCompartmentMgr,(IUnknown**)&globalCompartmentMgr);
521 if (FAILED(hr))
522 return hr;
525 ITfCompartmentMgr_AddRef(globalCompartmentMgr);
526 *ppCompMgr = globalCompartmentMgr;
527 return S_OK;
530 static HRESULT WINAPI ThreadMgr_ActivateEx(ITfThreadMgrEx *iface, TfClientId *id, DWORD flags)
532 ThreadMgr *This = impl_from_ITfThreadMgrEx(iface);
534 TRACE("(%p) %p, %#x\n", This, id, flags);
536 if (!id)
537 return E_INVALIDARG;
539 if (flags)
540 FIXME("Unimplemented flags %#x\n", flags);
542 if (!processId)
544 GUID guid;
545 CoCreateGuid(&guid);
546 ITfClientId_GetClientId(&This->ITfClientId_iface, &guid, &processId);
549 activate_textservices(iface);
550 This->activationCount++;
551 *id = processId;
552 return S_OK;
555 static HRESULT WINAPI ThreadMgr_GetActiveFlags(ITfThreadMgrEx *iface, DWORD *flags)
557 ThreadMgr *This = impl_from_ITfThreadMgrEx(iface);
559 FIXME("STUB:(%p)\n", This);
560 return E_NOTIMPL;
563 static const ITfThreadMgrExVtbl ThreadMgrExVtbl =
565 ThreadMgr_QueryInterface,
566 ThreadMgr_AddRef,
567 ThreadMgr_Release,
568 ThreadMgr_Activate,
569 ThreadMgr_Deactivate,
570 ThreadMgr_CreateDocumentMgr,
571 ThreadMgr_EnumDocumentMgrs,
572 ThreadMgr_GetFocus,
573 ThreadMgr_SetFocus,
574 ThreadMgr_AssociateFocus,
575 ThreadMgr_IsThreadFocus,
576 ThreadMgr_GetFunctionProvider,
577 ThreadMgr_EnumFunctionProviders,
578 ThreadMgr_GetGlobalCompartment,
580 ThreadMgr_ActivateEx,
581 ThreadMgr_GetActiveFlags
584 static HRESULT WINAPI Source_QueryInterface(ITfSource *iface, REFIID iid, LPVOID *ppvOut)
586 ThreadMgr *This = impl_from_ITfSource(iface);
587 return ITfThreadMgrEx_QueryInterface(&This->ITfThreadMgrEx_iface, iid, ppvOut);
590 static ULONG WINAPI Source_AddRef(ITfSource *iface)
592 ThreadMgr *This = impl_from_ITfSource(iface);
593 return ITfThreadMgrEx_AddRef(&This->ITfThreadMgrEx_iface);
596 static ULONG WINAPI Source_Release(ITfSource *iface)
598 ThreadMgr *This = impl_from_ITfSource(iface);
599 return ITfThreadMgrEx_Release(&This->ITfThreadMgrEx_iface);
602 /*****************************************************
603 * ITfSource functions
604 *****************************************************/
605 static HRESULT WINAPI ThreadMgrSource_AdviseSink(ITfSource *iface,
606 REFIID riid, IUnknown *punk, DWORD *pdwCookie)
608 ThreadMgr *This = impl_from_ITfSource(iface);
610 TRACE("(%p) %s %p %p\n",This,debugstr_guid(riid),punk,pdwCookie);
612 if (!riid || !punk || !pdwCookie)
613 return E_INVALIDARG;
615 if (IsEqualIID(riid, &IID_ITfThreadMgrEventSink))
616 return advise_sink(&This->ThreadMgrEventSink, &IID_ITfThreadMgrEventSink, COOKIE_MAGIC_TMSINK, punk, pdwCookie);
618 if (IsEqualIID(riid, &IID_ITfThreadFocusSink))
620 WARN("semi-stub for ITfThreadFocusSink: sink won't be used.\n");
621 return advise_sink(&This->ThreadFocusSink, &IID_ITfThreadFocusSink, COOKIE_MAGIC_THREADFOCUSSINK, punk, pdwCookie);
624 if (IsEqualIID(riid, &IID_ITfActiveLanguageProfileNotifySink))
626 WARN("semi-stub for ITfActiveLanguageProfileNotifySink: sink won't be used.\n");
627 return advise_sink(&This->ActiveLanguageProfileNotifySink, &IID_ITfActiveLanguageProfileNotifySink,
628 COOKIE_MAGIC_ACTIVELANGSINK, punk, pdwCookie);
631 if (IsEqualIID(riid, &IID_ITfKeyTraceEventSink))
633 WARN("semi-stub for ITfKeyTraceEventSink: sink won't be used.\n");
634 return advise_sink(&This->KeyTraceEventSink, &IID_ITfKeyTraceEventSink,
635 COOKIE_MAGIC_KEYTRACESINK, punk, pdwCookie);
638 if (IsEqualIID(riid, &IID_ITfUIElementSink))
640 WARN("semi-stub for ITfUIElementSink: sink won't be used.\n");
641 return advise_sink(&This->UIElementSink, &IID_ITfUIElementSink,
642 COOKIE_MAGIC_UIELEMENTSINK, punk, pdwCookie);
645 if (IsEqualIID(riid, &IID_ITfInputProcessorProfileActivationSink))
647 WARN("semi-stub for ITfInputProcessorProfileActivationSink: sink won't be used.\n");
648 return advise_sink(&This->InputProcessorProfileActivationSink, &IID_ITfInputProcessorProfileActivationSink,
649 COOKIE_MAGIC_INPUTPROCESSORPROFILEACTIVATIONSINK, punk, pdwCookie);
652 FIXME("(%p) Unhandled Sink: %s\n",This,debugstr_guid(riid));
653 return E_NOTIMPL;
656 static HRESULT WINAPI ThreadMgrSource_UnadviseSink(ITfSource *iface, DWORD pdwCookie)
658 ThreadMgr *This = impl_from_ITfSource(iface);
659 DWORD magic;
661 TRACE("(%p) %x\n",This,pdwCookie);
663 magic = get_Cookie_magic(pdwCookie);
664 if (magic != COOKIE_MAGIC_TMSINK && magic != COOKIE_MAGIC_THREADFOCUSSINK
665 && magic != COOKIE_MAGIC_KEYTRACESINK && magic != COOKIE_MAGIC_UIELEMENTSINK
666 && magic != COOKIE_MAGIC_INPUTPROCESSORPROFILEACTIVATIONSINK
667 && magic != COOKIE_MAGIC_ACTIVELANGSINK)
668 return E_INVALIDARG;
670 return unadvise_sink(pdwCookie);
673 static const ITfSourceVtbl ThreadMgrSourceVtbl =
675 Source_QueryInterface,
676 Source_AddRef,
677 Source_Release,
678 ThreadMgrSource_AdviseSink,
679 ThreadMgrSource_UnadviseSink,
682 /*****************************************************
683 * ITfKeystrokeMgr functions
684 *****************************************************/
686 static HRESULT WINAPI KeystrokeMgr_QueryInterface(ITfKeystrokeMgr *iface, REFIID iid, LPVOID *ppvOut)
688 ThreadMgr *This = impl_from_ITfKeystrokeMgr(iface);
689 return ITfThreadMgrEx_QueryInterface(&This->ITfThreadMgrEx_iface, iid, ppvOut);
692 static ULONG WINAPI KeystrokeMgr_AddRef(ITfKeystrokeMgr *iface)
694 ThreadMgr *This = impl_from_ITfKeystrokeMgr(iface);
695 return ITfThreadMgrEx_AddRef(&This->ITfThreadMgrEx_iface);
698 static ULONG WINAPI KeystrokeMgr_Release(ITfKeystrokeMgr *iface)
700 ThreadMgr *This = impl_from_ITfKeystrokeMgr(iface);
701 return ITfThreadMgrEx_Release(&This->ITfThreadMgrEx_iface);
704 static HRESULT WINAPI KeystrokeMgr_AdviseKeyEventSink(ITfKeystrokeMgr *iface,
705 TfClientId tid, ITfKeyEventSink *pSink, BOOL fForeground)
707 ThreadMgr *This = impl_from_ITfKeystrokeMgr(iface);
708 CLSID textservice;
709 ITfKeyEventSink *check = NULL;
711 TRACE("(%p) %x %p %i\n",This,tid,pSink,fForeground);
713 if (!tid || !pSink)
714 return E_INVALIDARG;
716 textservice = get_textservice_clsid(tid);
717 if (IsEqualCLSID(&GUID_NULL,&textservice))
718 return E_INVALIDARG;
720 get_textservice_sink(tid, &IID_ITfKeyEventSink, (IUnknown**)&check);
721 if (check != NULL)
722 return CONNECT_E_ADVISELIMIT;
724 if (FAILED(ITfKeyEventSink_QueryInterface(pSink,&IID_ITfKeyEventSink,(LPVOID*) &check)))
725 return E_INVALIDARG;
727 set_textservice_sink(tid, &IID_ITfKeyEventSink, (IUnknown*)check);
729 if (fForeground)
731 if (This->foregroundKeyEventSink)
733 ITfKeyEventSink_OnSetFocus(This->foregroundKeyEventSink, FALSE);
734 ITfKeyEventSink_Release(This->foregroundKeyEventSink);
736 ITfKeyEventSink_AddRef(check);
737 ITfKeyEventSink_OnSetFocus(check, TRUE);
738 This->foregroundKeyEventSink = check;
739 This->foregroundTextService = textservice;
741 return S_OK;
744 static HRESULT WINAPI KeystrokeMgr_UnadviseKeyEventSink(ITfKeystrokeMgr *iface,
745 TfClientId tid)
747 ThreadMgr *This = impl_from_ITfKeystrokeMgr(iface);
748 CLSID textservice;
749 ITfKeyEventSink *check = NULL;
750 TRACE("(%p) %x\n",This,tid);
752 if (!tid)
753 return E_INVALIDARG;
755 textservice = get_textservice_clsid(tid);
756 if (IsEqualCLSID(&GUID_NULL,&textservice))
757 return E_INVALIDARG;
759 get_textservice_sink(tid, &IID_ITfKeyEventSink, (IUnknown**)&check);
761 if (!check)
762 return CONNECT_E_NOCONNECTION;
764 set_textservice_sink(tid, &IID_ITfKeyEventSink, NULL);
765 ITfKeyEventSink_Release(check);
767 if (This->foregroundKeyEventSink == check)
769 ITfKeyEventSink_Release(This->foregroundKeyEventSink);
770 This->foregroundKeyEventSink = NULL;
771 This->foregroundTextService = GUID_NULL;
773 return S_OK;
776 static HRESULT WINAPI KeystrokeMgr_GetForeground(ITfKeystrokeMgr *iface,
777 CLSID *pclsid)
779 ThreadMgr *This = impl_from_ITfKeystrokeMgr(iface);
780 TRACE("(%p) %p\n",This,pclsid);
781 if (!pclsid)
782 return E_INVALIDARG;
784 if (IsEqualCLSID(&This->foregroundTextService,&GUID_NULL))
785 return S_FALSE;
787 *pclsid = This->foregroundTextService;
788 return S_OK;
791 static HRESULT WINAPI KeystrokeMgr_TestKeyDown(ITfKeystrokeMgr *iface,
792 WPARAM wParam, LPARAM lParam, BOOL *pfEaten)
794 ThreadMgr *This = impl_from_ITfKeystrokeMgr(iface);
795 FIXME("STUB:(%p)\n",This);
796 *pfEaten = FALSE;
797 return S_OK;
800 static HRESULT WINAPI KeystrokeMgr_TestKeyUp(ITfKeystrokeMgr *iface,
801 WPARAM wParam, LPARAM lParam, BOOL *pfEaten)
803 ThreadMgr *This = impl_from_ITfKeystrokeMgr(iface);
804 FIXME("STUB:(%p)\n",This);
805 *pfEaten = FALSE;
806 return S_OK;
809 static HRESULT WINAPI KeystrokeMgr_KeyDown(ITfKeystrokeMgr *iface,
810 WPARAM wParam, LPARAM lParam, BOOL *pfEaten)
812 ThreadMgr *This = impl_from_ITfKeystrokeMgr(iface);
813 FIXME("STUB:(%p)\n",This);
814 return E_NOTIMPL;
817 static HRESULT WINAPI KeystrokeMgr_KeyUp(ITfKeystrokeMgr *iface,
818 WPARAM wParam, LPARAM lParam, BOOL *pfEaten)
820 ThreadMgr *This = impl_from_ITfKeystrokeMgr(iface);
821 FIXME("STUB:(%p)\n",This);
822 return E_NOTIMPL;
825 static HRESULT WINAPI KeystrokeMgr_GetPreservedKey(ITfKeystrokeMgr *iface,
826 ITfContext *pic, const TF_PRESERVEDKEY *pprekey, GUID *pguid)
828 ThreadMgr *This = impl_from_ITfKeystrokeMgr(iface);
829 FIXME("STUB:(%p)\n",This);
830 return E_NOTIMPL;
833 static HRESULT WINAPI KeystrokeMgr_IsPreservedKey(ITfKeystrokeMgr *iface,
834 REFGUID rguid, const TF_PRESERVEDKEY *pprekey, BOOL *pfRegistered)
836 ThreadMgr *This = impl_from_ITfKeystrokeMgr(iface);
837 struct list *cursor;
839 TRACE("(%p) %s (%x %x) %p\n",This,debugstr_guid(rguid), (pprekey)?pprekey->uVKey:0, (pprekey)?pprekey->uModifiers:0, pfRegistered);
841 if (!rguid || !pprekey || !pfRegistered)
842 return E_INVALIDARG;
844 LIST_FOR_EACH(cursor, &This->CurrentPreservedKeys)
846 PreservedKey* key = LIST_ENTRY(cursor,PreservedKey,entry);
847 if (IsEqualGUID(rguid,&key->guid) && pprekey->uVKey == key->prekey.uVKey && pprekey->uModifiers == key->prekey.uModifiers)
849 *pfRegistered = TRUE;
850 return S_OK;
854 *pfRegistered = FALSE;
855 return S_FALSE;
858 static HRESULT WINAPI KeystrokeMgr_PreserveKey(ITfKeystrokeMgr *iface,
859 TfClientId tid, REFGUID rguid, const TF_PRESERVEDKEY *prekey,
860 const WCHAR *pchDesc, ULONG cchDesc)
862 ThreadMgr *This = impl_from_ITfKeystrokeMgr(iface);
863 struct list *cursor;
864 PreservedKey *newkey;
866 TRACE("(%p) %x %s (%x,%x) %s\n",This,tid, debugstr_guid(rguid),(prekey)?prekey->uVKey:0,(prekey)?prekey->uModifiers:0,debugstr_wn(pchDesc,cchDesc));
868 if (!tid || ! rguid || !prekey || (cchDesc && !pchDesc))
869 return E_INVALIDARG;
871 LIST_FOR_EACH(cursor, &This->CurrentPreservedKeys)
873 PreservedKey* key = LIST_ENTRY(cursor,PreservedKey,entry);
874 if (IsEqualGUID(rguid,&key->guid) && prekey->uVKey == key->prekey.uVKey && prekey->uModifiers == key->prekey.uModifiers)
875 return TF_E_ALREADY_EXISTS;
878 newkey = HeapAlloc(GetProcessHeap(),0,sizeof(PreservedKey));
879 if (!newkey)
880 return E_OUTOFMEMORY;
882 newkey->guid = *rguid;
883 newkey->prekey = *prekey;
884 newkey->tid = tid;
885 newkey->description = NULL;
886 if (cchDesc)
888 newkey->description = HeapAlloc(GetProcessHeap(),0,cchDesc * sizeof(WCHAR));
889 if (!newkey->description)
891 HeapFree(GetProcessHeap(),0,newkey);
892 return E_OUTOFMEMORY;
894 memcpy(newkey->description, pchDesc, cchDesc*sizeof(WCHAR));
897 list_add_head(&This->CurrentPreservedKeys,&newkey->entry);
899 return S_OK;
902 static HRESULT WINAPI KeystrokeMgr_UnpreserveKey(ITfKeystrokeMgr *iface,
903 REFGUID rguid, const TF_PRESERVEDKEY *pprekey)
905 ThreadMgr *This = impl_from_ITfKeystrokeMgr(iface);
906 PreservedKey* key = NULL;
907 struct list *cursor;
908 TRACE("(%p) %s (%x %x)\n",This,debugstr_guid(rguid),(pprekey)?pprekey->uVKey:0, (pprekey)?pprekey->uModifiers:0);
910 if (!pprekey || !rguid)
911 return E_INVALIDARG;
913 LIST_FOR_EACH(cursor, &This->CurrentPreservedKeys)
915 key = LIST_ENTRY(cursor,PreservedKey,entry);
916 if (IsEqualGUID(rguid,&key->guid) && pprekey->uVKey == key->prekey.uVKey && pprekey->uModifiers == key->prekey.uModifiers)
917 break;
918 key = NULL;
921 if (!key)
922 return CONNECT_E_NOCONNECTION;
924 list_remove(&key->entry);
925 HeapFree(GetProcessHeap(),0,key->description);
926 HeapFree(GetProcessHeap(),0,key);
928 return S_OK;
931 static HRESULT WINAPI KeystrokeMgr_SetPreservedKeyDescription(ITfKeystrokeMgr *iface,
932 REFGUID rguid, const WCHAR *pchDesc, ULONG cchDesc)
934 ThreadMgr *This = impl_from_ITfKeystrokeMgr(iface);
935 FIXME("STUB:(%p)\n",This);
936 return E_NOTIMPL;
939 static HRESULT WINAPI KeystrokeMgr_GetPreservedKeyDescription(ITfKeystrokeMgr *iface,
940 REFGUID rguid, BSTR *pbstrDesc)
942 ThreadMgr *This = impl_from_ITfKeystrokeMgr(iface);
943 FIXME("STUB:(%p)\n",This);
944 return E_NOTIMPL;
947 static HRESULT WINAPI KeystrokeMgr_SimulatePreservedKey(ITfKeystrokeMgr *iface,
948 ITfContext *pic, REFGUID rguid, BOOL *pfEaten)
950 ThreadMgr *This = impl_from_ITfKeystrokeMgr(iface);
951 FIXME("STUB:(%p)\n",This);
952 return E_NOTIMPL;
955 static const ITfKeystrokeMgrVtbl KeystrokeMgrVtbl =
957 KeystrokeMgr_QueryInterface,
958 KeystrokeMgr_AddRef,
959 KeystrokeMgr_Release,
960 KeystrokeMgr_AdviseKeyEventSink,
961 KeystrokeMgr_UnadviseKeyEventSink,
962 KeystrokeMgr_GetForeground,
963 KeystrokeMgr_TestKeyDown,
964 KeystrokeMgr_TestKeyUp,
965 KeystrokeMgr_KeyDown,
966 KeystrokeMgr_KeyUp,
967 KeystrokeMgr_GetPreservedKey,
968 KeystrokeMgr_IsPreservedKey,
969 KeystrokeMgr_PreserveKey,
970 KeystrokeMgr_UnpreserveKey,
971 KeystrokeMgr_SetPreservedKeyDescription,
972 KeystrokeMgr_GetPreservedKeyDescription,
973 KeystrokeMgr_SimulatePreservedKey
976 /*****************************************************
977 * ITfMessagePump functions
978 *****************************************************/
980 static HRESULT WINAPI MessagePump_QueryInterface(ITfMessagePump *iface, REFIID iid, LPVOID *ppvOut)
982 ThreadMgr *This = impl_from_ITfMessagePump(iface);
983 return ITfThreadMgrEx_QueryInterface(&This->ITfThreadMgrEx_iface, iid, ppvOut);
986 static ULONG WINAPI MessagePump_AddRef(ITfMessagePump *iface)
988 ThreadMgr *This = impl_from_ITfMessagePump(iface);
989 return ITfThreadMgrEx_AddRef(&This->ITfThreadMgrEx_iface);
992 static ULONG WINAPI MessagePump_Release(ITfMessagePump *iface)
994 ThreadMgr *This = impl_from_ITfMessagePump(iface);
995 return ITfThreadMgrEx_Release(&This->ITfThreadMgrEx_iface);
998 static HRESULT WINAPI MessagePump_PeekMessageA(ITfMessagePump *iface,
999 LPMSG pMsg, HWND hwnd, UINT wMsgFilterMin, UINT wMsgFilterMax,
1000 UINT wRemoveMsg, BOOL *pfResult)
1002 if (!pfResult)
1003 return E_INVALIDARG;
1004 *pfResult = PeekMessageA(pMsg, hwnd, wMsgFilterMin, wMsgFilterMax, wRemoveMsg);
1005 return S_OK;
1008 static HRESULT WINAPI MessagePump_GetMessageA(ITfMessagePump *iface,
1009 LPMSG pMsg, HWND hwnd, UINT wMsgFilterMin, UINT wMsgFilterMax,
1010 BOOL *pfResult)
1012 if (!pfResult)
1013 return E_INVALIDARG;
1014 *pfResult = GetMessageA(pMsg, hwnd, wMsgFilterMin, wMsgFilterMax);
1015 return S_OK;
1018 static HRESULT WINAPI MessagePump_PeekMessageW(ITfMessagePump *iface,
1019 LPMSG pMsg, HWND hwnd, UINT wMsgFilterMin, UINT wMsgFilterMax,
1020 UINT wRemoveMsg, BOOL *pfResult)
1022 if (!pfResult)
1023 return E_INVALIDARG;
1024 *pfResult = PeekMessageW(pMsg, hwnd, wMsgFilterMin, wMsgFilterMax, wRemoveMsg);
1025 return S_OK;
1028 static HRESULT WINAPI MessagePump_GetMessageW(ITfMessagePump *iface,
1029 LPMSG pMsg, HWND hwnd, UINT wMsgFilterMin, UINT wMsgFilterMax,
1030 BOOL *pfResult)
1032 if (!pfResult)
1033 return E_INVALIDARG;
1034 *pfResult = GetMessageW(pMsg, hwnd, wMsgFilterMin, wMsgFilterMax);
1035 return S_OK;
1038 static const ITfMessagePumpVtbl MessagePumpVtbl =
1040 MessagePump_QueryInterface,
1041 MessagePump_AddRef,
1042 MessagePump_Release,
1043 MessagePump_PeekMessageA,
1044 MessagePump_GetMessageA,
1045 MessagePump_PeekMessageW,
1046 MessagePump_GetMessageW
1049 /*****************************************************
1050 * ITfClientId functions
1051 *****************************************************/
1053 static HRESULT WINAPI ClientId_QueryInterface(ITfClientId *iface, REFIID iid, LPVOID *ppvOut)
1055 ThreadMgr *This = impl_from_ITfClientId(iface);
1056 return ITfThreadMgrEx_QueryInterface(&This->ITfThreadMgrEx_iface, iid, ppvOut);
1059 static ULONG WINAPI ClientId_AddRef(ITfClientId *iface)
1061 ThreadMgr *This = impl_from_ITfClientId(iface);
1062 return ITfThreadMgrEx_AddRef(&This->ITfThreadMgrEx_iface);
1065 static ULONG WINAPI ClientId_Release(ITfClientId *iface)
1067 ThreadMgr *This = impl_from_ITfClientId(iface);
1068 return ITfThreadMgrEx_Release(&This->ITfThreadMgrEx_iface);
1071 static HRESULT WINAPI ClientId_GetClientId(ITfClientId *iface,
1072 REFCLSID rclsid, TfClientId *ptid)
1075 ThreadMgr *This = impl_from_ITfClientId(iface);
1076 HRESULT hr;
1077 ITfCategoryMgr *catmgr;
1079 TRACE("(%p) %s\n",This,debugstr_guid(rclsid));
1081 CategoryMgr_Constructor(NULL,(IUnknown**)&catmgr);
1082 hr = ITfCategoryMgr_RegisterGUID(catmgr,rclsid,ptid);
1083 ITfCategoryMgr_Release(catmgr);
1085 return hr;
1088 static const ITfClientIdVtbl ClientIdVtbl =
1090 ClientId_QueryInterface,
1091 ClientId_AddRef,
1092 ClientId_Release,
1093 ClientId_GetClientId
1096 /*****************************************************
1097 * ITfThreadMgrEventSink functions (internal)
1098 *****************************************************/
1099 static HRESULT WINAPI ThreadMgrEventSink_QueryInterface(ITfThreadMgrEventSink *iface, REFIID iid, LPVOID *ppvOut)
1101 ThreadMgr *This = impl_from_ITfThreadMgrEventSink(iface);
1102 return ITfThreadMgrEx_QueryInterface(&This->ITfThreadMgrEx_iface, iid, ppvOut);
1105 static ULONG WINAPI ThreadMgrEventSink_AddRef(ITfThreadMgrEventSink *iface)
1107 ThreadMgr *This = impl_from_ITfThreadMgrEventSink(iface);
1108 return ITfThreadMgrEx_AddRef(&This->ITfThreadMgrEx_iface);
1111 static ULONG WINAPI ThreadMgrEventSink_Release(ITfThreadMgrEventSink *iface)
1113 ThreadMgr *This = impl_from_ITfThreadMgrEventSink(iface);
1114 return ITfThreadMgrEx_Release(&This->ITfThreadMgrEx_iface);
1118 static HRESULT WINAPI ThreadMgrEventSink_OnInitDocumentMgr(
1119 ITfThreadMgrEventSink *iface,ITfDocumentMgr *pdim)
1121 ThreadMgr *This = impl_from_ITfThreadMgrEventSink(iface);
1122 ITfThreadMgrEventSink *sink;
1123 struct list *cursor;
1125 TRACE("(%p) %p\n",This,pdim);
1127 SINK_FOR_EACH(cursor, &This->ThreadMgrEventSink, ITfThreadMgrEventSink, sink)
1129 ITfThreadMgrEventSink_OnInitDocumentMgr(sink, pdim);
1132 return S_OK;
1135 static HRESULT WINAPI ThreadMgrEventSink_OnUninitDocumentMgr(
1136 ITfThreadMgrEventSink *iface, ITfDocumentMgr *pdim)
1138 ThreadMgr *This = impl_from_ITfThreadMgrEventSink(iface);
1139 ITfThreadMgrEventSink *sink;
1140 struct list *cursor;
1142 TRACE("(%p) %p\n",This,pdim);
1144 SINK_FOR_EACH(cursor, &This->ThreadMgrEventSink, ITfThreadMgrEventSink, sink)
1146 ITfThreadMgrEventSink_OnUninitDocumentMgr(sink, pdim);
1149 return S_OK;
1152 static HRESULT WINAPI ThreadMgrEventSink_OnSetFocus(
1153 ITfThreadMgrEventSink *iface, ITfDocumentMgr *pdimFocus,
1154 ITfDocumentMgr *pdimPrevFocus)
1156 ThreadMgr *This = impl_from_ITfThreadMgrEventSink(iface);
1157 ITfThreadMgrEventSink *sink;
1158 struct list *cursor;
1160 TRACE("(%p) %p %p\n",This,pdimFocus, pdimPrevFocus);
1162 SINK_FOR_EACH(cursor, &This->ThreadMgrEventSink, ITfThreadMgrEventSink, sink)
1164 ITfThreadMgrEventSink_OnSetFocus(sink, pdimFocus, pdimPrevFocus);
1167 return S_OK;
1170 static HRESULT WINAPI ThreadMgrEventSink_OnPushContext(
1171 ITfThreadMgrEventSink *iface, ITfContext *pic)
1173 ThreadMgr *This = impl_from_ITfThreadMgrEventSink(iface);
1174 ITfThreadMgrEventSink *sink;
1175 struct list *cursor;
1177 TRACE("(%p) %p\n",This,pic);
1179 SINK_FOR_EACH(cursor, &This->ThreadMgrEventSink, ITfThreadMgrEventSink, sink)
1181 ITfThreadMgrEventSink_OnPushContext(sink, pic);
1184 return S_OK;
1187 static HRESULT WINAPI ThreadMgrEventSink_OnPopContext(
1188 ITfThreadMgrEventSink *iface, ITfContext *pic)
1190 ThreadMgr *This = impl_from_ITfThreadMgrEventSink(iface);
1191 ITfThreadMgrEventSink *sink;
1192 struct list *cursor;
1194 TRACE("(%p) %p\n",This,pic);
1196 SINK_FOR_EACH(cursor, &This->ThreadMgrEventSink, ITfThreadMgrEventSink, sink)
1198 ITfThreadMgrEventSink_OnPopContext(sink, pic);
1201 return S_OK;
1204 static const ITfThreadMgrEventSinkVtbl ThreadMgrEventSinkVtbl =
1206 ThreadMgrEventSink_QueryInterface,
1207 ThreadMgrEventSink_AddRef,
1208 ThreadMgrEventSink_Release,
1209 ThreadMgrEventSink_OnInitDocumentMgr,
1210 ThreadMgrEventSink_OnUninitDocumentMgr,
1211 ThreadMgrEventSink_OnSetFocus,
1212 ThreadMgrEventSink_OnPushContext,
1213 ThreadMgrEventSink_OnPopContext
1216 /*****************************************************
1217 * ITfUIElementMgr functions
1218 *****************************************************/
1219 static HRESULT WINAPI UIElementMgr_QueryInterface(ITfUIElementMgr *iface, REFIID iid, void **ppvOut)
1221 ThreadMgr *This = impl_from_ITfUIElementMgr(iface);
1223 return ITfThreadMgrEx_QueryInterface(&This->ITfThreadMgrEx_iface, iid, ppvOut);
1226 static ULONG WINAPI UIElementMgr_AddRef(ITfUIElementMgr *iface)
1228 ThreadMgr *This = impl_from_ITfUIElementMgr(iface);
1230 return ITfThreadMgrEx_AddRef(&This->ITfThreadMgrEx_iface);
1233 static ULONG WINAPI UIElementMgr_Release(ITfUIElementMgr *iface)
1235 ThreadMgr *This = impl_from_ITfUIElementMgr(iface);
1237 return ITfThreadMgrEx_Release(&This->ITfThreadMgrEx_iface);
1240 static HRESULT WINAPI UIElementMgr_BeginUIElement(ITfUIElementMgr *iface, ITfUIElement *element,
1241 BOOL *show, DWORD *id)
1243 ThreadMgr *This = impl_from_ITfUIElementMgr(iface);
1245 FIXME("STUB:(%p)\n", This);
1246 return E_NOTIMPL;
1249 static HRESULT WINAPI UIElementMgr_UpdateUIElement(ITfUIElementMgr *iface, DWORD id)
1251 ThreadMgr *This = impl_from_ITfUIElementMgr(iface);
1253 FIXME("STUB:(%p)\n", This);
1254 return E_NOTIMPL;
1257 static HRESULT WINAPI UIElementMgr_EndUIElement(ITfUIElementMgr *iface, DWORD id)
1259 ThreadMgr *This = impl_from_ITfUIElementMgr(iface);
1261 FIXME("STUB:(%p)\n", This);
1262 return E_NOTIMPL;
1265 static HRESULT WINAPI UIElementMgr_GetUIElement(ITfUIElementMgr *iface, DWORD id,
1266 ITfUIElement **element)
1268 ThreadMgr *This = impl_from_ITfUIElementMgr(iface);
1270 FIXME("STUB:(%p)\n", This);
1271 return E_NOTIMPL;
1274 static HRESULT WINAPI UIElementMgr_EnumUIElements(ITfUIElementMgr *iface,
1275 IEnumTfUIElements **enum_elements)
1277 ThreadMgr *This = impl_from_ITfUIElementMgr(iface);
1279 FIXME("STUB:(%p)\n", This);
1280 return E_NOTIMPL;
1283 static const ITfUIElementMgrVtbl ThreadMgrUIElementMgrVtbl =
1285 UIElementMgr_QueryInterface,
1286 UIElementMgr_AddRef,
1287 UIElementMgr_Release,
1289 UIElementMgr_BeginUIElement,
1290 UIElementMgr_UpdateUIElement,
1291 UIElementMgr_EndUIElement,
1292 UIElementMgr_GetUIElement,
1293 UIElementMgr_EnumUIElements
1296 /*****************************************************
1297 * ITfSourceSingle functions
1298 *****************************************************/
1299 static HRESULT WINAPI ThreadMgrSourceSingle_QueryInterface(ITfSourceSingle *iface, REFIID iid, LPVOID *ppvOut)
1301 ThreadMgr *This = impl_from_ITfSourceSingle(iface);
1302 return ITfThreadMgrEx_QueryInterface(&This->ITfThreadMgrEx_iface, iid, ppvOut);
1305 static ULONG WINAPI ThreadMgrSourceSingle_AddRef(ITfSourceSingle *iface)
1307 ThreadMgr *This = impl_from_ITfSourceSingle(iface);
1308 return ITfThreadMgrEx_AddRef(&This->ITfThreadMgrEx_iface);
1311 static ULONG WINAPI ThreadMgrSourceSingle_Release(ITfSourceSingle *iface)
1313 ThreadMgr *This = impl_from_ITfSourceSingle(iface);
1314 return ITfThreadMgrEx_Release(&This->ITfThreadMgrEx_iface);
1317 static HRESULT WINAPI ThreadMgrSourceSingle_AdviseSingleSink( ITfSourceSingle *iface,
1318 TfClientId tid, REFIID riid, IUnknown *punk)
1320 ThreadMgr *This = impl_from_ITfSourceSingle(iface);
1321 FIXME("STUB:(%p) %i %s %p\n",This, tid, debugstr_guid(riid),punk);
1322 return E_NOTIMPL;
1325 static HRESULT WINAPI ThreadMgrSourceSingle_UnadviseSingleSink( ITfSourceSingle *iface,
1326 TfClientId tid, REFIID riid)
1328 ThreadMgr *This = impl_from_ITfSourceSingle(iface);
1329 FIXME("STUB:(%p) %i %s\n",This, tid, debugstr_guid(riid));
1330 return E_NOTIMPL;
1333 static const ITfSourceSingleVtbl SourceSingleVtbl =
1335 ThreadMgrSourceSingle_QueryInterface,
1336 ThreadMgrSourceSingle_AddRef,
1337 ThreadMgrSourceSingle_Release,
1338 ThreadMgrSourceSingle_AdviseSingleSink,
1339 ThreadMgrSourceSingle_UnadviseSingleSink
1342 HRESULT ThreadMgr_Constructor(IUnknown *pUnkOuter, IUnknown **ppOut)
1344 ThreadMgr *This;
1345 if (pUnkOuter)
1346 return CLASS_E_NOAGGREGATION;
1348 /* Only 1 ThreadMgr is created per thread */
1349 This = TlsGetValue(tlsIndex);
1350 if (This)
1352 ThreadMgr_AddRef(&This->ITfThreadMgrEx_iface);
1353 *ppOut = (IUnknown*)&This->ITfThreadMgrEx_iface;
1354 return S_OK;
1357 This = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(ThreadMgr));
1358 if (This == NULL)
1359 return E_OUTOFMEMORY;
1361 This->ITfThreadMgrEx_iface.lpVtbl = &ThreadMgrExVtbl;
1362 This->ITfSource_iface.lpVtbl = &ThreadMgrSourceVtbl;
1363 This->ITfKeystrokeMgr_iface.lpVtbl = &KeystrokeMgrVtbl;
1364 This->ITfMessagePump_iface.lpVtbl = &MessagePumpVtbl;
1365 This->ITfClientId_iface.lpVtbl = &ClientIdVtbl;
1366 This->ITfThreadMgrEventSink_iface.lpVtbl = &ThreadMgrEventSinkVtbl;
1367 This->ITfUIElementMgr_iface.lpVtbl = &ThreadMgrUIElementMgrVtbl;
1368 This->ITfSourceSingle_iface.lpVtbl = &SourceSingleVtbl;
1369 This->refCount = 1;
1370 TlsSetValue(tlsIndex,This);
1372 CompartmentMgr_Constructor((IUnknown*)&This->ITfThreadMgrEx_iface, &IID_IUnknown, (IUnknown**)&This->CompartmentMgr);
1374 list_init(&This->CurrentPreservedKeys);
1375 list_init(&This->CreatedDocumentMgrs);
1376 list_init(&This->AssociatedFocusWindows);
1378 list_init(&This->ActiveLanguageProfileNotifySink);
1379 list_init(&This->DisplayAttributeNotifySink);
1380 list_init(&This->KeyTraceEventSink);
1381 list_init(&This->PreservedKeyNotifySink);
1382 list_init(&This->ThreadFocusSink);
1383 list_init(&This->ThreadMgrEventSink);
1384 list_init(&This->UIElementSink);
1385 list_init(&This->InputProcessorProfileActivationSink);
1387 TRACE("returning %p\n", This);
1388 *ppOut = (IUnknown *)&This->ITfThreadMgrEx_iface;
1389 return S_OK;
1392 /**************************************************
1393 * IEnumTfDocumentMgrs implementation
1394 **************************************************/
1395 static void EnumTfDocumentMgr_Destructor(EnumTfDocumentMgr *This)
1397 TRACE("destroying %p\n", This);
1398 HeapFree(GetProcessHeap(),0,This);
1401 static HRESULT WINAPI EnumTfDocumentMgr_QueryInterface(IEnumTfDocumentMgrs *iface, REFIID iid, LPVOID *ppvOut)
1403 EnumTfDocumentMgr *This = impl_from_IEnumTfDocumentMgrs(iface);
1404 *ppvOut = NULL;
1406 if (IsEqualIID(iid, &IID_IUnknown) || IsEqualIID(iid, &IID_IEnumTfDocumentMgrs))
1408 *ppvOut = &This->IEnumTfDocumentMgrs_iface;
1411 if (*ppvOut)
1413 IEnumTfDocumentMgrs_AddRef(iface);
1414 return S_OK;
1417 WARN("unsupported interface: %s\n", debugstr_guid(iid));
1418 return E_NOINTERFACE;
1421 static ULONG WINAPI EnumTfDocumentMgr_AddRef(IEnumTfDocumentMgrs *iface)
1423 EnumTfDocumentMgr *This = impl_from_IEnumTfDocumentMgrs(iface);
1424 return InterlockedIncrement(&This->refCount);
1427 static ULONG WINAPI EnumTfDocumentMgr_Release(IEnumTfDocumentMgrs *iface)
1429 EnumTfDocumentMgr *This = impl_from_IEnumTfDocumentMgrs(iface);
1430 ULONG ret;
1432 ret = InterlockedDecrement(&This->refCount);
1433 if (ret == 0)
1434 EnumTfDocumentMgr_Destructor(This);
1435 return ret;
1438 static HRESULT WINAPI EnumTfDocumentMgr_Next(IEnumTfDocumentMgrs *iface,
1439 ULONG ulCount, ITfDocumentMgr **rgDocumentMgr, ULONG *pcFetched)
1441 EnumTfDocumentMgr *This = impl_from_IEnumTfDocumentMgrs(iface);
1442 ULONG fetched = 0;
1444 TRACE("(%p)\n",This);
1446 if (rgDocumentMgr == NULL) return E_POINTER;
1448 while (fetched < ulCount)
1450 DocumentMgrEntry *mgrentry;
1451 if (This->index == NULL)
1452 break;
1454 mgrentry = LIST_ENTRY(This->index,DocumentMgrEntry,entry);
1455 if (mgrentry == NULL)
1456 break;
1458 *rgDocumentMgr = mgrentry->docmgr;
1459 ITfDocumentMgr_AddRef(*rgDocumentMgr);
1461 This->index = list_next(This->head, This->index);
1462 ++fetched;
1463 ++rgDocumentMgr;
1466 if (pcFetched) *pcFetched = fetched;
1467 return fetched == ulCount ? S_OK : S_FALSE;
1470 static HRESULT WINAPI EnumTfDocumentMgr_Skip( IEnumTfDocumentMgrs* iface, ULONG celt)
1472 EnumTfDocumentMgr *This = impl_from_IEnumTfDocumentMgrs(iface);
1473 ULONG i;
1475 TRACE("(%p)\n",This);
1476 for(i = 0; i < celt && This->index != NULL; i++)
1477 This->index = list_next(This->head, This->index);
1478 return S_OK;
1481 static HRESULT WINAPI EnumTfDocumentMgr_Reset( IEnumTfDocumentMgrs* iface)
1483 EnumTfDocumentMgr *This = impl_from_IEnumTfDocumentMgrs(iface);
1484 TRACE("(%p)\n",This);
1485 This->index = list_head(This->head);
1486 return S_OK;
1489 static HRESULT WINAPI EnumTfDocumentMgr_Clone( IEnumTfDocumentMgrs *iface,
1490 IEnumTfDocumentMgrs **ppenum)
1492 EnumTfDocumentMgr *This = impl_from_IEnumTfDocumentMgrs(iface);
1493 HRESULT res;
1495 TRACE("(%p)\n",This);
1497 if (ppenum == NULL) return E_POINTER;
1499 res = EnumTfDocumentMgr_Constructor(This->head, ppenum);
1500 if (SUCCEEDED(res))
1502 EnumTfDocumentMgr *new_This = impl_from_IEnumTfDocumentMgrs(*ppenum);
1503 new_This->index = This->index;
1505 return res;
1508 static const IEnumTfDocumentMgrsVtbl EnumTfDocumentMgrsVtbl =
1510 EnumTfDocumentMgr_QueryInterface,
1511 EnumTfDocumentMgr_AddRef,
1512 EnumTfDocumentMgr_Release,
1513 EnumTfDocumentMgr_Clone,
1514 EnumTfDocumentMgr_Next,
1515 EnumTfDocumentMgr_Reset,
1516 EnumTfDocumentMgr_Skip
1519 static HRESULT EnumTfDocumentMgr_Constructor(struct list* head, IEnumTfDocumentMgrs **ppOut)
1521 EnumTfDocumentMgr *This;
1523 This = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(EnumTfDocumentMgr));
1524 if (This == NULL)
1525 return E_OUTOFMEMORY;
1527 This->IEnumTfDocumentMgrs_iface.lpVtbl= &EnumTfDocumentMgrsVtbl;
1528 This->refCount = 1;
1529 This->head = head;
1530 This->index = list_head(This->head);
1532 TRACE("returning %p\n", &This->IEnumTfDocumentMgrs_iface);
1533 *ppOut = &This->IEnumTfDocumentMgrs_iface;
1534 return S_OK;
1537 void ThreadMgr_OnDocumentMgrDestruction(ITfThreadMgr *iface, ITfDocumentMgr *mgr)
1539 ThreadMgr *This = impl_from_ITfThreadMgrEx((ITfThreadMgrEx *)iface);
1540 struct list *cursor;
1541 BOOL found = FALSE;
1543 LIST_FOR_EACH(cursor, &This->CreatedDocumentMgrs)
1545 DocumentMgrEntry *mgrentry = LIST_ENTRY(cursor,DocumentMgrEntry,entry);
1546 if (mgrentry->docmgr == mgr)
1548 list_remove(cursor);
1549 HeapFree(GetProcessHeap(),0,mgrentry);
1550 found = TRUE;
1551 break;
1554 if (!found) FIXME("ITfDocumentMgr %p not found in this thread\n",mgr);
1556 LIST_FOR_EACH(cursor, &This->AssociatedFocusWindows)
1558 AssociatedWindow *wnd = LIST_ENTRY(cursor,AssociatedWindow,entry);
1559 if (wnd->docmgr == mgr)
1560 wnd->docmgr = NULL;