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