[NTOS:KE/x64] Handle NMI vs swapgs race condition
[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 <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
113 static inline ThreadMgr *impl_from_ITfThreadMgrEx(ITfThreadMgrEx *iface)
114 {
115 return CONTAINING_RECORD(iface, ThreadMgr, ITfThreadMgrEx_iface);
116 }
117
118 static inline ThreadMgr *impl_from_ITfSource(ITfSource *iface)
119 {
120 return CONTAINING_RECORD(iface, ThreadMgr, ITfSource_iface);
121 }
122
123 static inline ThreadMgr *impl_from_ITfKeystrokeMgr(ITfKeystrokeMgr *iface)
124 {
125 return CONTAINING_RECORD(iface, ThreadMgr, ITfKeystrokeMgr_iface);
126 }
127
128 static inline ThreadMgr *impl_from_ITfMessagePump(ITfMessagePump *iface)
129 {
130 return CONTAINING_RECORD(iface, ThreadMgr, ITfMessagePump_iface);
131 }
132
133 static inline ThreadMgr *impl_from_ITfClientId(ITfClientId *iface)
134 {
135 return CONTAINING_RECORD(iface, ThreadMgr, ITfClientId_iface);
136 }
137
138 static inline ThreadMgr *impl_from_ITfThreadMgrEventSink(ITfThreadMgrEventSink *iface)
139 {
140 return CONTAINING_RECORD(iface, ThreadMgr, ITfThreadMgrEventSink_iface);
141 }
142
143 static inline ThreadMgr *impl_from_ITfUIElementMgr(ITfUIElementMgr *iface)
144 {
145 return CONTAINING_RECORD(iface, ThreadMgr, ITfUIElementMgr_iface);
146 }
147
148 static inline ThreadMgr *impl_from_ITfSourceSingle(ITfSourceSingle *iface)
149 {
150 return CONTAINING_RECORD(iface, ThreadMgr, ITfSourceSingle_iface);
151 }
152
153 static inline EnumTfDocumentMgr *impl_from_IEnumTfDocumentMgrs(IEnumTfDocumentMgrs *iface)
154 {
155 return CONTAINING_RECORD(iface, EnumTfDocumentMgr, IEnumTfDocumentMgrs_iface);
156 }
157
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
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 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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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 *****************************************************/
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
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
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
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
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
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
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
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 *****************************************************/
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
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
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
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
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
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
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
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 *****************************************************/
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
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
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
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
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
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 **************************************************/
1395 static void EnumTfDocumentMgr_Destructor(EnumTfDocumentMgr *This)
1396 {
1397 TRACE("destroying %p\n", This);
1398 HeapFree(GetProcessHeap(),0,This);
1399 }
1400
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
1421 static ULONG WINAPI EnumTfDocumentMgr_AddRef(IEnumTfDocumentMgrs *iface)
1422 {
1423 EnumTfDocumentMgr *This = impl_from_IEnumTfDocumentMgrs(iface);
1424 return InterlockedIncrement(&This->refCount);
1425 }
1426
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
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
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
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
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
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
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 }