xref: /reactos/dll/win32/msctf/threadmgr.c (revision ac50127e)
1 /*
2  *  ITfThreadMgr implementation
3  *
4  *  Copyright 2008 Aric Stewart, CodeWeavers
5  *
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.
10  *
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.
15  *
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
19  */
20 
21 #include <stdarg.h>
22 
23 #define COBJMACROS
24 
25 #include "wine/debug.h"
26 #include "windef.h"
27 #include "winbase.h"
28 #include "winreg.h"
29 #include "winuser.h"
30 #include "shlwapi.h"
31 #include "winerror.h"
32 #include "objbase.h"
33 #include "olectl.h"
34 
35 #include "msctf.h"
36 #include "msctf_internal.h"
37 
38 WINE_DEFAULT_DEBUG_CHANNEL(msctf);
39 
40 typedef struct tagPreservedKey
41 {
42     struct list     entry;
43     GUID            guid;
44     TF_PRESERVEDKEY prekey;
45     LPWSTR          description;
46     TfClientId      tid;
47 } PreservedKey;
48 
49 typedef struct tagDocumentMgrs
50 {
51     struct list     entry;
52     ITfDocumentMgr  *docmgr;
53 } DocumentMgrEntry;
54 
55 typedef struct tagAssociatedWindow
56 {
57     struct list     entry;
58     HWND            hwnd;
59     ITfDocumentMgr  *docmgr;
60 } AssociatedWindow;
61 
62 typedef struct tagACLMulti {
63     ITfThreadMgrEx ITfThreadMgrEx_iface;
64     ITfSource ITfSource_iface;
65     ITfKeystrokeMgr ITfKeystrokeMgr_iface;
66     ITfMessagePump ITfMessagePump_iface;
67     ITfClientId ITfClientId_iface;
68     /* const ITfThreadMgrExVtbl *ThreadMgrExVtbl; */
69     /* const ITfConfigureSystemKeystrokeFeedVtbl *ConfigureSystemKeystrokeFeedVtbl; */
70     /* const ITfLangBarItemMgrVtbl *LangBarItemMgrVtbl; */
71     ITfUIElementMgr ITfUIElementMgr_iface;
72     ITfSourceSingle ITfSourceSingle_iface;
73     LONG refCount;
74 
75     /* Aggregation */
76     ITfCompartmentMgr  *CompartmentMgr;
77 
78     ITfThreadMgrEventSink ITfThreadMgrEventSink_iface; /* internal */
79 
80     ITfDocumentMgr *focus;
81     LONG activationCount;
82 
83     ITfKeyEventSink *foregroundKeyEventSink;
84     CLSID foregroundTextService;
85 
86     struct list CurrentPreservedKeys;
87     struct list CreatedDocumentMgrs;
88 
89     struct list AssociatedFocusWindows;
90     HHOOK  focusHook;
91 
92     /* kept as separate lists to reduce unnecessary iterations */
93     struct list     ActiveLanguageProfileNotifySink;
94     struct list     DisplayAttributeNotifySink;
95     struct list     KeyTraceEventSink;
96     struct list     PreservedKeyNotifySink;
97     struct list     ThreadFocusSink;
98     struct list     ThreadMgrEventSink;
99     struct list     UIElementSink;
100     struct list     InputProcessorProfileActivationSink;
101 } ThreadMgr;
102 
103 typedef struct tagEnumTfDocumentMgr {
104     IEnumTfDocumentMgrs IEnumTfDocumentMgrs_iface;
105     LONG refCount;
106 
107     struct list *index;
108     struct list *head;
109 } EnumTfDocumentMgr;
110 
111 static HRESULT EnumTfDocumentMgr_Constructor(struct list* head, IEnumTfDocumentMgrs **ppOut);
112 
impl_from_ITfThreadMgrEx(ITfThreadMgrEx * iface)113 static inline ThreadMgr *impl_from_ITfThreadMgrEx(ITfThreadMgrEx *iface)
114 {
115     return CONTAINING_RECORD(iface, ThreadMgr, ITfThreadMgrEx_iface);
116 }
117 
impl_from_ITfSource(ITfSource * iface)118 static inline ThreadMgr *impl_from_ITfSource(ITfSource *iface)
119 {
120     return CONTAINING_RECORD(iface, ThreadMgr, ITfSource_iface);
121 }
122 
impl_from_ITfKeystrokeMgr(ITfKeystrokeMgr * iface)123 static inline ThreadMgr *impl_from_ITfKeystrokeMgr(ITfKeystrokeMgr *iface)
124 {
125     return CONTAINING_RECORD(iface, ThreadMgr, ITfKeystrokeMgr_iface);
126 }
127 
impl_from_ITfMessagePump(ITfMessagePump * iface)128 static inline ThreadMgr *impl_from_ITfMessagePump(ITfMessagePump *iface)
129 {
130     return CONTAINING_RECORD(iface, ThreadMgr, ITfMessagePump_iface);
131 }
132 
impl_from_ITfClientId(ITfClientId * iface)133 static inline ThreadMgr *impl_from_ITfClientId(ITfClientId *iface)
134 {
135     return CONTAINING_RECORD(iface, ThreadMgr, ITfClientId_iface);
136 }
137 
impl_from_ITfThreadMgrEventSink(ITfThreadMgrEventSink * iface)138 static inline ThreadMgr *impl_from_ITfThreadMgrEventSink(ITfThreadMgrEventSink *iface)
139 {
140     return CONTAINING_RECORD(iface, ThreadMgr, ITfThreadMgrEventSink_iface);
141 }
142 
impl_from_ITfUIElementMgr(ITfUIElementMgr * iface)143 static inline ThreadMgr *impl_from_ITfUIElementMgr(ITfUIElementMgr *iface)
144 {
145     return CONTAINING_RECORD(iface, ThreadMgr, ITfUIElementMgr_iface);
146 }
147 
impl_from_ITfSourceSingle(ITfSourceSingle * iface)148 static inline ThreadMgr *impl_from_ITfSourceSingle(ITfSourceSingle *iface)
149 {
150     return CONTAINING_RECORD(iface, ThreadMgr, ITfSourceSingle_iface);
151 }
152 
impl_from_IEnumTfDocumentMgrs(IEnumTfDocumentMgrs * iface)153 static inline EnumTfDocumentMgr *impl_from_IEnumTfDocumentMgrs(IEnumTfDocumentMgrs *iface)
154 {
155     return CONTAINING_RECORD(iface, EnumTfDocumentMgr, IEnumTfDocumentMgrs_iface);
156 }
157 
ThreadMgr_Destructor(ThreadMgr * This)158 static void ThreadMgr_Destructor(ThreadMgr *This)
159 {
160     struct list *cursor, *cursor2;
161 
162     /* unhook right away */
163     if (This->focusHook)
164         UnhookWindowsHookEx(This->focusHook);
165 
166     TlsSetValue(tlsIndex,NULL);
167     TRACE("destroying %p\n", This);
168     if (This->focus)
169         ITfDocumentMgr_Release(This->focus);
170 
171     free_sinks(&This->ActiveLanguageProfileNotifySink);
172     free_sinks(&This->DisplayAttributeNotifySink);
173     free_sinks(&This->KeyTraceEventSink);
174     free_sinks(&This->PreservedKeyNotifySink);
175     free_sinks(&This->ThreadFocusSink);
176     free_sinks(&This->ThreadMgrEventSink);
177     free_sinks(&This->UIElementSink);
178     free_sinks(&This->InputProcessorProfileActivationSink);
179 
180     LIST_FOR_EACH_SAFE(cursor, cursor2, &This->CurrentPreservedKeys)
181     {
182         PreservedKey* key = LIST_ENTRY(cursor,PreservedKey,entry);
183         list_remove(cursor);
184         HeapFree(GetProcessHeap(),0,key->description);
185         HeapFree(GetProcessHeap(),0,key);
186     }
187 
188     LIST_FOR_EACH_SAFE(cursor, cursor2, &This->CreatedDocumentMgrs)
189     {
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);
194     }
195 
196     LIST_FOR_EACH_SAFE(cursor, cursor2, &This->AssociatedFocusWindows)
197     {
198         AssociatedWindow *wnd = LIST_ENTRY(cursor,AssociatedWindow,entry);
199         list_remove(cursor);
200         HeapFree(GetProcessHeap(),0,wnd);
201     }
202 
203     CompartmentMgr_Destructor(This->CompartmentMgr);
204 
205     HeapFree(GetProcessHeap(),0,This);
206 }
207 
ThreadMgr_QueryInterface(ITfThreadMgrEx * iface,REFIID iid,LPVOID * ppvOut)208 static HRESULT WINAPI ThreadMgr_QueryInterface(ITfThreadMgrEx *iface, REFIID iid, LPVOID *ppvOut)
209 {
210     ThreadMgr *This = impl_from_ITfThreadMgrEx(iface);
211     *ppvOut = NULL;
212 
213     if (IsEqualIID(iid, &IID_IUnknown) || IsEqualIID(iid, &IID_ITfThreadMgr)
214         || IsEqualIID(iid, &IID_ITfThreadMgrEx))
215     {
216         *ppvOut = &This->ITfThreadMgrEx_iface;
217     }
218     else if (IsEqualIID(iid, &IID_ITfSource))
219     {
220         *ppvOut = &This->ITfSource_iface;
221     }
222     else if (IsEqualIID(iid, &IID_ITfKeystrokeMgr))
223     {
224         *ppvOut = &This->ITfKeystrokeMgr_iface;
225     }
226     else if (IsEqualIID(iid, &IID_ITfMessagePump))
227     {
228         *ppvOut = &This->ITfMessagePump_iface;
229     }
230     else if (IsEqualIID(iid, &IID_ITfClientId))
231     {
232         *ppvOut = &This->ITfClientId_iface;
233     }
234     else if (IsEqualIID(iid, &IID_ITfCompartmentMgr))
235     {
236         *ppvOut = This->CompartmentMgr;
237     }
238     else if (IsEqualIID(iid, &IID_ITfUIElementMgr))
239     {
240         *ppvOut = &This->ITfUIElementMgr_iface;
241     }
242     else if (IsEqualIID(iid, &IID_ITfSourceSingle))
243     {
244         *ppvOut = &This->ITfSourceSingle_iface;
245     }
246 
247     if (*ppvOut)
248     {
249         ITfThreadMgrEx_AddRef(iface);
250         return S_OK;
251     }
252 
253     WARN("unsupported interface: %s\n", debugstr_guid(iid));
254     return E_NOINTERFACE;
255 }
256 
ThreadMgr_AddRef(ITfThreadMgrEx * iface)257 static ULONG WINAPI ThreadMgr_AddRef(ITfThreadMgrEx *iface)
258 {
259     ThreadMgr *This = impl_from_ITfThreadMgrEx(iface);
260     return InterlockedIncrement(&This->refCount);
261 }
262 
ThreadMgr_Release(ITfThreadMgrEx * iface)263 static ULONG WINAPI ThreadMgr_Release(ITfThreadMgrEx *iface)
264 {
265     ThreadMgr *This = impl_from_ITfThreadMgrEx(iface);
266     ULONG ret;
267 
268     ret = InterlockedDecrement(&This->refCount);
269     if (ret == 0)
270         ThreadMgr_Destructor(This);
271     return ret;
272 }
273 
274 /*****************************************************
275  * ITfThreadMgr functions
276  *****************************************************/
277 
ThreadMgr_Activate(ITfThreadMgrEx * iface,TfClientId * id)278 static HRESULT WINAPI ThreadMgr_Activate(ITfThreadMgrEx *iface, TfClientId *id)
279 {
280     ThreadMgr *This = impl_from_ITfThreadMgrEx(iface);
281 
282     TRACE("(%p) %p\n", This, id);
283     return ITfThreadMgrEx_ActivateEx(iface, id, 0);
284 }
285 
ThreadMgr_Deactivate(ITfThreadMgrEx * iface)286 static HRESULT WINAPI ThreadMgr_Deactivate(ITfThreadMgrEx *iface)
287 {
288     ThreadMgr *This = impl_from_ITfThreadMgrEx(iface);
289     TRACE("(%p)\n",This);
290 
291     if (This->activationCount == 0)
292         return E_UNEXPECTED;
293 
294     This->activationCount --;
295 
296     if (This->activationCount == 0)
297     {
298         if (This->focus)
299         {
300             ITfThreadMgrEventSink_OnSetFocus(&This->ITfThreadMgrEventSink_iface, 0, This->focus);
301             ITfDocumentMgr_Release(This->focus);
302             This->focus = 0;
303         }
304     }
305 
306     deactivate_textservices();
307 
308     return S_OK;
309 }
310 
ThreadMgr_CreateDocumentMgr(ITfThreadMgrEx * iface,ITfDocumentMgr ** ppdim)311 static HRESULT WINAPI ThreadMgr_CreateDocumentMgr(ITfThreadMgrEx *iface, ITfDocumentMgr **ppdim)
312 {
313     ThreadMgr *This = impl_from_ITfThreadMgrEx(iface);
314     DocumentMgrEntry *mgrentry;
315     HRESULT hr;
316 
317     TRACE("(%p)\n",iface);
318     mgrentry = HeapAlloc(GetProcessHeap(),0,sizeof(DocumentMgrEntry));
319     if (mgrentry == NULL)
320         return E_OUTOFMEMORY;
321 
322     hr = DocumentMgr_Constructor(&This->ITfThreadMgrEventSink_iface, ppdim);
323 
324     if (SUCCEEDED(hr))
325     {
326         mgrentry->docmgr = *ppdim;
327         list_add_head(&This->CreatedDocumentMgrs,&mgrentry->entry);
328     }
329     else
330         HeapFree(GetProcessHeap(),0,mgrentry);
331 
332     return hr;
333 }
334 
ThreadMgr_EnumDocumentMgrs(ITfThreadMgrEx * iface,IEnumTfDocumentMgrs ** ppEnum)335 static HRESULT WINAPI ThreadMgr_EnumDocumentMgrs(ITfThreadMgrEx *iface, IEnumTfDocumentMgrs **ppEnum)
336 {
337     ThreadMgr *This = impl_from_ITfThreadMgrEx(iface);
338     TRACE("(%p) %p\n",This,ppEnum);
339 
340     if (!ppEnum)
341         return E_INVALIDARG;
342 
343     return EnumTfDocumentMgr_Constructor(&This->CreatedDocumentMgrs, ppEnum);
344 }
345 
ThreadMgr_GetFocus(ITfThreadMgrEx * iface,ITfDocumentMgr ** ppdimFocus)346 static HRESULT WINAPI ThreadMgr_GetFocus(ITfThreadMgrEx *iface, ITfDocumentMgr **ppdimFocus)
347 {
348     ThreadMgr *This = impl_from_ITfThreadMgrEx(iface);
349     TRACE("(%p)\n",This);
350 
351     if (!ppdimFocus)
352         return E_INVALIDARG;
353 
354     *ppdimFocus = This->focus;
355 
356     TRACE("->%p\n",This->focus);
357 
358     if (This->focus == NULL)
359         return S_FALSE;
360 
361     ITfDocumentMgr_AddRef(This->focus);
362 
363     return S_OK;
364 }
365 
ThreadMgr_SetFocus(ITfThreadMgrEx * iface,ITfDocumentMgr * pdimFocus)366 static HRESULT WINAPI ThreadMgr_SetFocus(ITfThreadMgrEx *iface, ITfDocumentMgr *pdimFocus)
367 {
368     ThreadMgr *This = impl_from_ITfThreadMgrEx(iface);
369     ITfDocumentMgr *check;
370 
371     TRACE("(%p) %p\n",This,pdimFocus);
372 
373     if (!pdimFocus)
374         check = NULL;
375     else if (FAILED(ITfDocumentMgr_QueryInterface(pdimFocus,&IID_ITfDocumentMgr,(LPVOID*) &check)))
376         return E_INVALIDARG;
377 
378     ITfThreadMgrEventSink_OnSetFocus(&This->ITfThreadMgrEventSink_iface, check, This->focus);
379 
380     if (This->focus)
381         ITfDocumentMgr_Release(This->focus);
382 
383     This->focus = check;
384     return S_OK;
385 }
386 
ThreadFocusHookProc(int nCode,WPARAM wParam,LPARAM lParam)387 static LRESULT CALLBACK ThreadFocusHookProc(int nCode, WPARAM wParam, LPARAM lParam)
388 {
389     ThreadMgr *This;
390 
391     This = TlsGetValue(tlsIndex);
392     if (!This)
393     {
394         ERR("Hook proc but no ThreadMgr for this thread. Serious Error\n");
395         return 0;
396     }
397     if (!This->focusHook)
398     {
399         ERR("Hook proc but no ThreadMgr focus Hook. Serious Error\n");
400         return 0;
401     }
402 
403     if (nCode == HCBT_SETFOCUS) /* focus change within our thread */
404     {
405         struct list *cursor;
406 
407         LIST_FOR_EACH(cursor, &This->AssociatedFocusWindows)
408         {
409             AssociatedWindow *wnd = LIST_ENTRY(cursor,AssociatedWindow,entry);
410             if (wnd->hwnd == (HWND)wParam)
411             {
412                 TRACE("Triggering Associated window focus\n");
413                 if (This->focus != wnd->docmgr)
414                     ThreadMgr_SetFocus(&This->ITfThreadMgrEx_iface, wnd->docmgr);
415                 break;
416             }
417         }
418     }
419 
420     return CallNextHookEx(This->focusHook, nCode, wParam, lParam);
421 }
422 
SetupWindowsHook(ThreadMgr * This)423 static HRESULT SetupWindowsHook(ThreadMgr *This)
424 {
425     if (!This->focusHook)
426     {
427         This->focusHook = SetWindowsHookExW(WH_CBT, ThreadFocusHookProc, 0,
428                              GetCurrentThreadId());
429         if (!This->focusHook)
430         {
431             ERR("Unable to set focus hook\n");
432             return E_FAIL;
433         }
434         return S_OK;
435     }
436     return S_FALSE;
437 }
438 
ThreadMgr_AssociateFocus(ITfThreadMgrEx * iface,HWND hwnd,ITfDocumentMgr * pdimNew,ITfDocumentMgr ** ppdimPrev)439 static HRESULT WINAPI ThreadMgr_AssociateFocus(ITfThreadMgrEx *iface, HWND hwnd,
440 ITfDocumentMgr *pdimNew, ITfDocumentMgr **ppdimPrev)
441 {
442     ThreadMgr *This = impl_from_ITfThreadMgrEx(iface);
443     struct list *cursor, *cursor2;
444     AssociatedWindow *wnd;
445 
446     TRACE("(%p) %p %p %p\n",This,hwnd,pdimNew,ppdimPrev);
447 
448     if (!ppdimPrev)
449         return E_INVALIDARG;
450 
451     *ppdimPrev = NULL;
452 
453     LIST_FOR_EACH_SAFE(cursor, cursor2, &This->AssociatedFocusWindows)
454     {
455         wnd = LIST_ENTRY(cursor,AssociatedWindow,entry);
456         if (wnd->hwnd == hwnd)
457         {
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;
465         }
466     }
467 
468     wnd = HeapAlloc(GetProcessHeap(),0,sizeof(AssociatedWindow));
469     wnd->hwnd = hwnd;
470     wnd->docmgr = pdimNew;
471     list_add_head(&This->AssociatedFocusWindows,&wnd->entry);
472 
473     if (GetFocus() == hwnd)
474         ThreadMgr_SetFocus(iface,pdimNew);
475 
476     SetupWindowsHook(This);
477 
478     return S_OK;
479 }
480 
ThreadMgr_IsThreadFocus(ITfThreadMgrEx * iface,BOOL * pfThreadFocus)481 static HRESULT WINAPI ThreadMgr_IsThreadFocus(ITfThreadMgrEx *iface, BOOL *pfThreadFocus)
482 {
483     ThreadMgr *This = impl_from_ITfThreadMgrEx(iface);
484     HWND focus;
485 
486     TRACE("(%p) %p\n",This,pfThreadFocus);
487     focus = GetFocus();
488     *pfThreadFocus = (focus == NULL);
489     return S_OK;
490 }
491 
ThreadMgr_GetFunctionProvider(ITfThreadMgrEx * iface,REFCLSID clsid,ITfFunctionProvider ** ppFuncProv)492 static HRESULT WINAPI ThreadMgr_GetFunctionProvider(ITfThreadMgrEx *iface, REFCLSID clsid,
493 ITfFunctionProvider **ppFuncProv)
494 {
495     ThreadMgr *This = impl_from_ITfThreadMgrEx(iface);
496     FIXME("STUB:(%p)\n",This);
497     return E_NOTIMPL;
498 }
499 
ThreadMgr_EnumFunctionProviders(ITfThreadMgrEx * iface,IEnumTfFunctionProviders ** ppEnum)500 static HRESULT WINAPI ThreadMgr_EnumFunctionProviders(ITfThreadMgrEx *iface,
501 IEnumTfFunctionProviders **ppEnum)
502 {
503     ThreadMgr *This = impl_from_ITfThreadMgrEx(iface);
504     FIXME("STUB:(%p)\n",This);
505     return E_NOTIMPL;
506 }
507 
ThreadMgr_GetGlobalCompartment(ITfThreadMgrEx * iface,ITfCompartmentMgr ** ppCompMgr)508 static HRESULT WINAPI ThreadMgr_GetGlobalCompartment(ITfThreadMgrEx *iface,
509 ITfCompartmentMgr **ppCompMgr)
510 {
511     ThreadMgr *This = impl_from_ITfThreadMgrEx(iface);
512     HRESULT hr;
513     TRACE("(%p) %p\n",This, ppCompMgr);
514 
515     if (!ppCompMgr)
516         return E_INVALIDARG;
517 
518     if (!globalCompartmentMgr)
519     {
520         hr = CompartmentMgr_Constructor(NULL,&IID_ITfCompartmentMgr,(IUnknown**)&globalCompartmentMgr);
521         if (FAILED(hr))
522             return hr;
523     }
524 
525     ITfCompartmentMgr_AddRef(globalCompartmentMgr);
526     *ppCompMgr = globalCompartmentMgr;
527     return S_OK;
528 }
529 
ThreadMgr_ActivateEx(ITfThreadMgrEx * iface,TfClientId * id,DWORD flags)530 static HRESULT WINAPI ThreadMgr_ActivateEx(ITfThreadMgrEx *iface, TfClientId *id, DWORD flags)
531 {
532     ThreadMgr *This = impl_from_ITfThreadMgrEx(iface);
533 
534     TRACE("(%p) %p, %#x\n", This, id, flags);
535 
536     if (!id)
537         return E_INVALIDARG;
538 
539     if (flags)
540         FIXME("Unimplemented flags %#x\n", flags);
541 
542     if (!processId)
543     {
544         GUID guid;
545         CoCreateGuid(&guid);
546         ITfClientId_GetClientId(&This->ITfClientId_iface, &guid, &processId);
547     }
548 
549     activate_textservices(iface);
550     This->activationCount++;
551     *id = processId;
552     return S_OK;
553 }
554 
ThreadMgr_GetActiveFlags(ITfThreadMgrEx * iface,DWORD * flags)555 static HRESULT WINAPI ThreadMgr_GetActiveFlags(ITfThreadMgrEx *iface, DWORD *flags)
556 {
557     ThreadMgr *This = impl_from_ITfThreadMgrEx(iface);
558 
559     FIXME("STUB:(%p)\n", This);
560     return E_NOTIMPL;
561 }
562 
563 static const ITfThreadMgrExVtbl ThreadMgrExVtbl =
564 {
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,
579 
580     ThreadMgr_ActivateEx,
581     ThreadMgr_GetActiveFlags
582 };
583 
Source_QueryInterface(ITfSource * iface,REFIID iid,LPVOID * ppvOut)584 static HRESULT WINAPI Source_QueryInterface(ITfSource *iface, REFIID iid, LPVOID *ppvOut)
585 {
586     ThreadMgr *This = impl_from_ITfSource(iface);
587     return ITfThreadMgrEx_QueryInterface(&This->ITfThreadMgrEx_iface, iid, ppvOut);
588 }
589 
Source_AddRef(ITfSource * iface)590 static ULONG WINAPI Source_AddRef(ITfSource *iface)
591 {
592     ThreadMgr *This = impl_from_ITfSource(iface);
593     return ITfThreadMgrEx_AddRef(&This->ITfThreadMgrEx_iface);
594 }
595 
Source_Release(ITfSource * iface)596 static ULONG WINAPI Source_Release(ITfSource *iface)
597 {
598     ThreadMgr *This = impl_from_ITfSource(iface);
599     return ITfThreadMgrEx_Release(&This->ITfThreadMgrEx_iface);
600 }
601 
602 /*****************************************************
603  * ITfSource functions
604  *****************************************************/
ThreadMgrSource_AdviseSink(ITfSource * iface,REFIID riid,IUnknown * punk,DWORD * pdwCookie)605 static HRESULT WINAPI ThreadMgrSource_AdviseSink(ITfSource *iface,
606         REFIID riid, IUnknown *punk, DWORD *pdwCookie)
607 {
608     ThreadMgr *This = impl_from_ITfSource(iface);
609 
610     TRACE("(%p) %s %p %p\n",This,debugstr_guid(riid),punk,pdwCookie);
611 
612     if (!riid || !punk || !pdwCookie)
613         return E_INVALIDARG;
614 
615     if (IsEqualIID(riid, &IID_ITfThreadMgrEventSink))
616         return advise_sink(&This->ThreadMgrEventSink, &IID_ITfThreadMgrEventSink, COOKIE_MAGIC_TMSINK, punk, pdwCookie);
617 
618     if (IsEqualIID(riid, &IID_ITfThreadFocusSink))
619     {
620         WARN("semi-stub for ITfThreadFocusSink: sink won't be used.\n");
621         return advise_sink(&This->ThreadFocusSink, &IID_ITfThreadFocusSink, COOKIE_MAGIC_THREADFOCUSSINK, punk, pdwCookie);
622     }
623 
624     if (IsEqualIID(riid, &IID_ITfActiveLanguageProfileNotifySink))
625     {
626         WARN("semi-stub for ITfActiveLanguageProfileNotifySink: sink won't be used.\n");
627         return advise_sink(&This->ActiveLanguageProfileNotifySink, &IID_ITfActiveLanguageProfileNotifySink,
628                             COOKIE_MAGIC_ACTIVELANGSINK, punk, pdwCookie);
629     }
630 
631     if (IsEqualIID(riid, &IID_ITfKeyTraceEventSink))
632     {
633         WARN("semi-stub for ITfKeyTraceEventSink: sink won't be used.\n");
634         return advise_sink(&This->KeyTraceEventSink, &IID_ITfKeyTraceEventSink,
635                            COOKIE_MAGIC_KEYTRACESINK, punk, pdwCookie);
636     }
637 
638     if (IsEqualIID(riid, &IID_ITfUIElementSink))
639     {
640         WARN("semi-stub for ITfUIElementSink: sink won't be used.\n");
641         return advise_sink(&This->UIElementSink, &IID_ITfUIElementSink,
642                            COOKIE_MAGIC_UIELEMENTSINK, punk, pdwCookie);
643     }
644 
645     if (IsEqualIID(riid, &IID_ITfInputProcessorProfileActivationSink))
646     {
647         WARN("semi-stub for ITfInputProcessorProfileActivationSink: sink won't be used.\n");
648         return advise_sink(&This->InputProcessorProfileActivationSink, &IID_ITfInputProcessorProfileActivationSink,
649                            COOKIE_MAGIC_INPUTPROCESSORPROFILEACTIVATIONSINK, punk, pdwCookie);
650     }
651 
652     FIXME("(%p) Unhandled Sink: %s\n",This,debugstr_guid(riid));
653     return E_NOTIMPL;
654 }
655 
ThreadMgrSource_UnadviseSink(ITfSource * iface,DWORD pdwCookie)656 static HRESULT WINAPI ThreadMgrSource_UnadviseSink(ITfSource *iface, DWORD pdwCookie)
657 {
658     ThreadMgr *This = impl_from_ITfSource(iface);
659     DWORD magic;
660 
661     TRACE("(%p) %x\n",This,pdwCookie);
662 
663     magic = get_Cookie_magic(pdwCookie);
664     if (magic != COOKIE_MAGIC_TMSINK && magic != COOKIE_MAGIC_THREADFOCUSSINK
665         && magic != COOKIE_MAGIC_KEYTRACESINK && magic != COOKIE_MAGIC_UIELEMENTSINK
666         && magic != COOKIE_MAGIC_INPUTPROCESSORPROFILEACTIVATIONSINK
667         && magic != COOKIE_MAGIC_KEYTRACESINK)
668         return E_INVALIDARG;
669 
670     return unadvise_sink(pdwCookie);
671 }
672 
673 static const ITfSourceVtbl ThreadMgrSourceVtbl =
674 {
675     Source_QueryInterface,
676     Source_AddRef,
677     Source_Release,
678     ThreadMgrSource_AdviseSink,
679     ThreadMgrSource_UnadviseSink,
680 };
681 
682 /*****************************************************
683  * ITfKeystrokeMgr functions
684  *****************************************************/
685 
KeystrokeMgr_QueryInterface(ITfKeystrokeMgr * iface,REFIID iid,LPVOID * ppvOut)686 static HRESULT WINAPI KeystrokeMgr_QueryInterface(ITfKeystrokeMgr *iface, REFIID iid, LPVOID *ppvOut)
687 {
688     ThreadMgr *This = impl_from_ITfKeystrokeMgr(iface);
689     return ITfThreadMgrEx_QueryInterface(&This->ITfThreadMgrEx_iface, iid, ppvOut);
690 }
691 
KeystrokeMgr_AddRef(ITfKeystrokeMgr * iface)692 static ULONG WINAPI KeystrokeMgr_AddRef(ITfKeystrokeMgr *iface)
693 {
694     ThreadMgr *This = impl_from_ITfKeystrokeMgr(iface);
695     return ITfThreadMgrEx_AddRef(&This->ITfThreadMgrEx_iface);
696 }
697 
KeystrokeMgr_Release(ITfKeystrokeMgr * iface)698 static ULONG WINAPI KeystrokeMgr_Release(ITfKeystrokeMgr *iface)
699 {
700     ThreadMgr *This = impl_from_ITfKeystrokeMgr(iface);
701     return ITfThreadMgrEx_Release(&This->ITfThreadMgrEx_iface);
702 }
703 
KeystrokeMgr_AdviseKeyEventSink(ITfKeystrokeMgr * iface,TfClientId tid,ITfKeyEventSink * pSink,BOOL fForeground)704 static HRESULT WINAPI KeystrokeMgr_AdviseKeyEventSink(ITfKeystrokeMgr *iface,
705         TfClientId tid, ITfKeyEventSink *pSink, BOOL fForeground)
706 {
707     ThreadMgr *This = impl_from_ITfKeystrokeMgr(iface);
708     CLSID textservice;
709     ITfKeyEventSink *check = NULL;
710 
711     TRACE("(%p) %x %p %i\n",This,tid,pSink,fForeground);
712 
713     if (!tid || !pSink)
714         return E_INVALIDARG;
715 
716     textservice = get_textservice_clsid(tid);
717     if (IsEqualCLSID(&GUID_NULL,&textservice))
718         return E_INVALIDARG;
719 
720     get_textservice_sink(tid, &IID_ITfKeyEventSink, (IUnknown**)&check);
721     if (check != NULL)
722         return CONNECT_E_ADVISELIMIT;
723 
724     if (FAILED(ITfKeyEventSink_QueryInterface(pSink,&IID_ITfKeyEventSink,(LPVOID*) &check)))
725         return E_INVALIDARG;
726 
727     set_textservice_sink(tid, &IID_ITfKeyEventSink, (IUnknown*)check);
728 
729     if (fForeground)
730     {
731         if (This->foregroundKeyEventSink)
732         {
733             ITfKeyEventSink_OnSetFocus(This->foregroundKeyEventSink, FALSE);
734             ITfKeyEventSink_Release(This->foregroundKeyEventSink);
735         }
736         ITfKeyEventSink_AddRef(check);
737         ITfKeyEventSink_OnSetFocus(check, TRUE);
738         This->foregroundKeyEventSink = check;
739         This->foregroundTextService = textservice;
740     }
741     return S_OK;
742 }
743 
KeystrokeMgr_UnadviseKeyEventSink(ITfKeystrokeMgr * iface,TfClientId tid)744 static HRESULT WINAPI KeystrokeMgr_UnadviseKeyEventSink(ITfKeystrokeMgr *iface,
745         TfClientId tid)
746 {
747     ThreadMgr *This = impl_from_ITfKeystrokeMgr(iface);
748     CLSID textservice;
749     ITfKeyEventSink *check = NULL;
750     TRACE("(%p) %x\n",This,tid);
751 
752     if (!tid)
753         return E_INVALIDARG;
754 
755     textservice = get_textservice_clsid(tid);
756     if (IsEqualCLSID(&GUID_NULL,&textservice))
757         return E_INVALIDARG;
758 
759     get_textservice_sink(tid, &IID_ITfKeyEventSink, (IUnknown**)&check);
760 
761     if (!check)
762         return CONNECT_E_NOCONNECTION;
763 
764     set_textservice_sink(tid, &IID_ITfKeyEventSink, NULL);
765     ITfKeyEventSink_Release(check);
766 
767     if (This->foregroundKeyEventSink == check)
768     {
769         ITfKeyEventSink_Release(This->foregroundKeyEventSink);
770         This->foregroundKeyEventSink = NULL;
771         This->foregroundTextService = GUID_NULL;
772     }
773     return S_OK;
774 }
775 
KeystrokeMgr_GetForeground(ITfKeystrokeMgr * iface,CLSID * pclsid)776 static HRESULT WINAPI KeystrokeMgr_GetForeground(ITfKeystrokeMgr *iface,
777         CLSID *pclsid)
778 {
779     ThreadMgr *This = impl_from_ITfKeystrokeMgr(iface);
780     TRACE("(%p) %p\n",This,pclsid);
781     if (!pclsid)
782         return E_INVALIDARG;
783 
784     if (IsEqualCLSID(&This->foregroundTextService,&GUID_NULL))
785         return S_FALSE;
786 
787     *pclsid = This->foregroundTextService;
788     return S_OK;
789 }
790 
KeystrokeMgr_TestKeyDown(ITfKeystrokeMgr * iface,WPARAM wParam,LPARAM lParam,BOOL * pfEaten)791 static HRESULT WINAPI KeystrokeMgr_TestKeyDown(ITfKeystrokeMgr *iface,
792         WPARAM wParam, LPARAM lParam, BOOL *pfEaten)
793 {
794     ThreadMgr *This = impl_from_ITfKeystrokeMgr(iface);
795     FIXME("STUB:(%p)\n",This);
796     *pfEaten = FALSE;
797     return S_OK;
798 }
799 
KeystrokeMgr_TestKeyUp(ITfKeystrokeMgr * iface,WPARAM wParam,LPARAM lParam,BOOL * pfEaten)800 static HRESULT WINAPI KeystrokeMgr_TestKeyUp(ITfKeystrokeMgr *iface,
801         WPARAM wParam, LPARAM lParam, BOOL *pfEaten)
802 {
803     ThreadMgr *This = impl_from_ITfKeystrokeMgr(iface);
804     FIXME("STUB:(%p)\n",This);
805     *pfEaten = FALSE;
806     return S_OK;
807 }
808 
KeystrokeMgr_KeyDown(ITfKeystrokeMgr * iface,WPARAM wParam,LPARAM lParam,BOOL * pfEaten)809 static HRESULT WINAPI KeystrokeMgr_KeyDown(ITfKeystrokeMgr *iface,
810         WPARAM wParam, LPARAM lParam, BOOL *pfEaten)
811 {
812     ThreadMgr *This = impl_from_ITfKeystrokeMgr(iface);
813     FIXME("STUB:(%p)\n",This);
814     return E_NOTIMPL;
815 }
816 
KeystrokeMgr_KeyUp(ITfKeystrokeMgr * iface,WPARAM wParam,LPARAM lParam,BOOL * pfEaten)817 static HRESULT WINAPI KeystrokeMgr_KeyUp(ITfKeystrokeMgr *iface,
818         WPARAM wParam, LPARAM lParam, BOOL *pfEaten)
819 {
820     ThreadMgr *This = impl_from_ITfKeystrokeMgr(iface);
821     FIXME("STUB:(%p)\n",This);
822     return E_NOTIMPL;
823 }
824 
KeystrokeMgr_GetPreservedKey(ITfKeystrokeMgr * iface,ITfContext * pic,const TF_PRESERVEDKEY * pprekey,GUID * pguid)825 static HRESULT WINAPI KeystrokeMgr_GetPreservedKey(ITfKeystrokeMgr *iface,
826         ITfContext *pic, const TF_PRESERVEDKEY *pprekey, GUID *pguid)
827 {
828     ThreadMgr *This = impl_from_ITfKeystrokeMgr(iface);
829     FIXME("STUB:(%p)\n",This);
830     return E_NOTIMPL;
831 }
832 
KeystrokeMgr_IsPreservedKey(ITfKeystrokeMgr * iface,REFGUID rguid,const TF_PRESERVEDKEY * pprekey,BOOL * pfRegistered)833 static HRESULT WINAPI KeystrokeMgr_IsPreservedKey(ITfKeystrokeMgr *iface,
834         REFGUID rguid, const TF_PRESERVEDKEY *pprekey, BOOL *pfRegistered)
835 {
836     ThreadMgr *This = impl_from_ITfKeystrokeMgr(iface);
837     struct list *cursor;
838 
839     TRACE("(%p) %s (%x %x) %p\n",This,debugstr_guid(rguid), (pprekey)?pprekey->uVKey:0, (pprekey)?pprekey->uModifiers:0, pfRegistered);
840 
841     if (!rguid || !pprekey || !pfRegistered)
842         return E_INVALIDARG;
843 
844     LIST_FOR_EACH(cursor, &This->CurrentPreservedKeys)
845     {
846         PreservedKey* key = LIST_ENTRY(cursor,PreservedKey,entry);
847         if (IsEqualGUID(rguid,&key->guid) && pprekey->uVKey == key->prekey.uVKey && pprekey->uModifiers == key->prekey.uModifiers)
848         {
849             *pfRegistered = TRUE;
850             return S_OK;
851         }
852     }
853 
854     *pfRegistered = FALSE;
855     return S_FALSE;
856 }
857 
KeystrokeMgr_PreserveKey(ITfKeystrokeMgr * iface,TfClientId tid,REFGUID rguid,const TF_PRESERVEDKEY * prekey,const WCHAR * pchDesc,ULONG cchDesc)858 static HRESULT WINAPI KeystrokeMgr_PreserveKey(ITfKeystrokeMgr *iface,
859         TfClientId tid, REFGUID rguid, const TF_PRESERVEDKEY *prekey,
860         const WCHAR *pchDesc, ULONG cchDesc)
861 {
862     ThreadMgr *This = impl_from_ITfKeystrokeMgr(iface);
863     struct list *cursor;
864     PreservedKey *newkey;
865 
866     TRACE("(%p) %x %s (%x,%x) %s\n",This,tid, debugstr_guid(rguid),(prekey)?prekey->uVKey:0,(prekey)?prekey->uModifiers:0,debugstr_wn(pchDesc,cchDesc));
867 
868     if (!tid || ! rguid || !prekey || (cchDesc && !pchDesc))
869         return E_INVALIDARG;
870 
871     LIST_FOR_EACH(cursor, &This->CurrentPreservedKeys)
872     {
873         PreservedKey* key = LIST_ENTRY(cursor,PreservedKey,entry);
874         if (IsEqualGUID(rguid,&key->guid) && prekey->uVKey == key->prekey.uVKey && prekey->uModifiers == key->prekey.uModifiers)
875             return TF_E_ALREADY_EXISTS;
876     }
877 
878     newkey = HeapAlloc(GetProcessHeap(),0,sizeof(PreservedKey));
879     if (!newkey)
880         return E_OUTOFMEMORY;
881 
882     newkey->guid  = *rguid;
883     newkey->prekey = *prekey;
884     newkey->tid = tid;
885     newkey->description = NULL;
886     if (cchDesc)
887     {
888         newkey->description = HeapAlloc(GetProcessHeap(),0,cchDesc * sizeof(WCHAR));
889         if (!newkey->description)
890         {
891             HeapFree(GetProcessHeap(),0,newkey);
892             return E_OUTOFMEMORY;
893         }
894         memcpy(newkey->description, pchDesc, cchDesc*sizeof(WCHAR));
895     }
896 
897     list_add_head(&This->CurrentPreservedKeys,&newkey->entry);
898 
899     return S_OK;
900 }
901 
KeystrokeMgr_UnpreserveKey(ITfKeystrokeMgr * iface,REFGUID rguid,const TF_PRESERVEDKEY * pprekey)902 static HRESULT WINAPI KeystrokeMgr_UnpreserveKey(ITfKeystrokeMgr *iface,
903         REFGUID rguid, const TF_PRESERVEDKEY *pprekey)
904 {
905     ThreadMgr *This = impl_from_ITfKeystrokeMgr(iface);
906     PreservedKey* key = NULL;
907     struct list *cursor;
908     TRACE("(%p) %s (%x %x)\n",This,debugstr_guid(rguid),(pprekey)?pprekey->uVKey:0, (pprekey)?pprekey->uModifiers:0);
909 
910     if (!pprekey || !rguid)
911         return E_INVALIDARG;
912 
913     LIST_FOR_EACH(cursor, &This->CurrentPreservedKeys)
914     {
915         key = LIST_ENTRY(cursor,PreservedKey,entry);
916         if (IsEqualGUID(rguid,&key->guid) && pprekey->uVKey == key->prekey.uVKey && pprekey->uModifiers == key->prekey.uModifiers)
917             break;
918         key = NULL;
919     }
920 
921     if (!key)
922         return CONNECT_E_NOCONNECTION;
923 
924     list_remove(&key->entry);
925     HeapFree(GetProcessHeap(),0,key->description);
926     HeapFree(GetProcessHeap(),0,key);
927 
928     return S_OK;
929 }
930 
KeystrokeMgr_SetPreservedKeyDescription(ITfKeystrokeMgr * iface,REFGUID rguid,const WCHAR * pchDesc,ULONG cchDesc)931 static HRESULT WINAPI KeystrokeMgr_SetPreservedKeyDescription(ITfKeystrokeMgr *iface,
932         REFGUID rguid, const WCHAR *pchDesc, ULONG cchDesc)
933 {
934     ThreadMgr *This = impl_from_ITfKeystrokeMgr(iface);
935     FIXME("STUB:(%p)\n",This);
936     return E_NOTIMPL;
937 }
938 
KeystrokeMgr_GetPreservedKeyDescription(ITfKeystrokeMgr * iface,REFGUID rguid,BSTR * pbstrDesc)939 static HRESULT WINAPI KeystrokeMgr_GetPreservedKeyDescription(ITfKeystrokeMgr *iface,
940         REFGUID rguid, BSTR *pbstrDesc)
941 {
942     ThreadMgr *This = impl_from_ITfKeystrokeMgr(iface);
943     FIXME("STUB:(%p)\n",This);
944     return E_NOTIMPL;
945 }
946 
KeystrokeMgr_SimulatePreservedKey(ITfKeystrokeMgr * iface,ITfContext * pic,REFGUID rguid,BOOL * pfEaten)947 static HRESULT WINAPI KeystrokeMgr_SimulatePreservedKey(ITfKeystrokeMgr *iface,
948         ITfContext *pic, REFGUID rguid, BOOL *pfEaten)
949 {
950     ThreadMgr *This = impl_from_ITfKeystrokeMgr(iface);
951     FIXME("STUB:(%p)\n",This);
952     return E_NOTIMPL;
953 }
954 
955 static const ITfKeystrokeMgrVtbl KeystrokeMgrVtbl =
956 {
957     KeystrokeMgr_QueryInterface,
958     KeystrokeMgr_AddRef,
959     KeystrokeMgr_Release,
960     KeystrokeMgr_AdviseKeyEventSink,
961     KeystrokeMgr_UnadviseKeyEventSink,
962     KeystrokeMgr_GetForeground,
963     KeystrokeMgr_TestKeyDown,
964     KeystrokeMgr_TestKeyUp,
965     KeystrokeMgr_KeyDown,
966     KeystrokeMgr_KeyUp,
967     KeystrokeMgr_GetPreservedKey,
968     KeystrokeMgr_IsPreservedKey,
969     KeystrokeMgr_PreserveKey,
970     KeystrokeMgr_UnpreserveKey,
971     KeystrokeMgr_SetPreservedKeyDescription,
972     KeystrokeMgr_GetPreservedKeyDescription,
973     KeystrokeMgr_SimulatePreservedKey
974 };
975 
976 /*****************************************************
977  * ITfMessagePump functions
978  *****************************************************/
979 
MessagePump_QueryInterface(ITfMessagePump * iface,REFIID iid,LPVOID * ppvOut)980 static HRESULT WINAPI MessagePump_QueryInterface(ITfMessagePump *iface, REFIID iid, LPVOID *ppvOut)
981 {
982     ThreadMgr *This = impl_from_ITfMessagePump(iface);
983     return ITfThreadMgrEx_QueryInterface(&This->ITfThreadMgrEx_iface, iid, ppvOut);
984 }
985 
MessagePump_AddRef(ITfMessagePump * iface)986 static ULONG WINAPI MessagePump_AddRef(ITfMessagePump *iface)
987 {
988     ThreadMgr *This = impl_from_ITfMessagePump(iface);
989     return ITfThreadMgrEx_AddRef(&This->ITfThreadMgrEx_iface);
990 }
991 
MessagePump_Release(ITfMessagePump * iface)992 static ULONG WINAPI MessagePump_Release(ITfMessagePump *iface)
993 {
994     ThreadMgr *This = impl_from_ITfMessagePump(iface);
995     return ITfThreadMgrEx_Release(&This->ITfThreadMgrEx_iface);
996 }
997 
MessagePump_PeekMessageA(ITfMessagePump * iface,LPMSG pMsg,HWND hwnd,UINT wMsgFilterMin,UINT wMsgFilterMax,UINT wRemoveMsg,BOOL * pfResult)998 static HRESULT WINAPI MessagePump_PeekMessageA(ITfMessagePump *iface,
999         LPMSG pMsg, HWND hwnd, UINT wMsgFilterMin, UINT wMsgFilterMax,
1000         UINT wRemoveMsg, BOOL *pfResult)
1001 {
1002     if (!pfResult)
1003         return E_INVALIDARG;
1004     *pfResult = PeekMessageA(pMsg, hwnd, wMsgFilterMin, wMsgFilterMax, wRemoveMsg);
1005     return S_OK;
1006 }
1007 
MessagePump_GetMessageA(ITfMessagePump * iface,LPMSG pMsg,HWND hwnd,UINT wMsgFilterMin,UINT wMsgFilterMax,BOOL * pfResult)1008 static HRESULT WINAPI MessagePump_GetMessageA(ITfMessagePump *iface,
1009         LPMSG pMsg, HWND hwnd, UINT wMsgFilterMin, UINT wMsgFilterMax,
1010         BOOL *pfResult)
1011 {
1012     if (!pfResult)
1013         return E_INVALIDARG;
1014     *pfResult = GetMessageA(pMsg, hwnd, wMsgFilterMin, wMsgFilterMax);
1015     return S_OK;
1016 }
1017 
MessagePump_PeekMessageW(ITfMessagePump * iface,LPMSG pMsg,HWND hwnd,UINT wMsgFilterMin,UINT wMsgFilterMax,UINT wRemoveMsg,BOOL * pfResult)1018 static HRESULT WINAPI MessagePump_PeekMessageW(ITfMessagePump *iface,
1019         LPMSG pMsg, HWND hwnd, UINT wMsgFilterMin, UINT wMsgFilterMax,
1020         UINT wRemoveMsg, BOOL *pfResult)
1021 {
1022     if (!pfResult)
1023         return E_INVALIDARG;
1024     *pfResult = PeekMessageW(pMsg, hwnd, wMsgFilterMin, wMsgFilterMax, wRemoveMsg);
1025     return S_OK;
1026 }
1027 
MessagePump_GetMessageW(ITfMessagePump * iface,LPMSG pMsg,HWND hwnd,UINT wMsgFilterMin,UINT wMsgFilterMax,BOOL * pfResult)1028 static HRESULT WINAPI MessagePump_GetMessageW(ITfMessagePump *iface,
1029         LPMSG pMsg, HWND hwnd, UINT wMsgFilterMin, UINT wMsgFilterMax,
1030         BOOL *pfResult)
1031 {
1032     if (!pfResult)
1033         return E_INVALIDARG;
1034     *pfResult = GetMessageW(pMsg, hwnd, wMsgFilterMin, wMsgFilterMax);
1035     return S_OK;
1036 }
1037 
1038 static const ITfMessagePumpVtbl MessagePumpVtbl =
1039 {
1040     MessagePump_QueryInterface,
1041     MessagePump_AddRef,
1042     MessagePump_Release,
1043     MessagePump_PeekMessageA,
1044     MessagePump_GetMessageA,
1045     MessagePump_PeekMessageW,
1046     MessagePump_GetMessageW
1047 };
1048 
1049 /*****************************************************
1050  * ITfClientId functions
1051  *****************************************************/
1052 
ClientId_QueryInterface(ITfClientId * iface,REFIID iid,LPVOID * ppvOut)1053 static HRESULT WINAPI ClientId_QueryInterface(ITfClientId *iface, REFIID iid, LPVOID *ppvOut)
1054 {
1055     ThreadMgr *This = impl_from_ITfClientId(iface);
1056     return ITfThreadMgrEx_QueryInterface(&This->ITfThreadMgrEx_iface, iid, ppvOut);
1057 }
1058 
ClientId_AddRef(ITfClientId * iface)1059 static ULONG WINAPI ClientId_AddRef(ITfClientId *iface)
1060 {
1061     ThreadMgr *This = impl_from_ITfClientId(iface);
1062     return ITfThreadMgrEx_AddRef(&This->ITfThreadMgrEx_iface);
1063 }
1064 
ClientId_Release(ITfClientId * iface)1065 static ULONG WINAPI ClientId_Release(ITfClientId *iface)
1066 {
1067     ThreadMgr *This = impl_from_ITfClientId(iface);
1068     return ITfThreadMgrEx_Release(&This->ITfThreadMgrEx_iface);
1069 }
1070 
ClientId_GetClientId(ITfClientId * iface,REFCLSID rclsid,TfClientId * ptid)1071 static HRESULT WINAPI ClientId_GetClientId(ITfClientId *iface,
1072     REFCLSID rclsid, TfClientId *ptid)
1073 
1074 {
1075     ThreadMgr *This = impl_from_ITfClientId(iface);
1076     HRESULT hr;
1077     ITfCategoryMgr *catmgr;
1078 
1079     TRACE("(%p) %s\n",This,debugstr_guid(rclsid));
1080 
1081     CategoryMgr_Constructor(NULL,(IUnknown**)&catmgr);
1082     hr = ITfCategoryMgr_RegisterGUID(catmgr,rclsid,ptid);
1083     ITfCategoryMgr_Release(catmgr);
1084 
1085     return hr;
1086 }
1087 
1088 static const ITfClientIdVtbl ClientIdVtbl =
1089 {
1090     ClientId_QueryInterface,
1091     ClientId_AddRef,
1092     ClientId_Release,
1093     ClientId_GetClientId
1094 };
1095 
1096 /*****************************************************
1097  * ITfThreadMgrEventSink functions  (internal)
1098  *****************************************************/
ThreadMgrEventSink_QueryInterface(ITfThreadMgrEventSink * iface,REFIID iid,LPVOID * ppvOut)1099 static HRESULT WINAPI ThreadMgrEventSink_QueryInterface(ITfThreadMgrEventSink *iface, REFIID iid, LPVOID *ppvOut)
1100 {
1101     ThreadMgr *This = impl_from_ITfThreadMgrEventSink(iface);
1102     return ITfThreadMgrEx_QueryInterface(&This->ITfThreadMgrEx_iface, iid, ppvOut);
1103 }
1104 
ThreadMgrEventSink_AddRef(ITfThreadMgrEventSink * iface)1105 static ULONG WINAPI ThreadMgrEventSink_AddRef(ITfThreadMgrEventSink *iface)
1106 {
1107     ThreadMgr *This = impl_from_ITfThreadMgrEventSink(iface);
1108     return ITfThreadMgrEx_AddRef(&This->ITfThreadMgrEx_iface);
1109 }
1110 
ThreadMgrEventSink_Release(ITfThreadMgrEventSink * iface)1111 static ULONG WINAPI ThreadMgrEventSink_Release(ITfThreadMgrEventSink *iface)
1112 {
1113     ThreadMgr *This = impl_from_ITfThreadMgrEventSink(iface);
1114     return ITfThreadMgrEx_Release(&This->ITfThreadMgrEx_iface);
1115 }
1116 
1117 
ThreadMgrEventSink_OnInitDocumentMgr(ITfThreadMgrEventSink * iface,ITfDocumentMgr * pdim)1118 static HRESULT WINAPI ThreadMgrEventSink_OnInitDocumentMgr(
1119         ITfThreadMgrEventSink *iface,ITfDocumentMgr *pdim)
1120 {
1121     ThreadMgr *This = impl_from_ITfThreadMgrEventSink(iface);
1122     ITfThreadMgrEventSink *sink;
1123     struct list *cursor;
1124 
1125     TRACE("(%p) %p\n",This,pdim);
1126 
1127     SINK_FOR_EACH(cursor, &This->ThreadMgrEventSink, ITfThreadMgrEventSink, sink)
1128     {
1129         ITfThreadMgrEventSink_OnInitDocumentMgr(sink, pdim);
1130     }
1131 
1132     return S_OK;
1133 }
1134 
ThreadMgrEventSink_OnUninitDocumentMgr(ITfThreadMgrEventSink * iface,ITfDocumentMgr * pdim)1135 static HRESULT WINAPI ThreadMgrEventSink_OnUninitDocumentMgr(
1136         ITfThreadMgrEventSink *iface, ITfDocumentMgr *pdim)
1137 {
1138     ThreadMgr *This = impl_from_ITfThreadMgrEventSink(iface);
1139     ITfThreadMgrEventSink *sink;
1140     struct list *cursor;
1141 
1142     TRACE("(%p) %p\n",This,pdim);
1143 
1144     SINK_FOR_EACH(cursor, &This->ThreadMgrEventSink, ITfThreadMgrEventSink, sink)
1145     {
1146         ITfThreadMgrEventSink_OnUninitDocumentMgr(sink, pdim);
1147     }
1148 
1149     return S_OK;
1150 }
1151 
ThreadMgrEventSink_OnSetFocus(ITfThreadMgrEventSink * iface,ITfDocumentMgr * pdimFocus,ITfDocumentMgr * pdimPrevFocus)1152 static HRESULT WINAPI ThreadMgrEventSink_OnSetFocus(
1153         ITfThreadMgrEventSink *iface, ITfDocumentMgr *pdimFocus,
1154         ITfDocumentMgr *pdimPrevFocus)
1155 {
1156     ThreadMgr *This = impl_from_ITfThreadMgrEventSink(iface);
1157     ITfThreadMgrEventSink *sink;
1158     struct list *cursor;
1159 
1160     TRACE("(%p) %p %p\n",This,pdimFocus, pdimPrevFocus);
1161 
1162     SINK_FOR_EACH(cursor, &This->ThreadMgrEventSink, ITfThreadMgrEventSink, sink)
1163     {
1164         ITfThreadMgrEventSink_OnSetFocus(sink, pdimFocus, pdimPrevFocus);
1165     }
1166 
1167     return S_OK;
1168 }
1169 
ThreadMgrEventSink_OnPushContext(ITfThreadMgrEventSink * iface,ITfContext * pic)1170 static HRESULT WINAPI ThreadMgrEventSink_OnPushContext(
1171         ITfThreadMgrEventSink *iface, ITfContext *pic)
1172 {
1173     ThreadMgr *This = impl_from_ITfThreadMgrEventSink(iface);
1174     ITfThreadMgrEventSink *sink;
1175     struct list *cursor;
1176 
1177     TRACE("(%p) %p\n",This,pic);
1178 
1179     SINK_FOR_EACH(cursor, &This->ThreadMgrEventSink, ITfThreadMgrEventSink, sink)
1180     {
1181         ITfThreadMgrEventSink_OnPushContext(sink, pic);
1182     }
1183 
1184     return S_OK;
1185 }
1186 
ThreadMgrEventSink_OnPopContext(ITfThreadMgrEventSink * iface,ITfContext * pic)1187 static HRESULT WINAPI ThreadMgrEventSink_OnPopContext(
1188         ITfThreadMgrEventSink *iface, ITfContext *pic)
1189 {
1190     ThreadMgr *This = impl_from_ITfThreadMgrEventSink(iface);
1191     ITfThreadMgrEventSink *sink;
1192     struct list *cursor;
1193 
1194     TRACE("(%p) %p\n",This,pic);
1195 
1196     SINK_FOR_EACH(cursor, &This->ThreadMgrEventSink, ITfThreadMgrEventSink, sink)
1197     {
1198         ITfThreadMgrEventSink_OnPopContext(sink, pic);
1199     }
1200 
1201     return S_OK;
1202 }
1203 
1204 static const ITfThreadMgrEventSinkVtbl ThreadMgrEventSinkVtbl =
1205 {
1206     ThreadMgrEventSink_QueryInterface,
1207     ThreadMgrEventSink_AddRef,
1208     ThreadMgrEventSink_Release,
1209     ThreadMgrEventSink_OnInitDocumentMgr,
1210     ThreadMgrEventSink_OnUninitDocumentMgr,
1211     ThreadMgrEventSink_OnSetFocus,
1212     ThreadMgrEventSink_OnPushContext,
1213     ThreadMgrEventSink_OnPopContext
1214 };
1215 
1216 /*****************************************************
1217  * ITfUIElementMgr functions
1218  *****************************************************/
UIElementMgr_QueryInterface(ITfUIElementMgr * iface,REFIID iid,void ** ppvOut)1219 static HRESULT WINAPI UIElementMgr_QueryInterface(ITfUIElementMgr *iface, REFIID iid, void **ppvOut)
1220 {
1221     ThreadMgr *This = impl_from_ITfUIElementMgr(iface);
1222 
1223     return ITfThreadMgrEx_QueryInterface(&This->ITfThreadMgrEx_iface, iid, ppvOut);
1224 }
1225 
UIElementMgr_AddRef(ITfUIElementMgr * iface)1226 static ULONG WINAPI UIElementMgr_AddRef(ITfUIElementMgr *iface)
1227 {
1228     ThreadMgr *This = impl_from_ITfUIElementMgr(iface);
1229 
1230     return ITfThreadMgrEx_AddRef(&This->ITfThreadMgrEx_iface);
1231 }
1232 
UIElementMgr_Release(ITfUIElementMgr * iface)1233 static ULONG WINAPI UIElementMgr_Release(ITfUIElementMgr *iface)
1234 {
1235     ThreadMgr *This = impl_from_ITfUIElementMgr(iface);
1236 
1237     return ITfThreadMgrEx_Release(&This->ITfThreadMgrEx_iface);
1238 }
1239 
UIElementMgr_BeginUIElement(ITfUIElementMgr * iface,ITfUIElement * element,BOOL * show,DWORD * id)1240 static HRESULT WINAPI UIElementMgr_BeginUIElement(ITfUIElementMgr *iface, ITfUIElement *element,
1241                                                   BOOL *show, DWORD *id)
1242 {
1243     ThreadMgr *This = impl_from_ITfUIElementMgr(iface);
1244 
1245     FIXME("STUB:(%p)\n", This);
1246     return E_NOTIMPL;
1247 }
1248 
UIElementMgr_UpdateUIElement(ITfUIElementMgr * iface,DWORD id)1249 static HRESULT WINAPI UIElementMgr_UpdateUIElement(ITfUIElementMgr *iface, DWORD id)
1250 {
1251     ThreadMgr *This = impl_from_ITfUIElementMgr(iface);
1252 
1253     FIXME("STUB:(%p)\n", This);
1254     return E_NOTIMPL;
1255 }
1256 
UIElementMgr_EndUIElement(ITfUIElementMgr * iface,DWORD id)1257 static HRESULT WINAPI UIElementMgr_EndUIElement(ITfUIElementMgr *iface, DWORD id)
1258 {
1259     ThreadMgr *This = impl_from_ITfUIElementMgr(iface);
1260 
1261     FIXME("STUB:(%p)\n", This);
1262     return E_NOTIMPL;
1263 }
1264 
UIElementMgr_GetUIElement(ITfUIElementMgr * iface,DWORD id,ITfUIElement ** element)1265 static HRESULT WINAPI UIElementMgr_GetUIElement(ITfUIElementMgr *iface, DWORD id,
1266                                                 ITfUIElement **element)
1267 {
1268     ThreadMgr *This = impl_from_ITfUIElementMgr(iface);
1269 
1270     FIXME("STUB:(%p)\n", This);
1271     return E_NOTIMPL;
1272 }
1273 
UIElementMgr_EnumUIElements(ITfUIElementMgr * iface,IEnumTfUIElements ** enum_elements)1274 static HRESULT WINAPI UIElementMgr_EnumUIElements(ITfUIElementMgr *iface,
1275                                                   IEnumTfUIElements **enum_elements)
1276 {
1277     ThreadMgr *This = impl_from_ITfUIElementMgr(iface);
1278 
1279     FIXME("STUB:(%p)\n", This);
1280     return E_NOTIMPL;
1281 }
1282 
1283 static const ITfUIElementMgrVtbl ThreadMgrUIElementMgrVtbl =
1284 {
1285     UIElementMgr_QueryInterface,
1286     UIElementMgr_AddRef,
1287     UIElementMgr_Release,
1288 
1289     UIElementMgr_BeginUIElement,
1290     UIElementMgr_UpdateUIElement,
1291     UIElementMgr_EndUIElement,
1292     UIElementMgr_GetUIElement,
1293     UIElementMgr_EnumUIElements
1294 };
1295 
1296 /*****************************************************
1297  * ITfSourceSingle functions
1298  *****************************************************/
ThreadMgrSourceSingle_QueryInterface(ITfSourceSingle * iface,REFIID iid,LPVOID * ppvOut)1299 static HRESULT WINAPI ThreadMgrSourceSingle_QueryInterface(ITfSourceSingle *iface, REFIID iid, LPVOID *ppvOut)
1300 {
1301     ThreadMgr *This = impl_from_ITfSourceSingle(iface);
1302     return ITfThreadMgrEx_QueryInterface(&This->ITfThreadMgrEx_iface, iid, ppvOut);
1303 }
1304 
ThreadMgrSourceSingle_AddRef(ITfSourceSingle * iface)1305 static ULONG WINAPI ThreadMgrSourceSingle_AddRef(ITfSourceSingle *iface)
1306 {
1307     ThreadMgr *This = impl_from_ITfSourceSingle(iface);
1308     return ITfThreadMgrEx_AddRef(&This->ITfThreadMgrEx_iface);
1309 }
1310 
ThreadMgrSourceSingle_Release(ITfSourceSingle * iface)1311 static ULONG WINAPI ThreadMgrSourceSingle_Release(ITfSourceSingle *iface)
1312 {
1313     ThreadMgr *This = impl_from_ITfSourceSingle(iface);
1314     return ITfThreadMgrEx_Release(&This->ITfThreadMgrEx_iface);
1315 }
1316 
ThreadMgrSourceSingle_AdviseSingleSink(ITfSourceSingle * iface,TfClientId tid,REFIID riid,IUnknown * punk)1317 static HRESULT WINAPI ThreadMgrSourceSingle_AdviseSingleSink( ITfSourceSingle *iface,
1318     TfClientId tid, REFIID riid, IUnknown *punk)
1319 {
1320     ThreadMgr *This = impl_from_ITfSourceSingle(iface);
1321     FIXME("STUB:(%p) %i %s %p\n",This, tid, debugstr_guid(riid),punk);
1322     return E_NOTIMPL;
1323 }
1324 
ThreadMgrSourceSingle_UnadviseSingleSink(ITfSourceSingle * iface,TfClientId tid,REFIID riid)1325 static HRESULT WINAPI ThreadMgrSourceSingle_UnadviseSingleSink( ITfSourceSingle *iface,
1326     TfClientId tid, REFIID riid)
1327 {
1328     ThreadMgr *This = impl_from_ITfSourceSingle(iface);
1329     FIXME("STUB:(%p) %i %s\n",This, tid, debugstr_guid(riid));
1330     return E_NOTIMPL;
1331 }
1332 
1333 static const ITfSourceSingleVtbl SourceSingleVtbl =
1334 {
1335     ThreadMgrSourceSingle_QueryInterface,
1336     ThreadMgrSourceSingle_AddRef,
1337     ThreadMgrSourceSingle_Release,
1338     ThreadMgrSourceSingle_AdviseSingleSink,
1339     ThreadMgrSourceSingle_UnadviseSingleSink
1340 };
1341 
ThreadMgr_Constructor(IUnknown * pUnkOuter,IUnknown ** ppOut)1342 HRESULT ThreadMgr_Constructor(IUnknown *pUnkOuter, IUnknown **ppOut)
1343 {
1344     ThreadMgr *This;
1345     if (pUnkOuter)
1346         return CLASS_E_NOAGGREGATION;
1347 
1348     /* Only 1 ThreadMgr is created per thread */
1349     This = TlsGetValue(tlsIndex);
1350     if (This)
1351     {
1352         ThreadMgr_AddRef(&This->ITfThreadMgrEx_iface);
1353         *ppOut = (IUnknown*)&This->ITfThreadMgrEx_iface;
1354         return S_OK;
1355     }
1356 
1357     This = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(ThreadMgr));
1358     if (This == NULL)
1359         return E_OUTOFMEMORY;
1360 
1361     This->ITfThreadMgrEx_iface.lpVtbl = &ThreadMgrExVtbl;
1362     This->ITfSource_iface.lpVtbl = &ThreadMgrSourceVtbl;
1363     This->ITfKeystrokeMgr_iface.lpVtbl = &KeystrokeMgrVtbl;
1364     This->ITfMessagePump_iface.lpVtbl = &MessagePumpVtbl;
1365     This->ITfClientId_iface.lpVtbl = &ClientIdVtbl;
1366     This->ITfThreadMgrEventSink_iface.lpVtbl = &ThreadMgrEventSinkVtbl;
1367     This->ITfUIElementMgr_iface.lpVtbl = &ThreadMgrUIElementMgrVtbl;
1368     This->ITfSourceSingle_iface.lpVtbl = &SourceSingleVtbl;
1369     This->refCount = 1;
1370     TlsSetValue(tlsIndex,This);
1371 
1372     CompartmentMgr_Constructor((IUnknown*)&This->ITfThreadMgrEx_iface, &IID_IUnknown, (IUnknown**)&This->CompartmentMgr);
1373 
1374     list_init(&This->CurrentPreservedKeys);
1375     list_init(&This->CreatedDocumentMgrs);
1376     list_init(&This->AssociatedFocusWindows);
1377 
1378     list_init(&This->ActiveLanguageProfileNotifySink);
1379     list_init(&This->DisplayAttributeNotifySink);
1380     list_init(&This->KeyTraceEventSink);
1381     list_init(&This->PreservedKeyNotifySink);
1382     list_init(&This->ThreadFocusSink);
1383     list_init(&This->ThreadMgrEventSink);
1384     list_init(&This->UIElementSink);
1385     list_init(&This->InputProcessorProfileActivationSink);
1386 
1387     TRACE("returning %p\n", This);
1388     *ppOut = (IUnknown *)&This->ITfThreadMgrEx_iface;
1389     return S_OK;
1390 }
1391 
1392 /**************************************************
1393  * IEnumTfDocumentMgrs implementation
1394  **************************************************/
EnumTfDocumentMgr_Destructor(EnumTfDocumentMgr * This)1395 static void EnumTfDocumentMgr_Destructor(EnumTfDocumentMgr *This)
1396 {
1397     TRACE("destroying %p\n", This);
1398     HeapFree(GetProcessHeap(),0,This);
1399 }
1400 
EnumTfDocumentMgr_QueryInterface(IEnumTfDocumentMgrs * iface,REFIID iid,LPVOID * ppvOut)1401 static HRESULT WINAPI EnumTfDocumentMgr_QueryInterface(IEnumTfDocumentMgrs *iface, REFIID iid, LPVOID *ppvOut)
1402 {
1403     EnumTfDocumentMgr *This = impl_from_IEnumTfDocumentMgrs(iface);
1404     *ppvOut = NULL;
1405 
1406     if (IsEqualIID(iid, &IID_IUnknown) || IsEqualIID(iid, &IID_IEnumTfDocumentMgrs))
1407     {
1408         *ppvOut = &This->IEnumTfDocumentMgrs_iface;
1409     }
1410 
1411     if (*ppvOut)
1412     {
1413         IEnumTfDocumentMgrs_AddRef(iface);
1414         return S_OK;
1415     }
1416 
1417     WARN("unsupported interface: %s\n", debugstr_guid(iid));
1418     return E_NOINTERFACE;
1419 }
1420 
EnumTfDocumentMgr_AddRef(IEnumTfDocumentMgrs * iface)1421 static ULONG WINAPI EnumTfDocumentMgr_AddRef(IEnumTfDocumentMgrs *iface)
1422 {
1423     EnumTfDocumentMgr *This = impl_from_IEnumTfDocumentMgrs(iface);
1424     return InterlockedIncrement(&This->refCount);
1425 }
1426 
EnumTfDocumentMgr_Release(IEnumTfDocumentMgrs * iface)1427 static ULONG WINAPI EnumTfDocumentMgr_Release(IEnumTfDocumentMgrs *iface)
1428 {
1429     EnumTfDocumentMgr *This = impl_from_IEnumTfDocumentMgrs(iface);
1430     ULONG ret;
1431 
1432     ret = InterlockedDecrement(&This->refCount);
1433     if (ret == 0)
1434         EnumTfDocumentMgr_Destructor(This);
1435     return ret;
1436 }
1437 
EnumTfDocumentMgr_Next(IEnumTfDocumentMgrs * iface,ULONG ulCount,ITfDocumentMgr ** rgDocumentMgr,ULONG * pcFetched)1438 static HRESULT WINAPI EnumTfDocumentMgr_Next(IEnumTfDocumentMgrs *iface,
1439     ULONG ulCount, ITfDocumentMgr **rgDocumentMgr, ULONG *pcFetched)
1440 {
1441     EnumTfDocumentMgr *This = impl_from_IEnumTfDocumentMgrs(iface);
1442     ULONG fetched = 0;
1443 
1444     TRACE("(%p)\n",This);
1445 
1446     if (rgDocumentMgr == NULL) return E_POINTER;
1447 
1448     while (fetched < ulCount)
1449     {
1450         DocumentMgrEntry *mgrentry;
1451         if (This->index == NULL)
1452             break;
1453 
1454         mgrentry = LIST_ENTRY(This->index,DocumentMgrEntry,entry);
1455         if (mgrentry == NULL)
1456             break;
1457 
1458         *rgDocumentMgr = mgrentry->docmgr;
1459         ITfDocumentMgr_AddRef(*rgDocumentMgr);
1460 
1461         This->index = list_next(This->head, This->index);
1462         ++fetched;
1463         ++rgDocumentMgr;
1464     }
1465 
1466     if (pcFetched) *pcFetched = fetched;
1467     return fetched == ulCount ? S_OK : S_FALSE;
1468 }
1469 
EnumTfDocumentMgr_Skip(IEnumTfDocumentMgrs * iface,ULONG celt)1470 static HRESULT WINAPI EnumTfDocumentMgr_Skip( IEnumTfDocumentMgrs* iface, ULONG celt)
1471 {
1472     EnumTfDocumentMgr *This = impl_from_IEnumTfDocumentMgrs(iface);
1473     ULONG i;
1474 
1475     TRACE("(%p)\n",This);
1476     for(i = 0; i < celt && This->index != NULL; i++)
1477         This->index = list_next(This->head, This->index);
1478     return S_OK;
1479 }
1480 
EnumTfDocumentMgr_Reset(IEnumTfDocumentMgrs * iface)1481 static HRESULT WINAPI EnumTfDocumentMgr_Reset( IEnumTfDocumentMgrs* iface)
1482 {
1483     EnumTfDocumentMgr *This = impl_from_IEnumTfDocumentMgrs(iface);
1484     TRACE("(%p)\n",This);
1485     This->index = list_head(This->head);
1486     return S_OK;
1487 }
1488 
EnumTfDocumentMgr_Clone(IEnumTfDocumentMgrs * iface,IEnumTfDocumentMgrs ** ppenum)1489 static HRESULT WINAPI EnumTfDocumentMgr_Clone( IEnumTfDocumentMgrs *iface,
1490     IEnumTfDocumentMgrs **ppenum)
1491 {
1492     EnumTfDocumentMgr *This = impl_from_IEnumTfDocumentMgrs(iface);
1493     HRESULT res;
1494 
1495     TRACE("(%p)\n",This);
1496 
1497     if (ppenum == NULL) return E_POINTER;
1498 
1499     res = EnumTfDocumentMgr_Constructor(This->head, ppenum);
1500     if (SUCCEEDED(res))
1501     {
1502         EnumTfDocumentMgr *new_This = impl_from_IEnumTfDocumentMgrs(*ppenum);
1503         new_This->index = This->index;
1504     }
1505     return res;
1506 }
1507 
1508 static const IEnumTfDocumentMgrsVtbl EnumTfDocumentMgrsVtbl =
1509 {
1510     EnumTfDocumentMgr_QueryInterface,
1511     EnumTfDocumentMgr_AddRef,
1512     EnumTfDocumentMgr_Release,
1513     EnumTfDocumentMgr_Clone,
1514     EnumTfDocumentMgr_Next,
1515     EnumTfDocumentMgr_Reset,
1516     EnumTfDocumentMgr_Skip
1517 };
1518 
EnumTfDocumentMgr_Constructor(struct list * head,IEnumTfDocumentMgrs ** ppOut)1519 static HRESULT EnumTfDocumentMgr_Constructor(struct list* head, IEnumTfDocumentMgrs **ppOut)
1520 {
1521     EnumTfDocumentMgr *This;
1522 
1523     This = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(EnumTfDocumentMgr));
1524     if (This == NULL)
1525         return E_OUTOFMEMORY;
1526 
1527     This->IEnumTfDocumentMgrs_iface.lpVtbl= &EnumTfDocumentMgrsVtbl;
1528     This->refCount = 1;
1529     This->head = head;
1530     This->index = list_head(This->head);
1531 
1532     TRACE("returning %p\n", &This->IEnumTfDocumentMgrs_iface);
1533     *ppOut = &This->IEnumTfDocumentMgrs_iface;
1534     return S_OK;
1535 }
1536 
ThreadMgr_OnDocumentMgrDestruction(ITfThreadMgr * iface,ITfDocumentMgr * mgr)1537 void ThreadMgr_OnDocumentMgrDestruction(ITfThreadMgr *iface, ITfDocumentMgr *mgr)
1538 {
1539     ThreadMgr *This = impl_from_ITfThreadMgrEx((ITfThreadMgrEx *)iface);
1540     struct list *cursor;
1541     LIST_FOR_EACH(cursor, &This->CreatedDocumentMgrs)
1542     {
1543         DocumentMgrEntry *mgrentry = LIST_ENTRY(cursor,DocumentMgrEntry,entry);
1544         if (mgrentry->docmgr == mgr)
1545         {
1546             list_remove(cursor);
1547             HeapFree(GetProcessHeap(),0,mgrentry);
1548             return;
1549         }
1550     }
1551     FIXME("ITfDocumentMgr %p not found in this thread\n",mgr);
1552 }
1553