8ca12ac0788fdf87ff2907d1f626a328e290b3c0
[reactos.git] / dll / win32 / msctf / threadmgr.c
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 "config.h"
22
23 #include <stdarg.h>
24
25 #define COBJMACROS
26
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"
36
37 #include "wine/unicode.h"
38
39 #include "msctf.h"
40 #include "msctf_internal.h"
41
42 WINE_DEFAULT_DEBUG_CHANNEL(msctf);
43
44 typedef struct tagPreservedKey
45 {
46 struct list entry;
47 GUID guid;
48 TF_PRESERVEDKEY prekey;
49 LPWSTR description;
50 TfClientId tid;
51 } PreservedKey;
52
53 typedef struct tagDocumentMgrs
54 {
55 struct list entry;
56 ITfDocumentMgr *docmgr;
57 } DocumentMgrEntry;
58
59 typedef struct tagAssociatedWindow
60 {
61 struct list entry;
62 HWND hwnd;
63 ITfDocumentMgr *docmgr;
64 } AssociatedWindow;
65
66 typedef struct tagACLMulti {
67 ITfThreadMgrEx ITfThreadMgrEx_iface;
68 ITfSource ITfSource_iface;
69 ITfKeystrokeMgr ITfKeystrokeMgr_iface;
70 ITfMessagePump ITfMessagePump_iface;
71 ITfClientId ITfClientId_iface;
72 /* const ITfThreadMgrExVtbl *ThreadMgrExVtbl; */
73 /* const ITfConfigureSystemKeystrokeFeedVtbl *ConfigureSystemKeystrokeFeedVtbl; */
74 /* const ITfLangBarItemMgrVtbl *LangBarItemMgrVtbl; */
75 ITfUIElementMgr ITfUIElementMgr_iface;
76 ITfSourceSingle ITfSourceSingle_iface;
77 LONG refCount;
78
79 /* Aggregation */
80 ITfCompartmentMgr *CompartmentMgr;
81
82 ITfThreadMgrEventSink ITfThreadMgrEventSink_iface; /* internal */
83
84 ITfDocumentMgr *focus;
85 LONG activationCount;
86
87 ITfKeyEventSink *foregroundKeyEventSink;
88 CLSID foregroundTextService;
89
90 struct list CurrentPreservedKeys;
91 struct list CreatedDocumentMgrs;
92
93 struct list AssociatedFocusWindows;
94 HHOOK focusHook;
95
96 /* kept as separate lists to reduce unnecessary iterations */
97 struct list ActiveLanguageProfileNotifySink;
98 struct list DisplayAttributeNotifySink;
99 struct list KeyTraceEventSink;
100 struct list PreservedKeyNotifySink;
101 struct list ThreadFocusSink;
102 struct list ThreadMgrEventSink;
103 } ThreadMgr;
104
105 typedef struct tagEnumTfDocumentMgr {
106 IEnumTfDocumentMgrs IEnumTfDocumentMgrs_iface;
107 LONG refCount;
108
109 struct list *index;
110 struct list *head;
111 } EnumTfDocumentMgr;
112
113 static HRESULT EnumTfDocumentMgr_Constructor(struct list* head, IEnumTfDocumentMgrs **ppOut);
114
115 static inline ThreadMgr *impl_from_ITfThreadMgrEx(ITfThreadMgrEx *iface)
116 {
117 return CONTAINING_RECORD(iface, ThreadMgr, ITfThreadMgrEx_iface);
118 }
119
120 static inline ThreadMgr *impl_from_ITfSource(ITfSource *iface)
121 {
122 return CONTAINING_RECORD(iface, ThreadMgr, ITfSource_iface);
123 }
124
125 static inline ThreadMgr *impl_from_ITfKeystrokeMgr(ITfKeystrokeMgr *iface)
126 {
127 return CONTAINING_RECORD(iface, ThreadMgr, ITfKeystrokeMgr_iface);
128 }
129
130 static inline ThreadMgr *impl_from_ITfMessagePump(ITfMessagePump *iface)
131 {
132 return CONTAINING_RECORD(iface, ThreadMgr, ITfMessagePump_iface);
133 }
134
135 static inline ThreadMgr *impl_from_ITfClientId(ITfClientId *iface)
136 {
137 return CONTAINING_RECORD(iface, ThreadMgr, ITfClientId_iface);
138 }
139
140 static inline ThreadMgr *impl_from_ITfThreadMgrEventSink(ITfThreadMgrEventSink *iface)
141 {
142 return CONTAINING_RECORD(iface, ThreadMgr, ITfThreadMgrEventSink_iface);
143 }
144
145 static inline ThreadMgr *impl_from_ITfUIElementMgr(ITfUIElementMgr *iface)
146 {
147 return CONTAINING_RECORD(iface, ThreadMgr, ITfUIElementMgr_iface);
148 }
149
150 static inline ThreadMgr *impl_from_ITfSourceSingle(ITfSourceSingle *iface)
151 {
152 return CONTAINING_RECORD(iface, ThreadMgr, ITfSourceSingle_iface);
153 }
154
155 static inline EnumTfDocumentMgr *impl_from_IEnumTfDocumentMgrs(IEnumTfDocumentMgrs *iface)
156 {
157 return CONTAINING_RECORD(iface, EnumTfDocumentMgr, IEnumTfDocumentMgrs_iface);
158 }
159
160 static void ThreadMgr_Destructor(ThreadMgr *This)
161 {
162 struct list *cursor, *cursor2;
163
164 /* unhook right away */
165 if (This->focusHook)
166 UnhookWindowsHookEx(This->focusHook);
167
168 TlsSetValue(tlsIndex,NULL);
169 TRACE("destroying %p\n", This);
170 if (This->focus)
171 ITfDocumentMgr_Release(This->focus);
172
173 free_sinks(&This->ActiveLanguageProfileNotifySink);
174 free_sinks(&This->DisplayAttributeNotifySink);
175 free_sinks(&This->KeyTraceEventSink);
176 free_sinks(&This->PreservedKeyNotifySink);
177 free_sinks(&This->ThreadFocusSink);
178 free_sinks(&This->ThreadMgrEventSink);
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
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
257 static ULONG WINAPI ThreadMgr_AddRef(ITfThreadMgrEx *iface)
258 {
259 ThreadMgr *This = impl_from_ITfThreadMgrEx(iface);
260 return InterlockedIncrement(&This->refCount);
261 }
262
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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 *****************************************************/
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 FIXME("(%p) Unhandled Sink: %s\n",This,debugstr_guid(riid));
625 return E_NOTIMPL;
626 }
627
628 static HRESULT WINAPI ThreadMgrSource_UnadviseSink(ITfSource *iface, DWORD pdwCookie)
629 {
630 ThreadMgr *This = impl_from_ITfSource(iface);
631
632 TRACE("(%p) %x\n",This,pdwCookie);
633
634 if (get_Cookie_magic(pdwCookie) != COOKIE_MAGIC_TMSINK && get_Cookie_magic(pdwCookie) != COOKIE_MAGIC_THREADFOCUSSINK)
635 return E_INVALIDARG;
636
637 return unadvise_sink(pdwCookie);
638 }
639
640 static const ITfSourceVtbl ThreadMgrSourceVtbl =
641 {
642 Source_QueryInterface,
643 Source_AddRef,
644 Source_Release,
645 ThreadMgrSource_AdviseSink,
646 ThreadMgrSource_UnadviseSink,
647 };
648
649 /*****************************************************
650 * ITfKeystrokeMgr functions
651 *****************************************************/
652
653 static HRESULT WINAPI KeystrokeMgr_QueryInterface(ITfKeystrokeMgr *iface, REFIID iid, LPVOID *ppvOut)
654 {
655 ThreadMgr *This = impl_from_ITfKeystrokeMgr(iface);
656 return ITfThreadMgrEx_QueryInterface(&This->ITfThreadMgrEx_iface, iid, ppvOut);
657 }
658
659 static ULONG WINAPI KeystrokeMgr_AddRef(ITfKeystrokeMgr *iface)
660 {
661 ThreadMgr *This = impl_from_ITfKeystrokeMgr(iface);
662 return ITfThreadMgrEx_AddRef(&This->ITfThreadMgrEx_iface);
663 }
664
665 static ULONG WINAPI KeystrokeMgr_Release(ITfKeystrokeMgr *iface)
666 {
667 ThreadMgr *This = impl_from_ITfKeystrokeMgr(iface);
668 return ITfThreadMgrEx_Release(&This->ITfThreadMgrEx_iface);
669 }
670
671 static HRESULT WINAPI KeystrokeMgr_AdviseKeyEventSink(ITfKeystrokeMgr *iface,
672 TfClientId tid, ITfKeyEventSink *pSink, BOOL fForeground)
673 {
674 ThreadMgr *This = impl_from_ITfKeystrokeMgr(iface);
675 CLSID textservice;
676 ITfKeyEventSink *check = NULL;
677
678 TRACE("(%p) %x %p %i\n",This,tid,pSink,fForeground);
679
680 if (!tid || !pSink)
681 return E_INVALIDARG;
682
683 textservice = get_textservice_clsid(tid);
684 if (IsEqualCLSID(&GUID_NULL,&textservice))
685 return E_INVALIDARG;
686
687 get_textservice_sink(tid, &IID_ITfKeyEventSink, (IUnknown**)&check);
688 if (check != NULL)
689 return CONNECT_E_ADVISELIMIT;
690
691 if (FAILED(ITfKeyEventSink_QueryInterface(pSink,&IID_ITfKeyEventSink,(LPVOID*) &check)))
692 return E_INVALIDARG;
693
694 set_textservice_sink(tid, &IID_ITfKeyEventSink, (IUnknown*)check);
695
696 if (fForeground)
697 {
698 if (This->foregroundKeyEventSink)
699 {
700 ITfKeyEventSink_OnSetFocus(This->foregroundKeyEventSink, FALSE);
701 ITfKeyEventSink_Release(This->foregroundKeyEventSink);
702 }
703 ITfKeyEventSink_AddRef(check);
704 ITfKeyEventSink_OnSetFocus(check, TRUE);
705 This->foregroundKeyEventSink = check;
706 This->foregroundTextService = textservice;
707 }
708 return S_OK;
709 }
710
711 static HRESULT WINAPI KeystrokeMgr_UnadviseKeyEventSink(ITfKeystrokeMgr *iface,
712 TfClientId tid)
713 {
714 ThreadMgr *This = impl_from_ITfKeystrokeMgr(iface);
715 CLSID textservice;
716 ITfKeyEventSink *check = NULL;
717 TRACE("(%p) %x\n",This,tid);
718
719 if (!tid)
720 return E_INVALIDARG;
721
722 textservice = get_textservice_clsid(tid);
723 if (IsEqualCLSID(&GUID_NULL,&textservice))
724 return E_INVALIDARG;
725
726 get_textservice_sink(tid, &IID_ITfKeyEventSink, (IUnknown**)&check);
727
728 if (!check)
729 return CONNECT_E_NOCONNECTION;
730
731 set_textservice_sink(tid, &IID_ITfKeyEventSink, NULL);
732 ITfKeyEventSink_Release(check);
733
734 if (This->foregroundKeyEventSink == check)
735 {
736 ITfKeyEventSink_Release(This->foregroundKeyEventSink);
737 This->foregroundKeyEventSink = NULL;
738 This->foregroundTextService = GUID_NULL;
739 }
740 return S_OK;
741 }
742
743 static HRESULT WINAPI KeystrokeMgr_GetForeground(ITfKeystrokeMgr *iface,
744 CLSID *pclsid)
745 {
746 ThreadMgr *This = impl_from_ITfKeystrokeMgr(iface);
747 TRACE("(%p) %p\n",This,pclsid);
748 if (!pclsid)
749 return E_INVALIDARG;
750
751 if (IsEqualCLSID(&This->foregroundTextService,&GUID_NULL))
752 return S_FALSE;
753
754 *pclsid = This->foregroundTextService;
755 return S_OK;
756 }
757
758 static HRESULT WINAPI KeystrokeMgr_TestKeyDown(ITfKeystrokeMgr *iface,
759 WPARAM wParam, LPARAM lParam, BOOL *pfEaten)
760 {
761 ThreadMgr *This = impl_from_ITfKeystrokeMgr(iface);
762 FIXME("STUB:(%p)\n",This);
763 *pfEaten = FALSE;
764 return S_OK;
765 }
766
767 static HRESULT WINAPI KeystrokeMgr_TestKeyUp(ITfKeystrokeMgr *iface,
768 WPARAM wParam, LPARAM lParam, BOOL *pfEaten)
769 {
770 ThreadMgr *This = impl_from_ITfKeystrokeMgr(iface);
771 FIXME("STUB:(%p)\n",This);
772 *pfEaten = FALSE;
773 return S_OK;
774 }
775
776 static HRESULT WINAPI KeystrokeMgr_KeyDown(ITfKeystrokeMgr *iface,
777 WPARAM wParam, LPARAM lParam, BOOL *pfEaten)
778 {
779 ThreadMgr *This = impl_from_ITfKeystrokeMgr(iface);
780 FIXME("STUB:(%p)\n",This);
781 return E_NOTIMPL;
782 }
783
784 static HRESULT WINAPI KeystrokeMgr_KeyUp(ITfKeystrokeMgr *iface,
785 WPARAM wParam, LPARAM lParam, BOOL *pfEaten)
786 {
787 ThreadMgr *This = impl_from_ITfKeystrokeMgr(iface);
788 FIXME("STUB:(%p)\n",This);
789 return E_NOTIMPL;
790 }
791
792 static HRESULT WINAPI KeystrokeMgr_GetPreservedKey(ITfKeystrokeMgr *iface,
793 ITfContext *pic, const TF_PRESERVEDKEY *pprekey, GUID *pguid)
794 {
795 ThreadMgr *This = impl_from_ITfKeystrokeMgr(iface);
796 FIXME("STUB:(%p)\n",This);
797 return E_NOTIMPL;
798 }
799
800 static HRESULT WINAPI KeystrokeMgr_IsPreservedKey(ITfKeystrokeMgr *iface,
801 REFGUID rguid, const TF_PRESERVEDKEY *pprekey, BOOL *pfRegistered)
802 {
803 ThreadMgr *This = impl_from_ITfKeystrokeMgr(iface);
804 struct list *cursor;
805
806 TRACE("(%p) %s (%x %x) %p\n",This,debugstr_guid(rguid), (pprekey)?pprekey->uVKey:0, (pprekey)?pprekey->uModifiers:0, pfRegistered);
807
808 if (!rguid || !pprekey || !pfRegistered)
809 return E_INVALIDARG;
810
811 LIST_FOR_EACH(cursor, &This->CurrentPreservedKeys)
812 {
813 PreservedKey* key = LIST_ENTRY(cursor,PreservedKey,entry);
814 if (IsEqualGUID(rguid,&key->guid) && pprekey->uVKey == key->prekey.uVKey && pprekey->uModifiers == key->prekey.uModifiers)
815 {
816 *pfRegistered = TRUE;
817 return S_OK;
818 }
819 }
820
821 *pfRegistered = FALSE;
822 return S_FALSE;
823 }
824
825 static HRESULT WINAPI KeystrokeMgr_PreserveKey(ITfKeystrokeMgr *iface,
826 TfClientId tid, REFGUID rguid, const TF_PRESERVEDKEY *prekey,
827 const WCHAR *pchDesc, ULONG cchDesc)
828 {
829 ThreadMgr *This = impl_from_ITfKeystrokeMgr(iface);
830 struct list *cursor;
831 PreservedKey *newkey;
832
833 TRACE("(%p) %x %s (%x,%x) %s\n",This,tid, debugstr_guid(rguid),(prekey)?prekey->uVKey:0,(prekey)?prekey->uModifiers:0,debugstr_wn(pchDesc,cchDesc));
834
835 if (!tid || ! rguid || !prekey || (cchDesc && !pchDesc))
836 return E_INVALIDARG;
837
838 LIST_FOR_EACH(cursor, &This->CurrentPreservedKeys)
839 {
840 PreservedKey* key = LIST_ENTRY(cursor,PreservedKey,entry);
841 if (IsEqualGUID(rguid,&key->guid) && prekey->uVKey == key->prekey.uVKey && prekey->uModifiers == key->prekey.uModifiers)
842 return TF_E_ALREADY_EXISTS;
843 }
844
845 newkey = HeapAlloc(GetProcessHeap(),0,sizeof(PreservedKey));
846 if (!newkey)
847 return E_OUTOFMEMORY;
848
849 newkey->guid = *rguid;
850 newkey->prekey = *prekey;
851 newkey->tid = tid;
852 newkey->description = NULL;
853 if (cchDesc)
854 {
855 newkey->description = HeapAlloc(GetProcessHeap(),0,cchDesc * sizeof(WCHAR));
856 if (!newkey->description)
857 {
858 HeapFree(GetProcessHeap(),0,newkey);
859 return E_OUTOFMEMORY;
860 }
861 memcpy(newkey->description, pchDesc, cchDesc*sizeof(WCHAR));
862 }
863
864 list_add_head(&This->CurrentPreservedKeys,&newkey->entry);
865
866 return S_OK;
867 }
868
869 static HRESULT WINAPI KeystrokeMgr_UnpreserveKey(ITfKeystrokeMgr *iface,
870 REFGUID rguid, const TF_PRESERVEDKEY *pprekey)
871 {
872 ThreadMgr *This = impl_from_ITfKeystrokeMgr(iface);
873 PreservedKey* key = NULL;
874 struct list *cursor;
875 TRACE("(%p) %s (%x %x)\n",This,debugstr_guid(rguid),(pprekey)?pprekey->uVKey:0, (pprekey)?pprekey->uModifiers:0);
876
877 if (!pprekey || !rguid)
878 return E_INVALIDARG;
879
880 LIST_FOR_EACH(cursor, &This->CurrentPreservedKeys)
881 {
882 key = LIST_ENTRY(cursor,PreservedKey,entry);
883 if (IsEqualGUID(rguid,&key->guid) && pprekey->uVKey == key->prekey.uVKey && pprekey->uModifiers == key->prekey.uModifiers)
884 break;
885 key = NULL;
886 }
887
888 if (!key)
889 return CONNECT_E_NOCONNECTION;
890
891 list_remove(&key->entry);
892 HeapFree(GetProcessHeap(),0,key->description);
893 HeapFree(GetProcessHeap(),0,key);
894
895 return S_OK;
896 }
897
898 static HRESULT WINAPI KeystrokeMgr_SetPreservedKeyDescription(ITfKeystrokeMgr *iface,
899 REFGUID rguid, const WCHAR *pchDesc, ULONG cchDesc)
900 {
901 ThreadMgr *This = impl_from_ITfKeystrokeMgr(iface);
902 FIXME("STUB:(%p)\n",This);
903 return E_NOTIMPL;
904 }
905
906 static HRESULT WINAPI KeystrokeMgr_GetPreservedKeyDescription(ITfKeystrokeMgr *iface,
907 REFGUID rguid, BSTR *pbstrDesc)
908 {
909 ThreadMgr *This = impl_from_ITfKeystrokeMgr(iface);
910 FIXME("STUB:(%p)\n",This);
911 return E_NOTIMPL;
912 }
913
914 static HRESULT WINAPI KeystrokeMgr_SimulatePreservedKey(ITfKeystrokeMgr *iface,
915 ITfContext *pic, REFGUID rguid, BOOL *pfEaten)
916 {
917 ThreadMgr *This = impl_from_ITfKeystrokeMgr(iface);
918 FIXME("STUB:(%p)\n",This);
919 return E_NOTIMPL;
920 }
921
922 static const ITfKeystrokeMgrVtbl KeystrokeMgrVtbl =
923 {
924 KeystrokeMgr_QueryInterface,
925 KeystrokeMgr_AddRef,
926 KeystrokeMgr_Release,
927 KeystrokeMgr_AdviseKeyEventSink,
928 KeystrokeMgr_UnadviseKeyEventSink,
929 KeystrokeMgr_GetForeground,
930 KeystrokeMgr_TestKeyDown,
931 KeystrokeMgr_TestKeyUp,
932 KeystrokeMgr_KeyDown,
933 KeystrokeMgr_KeyUp,
934 KeystrokeMgr_GetPreservedKey,
935 KeystrokeMgr_IsPreservedKey,
936 KeystrokeMgr_PreserveKey,
937 KeystrokeMgr_UnpreserveKey,
938 KeystrokeMgr_SetPreservedKeyDescription,
939 KeystrokeMgr_GetPreservedKeyDescription,
940 KeystrokeMgr_SimulatePreservedKey
941 };
942
943 /*****************************************************
944 * ITfMessagePump functions
945 *****************************************************/
946
947 static HRESULT WINAPI MessagePump_QueryInterface(ITfMessagePump *iface, REFIID iid, LPVOID *ppvOut)
948 {
949 ThreadMgr *This = impl_from_ITfMessagePump(iface);
950 return ITfThreadMgrEx_QueryInterface(&This->ITfThreadMgrEx_iface, iid, ppvOut);
951 }
952
953 static ULONG WINAPI MessagePump_AddRef(ITfMessagePump *iface)
954 {
955 ThreadMgr *This = impl_from_ITfMessagePump(iface);
956 return ITfThreadMgrEx_AddRef(&This->ITfThreadMgrEx_iface);
957 }
958
959 static ULONG WINAPI MessagePump_Release(ITfMessagePump *iface)
960 {
961 ThreadMgr *This = impl_from_ITfMessagePump(iface);
962 return ITfThreadMgrEx_Release(&This->ITfThreadMgrEx_iface);
963 }
964
965 static HRESULT WINAPI MessagePump_PeekMessageA(ITfMessagePump *iface,
966 LPMSG pMsg, HWND hwnd, UINT wMsgFilterMin, UINT wMsgFilterMax,
967 UINT wRemoveMsg, BOOL *pfResult)
968 {
969 if (!pfResult)
970 return E_INVALIDARG;
971 *pfResult = PeekMessageA(pMsg, hwnd, wMsgFilterMin, wMsgFilterMax, wRemoveMsg);
972 return S_OK;
973 }
974
975 static HRESULT WINAPI MessagePump_GetMessageA(ITfMessagePump *iface,
976 LPMSG pMsg, HWND hwnd, UINT wMsgFilterMin, UINT wMsgFilterMax,
977 BOOL *pfResult)
978 {
979 if (!pfResult)
980 return E_INVALIDARG;
981 *pfResult = GetMessageA(pMsg, hwnd, wMsgFilterMin, wMsgFilterMax);
982 return S_OK;
983 }
984
985 static HRESULT WINAPI MessagePump_PeekMessageW(ITfMessagePump *iface,
986 LPMSG pMsg, HWND hwnd, UINT wMsgFilterMin, UINT wMsgFilterMax,
987 UINT wRemoveMsg, BOOL *pfResult)
988 {
989 if (!pfResult)
990 return E_INVALIDARG;
991 *pfResult = PeekMessageW(pMsg, hwnd, wMsgFilterMin, wMsgFilterMax, wRemoveMsg);
992 return S_OK;
993 }
994
995 static HRESULT WINAPI MessagePump_GetMessageW(ITfMessagePump *iface,
996 LPMSG pMsg, HWND hwnd, UINT wMsgFilterMin, UINT wMsgFilterMax,
997 BOOL *pfResult)
998 {
999 if (!pfResult)
1000 return E_INVALIDARG;
1001 *pfResult = GetMessageW(pMsg, hwnd, wMsgFilterMin, wMsgFilterMax);
1002 return S_OK;
1003 }
1004
1005 static const ITfMessagePumpVtbl MessagePumpVtbl =
1006 {
1007 MessagePump_QueryInterface,
1008 MessagePump_AddRef,
1009 MessagePump_Release,
1010 MessagePump_PeekMessageA,
1011 MessagePump_GetMessageA,
1012 MessagePump_PeekMessageW,
1013 MessagePump_GetMessageW
1014 };
1015
1016 /*****************************************************
1017 * ITfClientId functions
1018 *****************************************************/
1019
1020 static HRESULT WINAPI ClientId_QueryInterface(ITfClientId *iface, REFIID iid, LPVOID *ppvOut)
1021 {
1022 ThreadMgr *This = impl_from_ITfClientId(iface);
1023 return ITfThreadMgrEx_QueryInterface(&This->ITfThreadMgrEx_iface, iid, ppvOut);
1024 }
1025
1026 static ULONG WINAPI ClientId_AddRef(ITfClientId *iface)
1027 {
1028 ThreadMgr *This = impl_from_ITfClientId(iface);
1029 return ITfThreadMgrEx_AddRef(&This->ITfThreadMgrEx_iface);
1030 }
1031
1032 static ULONG WINAPI ClientId_Release(ITfClientId *iface)
1033 {
1034 ThreadMgr *This = impl_from_ITfClientId(iface);
1035 return ITfThreadMgrEx_Release(&This->ITfThreadMgrEx_iface);
1036 }
1037
1038 static HRESULT WINAPI ClientId_GetClientId(ITfClientId *iface,
1039 REFCLSID rclsid, TfClientId *ptid)
1040
1041 {
1042 ThreadMgr *This = impl_from_ITfClientId(iface);
1043 HRESULT hr;
1044 ITfCategoryMgr *catmgr;
1045
1046 TRACE("(%p) %s\n",This,debugstr_guid(rclsid));
1047
1048 CategoryMgr_Constructor(NULL,(IUnknown**)&catmgr);
1049 hr = ITfCategoryMgr_RegisterGUID(catmgr,rclsid,ptid);
1050 ITfCategoryMgr_Release(catmgr);
1051
1052 return hr;
1053 }
1054
1055 static const ITfClientIdVtbl ClientIdVtbl =
1056 {
1057 ClientId_QueryInterface,
1058 ClientId_AddRef,
1059 ClientId_Release,
1060 ClientId_GetClientId
1061 };
1062
1063 /*****************************************************
1064 * ITfThreadMgrEventSink functions (internal)
1065 *****************************************************/
1066 static HRESULT WINAPI ThreadMgrEventSink_QueryInterface(ITfThreadMgrEventSink *iface, REFIID iid, LPVOID *ppvOut)
1067 {
1068 ThreadMgr *This = impl_from_ITfThreadMgrEventSink(iface);
1069 return ITfThreadMgrEx_QueryInterface(&This->ITfThreadMgrEx_iface, iid, ppvOut);
1070 }
1071
1072 static ULONG WINAPI ThreadMgrEventSink_AddRef(ITfThreadMgrEventSink *iface)
1073 {
1074 ThreadMgr *This = impl_from_ITfThreadMgrEventSink(iface);
1075 return ITfThreadMgrEx_AddRef(&This->ITfThreadMgrEx_iface);
1076 }
1077
1078 static ULONG WINAPI ThreadMgrEventSink_Release(ITfThreadMgrEventSink *iface)
1079 {
1080 ThreadMgr *This = impl_from_ITfThreadMgrEventSink(iface);
1081 return ITfThreadMgrEx_Release(&This->ITfThreadMgrEx_iface);
1082 }
1083
1084
1085 static HRESULT WINAPI ThreadMgrEventSink_OnInitDocumentMgr(
1086 ITfThreadMgrEventSink *iface,ITfDocumentMgr *pdim)
1087 {
1088 ThreadMgr *This = impl_from_ITfThreadMgrEventSink(iface);
1089 ITfThreadMgrEventSink *sink;
1090 struct list *cursor;
1091
1092 TRACE("(%p) %p\n",This,pdim);
1093
1094 SINK_FOR_EACH(cursor, &This->ThreadMgrEventSink, ITfThreadMgrEventSink, sink)
1095 {
1096 ITfThreadMgrEventSink_OnInitDocumentMgr(sink, pdim);
1097 }
1098
1099 return S_OK;
1100 }
1101
1102 static HRESULT WINAPI ThreadMgrEventSink_OnUninitDocumentMgr(
1103 ITfThreadMgrEventSink *iface, ITfDocumentMgr *pdim)
1104 {
1105 ThreadMgr *This = impl_from_ITfThreadMgrEventSink(iface);
1106 ITfThreadMgrEventSink *sink;
1107 struct list *cursor;
1108
1109 TRACE("(%p) %p\n",This,pdim);
1110
1111 SINK_FOR_EACH(cursor, &This->ThreadMgrEventSink, ITfThreadMgrEventSink, sink)
1112 {
1113 ITfThreadMgrEventSink_OnUninitDocumentMgr(sink, pdim);
1114 }
1115
1116 return S_OK;
1117 }
1118
1119 static HRESULT WINAPI ThreadMgrEventSink_OnSetFocus(
1120 ITfThreadMgrEventSink *iface, ITfDocumentMgr *pdimFocus,
1121 ITfDocumentMgr *pdimPrevFocus)
1122 {
1123 ThreadMgr *This = impl_from_ITfThreadMgrEventSink(iface);
1124 ITfThreadMgrEventSink *sink;
1125 struct list *cursor;
1126
1127 TRACE("(%p) %p %p\n",This,pdimFocus, pdimPrevFocus);
1128
1129 SINK_FOR_EACH(cursor, &This->ThreadMgrEventSink, ITfThreadMgrEventSink, sink)
1130 {
1131 ITfThreadMgrEventSink_OnSetFocus(sink, pdimFocus, pdimPrevFocus);
1132 }
1133
1134 return S_OK;
1135 }
1136
1137 static HRESULT WINAPI ThreadMgrEventSink_OnPushContext(
1138 ITfThreadMgrEventSink *iface, ITfContext *pic)
1139 {
1140 ThreadMgr *This = impl_from_ITfThreadMgrEventSink(iface);
1141 ITfThreadMgrEventSink *sink;
1142 struct list *cursor;
1143
1144 TRACE("(%p) %p\n",This,pic);
1145
1146 SINK_FOR_EACH(cursor, &This->ThreadMgrEventSink, ITfThreadMgrEventSink, sink)
1147 {
1148 ITfThreadMgrEventSink_OnPushContext(sink, pic);
1149 }
1150
1151 return S_OK;
1152 }
1153
1154 static HRESULT WINAPI ThreadMgrEventSink_OnPopContext(
1155 ITfThreadMgrEventSink *iface, ITfContext *pic)
1156 {
1157 ThreadMgr *This = impl_from_ITfThreadMgrEventSink(iface);
1158 ITfThreadMgrEventSink *sink;
1159 struct list *cursor;
1160
1161 TRACE("(%p) %p\n",This,pic);
1162
1163 SINK_FOR_EACH(cursor, &This->ThreadMgrEventSink, ITfThreadMgrEventSink, sink)
1164 {
1165 ITfThreadMgrEventSink_OnPopContext(sink, pic);
1166 }
1167
1168 return S_OK;
1169 }
1170
1171 static const ITfThreadMgrEventSinkVtbl ThreadMgrEventSinkVtbl =
1172 {
1173 ThreadMgrEventSink_QueryInterface,
1174 ThreadMgrEventSink_AddRef,
1175 ThreadMgrEventSink_Release,
1176 ThreadMgrEventSink_OnInitDocumentMgr,
1177 ThreadMgrEventSink_OnUninitDocumentMgr,
1178 ThreadMgrEventSink_OnSetFocus,
1179 ThreadMgrEventSink_OnPushContext,
1180 ThreadMgrEventSink_OnPopContext
1181 };
1182
1183 /*****************************************************
1184 * ITfUIElementMgr functions
1185 *****************************************************/
1186 static HRESULT WINAPI UIElementMgr_QueryInterface(ITfUIElementMgr *iface, REFIID iid, void **ppvOut)
1187 {
1188 ThreadMgr *This = impl_from_ITfUIElementMgr(iface);
1189
1190 return ITfThreadMgrEx_QueryInterface(&This->ITfThreadMgrEx_iface, iid, ppvOut);
1191 }
1192
1193 static ULONG WINAPI UIElementMgr_AddRef(ITfUIElementMgr *iface)
1194 {
1195 ThreadMgr *This = impl_from_ITfUIElementMgr(iface);
1196
1197 return ITfThreadMgrEx_AddRef(&This->ITfThreadMgrEx_iface);
1198 }
1199
1200 static ULONG WINAPI UIElementMgr_Release(ITfUIElementMgr *iface)
1201 {
1202 ThreadMgr *This = impl_from_ITfUIElementMgr(iface);
1203
1204 return ITfThreadMgrEx_Release(&This->ITfThreadMgrEx_iface);
1205 }
1206
1207 static HRESULT WINAPI UIElementMgr_BeginUIElement(ITfUIElementMgr *iface, ITfUIElement *element,
1208 BOOL *show, DWORD *id)
1209 {
1210 ThreadMgr *This = impl_from_ITfUIElementMgr(iface);
1211
1212 FIXME("STUB:(%p)\n", This);
1213 return E_NOTIMPL;
1214 }
1215
1216 static HRESULT WINAPI UIElementMgr_UpdateUIElement(ITfUIElementMgr *iface, DWORD id)
1217 {
1218 ThreadMgr *This = impl_from_ITfUIElementMgr(iface);
1219
1220 FIXME("STUB:(%p)\n", This);
1221 return E_NOTIMPL;
1222 }
1223
1224 static HRESULT WINAPI UIElementMgr_EndUIElement(ITfUIElementMgr *iface, DWORD id)
1225 {
1226 ThreadMgr *This = impl_from_ITfUIElementMgr(iface);
1227
1228 FIXME("STUB:(%p)\n", This);
1229 return E_NOTIMPL;
1230 }
1231
1232 static HRESULT WINAPI UIElementMgr_GetUIElement(ITfUIElementMgr *iface, DWORD id,
1233 ITfUIElement **element)
1234 {
1235 ThreadMgr *This = impl_from_ITfUIElementMgr(iface);
1236
1237 FIXME("STUB:(%p)\n", This);
1238 return E_NOTIMPL;
1239 }
1240
1241 static HRESULT WINAPI UIElementMgr_EnumUIElements(ITfUIElementMgr *iface,
1242 IEnumTfUIElements **enum_elements)
1243 {
1244 ThreadMgr *This = impl_from_ITfUIElementMgr(iface);
1245
1246 FIXME("STUB:(%p)\n", This);
1247 return E_NOTIMPL;
1248 }
1249
1250 static const ITfUIElementMgrVtbl ThreadMgrUIElementMgrVtbl =
1251 {
1252 UIElementMgr_QueryInterface,
1253 UIElementMgr_AddRef,
1254 UIElementMgr_Release,
1255
1256 UIElementMgr_BeginUIElement,
1257 UIElementMgr_UpdateUIElement,
1258 UIElementMgr_EndUIElement,
1259 UIElementMgr_GetUIElement,
1260 UIElementMgr_EnumUIElements
1261 };
1262
1263 /*****************************************************
1264 * ITfSourceSingle functions
1265 *****************************************************/
1266 static HRESULT WINAPI ThreadMgrSourceSingle_QueryInterface(ITfSourceSingle *iface, REFIID iid, LPVOID *ppvOut)
1267 {
1268 ThreadMgr *This = impl_from_ITfSourceSingle(iface);
1269 return ITfThreadMgrEx_QueryInterface(&This->ITfThreadMgrEx_iface, iid, ppvOut);
1270 }
1271
1272 static ULONG WINAPI ThreadMgrSourceSingle_AddRef(ITfSourceSingle *iface)
1273 {
1274 ThreadMgr *This = impl_from_ITfSourceSingle(iface);
1275 return ITfThreadMgrEx_AddRef(&This->ITfThreadMgrEx_iface);
1276 }
1277
1278 static ULONG WINAPI ThreadMgrSourceSingle_Release(ITfSourceSingle *iface)
1279 {
1280 ThreadMgr *This = impl_from_ITfSourceSingle(iface);
1281 return ITfThreadMgrEx_Release(&This->ITfThreadMgrEx_iface);
1282 }
1283
1284 static HRESULT WINAPI ThreadMgrSourceSingle_AdviseSingleSink( ITfSourceSingle *iface,
1285 TfClientId tid, REFIID riid, IUnknown *punk)
1286 {
1287 ThreadMgr *This = impl_from_ITfSourceSingle(iface);
1288 FIXME("STUB:(%p) %i %s %p\n",This, tid, debugstr_guid(riid),punk);
1289 return E_NOTIMPL;
1290 }
1291
1292 static HRESULT WINAPI ThreadMgrSourceSingle_UnadviseSingleSink( ITfSourceSingle *iface,
1293 TfClientId tid, REFIID riid)
1294 {
1295 ThreadMgr *This = impl_from_ITfSourceSingle(iface);
1296 FIXME("STUB:(%p) %i %s\n",This, tid, debugstr_guid(riid));
1297 return E_NOTIMPL;
1298 }
1299
1300 static const ITfSourceSingleVtbl SourceSingleVtbl =
1301 {
1302 ThreadMgrSourceSingle_QueryInterface,
1303 ThreadMgrSourceSingle_AddRef,
1304 ThreadMgrSourceSingle_Release,
1305 ThreadMgrSourceSingle_AdviseSingleSink,
1306 ThreadMgrSourceSingle_UnadviseSingleSink
1307 };
1308
1309 HRESULT ThreadMgr_Constructor(IUnknown *pUnkOuter, IUnknown **ppOut)
1310 {
1311 ThreadMgr *This;
1312 if (pUnkOuter)
1313 return CLASS_E_NOAGGREGATION;
1314
1315 /* Only 1 ThreadMgr is created per thread */
1316 This = TlsGetValue(tlsIndex);
1317 if (This)
1318 {
1319 ThreadMgr_AddRef(&This->ITfThreadMgrEx_iface);
1320 *ppOut = (IUnknown*)&This->ITfThreadMgrEx_iface;
1321 return S_OK;
1322 }
1323
1324 This = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(ThreadMgr));
1325 if (This == NULL)
1326 return E_OUTOFMEMORY;
1327
1328 This->ITfThreadMgrEx_iface.lpVtbl = &ThreadMgrExVtbl;
1329 This->ITfSource_iface.lpVtbl = &ThreadMgrSourceVtbl;
1330 This->ITfKeystrokeMgr_iface.lpVtbl = &KeystrokeMgrVtbl;
1331 This->ITfMessagePump_iface.lpVtbl = &MessagePumpVtbl;
1332 This->ITfClientId_iface.lpVtbl = &ClientIdVtbl;
1333 This->ITfThreadMgrEventSink_iface.lpVtbl = &ThreadMgrEventSinkVtbl;
1334 This->ITfUIElementMgr_iface.lpVtbl = &ThreadMgrUIElementMgrVtbl;
1335 This->ITfSourceSingle_iface.lpVtbl = &SourceSingleVtbl;
1336 This->refCount = 1;
1337 TlsSetValue(tlsIndex,This);
1338
1339 CompartmentMgr_Constructor((IUnknown*)&This->ITfThreadMgrEx_iface, &IID_IUnknown, (IUnknown**)&This->CompartmentMgr);
1340
1341 list_init(&This->CurrentPreservedKeys);
1342 list_init(&This->CreatedDocumentMgrs);
1343 list_init(&This->AssociatedFocusWindows);
1344
1345 list_init(&This->ActiveLanguageProfileNotifySink);
1346 list_init(&This->DisplayAttributeNotifySink);
1347 list_init(&This->KeyTraceEventSink);
1348 list_init(&This->PreservedKeyNotifySink);
1349 list_init(&This->ThreadFocusSink);
1350 list_init(&This->ThreadMgrEventSink);
1351
1352 TRACE("returning %p\n", This);
1353 *ppOut = (IUnknown *)&This->ITfThreadMgrEx_iface;
1354 return S_OK;
1355 }
1356
1357 /**************************************************
1358 * IEnumTfDocumentMgrs implementation
1359 **************************************************/
1360 static void EnumTfDocumentMgr_Destructor(EnumTfDocumentMgr *This)
1361 {
1362 TRACE("destroying %p\n", This);
1363 HeapFree(GetProcessHeap(),0,This);
1364 }
1365
1366 static HRESULT WINAPI EnumTfDocumentMgr_QueryInterface(IEnumTfDocumentMgrs *iface, REFIID iid, LPVOID *ppvOut)
1367 {
1368 EnumTfDocumentMgr *This = impl_from_IEnumTfDocumentMgrs(iface);
1369 *ppvOut = NULL;
1370
1371 if (IsEqualIID(iid, &IID_IUnknown) || IsEqualIID(iid, &IID_IEnumTfDocumentMgrs))
1372 {
1373 *ppvOut = &This->IEnumTfDocumentMgrs_iface;
1374 }
1375
1376 if (*ppvOut)
1377 {
1378 IEnumTfDocumentMgrs_AddRef(iface);
1379 return S_OK;
1380 }
1381
1382 WARN("unsupported interface: %s\n", debugstr_guid(iid));
1383 return E_NOINTERFACE;
1384 }
1385
1386 static ULONG WINAPI EnumTfDocumentMgr_AddRef(IEnumTfDocumentMgrs *iface)
1387 {
1388 EnumTfDocumentMgr *This = impl_from_IEnumTfDocumentMgrs(iface);
1389 return InterlockedIncrement(&This->refCount);
1390 }
1391
1392 static ULONG WINAPI EnumTfDocumentMgr_Release(IEnumTfDocumentMgrs *iface)
1393 {
1394 EnumTfDocumentMgr *This = impl_from_IEnumTfDocumentMgrs(iface);
1395 ULONG ret;
1396
1397 ret = InterlockedDecrement(&This->refCount);
1398 if (ret == 0)
1399 EnumTfDocumentMgr_Destructor(This);
1400 return ret;
1401 }
1402
1403 static HRESULT WINAPI EnumTfDocumentMgr_Next(IEnumTfDocumentMgrs *iface,
1404 ULONG ulCount, ITfDocumentMgr **rgDocumentMgr, ULONG *pcFetched)
1405 {
1406 EnumTfDocumentMgr *This = impl_from_IEnumTfDocumentMgrs(iface);
1407 ULONG fetched = 0;
1408
1409 TRACE("(%p)\n",This);
1410
1411 if (rgDocumentMgr == NULL) return E_POINTER;
1412
1413 while (fetched < ulCount)
1414 {
1415 DocumentMgrEntry *mgrentry;
1416 if (This->index == NULL)
1417 break;
1418
1419 mgrentry = LIST_ENTRY(This->index,DocumentMgrEntry,entry);
1420 if (mgrentry == NULL)
1421 break;
1422
1423 *rgDocumentMgr = mgrentry->docmgr;
1424 ITfDocumentMgr_AddRef(*rgDocumentMgr);
1425
1426 This->index = list_next(This->head, This->index);
1427 ++fetched;
1428 ++rgDocumentMgr;
1429 }
1430
1431 if (pcFetched) *pcFetched = fetched;
1432 return fetched == ulCount ? S_OK : S_FALSE;
1433 }
1434
1435 static HRESULT WINAPI EnumTfDocumentMgr_Skip( IEnumTfDocumentMgrs* iface, ULONG celt)
1436 {
1437 EnumTfDocumentMgr *This = impl_from_IEnumTfDocumentMgrs(iface);
1438 ULONG i;
1439
1440 TRACE("(%p)\n",This);
1441 for(i = 0; i < celt && This->index != NULL; i++)
1442 This->index = list_next(This->head, This->index);
1443 return S_OK;
1444 }
1445
1446 static HRESULT WINAPI EnumTfDocumentMgr_Reset( IEnumTfDocumentMgrs* iface)
1447 {
1448 EnumTfDocumentMgr *This = impl_from_IEnumTfDocumentMgrs(iface);
1449 TRACE("(%p)\n",This);
1450 This->index = list_head(This->head);
1451 return S_OK;
1452 }
1453
1454 static HRESULT WINAPI EnumTfDocumentMgr_Clone( IEnumTfDocumentMgrs *iface,
1455 IEnumTfDocumentMgrs **ppenum)
1456 {
1457 EnumTfDocumentMgr *This = impl_from_IEnumTfDocumentMgrs(iface);
1458 HRESULT res;
1459
1460 TRACE("(%p)\n",This);
1461
1462 if (ppenum == NULL) return E_POINTER;
1463
1464 res = EnumTfDocumentMgr_Constructor(This->head, ppenum);
1465 if (SUCCEEDED(res))
1466 {
1467 EnumTfDocumentMgr *new_This = impl_from_IEnumTfDocumentMgrs(*ppenum);
1468 new_This->index = This->index;
1469 }
1470 return res;
1471 }
1472
1473 static const IEnumTfDocumentMgrsVtbl EnumTfDocumentMgrsVtbl =
1474 {
1475 EnumTfDocumentMgr_QueryInterface,
1476 EnumTfDocumentMgr_AddRef,
1477 EnumTfDocumentMgr_Release,
1478 EnumTfDocumentMgr_Clone,
1479 EnumTfDocumentMgr_Next,
1480 EnumTfDocumentMgr_Reset,
1481 EnumTfDocumentMgr_Skip
1482 };
1483
1484 static HRESULT EnumTfDocumentMgr_Constructor(struct list* head, IEnumTfDocumentMgrs **ppOut)
1485 {
1486 EnumTfDocumentMgr *This;
1487
1488 This = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(EnumTfDocumentMgr));
1489 if (This == NULL)
1490 return E_OUTOFMEMORY;
1491
1492 This->IEnumTfDocumentMgrs_iface.lpVtbl= &EnumTfDocumentMgrsVtbl;
1493 This->refCount = 1;
1494 This->head = head;
1495 This->index = list_head(This->head);
1496
1497 TRACE("returning %p\n", &This->IEnumTfDocumentMgrs_iface);
1498 *ppOut = &This->IEnumTfDocumentMgrs_iface;
1499 return S_OK;
1500 }
1501
1502 void ThreadMgr_OnDocumentMgrDestruction(ITfThreadMgr *iface, ITfDocumentMgr *mgr)
1503 {
1504 ThreadMgr *This = impl_from_ITfThreadMgrEx((ITfThreadMgrEx *)iface);
1505 struct list *cursor;
1506 LIST_FOR_EACH(cursor, &This->CreatedDocumentMgrs)
1507 {
1508 DocumentMgrEntry *mgrentry = LIST_ENTRY(cursor,DocumentMgrEntry,entry);
1509 if (mgrentry->docmgr == mgr)
1510 {
1511 list_remove(cursor);
1512 HeapFree(GetProcessHeap(),0,mgrentry);
1513 return;
1514 }
1515 }
1516 FIXME("ITfDocumentMgr %p not found in this thread\n",mgr);
1517 }