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