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