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