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