TESTING -- override pthreads to fix gstreamer v5
[wine/multimedia.git] / dlls / msctf / threadmgr.c
blob3f0e7f6cef80c4629668ecadb5885d76e728080f
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 tagDocumentMgrs
70 struct list entry;
71 ITfDocumentMgr *docmgr;
72 } DocumentMgrEntry;
74 typedef struct tagAssociatedWindow
76 struct list entry;
77 HWND hwnd;
78 ITfDocumentMgr *docmgr;
79 } AssociatedWindow;
81 typedef struct tagACLMulti {
82 ITfThreadMgrEx ITfThreadMgrEx_iface;
83 ITfSource ITfSource_iface;
84 ITfKeystrokeMgr ITfKeystrokeMgr_iface;
85 ITfMessagePump ITfMessagePump_iface;
86 ITfClientId ITfClientId_iface;
87 /* const ITfThreadMgrExVtbl *ThreadMgrExVtbl; */
88 /* const ITfConfigureSystemKeystrokeFeedVtbl *ConfigureSystemKeystrokeFeedVtbl; */
89 /* const ITfLangBarItemMgrVtbl *LangBarItemMgrVtbl; */
90 ITfUIElementMgr ITfUIElementMgr_iface;
91 ITfSourceSingle ITfSourceSingle_iface;
92 LONG refCount;
94 /* Aggregation */
95 ITfCompartmentMgr *CompartmentMgr;
97 ITfThreadMgrEventSink ITfThreadMgrEventSink_iface; /* internal */
99 ITfDocumentMgr *focus;
100 LONG activationCount;
102 ITfKeyEventSink *forgroundKeyEventSink;
103 CLSID forgroundTextService;
105 struct list CurrentPreservedKeys;
106 struct list CreatedDocumentMgrs;
108 struct list AssociatedFocusWindows;
109 HHOOK focusHook;
111 /* kept as separate lists to reduce unnecessary iterations */
112 struct list ActiveLanguageProfileNotifySink;
113 struct list DisplayAttributeNotifySink;
114 struct list KeyTraceEventSink;
115 struct list PreservedKeyNotifySink;
116 struct list ThreadFocusSink;
117 struct list ThreadMgrEventSink;
118 } ThreadMgr;
120 typedef struct tagEnumTfDocumentMgr {
121 IEnumTfDocumentMgrs IEnumTfDocumentMgrs_iface;
122 LONG refCount;
124 struct list *index;
125 struct list *head;
126 } EnumTfDocumentMgr;
128 static HRESULT EnumTfDocumentMgr_Constructor(struct list* head, IEnumTfDocumentMgrs **ppOut);
130 static inline ThreadMgr *impl_from_ITfThreadMgrEx(ITfThreadMgrEx *iface)
132 return CONTAINING_RECORD(iface, ThreadMgr, ITfThreadMgrEx_iface);
135 static inline ThreadMgr *impl_from_ITfSource(ITfSource *iface)
137 return CONTAINING_RECORD(iface, ThreadMgr, ITfSource_iface);
140 static inline ThreadMgr *impl_from_ITfKeystrokeMgr(ITfKeystrokeMgr *iface)
142 return CONTAINING_RECORD(iface, ThreadMgr, ITfKeystrokeMgr_iface);
145 static inline ThreadMgr *impl_from_ITfMessagePump(ITfMessagePump *iface)
147 return CONTAINING_RECORD(iface, ThreadMgr, ITfMessagePump_iface);
150 static inline ThreadMgr *impl_from_ITfClientId(ITfClientId *iface)
152 return CONTAINING_RECORD(iface, ThreadMgr, ITfClientId_iface);
155 static inline ThreadMgr *impl_from_ITfThreadMgrEventSink(ITfThreadMgrEventSink *iface)
157 return CONTAINING_RECORD(iface, ThreadMgr, ITfThreadMgrEventSink_iface);
160 static inline ThreadMgr *impl_from_ITfUIElementMgr(ITfUIElementMgr *iface)
162 return CONTAINING_RECORD(iface, ThreadMgr, ITfUIElementMgr_iface);
165 static inline ThreadMgr *impl_from_ITfSourceSingle(ITfSourceSingle *iface)
167 return CONTAINING_RECORD(iface, ThreadMgr, ITfSourceSingle_iface);
170 static inline EnumTfDocumentMgr *impl_from_IEnumTfDocumentMgrs(IEnumTfDocumentMgrs *iface)
172 return CONTAINING_RECORD(iface, EnumTfDocumentMgr, IEnumTfDocumentMgrs_iface);
175 static void free_sink(ThreadMgrSink *sink)
177 IUnknown_Release(sink->interfaces.pIUnknown);
178 HeapFree(GetProcessHeap(),0,sink);
181 static void ThreadMgr_Destructor(ThreadMgr *This)
183 struct list *cursor, *cursor2;
185 /* unhook right away */
186 if (This->focusHook)
187 UnhookWindowsHookEx(This->focusHook);
189 TlsSetValue(tlsIndex,NULL);
190 TRACE("destroying %p\n", This);
191 if (This->focus)
192 ITfDocumentMgr_Release(This->focus);
194 /* free sinks */
195 LIST_FOR_EACH_SAFE(cursor, cursor2, &This->ActiveLanguageProfileNotifySink)
197 ThreadMgrSink* sink = LIST_ENTRY(cursor,ThreadMgrSink,entry);
198 list_remove(cursor);
199 free_sink(sink);
201 LIST_FOR_EACH_SAFE(cursor, cursor2, &This->DisplayAttributeNotifySink)
203 ThreadMgrSink* sink = LIST_ENTRY(cursor,ThreadMgrSink,entry);
204 list_remove(cursor);
205 free_sink(sink);
207 LIST_FOR_EACH_SAFE(cursor, cursor2, &This->KeyTraceEventSink)
209 ThreadMgrSink* sink = LIST_ENTRY(cursor,ThreadMgrSink,entry);
210 list_remove(cursor);
211 free_sink(sink);
213 LIST_FOR_EACH_SAFE(cursor, cursor2, &This->PreservedKeyNotifySink)
215 ThreadMgrSink* sink = LIST_ENTRY(cursor,ThreadMgrSink,entry);
216 list_remove(cursor);
217 free_sink(sink);
219 LIST_FOR_EACH_SAFE(cursor, cursor2, &This->ThreadFocusSink)
221 ThreadMgrSink* sink = LIST_ENTRY(cursor,ThreadMgrSink,entry);
222 list_remove(cursor);
223 free_sink(sink);
225 LIST_FOR_EACH_SAFE(cursor, cursor2, &This->ThreadMgrEventSink)
227 ThreadMgrSink* sink = LIST_ENTRY(cursor,ThreadMgrSink,entry);
228 list_remove(cursor);
229 free_sink(sink);
232 LIST_FOR_EACH_SAFE(cursor, cursor2, &This->CurrentPreservedKeys)
234 PreservedKey* key = LIST_ENTRY(cursor,PreservedKey,entry);
235 list_remove(cursor);
236 HeapFree(GetProcessHeap(),0,key->description);
237 HeapFree(GetProcessHeap(),0,key);
240 LIST_FOR_EACH_SAFE(cursor, cursor2, &This->CreatedDocumentMgrs)
242 DocumentMgrEntry *mgr = LIST_ENTRY(cursor,DocumentMgrEntry,entry);
243 list_remove(cursor);
244 FIXME("Left Over ITfDocumentMgr. Should we do something with it?\n");
245 HeapFree(GetProcessHeap(),0,mgr);
248 LIST_FOR_EACH_SAFE(cursor, cursor2, &This->AssociatedFocusWindows)
250 AssociatedWindow *wnd = LIST_ENTRY(cursor,AssociatedWindow,entry);
251 list_remove(cursor);
252 HeapFree(GetProcessHeap(),0,wnd);
255 CompartmentMgr_Destructor(This->CompartmentMgr);
257 HeapFree(GetProcessHeap(),0,This);
260 static HRESULT WINAPI ThreadMgr_QueryInterface(ITfThreadMgrEx *iface, REFIID iid, LPVOID *ppvOut)
262 ThreadMgr *This = impl_from_ITfThreadMgrEx(iface);
263 *ppvOut = NULL;
265 if (IsEqualIID(iid, &IID_IUnknown) || IsEqualIID(iid, &IID_ITfThreadMgr)
266 || IsEqualIID(iid, &IID_ITfThreadMgrEx))
268 *ppvOut = &This->ITfThreadMgrEx_iface;
270 else if (IsEqualIID(iid, &IID_ITfSource))
272 *ppvOut = &This->ITfSource_iface;
274 else if (IsEqualIID(iid, &IID_ITfKeystrokeMgr))
276 *ppvOut = &This->ITfKeystrokeMgr_iface;
278 else if (IsEqualIID(iid, &IID_ITfMessagePump))
280 *ppvOut = &This->ITfMessagePump_iface;
282 else if (IsEqualIID(iid, &IID_ITfClientId))
284 *ppvOut = &This->ITfClientId_iface;
286 else if (IsEqualIID(iid, &IID_ITfCompartmentMgr))
288 *ppvOut = This->CompartmentMgr;
290 else if (IsEqualIID(iid, &IID_ITfUIElementMgr))
292 *ppvOut = &This->ITfUIElementMgr_iface;
294 else if (IsEqualIID(iid, &IID_ITfSourceSingle))
296 *ppvOut = &This->ITfSourceSingle_iface;
299 if (*ppvOut)
301 ITfThreadMgrEx_AddRef(iface);
302 return S_OK;
305 WARN("unsupported interface: %s\n", debugstr_guid(iid));
306 return E_NOINTERFACE;
309 static ULONG WINAPI ThreadMgr_AddRef(ITfThreadMgrEx *iface)
311 ThreadMgr *This = impl_from_ITfThreadMgrEx(iface);
312 return InterlockedIncrement(&This->refCount);
315 static ULONG WINAPI ThreadMgr_Release(ITfThreadMgrEx *iface)
317 ThreadMgr *This = impl_from_ITfThreadMgrEx(iface);
318 ULONG ret;
320 ret = InterlockedDecrement(&This->refCount);
321 if (ret == 0)
322 ThreadMgr_Destructor(This);
323 return ret;
326 /*****************************************************
327 * ITfThreadMgr functions
328 *****************************************************/
330 static HRESULT WINAPI ThreadMgr_Activate(ITfThreadMgrEx *iface, TfClientId *id)
332 ThreadMgr *This = impl_from_ITfThreadMgrEx(iface);
334 TRACE("(%p) %p\n", This, id);
335 return ITfThreadMgrEx_ActivateEx(iface, id, 0);
338 static HRESULT WINAPI ThreadMgr_Deactivate(ITfThreadMgrEx *iface)
340 ThreadMgr *This = impl_from_ITfThreadMgrEx(iface);
341 TRACE("(%p)\n",This);
343 if (This->activationCount == 0)
344 return E_UNEXPECTED;
346 This->activationCount --;
348 if (This->activationCount == 0)
350 if (This->focus)
352 ITfThreadMgrEventSink_OnSetFocus(&This->ITfThreadMgrEventSink_iface, 0, This->focus);
353 ITfDocumentMgr_Release(This->focus);
354 This->focus = 0;
358 deactivate_textservices();
360 return S_OK;
363 static HRESULT WINAPI ThreadMgr_CreateDocumentMgr(ITfThreadMgrEx *iface, ITfDocumentMgr **ppdim)
365 ThreadMgr *This = impl_from_ITfThreadMgrEx(iface);
366 DocumentMgrEntry *mgrentry;
367 HRESULT hr;
369 TRACE("(%p)\n",iface);
370 mgrentry = HeapAlloc(GetProcessHeap(),0,sizeof(DocumentMgrEntry));
371 if (mgrentry == NULL)
372 return E_OUTOFMEMORY;
374 hr = DocumentMgr_Constructor(&This->ITfThreadMgrEventSink_iface, ppdim);
376 if (SUCCEEDED(hr))
378 mgrentry->docmgr = *ppdim;
379 list_add_head(&This->CreatedDocumentMgrs,&mgrentry->entry);
381 else
382 HeapFree(GetProcessHeap(),0,mgrentry);
384 return hr;
387 static HRESULT WINAPI ThreadMgr_EnumDocumentMgrs(ITfThreadMgrEx *iface, IEnumTfDocumentMgrs **ppEnum)
389 ThreadMgr *This = impl_from_ITfThreadMgrEx(iface);
390 TRACE("(%p) %p\n",This,ppEnum);
392 if (!ppEnum)
393 return E_INVALIDARG;
395 return EnumTfDocumentMgr_Constructor(&This->CreatedDocumentMgrs, ppEnum);
398 static HRESULT WINAPI ThreadMgr_GetFocus(ITfThreadMgrEx *iface, ITfDocumentMgr **ppdimFocus)
400 ThreadMgr *This = impl_from_ITfThreadMgrEx(iface);
401 TRACE("(%p)\n",This);
403 if (!ppdimFocus)
404 return E_INVALIDARG;
406 *ppdimFocus = This->focus;
408 TRACE("->%p\n",This->focus);
410 if (This->focus == NULL)
411 return S_FALSE;
413 ITfDocumentMgr_AddRef(This->focus);
415 return S_OK;
418 static HRESULT WINAPI ThreadMgr_SetFocus(ITfThreadMgrEx *iface, ITfDocumentMgr *pdimFocus)
420 ThreadMgr *This = impl_from_ITfThreadMgrEx(iface);
421 ITfDocumentMgr *check;
423 TRACE("(%p) %p\n",This,pdimFocus);
425 if (!pdimFocus)
426 check = NULL;
427 else if (FAILED(ITfDocumentMgr_QueryInterface(pdimFocus,&IID_ITfDocumentMgr,(LPVOID*) &check)))
428 return E_INVALIDARG;
430 ITfThreadMgrEventSink_OnSetFocus(&This->ITfThreadMgrEventSink_iface, check, This->focus);
432 if (This->focus)
433 ITfDocumentMgr_Release(This->focus);
435 This->focus = check;
436 return S_OK;
439 static LRESULT CALLBACK ThreadFocusHookProc(int nCode, WPARAM wParam, LPARAM lParam)
441 ThreadMgr *This;
443 This = TlsGetValue(tlsIndex);
444 if (!This)
446 ERR("Hook proc but no ThreadMgr for this thread. Serious Error\n");
447 return 0;
449 if (!This->focusHook)
451 ERR("Hook proc but no ThreadMgr focus Hook. Serious Error\n");
452 return 0;
455 if (nCode == HCBT_SETFOCUS) /* focus change within our thread */
457 struct list *cursor;
459 LIST_FOR_EACH(cursor, &This->AssociatedFocusWindows)
461 AssociatedWindow *wnd = LIST_ENTRY(cursor,AssociatedWindow,entry);
462 if (wnd->hwnd == (HWND)wParam)
464 TRACE("Triggering Associated window focus\n");
465 if (This->focus != wnd->docmgr)
466 ThreadMgr_SetFocus(&This->ITfThreadMgrEx_iface, wnd->docmgr);
467 break;
472 return CallNextHookEx(This->focusHook, nCode, wParam, lParam);
475 static HRESULT SetupWindowsHook(ThreadMgr *This)
477 if (!This->focusHook)
479 This->focusHook = SetWindowsHookExW(WH_CBT, ThreadFocusHookProc, 0,
480 GetCurrentThreadId());
481 if (!This->focusHook)
483 ERR("Unable to set focus hook\n");
484 return E_FAIL;
486 return S_OK;
488 return S_FALSE;
491 static HRESULT WINAPI ThreadMgr_AssociateFocus(ITfThreadMgrEx *iface, HWND hwnd,
492 ITfDocumentMgr *pdimNew, ITfDocumentMgr **ppdimPrev)
494 ThreadMgr *This = impl_from_ITfThreadMgrEx(iface);
495 struct list *cursor, *cursor2;
496 AssociatedWindow *wnd;
498 TRACE("(%p) %p %p %p\n",This,hwnd,pdimNew,ppdimPrev);
500 if (!ppdimPrev)
501 return E_INVALIDARG;
503 *ppdimPrev = NULL;
505 LIST_FOR_EACH_SAFE(cursor, cursor2, &This->AssociatedFocusWindows)
507 wnd = LIST_ENTRY(cursor,AssociatedWindow,entry);
508 if (wnd->hwnd == hwnd)
510 if (wnd->docmgr)
511 ITfDocumentMgr_AddRef(wnd->docmgr);
512 *ppdimPrev = wnd->docmgr;
513 wnd->docmgr = pdimNew;
514 if (GetFocus() == hwnd)
515 ThreadMgr_SetFocus(iface,pdimNew);
516 return S_OK;
520 wnd = HeapAlloc(GetProcessHeap(),0,sizeof(AssociatedWindow));
521 wnd->hwnd = hwnd;
522 wnd->docmgr = pdimNew;
523 list_add_head(&This->AssociatedFocusWindows,&wnd->entry);
525 if (GetFocus() == hwnd)
526 ThreadMgr_SetFocus(iface,pdimNew);
528 SetupWindowsHook(This);
530 return S_OK;
533 static HRESULT WINAPI ThreadMgr_IsThreadFocus(ITfThreadMgrEx *iface, BOOL *pfThreadFocus)
535 ThreadMgr *This = impl_from_ITfThreadMgrEx(iface);
536 HWND focus;
538 TRACE("(%p) %p\n",This,pfThreadFocus);
539 focus = GetFocus();
540 *pfThreadFocus = (focus == NULL);
541 return S_OK;
544 static HRESULT WINAPI ThreadMgr_GetFunctionProvider(ITfThreadMgrEx *iface, REFCLSID clsid,
545 ITfFunctionProvider **ppFuncProv)
547 ThreadMgr *This = impl_from_ITfThreadMgrEx(iface);
548 FIXME("STUB:(%p)\n",This);
549 return E_NOTIMPL;
552 static HRESULT WINAPI ThreadMgr_EnumFunctionProviders(ITfThreadMgrEx *iface,
553 IEnumTfFunctionProviders **ppEnum)
555 ThreadMgr *This = impl_from_ITfThreadMgrEx(iface);
556 FIXME("STUB:(%p)\n",This);
557 return E_NOTIMPL;
560 static HRESULT WINAPI ThreadMgr_GetGlobalCompartment(ITfThreadMgrEx *iface,
561 ITfCompartmentMgr **ppCompMgr)
563 ThreadMgr *This = impl_from_ITfThreadMgrEx(iface);
564 HRESULT hr;
565 TRACE("(%p) %p\n",This, ppCompMgr);
567 if (!ppCompMgr)
568 return E_INVALIDARG;
570 if (!globalCompartmentMgr)
572 hr = CompartmentMgr_Constructor(NULL,&IID_ITfCompartmentMgr,(IUnknown**)&globalCompartmentMgr);
573 if (FAILED(hr))
574 return hr;
577 ITfCompartmentMgr_AddRef(globalCompartmentMgr);
578 *ppCompMgr = globalCompartmentMgr;
579 return S_OK;
582 static HRESULT WINAPI ThreadMgr_ActivateEx(ITfThreadMgrEx *iface, TfClientId *id, DWORD flags)
584 ThreadMgr *This = impl_from_ITfThreadMgrEx(iface);
586 TRACE("(%p) %p, %#x\n", This, id, flags);
588 if (!id)
589 return E_INVALIDARG;
591 if (flags)
592 FIXME("Unimplemented flags %#x\n", flags);
594 if (!processId)
596 GUID guid;
597 CoCreateGuid(&guid);
598 ITfClientId_GetClientId(&This->ITfClientId_iface, &guid, &processId);
601 activate_textservices(iface);
602 This->activationCount++;
603 *id = processId;
604 return S_OK;
607 static HRESULT WINAPI ThreadMgr_GetActiveFlags(ITfThreadMgrEx *iface, DWORD *flags)
609 ThreadMgr *This = impl_from_ITfThreadMgrEx(iface);
611 FIXME("STUB:(%p)\n", This);
612 return E_NOTIMPL;
615 static const ITfThreadMgrExVtbl ThreadMgrExVtbl =
617 ThreadMgr_QueryInterface,
618 ThreadMgr_AddRef,
619 ThreadMgr_Release,
620 ThreadMgr_Activate,
621 ThreadMgr_Deactivate,
622 ThreadMgr_CreateDocumentMgr,
623 ThreadMgr_EnumDocumentMgrs,
624 ThreadMgr_GetFocus,
625 ThreadMgr_SetFocus,
626 ThreadMgr_AssociateFocus,
627 ThreadMgr_IsThreadFocus,
628 ThreadMgr_GetFunctionProvider,
629 ThreadMgr_EnumFunctionProviders,
630 ThreadMgr_GetGlobalCompartment,
632 ThreadMgr_ActivateEx,
633 ThreadMgr_GetActiveFlags
636 static HRESULT WINAPI Source_QueryInterface(ITfSource *iface, REFIID iid, LPVOID *ppvOut)
638 ThreadMgr *This = impl_from_ITfSource(iface);
639 return ITfThreadMgrEx_QueryInterface(&This->ITfThreadMgrEx_iface, iid, ppvOut);
642 static ULONG WINAPI Source_AddRef(ITfSource *iface)
644 ThreadMgr *This = impl_from_ITfSource(iface);
645 return ITfThreadMgrEx_AddRef(&This->ITfThreadMgrEx_iface);
648 static ULONG WINAPI Source_Release(ITfSource *iface)
650 ThreadMgr *This = impl_from_ITfSource(iface);
651 return ITfThreadMgrEx_Release(&This->ITfThreadMgrEx_iface);
654 /*****************************************************
655 * ITfSource functions
656 *****************************************************/
657 static HRESULT WINAPI ThreadMgrSource_AdviseSink(ITfSource *iface,
658 REFIID riid, IUnknown *punk, DWORD *pdwCookie)
660 ThreadMgr *This = impl_from_ITfSource(iface);
661 ThreadMgrSink *tms;
663 TRACE("(%p) %s %p %p\n",This,debugstr_guid(riid),punk,pdwCookie);
665 if (!riid || !punk || !pdwCookie)
666 return E_INVALIDARG;
668 if (IsEqualIID(riid, &IID_ITfThreadMgrEventSink))
670 tms = HeapAlloc(GetProcessHeap(),0,sizeof(ThreadMgrSink));
671 if (!tms)
672 return E_OUTOFMEMORY;
673 if (FAILED(IUnknown_QueryInterface(punk, riid, (LPVOID *)&tms->interfaces.pITfThreadMgrEventSink)))
675 HeapFree(GetProcessHeap(),0,tms);
676 return CONNECT_E_CANNOTCONNECT;
678 list_add_head(&This->ThreadMgrEventSink,&tms->entry);
679 *pdwCookie = generate_Cookie(COOKIE_MAGIC_TMSINK, tms);
681 else
683 FIXME("(%p) Unhandled Sink: %s\n",This,debugstr_guid(riid));
684 return E_NOTIMPL;
687 TRACE("cookie %x\n",*pdwCookie);
689 return S_OK;
692 static HRESULT WINAPI ThreadMgrSource_UnadviseSink(ITfSource *iface, DWORD pdwCookie)
694 ThreadMgr *This = impl_from_ITfSource(iface);
695 ThreadMgrSink *sink;
697 TRACE("(%p) %x\n",This,pdwCookie);
699 if (get_Cookie_magic(pdwCookie)!=COOKIE_MAGIC_TMSINK)
700 return E_INVALIDARG;
702 sink = remove_Cookie(pdwCookie);
703 if (!sink)
704 return CONNECT_E_NOCONNECTION;
706 list_remove(&sink->entry);
707 free_sink(sink);
709 return S_OK;
712 static const ITfSourceVtbl ThreadMgrSourceVtbl =
714 Source_QueryInterface,
715 Source_AddRef,
716 Source_Release,
717 ThreadMgrSource_AdviseSink,
718 ThreadMgrSource_UnadviseSink,
721 /*****************************************************
722 * ITfKeystrokeMgr functions
723 *****************************************************/
725 static HRESULT WINAPI KeystrokeMgr_QueryInterface(ITfKeystrokeMgr *iface, REFIID iid, LPVOID *ppvOut)
727 ThreadMgr *This = impl_from_ITfKeystrokeMgr(iface);
728 return ITfThreadMgrEx_QueryInterface(&This->ITfThreadMgrEx_iface, iid, ppvOut);
731 static ULONG WINAPI KeystrokeMgr_AddRef(ITfKeystrokeMgr *iface)
733 ThreadMgr *This = impl_from_ITfKeystrokeMgr(iface);
734 return ITfThreadMgrEx_AddRef(&This->ITfThreadMgrEx_iface);
737 static ULONG WINAPI KeystrokeMgr_Release(ITfKeystrokeMgr *iface)
739 ThreadMgr *This = impl_from_ITfKeystrokeMgr(iface);
740 return ITfThreadMgrEx_Release(&This->ITfThreadMgrEx_iface);
743 static HRESULT WINAPI KeystrokeMgr_AdviseKeyEventSink(ITfKeystrokeMgr *iface,
744 TfClientId tid, ITfKeyEventSink *pSink, BOOL fForeground)
746 ThreadMgr *This = impl_from_ITfKeystrokeMgr(iface);
747 CLSID textservice;
748 ITfKeyEventSink *check = NULL;
750 TRACE("(%p) %x %p %i\n",This,tid,pSink,fForeground);
752 if (!tid || !pSink)
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);
760 if (check != NULL)
761 return CONNECT_E_ADVISELIMIT;
763 if (FAILED(ITfKeyEventSink_QueryInterface(pSink,&IID_ITfKeyEventSink,(LPVOID*) &check)))
764 return E_INVALIDARG;
766 set_textservice_sink(tid, &IID_ITfKeyEventSink, (IUnknown*)check);
768 if (fForeground)
770 if (This->forgroundKeyEventSink)
772 ITfKeyEventSink_OnSetFocus(This->forgroundKeyEventSink, FALSE);
773 ITfKeyEventSink_Release(This->forgroundKeyEventSink);
775 ITfKeyEventSink_AddRef(check);
776 ITfKeyEventSink_OnSetFocus(check, TRUE);
777 This->forgroundKeyEventSink = check;
778 This->forgroundTextService = textservice;
780 return S_OK;
783 static HRESULT WINAPI KeystrokeMgr_UnadviseKeyEventSink(ITfKeystrokeMgr *iface,
784 TfClientId tid)
786 ThreadMgr *This = impl_from_ITfKeystrokeMgr(iface);
787 CLSID textservice;
788 ITfKeyEventSink *check = NULL;
789 TRACE("(%p) %x\n",This,tid);
791 if (!tid)
792 return E_INVALIDARG;
794 textservice = get_textservice_clsid(tid);
795 if (IsEqualCLSID(&GUID_NULL,&textservice))
796 return E_INVALIDARG;
798 get_textservice_sink(tid, &IID_ITfKeyEventSink, (IUnknown**)&check);
800 if (!check)
801 return CONNECT_E_NOCONNECTION;
803 set_textservice_sink(tid, &IID_ITfKeyEventSink, NULL);
804 ITfKeyEventSink_Release(check);
806 if (This->forgroundKeyEventSink == check)
808 ITfKeyEventSink_Release(This->forgroundKeyEventSink);
809 This->forgroundKeyEventSink = NULL;
810 This->forgroundTextService = GUID_NULL;
812 return S_OK;
815 static HRESULT WINAPI KeystrokeMgr_GetForeground(ITfKeystrokeMgr *iface,
816 CLSID *pclsid)
818 ThreadMgr *This = impl_from_ITfKeystrokeMgr(iface);
819 TRACE("(%p) %p\n",This,pclsid);
820 if (!pclsid)
821 return E_INVALIDARG;
823 if (IsEqualCLSID(&This->forgroundTextService,&GUID_NULL))
824 return S_FALSE;
826 *pclsid = This->forgroundTextService;
827 return S_OK;
830 static HRESULT WINAPI KeystrokeMgr_TestKeyDown(ITfKeystrokeMgr *iface,
831 WPARAM wParam, LPARAM lParam, BOOL *pfEaten)
833 ThreadMgr *This = impl_from_ITfKeystrokeMgr(iface);
834 FIXME("STUB:(%p)\n",This);
835 return E_NOTIMPL;
838 static HRESULT WINAPI KeystrokeMgr_TestKeyUp(ITfKeystrokeMgr *iface,
839 WPARAM wParam, LPARAM lParam, BOOL *pfEaten)
841 ThreadMgr *This = impl_from_ITfKeystrokeMgr(iface);
842 FIXME("STUB:(%p)\n",This);
843 return E_NOTIMPL;
846 static HRESULT WINAPI KeystrokeMgr_KeyDown(ITfKeystrokeMgr *iface,
847 WPARAM wParam, LPARAM lParam, BOOL *pfEaten)
849 ThreadMgr *This = impl_from_ITfKeystrokeMgr(iface);
850 FIXME("STUB:(%p)\n",This);
851 return E_NOTIMPL;
854 static HRESULT WINAPI KeystrokeMgr_KeyUp(ITfKeystrokeMgr *iface,
855 WPARAM wParam, LPARAM lParam, BOOL *pfEaten)
857 ThreadMgr *This = impl_from_ITfKeystrokeMgr(iface);
858 FIXME("STUB:(%p)\n",This);
859 return E_NOTIMPL;
862 static HRESULT WINAPI KeystrokeMgr_GetPreservedKey(ITfKeystrokeMgr *iface,
863 ITfContext *pic, const TF_PRESERVEDKEY *pprekey, GUID *pguid)
865 ThreadMgr *This = impl_from_ITfKeystrokeMgr(iface);
866 FIXME("STUB:(%p)\n",This);
867 return E_NOTIMPL;
870 static HRESULT WINAPI KeystrokeMgr_IsPreservedKey(ITfKeystrokeMgr *iface,
871 REFGUID rguid, const TF_PRESERVEDKEY *pprekey, BOOL *pfRegistered)
873 ThreadMgr *This = impl_from_ITfKeystrokeMgr(iface);
874 struct list *cursor;
876 TRACE("(%p) %s (%x %x) %p\n",This,debugstr_guid(rguid), (pprekey)?pprekey->uVKey:0, (pprekey)?pprekey->uModifiers:0, pfRegistered);
878 if (!rguid || !pprekey || !pfRegistered)
879 return E_INVALIDARG;
881 LIST_FOR_EACH(cursor, &This->CurrentPreservedKeys)
883 PreservedKey* key = LIST_ENTRY(cursor,PreservedKey,entry);
884 if (IsEqualGUID(rguid,&key->guid) && pprekey->uVKey == key->prekey.uVKey && pprekey->uModifiers == key->prekey.uModifiers)
886 *pfRegistered = TRUE;
887 return S_OK;
891 *pfRegistered = FALSE;
892 return S_FALSE;
895 static HRESULT WINAPI KeystrokeMgr_PreserveKey(ITfKeystrokeMgr *iface,
896 TfClientId tid, REFGUID rguid, const TF_PRESERVEDKEY *prekey,
897 const WCHAR *pchDesc, ULONG cchDesc)
899 ThreadMgr *This = impl_from_ITfKeystrokeMgr(iface);
900 struct list *cursor;
901 PreservedKey *newkey;
903 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));
905 if (!tid || ! rguid || !prekey || (cchDesc && !pchDesc))
906 return E_INVALIDARG;
908 LIST_FOR_EACH(cursor, &This->CurrentPreservedKeys)
910 PreservedKey* key = LIST_ENTRY(cursor,PreservedKey,entry);
911 if (IsEqualGUID(rguid,&key->guid) && prekey->uVKey == key->prekey.uVKey && prekey->uModifiers == key->prekey.uModifiers)
912 return TF_E_ALREADY_EXISTS;
915 newkey = HeapAlloc(GetProcessHeap(),0,sizeof(PreservedKey));
916 if (!newkey)
917 return E_OUTOFMEMORY;
919 newkey->guid = *rguid;
920 newkey->prekey = *prekey;
921 newkey->tid = tid;
922 newkey->description = NULL;
923 if (cchDesc)
925 newkey->description = HeapAlloc(GetProcessHeap(),0,cchDesc * sizeof(WCHAR));
926 if (!newkey->description)
928 HeapFree(GetProcessHeap(),0,newkey);
929 return E_OUTOFMEMORY;
931 memcpy(newkey->description, pchDesc, cchDesc*sizeof(WCHAR));
934 list_add_head(&This->CurrentPreservedKeys,&newkey->entry);
936 return S_OK;
939 static HRESULT WINAPI KeystrokeMgr_UnpreserveKey(ITfKeystrokeMgr *iface,
940 REFGUID rguid, const TF_PRESERVEDKEY *pprekey)
942 ThreadMgr *This = impl_from_ITfKeystrokeMgr(iface);
943 PreservedKey* key = NULL;
944 struct list *cursor;
945 TRACE("(%p) %s (%x %x)\n",This,debugstr_guid(rguid),(pprekey)?pprekey->uVKey:0, (pprekey)?pprekey->uModifiers:0);
947 if (!pprekey || !rguid)
948 return E_INVALIDARG;
950 LIST_FOR_EACH(cursor, &This->CurrentPreservedKeys)
952 key = LIST_ENTRY(cursor,PreservedKey,entry);
953 if (IsEqualGUID(rguid,&key->guid) && pprekey->uVKey == key->prekey.uVKey && pprekey->uModifiers == key->prekey.uModifiers)
954 break;
955 key = NULL;
958 if (!key)
959 return CONNECT_E_NOCONNECTION;
961 list_remove(&key->entry);
962 HeapFree(GetProcessHeap(),0,key->description);
963 HeapFree(GetProcessHeap(),0,key);
965 return S_OK;
968 static HRESULT WINAPI KeystrokeMgr_SetPreservedKeyDescription(ITfKeystrokeMgr *iface,
969 REFGUID rguid, const WCHAR *pchDesc, ULONG cchDesc)
971 ThreadMgr *This = impl_from_ITfKeystrokeMgr(iface);
972 FIXME("STUB:(%p)\n",This);
973 return E_NOTIMPL;
976 static HRESULT WINAPI KeystrokeMgr_GetPreservedKeyDescription(ITfKeystrokeMgr *iface,
977 REFGUID rguid, BSTR *pbstrDesc)
979 ThreadMgr *This = impl_from_ITfKeystrokeMgr(iface);
980 FIXME("STUB:(%p)\n",This);
981 return E_NOTIMPL;
984 static HRESULT WINAPI KeystrokeMgr_SimulatePreservedKey(ITfKeystrokeMgr *iface,
985 ITfContext *pic, REFGUID rguid, BOOL *pfEaten)
987 ThreadMgr *This = impl_from_ITfKeystrokeMgr(iface);
988 FIXME("STUB:(%p)\n",This);
989 return E_NOTIMPL;
992 static const ITfKeystrokeMgrVtbl KeystrokeMgrVtbl =
994 KeystrokeMgr_QueryInterface,
995 KeystrokeMgr_AddRef,
996 KeystrokeMgr_Release,
997 KeystrokeMgr_AdviseKeyEventSink,
998 KeystrokeMgr_UnadviseKeyEventSink,
999 KeystrokeMgr_GetForeground,
1000 KeystrokeMgr_TestKeyDown,
1001 KeystrokeMgr_TestKeyUp,
1002 KeystrokeMgr_KeyDown,
1003 KeystrokeMgr_KeyUp,
1004 KeystrokeMgr_GetPreservedKey,
1005 KeystrokeMgr_IsPreservedKey,
1006 KeystrokeMgr_PreserveKey,
1007 KeystrokeMgr_UnpreserveKey,
1008 KeystrokeMgr_SetPreservedKeyDescription,
1009 KeystrokeMgr_GetPreservedKeyDescription,
1010 KeystrokeMgr_SimulatePreservedKey
1013 /*****************************************************
1014 * ITfMessagePump functions
1015 *****************************************************/
1017 static HRESULT WINAPI MessagePump_QueryInterface(ITfMessagePump *iface, REFIID iid, LPVOID *ppvOut)
1019 ThreadMgr *This = impl_from_ITfMessagePump(iface);
1020 return ITfThreadMgrEx_QueryInterface(&This->ITfThreadMgrEx_iface, iid, ppvOut);
1023 static ULONG WINAPI MessagePump_AddRef(ITfMessagePump *iface)
1025 ThreadMgr *This = impl_from_ITfMessagePump(iface);
1026 return ITfThreadMgrEx_AddRef(&This->ITfThreadMgrEx_iface);
1029 static ULONG WINAPI MessagePump_Release(ITfMessagePump *iface)
1031 ThreadMgr *This = impl_from_ITfMessagePump(iface);
1032 return ITfThreadMgrEx_Release(&This->ITfThreadMgrEx_iface);
1035 static HRESULT WINAPI MessagePump_PeekMessageA(ITfMessagePump *iface,
1036 LPMSG pMsg, HWND hwnd, UINT wMsgFilterMin, UINT wMsgFilterMax,
1037 UINT wRemoveMsg, BOOL *pfResult)
1039 if (!pfResult)
1040 return E_INVALIDARG;
1041 *pfResult = PeekMessageA(pMsg, hwnd, wMsgFilterMin, wMsgFilterMax, wRemoveMsg);
1042 return S_OK;
1045 static HRESULT WINAPI MessagePump_GetMessageA(ITfMessagePump *iface,
1046 LPMSG pMsg, HWND hwnd, UINT wMsgFilterMin, UINT wMsgFilterMax,
1047 BOOL *pfResult)
1049 if (!pfResult)
1050 return E_INVALIDARG;
1051 *pfResult = GetMessageA(pMsg, hwnd, wMsgFilterMin, wMsgFilterMax);
1052 return S_OK;
1055 static HRESULT WINAPI MessagePump_PeekMessageW(ITfMessagePump *iface,
1056 LPMSG pMsg, HWND hwnd, UINT wMsgFilterMin, UINT wMsgFilterMax,
1057 UINT wRemoveMsg, BOOL *pfResult)
1059 if (!pfResult)
1060 return E_INVALIDARG;
1061 *pfResult = PeekMessageW(pMsg, hwnd, wMsgFilterMin, wMsgFilterMax, wRemoveMsg);
1062 return S_OK;
1065 static HRESULT WINAPI MessagePump_GetMessageW(ITfMessagePump *iface,
1066 LPMSG pMsg, HWND hwnd, UINT wMsgFilterMin, UINT wMsgFilterMax,
1067 BOOL *pfResult)
1069 if (!pfResult)
1070 return E_INVALIDARG;
1071 *pfResult = GetMessageW(pMsg, hwnd, wMsgFilterMin, wMsgFilterMax);
1072 return S_OK;
1075 static const ITfMessagePumpVtbl MessagePumpVtbl =
1077 MessagePump_QueryInterface,
1078 MessagePump_AddRef,
1079 MessagePump_Release,
1080 MessagePump_PeekMessageA,
1081 MessagePump_GetMessageA,
1082 MessagePump_PeekMessageW,
1083 MessagePump_GetMessageW
1086 /*****************************************************
1087 * ITfClientId functions
1088 *****************************************************/
1090 static HRESULT WINAPI ClientId_QueryInterface(ITfClientId *iface, REFIID iid, LPVOID *ppvOut)
1092 ThreadMgr *This = impl_from_ITfClientId(iface);
1093 return ITfThreadMgrEx_QueryInterface(&This->ITfThreadMgrEx_iface, iid, ppvOut);
1096 static ULONG WINAPI ClientId_AddRef(ITfClientId *iface)
1098 ThreadMgr *This = impl_from_ITfClientId(iface);
1099 return ITfThreadMgrEx_AddRef(&This->ITfThreadMgrEx_iface);
1102 static ULONG WINAPI ClientId_Release(ITfClientId *iface)
1104 ThreadMgr *This = impl_from_ITfClientId(iface);
1105 return ITfThreadMgrEx_Release(&This->ITfThreadMgrEx_iface);
1108 static HRESULT WINAPI ClientId_GetClientId(ITfClientId *iface,
1109 REFCLSID rclsid, TfClientId *ptid)
1112 ThreadMgr *This = impl_from_ITfClientId(iface);
1113 HRESULT hr;
1114 ITfCategoryMgr *catmgr;
1116 TRACE("(%p) %s\n",This,debugstr_guid(rclsid));
1118 CategoryMgr_Constructor(NULL,(IUnknown**)&catmgr);
1119 hr = ITfCategoryMgr_RegisterGUID(catmgr,rclsid,ptid);
1120 ITfCategoryMgr_Release(catmgr);
1122 return hr;
1125 static const ITfClientIdVtbl ClientIdVtbl =
1127 ClientId_QueryInterface,
1128 ClientId_AddRef,
1129 ClientId_Release,
1130 ClientId_GetClientId
1133 /*****************************************************
1134 * ITfThreadMgrEventSink functions (internal)
1135 *****************************************************/
1136 static HRESULT WINAPI ThreadMgrEventSink_QueryInterface(ITfThreadMgrEventSink *iface, REFIID iid, LPVOID *ppvOut)
1138 ThreadMgr *This = impl_from_ITfThreadMgrEventSink(iface);
1139 return ITfThreadMgrEx_QueryInterface(&This->ITfThreadMgrEx_iface, iid, ppvOut);
1142 static ULONG WINAPI ThreadMgrEventSink_AddRef(ITfThreadMgrEventSink *iface)
1144 ThreadMgr *This = impl_from_ITfThreadMgrEventSink(iface);
1145 return ITfThreadMgrEx_AddRef(&This->ITfThreadMgrEx_iface);
1148 static ULONG WINAPI ThreadMgrEventSink_Release(ITfThreadMgrEventSink *iface)
1150 ThreadMgr *This = impl_from_ITfThreadMgrEventSink(iface);
1151 return ITfThreadMgrEx_Release(&This->ITfThreadMgrEx_iface);
1155 static HRESULT WINAPI ThreadMgrEventSink_OnInitDocumentMgr(
1156 ITfThreadMgrEventSink *iface,ITfDocumentMgr *pdim)
1158 struct list *cursor;
1159 ThreadMgr *This = impl_from_ITfThreadMgrEventSink(iface);
1161 TRACE("(%p) %p\n",This,pdim);
1163 LIST_FOR_EACH(cursor, &This->ThreadMgrEventSink)
1165 ThreadMgrSink* sink = LIST_ENTRY(cursor,ThreadMgrSink,entry);
1166 ITfThreadMgrEventSink_OnInitDocumentMgr(sink->interfaces.pITfThreadMgrEventSink,pdim);
1169 return S_OK;
1172 static HRESULT WINAPI ThreadMgrEventSink_OnUninitDocumentMgr(
1173 ITfThreadMgrEventSink *iface, ITfDocumentMgr *pdim)
1175 struct list *cursor;
1176 ThreadMgr *This = impl_from_ITfThreadMgrEventSink(iface);
1178 TRACE("(%p) %p\n",This,pdim);
1180 LIST_FOR_EACH(cursor, &This->ThreadMgrEventSink)
1182 ThreadMgrSink* sink = LIST_ENTRY(cursor,ThreadMgrSink,entry);
1183 ITfThreadMgrEventSink_OnUninitDocumentMgr(sink->interfaces.pITfThreadMgrEventSink,pdim);
1186 return S_OK;
1189 static HRESULT WINAPI ThreadMgrEventSink_OnSetFocus(
1190 ITfThreadMgrEventSink *iface, ITfDocumentMgr *pdimFocus,
1191 ITfDocumentMgr *pdimPrevFocus)
1193 struct list *cursor;
1194 ThreadMgr *This = impl_from_ITfThreadMgrEventSink(iface);
1196 TRACE("(%p) %p %p\n",This,pdimFocus, pdimPrevFocus);
1198 LIST_FOR_EACH(cursor, &This->ThreadMgrEventSink)
1200 ThreadMgrSink* sink = LIST_ENTRY(cursor,ThreadMgrSink,entry);
1201 ITfThreadMgrEventSink_OnSetFocus(sink->interfaces.pITfThreadMgrEventSink, pdimFocus, pdimPrevFocus);
1204 return S_OK;
1207 static HRESULT WINAPI ThreadMgrEventSink_OnPushContext(
1208 ITfThreadMgrEventSink *iface, ITfContext *pic)
1210 struct list *cursor;
1211 ThreadMgr *This = impl_from_ITfThreadMgrEventSink(iface);
1213 TRACE("(%p) %p\n",This,pic);
1215 LIST_FOR_EACH(cursor, &This->ThreadMgrEventSink)
1217 ThreadMgrSink* sink = LIST_ENTRY(cursor,ThreadMgrSink,entry);
1218 ITfThreadMgrEventSink_OnPushContext(sink->interfaces.pITfThreadMgrEventSink,pic);
1221 return S_OK;
1224 static HRESULT WINAPI ThreadMgrEventSink_OnPopContext(
1225 ITfThreadMgrEventSink *iface, ITfContext *pic)
1227 struct list *cursor;
1228 ThreadMgr *This = impl_from_ITfThreadMgrEventSink(iface);
1230 TRACE("(%p) %p\n",This,pic);
1232 LIST_FOR_EACH(cursor, &This->ThreadMgrEventSink)
1234 ThreadMgrSink* sink = LIST_ENTRY(cursor,ThreadMgrSink,entry);
1235 ITfThreadMgrEventSink_OnPopContext(sink->interfaces.pITfThreadMgrEventSink,pic);
1238 return S_OK;
1241 static const ITfThreadMgrEventSinkVtbl ThreadMgrEventSinkVtbl =
1243 ThreadMgrEventSink_QueryInterface,
1244 ThreadMgrEventSink_AddRef,
1245 ThreadMgrEventSink_Release,
1246 ThreadMgrEventSink_OnInitDocumentMgr,
1247 ThreadMgrEventSink_OnUninitDocumentMgr,
1248 ThreadMgrEventSink_OnSetFocus,
1249 ThreadMgrEventSink_OnPushContext,
1250 ThreadMgrEventSink_OnPopContext
1253 /*****************************************************
1254 * ITfUIElementMgr functions
1255 *****************************************************/
1256 static HRESULT WINAPI UIElementMgr_QueryInterface(ITfUIElementMgr *iface, REFIID iid, void **ppvOut)
1258 ThreadMgr *This = impl_from_ITfUIElementMgr(iface);
1260 return ITfThreadMgrEx_QueryInterface(&This->ITfThreadMgrEx_iface, iid, *ppvOut);
1263 static ULONG WINAPI UIElementMgr_AddRef(ITfUIElementMgr *iface)
1265 ThreadMgr *This = impl_from_ITfUIElementMgr(iface);
1267 return ITfThreadMgrEx_AddRef(&This->ITfThreadMgrEx_iface);
1270 static ULONG WINAPI UIElementMgr_Release(ITfUIElementMgr *iface)
1272 ThreadMgr *This = impl_from_ITfUIElementMgr(iface);
1274 return ITfThreadMgrEx_Release(&This->ITfThreadMgrEx_iface);
1277 static HRESULT WINAPI UIElementMgr_BeginUIElement(ITfUIElementMgr *iface, ITfUIElement *element,
1278 BOOL *show, DWORD *id)
1280 ThreadMgr *This = impl_from_ITfUIElementMgr(iface);
1282 FIXME("STUB:(%p)\n", This);
1283 return E_NOTIMPL;
1286 static HRESULT WINAPI UIElementMgr_UpdateUIElement(ITfUIElementMgr *iface, DWORD id)
1288 ThreadMgr *This = impl_from_ITfUIElementMgr(iface);
1290 FIXME("STUB:(%p)\n", This);
1291 return E_NOTIMPL;
1294 static HRESULT WINAPI UIElementMgr_EndUIElement(ITfUIElementMgr *iface, DWORD id)
1296 ThreadMgr *This = impl_from_ITfUIElementMgr(iface);
1298 FIXME("STUB:(%p)\n", This);
1299 return E_NOTIMPL;
1302 static HRESULT WINAPI UIElementMgr_GetUIElement(ITfUIElementMgr *iface, DWORD id,
1303 ITfUIElement **element)
1305 ThreadMgr *This = impl_from_ITfUIElementMgr(iface);
1307 FIXME("STUB:(%p)\n", This);
1308 return E_NOTIMPL;
1311 static HRESULT WINAPI UIElementMgr_EnumUIElements(ITfUIElementMgr *iface,
1312 IEnumTfUIElements **enum_elements)
1314 ThreadMgr *This = impl_from_ITfUIElementMgr(iface);
1316 FIXME("STUB:(%p)\n", This);
1317 return E_NOTIMPL;
1320 static const ITfUIElementMgrVtbl ThreadMgrUIElementMgrVtbl =
1322 UIElementMgr_QueryInterface,
1323 UIElementMgr_AddRef,
1324 UIElementMgr_Release,
1326 UIElementMgr_BeginUIElement,
1327 UIElementMgr_UpdateUIElement,
1328 UIElementMgr_EndUIElement,
1329 UIElementMgr_GetUIElement,
1330 UIElementMgr_EnumUIElements
1333 /*****************************************************
1334 * ITfSourceSingle functions
1335 *****************************************************/
1336 static HRESULT WINAPI ThreadMgrSourceSingle_QueryInterface(ITfSourceSingle *iface, REFIID iid, LPVOID *ppvOut)
1338 ThreadMgr *This = impl_from_ITfSourceSingle(iface);
1339 return ITfThreadMgrEx_QueryInterface(&This->ITfThreadMgrEx_iface, iid, ppvOut);
1342 static ULONG WINAPI ThreadMgrSourceSingle_AddRef(ITfSourceSingle *iface)
1344 ThreadMgr *This = impl_from_ITfSourceSingle(iface);
1345 return ITfThreadMgrEx_AddRef(&This->ITfThreadMgrEx_iface);
1348 static ULONG WINAPI ThreadMgrSourceSingle_Release(ITfSourceSingle *iface)
1350 ThreadMgr *This = impl_from_ITfSourceSingle(iface);
1351 return ITfThreadMgrEx_Release(&This->ITfThreadMgrEx_iface);
1354 static HRESULT WINAPI ThreadMgrSourceSingle_AdviseSingleSink( ITfSourceSingle *iface,
1355 TfClientId tid, REFIID riid, IUnknown *punk)
1357 ThreadMgr *This = impl_from_ITfSourceSingle(iface);
1358 FIXME("STUB:(%p) %i %s %p\n",This, tid, debugstr_guid(riid),punk);
1359 return E_NOTIMPL;
1362 static HRESULT WINAPI ThreadMgrSourceSingle_UnadviseSingleSink( ITfSourceSingle *iface,
1363 TfClientId tid, REFIID riid)
1365 ThreadMgr *This = impl_from_ITfSourceSingle(iface);
1366 FIXME("STUB:(%p) %i %s\n",This, tid, debugstr_guid(riid));
1367 return E_NOTIMPL;
1370 static const ITfSourceSingleVtbl SourceSingleVtbl =
1372 ThreadMgrSourceSingle_QueryInterface,
1373 ThreadMgrSourceSingle_AddRef,
1374 ThreadMgrSourceSingle_Release,
1375 ThreadMgrSourceSingle_AdviseSingleSink,
1376 ThreadMgrSourceSingle_UnadviseSingleSink
1379 HRESULT ThreadMgr_Constructor(IUnknown *pUnkOuter, IUnknown **ppOut)
1381 ThreadMgr *This;
1382 if (pUnkOuter)
1383 return CLASS_E_NOAGGREGATION;
1385 /* Only 1 ThreadMgr is created per thread */
1386 This = TlsGetValue(tlsIndex);
1387 if (This)
1389 ThreadMgr_AddRef(&This->ITfThreadMgrEx_iface);
1390 *ppOut = (IUnknown*)&This->ITfThreadMgrEx_iface;
1391 return S_OK;
1394 This = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(ThreadMgr));
1395 if (This == NULL)
1396 return E_OUTOFMEMORY;
1398 This->ITfThreadMgrEx_iface.lpVtbl = &ThreadMgrExVtbl;
1399 This->ITfSource_iface.lpVtbl = &ThreadMgrSourceVtbl;
1400 This->ITfKeystrokeMgr_iface.lpVtbl = &KeystrokeMgrVtbl;
1401 This->ITfMessagePump_iface.lpVtbl = &MessagePumpVtbl;
1402 This->ITfClientId_iface.lpVtbl = &ClientIdVtbl;
1403 This->ITfThreadMgrEventSink_iface.lpVtbl = &ThreadMgrEventSinkVtbl;
1404 This->ITfUIElementMgr_iface.lpVtbl = &ThreadMgrUIElementMgrVtbl;
1405 This->ITfSourceSingle_iface.lpVtbl = &SourceSingleVtbl;
1406 This->refCount = 1;
1407 TlsSetValue(tlsIndex,This);
1409 CompartmentMgr_Constructor((IUnknown*)This, &IID_IUnknown, (IUnknown**)&This->CompartmentMgr);
1411 list_init(&This->CurrentPreservedKeys);
1412 list_init(&This->CreatedDocumentMgrs);
1413 list_init(&This->AssociatedFocusWindows);
1415 list_init(&This->ActiveLanguageProfileNotifySink);
1416 list_init(&This->DisplayAttributeNotifySink);
1417 list_init(&This->KeyTraceEventSink);
1418 list_init(&This->PreservedKeyNotifySink);
1419 list_init(&This->ThreadFocusSink);
1420 list_init(&This->ThreadMgrEventSink);
1422 TRACE("returning %p\n", This);
1423 *ppOut = (IUnknown *)&This->ITfThreadMgrEx_iface;
1424 return S_OK;
1427 /**************************************************
1428 * IEnumTfDocumentMgrs implementation
1429 **************************************************/
1430 static void EnumTfDocumentMgr_Destructor(EnumTfDocumentMgr *This)
1432 TRACE("destroying %p\n", This);
1433 HeapFree(GetProcessHeap(),0,This);
1436 static HRESULT WINAPI EnumTfDocumentMgr_QueryInterface(IEnumTfDocumentMgrs *iface, REFIID iid, LPVOID *ppvOut)
1438 EnumTfDocumentMgr *This = impl_from_IEnumTfDocumentMgrs(iface);
1439 *ppvOut = NULL;
1441 if (IsEqualIID(iid, &IID_IUnknown) || IsEqualIID(iid, &IID_IEnumTfDocumentMgrs))
1443 *ppvOut = &This->IEnumTfDocumentMgrs_iface;
1446 if (*ppvOut)
1448 IEnumTfDocumentMgrs_AddRef(iface);
1449 return S_OK;
1452 WARN("unsupported interface: %s\n", debugstr_guid(iid));
1453 return E_NOINTERFACE;
1456 static ULONG WINAPI EnumTfDocumentMgr_AddRef(IEnumTfDocumentMgrs *iface)
1458 EnumTfDocumentMgr *This = impl_from_IEnumTfDocumentMgrs(iface);
1459 return InterlockedIncrement(&This->refCount);
1462 static ULONG WINAPI EnumTfDocumentMgr_Release(IEnumTfDocumentMgrs *iface)
1464 EnumTfDocumentMgr *This = impl_from_IEnumTfDocumentMgrs(iface);
1465 ULONG ret;
1467 ret = InterlockedDecrement(&This->refCount);
1468 if (ret == 0)
1469 EnumTfDocumentMgr_Destructor(This);
1470 return ret;
1473 static HRESULT WINAPI EnumTfDocumentMgr_Next(IEnumTfDocumentMgrs *iface,
1474 ULONG ulCount, ITfDocumentMgr **rgDocumentMgr, ULONG *pcFetched)
1476 EnumTfDocumentMgr *This = impl_from_IEnumTfDocumentMgrs(iface);
1477 ULONG fetched = 0;
1479 TRACE("(%p)\n",This);
1481 if (rgDocumentMgr == NULL) return E_POINTER;
1483 while (fetched < ulCount)
1485 DocumentMgrEntry *mgrentry;
1486 if (This->index == NULL)
1487 break;
1489 mgrentry = LIST_ENTRY(This->index,DocumentMgrEntry,entry);
1490 if (mgrentry == NULL)
1491 break;
1493 *rgDocumentMgr = mgrentry->docmgr;
1494 ITfDocumentMgr_AddRef(*rgDocumentMgr);
1496 This->index = list_next(This->head, This->index);
1497 ++fetched;
1498 ++rgDocumentMgr;
1501 if (pcFetched) *pcFetched = fetched;
1502 return fetched == ulCount ? S_OK : S_FALSE;
1505 static HRESULT WINAPI EnumTfDocumentMgr_Skip( IEnumTfDocumentMgrs* iface, ULONG celt)
1507 EnumTfDocumentMgr *This = impl_from_IEnumTfDocumentMgrs(iface);
1508 ULONG i;
1510 TRACE("(%p)\n",This);
1511 for(i = 0; i < celt && This->index != NULL; i++)
1512 This->index = list_next(This->head, This->index);
1513 return S_OK;
1516 static HRESULT WINAPI EnumTfDocumentMgr_Reset( IEnumTfDocumentMgrs* iface)
1518 EnumTfDocumentMgr *This = impl_from_IEnumTfDocumentMgrs(iface);
1519 TRACE("(%p)\n",This);
1520 This->index = list_head(This->head);
1521 return S_OK;
1524 static HRESULT WINAPI EnumTfDocumentMgr_Clone( IEnumTfDocumentMgrs *iface,
1525 IEnumTfDocumentMgrs **ppenum)
1527 EnumTfDocumentMgr *This = impl_from_IEnumTfDocumentMgrs(iface);
1528 HRESULT res;
1530 TRACE("(%p)\n",This);
1532 if (ppenum == NULL) return E_POINTER;
1534 res = EnumTfDocumentMgr_Constructor(This->head, ppenum);
1535 if (SUCCEEDED(res))
1537 EnumTfDocumentMgr *new_This = impl_from_IEnumTfDocumentMgrs(*ppenum);
1538 new_This->index = This->index;
1540 return res;
1543 static const IEnumTfDocumentMgrsVtbl EnumTfDocumentMgrsVtbl =
1545 EnumTfDocumentMgr_QueryInterface,
1546 EnumTfDocumentMgr_AddRef,
1547 EnumTfDocumentMgr_Release,
1548 EnumTfDocumentMgr_Clone,
1549 EnumTfDocumentMgr_Next,
1550 EnumTfDocumentMgr_Reset,
1551 EnumTfDocumentMgr_Skip
1554 static HRESULT EnumTfDocumentMgr_Constructor(struct list* head, IEnumTfDocumentMgrs **ppOut)
1556 EnumTfDocumentMgr *This;
1558 This = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(EnumTfDocumentMgr));
1559 if (This == NULL)
1560 return E_OUTOFMEMORY;
1562 This->IEnumTfDocumentMgrs_iface.lpVtbl= &EnumTfDocumentMgrsVtbl;
1563 This->refCount = 1;
1564 This->head = head;
1565 This->index = list_head(This->head);
1567 TRACE("returning %p\n", This);
1568 *ppOut = (IEnumTfDocumentMgrs*)This;
1569 return S_OK;
1572 void ThreadMgr_OnDocumentMgrDestruction(ITfThreadMgr *iface, ITfDocumentMgr *mgr)
1574 ThreadMgr *This = impl_from_ITfThreadMgrEx((ITfThreadMgrEx *)iface);
1575 struct list *cursor;
1576 LIST_FOR_EACH(cursor, &This->CreatedDocumentMgrs)
1578 DocumentMgrEntry *mgrentry = LIST_ENTRY(cursor,DocumentMgrEntry,entry);
1579 if (mgrentry->docmgr == mgr)
1581 list_remove(cursor);
1582 HeapFree(GetProcessHeap(),0,mgrentry);
1583 return;
1586 FIXME("ITfDocumentMgr %p not found in this thread\n",mgr);