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 "config.h" 22 23 #include <stdarg.h> 24 25 #define COBJMACROS 26 27 #include "wine/debug.h" 28 #include "windef.h" 29 #include "winbase.h" 30 #include "winreg.h" 31 #include "winuser.h" 32 #include "shlwapi.h" 33 #include "winerror.h" 34 #include "objbase.h" 35 #include "olectl.h" 36 37 #include "wine/unicode.h" 38 39 #include "msctf.h" 40 #include "msctf_internal.h" 41 42 WINE_DEFAULT_DEBUG_CHANNEL(msctf); 43 44 typedef struct tagPreservedKey 45 { 46 struct list entry; 47 GUID guid; 48 TF_PRESERVEDKEY prekey; 49 LPWSTR description; 50 TfClientId tid; 51 } PreservedKey; 52 53 typedef struct tagDocumentMgrs 54 { 55 struct list entry; 56 ITfDocumentMgr *docmgr; 57 } DocumentMgrEntry; 58 59 typedef struct tagAssociatedWindow 60 { 61 struct list entry; 62 HWND hwnd; 63 ITfDocumentMgr *docmgr; 64 } AssociatedWindow; 65 66 typedef struct tagACLMulti { 67 ITfThreadMgrEx ITfThreadMgrEx_iface; 68 ITfSource ITfSource_iface; 69 ITfKeystrokeMgr ITfKeystrokeMgr_iface; 70 ITfMessagePump ITfMessagePump_iface; 71 ITfClientId ITfClientId_iface; 72 /* const ITfThreadMgrExVtbl *ThreadMgrExVtbl; */ 73 /* const ITfConfigureSystemKeystrokeFeedVtbl *ConfigureSystemKeystrokeFeedVtbl; */ 74 /* const ITfLangBarItemMgrVtbl *LangBarItemMgrVtbl; */ 75 ITfUIElementMgr ITfUIElementMgr_iface; 76 ITfSourceSingle ITfSourceSingle_iface; 77 LONG refCount; 78 79 /* Aggregation */ 80 ITfCompartmentMgr *CompartmentMgr; 81 82 ITfThreadMgrEventSink ITfThreadMgrEventSink_iface; /* internal */ 83 84 ITfDocumentMgr *focus; 85 LONG activationCount; 86 87 ITfKeyEventSink *foregroundKeyEventSink; 88 CLSID foregroundTextService; 89 90 struct list CurrentPreservedKeys; 91 struct list CreatedDocumentMgrs; 92 93 struct list AssociatedFocusWindows; 94 HHOOK focusHook; 95 96 /* kept as separate lists to reduce unnecessary iterations */ 97 struct list ActiveLanguageProfileNotifySink; 98 struct list DisplayAttributeNotifySink; 99 struct list KeyTraceEventSink; 100 struct list PreservedKeyNotifySink; 101 struct list ThreadFocusSink; 102 struct list ThreadMgrEventSink; 103 } ThreadMgr; 104 105 typedef struct tagEnumTfDocumentMgr { 106 IEnumTfDocumentMgrs IEnumTfDocumentMgrs_iface; 107 LONG refCount; 108 109 struct list *index; 110 struct list *head; 111 } EnumTfDocumentMgr; 112 113 static HRESULT EnumTfDocumentMgr_Constructor(struct list* head, IEnumTfDocumentMgrs **ppOut); 114 115 static inline ThreadMgr *impl_from_ITfThreadMgrEx(ITfThreadMgrEx *iface) 116 { 117 return CONTAINING_RECORD(iface, ThreadMgr, ITfThreadMgrEx_iface); 118 } 119 120 static inline ThreadMgr *impl_from_ITfSource(ITfSource *iface) 121 { 122 return CONTAINING_RECORD(iface, ThreadMgr, ITfSource_iface); 123 } 124 125 static inline ThreadMgr *impl_from_ITfKeystrokeMgr(ITfKeystrokeMgr *iface) 126 { 127 return CONTAINING_RECORD(iface, ThreadMgr, ITfKeystrokeMgr_iface); 128 } 129 130 static inline ThreadMgr *impl_from_ITfMessagePump(ITfMessagePump *iface) 131 { 132 return CONTAINING_RECORD(iface, ThreadMgr, ITfMessagePump_iface); 133 } 134 135 static inline ThreadMgr *impl_from_ITfClientId(ITfClientId *iface) 136 { 137 return CONTAINING_RECORD(iface, ThreadMgr, ITfClientId_iface); 138 } 139 140 static inline ThreadMgr *impl_from_ITfThreadMgrEventSink(ITfThreadMgrEventSink *iface) 141 { 142 return CONTAINING_RECORD(iface, ThreadMgr, ITfThreadMgrEventSink_iface); 143 } 144 145 static inline ThreadMgr *impl_from_ITfUIElementMgr(ITfUIElementMgr *iface) 146 { 147 return CONTAINING_RECORD(iface, ThreadMgr, ITfUIElementMgr_iface); 148 } 149 150 static inline ThreadMgr *impl_from_ITfSourceSingle(ITfSourceSingle *iface) 151 { 152 return CONTAINING_RECORD(iface, ThreadMgr, ITfSourceSingle_iface); 153 } 154 155 static inline EnumTfDocumentMgr *impl_from_IEnumTfDocumentMgrs(IEnumTfDocumentMgrs *iface) 156 { 157 return CONTAINING_RECORD(iface, EnumTfDocumentMgr, IEnumTfDocumentMgrs_iface); 158 } 159 160 static void ThreadMgr_Destructor(ThreadMgr *This) 161 { 162 struct list *cursor, *cursor2; 163 164 /* unhook right away */ 165 if (This->focusHook) 166 UnhookWindowsHookEx(This->focusHook); 167 168 TlsSetValue(tlsIndex,NULL); 169 TRACE("destroying %p\n", This); 170 if (This->focus) 171 ITfDocumentMgr_Release(This->focus); 172 173 free_sinks(&This->ActiveLanguageProfileNotifySink); 174 free_sinks(&This->DisplayAttributeNotifySink); 175 free_sinks(&This->KeyTraceEventSink); 176 free_sinks(&This->PreservedKeyNotifySink); 177 free_sinks(&This->ThreadFocusSink); 178 free_sinks(&This->ThreadMgrEventSink); 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_ITfKeyTraceEventSink)) 625 { 626 WARN("semi-stub for ITfKeyTraceEventSink: sink won't be used.\n"); 627 return advise_sink(&This->KeyTraceEventSink, &IID_ITfKeyTraceEventSink, 628 COOKIE_MAGIC_KEYTRACESINK, punk, pdwCookie); 629 } 630 631 FIXME("(%p) Unhandled Sink: %s\n",This,debugstr_guid(riid)); 632 return E_NOTIMPL; 633 } 634 635 static HRESULT WINAPI ThreadMgrSource_UnadviseSink(ITfSource *iface, DWORD pdwCookie) 636 { 637 ThreadMgr *This = impl_from_ITfSource(iface); 638 DWORD magic; 639 640 TRACE("(%p) %x\n",This,pdwCookie); 641 642 magic = get_Cookie_magic(pdwCookie); 643 if (magic != COOKIE_MAGIC_TMSINK && magic != COOKIE_MAGIC_THREADFOCUSSINK 644 && magic != COOKIE_MAGIC_KEYTRACESINK) 645 return E_INVALIDARG; 646 647 return unadvise_sink(pdwCookie); 648 } 649 650 static const ITfSourceVtbl ThreadMgrSourceVtbl = 651 { 652 Source_QueryInterface, 653 Source_AddRef, 654 Source_Release, 655 ThreadMgrSource_AdviseSink, 656 ThreadMgrSource_UnadviseSink, 657 }; 658 659 /***************************************************** 660 * ITfKeystrokeMgr functions 661 *****************************************************/ 662 663 static HRESULT WINAPI KeystrokeMgr_QueryInterface(ITfKeystrokeMgr *iface, REFIID iid, LPVOID *ppvOut) 664 { 665 ThreadMgr *This = impl_from_ITfKeystrokeMgr(iface); 666 return ITfThreadMgrEx_QueryInterface(&This->ITfThreadMgrEx_iface, iid, ppvOut); 667 } 668 669 static ULONG WINAPI KeystrokeMgr_AddRef(ITfKeystrokeMgr *iface) 670 { 671 ThreadMgr *This = impl_from_ITfKeystrokeMgr(iface); 672 return ITfThreadMgrEx_AddRef(&This->ITfThreadMgrEx_iface); 673 } 674 675 static ULONG WINAPI KeystrokeMgr_Release(ITfKeystrokeMgr *iface) 676 { 677 ThreadMgr *This = impl_from_ITfKeystrokeMgr(iface); 678 return ITfThreadMgrEx_Release(&This->ITfThreadMgrEx_iface); 679 } 680 681 static HRESULT WINAPI KeystrokeMgr_AdviseKeyEventSink(ITfKeystrokeMgr *iface, 682 TfClientId tid, ITfKeyEventSink *pSink, BOOL fForeground) 683 { 684 ThreadMgr *This = impl_from_ITfKeystrokeMgr(iface); 685 CLSID textservice; 686 ITfKeyEventSink *check = NULL; 687 688 TRACE("(%p) %x %p %i\n",This,tid,pSink,fForeground); 689 690 if (!tid || !pSink) 691 return E_INVALIDARG; 692 693 textservice = get_textservice_clsid(tid); 694 if (IsEqualCLSID(&GUID_NULL,&textservice)) 695 return E_INVALIDARG; 696 697 get_textservice_sink(tid, &IID_ITfKeyEventSink, (IUnknown**)&check); 698 if (check != NULL) 699 return CONNECT_E_ADVISELIMIT; 700 701 if (FAILED(ITfKeyEventSink_QueryInterface(pSink,&IID_ITfKeyEventSink,(LPVOID*) &check))) 702 return E_INVALIDARG; 703 704 set_textservice_sink(tid, &IID_ITfKeyEventSink, (IUnknown*)check); 705 706 if (fForeground) 707 { 708 if (This->foregroundKeyEventSink) 709 { 710 ITfKeyEventSink_OnSetFocus(This->foregroundKeyEventSink, FALSE); 711 ITfKeyEventSink_Release(This->foregroundKeyEventSink); 712 } 713 ITfKeyEventSink_AddRef(check); 714 ITfKeyEventSink_OnSetFocus(check, TRUE); 715 This->foregroundKeyEventSink = check; 716 This->foregroundTextService = textservice; 717 } 718 return S_OK; 719 } 720 721 static HRESULT WINAPI KeystrokeMgr_UnadviseKeyEventSink(ITfKeystrokeMgr *iface, 722 TfClientId tid) 723 { 724 ThreadMgr *This = impl_from_ITfKeystrokeMgr(iface); 725 CLSID textservice; 726 ITfKeyEventSink *check = NULL; 727 TRACE("(%p) %x\n",This,tid); 728 729 if (!tid) 730 return E_INVALIDARG; 731 732 textservice = get_textservice_clsid(tid); 733 if (IsEqualCLSID(&GUID_NULL,&textservice)) 734 return E_INVALIDARG; 735 736 get_textservice_sink(tid, &IID_ITfKeyEventSink, (IUnknown**)&check); 737 738 if (!check) 739 return CONNECT_E_NOCONNECTION; 740 741 set_textservice_sink(tid, &IID_ITfKeyEventSink, NULL); 742 ITfKeyEventSink_Release(check); 743 744 if (This->foregroundKeyEventSink == check) 745 { 746 ITfKeyEventSink_Release(This->foregroundKeyEventSink); 747 This->foregroundKeyEventSink = NULL; 748 This->foregroundTextService = GUID_NULL; 749 } 750 return S_OK; 751 } 752 753 static HRESULT WINAPI KeystrokeMgr_GetForeground(ITfKeystrokeMgr *iface, 754 CLSID *pclsid) 755 { 756 ThreadMgr *This = impl_from_ITfKeystrokeMgr(iface); 757 TRACE("(%p) %p\n",This,pclsid); 758 if (!pclsid) 759 return E_INVALIDARG; 760 761 if (IsEqualCLSID(&This->foregroundTextService,&GUID_NULL)) 762 return S_FALSE; 763 764 *pclsid = This->foregroundTextService; 765 return S_OK; 766 } 767 768 static HRESULT WINAPI KeystrokeMgr_TestKeyDown(ITfKeystrokeMgr *iface, 769 WPARAM wParam, LPARAM lParam, BOOL *pfEaten) 770 { 771 ThreadMgr *This = impl_from_ITfKeystrokeMgr(iface); 772 FIXME("STUB:(%p)\n",This); 773 *pfEaten = FALSE; 774 return S_OK; 775 } 776 777 static HRESULT WINAPI KeystrokeMgr_TestKeyUp(ITfKeystrokeMgr *iface, 778 WPARAM wParam, LPARAM lParam, BOOL *pfEaten) 779 { 780 ThreadMgr *This = impl_from_ITfKeystrokeMgr(iface); 781 FIXME("STUB:(%p)\n",This); 782 *pfEaten = FALSE; 783 return S_OK; 784 } 785 786 static HRESULT WINAPI KeystrokeMgr_KeyDown(ITfKeystrokeMgr *iface, 787 WPARAM wParam, LPARAM lParam, BOOL *pfEaten) 788 { 789 ThreadMgr *This = impl_from_ITfKeystrokeMgr(iface); 790 FIXME("STUB:(%p)\n",This); 791 return E_NOTIMPL; 792 } 793 794 static HRESULT WINAPI KeystrokeMgr_KeyUp(ITfKeystrokeMgr *iface, 795 WPARAM wParam, LPARAM lParam, BOOL *pfEaten) 796 { 797 ThreadMgr *This = impl_from_ITfKeystrokeMgr(iface); 798 FIXME("STUB:(%p)\n",This); 799 return E_NOTIMPL; 800 } 801 802 static HRESULT WINAPI KeystrokeMgr_GetPreservedKey(ITfKeystrokeMgr *iface, 803 ITfContext *pic, const TF_PRESERVEDKEY *pprekey, GUID *pguid) 804 { 805 ThreadMgr *This = impl_from_ITfKeystrokeMgr(iface); 806 FIXME("STUB:(%p)\n",This); 807 return E_NOTIMPL; 808 } 809 810 static HRESULT WINAPI KeystrokeMgr_IsPreservedKey(ITfKeystrokeMgr *iface, 811 REFGUID rguid, const TF_PRESERVEDKEY *pprekey, BOOL *pfRegistered) 812 { 813 ThreadMgr *This = impl_from_ITfKeystrokeMgr(iface); 814 struct list *cursor; 815 816 TRACE("(%p) %s (%x %x) %p\n",This,debugstr_guid(rguid), (pprekey)?pprekey->uVKey:0, (pprekey)?pprekey->uModifiers:0, pfRegistered); 817 818 if (!rguid || !pprekey || !pfRegistered) 819 return E_INVALIDARG; 820 821 LIST_FOR_EACH(cursor, &This->CurrentPreservedKeys) 822 { 823 PreservedKey* key = LIST_ENTRY(cursor,PreservedKey,entry); 824 if (IsEqualGUID(rguid,&key->guid) && pprekey->uVKey == key->prekey.uVKey && pprekey->uModifiers == key->prekey.uModifiers) 825 { 826 *pfRegistered = TRUE; 827 return S_OK; 828 } 829 } 830 831 *pfRegistered = FALSE; 832 return S_FALSE; 833 } 834 835 static HRESULT WINAPI KeystrokeMgr_PreserveKey(ITfKeystrokeMgr *iface, 836 TfClientId tid, REFGUID rguid, const TF_PRESERVEDKEY *prekey, 837 const WCHAR *pchDesc, ULONG cchDesc) 838 { 839 ThreadMgr *This = impl_from_ITfKeystrokeMgr(iface); 840 struct list *cursor; 841 PreservedKey *newkey; 842 843 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)); 844 845 if (!tid || ! rguid || !prekey || (cchDesc && !pchDesc)) 846 return E_INVALIDARG; 847 848 LIST_FOR_EACH(cursor, &This->CurrentPreservedKeys) 849 { 850 PreservedKey* key = LIST_ENTRY(cursor,PreservedKey,entry); 851 if (IsEqualGUID(rguid,&key->guid) && prekey->uVKey == key->prekey.uVKey && prekey->uModifiers == key->prekey.uModifiers) 852 return TF_E_ALREADY_EXISTS; 853 } 854 855 newkey = HeapAlloc(GetProcessHeap(),0,sizeof(PreservedKey)); 856 if (!newkey) 857 return E_OUTOFMEMORY; 858 859 newkey->guid = *rguid; 860 newkey->prekey = *prekey; 861 newkey->tid = tid; 862 newkey->description = NULL; 863 if (cchDesc) 864 { 865 newkey->description = HeapAlloc(GetProcessHeap(),0,cchDesc * sizeof(WCHAR)); 866 if (!newkey->description) 867 { 868 HeapFree(GetProcessHeap(),0,newkey); 869 return E_OUTOFMEMORY; 870 } 871 memcpy(newkey->description, pchDesc, cchDesc*sizeof(WCHAR)); 872 } 873 874 list_add_head(&This->CurrentPreservedKeys,&newkey->entry); 875 876 return S_OK; 877 } 878 879 static HRESULT WINAPI KeystrokeMgr_UnpreserveKey(ITfKeystrokeMgr *iface, 880 REFGUID rguid, const TF_PRESERVEDKEY *pprekey) 881 { 882 ThreadMgr *This = impl_from_ITfKeystrokeMgr(iface); 883 PreservedKey* key = NULL; 884 struct list *cursor; 885 TRACE("(%p) %s (%x %x)\n",This,debugstr_guid(rguid),(pprekey)?pprekey->uVKey:0, (pprekey)?pprekey->uModifiers:0); 886 887 if (!pprekey || !rguid) 888 return E_INVALIDARG; 889 890 LIST_FOR_EACH(cursor, &This->CurrentPreservedKeys) 891 { 892 key = LIST_ENTRY(cursor,PreservedKey,entry); 893 if (IsEqualGUID(rguid,&key->guid) && pprekey->uVKey == key->prekey.uVKey && pprekey->uModifiers == key->prekey.uModifiers) 894 break; 895 key = NULL; 896 } 897 898 if (!key) 899 return CONNECT_E_NOCONNECTION; 900 901 list_remove(&key->entry); 902 HeapFree(GetProcessHeap(),0,key->description); 903 HeapFree(GetProcessHeap(),0,key); 904 905 return S_OK; 906 } 907 908 static HRESULT WINAPI KeystrokeMgr_SetPreservedKeyDescription(ITfKeystrokeMgr *iface, 909 REFGUID rguid, const WCHAR *pchDesc, ULONG cchDesc) 910 { 911 ThreadMgr *This = impl_from_ITfKeystrokeMgr(iface); 912 FIXME("STUB:(%p)\n",This); 913 return E_NOTIMPL; 914 } 915 916 static HRESULT WINAPI KeystrokeMgr_GetPreservedKeyDescription(ITfKeystrokeMgr *iface, 917 REFGUID rguid, BSTR *pbstrDesc) 918 { 919 ThreadMgr *This = impl_from_ITfKeystrokeMgr(iface); 920 FIXME("STUB:(%p)\n",This); 921 return E_NOTIMPL; 922 } 923 924 static HRESULT WINAPI KeystrokeMgr_SimulatePreservedKey(ITfKeystrokeMgr *iface, 925 ITfContext *pic, REFGUID rguid, BOOL *pfEaten) 926 { 927 ThreadMgr *This = impl_from_ITfKeystrokeMgr(iface); 928 FIXME("STUB:(%p)\n",This); 929 return E_NOTIMPL; 930 } 931 932 static const ITfKeystrokeMgrVtbl KeystrokeMgrVtbl = 933 { 934 KeystrokeMgr_QueryInterface, 935 KeystrokeMgr_AddRef, 936 KeystrokeMgr_Release, 937 KeystrokeMgr_AdviseKeyEventSink, 938 KeystrokeMgr_UnadviseKeyEventSink, 939 KeystrokeMgr_GetForeground, 940 KeystrokeMgr_TestKeyDown, 941 KeystrokeMgr_TestKeyUp, 942 KeystrokeMgr_KeyDown, 943 KeystrokeMgr_KeyUp, 944 KeystrokeMgr_GetPreservedKey, 945 KeystrokeMgr_IsPreservedKey, 946 KeystrokeMgr_PreserveKey, 947 KeystrokeMgr_UnpreserveKey, 948 KeystrokeMgr_SetPreservedKeyDescription, 949 KeystrokeMgr_GetPreservedKeyDescription, 950 KeystrokeMgr_SimulatePreservedKey 951 }; 952 953 /***************************************************** 954 * ITfMessagePump functions 955 *****************************************************/ 956 957 static HRESULT WINAPI MessagePump_QueryInterface(ITfMessagePump *iface, REFIID iid, LPVOID *ppvOut) 958 { 959 ThreadMgr *This = impl_from_ITfMessagePump(iface); 960 return ITfThreadMgrEx_QueryInterface(&This->ITfThreadMgrEx_iface, iid, ppvOut); 961 } 962 963 static ULONG WINAPI MessagePump_AddRef(ITfMessagePump *iface) 964 { 965 ThreadMgr *This = impl_from_ITfMessagePump(iface); 966 return ITfThreadMgrEx_AddRef(&This->ITfThreadMgrEx_iface); 967 } 968 969 static ULONG WINAPI MessagePump_Release(ITfMessagePump *iface) 970 { 971 ThreadMgr *This = impl_from_ITfMessagePump(iface); 972 return ITfThreadMgrEx_Release(&This->ITfThreadMgrEx_iface); 973 } 974 975 static HRESULT WINAPI MessagePump_PeekMessageA(ITfMessagePump *iface, 976 LPMSG pMsg, HWND hwnd, UINT wMsgFilterMin, UINT wMsgFilterMax, 977 UINT wRemoveMsg, BOOL *pfResult) 978 { 979 if (!pfResult) 980 return E_INVALIDARG; 981 *pfResult = PeekMessageA(pMsg, hwnd, wMsgFilterMin, wMsgFilterMax, wRemoveMsg); 982 return S_OK; 983 } 984 985 static HRESULT WINAPI MessagePump_GetMessageA(ITfMessagePump *iface, 986 LPMSG pMsg, HWND hwnd, UINT wMsgFilterMin, UINT wMsgFilterMax, 987 BOOL *pfResult) 988 { 989 if (!pfResult) 990 return E_INVALIDARG; 991 *pfResult = GetMessageA(pMsg, hwnd, wMsgFilterMin, wMsgFilterMax); 992 return S_OK; 993 } 994 995 static HRESULT WINAPI MessagePump_PeekMessageW(ITfMessagePump *iface, 996 LPMSG pMsg, HWND hwnd, UINT wMsgFilterMin, UINT wMsgFilterMax, 997 UINT wRemoveMsg, BOOL *pfResult) 998 { 999 if (!pfResult) 1000 return E_INVALIDARG; 1001 *pfResult = PeekMessageW(pMsg, hwnd, wMsgFilterMin, wMsgFilterMax, wRemoveMsg); 1002 return S_OK; 1003 } 1004 1005 static HRESULT WINAPI MessagePump_GetMessageW(ITfMessagePump *iface, 1006 LPMSG pMsg, HWND hwnd, UINT wMsgFilterMin, UINT wMsgFilterMax, 1007 BOOL *pfResult) 1008 { 1009 if (!pfResult) 1010 return E_INVALIDARG; 1011 *pfResult = GetMessageW(pMsg, hwnd, wMsgFilterMin, wMsgFilterMax); 1012 return S_OK; 1013 } 1014 1015 static const ITfMessagePumpVtbl MessagePumpVtbl = 1016 { 1017 MessagePump_QueryInterface, 1018 MessagePump_AddRef, 1019 MessagePump_Release, 1020 MessagePump_PeekMessageA, 1021 MessagePump_GetMessageA, 1022 MessagePump_PeekMessageW, 1023 MessagePump_GetMessageW 1024 }; 1025 1026 /***************************************************** 1027 * ITfClientId functions 1028 *****************************************************/ 1029 1030 static HRESULT WINAPI ClientId_QueryInterface(ITfClientId *iface, REFIID iid, LPVOID *ppvOut) 1031 { 1032 ThreadMgr *This = impl_from_ITfClientId(iface); 1033 return ITfThreadMgrEx_QueryInterface(&This->ITfThreadMgrEx_iface, iid, ppvOut); 1034 } 1035 1036 static ULONG WINAPI ClientId_AddRef(ITfClientId *iface) 1037 { 1038 ThreadMgr *This = impl_from_ITfClientId(iface); 1039 return ITfThreadMgrEx_AddRef(&This->ITfThreadMgrEx_iface); 1040 } 1041 1042 static ULONG WINAPI ClientId_Release(ITfClientId *iface) 1043 { 1044 ThreadMgr *This = impl_from_ITfClientId(iface); 1045 return ITfThreadMgrEx_Release(&This->ITfThreadMgrEx_iface); 1046 } 1047 1048 static HRESULT WINAPI ClientId_GetClientId(ITfClientId *iface, 1049 REFCLSID rclsid, TfClientId *ptid) 1050 1051 { 1052 ThreadMgr *This = impl_from_ITfClientId(iface); 1053 HRESULT hr; 1054 ITfCategoryMgr *catmgr; 1055 1056 TRACE("(%p) %s\n",This,debugstr_guid(rclsid)); 1057 1058 CategoryMgr_Constructor(NULL,(IUnknown**)&catmgr); 1059 hr = ITfCategoryMgr_RegisterGUID(catmgr,rclsid,ptid); 1060 ITfCategoryMgr_Release(catmgr); 1061 1062 return hr; 1063 } 1064 1065 static const ITfClientIdVtbl ClientIdVtbl = 1066 { 1067 ClientId_QueryInterface, 1068 ClientId_AddRef, 1069 ClientId_Release, 1070 ClientId_GetClientId 1071 }; 1072 1073 /***************************************************** 1074 * ITfThreadMgrEventSink functions (internal) 1075 *****************************************************/ 1076 static HRESULT WINAPI ThreadMgrEventSink_QueryInterface(ITfThreadMgrEventSink *iface, REFIID iid, LPVOID *ppvOut) 1077 { 1078 ThreadMgr *This = impl_from_ITfThreadMgrEventSink(iface); 1079 return ITfThreadMgrEx_QueryInterface(&This->ITfThreadMgrEx_iface, iid, ppvOut); 1080 } 1081 1082 static ULONG WINAPI ThreadMgrEventSink_AddRef(ITfThreadMgrEventSink *iface) 1083 { 1084 ThreadMgr *This = impl_from_ITfThreadMgrEventSink(iface); 1085 return ITfThreadMgrEx_AddRef(&This->ITfThreadMgrEx_iface); 1086 } 1087 1088 static ULONG WINAPI ThreadMgrEventSink_Release(ITfThreadMgrEventSink *iface) 1089 { 1090 ThreadMgr *This = impl_from_ITfThreadMgrEventSink(iface); 1091 return ITfThreadMgrEx_Release(&This->ITfThreadMgrEx_iface); 1092 } 1093 1094 1095 static HRESULT WINAPI ThreadMgrEventSink_OnInitDocumentMgr( 1096 ITfThreadMgrEventSink *iface,ITfDocumentMgr *pdim) 1097 { 1098 ThreadMgr *This = impl_from_ITfThreadMgrEventSink(iface); 1099 ITfThreadMgrEventSink *sink; 1100 struct list *cursor; 1101 1102 TRACE("(%p) %p\n",This,pdim); 1103 1104 SINK_FOR_EACH(cursor, &This->ThreadMgrEventSink, ITfThreadMgrEventSink, sink) 1105 { 1106 ITfThreadMgrEventSink_OnInitDocumentMgr(sink, pdim); 1107 } 1108 1109 return S_OK; 1110 } 1111 1112 static HRESULT WINAPI ThreadMgrEventSink_OnUninitDocumentMgr( 1113 ITfThreadMgrEventSink *iface, ITfDocumentMgr *pdim) 1114 { 1115 ThreadMgr *This = impl_from_ITfThreadMgrEventSink(iface); 1116 ITfThreadMgrEventSink *sink; 1117 struct list *cursor; 1118 1119 TRACE("(%p) %p\n",This,pdim); 1120 1121 SINK_FOR_EACH(cursor, &This->ThreadMgrEventSink, ITfThreadMgrEventSink, sink) 1122 { 1123 ITfThreadMgrEventSink_OnUninitDocumentMgr(sink, pdim); 1124 } 1125 1126 return S_OK; 1127 } 1128 1129 static HRESULT WINAPI ThreadMgrEventSink_OnSetFocus( 1130 ITfThreadMgrEventSink *iface, ITfDocumentMgr *pdimFocus, 1131 ITfDocumentMgr *pdimPrevFocus) 1132 { 1133 ThreadMgr *This = impl_from_ITfThreadMgrEventSink(iface); 1134 ITfThreadMgrEventSink *sink; 1135 struct list *cursor; 1136 1137 TRACE("(%p) %p %p\n",This,pdimFocus, pdimPrevFocus); 1138 1139 SINK_FOR_EACH(cursor, &This->ThreadMgrEventSink, ITfThreadMgrEventSink, sink) 1140 { 1141 ITfThreadMgrEventSink_OnSetFocus(sink, pdimFocus, pdimPrevFocus); 1142 } 1143 1144 return S_OK; 1145 } 1146 1147 static HRESULT WINAPI ThreadMgrEventSink_OnPushContext( 1148 ITfThreadMgrEventSink *iface, ITfContext *pic) 1149 { 1150 ThreadMgr *This = impl_from_ITfThreadMgrEventSink(iface); 1151 ITfThreadMgrEventSink *sink; 1152 struct list *cursor; 1153 1154 TRACE("(%p) %p\n",This,pic); 1155 1156 SINK_FOR_EACH(cursor, &This->ThreadMgrEventSink, ITfThreadMgrEventSink, sink) 1157 { 1158 ITfThreadMgrEventSink_OnPushContext(sink, pic); 1159 } 1160 1161 return S_OK; 1162 } 1163 1164 static HRESULT WINAPI ThreadMgrEventSink_OnPopContext( 1165 ITfThreadMgrEventSink *iface, ITfContext *pic) 1166 { 1167 ThreadMgr *This = impl_from_ITfThreadMgrEventSink(iface); 1168 ITfThreadMgrEventSink *sink; 1169 struct list *cursor; 1170 1171 TRACE("(%p) %p\n",This,pic); 1172 1173 SINK_FOR_EACH(cursor, &This->ThreadMgrEventSink, ITfThreadMgrEventSink, sink) 1174 { 1175 ITfThreadMgrEventSink_OnPopContext(sink, pic); 1176 } 1177 1178 return S_OK; 1179 } 1180 1181 static const ITfThreadMgrEventSinkVtbl ThreadMgrEventSinkVtbl = 1182 { 1183 ThreadMgrEventSink_QueryInterface, 1184 ThreadMgrEventSink_AddRef, 1185 ThreadMgrEventSink_Release, 1186 ThreadMgrEventSink_OnInitDocumentMgr, 1187 ThreadMgrEventSink_OnUninitDocumentMgr, 1188 ThreadMgrEventSink_OnSetFocus, 1189 ThreadMgrEventSink_OnPushContext, 1190 ThreadMgrEventSink_OnPopContext 1191 }; 1192 1193 /***************************************************** 1194 * ITfUIElementMgr functions 1195 *****************************************************/ 1196 static HRESULT WINAPI UIElementMgr_QueryInterface(ITfUIElementMgr *iface, REFIID iid, void **ppvOut) 1197 { 1198 ThreadMgr *This = impl_from_ITfUIElementMgr(iface); 1199 1200 return ITfThreadMgrEx_QueryInterface(&This->ITfThreadMgrEx_iface, iid, ppvOut); 1201 } 1202 1203 static ULONG WINAPI UIElementMgr_AddRef(ITfUIElementMgr *iface) 1204 { 1205 ThreadMgr *This = impl_from_ITfUIElementMgr(iface); 1206 1207 return ITfThreadMgrEx_AddRef(&This->ITfThreadMgrEx_iface); 1208 } 1209 1210 static ULONG WINAPI UIElementMgr_Release(ITfUIElementMgr *iface) 1211 { 1212 ThreadMgr *This = impl_from_ITfUIElementMgr(iface); 1213 1214 return ITfThreadMgrEx_Release(&This->ITfThreadMgrEx_iface); 1215 } 1216 1217 static HRESULT WINAPI UIElementMgr_BeginUIElement(ITfUIElementMgr *iface, ITfUIElement *element, 1218 BOOL *show, DWORD *id) 1219 { 1220 ThreadMgr *This = impl_from_ITfUIElementMgr(iface); 1221 1222 FIXME("STUB:(%p)\n", This); 1223 return E_NOTIMPL; 1224 } 1225 1226 static HRESULT WINAPI UIElementMgr_UpdateUIElement(ITfUIElementMgr *iface, DWORD id) 1227 { 1228 ThreadMgr *This = impl_from_ITfUIElementMgr(iface); 1229 1230 FIXME("STUB:(%p)\n", This); 1231 return E_NOTIMPL; 1232 } 1233 1234 static HRESULT WINAPI UIElementMgr_EndUIElement(ITfUIElementMgr *iface, DWORD id) 1235 { 1236 ThreadMgr *This = impl_from_ITfUIElementMgr(iface); 1237 1238 FIXME("STUB:(%p)\n", This); 1239 return E_NOTIMPL; 1240 } 1241 1242 static HRESULT WINAPI UIElementMgr_GetUIElement(ITfUIElementMgr *iface, DWORD id, 1243 ITfUIElement **element) 1244 { 1245 ThreadMgr *This = impl_from_ITfUIElementMgr(iface); 1246 1247 FIXME("STUB:(%p)\n", This); 1248 return E_NOTIMPL; 1249 } 1250 1251 static HRESULT WINAPI UIElementMgr_EnumUIElements(ITfUIElementMgr *iface, 1252 IEnumTfUIElements **enum_elements) 1253 { 1254 ThreadMgr *This = impl_from_ITfUIElementMgr(iface); 1255 1256 FIXME("STUB:(%p)\n", This); 1257 return E_NOTIMPL; 1258 } 1259 1260 static const ITfUIElementMgrVtbl ThreadMgrUIElementMgrVtbl = 1261 { 1262 UIElementMgr_QueryInterface, 1263 UIElementMgr_AddRef, 1264 UIElementMgr_Release, 1265 1266 UIElementMgr_BeginUIElement, 1267 UIElementMgr_UpdateUIElement, 1268 UIElementMgr_EndUIElement, 1269 UIElementMgr_GetUIElement, 1270 UIElementMgr_EnumUIElements 1271 }; 1272 1273 /***************************************************** 1274 * ITfSourceSingle functions 1275 *****************************************************/ 1276 static HRESULT WINAPI ThreadMgrSourceSingle_QueryInterface(ITfSourceSingle *iface, REFIID iid, LPVOID *ppvOut) 1277 { 1278 ThreadMgr *This = impl_from_ITfSourceSingle(iface); 1279 return ITfThreadMgrEx_QueryInterface(&This->ITfThreadMgrEx_iface, iid, ppvOut); 1280 } 1281 1282 static ULONG WINAPI ThreadMgrSourceSingle_AddRef(ITfSourceSingle *iface) 1283 { 1284 ThreadMgr *This = impl_from_ITfSourceSingle(iface); 1285 return ITfThreadMgrEx_AddRef(&This->ITfThreadMgrEx_iface); 1286 } 1287 1288 static ULONG WINAPI ThreadMgrSourceSingle_Release(ITfSourceSingle *iface) 1289 { 1290 ThreadMgr *This = impl_from_ITfSourceSingle(iface); 1291 return ITfThreadMgrEx_Release(&This->ITfThreadMgrEx_iface); 1292 } 1293 1294 static HRESULT WINAPI ThreadMgrSourceSingle_AdviseSingleSink( ITfSourceSingle *iface, 1295 TfClientId tid, REFIID riid, IUnknown *punk) 1296 { 1297 ThreadMgr *This = impl_from_ITfSourceSingle(iface); 1298 FIXME("STUB:(%p) %i %s %p\n",This, tid, debugstr_guid(riid),punk); 1299 return E_NOTIMPL; 1300 } 1301 1302 static HRESULT WINAPI ThreadMgrSourceSingle_UnadviseSingleSink( ITfSourceSingle *iface, 1303 TfClientId tid, REFIID riid) 1304 { 1305 ThreadMgr *This = impl_from_ITfSourceSingle(iface); 1306 FIXME("STUB:(%p) %i %s\n",This, tid, debugstr_guid(riid)); 1307 return E_NOTIMPL; 1308 } 1309 1310 static const ITfSourceSingleVtbl SourceSingleVtbl = 1311 { 1312 ThreadMgrSourceSingle_QueryInterface, 1313 ThreadMgrSourceSingle_AddRef, 1314 ThreadMgrSourceSingle_Release, 1315 ThreadMgrSourceSingle_AdviseSingleSink, 1316 ThreadMgrSourceSingle_UnadviseSingleSink 1317 }; 1318 1319 HRESULT ThreadMgr_Constructor(IUnknown *pUnkOuter, IUnknown **ppOut) 1320 { 1321 ThreadMgr *This; 1322 if (pUnkOuter) 1323 return CLASS_E_NOAGGREGATION; 1324 1325 /* Only 1 ThreadMgr is created per thread */ 1326 This = TlsGetValue(tlsIndex); 1327 if (This) 1328 { 1329 ThreadMgr_AddRef(&This->ITfThreadMgrEx_iface); 1330 *ppOut = (IUnknown*)&This->ITfThreadMgrEx_iface; 1331 return S_OK; 1332 } 1333 1334 This = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(ThreadMgr)); 1335 if (This == NULL) 1336 return E_OUTOFMEMORY; 1337 1338 This->ITfThreadMgrEx_iface.lpVtbl = &ThreadMgrExVtbl; 1339 This->ITfSource_iface.lpVtbl = &ThreadMgrSourceVtbl; 1340 This->ITfKeystrokeMgr_iface.lpVtbl = &KeystrokeMgrVtbl; 1341 This->ITfMessagePump_iface.lpVtbl = &MessagePumpVtbl; 1342 This->ITfClientId_iface.lpVtbl = &ClientIdVtbl; 1343 This->ITfThreadMgrEventSink_iface.lpVtbl = &ThreadMgrEventSinkVtbl; 1344 This->ITfUIElementMgr_iface.lpVtbl = &ThreadMgrUIElementMgrVtbl; 1345 This->ITfSourceSingle_iface.lpVtbl = &SourceSingleVtbl; 1346 This->refCount = 1; 1347 TlsSetValue(tlsIndex,This); 1348 1349 CompartmentMgr_Constructor((IUnknown*)&This->ITfThreadMgrEx_iface, &IID_IUnknown, (IUnknown**)&This->CompartmentMgr); 1350 1351 list_init(&This->CurrentPreservedKeys); 1352 list_init(&This->CreatedDocumentMgrs); 1353 list_init(&This->AssociatedFocusWindows); 1354 1355 list_init(&This->ActiveLanguageProfileNotifySink); 1356 list_init(&This->DisplayAttributeNotifySink); 1357 list_init(&This->KeyTraceEventSink); 1358 list_init(&This->PreservedKeyNotifySink); 1359 list_init(&This->ThreadFocusSink); 1360 list_init(&This->ThreadMgrEventSink); 1361 1362 TRACE("returning %p\n", This); 1363 *ppOut = (IUnknown *)&This->ITfThreadMgrEx_iface; 1364 return S_OK; 1365 } 1366 1367 /************************************************** 1368 * IEnumTfDocumentMgrs implementation 1369 **************************************************/ 1370 static void EnumTfDocumentMgr_Destructor(EnumTfDocumentMgr *This) 1371 { 1372 TRACE("destroying %p\n", This); 1373 HeapFree(GetProcessHeap(),0,This); 1374 } 1375 1376 static HRESULT WINAPI EnumTfDocumentMgr_QueryInterface(IEnumTfDocumentMgrs *iface, REFIID iid, LPVOID *ppvOut) 1377 { 1378 EnumTfDocumentMgr *This = impl_from_IEnumTfDocumentMgrs(iface); 1379 *ppvOut = NULL; 1380 1381 if (IsEqualIID(iid, &IID_IUnknown) || IsEqualIID(iid, &IID_IEnumTfDocumentMgrs)) 1382 { 1383 *ppvOut = &This->IEnumTfDocumentMgrs_iface; 1384 } 1385 1386 if (*ppvOut) 1387 { 1388 IEnumTfDocumentMgrs_AddRef(iface); 1389 return S_OK; 1390 } 1391 1392 WARN("unsupported interface: %s\n", debugstr_guid(iid)); 1393 return E_NOINTERFACE; 1394 } 1395 1396 static ULONG WINAPI EnumTfDocumentMgr_AddRef(IEnumTfDocumentMgrs *iface) 1397 { 1398 EnumTfDocumentMgr *This = impl_from_IEnumTfDocumentMgrs(iface); 1399 return InterlockedIncrement(&This->refCount); 1400 } 1401 1402 static ULONG WINAPI EnumTfDocumentMgr_Release(IEnumTfDocumentMgrs *iface) 1403 { 1404 EnumTfDocumentMgr *This = impl_from_IEnumTfDocumentMgrs(iface); 1405 ULONG ret; 1406 1407 ret = InterlockedDecrement(&This->refCount); 1408 if (ret == 0) 1409 EnumTfDocumentMgr_Destructor(This); 1410 return ret; 1411 } 1412 1413 static HRESULT WINAPI EnumTfDocumentMgr_Next(IEnumTfDocumentMgrs *iface, 1414 ULONG ulCount, ITfDocumentMgr **rgDocumentMgr, ULONG *pcFetched) 1415 { 1416 EnumTfDocumentMgr *This = impl_from_IEnumTfDocumentMgrs(iface); 1417 ULONG fetched = 0; 1418 1419 TRACE("(%p)\n",This); 1420 1421 if (rgDocumentMgr == NULL) return E_POINTER; 1422 1423 while (fetched < ulCount) 1424 { 1425 DocumentMgrEntry *mgrentry; 1426 if (This->index == NULL) 1427 break; 1428 1429 mgrentry = LIST_ENTRY(This->index,DocumentMgrEntry,entry); 1430 if (mgrentry == NULL) 1431 break; 1432 1433 *rgDocumentMgr = mgrentry->docmgr; 1434 ITfDocumentMgr_AddRef(*rgDocumentMgr); 1435 1436 This->index = list_next(This->head, This->index); 1437 ++fetched; 1438 ++rgDocumentMgr; 1439 } 1440 1441 if (pcFetched) *pcFetched = fetched; 1442 return fetched == ulCount ? S_OK : S_FALSE; 1443 } 1444 1445 static HRESULT WINAPI EnumTfDocumentMgr_Skip( IEnumTfDocumentMgrs* iface, ULONG celt) 1446 { 1447 EnumTfDocumentMgr *This = impl_from_IEnumTfDocumentMgrs(iface); 1448 ULONG i; 1449 1450 TRACE("(%p)\n",This); 1451 for(i = 0; i < celt && This->index != NULL; i++) 1452 This->index = list_next(This->head, This->index); 1453 return S_OK; 1454 } 1455 1456 static HRESULT WINAPI EnumTfDocumentMgr_Reset( IEnumTfDocumentMgrs* iface) 1457 { 1458 EnumTfDocumentMgr *This = impl_from_IEnumTfDocumentMgrs(iface); 1459 TRACE("(%p)\n",This); 1460 This->index = list_head(This->head); 1461 return S_OK; 1462 } 1463 1464 static HRESULT WINAPI EnumTfDocumentMgr_Clone( IEnumTfDocumentMgrs *iface, 1465 IEnumTfDocumentMgrs **ppenum) 1466 { 1467 EnumTfDocumentMgr *This = impl_from_IEnumTfDocumentMgrs(iface); 1468 HRESULT res; 1469 1470 TRACE("(%p)\n",This); 1471 1472 if (ppenum == NULL) return E_POINTER; 1473 1474 res = EnumTfDocumentMgr_Constructor(This->head, ppenum); 1475 if (SUCCEEDED(res)) 1476 { 1477 EnumTfDocumentMgr *new_This = impl_from_IEnumTfDocumentMgrs(*ppenum); 1478 new_This->index = This->index; 1479 } 1480 return res; 1481 } 1482 1483 static const IEnumTfDocumentMgrsVtbl EnumTfDocumentMgrsVtbl = 1484 { 1485 EnumTfDocumentMgr_QueryInterface, 1486 EnumTfDocumentMgr_AddRef, 1487 EnumTfDocumentMgr_Release, 1488 EnumTfDocumentMgr_Clone, 1489 EnumTfDocumentMgr_Next, 1490 EnumTfDocumentMgr_Reset, 1491 EnumTfDocumentMgr_Skip 1492 }; 1493 1494 static HRESULT EnumTfDocumentMgr_Constructor(struct list* head, IEnumTfDocumentMgrs **ppOut) 1495 { 1496 EnumTfDocumentMgr *This; 1497 1498 This = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(EnumTfDocumentMgr)); 1499 if (This == NULL) 1500 return E_OUTOFMEMORY; 1501 1502 This->IEnumTfDocumentMgrs_iface.lpVtbl= &EnumTfDocumentMgrsVtbl; 1503 This->refCount = 1; 1504 This->head = head; 1505 This->index = list_head(This->head); 1506 1507 TRACE("returning %p\n", &This->IEnumTfDocumentMgrs_iface); 1508 *ppOut = &This->IEnumTfDocumentMgrs_iface; 1509 return S_OK; 1510 } 1511 1512 void ThreadMgr_OnDocumentMgrDestruction(ITfThreadMgr *iface, ITfDocumentMgr *mgr) 1513 { 1514 ThreadMgr *This = impl_from_ITfThreadMgrEx((ITfThreadMgrEx *)iface); 1515 struct list *cursor; 1516 LIST_FOR_EACH(cursor, &This->CreatedDocumentMgrs) 1517 { 1518 DocumentMgrEntry *mgrentry = LIST_ENTRY(cursor,DocumentMgrEntry,entry); 1519 if (mgrentry->docmgr == mgr) 1520 { 1521 list_remove(cursor); 1522 HeapFree(GetProcessHeap(),0,mgrentry); 1523 return; 1524 } 1525 } 1526 FIXME("ITfDocumentMgr %p not found in this thread\n",mgr); 1527 } 1528