msctf: Remove incorrect dereference of double pointer.
[wine.git] / dlls / msctf / threadmgr.c
blob62ddfd253fec51276e674a1d5b9d50072385546a
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"
39 #include "msctf.h"
40 #include "msctf_internal.h"
42 WINE_DEFAULT_DEBUG_CHANNEL(msctf);
44 typedef struct tagPreservedKey
46 struct list entry;
47 GUID guid;
48 TF_PRESERVEDKEY prekey;
49 LPWSTR description;
50 TfClientId tid;
51 } PreservedKey;
53 typedef struct tagDocumentMgrs
55 struct list entry;
56 ITfDocumentMgr *docmgr;
57 } DocumentMgrEntry;
59 typedef struct tagAssociatedWindow
61 struct list entry;
62 HWND hwnd;
63 ITfDocumentMgr *docmgr;
64 } AssociatedWindow;
66 typedef struct tagACLMulti {
67 ITfThreadMgrEx ITfThreadMgrEx_iface;
68 ITfSource ITfSource_iface;
69 ITfKeystrokeMgr ITfKeystrokeMgr_iface;
70 ITfMessagePump ITfMessagePump_iface;
71 ITfClientId ITfClientId_iface;
72 /* const ITfThreadMgrExVtbl *ThreadMgrExVtbl; */
73 /* const ITfConfigureSystemKeystrokeFeedVtbl *ConfigureSystemKeystrokeFeedVtbl; */
74 /* const ITfLangBarItemMgrVtbl *LangBarItemMgrVtbl; */
75 ITfUIElementMgr ITfUIElementMgr_iface;
76 ITfSourceSingle ITfSourceSingle_iface;
77 LONG refCount;
79 /* Aggregation */
80 ITfCompartmentMgr *CompartmentMgr;
82 ITfThreadMgrEventSink ITfThreadMgrEventSink_iface; /* internal */
84 ITfDocumentMgr *focus;
85 LONG activationCount;
87 ITfKeyEventSink *foregroundKeyEventSink;
88 CLSID foregroundTextService;
90 struct list CurrentPreservedKeys;
91 struct list CreatedDocumentMgrs;
93 struct list AssociatedFocusWindows;
94 HHOOK focusHook;
96 /* kept as separate lists to reduce unnecessary iterations */
97 struct list ActiveLanguageProfileNotifySink;
98 struct list DisplayAttributeNotifySink;
99 struct list KeyTraceEventSink;
100 struct list PreservedKeyNotifySink;
101 struct list ThreadFocusSink;
102 struct list ThreadMgrEventSink;
103 } ThreadMgr;
105 typedef struct tagEnumTfDocumentMgr {
106 IEnumTfDocumentMgrs IEnumTfDocumentMgrs_iface;
107 LONG refCount;
109 struct list *index;
110 struct list *head;
111 } EnumTfDocumentMgr;
113 static HRESULT EnumTfDocumentMgr_Constructor(struct list* head, IEnumTfDocumentMgrs **ppOut);
115 static inline ThreadMgr *impl_from_ITfThreadMgrEx(ITfThreadMgrEx *iface)
117 return CONTAINING_RECORD(iface, ThreadMgr, ITfThreadMgrEx_iface);
120 static inline ThreadMgr *impl_from_ITfSource(ITfSource *iface)
122 return CONTAINING_RECORD(iface, ThreadMgr, ITfSource_iface);
125 static inline ThreadMgr *impl_from_ITfKeystrokeMgr(ITfKeystrokeMgr *iface)
127 return CONTAINING_RECORD(iface, ThreadMgr, ITfKeystrokeMgr_iface);
130 static inline ThreadMgr *impl_from_ITfMessagePump(ITfMessagePump *iface)
132 return CONTAINING_RECORD(iface, ThreadMgr, ITfMessagePump_iface);
135 static inline ThreadMgr *impl_from_ITfClientId(ITfClientId *iface)
137 return CONTAINING_RECORD(iface, ThreadMgr, ITfClientId_iface);
140 static inline ThreadMgr *impl_from_ITfThreadMgrEventSink(ITfThreadMgrEventSink *iface)
142 return CONTAINING_RECORD(iface, ThreadMgr, ITfThreadMgrEventSink_iface);
145 static inline ThreadMgr *impl_from_ITfUIElementMgr(ITfUIElementMgr *iface)
147 return CONTAINING_RECORD(iface, ThreadMgr, ITfUIElementMgr_iface);
150 static inline ThreadMgr *impl_from_ITfSourceSingle(ITfSourceSingle *iface)
152 return CONTAINING_RECORD(iface, ThreadMgr, ITfSourceSingle_iface);
155 static inline EnumTfDocumentMgr *impl_from_IEnumTfDocumentMgrs(IEnumTfDocumentMgrs *iface)
157 return CONTAINING_RECORD(iface, EnumTfDocumentMgr, IEnumTfDocumentMgrs_iface);
160 static void ThreadMgr_Destructor(ThreadMgr *This)
162 struct list *cursor, *cursor2;
164 /* unhook right away */
165 if (This->focusHook)
166 UnhookWindowsHookEx(This->focusHook);
168 TlsSetValue(tlsIndex,NULL);
169 TRACE("destroying %p\n", This);
170 if (This->focus)
171 ITfDocumentMgr_Release(This->focus);
173 free_sinks(&This->ActiveLanguageProfileNotifySink);
174 free_sinks(&This->DisplayAttributeNotifySink);
175 free_sinks(&This->KeyTraceEventSink);
176 free_sinks(&This->PreservedKeyNotifySink);
177 free_sinks(&This->ThreadFocusSink);
178 free_sinks(&This->ThreadMgrEventSink);
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->ThreadMgrEventSink, &IID_ITfThreadMgrEventSink, COOKIE_MAGIC_TMSINK, punk, pdwCookie);
624 FIXME("(%p) Unhandled Sink: %s\n",This,debugstr_guid(riid));
625 return E_NOTIMPL;
628 static HRESULT WINAPI ThreadMgrSource_UnadviseSink(ITfSource *iface, DWORD pdwCookie)
630 ThreadMgr *This = impl_from_ITfSource(iface);
632 TRACE("(%p) %x\n",This,pdwCookie);
634 if (get_Cookie_magic(pdwCookie)!=COOKIE_MAGIC_TMSINK)
635 return E_INVALIDARG;
637 return unadvise_sink(pdwCookie);
640 static const ITfSourceVtbl ThreadMgrSourceVtbl =
642 Source_QueryInterface,
643 Source_AddRef,
644 Source_Release,
645 ThreadMgrSource_AdviseSink,
646 ThreadMgrSource_UnadviseSink,
649 /*****************************************************
650 * ITfKeystrokeMgr functions
651 *****************************************************/
653 static HRESULT WINAPI KeystrokeMgr_QueryInterface(ITfKeystrokeMgr *iface, REFIID iid, LPVOID *ppvOut)
655 ThreadMgr *This = impl_from_ITfKeystrokeMgr(iface);
656 return ITfThreadMgrEx_QueryInterface(&This->ITfThreadMgrEx_iface, iid, ppvOut);
659 static ULONG WINAPI KeystrokeMgr_AddRef(ITfKeystrokeMgr *iface)
661 ThreadMgr *This = impl_from_ITfKeystrokeMgr(iface);
662 return ITfThreadMgrEx_AddRef(&This->ITfThreadMgrEx_iface);
665 static ULONG WINAPI KeystrokeMgr_Release(ITfKeystrokeMgr *iface)
667 ThreadMgr *This = impl_from_ITfKeystrokeMgr(iface);
668 return ITfThreadMgrEx_Release(&This->ITfThreadMgrEx_iface);
671 static HRESULT WINAPI KeystrokeMgr_AdviseKeyEventSink(ITfKeystrokeMgr *iface,
672 TfClientId tid, ITfKeyEventSink *pSink, BOOL fForeground)
674 ThreadMgr *This = impl_from_ITfKeystrokeMgr(iface);
675 CLSID textservice;
676 ITfKeyEventSink *check = NULL;
678 TRACE("(%p) %x %p %i\n",This,tid,pSink,fForeground);
680 if (!tid || !pSink)
681 return E_INVALIDARG;
683 textservice = get_textservice_clsid(tid);
684 if (IsEqualCLSID(&GUID_NULL,&textservice))
685 return E_INVALIDARG;
687 get_textservice_sink(tid, &IID_ITfKeyEventSink, (IUnknown**)&check);
688 if (check != NULL)
689 return CONNECT_E_ADVISELIMIT;
691 if (FAILED(ITfKeyEventSink_QueryInterface(pSink,&IID_ITfKeyEventSink,(LPVOID*) &check)))
692 return E_INVALIDARG;
694 set_textservice_sink(tid, &IID_ITfKeyEventSink, (IUnknown*)check);
696 if (fForeground)
698 if (This->foregroundKeyEventSink)
700 ITfKeyEventSink_OnSetFocus(This->foregroundKeyEventSink, FALSE);
701 ITfKeyEventSink_Release(This->foregroundKeyEventSink);
703 ITfKeyEventSink_AddRef(check);
704 ITfKeyEventSink_OnSetFocus(check, TRUE);
705 This->foregroundKeyEventSink = check;
706 This->foregroundTextService = textservice;
708 return S_OK;
711 static HRESULT WINAPI KeystrokeMgr_UnadviseKeyEventSink(ITfKeystrokeMgr *iface,
712 TfClientId tid)
714 ThreadMgr *This = impl_from_ITfKeystrokeMgr(iface);
715 CLSID textservice;
716 ITfKeyEventSink *check = NULL;
717 TRACE("(%p) %x\n",This,tid);
719 if (!tid)
720 return E_INVALIDARG;
722 textservice = get_textservice_clsid(tid);
723 if (IsEqualCLSID(&GUID_NULL,&textservice))
724 return E_INVALIDARG;
726 get_textservice_sink(tid, &IID_ITfKeyEventSink, (IUnknown**)&check);
728 if (!check)
729 return CONNECT_E_NOCONNECTION;
731 set_textservice_sink(tid, &IID_ITfKeyEventSink, NULL);
732 ITfKeyEventSink_Release(check);
734 if (This->foregroundKeyEventSink == check)
736 ITfKeyEventSink_Release(This->foregroundKeyEventSink);
737 This->foregroundKeyEventSink = NULL;
738 This->foregroundTextService = GUID_NULL;
740 return S_OK;
743 static HRESULT WINAPI KeystrokeMgr_GetForeground(ITfKeystrokeMgr *iface,
744 CLSID *pclsid)
746 ThreadMgr *This = impl_from_ITfKeystrokeMgr(iface);
747 TRACE("(%p) %p\n",This,pclsid);
748 if (!pclsid)
749 return E_INVALIDARG;
751 if (IsEqualCLSID(&This->foregroundTextService,&GUID_NULL))
752 return S_FALSE;
754 *pclsid = This->foregroundTextService;
755 return S_OK;
758 static HRESULT WINAPI KeystrokeMgr_TestKeyDown(ITfKeystrokeMgr *iface,
759 WPARAM wParam, LPARAM lParam, BOOL *pfEaten)
761 ThreadMgr *This = impl_from_ITfKeystrokeMgr(iface);
762 FIXME("STUB:(%p)\n",This);
763 *pfEaten = FALSE;
764 return S_OK;
767 static HRESULT WINAPI KeystrokeMgr_TestKeyUp(ITfKeystrokeMgr *iface,
768 WPARAM wParam, LPARAM lParam, BOOL *pfEaten)
770 ThreadMgr *This = impl_from_ITfKeystrokeMgr(iface);
771 FIXME("STUB:(%p)\n",This);
772 *pfEaten = FALSE;
773 return S_OK;
776 static HRESULT WINAPI KeystrokeMgr_KeyDown(ITfKeystrokeMgr *iface,
777 WPARAM wParam, LPARAM lParam, BOOL *pfEaten)
779 ThreadMgr *This = impl_from_ITfKeystrokeMgr(iface);
780 FIXME("STUB:(%p)\n",This);
781 return E_NOTIMPL;
784 static HRESULT WINAPI KeystrokeMgr_KeyUp(ITfKeystrokeMgr *iface,
785 WPARAM wParam, LPARAM lParam, BOOL *pfEaten)
787 ThreadMgr *This = impl_from_ITfKeystrokeMgr(iface);
788 FIXME("STUB:(%p)\n",This);
789 return E_NOTIMPL;
792 static HRESULT WINAPI KeystrokeMgr_GetPreservedKey(ITfKeystrokeMgr *iface,
793 ITfContext *pic, const TF_PRESERVEDKEY *pprekey, GUID *pguid)
795 ThreadMgr *This = impl_from_ITfKeystrokeMgr(iface);
796 FIXME("STUB:(%p)\n",This);
797 return E_NOTIMPL;
800 static HRESULT WINAPI KeystrokeMgr_IsPreservedKey(ITfKeystrokeMgr *iface,
801 REFGUID rguid, const TF_PRESERVEDKEY *pprekey, BOOL *pfRegistered)
803 ThreadMgr *This = impl_from_ITfKeystrokeMgr(iface);
804 struct list *cursor;
806 TRACE("(%p) %s (%x %x) %p\n",This,debugstr_guid(rguid), (pprekey)?pprekey->uVKey:0, (pprekey)?pprekey->uModifiers:0, pfRegistered);
808 if (!rguid || !pprekey || !pfRegistered)
809 return E_INVALIDARG;
811 LIST_FOR_EACH(cursor, &This->CurrentPreservedKeys)
813 PreservedKey* key = LIST_ENTRY(cursor,PreservedKey,entry);
814 if (IsEqualGUID(rguid,&key->guid) && pprekey->uVKey == key->prekey.uVKey && pprekey->uModifiers == key->prekey.uModifiers)
816 *pfRegistered = TRUE;
817 return S_OK;
821 *pfRegistered = FALSE;
822 return S_FALSE;
825 static HRESULT WINAPI KeystrokeMgr_PreserveKey(ITfKeystrokeMgr *iface,
826 TfClientId tid, REFGUID rguid, const TF_PRESERVEDKEY *prekey,
827 const WCHAR *pchDesc, ULONG cchDesc)
829 ThreadMgr *This = impl_from_ITfKeystrokeMgr(iface);
830 struct list *cursor;
831 PreservedKey *newkey;
833 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));
835 if (!tid || ! rguid || !prekey || (cchDesc && !pchDesc))
836 return E_INVALIDARG;
838 LIST_FOR_EACH(cursor, &This->CurrentPreservedKeys)
840 PreservedKey* key = LIST_ENTRY(cursor,PreservedKey,entry);
841 if (IsEqualGUID(rguid,&key->guid) && prekey->uVKey == key->prekey.uVKey && prekey->uModifiers == key->prekey.uModifiers)
842 return TF_E_ALREADY_EXISTS;
845 newkey = HeapAlloc(GetProcessHeap(),0,sizeof(PreservedKey));
846 if (!newkey)
847 return E_OUTOFMEMORY;
849 newkey->guid = *rguid;
850 newkey->prekey = *prekey;
851 newkey->tid = tid;
852 newkey->description = NULL;
853 if (cchDesc)
855 newkey->description = HeapAlloc(GetProcessHeap(),0,cchDesc * sizeof(WCHAR));
856 if (!newkey->description)
858 HeapFree(GetProcessHeap(),0,newkey);
859 return E_OUTOFMEMORY;
861 memcpy(newkey->description, pchDesc, cchDesc*sizeof(WCHAR));
864 list_add_head(&This->CurrentPreservedKeys,&newkey->entry);
866 return S_OK;
869 static HRESULT WINAPI KeystrokeMgr_UnpreserveKey(ITfKeystrokeMgr *iface,
870 REFGUID rguid, const TF_PRESERVEDKEY *pprekey)
872 ThreadMgr *This = impl_from_ITfKeystrokeMgr(iface);
873 PreservedKey* key = NULL;
874 struct list *cursor;
875 TRACE("(%p) %s (%x %x)\n",This,debugstr_guid(rguid),(pprekey)?pprekey->uVKey:0, (pprekey)?pprekey->uModifiers:0);
877 if (!pprekey || !rguid)
878 return E_INVALIDARG;
880 LIST_FOR_EACH(cursor, &This->CurrentPreservedKeys)
882 key = LIST_ENTRY(cursor,PreservedKey,entry);
883 if (IsEqualGUID(rguid,&key->guid) && pprekey->uVKey == key->prekey.uVKey && pprekey->uModifiers == key->prekey.uModifiers)
884 break;
885 key = NULL;
888 if (!key)
889 return CONNECT_E_NOCONNECTION;
891 list_remove(&key->entry);
892 HeapFree(GetProcessHeap(),0,key->description);
893 HeapFree(GetProcessHeap(),0,key);
895 return S_OK;
898 static HRESULT WINAPI KeystrokeMgr_SetPreservedKeyDescription(ITfKeystrokeMgr *iface,
899 REFGUID rguid, const WCHAR *pchDesc, ULONG cchDesc)
901 ThreadMgr *This = impl_from_ITfKeystrokeMgr(iface);
902 FIXME("STUB:(%p)\n",This);
903 return E_NOTIMPL;
906 static HRESULT WINAPI KeystrokeMgr_GetPreservedKeyDescription(ITfKeystrokeMgr *iface,
907 REFGUID rguid, BSTR *pbstrDesc)
909 ThreadMgr *This = impl_from_ITfKeystrokeMgr(iface);
910 FIXME("STUB:(%p)\n",This);
911 return E_NOTIMPL;
914 static HRESULT WINAPI KeystrokeMgr_SimulatePreservedKey(ITfKeystrokeMgr *iface,
915 ITfContext *pic, REFGUID rguid, BOOL *pfEaten)
917 ThreadMgr *This = impl_from_ITfKeystrokeMgr(iface);
918 FIXME("STUB:(%p)\n",This);
919 return E_NOTIMPL;
922 static const ITfKeystrokeMgrVtbl KeystrokeMgrVtbl =
924 KeystrokeMgr_QueryInterface,
925 KeystrokeMgr_AddRef,
926 KeystrokeMgr_Release,
927 KeystrokeMgr_AdviseKeyEventSink,
928 KeystrokeMgr_UnadviseKeyEventSink,
929 KeystrokeMgr_GetForeground,
930 KeystrokeMgr_TestKeyDown,
931 KeystrokeMgr_TestKeyUp,
932 KeystrokeMgr_KeyDown,
933 KeystrokeMgr_KeyUp,
934 KeystrokeMgr_GetPreservedKey,
935 KeystrokeMgr_IsPreservedKey,
936 KeystrokeMgr_PreserveKey,
937 KeystrokeMgr_UnpreserveKey,
938 KeystrokeMgr_SetPreservedKeyDescription,
939 KeystrokeMgr_GetPreservedKeyDescription,
940 KeystrokeMgr_SimulatePreservedKey
943 /*****************************************************
944 * ITfMessagePump functions
945 *****************************************************/
947 static HRESULT WINAPI MessagePump_QueryInterface(ITfMessagePump *iface, REFIID iid, LPVOID *ppvOut)
949 ThreadMgr *This = impl_from_ITfMessagePump(iface);
950 return ITfThreadMgrEx_QueryInterface(&This->ITfThreadMgrEx_iface, iid, ppvOut);
953 static ULONG WINAPI MessagePump_AddRef(ITfMessagePump *iface)
955 ThreadMgr *This = impl_from_ITfMessagePump(iface);
956 return ITfThreadMgrEx_AddRef(&This->ITfThreadMgrEx_iface);
959 static ULONG WINAPI MessagePump_Release(ITfMessagePump *iface)
961 ThreadMgr *This = impl_from_ITfMessagePump(iface);
962 return ITfThreadMgrEx_Release(&This->ITfThreadMgrEx_iface);
965 static HRESULT WINAPI MessagePump_PeekMessageA(ITfMessagePump *iface,
966 LPMSG pMsg, HWND hwnd, UINT wMsgFilterMin, UINT wMsgFilterMax,
967 UINT wRemoveMsg, BOOL *pfResult)
969 if (!pfResult)
970 return E_INVALIDARG;
971 *pfResult = PeekMessageA(pMsg, hwnd, wMsgFilterMin, wMsgFilterMax, wRemoveMsg);
972 return S_OK;
975 static HRESULT WINAPI MessagePump_GetMessageA(ITfMessagePump *iface,
976 LPMSG pMsg, HWND hwnd, UINT wMsgFilterMin, UINT wMsgFilterMax,
977 BOOL *pfResult)
979 if (!pfResult)
980 return E_INVALIDARG;
981 *pfResult = GetMessageA(pMsg, hwnd, wMsgFilterMin, wMsgFilterMax);
982 return S_OK;
985 static HRESULT WINAPI MessagePump_PeekMessageW(ITfMessagePump *iface,
986 LPMSG pMsg, HWND hwnd, UINT wMsgFilterMin, UINT wMsgFilterMax,
987 UINT wRemoveMsg, BOOL *pfResult)
989 if (!pfResult)
990 return E_INVALIDARG;
991 *pfResult = PeekMessageW(pMsg, hwnd, wMsgFilterMin, wMsgFilterMax, wRemoveMsg);
992 return S_OK;
995 static HRESULT WINAPI MessagePump_GetMessageW(ITfMessagePump *iface,
996 LPMSG pMsg, HWND hwnd, UINT wMsgFilterMin, UINT wMsgFilterMax,
997 BOOL *pfResult)
999 if (!pfResult)
1000 return E_INVALIDARG;
1001 *pfResult = GetMessageW(pMsg, hwnd, wMsgFilterMin, wMsgFilterMax);
1002 return S_OK;
1005 static const ITfMessagePumpVtbl MessagePumpVtbl =
1007 MessagePump_QueryInterface,
1008 MessagePump_AddRef,
1009 MessagePump_Release,
1010 MessagePump_PeekMessageA,
1011 MessagePump_GetMessageA,
1012 MessagePump_PeekMessageW,
1013 MessagePump_GetMessageW
1016 /*****************************************************
1017 * ITfClientId functions
1018 *****************************************************/
1020 static HRESULT WINAPI ClientId_QueryInterface(ITfClientId *iface, REFIID iid, LPVOID *ppvOut)
1022 ThreadMgr *This = impl_from_ITfClientId(iface);
1023 return ITfThreadMgrEx_QueryInterface(&This->ITfThreadMgrEx_iface, iid, ppvOut);
1026 static ULONG WINAPI ClientId_AddRef(ITfClientId *iface)
1028 ThreadMgr *This = impl_from_ITfClientId(iface);
1029 return ITfThreadMgrEx_AddRef(&This->ITfThreadMgrEx_iface);
1032 static ULONG WINAPI ClientId_Release(ITfClientId *iface)
1034 ThreadMgr *This = impl_from_ITfClientId(iface);
1035 return ITfThreadMgrEx_Release(&This->ITfThreadMgrEx_iface);
1038 static HRESULT WINAPI ClientId_GetClientId(ITfClientId *iface,
1039 REFCLSID rclsid, TfClientId *ptid)
1042 ThreadMgr *This = impl_from_ITfClientId(iface);
1043 HRESULT hr;
1044 ITfCategoryMgr *catmgr;
1046 TRACE("(%p) %s\n",This,debugstr_guid(rclsid));
1048 CategoryMgr_Constructor(NULL,(IUnknown**)&catmgr);
1049 hr = ITfCategoryMgr_RegisterGUID(catmgr,rclsid,ptid);
1050 ITfCategoryMgr_Release(catmgr);
1052 return hr;
1055 static const ITfClientIdVtbl ClientIdVtbl =
1057 ClientId_QueryInterface,
1058 ClientId_AddRef,
1059 ClientId_Release,
1060 ClientId_GetClientId
1063 /*****************************************************
1064 * ITfThreadMgrEventSink functions (internal)
1065 *****************************************************/
1066 static HRESULT WINAPI ThreadMgrEventSink_QueryInterface(ITfThreadMgrEventSink *iface, REFIID iid, LPVOID *ppvOut)
1068 ThreadMgr *This = impl_from_ITfThreadMgrEventSink(iface);
1069 return ITfThreadMgrEx_QueryInterface(&This->ITfThreadMgrEx_iface, iid, ppvOut);
1072 static ULONG WINAPI ThreadMgrEventSink_AddRef(ITfThreadMgrEventSink *iface)
1074 ThreadMgr *This = impl_from_ITfThreadMgrEventSink(iface);
1075 return ITfThreadMgrEx_AddRef(&This->ITfThreadMgrEx_iface);
1078 static ULONG WINAPI ThreadMgrEventSink_Release(ITfThreadMgrEventSink *iface)
1080 ThreadMgr *This = impl_from_ITfThreadMgrEventSink(iface);
1081 return ITfThreadMgrEx_Release(&This->ITfThreadMgrEx_iface);
1085 static HRESULT WINAPI ThreadMgrEventSink_OnInitDocumentMgr(
1086 ITfThreadMgrEventSink *iface,ITfDocumentMgr *pdim)
1088 ThreadMgr *This = impl_from_ITfThreadMgrEventSink(iface);
1089 ITfThreadMgrEventSink *sink;
1090 struct list *cursor;
1092 TRACE("(%p) %p\n",This,pdim);
1094 SINK_FOR_EACH(cursor, &This->ThreadMgrEventSink, ITfThreadMgrEventSink, sink)
1096 ITfThreadMgrEventSink_OnInitDocumentMgr(sink, pdim);
1099 return S_OK;
1102 static HRESULT WINAPI ThreadMgrEventSink_OnUninitDocumentMgr(
1103 ITfThreadMgrEventSink *iface, ITfDocumentMgr *pdim)
1105 ThreadMgr *This = impl_from_ITfThreadMgrEventSink(iface);
1106 ITfThreadMgrEventSink *sink;
1107 struct list *cursor;
1109 TRACE("(%p) %p\n",This,pdim);
1111 SINK_FOR_EACH(cursor, &This->ThreadMgrEventSink, ITfThreadMgrEventSink, sink)
1113 ITfThreadMgrEventSink_OnUninitDocumentMgr(sink, pdim);
1116 return S_OK;
1119 static HRESULT WINAPI ThreadMgrEventSink_OnSetFocus(
1120 ITfThreadMgrEventSink *iface, ITfDocumentMgr *pdimFocus,
1121 ITfDocumentMgr *pdimPrevFocus)
1123 ThreadMgr *This = impl_from_ITfThreadMgrEventSink(iface);
1124 ITfThreadMgrEventSink *sink;
1125 struct list *cursor;
1127 TRACE("(%p) %p %p\n",This,pdimFocus, pdimPrevFocus);
1129 SINK_FOR_EACH(cursor, &This->ThreadMgrEventSink, ITfThreadMgrEventSink, sink)
1131 ITfThreadMgrEventSink_OnSetFocus(sink, pdimFocus, pdimPrevFocus);
1134 return S_OK;
1137 static HRESULT WINAPI ThreadMgrEventSink_OnPushContext(
1138 ITfThreadMgrEventSink *iface, ITfContext *pic)
1140 ThreadMgr *This = impl_from_ITfThreadMgrEventSink(iface);
1141 ITfThreadMgrEventSink *sink;
1142 struct list *cursor;
1144 TRACE("(%p) %p\n",This,pic);
1146 SINK_FOR_EACH(cursor, &This->ThreadMgrEventSink, ITfThreadMgrEventSink, sink)
1148 ITfThreadMgrEventSink_OnPushContext(sink, pic);
1151 return S_OK;
1154 static HRESULT WINAPI ThreadMgrEventSink_OnPopContext(
1155 ITfThreadMgrEventSink *iface, ITfContext *pic)
1157 ThreadMgr *This = impl_from_ITfThreadMgrEventSink(iface);
1158 ITfThreadMgrEventSink *sink;
1159 struct list *cursor;
1161 TRACE("(%p) %p\n",This,pic);
1163 SINK_FOR_EACH(cursor, &This->ThreadMgrEventSink, ITfThreadMgrEventSink, sink)
1165 ITfThreadMgrEventSink_OnPopContext(sink, pic);
1168 return S_OK;
1171 static const ITfThreadMgrEventSinkVtbl ThreadMgrEventSinkVtbl =
1173 ThreadMgrEventSink_QueryInterface,
1174 ThreadMgrEventSink_AddRef,
1175 ThreadMgrEventSink_Release,
1176 ThreadMgrEventSink_OnInitDocumentMgr,
1177 ThreadMgrEventSink_OnUninitDocumentMgr,
1178 ThreadMgrEventSink_OnSetFocus,
1179 ThreadMgrEventSink_OnPushContext,
1180 ThreadMgrEventSink_OnPopContext
1183 /*****************************************************
1184 * ITfUIElementMgr functions
1185 *****************************************************/
1186 static HRESULT WINAPI UIElementMgr_QueryInterface(ITfUIElementMgr *iface, REFIID iid, void **ppvOut)
1188 ThreadMgr *This = impl_from_ITfUIElementMgr(iface);
1190 return ITfThreadMgrEx_QueryInterface(&This->ITfThreadMgrEx_iface, iid, ppvOut);
1193 static ULONG WINAPI UIElementMgr_AddRef(ITfUIElementMgr *iface)
1195 ThreadMgr *This = impl_from_ITfUIElementMgr(iface);
1197 return ITfThreadMgrEx_AddRef(&This->ITfThreadMgrEx_iface);
1200 static ULONG WINAPI UIElementMgr_Release(ITfUIElementMgr *iface)
1202 ThreadMgr *This = impl_from_ITfUIElementMgr(iface);
1204 return ITfThreadMgrEx_Release(&This->ITfThreadMgrEx_iface);
1207 static HRESULT WINAPI UIElementMgr_BeginUIElement(ITfUIElementMgr *iface, ITfUIElement *element,
1208 BOOL *show, DWORD *id)
1210 ThreadMgr *This = impl_from_ITfUIElementMgr(iface);
1212 FIXME("STUB:(%p)\n", This);
1213 return E_NOTIMPL;
1216 static HRESULT WINAPI UIElementMgr_UpdateUIElement(ITfUIElementMgr *iface, DWORD id)
1218 ThreadMgr *This = impl_from_ITfUIElementMgr(iface);
1220 FIXME("STUB:(%p)\n", This);
1221 return E_NOTIMPL;
1224 static HRESULT WINAPI UIElementMgr_EndUIElement(ITfUIElementMgr *iface, DWORD id)
1226 ThreadMgr *This = impl_from_ITfUIElementMgr(iface);
1228 FIXME("STUB:(%p)\n", This);
1229 return E_NOTIMPL;
1232 static HRESULT WINAPI UIElementMgr_GetUIElement(ITfUIElementMgr *iface, DWORD id,
1233 ITfUIElement **element)
1235 ThreadMgr *This = impl_from_ITfUIElementMgr(iface);
1237 FIXME("STUB:(%p)\n", This);
1238 return E_NOTIMPL;
1241 static HRESULT WINAPI UIElementMgr_EnumUIElements(ITfUIElementMgr *iface,
1242 IEnumTfUIElements **enum_elements)
1244 ThreadMgr *This = impl_from_ITfUIElementMgr(iface);
1246 FIXME("STUB:(%p)\n", This);
1247 return E_NOTIMPL;
1250 static const ITfUIElementMgrVtbl ThreadMgrUIElementMgrVtbl =
1252 UIElementMgr_QueryInterface,
1253 UIElementMgr_AddRef,
1254 UIElementMgr_Release,
1256 UIElementMgr_BeginUIElement,
1257 UIElementMgr_UpdateUIElement,
1258 UIElementMgr_EndUIElement,
1259 UIElementMgr_GetUIElement,
1260 UIElementMgr_EnumUIElements
1263 /*****************************************************
1264 * ITfSourceSingle functions
1265 *****************************************************/
1266 static HRESULT WINAPI ThreadMgrSourceSingle_QueryInterface(ITfSourceSingle *iface, REFIID iid, LPVOID *ppvOut)
1268 ThreadMgr *This = impl_from_ITfSourceSingle(iface);
1269 return ITfThreadMgrEx_QueryInterface(&This->ITfThreadMgrEx_iface, iid, ppvOut);
1272 static ULONG WINAPI ThreadMgrSourceSingle_AddRef(ITfSourceSingle *iface)
1274 ThreadMgr *This = impl_from_ITfSourceSingle(iface);
1275 return ITfThreadMgrEx_AddRef(&This->ITfThreadMgrEx_iface);
1278 static ULONG WINAPI ThreadMgrSourceSingle_Release(ITfSourceSingle *iface)
1280 ThreadMgr *This = impl_from_ITfSourceSingle(iface);
1281 return ITfThreadMgrEx_Release(&This->ITfThreadMgrEx_iface);
1284 static HRESULT WINAPI ThreadMgrSourceSingle_AdviseSingleSink( ITfSourceSingle *iface,
1285 TfClientId tid, REFIID riid, IUnknown *punk)
1287 ThreadMgr *This = impl_from_ITfSourceSingle(iface);
1288 FIXME("STUB:(%p) %i %s %p\n",This, tid, debugstr_guid(riid),punk);
1289 return E_NOTIMPL;
1292 static HRESULT WINAPI ThreadMgrSourceSingle_UnadviseSingleSink( ITfSourceSingle *iface,
1293 TfClientId tid, REFIID riid)
1295 ThreadMgr *This = impl_from_ITfSourceSingle(iface);
1296 FIXME("STUB:(%p) %i %s\n",This, tid, debugstr_guid(riid));
1297 return E_NOTIMPL;
1300 static const ITfSourceSingleVtbl SourceSingleVtbl =
1302 ThreadMgrSourceSingle_QueryInterface,
1303 ThreadMgrSourceSingle_AddRef,
1304 ThreadMgrSourceSingle_Release,
1305 ThreadMgrSourceSingle_AdviseSingleSink,
1306 ThreadMgrSourceSingle_UnadviseSingleSink
1309 HRESULT ThreadMgr_Constructor(IUnknown *pUnkOuter, IUnknown **ppOut)
1311 ThreadMgr *This;
1312 if (pUnkOuter)
1313 return CLASS_E_NOAGGREGATION;
1315 /* Only 1 ThreadMgr is created per thread */
1316 This = TlsGetValue(tlsIndex);
1317 if (This)
1319 ThreadMgr_AddRef(&This->ITfThreadMgrEx_iface);
1320 *ppOut = (IUnknown*)&This->ITfThreadMgrEx_iface;
1321 return S_OK;
1324 This = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(ThreadMgr));
1325 if (This == NULL)
1326 return E_OUTOFMEMORY;
1328 This->ITfThreadMgrEx_iface.lpVtbl = &ThreadMgrExVtbl;
1329 This->ITfSource_iface.lpVtbl = &ThreadMgrSourceVtbl;
1330 This->ITfKeystrokeMgr_iface.lpVtbl = &KeystrokeMgrVtbl;
1331 This->ITfMessagePump_iface.lpVtbl = &MessagePumpVtbl;
1332 This->ITfClientId_iface.lpVtbl = &ClientIdVtbl;
1333 This->ITfThreadMgrEventSink_iface.lpVtbl = &ThreadMgrEventSinkVtbl;
1334 This->ITfUIElementMgr_iface.lpVtbl = &ThreadMgrUIElementMgrVtbl;
1335 This->ITfSourceSingle_iface.lpVtbl = &SourceSingleVtbl;
1336 This->refCount = 1;
1337 TlsSetValue(tlsIndex,This);
1339 CompartmentMgr_Constructor((IUnknown*)&This->ITfThreadMgrEx_iface, &IID_IUnknown, (IUnknown**)&This->CompartmentMgr);
1341 list_init(&This->CurrentPreservedKeys);
1342 list_init(&This->CreatedDocumentMgrs);
1343 list_init(&This->AssociatedFocusWindows);
1345 list_init(&This->ActiveLanguageProfileNotifySink);
1346 list_init(&This->DisplayAttributeNotifySink);
1347 list_init(&This->KeyTraceEventSink);
1348 list_init(&This->PreservedKeyNotifySink);
1349 list_init(&This->ThreadFocusSink);
1350 list_init(&This->ThreadMgrEventSink);
1352 TRACE("returning %p\n", This);
1353 *ppOut = (IUnknown *)&This->ITfThreadMgrEx_iface;
1354 return S_OK;
1357 /**************************************************
1358 * IEnumTfDocumentMgrs implementation
1359 **************************************************/
1360 static void EnumTfDocumentMgr_Destructor(EnumTfDocumentMgr *This)
1362 TRACE("destroying %p\n", This);
1363 HeapFree(GetProcessHeap(),0,This);
1366 static HRESULT WINAPI EnumTfDocumentMgr_QueryInterface(IEnumTfDocumentMgrs *iface, REFIID iid, LPVOID *ppvOut)
1368 EnumTfDocumentMgr *This = impl_from_IEnumTfDocumentMgrs(iface);
1369 *ppvOut = NULL;
1371 if (IsEqualIID(iid, &IID_IUnknown) || IsEqualIID(iid, &IID_IEnumTfDocumentMgrs))
1373 *ppvOut = &This->IEnumTfDocumentMgrs_iface;
1376 if (*ppvOut)
1378 IEnumTfDocumentMgrs_AddRef(iface);
1379 return S_OK;
1382 WARN("unsupported interface: %s\n", debugstr_guid(iid));
1383 return E_NOINTERFACE;
1386 static ULONG WINAPI EnumTfDocumentMgr_AddRef(IEnumTfDocumentMgrs *iface)
1388 EnumTfDocumentMgr *This = impl_from_IEnumTfDocumentMgrs(iface);
1389 return InterlockedIncrement(&This->refCount);
1392 static ULONG WINAPI EnumTfDocumentMgr_Release(IEnumTfDocumentMgrs *iface)
1394 EnumTfDocumentMgr *This = impl_from_IEnumTfDocumentMgrs(iface);
1395 ULONG ret;
1397 ret = InterlockedDecrement(&This->refCount);
1398 if (ret == 0)
1399 EnumTfDocumentMgr_Destructor(This);
1400 return ret;
1403 static HRESULT WINAPI EnumTfDocumentMgr_Next(IEnumTfDocumentMgrs *iface,
1404 ULONG ulCount, ITfDocumentMgr **rgDocumentMgr, ULONG *pcFetched)
1406 EnumTfDocumentMgr *This = impl_from_IEnumTfDocumentMgrs(iface);
1407 ULONG fetched = 0;
1409 TRACE("(%p)\n",This);
1411 if (rgDocumentMgr == NULL) return E_POINTER;
1413 while (fetched < ulCount)
1415 DocumentMgrEntry *mgrentry;
1416 if (This->index == NULL)
1417 break;
1419 mgrentry = LIST_ENTRY(This->index,DocumentMgrEntry,entry);
1420 if (mgrentry == NULL)
1421 break;
1423 *rgDocumentMgr = mgrentry->docmgr;
1424 ITfDocumentMgr_AddRef(*rgDocumentMgr);
1426 This->index = list_next(This->head, This->index);
1427 ++fetched;
1428 ++rgDocumentMgr;
1431 if (pcFetched) *pcFetched = fetched;
1432 return fetched == ulCount ? S_OK : S_FALSE;
1435 static HRESULT WINAPI EnumTfDocumentMgr_Skip( IEnumTfDocumentMgrs* iface, ULONG celt)
1437 EnumTfDocumentMgr *This = impl_from_IEnumTfDocumentMgrs(iface);
1438 ULONG i;
1440 TRACE("(%p)\n",This);
1441 for(i = 0; i < celt && This->index != NULL; i++)
1442 This->index = list_next(This->head, This->index);
1443 return S_OK;
1446 static HRESULT WINAPI EnumTfDocumentMgr_Reset( IEnumTfDocumentMgrs* iface)
1448 EnumTfDocumentMgr *This = impl_from_IEnumTfDocumentMgrs(iface);
1449 TRACE("(%p)\n",This);
1450 This->index = list_head(This->head);
1451 return S_OK;
1454 static HRESULT WINAPI EnumTfDocumentMgr_Clone( IEnumTfDocumentMgrs *iface,
1455 IEnumTfDocumentMgrs **ppenum)
1457 EnumTfDocumentMgr *This = impl_from_IEnumTfDocumentMgrs(iface);
1458 HRESULT res;
1460 TRACE("(%p)\n",This);
1462 if (ppenum == NULL) return E_POINTER;
1464 res = EnumTfDocumentMgr_Constructor(This->head, ppenum);
1465 if (SUCCEEDED(res))
1467 EnumTfDocumentMgr *new_This = impl_from_IEnumTfDocumentMgrs(*ppenum);
1468 new_This->index = This->index;
1470 return res;
1473 static const IEnumTfDocumentMgrsVtbl EnumTfDocumentMgrsVtbl =
1475 EnumTfDocumentMgr_QueryInterface,
1476 EnumTfDocumentMgr_AddRef,
1477 EnumTfDocumentMgr_Release,
1478 EnumTfDocumentMgr_Clone,
1479 EnumTfDocumentMgr_Next,
1480 EnumTfDocumentMgr_Reset,
1481 EnumTfDocumentMgr_Skip
1484 static HRESULT EnumTfDocumentMgr_Constructor(struct list* head, IEnumTfDocumentMgrs **ppOut)
1486 EnumTfDocumentMgr *This;
1488 This = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(EnumTfDocumentMgr));
1489 if (This == NULL)
1490 return E_OUTOFMEMORY;
1492 This->IEnumTfDocumentMgrs_iface.lpVtbl= &EnumTfDocumentMgrsVtbl;
1493 This->refCount = 1;
1494 This->head = head;
1495 This->index = list_head(This->head);
1497 TRACE("returning %p\n", &This->IEnumTfDocumentMgrs_iface);
1498 *ppOut = &This->IEnumTfDocumentMgrs_iface;
1499 return S_OK;
1502 void ThreadMgr_OnDocumentMgrDestruction(ITfThreadMgr *iface, ITfDocumentMgr *mgr)
1504 ThreadMgr *This = impl_from_ITfThreadMgrEx((ITfThreadMgrEx *)iface);
1505 struct list *cursor;
1506 LIST_FOR_EACH(cursor, &This->CreatedDocumentMgrs)
1508 DocumentMgrEntry *mgrentry = LIST_ENTRY(cursor,DocumentMgrEntry,entry);
1509 if (mgrentry->docmgr == mgr)
1511 list_remove(cursor);
1512 HeapFree(GetProcessHeap(),0,mgrentry);
1513 return;
1516 FIXME("ITfDocumentMgr %p not found in this thread\n",mgr);