msvcrt: Add __swprintf_l.
[wine.git] / dlls / msctf / threadmgr.c
blob960548cfc2228210a379dc022fadbb3edc22ce74
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 ITfThreadMgr ITfThreadMgr_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 /* const ITfUIElementMgrVtbl *UIElementMgrVtbl; */
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_ITfThreadMgr(ITfThreadMgr *iface)
132 return CONTAINING_RECORD(iface, ThreadMgr, ITfThreadMgr_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_ITfSourceSingle(ITfSourceSingle *iface)
162 return CONTAINING_RECORD(iface, ThreadMgr, ITfSourceSingle_iface);
165 static inline EnumTfDocumentMgr *impl_from_IEnumTfDocumentMgrs(IEnumTfDocumentMgrs *iface)
167 return CONTAINING_RECORD(iface, EnumTfDocumentMgr, IEnumTfDocumentMgrs_iface);
170 static void free_sink(ThreadMgrSink *sink)
172 IUnknown_Release(sink->interfaces.pIUnknown);
173 HeapFree(GetProcessHeap(),0,sink);
176 static void ThreadMgr_Destructor(ThreadMgr *This)
178 struct list *cursor, *cursor2;
180 /* unhook right away */
181 if (This->focusHook)
182 UnhookWindowsHookEx(This->focusHook);
184 TlsSetValue(tlsIndex,NULL);
185 TRACE("destroying %p\n", This);
186 if (This->focus)
187 ITfDocumentMgr_Release(This->focus);
189 /* free sinks */
190 LIST_FOR_EACH_SAFE(cursor, cursor2, &This->ActiveLanguageProfileNotifySink)
192 ThreadMgrSink* sink = LIST_ENTRY(cursor,ThreadMgrSink,entry);
193 list_remove(cursor);
194 free_sink(sink);
196 LIST_FOR_EACH_SAFE(cursor, cursor2, &This->DisplayAttributeNotifySink)
198 ThreadMgrSink* sink = LIST_ENTRY(cursor,ThreadMgrSink,entry);
199 list_remove(cursor);
200 free_sink(sink);
202 LIST_FOR_EACH_SAFE(cursor, cursor2, &This->KeyTraceEventSink)
204 ThreadMgrSink* sink = LIST_ENTRY(cursor,ThreadMgrSink,entry);
205 list_remove(cursor);
206 free_sink(sink);
208 LIST_FOR_EACH_SAFE(cursor, cursor2, &This->PreservedKeyNotifySink)
210 ThreadMgrSink* sink = LIST_ENTRY(cursor,ThreadMgrSink,entry);
211 list_remove(cursor);
212 free_sink(sink);
214 LIST_FOR_EACH_SAFE(cursor, cursor2, &This->ThreadFocusSink)
216 ThreadMgrSink* sink = LIST_ENTRY(cursor,ThreadMgrSink,entry);
217 list_remove(cursor);
218 free_sink(sink);
220 LIST_FOR_EACH_SAFE(cursor, cursor2, &This->ThreadMgrEventSink)
222 ThreadMgrSink* sink = LIST_ENTRY(cursor,ThreadMgrSink,entry);
223 list_remove(cursor);
224 free_sink(sink);
227 LIST_FOR_EACH_SAFE(cursor, cursor2, &This->CurrentPreservedKeys)
229 PreservedKey* key = LIST_ENTRY(cursor,PreservedKey,entry);
230 list_remove(cursor);
231 HeapFree(GetProcessHeap(),0,key->description);
232 HeapFree(GetProcessHeap(),0,key);
235 LIST_FOR_EACH_SAFE(cursor, cursor2, &This->CreatedDocumentMgrs)
237 DocumentMgrEntry *mgr = LIST_ENTRY(cursor,DocumentMgrEntry,entry);
238 list_remove(cursor);
239 FIXME("Left Over ITfDocumentMgr. Should we do something with it?\n");
240 HeapFree(GetProcessHeap(),0,mgr);
243 LIST_FOR_EACH_SAFE(cursor, cursor2, &This->AssociatedFocusWindows)
245 AssociatedWindow *wnd = LIST_ENTRY(cursor,AssociatedWindow,entry);
246 list_remove(cursor);
247 HeapFree(GetProcessHeap(),0,wnd);
250 CompartmentMgr_Destructor(This->CompartmentMgr);
252 HeapFree(GetProcessHeap(),0,This);
255 static HRESULT WINAPI ThreadMgr_QueryInterface(ITfThreadMgr *iface, REFIID iid, LPVOID *ppvOut)
257 ThreadMgr *This = impl_from_ITfThreadMgr(iface);
258 *ppvOut = NULL;
260 if (IsEqualIID(iid, &IID_IUnknown) || IsEqualIID(iid, &IID_ITfThreadMgr))
262 *ppvOut = &This->ITfThreadMgr_iface;
264 else if (IsEqualIID(iid, &IID_ITfSource))
266 *ppvOut = &This->ITfSource_iface;
268 else if (IsEqualIID(iid, &IID_ITfKeystrokeMgr))
270 *ppvOut = &This->ITfKeystrokeMgr_iface;
272 else if (IsEqualIID(iid, &IID_ITfMessagePump))
274 *ppvOut = &This->ITfMessagePump_iface;
276 else if (IsEqualIID(iid, &IID_ITfClientId))
278 *ppvOut = &This->ITfClientId_iface;
280 else if (IsEqualIID(iid, &IID_ITfCompartmentMgr))
282 *ppvOut = This->CompartmentMgr;
284 else if (IsEqualIID(iid, &IID_ITfSourceSingle))
286 *ppvOut = &This->ITfSourceSingle_iface;
289 if (*ppvOut)
291 ITfThreadMgr_AddRef(iface);
292 return S_OK;
295 WARN("unsupported interface: %s\n", debugstr_guid(iid));
296 return E_NOINTERFACE;
299 static ULONG WINAPI ThreadMgr_AddRef(ITfThreadMgr *iface)
301 ThreadMgr *This = impl_from_ITfThreadMgr(iface);
302 return InterlockedIncrement(&This->refCount);
305 static ULONG WINAPI ThreadMgr_Release(ITfThreadMgr *iface)
307 ThreadMgr *This = impl_from_ITfThreadMgr(iface);
308 ULONG ret;
310 ret = InterlockedDecrement(&This->refCount);
311 if (ret == 0)
312 ThreadMgr_Destructor(This);
313 return ret;
316 /*****************************************************
317 * ITfThreadMgr functions
318 *****************************************************/
320 static HRESULT WINAPI ThreadMgr_fnActivate( ITfThreadMgr* iface, TfClientId *ptid)
322 ThreadMgr *This = impl_from_ITfThreadMgr(iface);
324 TRACE("(%p) %p\n",This, ptid);
326 if (!ptid)
327 return E_INVALIDARG;
329 if (!processId)
331 GUID guid;
332 CoCreateGuid(&guid);
333 ITfClientId_GetClientId(&This->ITfClientId_iface, &guid, &processId);
336 activate_textservices(iface);
337 This->activationCount++;
338 *ptid = processId;
339 return S_OK;
342 static HRESULT WINAPI ThreadMgr_fnDeactivate( ITfThreadMgr* iface)
344 ThreadMgr *This = impl_from_ITfThreadMgr(iface);
345 TRACE("(%p)\n",This);
347 if (This->activationCount == 0)
348 return E_UNEXPECTED;
350 This->activationCount --;
352 if (This->activationCount == 0)
354 if (This->focus)
356 ITfThreadMgrEventSink_OnSetFocus(&This->ITfThreadMgrEventSink_iface, 0, This->focus);
357 ITfDocumentMgr_Release(This->focus);
358 This->focus = 0;
362 deactivate_textservices();
364 return S_OK;
367 static HRESULT WINAPI ThreadMgr_CreateDocumentMgr(ITfThreadMgr* iface, ITfDocumentMgr **ppdim)
369 ThreadMgr *This = impl_from_ITfThreadMgr(iface);
370 DocumentMgrEntry *mgrentry;
371 HRESULT hr;
373 TRACE("(%p)\n",iface);
374 mgrentry = HeapAlloc(GetProcessHeap(),0,sizeof(DocumentMgrEntry));
375 if (mgrentry == NULL)
376 return E_OUTOFMEMORY;
378 hr = DocumentMgr_Constructor(&This->ITfThreadMgrEventSink_iface, ppdim);
380 if (SUCCEEDED(hr))
382 mgrentry->docmgr = *ppdim;
383 list_add_head(&This->CreatedDocumentMgrs,&mgrentry->entry);
385 else
386 HeapFree(GetProcessHeap(),0,mgrentry);
388 return hr;
391 static HRESULT WINAPI ThreadMgr_EnumDocumentMgrs( ITfThreadMgr* iface, IEnumTfDocumentMgrs **ppEnum)
393 ThreadMgr *This = impl_from_ITfThreadMgr(iface);
394 TRACE("(%p) %p\n",This,ppEnum);
396 if (!ppEnum)
397 return E_INVALIDARG;
399 return EnumTfDocumentMgr_Constructor(&This->CreatedDocumentMgrs, ppEnum);
402 static HRESULT WINAPI ThreadMgr_GetFocus( ITfThreadMgr* iface, ITfDocumentMgr
403 **ppdimFocus)
405 ThreadMgr *This = impl_from_ITfThreadMgr(iface);
406 TRACE("(%p)\n",This);
408 if (!ppdimFocus)
409 return E_INVALIDARG;
411 *ppdimFocus = This->focus;
413 TRACE("->%p\n",This->focus);
415 if (This->focus == NULL)
416 return S_FALSE;
418 ITfDocumentMgr_AddRef(This->focus);
420 return S_OK;
423 static HRESULT WINAPI ThreadMgr_SetFocus( ITfThreadMgr* iface, ITfDocumentMgr *pdimFocus)
425 ThreadMgr *This = impl_from_ITfThreadMgr(iface);
426 ITfDocumentMgr *check;
428 TRACE("(%p) %p\n",This,pdimFocus);
430 if (!pdimFocus)
431 check = NULL;
432 else if (FAILED(ITfDocumentMgr_QueryInterface(pdimFocus,&IID_ITfDocumentMgr,(LPVOID*) &check)))
433 return E_INVALIDARG;
435 ITfThreadMgrEventSink_OnSetFocus(&This->ITfThreadMgrEventSink_iface, check, This->focus);
437 if (This->focus)
438 ITfDocumentMgr_Release(This->focus);
440 This->focus = check;
441 return S_OK;
444 static LRESULT CALLBACK ThreadFocusHookProc(int nCode, WPARAM wParam, LPARAM lParam)
446 ThreadMgr *This;
448 This = TlsGetValue(tlsIndex);
449 if (!This)
451 ERR("Hook proc but no ThreadMgr for this thread. Serious Error\n");
452 return 0;
454 if (!This->focusHook)
456 ERR("Hook proc but no ThreadMgr focus Hook. Serious Error\n");
457 return 0;
460 if (nCode == HCBT_SETFOCUS) /* focus change within our thread */
462 struct list *cursor;
464 LIST_FOR_EACH(cursor, &This->AssociatedFocusWindows)
466 AssociatedWindow *wnd = LIST_ENTRY(cursor,AssociatedWindow,entry);
467 if (wnd->hwnd == (HWND)wParam)
469 TRACE("Triggering Associated window focus\n");
470 if (This->focus != wnd->docmgr)
471 ThreadMgr_SetFocus((ITfThreadMgr*)This, wnd->docmgr);
472 break;
477 return CallNextHookEx(This->focusHook, nCode, wParam, lParam);
480 static HRESULT SetupWindowsHook(ThreadMgr *This)
482 if (!This->focusHook)
484 This->focusHook = SetWindowsHookExW(WH_CBT, ThreadFocusHookProc, 0,
485 GetCurrentThreadId());
486 if (!This->focusHook)
488 ERR("Unable to set focus hook\n");
489 return E_FAIL;
491 return S_OK;
493 return S_FALSE;
496 static HRESULT WINAPI ThreadMgr_AssociateFocus( ITfThreadMgr* iface, HWND hwnd,
497 ITfDocumentMgr *pdimNew, ITfDocumentMgr **ppdimPrev)
499 ThreadMgr *This = impl_from_ITfThreadMgr(iface);
500 struct list *cursor, *cursor2;
501 AssociatedWindow *wnd;
503 TRACE("(%p) %p %p %p\n",This,hwnd,pdimNew,ppdimPrev);
505 if (!ppdimPrev)
506 return E_INVALIDARG;
508 *ppdimPrev = NULL;
510 LIST_FOR_EACH_SAFE(cursor, cursor2, &This->AssociatedFocusWindows)
512 wnd = LIST_ENTRY(cursor,AssociatedWindow,entry);
513 if (wnd->hwnd == hwnd)
515 if (wnd->docmgr)
516 ITfDocumentMgr_AddRef(wnd->docmgr);
517 *ppdimPrev = wnd->docmgr;
518 wnd->docmgr = pdimNew;
519 if (GetFocus() == hwnd)
520 ThreadMgr_SetFocus(iface,pdimNew);
521 return S_OK;
525 wnd = HeapAlloc(GetProcessHeap(),0,sizeof(AssociatedWindow));
526 wnd->hwnd = hwnd;
527 wnd->docmgr = pdimNew;
528 list_add_head(&This->AssociatedFocusWindows,&wnd->entry);
530 if (GetFocus() == hwnd)
531 ThreadMgr_SetFocus(iface,pdimNew);
533 SetupWindowsHook(This);
535 return S_OK;
538 static HRESULT WINAPI ThreadMgr_IsThreadFocus( ITfThreadMgr* iface, BOOL *pfThreadFocus)
540 ThreadMgr *This = impl_from_ITfThreadMgr(iface);
541 HWND focus;
543 TRACE("(%p) %p\n",This,pfThreadFocus);
544 focus = GetFocus();
545 *pfThreadFocus = (focus == NULL);
546 return S_OK;
549 static HRESULT WINAPI ThreadMgr_GetFunctionProvider( ITfThreadMgr* iface, REFCLSID clsid,
550 ITfFunctionProvider **ppFuncProv)
552 ThreadMgr *This = impl_from_ITfThreadMgr(iface);
553 FIXME("STUB:(%p)\n",This);
554 return E_NOTIMPL;
557 static HRESULT WINAPI ThreadMgr_EnumFunctionProviders( ITfThreadMgr* iface,
558 IEnumTfFunctionProviders **ppEnum)
560 ThreadMgr *This = impl_from_ITfThreadMgr(iface);
561 FIXME("STUB:(%p)\n",This);
562 return E_NOTIMPL;
565 static HRESULT WINAPI ThreadMgr_GetGlobalCompartment( ITfThreadMgr* iface,
566 ITfCompartmentMgr **ppCompMgr)
568 ThreadMgr *This = impl_from_ITfThreadMgr(iface);
569 HRESULT hr;
570 TRACE("(%p) %p\n",This, ppCompMgr);
572 if (!ppCompMgr)
573 return E_INVALIDARG;
575 if (!globalCompartmentMgr)
577 hr = CompartmentMgr_Constructor(NULL,&IID_ITfCompartmentMgr,(IUnknown**)&globalCompartmentMgr);
578 if (FAILED(hr))
579 return hr;
582 ITfCompartmentMgr_AddRef(globalCompartmentMgr);
583 *ppCompMgr = globalCompartmentMgr;
584 return S_OK;
587 static const ITfThreadMgrVtbl ThreadMgrVtbl =
589 ThreadMgr_QueryInterface,
590 ThreadMgr_AddRef,
591 ThreadMgr_Release,
592 ThreadMgr_fnActivate,
593 ThreadMgr_fnDeactivate,
594 ThreadMgr_CreateDocumentMgr,
595 ThreadMgr_EnumDocumentMgrs,
596 ThreadMgr_GetFocus,
597 ThreadMgr_SetFocus,
598 ThreadMgr_AssociateFocus,
599 ThreadMgr_IsThreadFocus,
600 ThreadMgr_GetFunctionProvider,
601 ThreadMgr_EnumFunctionProviders,
602 ThreadMgr_GetGlobalCompartment
605 static HRESULT WINAPI Source_QueryInterface(ITfSource *iface, REFIID iid, LPVOID *ppvOut)
607 ThreadMgr *This = impl_from_ITfSource(iface);
608 return ITfThreadMgr_QueryInterface(&This->ITfThreadMgr_iface, iid, ppvOut);
611 static ULONG WINAPI Source_AddRef(ITfSource *iface)
613 ThreadMgr *This = impl_from_ITfSource(iface);
614 return ITfThreadMgr_AddRef(&This->ITfThreadMgr_iface);
617 static ULONG WINAPI Source_Release(ITfSource *iface)
619 ThreadMgr *This = impl_from_ITfSource(iface);
620 return ITfThreadMgr_Release(&This->ITfThreadMgr_iface);
623 /*****************************************************
624 * ITfSource functions
625 *****************************************************/
626 static HRESULT WINAPI ThreadMgrSource_AdviseSink(ITfSource *iface,
627 REFIID riid, IUnknown *punk, DWORD *pdwCookie)
629 ThreadMgr *This = impl_from_ITfSource(iface);
630 ThreadMgrSink *tms;
632 TRACE("(%p) %s %p %p\n",This,debugstr_guid(riid),punk,pdwCookie);
634 if (!riid || !punk || !pdwCookie)
635 return E_INVALIDARG;
637 if (IsEqualIID(riid, &IID_ITfThreadMgrEventSink))
639 tms = HeapAlloc(GetProcessHeap(),0,sizeof(ThreadMgrSink));
640 if (!tms)
641 return E_OUTOFMEMORY;
642 if (FAILED(IUnknown_QueryInterface(punk, riid, (LPVOID *)&tms->interfaces.pITfThreadMgrEventSink)))
644 HeapFree(GetProcessHeap(),0,tms);
645 return CONNECT_E_CANNOTCONNECT;
647 list_add_head(&This->ThreadMgrEventSink,&tms->entry);
648 *pdwCookie = generate_Cookie(COOKIE_MAGIC_TMSINK, tms);
650 else
652 FIXME("(%p) Unhandled Sink: %s\n",This,debugstr_guid(riid));
653 return E_NOTIMPL;
656 TRACE("cookie %x\n",*pdwCookie);
658 return S_OK;
661 static HRESULT WINAPI ThreadMgrSource_UnadviseSink(ITfSource *iface, DWORD pdwCookie)
663 ThreadMgr *This = impl_from_ITfSource(iface);
664 ThreadMgrSink *sink;
666 TRACE("(%p) %x\n",This,pdwCookie);
668 if (get_Cookie_magic(pdwCookie)!=COOKIE_MAGIC_TMSINK)
669 return E_INVALIDARG;
671 sink = remove_Cookie(pdwCookie);
672 if (!sink)
673 return CONNECT_E_NOCONNECTION;
675 list_remove(&sink->entry);
676 free_sink(sink);
678 return S_OK;
681 static const ITfSourceVtbl ThreadMgrSourceVtbl =
683 Source_QueryInterface,
684 Source_AddRef,
685 Source_Release,
686 ThreadMgrSource_AdviseSink,
687 ThreadMgrSource_UnadviseSink,
690 /*****************************************************
691 * ITfKeystrokeMgr functions
692 *****************************************************/
694 static HRESULT WINAPI KeystrokeMgr_QueryInterface(ITfKeystrokeMgr *iface, REFIID iid, LPVOID *ppvOut)
696 ThreadMgr *This = impl_from_ITfKeystrokeMgr(iface);
697 return ITfThreadMgr_QueryInterface(&This->ITfThreadMgr_iface, iid, ppvOut);
700 static ULONG WINAPI KeystrokeMgr_AddRef(ITfKeystrokeMgr *iface)
702 ThreadMgr *This = impl_from_ITfKeystrokeMgr(iface);
703 return ITfThreadMgr_AddRef(&This->ITfThreadMgr_iface);
706 static ULONG WINAPI KeystrokeMgr_Release(ITfKeystrokeMgr *iface)
708 ThreadMgr *This = impl_from_ITfKeystrokeMgr(iface);
709 return ITfThreadMgr_Release(&This->ITfThreadMgr_iface);
712 static HRESULT WINAPI KeystrokeMgr_AdviseKeyEventSink(ITfKeystrokeMgr *iface,
713 TfClientId tid, ITfKeyEventSink *pSink, BOOL fForeground)
715 ThreadMgr *This = impl_from_ITfKeystrokeMgr(iface);
716 CLSID textservice;
717 ITfKeyEventSink *check = NULL;
719 TRACE("(%p) %x %p %i\n",This,tid,pSink,fForeground);
721 if (!tid || !pSink)
722 return E_INVALIDARG;
724 textservice = get_textservice_clsid(tid);
725 if (IsEqualCLSID(&GUID_NULL,&textservice))
726 return E_INVALIDARG;
728 get_textservice_sink(tid, &IID_ITfKeyEventSink, (IUnknown**)&check);
729 if (check != NULL)
730 return CONNECT_E_ADVISELIMIT;
732 if (FAILED(ITfKeyEventSink_QueryInterface(pSink,&IID_ITfKeyEventSink,(LPVOID*) &check)))
733 return E_INVALIDARG;
735 set_textservice_sink(tid, &IID_ITfKeyEventSink, (IUnknown*)check);
737 if (fForeground)
739 if (This->forgroundKeyEventSink)
741 ITfKeyEventSink_OnSetFocus(This->forgroundKeyEventSink, FALSE);
742 ITfKeyEventSink_Release(This->forgroundKeyEventSink);
744 ITfKeyEventSink_AddRef(check);
745 ITfKeyEventSink_OnSetFocus(check, TRUE);
746 This->forgroundKeyEventSink = check;
747 This->forgroundTextService = textservice;
749 return S_OK;
752 static HRESULT WINAPI KeystrokeMgr_UnadviseKeyEventSink(ITfKeystrokeMgr *iface,
753 TfClientId tid)
755 ThreadMgr *This = impl_from_ITfKeystrokeMgr(iface);
756 CLSID textservice;
757 ITfKeyEventSink *check = NULL;
758 TRACE("(%p) %x\n",This,tid);
760 if (!tid)
761 return E_INVALIDARG;
763 textservice = get_textservice_clsid(tid);
764 if (IsEqualCLSID(&GUID_NULL,&textservice))
765 return E_INVALIDARG;
767 get_textservice_sink(tid, &IID_ITfKeyEventSink, (IUnknown**)&check);
769 if (!check)
770 return CONNECT_E_NOCONNECTION;
772 set_textservice_sink(tid, &IID_ITfKeyEventSink, NULL);
773 ITfKeyEventSink_Release(check);
775 if (This->forgroundKeyEventSink == check)
777 ITfKeyEventSink_Release(This->forgroundKeyEventSink);
778 This->forgroundKeyEventSink = NULL;
779 This->forgroundTextService = GUID_NULL;
781 return S_OK;
784 static HRESULT WINAPI KeystrokeMgr_GetForeground(ITfKeystrokeMgr *iface,
785 CLSID *pclsid)
787 ThreadMgr *This = impl_from_ITfKeystrokeMgr(iface);
788 TRACE("(%p) %p\n",This,pclsid);
789 if (!pclsid)
790 return E_INVALIDARG;
792 if (IsEqualCLSID(&This->forgroundTextService,&GUID_NULL))
793 return S_FALSE;
795 *pclsid = This->forgroundTextService;
796 return S_OK;
799 static HRESULT WINAPI KeystrokeMgr_TestKeyDown(ITfKeystrokeMgr *iface,
800 WPARAM wParam, LPARAM lParam, BOOL *pfEaten)
802 ThreadMgr *This = impl_from_ITfKeystrokeMgr(iface);
803 FIXME("STUB:(%p)\n",This);
804 return E_NOTIMPL;
807 static HRESULT WINAPI KeystrokeMgr_TestKeyUp(ITfKeystrokeMgr *iface,
808 WPARAM wParam, LPARAM lParam, BOOL *pfEaten)
810 ThreadMgr *This = impl_from_ITfKeystrokeMgr(iface);
811 FIXME("STUB:(%p)\n",This);
812 return E_NOTIMPL;
815 static HRESULT WINAPI KeystrokeMgr_KeyDown(ITfKeystrokeMgr *iface,
816 WPARAM wParam, LPARAM lParam, BOOL *pfEaten)
818 ThreadMgr *This = impl_from_ITfKeystrokeMgr(iface);
819 FIXME("STUB:(%p)\n",This);
820 return E_NOTIMPL;
823 static HRESULT WINAPI KeystrokeMgr_KeyUp(ITfKeystrokeMgr *iface,
824 WPARAM wParam, LPARAM lParam, BOOL *pfEaten)
826 ThreadMgr *This = impl_from_ITfKeystrokeMgr(iface);
827 FIXME("STUB:(%p)\n",This);
828 return E_NOTIMPL;
831 static HRESULT WINAPI KeystrokeMgr_GetPreservedKey(ITfKeystrokeMgr *iface,
832 ITfContext *pic, const TF_PRESERVEDKEY *pprekey, GUID *pguid)
834 ThreadMgr *This = impl_from_ITfKeystrokeMgr(iface);
835 FIXME("STUB:(%p)\n",This);
836 return E_NOTIMPL;
839 static HRESULT WINAPI KeystrokeMgr_IsPreservedKey(ITfKeystrokeMgr *iface,
840 REFGUID rguid, const TF_PRESERVEDKEY *pprekey, BOOL *pfRegistered)
842 ThreadMgr *This = impl_from_ITfKeystrokeMgr(iface);
843 struct list *cursor;
845 TRACE("(%p) %s (%x %x) %p\n",This,debugstr_guid(rguid), (pprekey)?pprekey->uVKey:0, (pprekey)?pprekey->uModifiers:0, pfRegistered);
847 if (!rguid || !pprekey || !pfRegistered)
848 return E_INVALIDARG;
850 LIST_FOR_EACH(cursor, &This->CurrentPreservedKeys)
852 PreservedKey* key = LIST_ENTRY(cursor,PreservedKey,entry);
853 if (IsEqualGUID(rguid,&key->guid) && pprekey->uVKey == key->prekey.uVKey && pprekey->uModifiers == key->prekey.uModifiers)
855 *pfRegistered = TRUE;
856 return S_OK;
860 *pfRegistered = FALSE;
861 return S_FALSE;
864 static HRESULT WINAPI KeystrokeMgr_PreserveKey(ITfKeystrokeMgr *iface,
865 TfClientId tid, REFGUID rguid, const TF_PRESERVEDKEY *prekey,
866 const WCHAR *pchDesc, ULONG cchDesc)
868 ThreadMgr *This = impl_from_ITfKeystrokeMgr(iface);
869 struct list *cursor;
870 PreservedKey *newkey;
872 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));
874 if (!tid || ! rguid || !prekey || (cchDesc && !pchDesc))
875 return E_INVALIDARG;
877 LIST_FOR_EACH(cursor, &This->CurrentPreservedKeys)
879 PreservedKey* key = LIST_ENTRY(cursor,PreservedKey,entry);
880 if (IsEqualGUID(rguid,&key->guid) && prekey->uVKey == key->prekey.uVKey && prekey->uModifiers == key->prekey.uModifiers)
881 return TF_E_ALREADY_EXISTS;
884 newkey = HeapAlloc(GetProcessHeap(),0,sizeof(PreservedKey));
885 if (!newkey)
886 return E_OUTOFMEMORY;
888 newkey->guid = *rguid;
889 newkey->prekey = *prekey;
890 newkey->tid = tid;
891 newkey->description = NULL;
892 if (cchDesc)
894 newkey->description = HeapAlloc(GetProcessHeap(),0,cchDesc * sizeof(WCHAR));
895 if (!newkey->description)
897 HeapFree(GetProcessHeap(),0,newkey);
898 return E_OUTOFMEMORY;
900 memcpy(newkey->description, pchDesc, cchDesc*sizeof(WCHAR));
903 list_add_head(&This->CurrentPreservedKeys,&newkey->entry);
905 return S_OK;
908 static HRESULT WINAPI KeystrokeMgr_UnpreserveKey(ITfKeystrokeMgr *iface,
909 REFGUID rguid, const TF_PRESERVEDKEY *pprekey)
911 ThreadMgr *This = impl_from_ITfKeystrokeMgr(iface);
912 PreservedKey* key = NULL;
913 struct list *cursor;
914 TRACE("(%p) %s (%x %x)\n",This,debugstr_guid(rguid),(pprekey)?pprekey->uVKey:0, (pprekey)?pprekey->uModifiers:0);
916 if (!pprekey || !rguid)
917 return E_INVALIDARG;
919 LIST_FOR_EACH(cursor, &This->CurrentPreservedKeys)
921 key = LIST_ENTRY(cursor,PreservedKey,entry);
922 if (IsEqualGUID(rguid,&key->guid) && pprekey->uVKey == key->prekey.uVKey && pprekey->uModifiers == key->prekey.uModifiers)
923 break;
924 key = NULL;
927 if (!key)
928 return CONNECT_E_NOCONNECTION;
930 list_remove(&key->entry);
931 HeapFree(GetProcessHeap(),0,key->description);
932 HeapFree(GetProcessHeap(),0,key);
934 return S_OK;
937 static HRESULT WINAPI KeystrokeMgr_SetPreservedKeyDescription(ITfKeystrokeMgr *iface,
938 REFGUID rguid, const WCHAR *pchDesc, ULONG cchDesc)
940 ThreadMgr *This = impl_from_ITfKeystrokeMgr(iface);
941 FIXME("STUB:(%p)\n",This);
942 return E_NOTIMPL;
945 static HRESULT WINAPI KeystrokeMgr_GetPreservedKeyDescription(ITfKeystrokeMgr *iface,
946 REFGUID rguid, BSTR *pbstrDesc)
948 ThreadMgr *This = impl_from_ITfKeystrokeMgr(iface);
949 FIXME("STUB:(%p)\n",This);
950 return E_NOTIMPL;
953 static HRESULT WINAPI KeystrokeMgr_SimulatePreservedKey(ITfKeystrokeMgr *iface,
954 ITfContext *pic, REFGUID rguid, BOOL *pfEaten)
956 ThreadMgr *This = impl_from_ITfKeystrokeMgr(iface);
957 FIXME("STUB:(%p)\n",This);
958 return E_NOTIMPL;
961 static const ITfKeystrokeMgrVtbl KeystrokeMgrVtbl =
963 KeystrokeMgr_QueryInterface,
964 KeystrokeMgr_AddRef,
965 KeystrokeMgr_Release,
966 KeystrokeMgr_AdviseKeyEventSink,
967 KeystrokeMgr_UnadviseKeyEventSink,
968 KeystrokeMgr_GetForeground,
969 KeystrokeMgr_TestKeyDown,
970 KeystrokeMgr_TestKeyUp,
971 KeystrokeMgr_KeyDown,
972 KeystrokeMgr_KeyUp,
973 KeystrokeMgr_GetPreservedKey,
974 KeystrokeMgr_IsPreservedKey,
975 KeystrokeMgr_PreserveKey,
976 KeystrokeMgr_UnpreserveKey,
977 KeystrokeMgr_SetPreservedKeyDescription,
978 KeystrokeMgr_GetPreservedKeyDescription,
979 KeystrokeMgr_SimulatePreservedKey
982 /*****************************************************
983 * ITfMessagePump functions
984 *****************************************************/
986 static HRESULT WINAPI MessagePump_QueryInterface(ITfMessagePump *iface, REFIID iid, LPVOID *ppvOut)
988 ThreadMgr *This = impl_from_ITfMessagePump(iface);
989 return ITfThreadMgr_QueryInterface(&This->ITfThreadMgr_iface, iid, ppvOut);
992 static ULONG WINAPI MessagePump_AddRef(ITfMessagePump *iface)
994 ThreadMgr *This = impl_from_ITfMessagePump(iface);
995 return ITfThreadMgr_AddRef(&This->ITfThreadMgr_iface);
998 static ULONG WINAPI MessagePump_Release(ITfMessagePump *iface)
1000 ThreadMgr *This = impl_from_ITfMessagePump(iface);
1001 return ITfThreadMgr_Release(&This->ITfThreadMgr_iface);
1004 static HRESULT WINAPI MessagePump_PeekMessageA(ITfMessagePump *iface,
1005 LPMSG pMsg, HWND hwnd, UINT wMsgFilterMin, UINT wMsgFilterMax,
1006 UINT wRemoveMsg, BOOL *pfResult)
1008 if (!pfResult)
1009 return E_INVALIDARG;
1010 *pfResult = PeekMessageA(pMsg, hwnd, wMsgFilterMin, wMsgFilterMax, wRemoveMsg);
1011 return S_OK;
1014 static HRESULT WINAPI MessagePump_GetMessageA(ITfMessagePump *iface,
1015 LPMSG pMsg, HWND hwnd, UINT wMsgFilterMin, UINT wMsgFilterMax,
1016 BOOL *pfResult)
1018 if (!pfResult)
1019 return E_INVALIDARG;
1020 *pfResult = GetMessageA(pMsg, hwnd, wMsgFilterMin, wMsgFilterMax);
1021 return S_OK;
1024 static HRESULT WINAPI MessagePump_PeekMessageW(ITfMessagePump *iface,
1025 LPMSG pMsg, HWND hwnd, UINT wMsgFilterMin, UINT wMsgFilterMax,
1026 UINT wRemoveMsg, BOOL *pfResult)
1028 if (!pfResult)
1029 return E_INVALIDARG;
1030 *pfResult = PeekMessageW(pMsg, hwnd, wMsgFilterMin, wMsgFilterMax, wRemoveMsg);
1031 return S_OK;
1034 static HRESULT WINAPI MessagePump_GetMessageW(ITfMessagePump *iface,
1035 LPMSG pMsg, HWND hwnd, UINT wMsgFilterMin, UINT wMsgFilterMax,
1036 BOOL *pfResult)
1038 if (!pfResult)
1039 return E_INVALIDARG;
1040 *pfResult = GetMessageW(pMsg, hwnd, wMsgFilterMin, wMsgFilterMax);
1041 return S_OK;
1044 static const ITfMessagePumpVtbl MessagePumpVtbl =
1046 MessagePump_QueryInterface,
1047 MessagePump_AddRef,
1048 MessagePump_Release,
1049 MessagePump_PeekMessageA,
1050 MessagePump_GetMessageA,
1051 MessagePump_PeekMessageW,
1052 MessagePump_GetMessageW
1055 /*****************************************************
1056 * ITfClientId functions
1057 *****************************************************/
1059 static HRESULT WINAPI ClientId_QueryInterface(ITfClientId *iface, REFIID iid, LPVOID *ppvOut)
1061 ThreadMgr *This = impl_from_ITfClientId(iface);
1062 return ITfThreadMgr_QueryInterface(&This->ITfThreadMgr_iface, iid, ppvOut);
1065 static ULONG WINAPI ClientId_AddRef(ITfClientId *iface)
1067 ThreadMgr *This = impl_from_ITfClientId(iface);
1068 return ITfThreadMgr_AddRef(&This->ITfThreadMgr_iface);
1071 static ULONG WINAPI ClientId_Release(ITfClientId *iface)
1073 ThreadMgr *This = impl_from_ITfClientId(iface);
1074 return ITfThreadMgr_Release(&This->ITfThreadMgr_iface);
1077 static HRESULT WINAPI ClientId_GetClientId(ITfClientId *iface,
1078 REFCLSID rclsid, TfClientId *ptid)
1081 ThreadMgr *This = impl_from_ITfClientId(iface);
1082 HRESULT hr;
1083 ITfCategoryMgr *catmgr;
1085 TRACE("(%p) %s\n",This,debugstr_guid(rclsid));
1087 CategoryMgr_Constructor(NULL,(IUnknown**)&catmgr);
1088 hr = ITfCategoryMgr_RegisterGUID(catmgr,rclsid,ptid);
1089 ITfCategoryMgr_Release(catmgr);
1091 return hr;
1094 static const ITfClientIdVtbl ClientIdVtbl =
1096 ClientId_QueryInterface,
1097 ClientId_AddRef,
1098 ClientId_Release,
1099 ClientId_GetClientId
1102 /*****************************************************
1103 * ITfThreadMgrEventSink functions (internal)
1104 *****************************************************/
1105 static HRESULT WINAPI ThreadMgrEventSink_QueryInterface(ITfThreadMgrEventSink *iface, REFIID iid, LPVOID *ppvOut)
1107 ThreadMgr *This = impl_from_ITfThreadMgrEventSink(iface);
1108 return ITfThreadMgr_QueryInterface(&This->ITfThreadMgr_iface, iid, ppvOut);
1111 static ULONG WINAPI ThreadMgrEventSink_AddRef(ITfThreadMgrEventSink *iface)
1113 ThreadMgr *This = impl_from_ITfThreadMgrEventSink(iface);
1114 return ITfThreadMgr_AddRef(&This->ITfThreadMgr_iface);
1117 static ULONG WINAPI ThreadMgrEventSink_Release(ITfThreadMgrEventSink *iface)
1119 ThreadMgr *This = impl_from_ITfThreadMgrEventSink(iface);
1120 return ITfThreadMgr_Release(&This->ITfThreadMgr_iface);
1124 static HRESULT WINAPI ThreadMgrEventSink_OnInitDocumentMgr(
1125 ITfThreadMgrEventSink *iface,ITfDocumentMgr *pdim)
1127 struct list *cursor;
1128 ThreadMgr *This = impl_from_ITfThreadMgrEventSink(iface);
1130 TRACE("(%p) %p\n",This,pdim);
1132 LIST_FOR_EACH(cursor, &This->ThreadMgrEventSink)
1134 ThreadMgrSink* sink = LIST_ENTRY(cursor,ThreadMgrSink,entry);
1135 ITfThreadMgrEventSink_OnInitDocumentMgr(sink->interfaces.pITfThreadMgrEventSink,pdim);
1138 return S_OK;
1141 static HRESULT WINAPI ThreadMgrEventSink_OnUninitDocumentMgr(
1142 ITfThreadMgrEventSink *iface, ITfDocumentMgr *pdim)
1144 struct list *cursor;
1145 ThreadMgr *This = impl_from_ITfThreadMgrEventSink(iface);
1147 TRACE("(%p) %p\n",This,pdim);
1149 LIST_FOR_EACH(cursor, &This->ThreadMgrEventSink)
1151 ThreadMgrSink* sink = LIST_ENTRY(cursor,ThreadMgrSink,entry);
1152 ITfThreadMgrEventSink_OnUninitDocumentMgr(sink->interfaces.pITfThreadMgrEventSink,pdim);
1155 return S_OK;
1158 static HRESULT WINAPI ThreadMgrEventSink_OnSetFocus(
1159 ITfThreadMgrEventSink *iface, ITfDocumentMgr *pdimFocus,
1160 ITfDocumentMgr *pdimPrevFocus)
1162 struct list *cursor;
1163 ThreadMgr *This = impl_from_ITfThreadMgrEventSink(iface);
1165 TRACE("(%p) %p %p\n",This,pdimFocus, pdimPrevFocus);
1167 LIST_FOR_EACH(cursor, &This->ThreadMgrEventSink)
1169 ThreadMgrSink* sink = LIST_ENTRY(cursor,ThreadMgrSink,entry);
1170 ITfThreadMgrEventSink_OnSetFocus(sink->interfaces.pITfThreadMgrEventSink, pdimFocus, pdimPrevFocus);
1173 return S_OK;
1176 static HRESULT WINAPI ThreadMgrEventSink_OnPushContext(
1177 ITfThreadMgrEventSink *iface, ITfContext *pic)
1179 struct list *cursor;
1180 ThreadMgr *This = impl_from_ITfThreadMgrEventSink(iface);
1182 TRACE("(%p) %p\n",This,pic);
1184 LIST_FOR_EACH(cursor, &This->ThreadMgrEventSink)
1186 ThreadMgrSink* sink = LIST_ENTRY(cursor,ThreadMgrSink,entry);
1187 ITfThreadMgrEventSink_OnPushContext(sink->interfaces.pITfThreadMgrEventSink,pic);
1190 return S_OK;
1193 static HRESULT WINAPI ThreadMgrEventSink_OnPopContext(
1194 ITfThreadMgrEventSink *iface, ITfContext *pic)
1196 struct list *cursor;
1197 ThreadMgr *This = impl_from_ITfThreadMgrEventSink(iface);
1199 TRACE("(%p) %p\n",This,pic);
1201 LIST_FOR_EACH(cursor, &This->ThreadMgrEventSink)
1203 ThreadMgrSink* sink = LIST_ENTRY(cursor,ThreadMgrSink,entry);
1204 ITfThreadMgrEventSink_OnPopContext(sink->interfaces.pITfThreadMgrEventSink,pic);
1207 return S_OK;
1210 static const ITfThreadMgrEventSinkVtbl ThreadMgrEventSinkVtbl =
1212 ThreadMgrEventSink_QueryInterface,
1213 ThreadMgrEventSink_AddRef,
1214 ThreadMgrEventSink_Release,
1215 ThreadMgrEventSink_OnInitDocumentMgr,
1216 ThreadMgrEventSink_OnUninitDocumentMgr,
1217 ThreadMgrEventSink_OnSetFocus,
1218 ThreadMgrEventSink_OnPushContext,
1219 ThreadMgrEventSink_OnPopContext
1222 /*****************************************************
1223 * ITfSourceSingle functions
1224 *****************************************************/
1225 static HRESULT WINAPI ThreadMgrSourceSingle_QueryInterface(ITfSourceSingle *iface, REFIID iid, LPVOID *ppvOut)
1227 ThreadMgr *This = impl_from_ITfSourceSingle(iface);
1228 return ITfThreadMgr_QueryInterface(&This->ITfThreadMgr_iface, iid, ppvOut);
1231 static ULONG WINAPI ThreadMgrSourceSingle_AddRef(ITfSourceSingle *iface)
1233 ThreadMgr *This = impl_from_ITfSourceSingle(iface);
1234 return ITfThreadMgr_AddRef(&This->ITfThreadMgr_iface);
1237 static ULONG WINAPI ThreadMgrSourceSingle_Release(ITfSourceSingle *iface)
1239 ThreadMgr *This = impl_from_ITfSourceSingle(iface);
1240 return ITfThreadMgr_Release(&This->ITfThreadMgr_iface);
1243 static HRESULT WINAPI ThreadMgrSourceSingle_AdviseSingleSink( ITfSourceSingle *iface,
1244 TfClientId tid, REFIID riid, IUnknown *punk)
1246 ThreadMgr *This = impl_from_ITfSourceSingle(iface);
1247 FIXME("STUB:(%p) %i %s %p\n",This, tid, debugstr_guid(riid),punk);
1248 return E_NOTIMPL;
1251 static HRESULT WINAPI ThreadMgrSourceSingle_UnadviseSingleSink( ITfSourceSingle *iface,
1252 TfClientId tid, REFIID riid)
1254 ThreadMgr *This = impl_from_ITfSourceSingle(iface);
1255 FIXME("STUB:(%p) %i %s\n",This, tid, debugstr_guid(riid));
1256 return E_NOTIMPL;
1259 static const ITfSourceSingleVtbl SourceSingleVtbl =
1261 ThreadMgrSourceSingle_QueryInterface,
1262 ThreadMgrSourceSingle_AddRef,
1263 ThreadMgrSourceSingle_Release,
1264 ThreadMgrSourceSingle_AdviseSingleSink,
1265 ThreadMgrSourceSingle_UnadviseSingleSink
1268 HRESULT ThreadMgr_Constructor(IUnknown *pUnkOuter, IUnknown **ppOut)
1270 ThreadMgr *This;
1271 if (pUnkOuter)
1272 return CLASS_E_NOAGGREGATION;
1274 /* Only 1 ThreadMgr is created per thread */
1275 This = TlsGetValue(tlsIndex);
1276 if (This)
1278 ThreadMgr_AddRef(&This->ITfThreadMgr_iface);
1279 *ppOut = (IUnknown*)&This->ITfThreadMgr_iface;
1280 return S_OK;
1283 This = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(ThreadMgr));
1284 if (This == NULL)
1285 return E_OUTOFMEMORY;
1287 This->ITfThreadMgr_iface.lpVtbl= &ThreadMgrVtbl;
1288 This->ITfSource_iface.lpVtbl = &ThreadMgrSourceVtbl;
1289 This->ITfKeystrokeMgr_iface.lpVtbl= &KeystrokeMgrVtbl;
1290 This->ITfMessagePump_iface.lpVtbl = &MessagePumpVtbl;
1291 This->ITfClientId_iface.lpVtbl = &ClientIdVtbl;
1292 This->ITfThreadMgrEventSink_iface.lpVtbl = &ThreadMgrEventSinkVtbl;
1293 This->ITfSourceSingle_iface.lpVtbl = &SourceSingleVtbl;
1294 This->refCount = 1;
1295 TlsSetValue(tlsIndex,This);
1297 CompartmentMgr_Constructor((IUnknown*)This, &IID_IUnknown, (IUnknown**)&This->CompartmentMgr);
1299 list_init(&This->CurrentPreservedKeys);
1300 list_init(&This->CreatedDocumentMgrs);
1301 list_init(&This->AssociatedFocusWindows);
1303 list_init(&This->ActiveLanguageProfileNotifySink);
1304 list_init(&This->DisplayAttributeNotifySink);
1305 list_init(&This->KeyTraceEventSink);
1306 list_init(&This->PreservedKeyNotifySink);
1307 list_init(&This->ThreadFocusSink);
1308 list_init(&This->ThreadMgrEventSink);
1310 TRACE("returning %p\n", This);
1311 *ppOut = (IUnknown *)&This->ITfThreadMgr_iface;
1312 return S_OK;
1315 /**************************************************
1316 * IEnumTfDocumentMgrs implementation
1317 **************************************************/
1318 static void EnumTfDocumentMgr_Destructor(EnumTfDocumentMgr *This)
1320 TRACE("destroying %p\n", This);
1321 HeapFree(GetProcessHeap(),0,This);
1324 static HRESULT WINAPI EnumTfDocumentMgr_QueryInterface(IEnumTfDocumentMgrs *iface, REFIID iid, LPVOID *ppvOut)
1326 EnumTfDocumentMgr *This = impl_from_IEnumTfDocumentMgrs(iface);
1327 *ppvOut = NULL;
1329 if (IsEqualIID(iid, &IID_IUnknown) || IsEqualIID(iid, &IID_IEnumTfDocumentMgrs))
1331 *ppvOut = &This->IEnumTfDocumentMgrs_iface;
1334 if (*ppvOut)
1336 IEnumTfDocumentMgrs_AddRef(iface);
1337 return S_OK;
1340 WARN("unsupported interface: %s\n", debugstr_guid(iid));
1341 return E_NOINTERFACE;
1344 static ULONG WINAPI EnumTfDocumentMgr_AddRef(IEnumTfDocumentMgrs *iface)
1346 EnumTfDocumentMgr *This = impl_from_IEnumTfDocumentMgrs(iface);
1347 return InterlockedIncrement(&This->refCount);
1350 static ULONG WINAPI EnumTfDocumentMgr_Release(IEnumTfDocumentMgrs *iface)
1352 EnumTfDocumentMgr *This = impl_from_IEnumTfDocumentMgrs(iface);
1353 ULONG ret;
1355 ret = InterlockedDecrement(&This->refCount);
1356 if (ret == 0)
1357 EnumTfDocumentMgr_Destructor(This);
1358 return ret;
1361 static HRESULT WINAPI EnumTfDocumentMgr_Next(IEnumTfDocumentMgrs *iface,
1362 ULONG ulCount, ITfDocumentMgr **rgDocumentMgr, ULONG *pcFetched)
1364 EnumTfDocumentMgr *This = impl_from_IEnumTfDocumentMgrs(iface);
1365 ULONG fetched = 0;
1367 TRACE("(%p)\n",This);
1369 if (rgDocumentMgr == NULL) return E_POINTER;
1371 while (fetched < ulCount)
1373 DocumentMgrEntry *mgrentry;
1374 if (This->index == NULL)
1375 break;
1377 mgrentry = LIST_ENTRY(This->index,DocumentMgrEntry,entry);
1378 if (mgrentry == NULL)
1379 break;
1381 *rgDocumentMgr = mgrentry->docmgr;
1382 ITfDocumentMgr_AddRef(*rgDocumentMgr);
1384 This->index = list_next(This->head, This->index);
1385 ++fetched;
1386 ++rgDocumentMgr;
1389 if (pcFetched) *pcFetched = fetched;
1390 return fetched == ulCount ? S_OK : S_FALSE;
1393 static HRESULT WINAPI EnumTfDocumentMgr_Skip( IEnumTfDocumentMgrs* iface, ULONG celt)
1395 EnumTfDocumentMgr *This = impl_from_IEnumTfDocumentMgrs(iface);
1396 ULONG i;
1398 TRACE("(%p)\n",This);
1399 for(i = 0; i < celt && This->index != NULL; i++)
1400 This->index = list_next(This->head, This->index);
1401 return S_OK;
1404 static HRESULT WINAPI EnumTfDocumentMgr_Reset( IEnumTfDocumentMgrs* iface)
1406 EnumTfDocumentMgr *This = impl_from_IEnumTfDocumentMgrs(iface);
1407 TRACE("(%p)\n",This);
1408 This->index = list_head(This->head);
1409 return S_OK;
1412 static HRESULT WINAPI EnumTfDocumentMgr_Clone( IEnumTfDocumentMgrs *iface,
1413 IEnumTfDocumentMgrs **ppenum)
1415 EnumTfDocumentMgr *This = impl_from_IEnumTfDocumentMgrs(iface);
1416 HRESULT res;
1418 TRACE("(%p)\n",This);
1420 if (ppenum == NULL) return E_POINTER;
1422 res = EnumTfDocumentMgr_Constructor(This->head, ppenum);
1423 if (SUCCEEDED(res))
1425 EnumTfDocumentMgr *new_This = impl_from_IEnumTfDocumentMgrs(*ppenum);
1426 new_This->index = This->index;
1428 return res;
1431 static const IEnumTfDocumentMgrsVtbl EnumTfDocumentMgrsVtbl =
1433 EnumTfDocumentMgr_QueryInterface,
1434 EnumTfDocumentMgr_AddRef,
1435 EnumTfDocumentMgr_Release,
1436 EnumTfDocumentMgr_Clone,
1437 EnumTfDocumentMgr_Next,
1438 EnumTfDocumentMgr_Reset,
1439 EnumTfDocumentMgr_Skip
1442 static HRESULT EnumTfDocumentMgr_Constructor(struct list* head, IEnumTfDocumentMgrs **ppOut)
1444 EnumTfDocumentMgr *This;
1446 This = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(EnumTfDocumentMgr));
1447 if (This == NULL)
1448 return E_OUTOFMEMORY;
1450 This->IEnumTfDocumentMgrs_iface.lpVtbl= &EnumTfDocumentMgrsVtbl;
1451 This->refCount = 1;
1452 This->head = head;
1453 This->index = list_head(This->head);
1455 TRACE("returning %p\n", This);
1456 *ppOut = (IEnumTfDocumentMgrs*)This;
1457 return S_OK;
1460 void ThreadMgr_OnDocumentMgrDestruction(ITfThreadMgr *iface, ITfDocumentMgr *mgr)
1462 ThreadMgr *This = impl_from_ITfThreadMgr(iface);
1463 struct list *cursor;
1464 LIST_FOR_EACH(cursor, &This->CreatedDocumentMgrs)
1466 DocumentMgrEntry *mgrentry = LIST_ENTRY(cursor,DocumentMgrEntry,entry);
1467 if (mgrentry->docmgr == mgr)
1469 list_remove(cursor);
1470 HeapFree(GetProcessHeap(),0,mgrentry);
1471 return;
1474 FIXME("ITfDocumentMgr %p not found in this thread\n",mgr);