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