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