1 /* 2 * Unit tests for ITfInputProcessor 3 * 4 * Copyright 2009 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 <stdio.h> 22 23 #define COBJMACROS 24 #define CONST_VTABLE 25 #include "wine/test.h" 26 #include "winuser.h" 27 #include "initguid.h" 28 #include "shlwapi.h" 29 #include "shlguid.h" 30 #include "comcat.h" 31 #include "msctf.h" 32 #include "olectl.h" 33 34 static ITfInputProcessorProfiles* g_ipp; 35 static LANGID gLangid; 36 static ITfCategoryMgr * g_cm = NULL; 37 static ITfThreadMgr* g_tm = NULL; 38 static ITfDocumentMgr *g_dm = NULL; 39 static TfClientId cid = 0; 40 static TfClientId tid = 0; 41 42 static ITextStoreACPSink *ACPSink; 43 44 #define SINK_UNEXPECTED 0 45 #define SINK_EXPECTED 1 46 #define SINK_FIRED 2 47 #define SINK_IGNORE 3 48 #define SINK_OPTIONAL 4 49 #define SINK_SAVE 5 50 51 #define SINK_ACTION_MASK 0xff 52 #define SINK_OPTION_MASK 0xff00 53 #define SINK_EXPECTED_COUNT_MASK 0xff0000 54 55 #define SINK_OPTION_TODO 0x0100 56 57 #define FOCUS_IGNORE (ITfDocumentMgr*)0xffffffff 58 #define FOCUS_SAVE (ITfDocumentMgr*)0xfffffffe 59 60 static BOOL test_ShouldActivate = FALSE; 61 static BOOL test_ShouldDeactivate = FALSE; 62 63 static DWORD tmSinkCookie; 64 static DWORD tmSinkRefCount; 65 static DWORD dmSinkCookie; 66 static DWORD documentStatus; 67 static DWORD key_trace_sink_cookie, ui_element_sink_cookie, profile_activation_sink_cookie; 68 static DWORD fake_service_onactivated_flags = 0; 69 static ITfDocumentMgr *test_CurrentFocus = NULL; 70 static ITfDocumentMgr *test_PrevFocus = NULL; 71 static ITfDocumentMgr *test_LastCurrentFocus = FOCUS_SAVE; 72 static ITfDocumentMgr *test_FirstPrevFocus = FOCUS_SAVE; 73 static INT test_OnSetFocus = SINK_UNEXPECTED; 74 static INT test_OnInitDocumentMgr = SINK_UNEXPECTED; 75 static INT test_OnPushContext = SINK_UNEXPECTED; 76 static INT test_OnPopContext = SINK_UNEXPECTED; 77 static INT test_KEV_OnSetFocus = SINK_UNEXPECTED; 78 static INT test_ACP_AdviseSink = SINK_UNEXPECTED; 79 static INT test_ACP_UnadviseSink = SINK_UNEXPECTED; 80 static INT test_ACP_GetStatus = SINK_UNEXPECTED; 81 static INT test_ACP_RequestLock = SINK_UNEXPECTED; 82 static INT test_ACP_GetEndACP = SINK_UNEXPECTED; 83 static INT test_ACP_GetSelection = SINK_UNEXPECTED; 84 static INT test_DoEditSession = SINK_UNEXPECTED; 85 static INT test_ACP_InsertTextAtSelection = SINK_UNEXPECTED; 86 static INT test_ACP_SetSelection = SINK_UNEXPECTED; 87 static INT test_OnEndEdit = SINK_UNEXPECTED; 88 89 DEFINE_GUID(CLSID_FakeService, 0xEDE1A7AD,0x66DE,0x47E0,0xB6,0x20,0x3E,0x92,0xF8,0x24,0x6B,0xF3); 90 91 static inline int expected_count(int *sink) 92 { 93 return (*sink & SINK_EXPECTED_COUNT_MASK)>>16; 94 } 95 96 static inline void _sink_fire_ok(INT *sink, const CHAR* name) 97 { 98 int count; 99 int todo = *sink & SINK_OPTION_TODO; 100 int action = *sink & SINK_ACTION_MASK; 101 102 if (winetest_interactive) 103 winetest_trace("firing %s\n",name); 104 105 switch (action) 106 { 107 case SINK_OPTIONAL: 108 case SINK_EXPECTED: 109 count = expected_count(sink); 110 if (count > 1) 111 { 112 count --; 113 *sink = (*sink & ~SINK_EXPECTED_COUNT_MASK) + (count << 16); 114 return; 115 } 116 break; 117 case SINK_IGNORE: 118 winetest_trace("Ignoring %s\n",name); 119 return; 120 case SINK_SAVE: 121 count = expected_count(sink) + 1; 122 *sink = (*sink & ~SINK_EXPECTED_COUNT_MASK) + (count << 16); 123 return; 124 default: 125 todo_wine_if (todo) 126 winetest_ok(0, "Unexpected %s sink\n",name); 127 } 128 *sink = SINK_FIRED; 129 } 130 131 #define sink_fire_ok(a,b) (winetest_set_location(__FILE__,__LINE__), 0) ? 0 : _sink_fire_ok(a,b) 132 133 static inline void _sink_check_ok(INT *sink, const CHAR* name) 134 { 135 int action = *sink & SINK_ACTION_MASK; 136 int todo = *sink & SINK_OPTION_TODO; 137 int count = expected_count(sink); 138 139 switch (action) 140 { 141 case SINK_OPTIONAL: 142 if (winetest_interactive) 143 winetest_trace("optional sink %s not fired\n",name); 144 case SINK_FIRED: 145 break; 146 case SINK_IGNORE: 147 return; 148 case SINK_SAVE: 149 if (count == 0 && winetest_interactive) 150 winetest_trace("optional sink %s not fired\n",name); 151 break; 152 default: 153 todo_wine_if (todo) 154 winetest_ok(0, "%s not fired as expected, in state %x\n",name,*sink); 155 } 156 *sink = SINK_UNEXPECTED; 157 } 158 159 #define sink_check_ok(a,b) (winetest_set_location(__FILE__,__LINE__), 0) ? 0 : _sink_check_ok(a,b) 160 161 static inline void _sink_check_saved(INT *sink, ITfDocumentMgr *PrevFocus, ITfDocumentMgr *CurrentFocus, const CHAR* name) 162 { 163 int count = expected_count(sink); 164 _sink_check_ok(sink, name); 165 if (PrevFocus != FOCUS_IGNORE && count != 0) 166 winetest_ok(PrevFocus == test_FirstPrevFocus, "%s expected prev focus %p got %p\n", name, PrevFocus, test_FirstPrevFocus); 167 if (CurrentFocus != FOCUS_IGNORE && count != 0) 168 winetest_ok(CurrentFocus == test_LastCurrentFocus, "%s expected current focus %p got %p\n", name, CurrentFocus, test_LastCurrentFocus); 169 test_FirstPrevFocus = FOCUS_SAVE; 170 test_LastCurrentFocus = FOCUS_SAVE; 171 } 172 173 #define sink_check_saved(s,p,c,n) (winetest_set_location(__FILE__,__LINE__), 0) ? 0 : _sink_check_saved(s,p,c,n) 174 175 /********************************************************************** 176 * ITextStoreACP 177 **********************************************************************/ 178 typedef struct tagTextStoreACP 179 { 180 ITextStoreACP ITextStoreACP_iface; 181 LONG refCount; 182 183 } TextStoreACP; 184 185 static inline TextStoreACP *impl_from_ITextStoreACP(ITextStoreACP *iface) 186 { 187 return CONTAINING_RECORD(iface, TextStoreACP, ITextStoreACP_iface); 188 } 189 190 static void TextStoreACP_Destructor(TextStoreACP *This) 191 { 192 HeapFree(GetProcessHeap(),0,This); 193 } 194 195 static HRESULT WINAPI TextStoreACP_QueryInterface(ITextStoreACP *iface, REFIID iid, LPVOID *ppvOut) 196 { 197 *ppvOut = NULL; 198 199 if (IsEqualIID(iid, &IID_IUnknown) || IsEqualIID(iid, &IID_ITextStoreACP)) 200 { 201 *ppvOut = iface; 202 } 203 204 if (*ppvOut) 205 { 206 ITextStoreACP_AddRef(iface); 207 return S_OK; 208 } 209 210 return E_NOINTERFACE; 211 } 212 213 static ULONG WINAPI TextStoreACP_AddRef(ITextStoreACP *iface) 214 { 215 TextStoreACP *This = impl_from_ITextStoreACP(iface); 216 return InterlockedIncrement(&This->refCount); 217 } 218 219 static ULONG WINAPI TextStoreACP_Release(ITextStoreACP *iface) 220 { 221 TextStoreACP *This = impl_from_ITextStoreACP(iface); 222 ULONG ret; 223 224 ret = InterlockedDecrement(&This->refCount); 225 if (ret == 0) 226 TextStoreACP_Destructor(This); 227 return ret; 228 } 229 230 static HRESULT WINAPI TextStoreACP_AdviseSink(ITextStoreACP *iface, 231 REFIID riid, IUnknown *punk, DWORD dwMask) 232 { 233 ITextStoreACPServices *services; 234 HRESULT hr; 235 236 sink_fire_ok(&test_ACP_AdviseSink,"TextStoreACP_AdviseSink"); 237 238 if(ACPSink) 239 return S_OK; 240 241 hr = IUnknown_QueryInterface(punk, &IID_ITextStoreACPSink, (void**)&ACPSink); 242 ok(SUCCEEDED(hr),"Unable to QueryInterface on sink\n"); 243 244 hr = ITextStoreACPSink_QueryInterface(ACPSink, &IID_ITextStoreACPServices, (void**)&services); 245 ok(hr == S_OK, "got 0x%08x\n", hr); 246 ITextStoreACPServices_Release(services); 247 248 return S_OK; 249 } 250 251 static HRESULT WINAPI TextStoreACP_UnadviseSink(ITextStoreACP *iface, 252 IUnknown *punk) 253 { 254 sink_fire_ok(&test_ACP_UnadviseSink,"TextStoreACP_UnadviseSink"); 255 return S_OK; 256 } 257 258 static HRESULT WINAPI TextStoreACP_RequestLock(ITextStoreACP *iface, 259 DWORD dwLockFlags, HRESULT *phrSession) 260 { 261 sink_fire_ok(&test_ACP_RequestLock,"TextStoreACP_RequestLock"); 262 *phrSession = ITextStoreACPSink_OnLockGranted(ACPSink, dwLockFlags); 263 return S_OK; 264 } 265 static HRESULT WINAPI TextStoreACP_GetStatus(ITextStoreACP *iface, 266 TS_STATUS *pdcs) 267 { 268 sink_fire_ok(&test_ACP_GetStatus,"TextStoreACP_GetStatus"); 269 pdcs->dwDynamicFlags = documentStatus; 270 return S_OK; 271 } 272 static HRESULT WINAPI TextStoreACP_QueryInsert(ITextStoreACP *iface, 273 LONG acpTestStart, LONG acpTestEnd, ULONG cch, LONG *pacpResultStart, 274 LONG *pacpResultEnd) 275 { 276 trace("\n"); 277 return S_OK; 278 } 279 static HRESULT WINAPI TextStoreACP_GetSelection(ITextStoreACP *iface, 280 ULONG ulIndex, ULONG ulCount, TS_SELECTION_ACP *pSelection, ULONG *pcFetched) 281 { 282 sink_fire_ok(&test_ACP_GetSelection,"TextStoreACP_GetSelection"); 283 284 pSelection->acpStart = 10; 285 pSelection->acpEnd = 20; 286 pSelection->style.fInterimChar = 0; 287 pSelection->style.ase = TS_AE_NONE; 288 *pcFetched = 1; 289 290 return S_OK; 291 } 292 static HRESULT WINAPI TextStoreACP_SetSelection(ITextStoreACP *iface, 293 ULONG ulCount, const TS_SELECTION_ACP *pSelection) 294 { 295 sink_fire_ok(&test_ACP_SetSelection,"TextStoreACP_SetSelection"); 296 return S_OK; 297 } 298 static HRESULT WINAPI TextStoreACP_GetText(ITextStoreACP *iface, 299 LONG acpStart, LONG acpEnd, WCHAR *pchPlain, ULONG cchPlainReq, 300 ULONG *pcchPlainRet, TS_RUNINFO *prgRunInfo, ULONG cRunInfoReq, 301 ULONG *pcRunInfoRet, LONG *pacpNext) 302 { 303 trace("\n"); 304 return S_OK; 305 } 306 static HRESULT WINAPI TextStoreACP_SetText(ITextStoreACP *iface, 307 DWORD dwFlags, LONG acpStart, LONG acpEnd, const WCHAR *pchText, 308 ULONG cch, TS_TEXTCHANGE *pChange) 309 { 310 trace("\n"); 311 return S_OK; 312 } 313 static HRESULT WINAPI TextStoreACP_GetFormattedText(ITextStoreACP *iface, 314 LONG acpStart, LONG acpEnd, IDataObject **ppDataObject) 315 { 316 trace("\n"); 317 return S_OK; 318 } 319 static HRESULT WINAPI TextStoreACP_GetEmbedded(ITextStoreACP *iface, 320 LONG acpPos, REFGUID rguidService, REFIID riid, IUnknown **ppunk) 321 { 322 trace("\n"); 323 return S_OK; 324 } 325 static HRESULT WINAPI TextStoreACP_QueryInsertEmbedded(ITextStoreACP *iface, 326 const GUID *pguidService, const FORMATETC *pFormatEtc, BOOL *pfInsertable) 327 { 328 trace("\n"); 329 return S_OK; 330 } 331 static HRESULT WINAPI TextStoreACP_InsertEmbedded(ITextStoreACP *iface, 332 DWORD dwFlags, LONG acpStart, LONG acpEnd, IDataObject *pDataObject, 333 TS_TEXTCHANGE *pChange) 334 { 335 trace("\n"); 336 return S_OK; 337 } 338 static HRESULT WINAPI TextStoreACP_InsertTextAtSelection(ITextStoreACP *iface, 339 DWORD dwFlags, const WCHAR *pchText, ULONG cch, LONG *pacpStart, 340 LONG *pacpEnd, TS_TEXTCHANGE *pChange) 341 { 342 sink_fire_ok(&test_ACP_InsertTextAtSelection,"TextStoreACP_InsertTextAtSelection"); 343 return S_OK; 344 } 345 static HRESULT WINAPI TextStoreACP_InsertEmbeddedAtSelection(ITextStoreACP *iface, 346 DWORD dwFlags, IDataObject *pDataObject, LONG *pacpStart, LONG *pacpEnd, 347 TS_TEXTCHANGE *pChange) 348 { 349 trace("\n"); 350 return S_OK; 351 } 352 static HRESULT WINAPI TextStoreACP_RequestSupportedAttrs(ITextStoreACP *iface, 353 DWORD dwFlags, ULONG cFilterAttrs, const TS_ATTRID *paFilterAttrs) 354 { 355 trace("\n"); 356 return S_OK; 357 } 358 static HRESULT WINAPI TextStoreACP_RequestAttrsAtPosition(ITextStoreACP *iface, 359 LONG acpPos, ULONG cFilterAttrs, const TS_ATTRID *paFilterAttrs, 360 DWORD dwFlags) 361 { 362 trace("\n"); 363 return S_OK; 364 } 365 static HRESULT WINAPI TextStoreACP_RequestAttrsTransitioningAtPosition(ITextStoreACP *iface, 366 LONG acpPos, ULONG cFilterAttrs, const TS_ATTRID *paFilterAttrs, 367 DWORD dwFlags) 368 { 369 trace("\n"); 370 return S_OK; 371 } 372 static HRESULT WINAPI TextStoreACP_FindNextAttrTransition(ITextStoreACP *iface, 373 LONG acpStart, LONG acpHalt, ULONG cFilterAttrs, const TS_ATTRID *paFilterAttrs, 374 DWORD dwFlags, LONG *pacpNext, BOOL *pfFound, LONG *plFoundOffset) 375 { 376 trace("\n"); 377 return S_OK; 378 } 379 static HRESULT WINAPI TextStoreACP_RetrieveRequestedAttrs(ITextStoreACP *iface, 380 ULONG ulCount, TS_ATTRVAL *paAttrVals, ULONG *pcFetched) 381 { 382 trace("\n"); 383 return S_OK; 384 } 385 static HRESULT WINAPI TextStoreACP_GetEndACP(ITextStoreACP *iface, 386 LONG *pacp) 387 { 388 sink_fire_ok(&test_ACP_GetEndACP,"TextStoreACP_GetEndACP"); 389 return S_OK; 390 } 391 static HRESULT WINAPI TextStoreACP_GetActiveView(ITextStoreACP *iface, 392 TsViewCookie *pvcView) 393 { 394 trace("\n"); 395 return S_OK; 396 } 397 static HRESULT WINAPI TextStoreACP_GetACPFromPoint(ITextStoreACP *iface, 398 TsViewCookie vcView, const POINT *ptScreen, DWORD dwFlags, 399 LONG *pacp) 400 { 401 trace("\n"); 402 return S_OK; 403 } 404 static HRESULT WINAPI TextStoreACP_GetTextExt(ITextStoreACP *iface, 405 TsViewCookie vcView, LONG acpStart, LONG acpEnd, RECT *prc, 406 BOOL *pfClipped) 407 { 408 trace("\n"); 409 return S_OK; 410 } 411 static HRESULT WINAPI TextStoreACP_GetScreenExt(ITextStoreACP *iface, 412 TsViewCookie vcView, RECT *prc) 413 { 414 trace("\n"); 415 return S_OK; 416 } 417 static HRESULT WINAPI TextStoreACP_GetWnd(ITextStoreACP *iface, 418 TsViewCookie vcView, HWND *phwnd) 419 { 420 trace("\n"); 421 return S_OK; 422 } 423 424 static const ITextStoreACPVtbl TextStoreACP_TextStoreACPVtbl = 425 { 426 TextStoreACP_QueryInterface, 427 TextStoreACP_AddRef, 428 TextStoreACP_Release, 429 430 TextStoreACP_AdviseSink, 431 TextStoreACP_UnadviseSink, 432 TextStoreACP_RequestLock, 433 TextStoreACP_GetStatus, 434 TextStoreACP_QueryInsert, 435 TextStoreACP_GetSelection, 436 TextStoreACP_SetSelection, 437 TextStoreACP_GetText, 438 TextStoreACP_SetText, 439 TextStoreACP_GetFormattedText, 440 TextStoreACP_GetEmbedded, 441 TextStoreACP_QueryInsertEmbedded, 442 TextStoreACP_InsertEmbedded, 443 TextStoreACP_InsertTextAtSelection, 444 TextStoreACP_InsertEmbeddedAtSelection, 445 TextStoreACP_RequestSupportedAttrs, 446 TextStoreACP_RequestAttrsAtPosition, 447 TextStoreACP_RequestAttrsTransitioningAtPosition, 448 TextStoreACP_FindNextAttrTransition, 449 TextStoreACP_RetrieveRequestedAttrs, 450 TextStoreACP_GetEndACP, 451 TextStoreACP_GetActiveView, 452 TextStoreACP_GetACPFromPoint, 453 TextStoreACP_GetTextExt, 454 TextStoreACP_GetScreenExt, 455 TextStoreACP_GetWnd 456 }; 457 458 static HRESULT TextStoreACP_Constructor(IUnknown **ppOut) 459 { 460 TextStoreACP *This; 461 462 This = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(TextStoreACP)); 463 if (This == NULL) 464 return E_OUTOFMEMORY; 465 466 This->ITextStoreACP_iface.lpVtbl = &TextStoreACP_TextStoreACPVtbl; 467 This->refCount = 1; 468 469 *ppOut = (IUnknown*)&This->ITextStoreACP_iface; 470 return S_OK; 471 } 472 473 /********************************************************************** 474 * ITfThreadMgrEventSink 475 **********************************************************************/ 476 typedef struct tagThreadMgrEventSink 477 { 478 ITfThreadMgrEventSink ITfThreadMgrEventSink_iface; 479 LONG refCount; 480 } ThreadMgrEventSink; 481 482 static inline ThreadMgrEventSink *impl_from_ITfThreadMgrEventSink(ITfThreadMgrEventSink *iface) 483 { 484 return CONTAINING_RECORD(iface, ThreadMgrEventSink, ITfThreadMgrEventSink_iface); 485 } 486 487 static void ThreadMgrEventSink_Destructor(ThreadMgrEventSink *This) 488 { 489 HeapFree(GetProcessHeap(),0,This); 490 } 491 492 static HRESULT WINAPI ThreadMgrEventSink_QueryInterface(ITfThreadMgrEventSink *iface, REFIID iid, LPVOID *ppvOut) 493 { 494 *ppvOut = NULL; 495 496 if (IsEqualIID(iid, &IID_IUnknown) || IsEqualIID(iid, &IID_ITfThreadMgrEventSink)) 497 { 498 *ppvOut = iface; 499 } 500 501 if (*ppvOut) 502 { 503 ITfThreadMgrEventSink_AddRef(iface); 504 return S_OK; 505 } 506 507 return E_NOINTERFACE; 508 } 509 510 static ULONG WINAPI ThreadMgrEventSink_AddRef(ITfThreadMgrEventSink *iface) 511 { 512 ThreadMgrEventSink *This = impl_from_ITfThreadMgrEventSink(iface); 513 ok (tmSinkRefCount == This->refCount,"ThreadMgrEventSink refcount off %i vs %i\n",This->refCount,tmSinkRefCount); 514 return InterlockedIncrement(&This->refCount); 515 } 516 517 static ULONG WINAPI ThreadMgrEventSink_Release(ITfThreadMgrEventSink *iface) 518 { 519 ThreadMgrEventSink *This = impl_from_ITfThreadMgrEventSink(iface); 520 ULONG ret; 521 522 ok (tmSinkRefCount == This->refCount,"ThreadMgrEventSink refcount off %i vs %i\n",This->refCount,tmSinkRefCount); 523 ret = InterlockedDecrement(&This->refCount); 524 if (ret == 0) 525 ThreadMgrEventSink_Destructor(This); 526 return ret; 527 } 528 529 static HRESULT WINAPI ThreadMgrEventSink_OnInitDocumentMgr(ITfThreadMgrEventSink *iface, 530 ITfDocumentMgr *pdim) 531 { 532 sink_fire_ok(&test_OnInitDocumentMgr,"ThreadMgrEventSink_OnInitDocumentMgr"); 533 return S_OK; 534 } 535 536 static HRESULT WINAPI ThreadMgrEventSink_OnUninitDocumentMgr(ITfThreadMgrEventSink *iface, 537 ITfDocumentMgr *pdim) 538 { 539 trace("\n"); 540 return S_OK; 541 } 542 543 static HRESULT WINAPI ThreadMgrEventSink_OnSetFocus(ITfThreadMgrEventSink *iface, 544 ITfDocumentMgr *pdimFocus, ITfDocumentMgr *pdimPrevFocus) 545 { 546 sink_fire_ok(&test_OnSetFocus,"ThreadMgrEventSink_OnSetFocus"); 547 if (test_CurrentFocus == FOCUS_SAVE) 548 test_LastCurrentFocus = pdimFocus; 549 else if (test_CurrentFocus != FOCUS_IGNORE) 550 ok(pdimFocus == test_CurrentFocus,"Sink reports wrong focus\n"); 551 if (test_PrevFocus == FOCUS_SAVE) 552 { 553 if (test_FirstPrevFocus == FOCUS_SAVE) 554 test_FirstPrevFocus = pdimPrevFocus; 555 } 556 else if (test_PrevFocus != FOCUS_IGNORE) 557 ok(pdimPrevFocus == test_PrevFocus,"Sink reports wrong previous focus\n"); 558 return S_OK; 559 } 560 561 static HRESULT WINAPI ThreadMgrEventSink_OnPushContext(ITfThreadMgrEventSink *iface, 562 ITfContext *pic) 563 { 564 HRESULT hr; 565 ITfDocumentMgr *docmgr; 566 ITfContext *test; 567 568 hr = ITfContext_GetDocumentMgr(pic,&docmgr); 569 ok(SUCCEEDED(hr),"GetDocumentMgr failed\n"); 570 test = (ITfContext*)0xdeadbeef; 571 hr = ITfDocumentMgr_GetTop(docmgr,&test); 572 ok(SUCCEEDED(hr),"GetTop failed\n"); 573 ITfDocumentMgr_Release(docmgr); 574 ok(test == pic, "Wrong context is on top\n"); 575 if (test) 576 ITfContext_Release(test); 577 578 sink_fire_ok(&test_OnPushContext,"ThreadMgrEventSink_OnPushContext"); 579 return S_OK; 580 } 581 582 static HRESULT WINAPI ThreadMgrEventSink_OnPopContext(ITfThreadMgrEventSink *iface, 583 ITfContext *pic) 584 { 585 HRESULT hr; 586 ITfDocumentMgr *docmgr; 587 ITfContext *test; 588 589 hr = ITfContext_GetDocumentMgr(pic,&docmgr); 590 ok(SUCCEEDED(hr),"GetDocumentMgr failed\n"); 591 ITfDocumentMgr_Release(docmgr); 592 test = (ITfContext*)0xdeadbeef; 593 hr = ITfDocumentMgr_GetTop(docmgr,&test); 594 ok(SUCCEEDED(hr),"GetTop failed\n"); 595 ok(test == pic, "Wrong context is on top\n"); 596 if (test) 597 ITfContext_Release(test); 598 599 sink_fire_ok(&test_OnPopContext,"ThreadMgrEventSink_OnPopContext"); 600 return S_OK; 601 } 602 603 static const ITfThreadMgrEventSinkVtbl ThreadMgrEventSink_ThreadMgrEventSinkVtbl = 604 { 605 ThreadMgrEventSink_QueryInterface, 606 ThreadMgrEventSink_AddRef, 607 ThreadMgrEventSink_Release, 608 609 ThreadMgrEventSink_OnInitDocumentMgr, 610 ThreadMgrEventSink_OnUninitDocumentMgr, 611 ThreadMgrEventSink_OnSetFocus, 612 ThreadMgrEventSink_OnPushContext, 613 ThreadMgrEventSink_OnPopContext 614 }; 615 616 static HRESULT ThreadMgrEventSink_Constructor(IUnknown **ppOut) 617 { 618 ThreadMgrEventSink *This; 619 620 This = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(ThreadMgrEventSink)); 621 if (This == NULL) 622 return E_OUTOFMEMORY; 623 624 This->ITfThreadMgrEventSink_iface.lpVtbl = &ThreadMgrEventSink_ThreadMgrEventSinkVtbl; 625 This->refCount = 1; 626 627 *ppOut = (IUnknown*)&This->ITfThreadMgrEventSink_iface; 628 return S_OK; 629 } 630 631 static HRESULT WINAPI TfKeyTraceEventSink_QueryInterface(ITfKeyTraceEventSink *iface, REFIID riid, void **ppv) 632 { 633 if(IsEqualGUID(&IID_IUnknown, riid) || IsEqualGUID(&IID_ITfKeyTraceEventSink, riid)) { 634 *ppv = iface; 635 return S_OK; 636 } 637 638 *ppv = NULL; 639 return E_NOINTERFACE; 640 } 641 642 static ULONG WINAPI TfKeyTraceEventSink_AddRef(ITfKeyTraceEventSink *iface) 643 { 644 return 2; 645 } 646 647 static ULONG WINAPI TfKeyTraceEventSink_Release(ITfKeyTraceEventSink *iface) 648 { 649 return 1; 650 } 651 652 static HRESULT WINAPI TfKeyTraceEventSink_OnKeyTraceDown(ITfKeyTraceEventSink *iface, 653 WPARAM wparam, LPARAM lparam) 654 { 655 ok(0, "unexpected call\n"); 656 return E_NOTIMPL; 657 } 658 659 static HRESULT WINAPI TfKeyTraceEventSink_OnKeyTraceUp(ITfKeyTraceEventSink *iface, 660 WPARAM wparam, LPARAM lparam) 661 { 662 ok(0, "unexpected call\n"); 663 return E_NOTIMPL; 664 } 665 666 static const ITfKeyTraceEventSinkVtbl TfKeyTraceEventSinkVtbl = { 667 TfKeyTraceEventSink_QueryInterface, 668 TfKeyTraceEventSink_AddRef, 669 TfKeyTraceEventSink_Release, 670 TfKeyTraceEventSink_OnKeyTraceDown, 671 TfKeyTraceEventSink_OnKeyTraceUp 672 }; 673 674 static ITfKeyTraceEventSink TfKeyTraceEventSink = { &TfKeyTraceEventSinkVtbl }; 675 676 static HRESULT WINAPI TfUIElementSink_QueryInterface(ITfUIElementSink *iface, 677 REFIID riid, void **ppvObject) 678 { 679 if(IsEqualGUID(&IID_IUnknown, riid) || IsEqualGUID(&IID_ITfUIElementSink, riid)){ 680 *ppvObject = iface; 681 return S_OK; 682 } 683 684 *ppvObject = NULL; 685 return E_NOINTERFACE; 686 } 687 688 static ULONG WINAPI TfUIElementSink_AddRef(ITfUIElementSink *iface) 689 { 690 return 2; 691 } 692 693 static ULONG WINAPI TfUIElementSink_Release(ITfUIElementSink *iface) 694 { 695 return 1; 696 } 697 698 static HRESULT WINAPI TfUIElementSink_BeginUIElement(ITfUIElementSink *iface, 699 DWORD id, BOOL *show) 700 { 701 ok(0, "unexpected call\n"); 702 return E_NOTIMPL; 703 } 704 705 static HRESULT WINAPI TfUIElementSink_UpdateUIElement(ITfUIElementSink *iface, 706 DWORD id) 707 { 708 ok(0, "unexpected call\n"); 709 return E_NOTIMPL; 710 } 711 712 static HRESULT WINAPI TfUIElementSink_EndUIElement(ITfUIElementSink *iface, 713 DWORD id) 714 { 715 ok(0, "unexpected call\n"); 716 return E_NOTIMPL; 717 } 718 719 static const ITfUIElementSinkVtbl TfUIElementSinkVtbl = { 720 TfUIElementSink_QueryInterface, 721 TfUIElementSink_AddRef, 722 TfUIElementSink_Release, 723 TfUIElementSink_BeginUIElement, 724 TfUIElementSink_UpdateUIElement, 725 TfUIElementSink_EndUIElement 726 }; 727 728 static ITfUIElementSink TfUIElementSink = { &TfUIElementSinkVtbl }; 729 730 static HRESULT WINAPI ProfileActivationSink_QueryInterface(ITfInputProcessorProfileActivationSink *iface, 731 REFIID riid, void **ppvObject) 732 { 733 if(IsEqualGUID(&IID_IUnknown, riid) || IsEqualGUID(&IID_ITfInputProcessorProfileActivationSink, riid)){ 734 *ppvObject = iface; 735 return S_OK; 736 } 737 738 *ppvObject = NULL; 739 return E_NOINTERFACE; 740 } 741 742 static ULONG WINAPI ProfileActivationSink_AddRef(ITfInputProcessorProfileActivationSink *iface) 743 { 744 return 2; 745 } 746 747 static ULONG WINAPI ProfileActivationSink_Release(ITfInputProcessorProfileActivationSink *iface) 748 { 749 return 1; 750 } 751 752 static HRESULT WINAPI ProfileActivationSink_OnActivated(ITfInputProcessorProfileActivationSink *iface, 753 DWORD dwProfileType, LANGID langid, REFCLSID clsid, REFGUID catid, 754 REFGUID guidProfile, HKL hkl, DWORD dwFlags) 755 { 756 trace("Got OnActivated: {dwProfileType %08x, langid %08x, clsid %s, catid %s, guidProfile %s, %p, dwFlags %08x}\n", 757 dwProfileType, langid, wine_dbgstr_guid(clsid), 758 wine_dbgstr_guid(catid), wine_dbgstr_guid(guidProfile), hkl, dwFlags); 759 760 ok(dwProfileType == TF_PROFILETYPE_INPUTPROCESSOR || dwProfileType == TF_PROFILETYPE_KEYBOARDLAYOUT, 761 "unexpected dwProfileType: 0x%x\n", dwProfileType); 762 763 if(dwProfileType == TF_PROFILETYPE_INPUTPROCESSOR && IsEqualGUID(&CLSID_FakeService, clsid)){ 764 if(dwFlags & TF_IPSINK_FLAG_ACTIVE){ 765 ok(test_ShouldActivate, "OnActivated: Activation came unexpectedly\n"); 766 } 767 768 fake_service_onactivated_flags = dwFlags; 769 } 770 771 return S_OK; 772 } 773 774 static const ITfInputProcessorProfileActivationSinkVtbl TfInputProcessorProfileActivationSinkVtbl = { 775 ProfileActivationSink_QueryInterface, 776 ProfileActivationSink_AddRef, 777 ProfileActivationSink_Release, 778 ProfileActivationSink_OnActivated 779 }; 780 781 static ITfInputProcessorProfileActivationSink TfInputProcessorProfileActivationSink = { 782 &TfInputProcessorProfileActivationSinkVtbl 783 }; 784 785 static HRESULT WINAPI TfTransitoryExtensionSink_QueryInterface(ITfTransitoryExtensionSink *iface, REFIID riid, void **ppv) 786 { 787 if(IsEqualGUID(&IID_IUnknown, riid) || IsEqualGUID(&IID_ITfTransitoryExtensionSink, riid)) { 788 *ppv = iface; 789 return S_OK; 790 } 791 792 *ppv = NULL; 793 return E_NOINTERFACE; 794 } 795 796 static ULONG WINAPI TfTransitoryExtensionSink_AddRef(ITfTransitoryExtensionSink *iface) 797 { 798 return 2; 799 } 800 801 static ULONG WINAPI TfTransitoryExtensionSink_Release(ITfTransitoryExtensionSink *iface) 802 { 803 return 1; 804 } 805 806 static HRESULT WINAPI TfTransitoryExtensionSink_OnTransitoryExtensionUpdated(ITfTransitoryExtensionSink *iface, ITfContext *pic, 807 TfEditCookie ecReadOnly, ITfRange *pResultRange, ITfRange *pCompositionRange, BOOL *pfDeleteResultRange) 808 { 809 ok(0, "unexpected call\n"); 810 return E_NOTIMPL; 811 } 812 813 static const ITfTransitoryExtensionSinkVtbl TfTransitoryExtensionSinkVtbl = { 814 TfTransitoryExtensionSink_QueryInterface, 815 TfTransitoryExtensionSink_AddRef, 816 TfTransitoryExtensionSink_Release, 817 TfTransitoryExtensionSink_OnTransitoryExtensionUpdated 818 }; 819 820 static ITfTransitoryExtensionSink TfTransitoryExtensionSink = { &TfTransitoryExtensionSinkVtbl }; 821 822 /******************************************************************************************** 823 * Stub text service for testing 824 ********************************************************************************************/ 825 826 static LONG TS_refCount; 827 static IClassFactory *cf; 828 static DWORD regid; 829 830 typedef HRESULT (*LPFNCONSTRUCTOR)(IUnknown *pUnkOuter, IUnknown **ppvOut); 831 832 typedef struct tagClassFactory 833 { 834 IClassFactory IClassFactory_iface; 835 LONG ref; 836 LPFNCONSTRUCTOR ctor; 837 } ClassFactory; 838 839 static inline ClassFactory *impl_from_IClassFactory(IClassFactory *iface) 840 { 841 return CONTAINING_RECORD(iface, ClassFactory, IClassFactory_iface); 842 } 843 844 typedef struct tagTextService 845 { 846 ITfTextInputProcessor ITfTextInputProcessor_iface; 847 LONG refCount; 848 } TextService; 849 850 static inline TextService *impl_from_ITfTextInputProcessor(ITfTextInputProcessor *iface) 851 { 852 return CONTAINING_RECORD(iface, TextService, ITfTextInputProcessor_iface); 853 } 854 855 static void ClassFactory_Destructor(ClassFactory *This) 856 { 857 HeapFree(GetProcessHeap(),0,This); 858 TS_refCount--; 859 } 860 861 static HRESULT WINAPI ClassFactory_QueryInterface(IClassFactory *iface, REFIID riid, LPVOID *ppvOut) 862 { 863 *ppvOut = NULL; 864 if (IsEqualIID(riid, &IID_IClassFactory) || IsEqualIID(riid, &IID_IUnknown)) 865 { 866 IClassFactory_AddRef(iface); 867 *ppvOut = iface; 868 return S_OK; 869 } 870 871 return E_NOINTERFACE; 872 } 873 874 static ULONG WINAPI ClassFactory_AddRef(IClassFactory *iface) 875 { 876 ClassFactory *This = impl_from_IClassFactory(iface); 877 return InterlockedIncrement(&This->ref); 878 } 879 880 static ULONG WINAPI ClassFactory_Release(IClassFactory *iface) 881 { 882 ClassFactory *This = impl_from_IClassFactory(iface); 883 ULONG ret = InterlockedDecrement(&This->ref); 884 885 if (ret == 0) 886 ClassFactory_Destructor(This); 887 return ret; 888 } 889 890 static HRESULT WINAPI ClassFactory_CreateInstance(IClassFactory *iface, IUnknown *punkOuter, REFIID iid, LPVOID *ppvOut) 891 { 892 ClassFactory *This = impl_from_IClassFactory(iface); 893 HRESULT ret; 894 IUnknown *obj; 895 896 ret = This->ctor(punkOuter, &obj); 897 if (FAILED(ret)) 898 return ret; 899 ret = IUnknown_QueryInterface(obj, iid, ppvOut); 900 IUnknown_Release(obj); 901 return ret; 902 } 903 904 static HRESULT WINAPI ClassFactory_LockServer(IClassFactory *iface, BOOL fLock) 905 { 906 if(fLock) 907 InterlockedIncrement(&TS_refCount); 908 else 909 InterlockedDecrement(&TS_refCount); 910 911 return S_OK; 912 } 913 914 static const IClassFactoryVtbl ClassFactoryVtbl = { 915 /* IUnknown */ 916 ClassFactory_QueryInterface, 917 ClassFactory_AddRef, 918 ClassFactory_Release, 919 920 /* IClassFactory*/ 921 ClassFactory_CreateInstance, 922 ClassFactory_LockServer 923 }; 924 925 static HRESULT ClassFactory_Constructor(LPFNCONSTRUCTOR ctor, LPVOID *ppvOut) 926 { 927 ClassFactory *This = HeapAlloc(GetProcessHeap(),0,sizeof(ClassFactory)); 928 This->IClassFactory_iface.lpVtbl = &ClassFactoryVtbl; 929 This->ref = 1; 930 This->ctor = ctor; 931 *ppvOut = &This->IClassFactory_iface; 932 TS_refCount++; 933 return S_OK; 934 } 935 936 static void TextService_Destructor(TextService *This) 937 { 938 HeapFree(GetProcessHeap(),0,This); 939 } 940 941 static HRESULT WINAPI TextService_QueryInterface(ITfTextInputProcessor *iface, REFIID iid, LPVOID *ppvOut) 942 { 943 *ppvOut = NULL; 944 945 if (IsEqualIID(iid, &IID_IUnknown) || IsEqualIID(iid, &IID_ITfTextInputProcessor)) 946 { 947 *ppvOut = iface; 948 } 949 950 if (*ppvOut) 951 { 952 ITfTextInputProcessor_AddRef(iface); 953 return S_OK; 954 } 955 956 return E_NOINTERFACE; 957 } 958 959 static ULONG WINAPI TextService_AddRef(ITfTextInputProcessor *iface) 960 { 961 TextService *This = impl_from_ITfTextInputProcessor(iface); 962 return InterlockedIncrement(&This->refCount); 963 } 964 965 static ULONG WINAPI TextService_Release(ITfTextInputProcessor *iface) 966 { 967 TextService *This = impl_from_ITfTextInputProcessor(iface); 968 ULONG ret; 969 970 ret = InterlockedDecrement(&This->refCount); 971 if (ret == 0) 972 TextService_Destructor(This); 973 return ret; 974 } 975 976 static HRESULT WINAPI TextService_Activate(ITfTextInputProcessor *iface, 977 ITfThreadMgr *ptim, TfClientId id) 978 { 979 trace("TextService_Activate\n"); 980 ok(test_ShouldActivate,"Activation came unexpectedly\n"); 981 tid = id; 982 return S_OK; 983 } 984 985 static HRESULT WINAPI TextService_Deactivate(ITfTextInputProcessor *iface) 986 { 987 trace("TextService_Deactivate\n"); 988 ok(test_ShouldDeactivate,"Deactivation came unexpectedly\n"); 989 return S_OK; 990 } 991 992 static const ITfTextInputProcessorVtbl TextService_TextInputProcessorVtbl= 993 { 994 TextService_QueryInterface, 995 TextService_AddRef, 996 TextService_Release, 997 998 TextService_Activate, 999 TextService_Deactivate 1000 }; 1001 1002 static HRESULT TextService_Constructor(IUnknown *pUnkOuter, IUnknown **ppOut) 1003 { 1004 TextService *This; 1005 if (pUnkOuter) 1006 return CLASS_E_NOAGGREGATION; 1007 1008 This = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(TextService)); 1009 if (This == NULL) 1010 return E_OUTOFMEMORY; 1011 1012 This->ITfTextInputProcessor_iface.lpVtbl = &TextService_TextInputProcessorVtbl; 1013 This->refCount = 1; 1014 1015 *ppOut = (IUnknown*)&This->ITfTextInputProcessor_iface; 1016 return S_OK; 1017 } 1018 1019 static HRESULT RegisterTextService(REFCLSID rclsid) 1020 { 1021 ClassFactory_Constructor( TextService_Constructor ,(LPVOID*)&cf); 1022 return CoRegisterClassObject(rclsid, (IUnknown*) cf, CLSCTX_INPROC_SERVER, REGCLS_MULTIPLEUSE, ®id); 1023 } 1024 1025 static HRESULT UnregisterTextService(void) 1026 { 1027 return CoRevokeClassObject(regid); 1028 } 1029 1030 /* 1031 * The tests 1032 */ 1033 1034 DEFINE_GUID(CLSID_TF_InputProcessorProfiles, 0x33c53a50,0xf456,0x4884,0xb0,0x49,0x85,0xfd,0x64,0x3e,0xcf,0xed); 1035 DEFINE_GUID(CLSID_TF_CategoryMgr, 0xA4B544A1,0x438D,0x4B41,0x93,0x25,0x86,0x95,0x23,0xE2,0xD6,0xC7); 1036 DEFINE_GUID(GUID_TFCAT_TIP_KEYBOARD, 0x34745c63,0xb2f0,0x4784,0x8b,0x67,0x5e,0x12,0xc8,0x70,0x1a,0x31); 1037 DEFINE_GUID(GUID_TFCAT_TIP_SPEECH, 0xB5A73CD1,0x8355,0x426B,0xA1,0x61,0x25,0x98,0x08,0xF2,0x6B,0x14); 1038 DEFINE_GUID(GUID_TFCAT_TIP_HANDWRITING, 0x246ecb87,0xc2f2,0x4abe,0x90,0x5b,0xc8,0xb3,0x8a,0xdd,0x2c,0x43); 1039 DEFINE_GUID (GUID_TFCAT_DISPLAYATTRIBUTEPROVIDER, 0x046B8C80,0x1647,0x40F7,0x9B,0x21,0xB9,0x3B,0x81,0xAA,0xBC,0x1B); 1040 DEFINE_GUID(GUID_NULL,0,0,0,0,0,0,0,0,0,0,0); 1041 DEFINE_GUID(CLSID_TF_ThreadMgr, 0x529a9e6b,0x6587,0x4f23,0xab,0x9e,0x9c,0x7d,0x68,0x3e,0x3c,0x50); 1042 DEFINE_GUID(CLSID_PreservedKey, 0xA0ED8E55,0xCD3B,0x4274,0xB2,0x95,0xF6,0xC9,0xBA,0x2B,0x84,0x72); 1043 DEFINE_GUID(GUID_COMPARTMENT_KEYBOARD_DISABLED, 0x71a5b253,0x1951,0x466b,0x9f,0xbc,0x9c,0x88,0x08,0xfa,0x84,0xf2); 1044 DEFINE_GUID(GUID_COMPARTMENT_KEYBOARD_OPENCLOSE, 0x58273aad,0x01bb,0x4164,0x95,0xc6,0x75,0x5b,0xa0,0xb5,0x16,0x2d); 1045 DEFINE_GUID(GUID_COMPARTMENT_HANDWRITING_OPENCLOSE, 0xf9ae2c6b,0x1866,0x4361,0xaf,0x72,0x7a,0xa3,0x09,0x48,0x89,0x0e); 1046 DEFINE_GUID(GUID_COMPARTMENT_SPEECH_DISABLED, 0x56c5c607,0x0703,0x4e59,0x8e,0x52,0xcb,0xc8,0x4e,0x8b,0xbe,0x35); 1047 DEFINE_GUID(GUID_COMPARTMENT_SPEECH_OPENCLOSE, 0x544d6a63,0xe2e8,0x4752,0xbb,0xd1,0x00,0x09,0x60,0xbc,0xa0,0x83); 1048 DEFINE_GUID(GUID_COMPARTMENT_SPEECH_GLOBALSTATE, 0x2a54fe8e,0x0d08,0x460c,0xa7,0x5d,0x87,0x03,0x5f,0xf4,0x36,0xc5); 1049 DEFINE_GUID(GUID_COMPARTMENT_PERSISTMENUENABLED, 0x575f3783,0x70c8,0x47c8,0xae,0x5d,0x91,0xa0,0x1a,0x1f,0x75,0x92); 1050 DEFINE_GUID(GUID_COMPARTMENT_EMPTYCONTEXT, 0xd7487dbf,0x804e,0x41c5,0x89,0x4d,0xad,0x96,0xfd,0x4e,0xea,0x13); 1051 DEFINE_GUID(GUID_COMPARTMENT_TIPUISTATUS, 0x148ca3ec,0x0366,0x401c,0x8d,0x75,0xed,0x97,0x8d,0x85,0xfb,0xc9); 1052 1053 static HRESULT initialize(void) 1054 { 1055 HRESULT hr; 1056 HKEY hkey; 1057 1058 CoInitialize(NULL); 1059 1060 if (RegOpenKeyExA(HKEY_LOCAL_MACHINE, "Software\\Microsoft\\CTF\\TIP", 0, 1061 KEY_READ|KEY_WRITE, &hkey) != ERROR_SUCCESS) 1062 { 1063 skip("Not enough permission to register input processor\n"); 1064 return E_FAIL; 1065 } 1066 RegCloseKey(hkey); 1067 1068 hr = CoCreateInstance (&CLSID_TF_InputProcessorProfiles, NULL, 1069 CLSCTX_INPROC_SERVER, &IID_ITfInputProcessorProfiles, (void**)&g_ipp); 1070 if (SUCCEEDED(hr)) 1071 hr = CoCreateInstance (&CLSID_TF_CategoryMgr, NULL, 1072 CLSCTX_INPROC_SERVER, &IID_ITfCategoryMgr, (void**)&g_cm); 1073 if (SUCCEEDED(hr)) 1074 hr = CoCreateInstance (&CLSID_TF_ThreadMgr, NULL, 1075 CLSCTX_INPROC_SERVER, &IID_ITfThreadMgr, (void**)&g_tm); 1076 return hr; 1077 } 1078 1079 static void cleanup(void) 1080 { 1081 if (g_ipp) 1082 ITfInputProcessorProfiles_Release(g_ipp); 1083 if (g_cm) 1084 ITfCategoryMgr_Release(g_cm); 1085 if (g_tm) 1086 ITfThreadMgr_Release(g_tm); 1087 CoUninitialize(); 1088 } 1089 1090 static void test_Register(void) 1091 { 1092 HRESULT hr; 1093 1094 static const WCHAR szDesc[] = {'F','a','k','e',' ','W','i','n','e',' ','S','e','r','v','i','c','e',0}; 1095 static const WCHAR szFile[] = {'F','a','k','e',' ','W','i','n','e',' ','S','e','r','v','i','c','e',' ','F','i','l','e',0}; 1096 1097 hr = ITfInputProcessorProfiles_GetCurrentLanguage(g_ipp,&gLangid); 1098 ok(SUCCEEDED(hr),"Unable to get current language id\n"); 1099 trace("Current Language %x\n",gLangid); 1100 1101 hr = RegisterTextService(&CLSID_FakeService); 1102 ok(SUCCEEDED(hr),"Unable to register COM for TextService\n"); 1103 hr = ITfInputProcessorProfiles_Register(g_ipp, &CLSID_FakeService); 1104 ok(SUCCEEDED(hr),"Unable to register text service(%x)\n",hr); 1105 hr = ITfInputProcessorProfiles_AddLanguageProfile(g_ipp, &CLSID_FakeService, gLangid, 1106 &CLSID_FakeService, szDesc, ARRAY_SIZE(szDesc), szFile, ARRAY_SIZE(szFile), 1); 1107 ok(SUCCEEDED(hr),"Unable to add Language Profile (%x)\n",hr); 1108 } 1109 1110 static void test_Unregister(void) 1111 { 1112 HRESULT hr; 1113 hr = ITfInputProcessorProfiles_Unregister(g_ipp, &CLSID_FakeService); 1114 ok(SUCCEEDED(hr),"Unable to unregister text service(%x)\n",hr); 1115 UnregisterTextService(); 1116 } 1117 1118 static void test_EnumInputProcessorInfo(void) 1119 { 1120 IEnumGUID *ppEnum; 1121 BOOL found = FALSE; 1122 1123 if (SUCCEEDED(ITfInputProcessorProfiles_EnumInputProcessorInfo(g_ipp, &ppEnum))) 1124 { 1125 ULONG fetched; 1126 GUID g; 1127 while (IEnumGUID_Next(ppEnum, 1, &g, &fetched) == S_OK) 1128 { 1129 if(IsEqualGUID(&g,&CLSID_FakeService)) 1130 found = TRUE; 1131 } 1132 IEnumGUID_Release(ppEnum); 1133 } 1134 ok(found,"Did not find registered text service\n"); 1135 } 1136 1137 static void test_EnumLanguageProfiles(void) 1138 { 1139 BOOL found = FALSE; 1140 IEnumTfLanguageProfiles *ppEnum; 1141 HRESULT hr; 1142 1143 hr = ITfInputProcessorProfiles_EnumLanguageProfiles(g_ipp, gLangid, NULL); 1144 ok(hr == E_INVALIDARG, "EnumLanguageProfiles failed: %x\n", hr); 1145 1146 if (SUCCEEDED(ITfInputProcessorProfiles_EnumLanguageProfiles(g_ipp,gLangid,&ppEnum))) 1147 { 1148 TF_LANGUAGEPROFILE profile; 1149 while (IEnumTfLanguageProfiles_Next(ppEnum,1,&profile,NULL)==S_OK) 1150 { 1151 if (IsEqualGUID(&profile.clsid,&CLSID_FakeService)) 1152 { 1153 found = TRUE; 1154 ok(profile.langid == gLangid, "LangId Incorrect\n"); 1155 ok(IsEqualGUID(&profile.catid,&GUID_TFCAT_TIP_KEYBOARD) || 1156 broken(IsEqualGUID(&profile.catid,&GUID_NULL) /* Win8 */), "CatId Incorrect\n"); 1157 ok(IsEqualGUID(&profile.guidProfile,&CLSID_FakeService), "guidProfile Incorrect\n"); 1158 } 1159 } 1160 IEnumTfLanguageProfiles_Release(ppEnum); 1161 } 1162 ok(found,"Registered text service not found\n"); 1163 } 1164 1165 static void test_RegisterCategory(void) 1166 { 1167 HRESULT hr; 1168 hr = ITfCategoryMgr_RegisterCategory(g_cm, &CLSID_FakeService, &GUID_TFCAT_TIP_KEYBOARD, &CLSID_FakeService); 1169 ok(SUCCEEDED(hr),"ITfCategoryMgr_RegisterCategory failed\n"); 1170 hr = ITfCategoryMgr_RegisterCategory(g_cm, &CLSID_FakeService, &GUID_TFCAT_DISPLAYATTRIBUTEPROVIDER, &CLSID_FakeService); 1171 ok(SUCCEEDED(hr),"ITfCategoryMgr_RegisterCategory failed\n"); 1172 } 1173 1174 static void test_UnregisterCategory(void) 1175 { 1176 HRESULT hr; 1177 hr = ITfCategoryMgr_UnregisterCategory(g_cm, &CLSID_FakeService, &GUID_TFCAT_TIP_KEYBOARD, &CLSID_FakeService); 1178 ok(SUCCEEDED(hr),"ITfCategoryMgr_UnregisterCategory failed\n"); 1179 hr = ITfCategoryMgr_UnregisterCategory(g_cm, &CLSID_FakeService, &GUID_TFCAT_DISPLAYATTRIBUTEPROVIDER, &CLSID_FakeService); 1180 ok(SUCCEEDED(hr),"ITfCategoryMgr_UnregisterCategory failed\n"); 1181 } 1182 1183 static void test_FindClosestCategory(void) 1184 { 1185 GUID output; 1186 HRESULT hr; 1187 const GUID *list[3] = {&GUID_TFCAT_TIP_SPEECH, &GUID_TFCAT_TIP_KEYBOARD, &GUID_TFCAT_TIP_HANDWRITING}; 1188 1189 hr = ITfCategoryMgr_FindClosestCategory(g_cm, &CLSID_FakeService, &output, NULL, 0); 1190 ok(SUCCEEDED(hr),"ITfCategoryMgr_FindClosestCategory failed (%x)\n",hr); 1191 ok(IsEqualGUID(&output,&GUID_TFCAT_DISPLAYATTRIBUTEPROVIDER),"Wrong GUID\n"); 1192 1193 hr = ITfCategoryMgr_FindClosestCategory(g_cm, &CLSID_FakeService, &output, list, 1); 1194 ok(SUCCEEDED(hr),"ITfCategoryMgr_FindClosestCategory failed (%x)\n",hr); 1195 ok(IsEqualGUID(&output,&GUID_NULL),"Wrong GUID\n"); 1196 1197 hr = ITfCategoryMgr_FindClosestCategory(g_cm, &CLSID_FakeService, &output, list, 3); 1198 ok(SUCCEEDED(hr),"ITfCategoryMgr_FindClosestCategory failed (%x)\n",hr); 1199 ok(IsEqualGUID(&output,&GUID_TFCAT_TIP_KEYBOARD),"Wrong GUID\n"); 1200 } 1201 1202 static void test_Enable(void) 1203 { 1204 HRESULT hr; 1205 BOOL enabled = FALSE; 1206 1207 hr = ITfInputProcessorProfiles_EnableLanguageProfile(g_ipp,&CLSID_FakeService, gLangid, &CLSID_FakeService, TRUE); 1208 ok(SUCCEEDED(hr),"Failed to enable text service\n"); 1209 hr = ITfInputProcessorProfiles_IsEnabledLanguageProfile(g_ipp,&CLSID_FakeService, gLangid, &CLSID_FakeService, &enabled); 1210 ok(SUCCEEDED(hr),"Failed to get enabled state\n"); 1211 ok(enabled == TRUE,"enabled state incorrect\n"); 1212 } 1213 1214 static void test_Disable(void) 1215 { 1216 HRESULT hr; 1217 1218 trace("Disabling\n"); 1219 hr = ITfInputProcessorProfiles_EnableLanguageProfile(g_ipp,&CLSID_FakeService, gLangid, &CLSID_FakeService, FALSE); 1220 ok(SUCCEEDED(hr),"Failed to disable text service\n"); 1221 } 1222 1223 static void test_ThreadMgrAdviseSinks(void) 1224 { 1225 ITfSource *source = NULL; 1226 HRESULT hr; 1227 IUnknown *sink; 1228 1229 hr = ITfThreadMgr_QueryInterface(g_tm, &IID_ITfSource, (LPVOID*)&source); 1230 ok(SUCCEEDED(hr),"Failed to get IID_ITfSource for ThreadMgr\n"); 1231 if (!source) 1232 return; 1233 1234 hr = ThreadMgrEventSink_Constructor(&sink); 1235 ok(hr == S_OK, "got %08x\n", hr); 1236 if(FAILED(hr)) return; 1237 1238 tmSinkRefCount = 1; 1239 tmSinkCookie = 0; 1240 hr = ITfSource_AdviseSink(source,&IID_ITfThreadMgrEventSink, sink, &tmSinkCookie); 1241 ok(hr == S_OK, "Failed to Advise ITfThreadMgrEventSink\n"); 1242 ok(tmSinkCookie!=0,"Failed to get sink cookie\n"); 1243 1244 /* Advising the sink adds a ref, Releasing here lets the object be deleted 1245 when unadvised */ 1246 tmSinkRefCount = 2; 1247 IUnknown_Release(sink); 1248 1249 hr = ITfSource_AdviseSink(source, &IID_ITfKeyTraceEventSink, (IUnknown*)&TfKeyTraceEventSink, 1250 &key_trace_sink_cookie); 1251 ok(hr == S_OK, "Failed to Advise ITfKeyTraceEventSink\n"); 1252 1253 hr = ITfSource_AdviseSink(source, &IID_ITfUIElementSink, (IUnknown*)&TfUIElementSink, 1254 &ui_element_sink_cookie); 1255 ok(hr == S_OK, "Failed to Advise ITfUIElementSink\n"); 1256 1257 hr = ITfSource_AdviseSink(source, &IID_ITfInputProcessorProfileActivationSink, (IUnknown*)&TfInputProcessorProfileActivationSink, 1258 &profile_activation_sink_cookie); 1259 ok(hr == S_OK, "Failed to Advise ITfInputProcessorProfileActivationSink\n"); 1260 1261 ITfSource_Release(source); 1262 } 1263 1264 static void test_ThreadMgrUnadviseSinks(void) 1265 { 1266 ITfSource *source = NULL; 1267 HRESULT hr; 1268 1269 hr = ITfThreadMgr_QueryInterface(g_tm, &IID_ITfSource, (LPVOID*)&source); 1270 ok(SUCCEEDED(hr),"Failed to get IID_ITfSource for ThreadMgr\n"); 1271 if (!source) 1272 return; 1273 1274 tmSinkRefCount = 1; 1275 hr = ITfSource_UnadviseSink(source, tmSinkCookie); 1276 ok(hr == S_OK, "Failed to unadvise ITfThreadMgrEventSink\n"); 1277 1278 hr = ITfSource_UnadviseSink(source, key_trace_sink_cookie); 1279 ok(hr == S_OK, "Failed to unadvise ITfKeyTraceEventSink\n"); 1280 1281 hr = ITfSource_UnadviseSink(source, ui_element_sink_cookie); 1282 ok(hr == S_OK, "Failed to unadvise ITfUIElementSink\n"); 1283 1284 hr = ITfSource_UnadviseSink(source, profile_activation_sink_cookie); 1285 ok(hr == S_OK, "Failed to unadvise ITfInputProcessorProfileActivationSink\n"); 1286 1287 ITfSource_Release(source); 1288 } 1289 1290 static void test_DocumentMgrAdviseSinks(void) 1291 { 1292 ITfSource *source; 1293 HRESULT hr; 1294 1295 hr = ITfDocumentMgr_QueryInterface(g_dm, &IID_ITfSource, (void**)&source); 1296 ok(hr == S_OK,"Failed to get IID_ITfSource for DocumentMgr\n"); 1297 1298 dmSinkCookie = 0; 1299 hr = ITfSource_AdviseSink(source, &IID_ITfTransitoryExtensionSink, (IUnknown*)&TfTransitoryExtensionSink, &dmSinkCookie); 1300 ok(hr == S_OK,"Failed to Advise Sink\n"); 1301 1302 ITfSource_Release(source); 1303 } 1304 1305 static void test_DocumentMgrUnadviseSinks(void) 1306 { 1307 ITfSource *source = NULL; 1308 HRESULT hr; 1309 1310 hr = ITfDocumentMgr_QueryInterface(g_dm, &IID_ITfSource, (void**)&source); 1311 ok(hr == S_OK,"Failed to get IID_ITfSource for DocumentMgr\n"); 1312 1313 hr = ITfSource_UnadviseSink(source, dmSinkCookie); 1314 ok(hr == S_OK,"Failed to unadvise Sink\n"); 1315 ITfSource_Release(source); 1316 } 1317 1318 /********************************************************************** 1319 * ITfKeyEventSink 1320 **********************************************************************/ 1321 typedef struct tagKeyEventSink 1322 { 1323 ITfKeyEventSink ITfKeyEventSink_iface; 1324 LONG refCount; 1325 } KeyEventSink; 1326 1327 static inline KeyEventSink *impl_from_ITfKeyEventSink(ITfKeyEventSink *iface) 1328 { 1329 return CONTAINING_RECORD(iface, KeyEventSink, ITfKeyEventSink_iface); 1330 } 1331 1332 static void KeyEventSink_Destructor(KeyEventSink *This) 1333 { 1334 HeapFree(GetProcessHeap(),0,This); 1335 } 1336 1337 static HRESULT WINAPI KeyEventSink_QueryInterface(ITfKeyEventSink *iface, REFIID iid, LPVOID *ppvOut) 1338 { 1339 *ppvOut = NULL; 1340 1341 if (IsEqualIID(iid, &IID_IUnknown) || IsEqualIID(iid, &IID_ITfKeyEventSink)) 1342 { 1343 *ppvOut = iface; 1344 } 1345 1346 if (*ppvOut) 1347 { 1348 ITfKeyEventSink_AddRef(iface); 1349 return S_OK; 1350 } 1351 1352 return E_NOINTERFACE; 1353 } 1354 1355 static ULONG WINAPI KeyEventSink_AddRef(ITfKeyEventSink *iface) 1356 { 1357 KeyEventSink *This = impl_from_ITfKeyEventSink(iface); 1358 return InterlockedIncrement(&This->refCount); 1359 } 1360 1361 static ULONG WINAPI KeyEventSink_Release(ITfKeyEventSink *iface) 1362 { 1363 KeyEventSink *This = impl_from_ITfKeyEventSink(iface); 1364 ULONG ret; 1365 1366 ret = InterlockedDecrement(&This->refCount); 1367 if (ret == 0) 1368 KeyEventSink_Destructor(This); 1369 return ret; 1370 } 1371 1372 static HRESULT WINAPI KeyEventSink_OnSetFocus(ITfKeyEventSink *iface, 1373 BOOL fForeground) 1374 { 1375 sink_fire_ok(&test_KEV_OnSetFocus,"KeyEventSink_OnSetFocus"); 1376 return S_OK; 1377 } 1378 1379 static HRESULT WINAPI KeyEventSink_OnTestKeyDown(ITfKeyEventSink *iface, 1380 ITfContext *pic, WPARAM wParam, LPARAM lParam, BOOL *pfEaten) 1381 { 1382 trace("\n"); 1383 return S_OK; 1384 } 1385 1386 static HRESULT WINAPI KeyEventSink_OnTestKeyUp(ITfKeyEventSink *iface, 1387 ITfContext *pic, WPARAM wParam, LPARAM lParam, BOOL *pfEaten) 1388 { 1389 trace("\n"); 1390 return S_OK; 1391 } 1392 1393 static HRESULT WINAPI KeyEventSink_OnKeyDown(ITfKeyEventSink *iface, 1394 ITfContext *pic, WPARAM wParam, LPARAM lParam, BOOL *pfEaten) 1395 { 1396 trace("\n"); 1397 return S_OK; 1398 } 1399 1400 static HRESULT WINAPI KeyEventSink_OnKeyUp(ITfKeyEventSink *iface, 1401 ITfContext *pic, WPARAM wParam, LPARAM lParam, BOOL *pfEaten) 1402 { 1403 trace("\n"); 1404 return S_OK; 1405 } 1406 1407 static HRESULT WINAPI KeyEventSink_OnPreservedKey(ITfKeyEventSink *iface, 1408 ITfContext *pic, REFGUID rguid, BOOL *pfEaten) 1409 { 1410 trace("\n"); 1411 return S_OK; 1412 } 1413 1414 static const ITfKeyEventSinkVtbl KeyEventSink_KeyEventSinkVtbl = 1415 { 1416 KeyEventSink_QueryInterface, 1417 KeyEventSink_AddRef, 1418 KeyEventSink_Release, 1419 1420 KeyEventSink_OnSetFocus, 1421 KeyEventSink_OnTestKeyDown, 1422 KeyEventSink_OnTestKeyUp, 1423 KeyEventSink_OnKeyDown, 1424 KeyEventSink_OnKeyUp, 1425 KeyEventSink_OnPreservedKey 1426 }; 1427 1428 static HRESULT KeyEventSink_Constructor(ITfKeyEventSink **ppOut) 1429 { 1430 KeyEventSink *This; 1431 1432 This = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(KeyEventSink)); 1433 if (This == NULL) 1434 return E_OUTOFMEMORY; 1435 1436 This->ITfKeyEventSink_iface.lpVtbl = &KeyEventSink_KeyEventSinkVtbl; 1437 This->refCount = 1; 1438 1439 *ppOut = &This->ITfKeyEventSink_iface; 1440 return S_OK; 1441 } 1442 1443 1444 static void test_KeystrokeMgr(void) 1445 { 1446 ITfKeystrokeMgr *keymgr= NULL; 1447 HRESULT hr; 1448 TF_PRESERVEDKEY tfpk; 1449 BOOL preserved; 1450 ITfKeyEventSink *sink = NULL; 1451 1452 KeyEventSink_Constructor(&sink); 1453 1454 hr = ITfThreadMgr_QueryInterface(g_tm, &IID_ITfKeystrokeMgr, (LPVOID*)&keymgr); 1455 ok(SUCCEEDED(hr),"Failed to get IID_ITfKeystrokeMgr for ThreadMgr\n"); 1456 1457 tfpk.uVKey = 'A'; 1458 tfpk.uModifiers = TF_MOD_SHIFT; 1459 1460 test_KEV_OnSetFocus = SINK_EXPECTED; 1461 hr = ITfKeystrokeMgr_AdviseKeyEventSink(keymgr,tid,sink,TRUE); 1462 ok(SUCCEEDED(hr),"ITfKeystrokeMgr_AdviseKeyEventSink failed\n"); 1463 sink_check_ok(&test_KEV_OnSetFocus,"KeyEventSink_OnSetFocus"); 1464 hr = ITfKeystrokeMgr_AdviseKeyEventSink(keymgr,tid,sink,TRUE); 1465 ok(hr == CONNECT_E_ADVISELIMIT,"Wrong return, expected CONNECT_E_ADVISELIMIT\n"); 1466 hr = ITfKeystrokeMgr_AdviseKeyEventSink(keymgr,cid,sink,TRUE); 1467 ok(hr == E_INVALIDARG,"Wrong return, expected E_INVALIDARG\n"); 1468 1469 hr =ITfKeystrokeMgr_PreserveKey(keymgr, 0, &CLSID_PreservedKey, &tfpk, NULL, 0); 1470 ok(hr==E_INVALIDARG,"ITfKeystrokeMgr_PreserveKey improperly succeeded\n"); 1471 1472 hr =ITfKeystrokeMgr_PreserveKey(keymgr, tid, &CLSID_PreservedKey, &tfpk, NULL, 0); 1473 ok(SUCCEEDED(hr),"ITfKeystrokeMgr_PreserveKey failed\n"); 1474 1475 hr =ITfKeystrokeMgr_PreserveKey(keymgr, tid, &CLSID_PreservedKey, &tfpk, NULL, 0); 1476 ok(hr == TF_E_ALREADY_EXISTS,"ITfKeystrokeMgr_PreserveKey improperly succeeded\n"); 1477 1478 preserved = FALSE; 1479 hr = ITfKeystrokeMgr_IsPreservedKey(keymgr, &CLSID_PreservedKey, &tfpk, &preserved); 1480 ok(hr == S_OK, "ITfKeystrokeMgr_IsPreservedKey failed\n"); 1481 if (hr == S_OK) ok(preserved == TRUE,"misreporting preserved key\n"); 1482 1483 hr = ITfKeystrokeMgr_UnpreserveKey(keymgr, &CLSID_PreservedKey,&tfpk); 1484 ok(SUCCEEDED(hr),"ITfKeystrokeMgr_UnpreserveKey failed\n"); 1485 1486 hr = ITfKeystrokeMgr_IsPreservedKey(keymgr, &CLSID_PreservedKey, &tfpk, &preserved); 1487 ok(hr == S_FALSE, "ITfKeystrokeMgr_IsPreservedKey failed\n"); 1488 if (hr == S_FALSE) ok(preserved == FALSE,"misreporting preserved key\n"); 1489 1490 hr = ITfKeystrokeMgr_UnpreserveKey(keymgr, &CLSID_PreservedKey,&tfpk); 1491 ok(hr==CONNECT_E_NOCONNECTION,"ITfKeystrokeMgr_UnpreserveKey improperly succeeded\n"); 1492 1493 hr = ITfKeystrokeMgr_UnadviseKeyEventSink(keymgr,tid); 1494 ok(SUCCEEDED(hr),"ITfKeystrokeMgr_UnadviseKeyEventSink failed\n"); 1495 1496 ITfKeystrokeMgr_Release(keymgr); 1497 ITfKeyEventSink_Release(sink); 1498 } 1499 1500 static void test_Activate(void) 1501 { 1502 HRESULT hr; 1503 1504 test_ShouldActivate = TRUE; /* Win7 */ 1505 hr = ITfInputProcessorProfiles_ActivateLanguageProfile(g_ipp,&CLSID_FakeService,gLangid,&CLSID_FakeService); 1506 ok(SUCCEEDED(hr),"Failed to Activate text service\n"); 1507 test_ShouldActivate = FALSE; 1508 } 1509 1510 1511 static void test_EnumContexts(ITfDocumentMgr *dm, ITfContext *search) 1512 { 1513 HRESULT hr; 1514 IEnumTfContexts* pEnum; 1515 BOOL found = FALSE; 1516 1517 hr = ITfDocumentMgr_EnumContexts(dm,&pEnum); 1518 ok(SUCCEEDED(hr),"EnumContexts failed\n"); 1519 if (SUCCEEDED(hr)) 1520 { 1521 ULONG fetched; 1522 ITfContext *cxt; 1523 while (IEnumTfContexts_Next(pEnum, 1, &cxt, &fetched) == S_OK) 1524 { 1525 if (!search) 1526 found = TRUE; 1527 else if (search == cxt) 1528 found = TRUE; 1529 ITfContext_Release(cxt); 1530 } 1531 IEnumTfContexts_Release(pEnum); 1532 } 1533 if (search) 1534 ok(found,"Did not find proper ITfContext\n"); 1535 else 1536 ok(!found,"Found an ITfContext we should should not have\n"); 1537 } 1538 1539 static void test_EnumDocumentMgr(ITfThreadMgr *tm, ITfDocumentMgr *search, ITfDocumentMgr *absent) 1540 { 1541 HRESULT hr; 1542 IEnumTfDocumentMgrs* pEnum; 1543 BOOL found = FALSE; 1544 BOOL notfound = TRUE; 1545 1546 hr = ITfThreadMgr_EnumDocumentMgrs(tm,&pEnum); 1547 ok(SUCCEEDED(hr),"EnumDocumentMgrs failed\n"); 1548 if (SUCCEEDED(hr)) 1549 { 1550 ULONG fetched; 1551 ITfDocumentMgr *dm; 1552 while (IEnumTfDocumentMgrs_Next(pEnum, 1, &dm, &fetched) == S_OK) 1553 { 1554 if (!search) 1555 found = TRUE; 1556 else if (search == dm) 1557 found = TRUE; 1558 if (absent && dm == absent) 1559 notfound = FALSE; 1560 ITfDocumentMgr_Release(dm); 1561 } 1562 IEnumTfDocumentMgrs_Release(pEnum); 1563 } 1564 if (search) 1565 ok(found,"Did not find proper ITfDocumentMgr\n"); 1566 else 1567 ok(!found,"Found an ITfDocumentMgr we should should not have\n"); 1568 if (absent) 1569 ok(notfound,"Found an ITfDocumentMgr we believe should be absent\n"); 1570 } 1571 1572 static inline int check_context_refcount(ITfContext *iface) 1573 { 1574 ITfContext_AddRef(iface); 1575 return ITfContext_Release(iface); 1576 } 1577 1578 1579 /********************************************************************** 1580 * ITfTextEditSink 1581 **********************************************************************/ 1582 typedef struct tagTextEditSink 1583 { 1584 ITfTextEditSink ITfTextEditSink_iface; 1585 LONG refCount; 1586 } TextEditSink; 1587 1588 static inline TextEditSink *impl_from_ITfTextEditSink(ITfTextEditSink *iface) 1589 { 1590 return CONTAINING_RECORD(iface, TextEditSink, ITfTextEditSink_iface); 1591 } 1592 1593 static void TextEditSink_Destructor(TextEditSink *This) 1594 { 1595 HeapFree(GetProcessHeap(),0,This); 1596 } 1597 1598 static HRESULT WINAPI TextEditSink_QueryInterface(ITfTextEditSink *iface, REFIID iid, LPVOID *ppvOut) 1599 { 1600 *ppvOut = NULL; 1601 1602 if (IsEqualIID(iid, &IID_IUnknown) || IsEqualIID(iid, &IID_ITfTextEditSink)) 1603 { 1604 *ppvOut = iface; 1605 } 1606 1607 if (*ppvOut) 1608 { 1609 ITfTextEditSink_AddRef(iface); 1610 return S_OK; 1611 } 1612 1613 return E_NOINTERFACE; 1614 } 1615 1616 static ULONG WINAPI TextEditSink_AddRef(ITfTextEditSink *iface) 1617 { 1618 TextEditSink *This = impl_from_ITfTextEditSink(iface); 1619 return InterlockedIncrement(&This->refCount); 1620 } 1621 1622 static ULONG WINAPI TextEditSink_Release(ITfTextEditSink *iface) 1623 { 1624 TextEditSink *This = impl_from_ITfTextEditSink(iface); 1625 ULONG ret; 1626 1627 ret = InterlockedDecrement(&This->refCount); 1628 if (ret == 0) 1629 TextEditSink_Destructor(This); 1630 return ret; 1631 } 1632 1633 static HRESULT WINAPI TextEditSink_OnEndEdit(ITfTextEditSink *iface, 1634 ITfContext *pic, TfEditCookie ecReadOnly, ITfEditRecord *pEditRecord) 1635 { 1636 sink_fire_ok(&test_OnEndEdit,"TextEditSink_OnEndEdit"); 1637 return S_OK; 1638 } 1639 1640 static const ITfTextEditSinkVtbl TextEditSink_TextEditSinkVtbl = 1641 { 1642 TextEditSink_QueryInterface, 1643 TextEditSink_AddRef, 1644 TextEditSink_Release, 1645 1646 TextEditSink_OnEndEdit 1647 }; 1648 1649 static HRESULT TextEditSink_Constructor(ITfTextEditSink **ppOut) 1650 { 1651 TextEditSink *This; 1652 1653 *ppOut = NULL; 1654 This = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(TextEditSink)); 1655 if (This == NULL) 1656 return E_OUTOFMEMORY; 1657 1658 This->ITfTextEditSink_iface.lpVtbl = &TextEditSink_TextEditSinkVtbl; 1659 This->refCount = 1; 1660 1661 *ppOut = &This->ITfTextEditSink_iface; 1662 return S_OK; 1663 } 1664 1665 static void test_startSession(void) 1666 { 1667 HRESULT hr; 1668 DWORD cnt; 1669 DWORD editCookie; 1670 ITfDocumentMgr *dmtest; 1671 ITfContext *cxt,*cxt2,*cxt3,*cxtTest; 1672 ITextStoreACP *ts = NULL; 1673 TfClientId cid2 = 0; 1674 ITfThreadMgrEx *tmex; 1675 1676 hr = ITfThreadMgr_Deactivate(g_tm); 1677 ok(hr == E_UNEXPECTED,"Deactivate should have failed with E_UNEXPECTED\n"); 1678 1679 test_ShouldActivate = TRUE; 1680 hr = ITfThreadMgr_Activate(g_tm,&cid); 1681 ok(SUCCEEDED(hr),"Failed to Activate\n"); 1682 ok(cid != tid,"TextService id mistakenly matches Client id\n"); 1683 1684 todo_wine ok(fake_service_onactivated_flags & TF_IPSINK_FLAG_ACTIVE, "Expected OnActivated callback\n"); 1685 1686 test_ShouldActivate = FALSE; 1687 hr = ITfThreadMgr_Activate(g_tm,&cid2); 1688 ok(SUCCEEDED(hr),"Failed to Activate\n"); 1689 ok(cid == cid2, "Second activate client ID does not match\n"); 1690 1691 hr = ITfThreadMgr_QueryInterface(g_tm, &IID_ITfThreadMgrEx, (void **)&tmex); 1692 if (hr == S_OK) 1693 { 1694 hr = ITfThreadMgrEx_ActivateEx(tmex, &cid2, 0); 1695 ok(SUCCEEDED(hr), "Failed to Activate\n"); 1696 ok(cid == cid2, "ActivateEx client ID does not match\n"); 1697 1698 ITfThreadMgrEx_Release(tmex); 1699 } 1700 else 1701 win_skip("ITfThreadMgrEx is not supported\n"); 1702 1703 hr = ITfThreadMgr_Deactivate(g_tm); 1704 ok(SUCCEEDED(hr), "Failed to Deactivate\n"); 1705 hr = ITfThreadMgr_Deactivate(g_tm); 1706 ok(SUCCEEDED(hr), "Failed to Deactivate\n"); 1707 1708 test_EnumDocumentMgr(g_tm,NULL,NULL); 1709 1710 hr = ITfThreadMgr_CreateDocumentMgr(g_tm,&g_dm); 1711 ok(SUCCEEDED(hr),"CreateDocumentMgr failed\n"); 1712 1713 test_EnumDocumentMgr(g_tm,g_dm,NULL); 1714 1715 hr = ITfThreadMgr_CreateDocumentMgr(g_tm,&dmtest); 1716 ok(SUCCEEDED(hr),"CreateDocumentMgr failed\n"); 1717 1718 test_EnumDocumentMgr(g_tm,dmtest,NULL); 1719 1720 ITfDocumentMgr_Release(dmtest); 1721 test_EnumDocumentMgr(g_tm,g_dm,dmtest); 1722 1723 hr = ITfThreadMgr_GetFocus(g_tm,&dmtest); 1724 ok(SUCCEEDED(hr),"GetFocus Failed\n"); 1725 ok(dmtest == NULL,"Initial focus not null\n"); 1726 1727 test_CurrentFocus = g_dm; 1728 test_PrevFocus = NULL; 1729 test_OnSetFocus = SINK_OPTIONAL; /* Doesn't always fire on Win7 */ 1730 hr = ITfThreadMgr_SetFocus(g_tm,g_dm); 1731 ok(SUCCEEDED(hr),"SetFocus Failed\n"); 1732 sink_check_ok(&test_OnSetFocus,"OnSetFocus"); 1733 1734 hr = ITfThreadMgr_GetFocus(g_tm,&dmtest); 1735 ok(SUCCEEDED(hr),"GetFocus Failed\n"); 1736 ok(g_dm == dmtest,"Expected DocumentMgr not focused\n"); 1737 1738 ITfDocumentMgr_Release(g_dm); 1739 1740 hr = ITfThreadMgr_GetFocus(g_tm,&dmtest); 1741 ok(SUCCEEDED(hr),"GetFocus Failed\n"); 1742 ok(g_dm == dmtest,"Expected DocumentMgr not focused\n"); 1743 ITfDocumentMgr_Release(dmtest); 1744 1745 hr = TextStoreACP_Constructor((IUnknown**)&ts); 1746 ok(SUCCEEDED(hr),"Constructor Failed\n"); 1747 if (FAILED(hr)) return; 1748 1749 hr = ITfDocumentMgr_CreateContext(g_dm, cid, 0, (IUnknown*)ts, &cxt, &editCookie); 1750 ok(SUCCEEDED(hr),"CreateContext Failed\n"); 1751 1752 hr = ITfDocumentMgr_CreateContext(g_dm, cid, 0, NULL, &cxt2, &editCookie); 1753 ok(SUCCEEDED(hr),"CreateContext Failed\n"); 1754 1755 hr = ITfDocumentMgr_CreateContext(g_dm, cid, 0, NULL, &cxt3, &editCookie); 1756 ok(SUCCEEDED(hr),"CreateContext Failed\n"); 1757 1758 test_EnumContexts(g_dm, NULL); 1759 1760 hr = ITfContext_GetDocumentMgr(cxt,&dmtest); 1761 ok(hr == S_OK, "ITfContext_GetDocumentMgr failed with %x\n",hr); 1762 ok(dmtest == g_dm, "Wrong documentmgr\n"); 1763 ITfDocumentMgr_Release(dmtest); 1764 1765 cnt = check_context_refcount(cxt); 1766 test_OnPushContext = SINK_EXPECTED; 1767 test_ACP_AdviseSink = SINK_EXPECTED; 1768 test_OnInitDocumentMgr = SINK_EXPECTED; 1769 hr = ITfDocumentMgr_Push(g_dm, cxt); 1770 ok(SUCCEEDED(hr),"Push Failed\n"); 1771 ok(check_context_refcount(cxt) > cnt, "Ref count did not increase\n"); 1772 sink_check_ok(&test_OnPushContext,"OnPushContext"); 1773 sink_check_ok(&test_OnInitDocumentMgr,"OnInitDocumentMgr"); 1774 sink_check_ok(&test_ACP_AdviseSink,"TextStoreACP_AdviseSink"); 1775 1776 test_EnumContexts(g_dm, cxt); 1777 1778 hr = ITfDocumentMgr_GetTop(g_dm, &cxtTest); 1779 ok(SUCCEEDED(hr),"GetTop Failed\n"); 1780 ok(cxtTest == cxt, "Wrong context on top\n"); 1781 ok(check_context_refcount(cxt) > cnt, "Ref count did not increase\n"); 1782 cnt = ITfContext_Release(cxtTest); 1783 1784 hr = ITfDocumentMgr_GetBase(g_dm, &cxtTest); 1785 ok(SUCCEEDED(hr),"GetBase Failed\n"); 1786 ok(cxtTest == cxt, "Wrong context on Base\n"); 1787 ok(check_context_refcount(cxt) > cnt, "Ref count did not increase\n"); 1788 ITfContext_Release(cxtTest); 1789 1790 check_context_refcount(cxt2); 1791 test_OnPushContext = SINK_EXPECTED; 1792 hr = ITfDocumentMgr_Push(g_dm, cxt2); 1793 ok(SUCCEEDED(hr),"Push Failed\n"); 1794 sink_check_ok(&test_OnPushContext,"OnPushContext"); 1795 1796 cnt = check_context_refcount(cxt2); 1797 hr = ITfDocumentMgr_GetTop(g_dm, &cxtTest); 1798 ok(SUCCEEDED(hr),"GetTop Failed\n"); 1799 ok(cxtTest == cxt2, "Wrong context on top\n"); 1800 ok(check_context_refcount(cxt2) > cnt, "Ref count did not increase\n"); 1801 ITfContext_Release(cxtTest); 1802 1803 cnt = check_context_refcount(cxt); 1804 hr = ITfDocumentMgr_GetBase(g_dm, &cxtTest); 1805 ok(SUCCEEDED(hr),"GetBase Failed\n"); 1806 ok(cxtTest == cxt, "Wrong context on Base\n"); 1807 ok(check_context_refcount(cxt) > cnt, "Ref count did not increase\n"); 1808 ITfContext_Release(cxtTest); 1809 1810 cnt = check_context_refcount(cxt3); 1811 hr = ITfDocumentMgr_Push(g_dm, cxt3); 1812 ok(FAILED(hr),"Push Succeeded\n"); 1813 ok(check_context_refcount(cxt3) == cnt, "Ref changed\n"); 1814 1815 cnt = check_context_refcount(cxt2); 1816 hr = ITfDocumentMgr_GetTop(g_dm, &cxtTest); 1817 ok(SUCCEEDED(hr),"GetTop Failed\n"); 1818 ok(cxtTest == cxt2, "Wrong context on top\n"); 1819 ok(check_context_refcount(cxt2) > cnt, "Ref count did not increase\n"); 1820 ITfContext_Release(cxtTest); 1821 1822 cnt = check_context_refcount(cxt); 1823 hr = ITfDocumentMgr_GetBase(g_dm, &cxtTest); 1824 ok(SUCCEEDED(hr),"GetBase Failed\n"); 1825 ok(cxtTest == cxt, "Wrong context on Base\n"); 1826 ok(check_context_refcount(cxt) > cnt, "Ref count did not increase\n"); 1827 ITfContext_Release(cxtTest); 1828 1829 cnt = check_context_refcount(cxt2); 1830 test_OnPopContext = SINK_EXPECTED; 1831 hr = ITfDocumentMgr_Pop(g_dm, 0); 1832 ok(SUCCEEDED(hr),"Pop Failed\n"); 1833 ok(check_context_refcount(cxt2) < cnt, "Ref count did not decrease\n"); 1834 sink_check_ok(&test_OnPopContext,"OnPopContext"); 1835 1836 dmtest = (void *)0xfeedface; 1837 hr = ITfContext_GetDocumentMgr(cxt2,&dmtest); 1838 ok(hr == S_FALSE, "ITfContext_GetDocumentMgr wrong rc %x\n",hr); 1839 ok(dmtest == NULL,"returned documentmgr should be null\n"); 1840 1841 ITfContext_Release(cxt2); 1842 1843 hr = ITfDocumentMgr_GetTop(g_dm, &cxtTest); 1844 ok(SUCCEEDED(hr),"GetTop Failed\n"); 1845 ok(cxtTest == cxt, "Wrong context on top\n"); 1846 ITfContext_Release(cxtTest); 1847 1848 hr = ITfDocumentMgr_GetBase(g_dm, &cxtTest); 1849 ok(SUCCEEDED(hr),"GetBase Failed\n"); 1850 ok(cxtTest == cxt, "Wrong context on base\n"); 1851 ITfContext_Release(cxtTest); 1852 1853 hr = ITfDocumentMgr_CreateContext(g_dm, cid, 0, (IUnknown*)ts, &cxt2, &editCookie); 1854 ok(hr == S_OK,"CreateContext Failed\n"); 1855 1856 test_OnPushContext = SINK_EXPECTED; 1857 test_ACP_AdviseSink = SINK_EXPECTED; 1858 hr = ITfDocumentMgr_Push(g_dm, cxt2); 1859 ok(hr == S_OK,"Push Failed\n"); 1860 sink_check_ok(&test_OnPushContext,"OnPushContext"); 1861 sink_check_ok(&test_ACP_AdviseSink,"TextStoreACP_AdviseSink"); 1862 1863 test_ACP_UnadviseSink = SINK_EXPECTED; 1864 cnt = check_context_refcount(cxt2); 1865 test_OnPopContext = SINK_EXPECTED; 1866 hr = ITfDocumentMgr_Pop(g_dm, 0); 1867 ok(hr == S_OK,"Pop Failed\n"); 1868 ok(check_context_refcount(cxt2) < cnt, "Ref count did not decrease\n"); 1869 sink_check_ok(&test_OnPopContext,"OnPopContext"); 1870 sink_check_ok(&test_ACP_UnadviseSink,"TextStoreACP_AdviseSink"); 1871 1872 hr = ITfDocumentMgr_Pop(g_dm, 0); 1873 ok(FAILED(hr),"Pop Succeeded\n"); 1874 1875 hr = ITfDocumentMgr_GetTop(g_dm, &cxtTest); 1876 ok(SUCCEEDED(hr),"GetTop Failed\n"); 1877 ok(cxtTest == cxt, "Wrong context on top\n"); 1878 ITfContext_Release(cxtTest); 1879 1880 hr = ITfDocumentMgr_GetBase(g_dm, &cxtTest); 1881 ok(SUCCEEDED(hr),"GetBase Failed\n"); 1882 ok(cxtTest == cxt, "Wrong context on base\n"); 1883 ITfContext_Release(cxtTest); 1884 1885 ITfContext_Release(cxt); 1886 ITfContext_Release(cxt2); 1887 ITfContext_Release(cxt3); 1888 ITextStoreACP_Release(ts); 1889 } 1890 1891 static void test_endSession(void) 1892 { 1893 HRESULT hr; 1894 test_ShouldDeactivate = TRUE; 1895 test_CurrentFocus = NULL; 1896 test_PrevFocus = g_dm; 1897 test_OnSetFocus = SINK_OPTIONAL; /* Doesn't fire on Win7 */ 1898 hr = ITfThreadMgr_Deactivate(g_tm); 1899 ok(SUCCEEDED(hr),"Failed to Deactivate\n"); 1900 sink_check_ok(&test_OnSetFocus,"OnSetFocus"); 1901 test_OnSetFocus = SINK_UNEXPECTED; 1902 } 1903 1904 static void test_TfGuidAtom(void) 1905 { 1906 GUID gtest,g1; 1907 HRESULT hr; 1908 TfGuidAtom atom1,atom2; 1909 BOOL equal; 1910 1911 CoCreateGuid(>est); 1912 1913 /* msdn reports this should return E_INVALIDARG. However my test show it crashing (winxp)*/ 1914 /* 1915 hr = ITfCategoryMgr_RegisterGUID(g_cm,>est,NULL); 1916 ok(hr==E_INVALIDARG,"ITfCategoryMgr_RegisterGUID should have failed\n"); 1917 */ 1918 hr = ITfCategoryMgr_RegisterGUID(g_cm,>est,&atom1); 1919 ok(SUCCEEDED(hr),"ITfCategoryMgr_RegisterGUID failed\n"); 1920 hr = ITfCategoryMgr_RegisterGUID(g_cm,>est,&atom2); 1921 ok(SUCCEEDED(hr),"ITfCategoryMgr_RegisterGUID failed\n"); 1922 ok(atom1 == atom2,"atoms do not match\n"); 1923 hr = ITfCategoryMgr_GetGUID(g_cm,atom2,NULL); 1924 ok(hr==E_INVALIDARG,"ITfCategoryMgr_GetGUID should have failed\n"); 1925 hr = ITfCategoryMgr_GetGUID(g_cm,atom2,&g1); 1926 ok(SUCCEEDED(hr),"ITfCategoryMgr_GetGUID failed\n"); 1927 ok(IsEqualGUID(&g1,>est),"guids do not match\n"); 1928 hr = ITfCategoryMgr_IsEqualTfGuidAtom(g_cm,atom1,>est,NULL); 1929 ok(hr==E_INVALIDARG,"ITfCategoryMgr_IsEqualTfGuidAtom should have failed\n"); 1930 hr = ITfCategoryMgr_IsEqualTfGuidAtom(g_cm,atom1,>est,&equal); 1931 ok(SUCCEEDED(hr),"ITfCategoryMgr_IsEqualTfGuidAtom failed\n"); 1932 ok(equal == TRUE,"Equal value invalid\n"); 1933 1934 /* show that cid and tid TfClientIds are also TfGuidAtoms */ 1935 hr = ITfCategoryMgr_IsEqualTfGuidAtom(g_cm,tid,&CLSID_FakeService,&equal); 1936 ok(SUCCEEDED(hr),"ITfCategoryMgr_IsEqualTfGuidAtom failed\n"); 1937 ok(equal == TRUE,"Equal value invalid\n"); 1938 hr = ITfCategoryMgr_GetGUID(g_cm,cid,&g1); 1939 ok(SUCCEEDED(hr),"ITfCategoryMgr_GetGUID failed\n"); 1940 ok(!IsEqualGUID(&g1,&GUID_NULL),"guid should not be NULL\n"); 1941 } 1942 1943 static void test_ClientId(void) 1944 { 1945 ITfClientId *pcid; 1946 TfClientId id1,id2; 1947 HRESULT hr; 1948 GUID g2; 1949 1950 hr = ITfThreadMgr_QueryInterface(g_tm, &IID_ITfClientId, (LPVOID*)&pcid); 1951 ok(SUCCEEDED(hr),"Unable to acquire ITfClientId interface\n"); 1952 1953 CoCreateGuid(&g2); 1954 1955 hr = ITfClientId_GetClientId(pcid,&GUID_NULL,&id1); 1956 ok(SUCCEEDED(hr),"GetClientId failed\n"); 1957 hr = ITfClientId_GetClientId(pcid,&GUID_NULL,&id2); 1958 ok(SUCCEEDED(hr),"GetClientId failed\n"); 1959 ok(id1==id2,"Id's for GUID_NULL do not match\n"); 1960 hr = ITfClientId_GetClientId(pcid,&CLSID_FakeService,&id2); 1961 ok(SUCCEEDED(hr),"GetClientId failed\n"); 1962 ok(id2!=id1,"Id matches GUID_NULL\n"); 1963 ok(id2==tid,"Id for CLSID_FakeService not matching tid\n"); 1964 ok(id2!=cid,"Id for CLSID_FakeService matching cid\n"); 1965 hr = ITfClientId_GetClientId(pcid,&g2,&id2); 1966 ok(SUCCEEDED(hr),"GetClientId failed\n"); 1967 ok(id2!=id1,"Id matches GUID_NULL\n"); 1968 ok(id2!=tid,"Id for random guid matching tid\n"); 1969 ok(id2!=cid,"Id for random guid matching cid\n"); 1970 ITfClientId_Release(pcid); 1971 } 1972 1973 /********************************************************************** 1974 * ITfEditSession 1975 **********************************************************************/ 1976 typedef struct tagEditSession 1977 { 1978 ITfEditSession ITfEditSession_iface; 1979 LONG refCount; 1980 } EditSession; 1981 1982 static inline EditSession *impl_from_ITfEditSession(ITfEditSession *iface) 1983 { 1984 return CONTAINING_RECORD(iface, EditSession, ITfEditSession_iface); 1985 } 1986 1987 static void EditSession_Destructor(EditSession *This) 1988 { 1989 HeapFree(GetProcessHeap(),0,This); 1990 } 1991 1992 static HRESULT WINAPI EditSession_QueryInterface(ITfEditSession *iface, REFIID iid, LPVOID *ppvOut) 1993 { 1994 *ppvOut = NULL; 1995 1996 if (IsEqualIID(iid, &IID_IUnknown) || IsEqualIID(iid, &IID_ITfEditSession)) 1997 { 1998 *ppvOut = iface; 1999 } 2000 2001 if (*ppvOut) 2002 { 2003 ITfEditSession_AddRef(iface); 2004 return S_OK; 2005 } 2006 2007 return E_NOINTERFACE; 2008 } 2009 2010 static ULONG WINAPI EditSession_AddRef(ITfEditSession *iface) 2011 { 2012 EditSession *This = impl_from_ITfEditSession(iface); 2013 return InterlockedIncrement(&This->refCount); 2014 } 2015 2016 static ULONG WINAPI EditSession_Release(ITfEditSession *iface) 2017 { 2018 EditSession *This = impl_from_ITfEditSession(iface); 2019 ULONG ret; 2020 2021 ret = InterlockedDecrement(&This->refCount); 2022 if (ret == 0) 2023 EditSession_Destructor(This); 2024 return ret; 2025 } 2026 2027 static void test_InsertAtSelection(TfEditCookie ec, ITfContext *cxt) 2028 { 2029 HRESULT hr; 2030 ITfInsertAtSelection *iis; 2031 ITfRange *range=NULL; 2032 static const WCHAR txt[] = {'H','e','l','l','o',' ','W','o','r','l','d',0}; 2033 2034 hr = ITfContext_QueryInterface(cxt, &IID_ITfInsertAtSelection , (LPVOID*)&iis); 2035 ok(SUCCEEDED(hr),"Failed to get ITfInsertAtSelection interface\n"); 2036 test_ACP_InsertTextAtSelection = SINK_EXPECTED; 2037 hr = ITfInsertAtSelection_InsertTextAtSelection(iis, ec, 0, txt, 11, &range); 2038 ok(SUCCEEDED(hr),"ITfInsertAtSelection_InsertTextAtSelection failed %x\n",hr); 2039 sink_check_ok(&test_ACP_InsertTextAtSelection,"InsertTextAtSelection"); 2040 ok(range != NULL,"No range returned\n"); 2041 ITfRange_Release(range); 2042 ITfInsertAtSelection_Release(iis); 2043 } 2044 2045 static HRESULT WINAPI EditSession_DoEditSession(ITfEditSession *iface, 2046 TfEditCookie ec) 2047 { 2048 ITfContext *cxt; 2049 ITfDocumentMgr *dm; 2050 ITfRange *range; 2051 TF_SELECTION selection; 2052 ULONG fetched; 2053 HRESULT hr; 2054 2055 sink_fire_ok(&test_DoEditSession,"EditSession_DoEditSession"); 2056 sink_check_ok(&test_ACP_RequestLock,"RequestLock"); 2057 2058 ITfThreadMgr_GetFocus(g_tm, &dm); 2059 ITfDocumentMgr_GetTop(dm,&cxt); 2060 2061 hr = ITfContext_GetStart(cxt,ec,NULL); 2062 ok(hr == E_INVALIDARG,"Unexpected return code %x\n",hr); 2063 2064 range = (ITfRange*)0xdeaddead; 2065 hr = ITfContext_GetStart(cxt,0xdeadcafe,&range); 2066 ok(hr == TF_E_NOLOCK,"Unexpected return code %x\n",hr); 2067 ok(range == NULL,"Range not set to NULL\n"); 2068 2069 hr = ITfContext_GetStart(cxt,ec,&range); 2070 ok(SUCCEEDED(hr),"Unexpected return code %x\n",hr); 2071 ok(range != NULL,"Range set to NULL\n"); 2072 2073 ITfRange_Release(range); 2074 2075 hr = ITfContext_GetEnd(cxt,ec,NULL); 2076 ok(hr == E_INVALIDARG,"Unexpected return code %x\n",hr); 2077 2078 range = (ITfRange*)0xdeaddead; 2079 hr = ITfContext_GetEnd(cxt,0xdeadcafe,&range); 2080 ok(hr == TF_E_NOLOCK,"Unexpected return code %x\n",hr); 2081 ok(range == NULL,"Range not set to NULL\n"); 2082 2083 test_ACP_GetEndACP = SINK_EXPECTED; 2084 hr = ITfContext_GetEnd(cxt,ec,&range); 2085 ok(SUCCEEDED(hr),"Unexpected return code %x\n",hr); 2086 ok(range != NULL,"Range set to NULL\n"); 2087 sink_check_ok(&test_ACP_GetEndACP,"GetEndACP"); 2088 2089 ITfRange_Release(range); 2090 2091 selection.range = NULL; 2092 test_ACP_GetSelection = SINK_EXPECTED; 2093 hr = ITfContext_GetSelection(cxt, ec, TF_DEFAULT_SELECTION, 1, &selection, &fetched); 2094 ok(SUCCEEDED(hr),"ITfContext_GetSelection failed\n"); 2095 ok(fetched == 1,"fetched incorrect\n"); 2096 ok(selection.range != NULL,"NULL range\n"); 2097 sink_check_ok(&test_ACP_GetSelection,"GetSelection"); 2098 ITfRange_Release(selection.range); 2099 2100 test_InsertAtSelection(ec, cxt); 2101 2102 test_ACP_GetEndACP = SINK_EXPECTED; 2103 hr = ITfContext_GetEnd(cxt,ec,&range); 2104 ok(SUCCEEDED(hr),"Unexpected return code %x\n",hr); 2105 ok(range != NULL,"Range set to NULL\n"); 2106 sink_check_ok(&test_ACP_GetEndACP,"GetEndACP"); 2107 2108 selection.range = range; 2109 selection.style.ase = TF_AE_NONE; 2110 selection.style.fInterimChar = FALSE; 2111 test_ACP_SetSelection = SINK_EXPECTED; 2112 hr = ITfContext_SetSelection(cxt, ec, 1, &selection); 2113 ok(SUCCEEDED(hr),"ITfContext_SetSelection failed\n"); 2114 sink_check_ok(&test_ACP_SetSelection,"SetSelection"); 2115 ITfRange_Release(range); 2116 2117 ITfContext_Release(cxt); 2118 ITfDocumentMgr_Release(dm); 2119 return 0xdeadcafe; 2120 } 2121 2122 static const ITfEditSessionVtbl EditSession_EditSessionVtbl = 2123 { 2124 EditSession_QueryInterface, 2125 EditSession_AddRef, 2126 EditSession_Release, 2127 2128 EditSession_DoEditSession 2129 }; 2130 2131 static HRESULT EditSession_Constructor(ITfEditSession **ppOut) 2132 { 2133 EditSession *This; 2134 2135 *ppOut = NULL; 2136 This = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(EditSession)); 2137 if (This == NULL) 2138 return E_OUTOFMEMORY; 2139 2140 This->ITfEditSession_iface.lpVtbl = &EditSession_EditSessionVtbl; 2141 This->refCount = 1; 2142 2143 *ppOut = &This->ITfEditSession_iface; 2144 return S_OK; 2145 } 2146 2147 static void test_TStoApplicationText(void) 2148 { 2149 HRESULT hr, hrSession; 2150 ITfEditSession *es; 2151 ITfContext *cxt; 2152 ITfDocumentMgr *dm; 2153 ITfTextEditSink *sink; 2154 ITfSource *source = NULL; 2155 DWORD editSinkCookie = -1; 2156 2157 ITfThreadMgr_GetFocus(g_tm, &dm); 2158 EditSession_Constructor(&es); 2159 ITfDocumentMgr_GetTop(dm,&cxt); 2160 2161 TextEditSink_Constructor(&sink); 2162 hr = ITfContext_QueryInterface(cxt,&IID_ITfSource,(LPVOID*)&source); 2163 ok(SUCCEEDED(hr),"Failed to get IID_ITfSource for Context\n"); 2164 if (source) 2165 { 2166 hr = ITfSource_AdviseSink(source, &IID_ITfTextEditSink, (LPVOID)sink, &editSinkCookie); 2167 ok(SUCCEEDED(hr),"Failed to advise Sink\n"); 2168 ok(editSinkCookie != -1,"Failed to get sink cookie\n"); 2169 } 2170 2171 hrSession = 0xfeedface; 2172 /* Test no permissions flags */ 2173 hr = ITfContext_RequestEditSession(cxt, tid, es, TF_ES_SYNC, &hrSession); 2174 ok(hr == E_INVALIDARG,"RequestEditSession should have failed with %x not %x\n",E_INVALIDARG,hr); 2175 ok(hrSession == E_FAIL,"hrSession should be %x not %x\n",E_FAIL,hrSession); 2176 2177 documentStatus = TS_SD_READONLY; 2178 hrSession = 0xfeedface; 2179 test_ACP_GetStatus = SINK_EXPECTED; 2180 hr = ITfContext_RequestEditSession(cxt, tid, es, TF_ES_SYNC|TF_ES_READWRITE, &hrSession); 2181 ok(SUCCEEDED(hr),"ITfContext_RequestEditSession failed\n"); 2182 ok(hrSession == TS_E_READONLY,"Unexpected hrSession (%x)\n",hrSession); 2183 sink_check_ok(&test_ACP_GetStatus,"GetStatus"); 2184 2185 /* signal a change to allow readwrite sessions */ 2186 documentStatus = 0; 2187 test_ACP_RequestLock = SINK_EXPECTED; 2188 ITextStoreACPSink_OnStatusChange(ACPSink,documentStatus); 2189 sink_check_ok(&test_ACP_RequestLock,"RequestLock"); 2190 2191 test_ACP_GetStatus = SINK_EXPECTED; 2192 test_ACP_RequestLock = SINK_EXPECTED; 2193 test_DoEditSession = SINK_EXPECTED; 2194 hrSession = 0xfeedface; 2195 test_OnEndEdit = SINK_EXPECTED; 2196 hr = ITfContext_RequestEditSession(cxt, tid, es, TF_ES_SYNC|TF_ES_READWRITE, &hrSession); 2197 ok(SUCCEEDED(hr),"ITfContext_RequestEditSession failed\n"); 2198 sink_check_ok(&test_OnEndEdit,"OnEndEdit"); 2199 sink_check_ok(&test_DoEditSession,"DoEditSession"); 2200 sink_check_ok(&test_ACP_GetStatus,"GetStatus"); 2201 ok(hrSession == 0xdeadcafe,"Unexpected hrSession (%x)\n",hrSession); 2202 2203 if (source) 2204 { 2205 hr = ITfSource_UnadviseSink(source, editSinkCookie); 2206 ok(SUCCEEDED(hr),"Failed to unadvise Sink\n"); 2207 ITfSource_Release(source); 2208 } 2209 ITfTextEditSink_Release(sink); 2210 ITfContext_Release(cxt); 2211 ITfDocumentMgr_Release(dm); 2212 ITfEditSession_Release(es); 2213 } 2214 2215 static void enum_compartments(ITfCompartmentMgr *cmpmgr, REFGUID present, REFGUID absent) 2216 { 2217 BOOL found,found2; 2218 IEnumGUID *ppEnum; 2219 found = FALSE; 2220 found2 = FALSE; 2221 if (SUCCEEDED(ITfCompartmentMgr_EnumCompartments(cmpmgr, &ppEnum))) 2222 { 2223 ULONG fetched; 2224 GUID g; 2225 while (IEnumGUID_Next(ppEnum, 1, &g, &fetched) == S_OK) 2226 { 2227 WCHAR str[50]; 2228 CHAR strA[50]; 2229 StringFromGUID2(&g,str,ARRAY_SIZE(str)); 2230 WideCharToMultiByte(CP_ACP,0,str,-1,strA,sizeof(strA),0,0); 2231 trace("found %s\n",strA); 2232 if (present && IsEqualGUID(present,&g)) 2233 found = TRUE; 2234 if (absent && IsEqualGUID(absent, &g)) 2235 found2 = TRUE; 2236 } 2237 IEnumGUID_Release(ppEnum); 2238 } 2239 if (present) 2240 ok(found,"Did not find compartment\n"); 2241 if (absent) 2242 ok(!found2,"Found compartment that should be absent\n"); 2243 } 2244 2245 static void test_Compartments(void) 2246 { 2247 ITfContext *cxt; 2248 ITfDocumentMgr *dm; 2249 ITfCompartmentMgr *cmpmgr; 2250 ITfCompartment *cmp; 2251 HRESULT hr; 2252 2253 ITfThreadMgr_GetFocus(g_tm, &dm); 2254 ITfDocumentMgr_GetTop(dm,&cxt); 2255 2256 /* Global */ 2257 hr = ITfThreadMgr_GetGlobalCompartment(g_tm, &cmpmgr); 2258 ok(SUCCEEDED(hr),"GetGlobalCompartment failed\n"); 2259 hr = ITfCompartmentMgr_GetCompartment(cmpmgr, &GUID_COMPARTMENT_SPEECH_OPENCLOSE, &cmp); 2260 ok(SUCCEEDED(hr),"GetCompartment failed\n"); 2261 ITfCompartment_Release(cmp); 2262 enum_compartments(cmpmgr,&GUID_COMPARTMENT_SPEECH_OPENCLOSE,NULL); 2263 ITfCompartmentMgr_Release(cmpmgr); 2264 2265 /* Thread */ 2266 hr = ITfThreadMgr_QueryInterface(g_tm, &IID_ITfCompartmentMgr, (LPVOID*)&cmpmgr); 2267 ok(SUCCEEDED(hr),"ThreadMgr QI for IID_ITfCompartmentMgr failed\n"); 2268 hr = ITfCompartmentMgr_GetCompartment(cmpmgr, &CLSID_FakeService, &cmp); 2269 ok(SUCCEEDED(hr),"GetCompartment failed\n"); 2270 enum_compartments(cmpmgr,&CLSID_FakeService,&GUID_COMPARTMENT_SPEECH_OPENCLOSE); 2271 ITfCompartmentMgr_ClearCompartment(cmpmgr,tid,&CLSID_FakeService); 2272 enum_compartments(cmpmgr,NULL,&CLSID_FakeService); 2273 ITfCompartmentMgr_Release(cmpmgr); 2274 ITfCompartment_Release(cmp); 2275 2276 /* DocumentMgr */ 2277 hr = ITfDocumentMgr_QueryInterface(dm, &IID_ITfCompartmentMgr, (LPVOID*)&cmpmgr); 2278 ok(SUCCEEDED(hr),"DocumentMgr QI for IID_ITfCompartmentMgr failed\n"); 2279 2280 hr = ITfCompartmentMgr_GetCompartment(cmpmgr, &GUID_COMPARTMENT_PERSISTMENUENABLED, &cmp); 2281 ok(SUCCEEDED(hr),"GetCompartment failed\n"); 2282 enum_compartments(cmpmgr,&GUID_COMPARTMENT_PERSISTMENUENABLED,&GUID_COMPARTMENT_SPEECH_OPENCLOSE); 2283 ITfCompartmentMgr_Release(cmpmgr); 2284 2285 /* Context */ 2286 hr = ITfContext_QueryInterface(cxt, &IID_ITfCompartmentMgr, (LPVOID*)&cmpmgr); 2287 ok(SUCCEEDED(hr),"Context QI for IID_ITfCompartmentMgr failed\n"); 2288 enum_compartments(cmpmgr,NULL,&GUID_COMPARTMENT_PERSISTMENUENABLED); 2289 ITfCompartmentMgr_Release(cmpmgr); 2290 2291 ITfContext_Release(cxt); 2292 ITfDocumentMgr_Release(dm); 2293 } 2294 2295 static void processPendingMessages(void) 2296 { 2297 MSG msg; 2298 int diff = 200; 2299 int min_timeout = 100; 2300 DWORD time = GetTickCount() + diff; 2301 2302 while (diff > 0) 2303 { 2304 if (MsgWaitForMultipleObjects(0, NULL, FALSE, min_timeout, QS_ALLINPUT) == WAIT_TIMEOUT) 2305 break; 2306 while (PeekMessageW(&msg, 0, 0, 0, PM_REMOVE)) 2307 { 2308 TranslateMessage(&msg); 2309 DispatchMessageW(&msg); 2310 } 2311 diff = time - GetTickCount(); 2312 } 2313 } 2314 2315 static void test_AssociateFocus(void) 2316 { 2317 ITfDocumentMgr *dm1, *dm2, *olddm, *dmcheck, *dmorig; 2318 HWND wnd1, wnd2, wnd3; 2319 HRESULT hr; 2320 2321 ITfThreadMgr_GetFocus(g_tm, &dmorig); 2322 test_CurrentFocus = NULL; 2323 test_PrevFocus = dmorig; 2324 test_OnSetFocus = SINK_OPTIONAL; /* Doesn't always fire on Win7 */ 2325 test_ACP_GetStatus = SINK_OPTIONAL; 2326 hr = ITfThreadMgr_SetFocus(g_tm,NULL); 2327 ok(SUCCEEDED(hr),"ITfThreadMgr_SetFocus failed\n"); 2328 sink_check_ok(&test_OnSetFocus,"OnSetFocus"); 2329 test_ACP_GetStatus = SINK_UNEXPECTED; 2330 ITfDocumentMgr_Release(dmorig); 2331 2332 hr = ITfThreadMgr_CreateDocumentMgr(g_tm,&dm1); 2333 ok(SUCCEEDED(hr),"CreateDocumentMgr failed\n"); 2334 2335 hr = ITfThreadMgr_CreateDocumentMgr(g_tm,&dm2); 2336 ok(SUCCEEDED(hr),"CreateDocumentMgr failed\n"); 2337 2338 wnd1 = CreateWindowA("edit",NULL,WS_POPUP,0,0,200,60,NULL,NULL,NULL,NULL); 2339 ok(wnd1!=NULL,"Unable to create window 1\n"); 2340 wnd2 = CreateWindowA("edit",NULL,WS_POPUP,0,65,200,60,NULL,NULL,NULL,NULL); 2341 ok(wnd2!=NULL,"Unable to create window 2\n"); 2342 wnd3 = CreateWindowA("edit",NULL,WS_POPUP,0,130,200,60,NULL,NULL,NULL,NULL); 2343 ok(wnd3!=NULL,"Unable to create window 3\n"); 2344 2345 processPendingMessages(); 2346 2347 test_OnInitDocumentMgr = SINK_OPTIONAL; /* Vista and greater */ 2348 test_OnPushContext = SINK_OPTIONAL; /* Vista and greater */ 2349 test_OnSetFocus = SINK_OPTIONAL; /* Win7 */ 2350 test_PrevFocus = NULL; 2351 test_CurrentFocus = FOCUS_IGNORE; 2352 2353 ShowWindow(wnd1,SW_SHOWNORMAL); 2354 test_OnSetFocus = SINK_UNEXPECTED; 2355 SetFocus(wnd1); 2356 sink_check_ok(&test_OnInitDocumentMgr,"OnInitDocumentMgr"); 2357 sink_check_ok(&test_OnPushContext,"OnPushContext"); 2358 2359 test_OnSetFocus = SINK_OPTIONAL; /* Vista and greater */ 2360 test_ACP_RequestLock = SINK_OPTIONAL; /* Win7 x64 */ 2361 test_ACP_GetSelection = SINK_OPTIONAL; /* Win7 x64 */ 2362 ITfThreadMgr_GetFocus(g_tm, &test_PrevFocus); 2363 test_CurrentFocus = FOCUS_IGNORE; /* This is a default system context */ 2364 processPendingMessages(); 2365 sink_check_ok(&test_OnSetFocus,"OnSetFocus"); 2366 test_ACP_RequestLock = SINK_UNEXPECTED; 2367 test_ACP_GetSelection = SINK_UNEXPECTED; 2368 2369 test_CurrentFocus = dm1; 2370 test_PrevFocus = FOCUS_IGNORE; 2371 test_OnSetFocus = SINK_OPTIONAL; 2372 test_ShouldDeactivate = TRUE; 2373 hr = ITfThreadMgr_AssociateFocus(g_tm,wnd1,dm1,&olddm); 2374 ok(SUCCEEDED(hr),"AssociateFocus failed\n"); 2375 sink_check_ok(&test_OnSetFocus,"OnSetFocus"); 2376 test_ShouldDeactivate = FALSE; 2377 2378 processPendingMessages(); 2379 2380 ITfThreadMgr_GetFocus(g_tm, &dmcheck); 2381 ok(dmcheck == dm1 || broken(dmcheck == dmorig /* Win7+ */), "Expected DocumentMgr not focused\n"); 2382 ITfDocumentMgr_Release(dmcheck); 2383 2384 /* We need to explicitly set focus on Win7+ */ 2385 test_CurrentFocus = dm1; 2386 test_PrevFocus = FOCUS_IGNORE; 2387 test_OnSetFocus = SINK_OPTIONAL; /* Doesn't always fire on Win7+ */ 2388 ITfThreadMgr_SetFocus(g_tm, dm1); 2389 sink_check_ok(&test_OnSetFocus, "OnSetFocus"); 2390 2391 hr = ITfThreadMgr_AssociateFocus(g_tm,wnd2,dm2,&olddm); 2392 ok(SUCCEEDED(hr),"AssociateFocus failed\n"); 2393 processPendingMessages(); 2394 ITfThreadMgr_GetFocus(g_tm, &dmcheck); 2395 ok(dmcheck == dm1, "Expected DocumentMgr not focused\n"); 2396 ITfDocumentMgr_Release(dmcheck); 2397 2398 hr = ITfThreadMgr_AssociateFocus(g_tm,wnd3,dm2,&olddm); 2399 ok(SUCCEEDED(hr),"AssociateFocus failed\n"); 2400 processPendingMessages(); 2401 ITfThreadMgr_GetFocus(g_tm, &dmcheck); 2402 ok(dmcheck == dm1, "Expected DocumentMgr not focused\n"); 2403 ITfDocumentMgr_Release(dmcheck); 2404 2405 test_CurrentFocus = FOCUS_SAVE; 2406 test_PrevFocus = FOCUS_SAVE; 2407 test_OnSetFocus = SINK_SAVE; 2408 test_ShouldDeactivate = TRUE; /* win 8/10 */ 2409 ShowWindow(wnd2,SW_SHOWNORMAL); 2410 SetFocus(wnd2); 2411 sink_check_saved(&test_OnSetFocus,dm1,dm2,"OnSetFocus"); 2412 test_CurrentFocus = FOCUS_IGNORE; /* occasional wine race */ 2413 test_PrevFocus = FOCUS_IGNORE; /* occasional wine race */ 2414 test_OnSetFocus = SINK_IGNORE; /* occasional wine race */ 2415 test_ShouldDeactivate = FALSE; 2416 processPendingMessages(); 2417 2418 ShowWindow(wnd3,SW_SHOWNORMAL); 2419 SetFocus(wnd3); 2420 processPendingMessages(); 2421 2422 test_CurrentFocus = FOCUS_SAVE; 2423 test_PrevFocus = FOCUS_SAVE; 2424 test_OnSetFocus = SINK_SAVE; 2425 SetFocus(wnd1); 2426 processPendingMessages(); 2427 sink_check_saved(&test_OnSetFocus,dm2,dm1,"OnSetFocus"); 2428 2429 hr = ITfThreadMgr_AssociateFocus(g_tm,wnd3,NULL,&olddm); 2430 ok(SUCCEEDED(hr),"AssociateFocus failed\n"); 2431 ok(olddm == dm2, "incorrect old DocumentMgr returned\n"); 2432 ITfDocumentMgr_Release(olddm); 2433 2434 test_CurrentFocus = dmorig; 2435 test_PrevFocus = dm1; 2436 test_OnSetFocus = SINK_OPTIONAL; /* Doesn't always fire on Win7+ */ 2437 test_ACP_GetStatus = SINK_IGNORE; 2438 ITfThreadMgr_SetFocus(g_tm,dmorig); 2439 sink_check_ok(&test_OnSetFocus,"OnSetFocus"); 2440 2441 test_CurrentFocus = FOCUS_SAVE; 2442 test_PrevFocus = FOCUS_SAVE; 2443 test_OnSetFocus = SINK_SAVE; 2444 SetFocus(wnd3); 2445 processPendingMessages(); 2446 sink_check_saved(&test_OnSetFocus,dmorig,FOCUS_IGNORE,"OnSetFocus"); /* CurrentFocus NULL on XP, system default on Vista */ 2447 2448 hr = ITfThreadMgr_AssociateFocus(g_tm,wnd2,NULL,&olddm); 2449 ok(SUCCEEDED(hr),"AssociateFocus failed\n"); 2450 ok(olddm == dm2, "incorrect old DocumentMgr returned\n"); 2451 ITfDocumentMgr_Release(olddm); 2452 hr = ITfThreadMgr_AssociateFocus(g_tm,wnd1,NULL,&olddm); 2453 ok(SUCCEEDED(hr),"AssociateFocus failed\n"); 2454 ok(olddm == dm1, "incorrect old DocumentMgr returned\n"); 2455 ITfDocumentMgr_Release(olddm); 2456 2457 test_OnSetFocus = SINK_IGNORE; /* OnSetFocus fires a couple of times on Win7 */ 2458 test_CurrentFocus = FOCUS_IGNORE; 2459 test_PrevFocus = FOCUS_IGNORE; 2460 SetFocus(wnd2); 2461 processPendingMessages(); 2462 SetFocus(wnd1); 2463 processPendingMessages(); 2464 test_OnSetFocus = SINK_UNEXPECTED; 2465 2466 ITfDocumentMgr_Release(dm1); 2467 ITfDocumentMgr_Release(dm2); 2468 2469 test_CurrentFocus = dmorig; 2470 test_PrevFocus = FOCUS_IGNORE; 2471 test_OnSetFocus = SINK_OPTIONAL; 2472 test_ACP_GetStatus = SINK_IGNORE; 2473 ITfThreadMgr_SetFocus(g_tm,dmorig); 2474 sink_check_ok(&test_OnSetFocus,"OnSetFocus"); 2475 2476 test_OnSetFocus = SINK_IGNORE; /* OnSetFocus fires a couple of times on Win7 */ 2477 test_CurrentFocus = FOCUS_IGNORE; 2478 test_PrevFocus = FOCUS_IGNORE; 2479 DestroyWindow(wnd1); 2480 DestroyWindow(wnd2); 2481 test_OnPopContext = SINK_OPTIONAL; /* Vista and greater */ 2482 test_OnSetFocus = SINK_OPTIONAL; /* Vista and greater */ 2483 ITfThreadMgr_GetFocus(g_tm, &test_PrevFocus); 2484 test_CurrentFocus = NULL; 2485 test_ShouldDeactivate = TRUE; /* Win7 */ 2486 DestroyWindow(wnd3); 2487 test_ShouldDeactivate = FALSE; 2488 sink_check_ok(&test_OnSetFocus,"OnSetFocus"); 2489 sink_check_ok(&test_OnPopContext,"OnPopContext"); 2490 } 2491 2492 static void test_profile_mgr(void) 2493 { 2494 IEnumTfInputProcessorProfiles *enum_profiles; 2495 ITfInputProcessorProfileMgr *ipp_mgr; 2496 HRESULT hres; 2497 2498 hres = ITfInputProcessorProfiles_QueryInterface(g_ipp, &IID_ITfInputProcessorProfileMgr, (void**)&ipp_mgr); 2499 if (hres != S_OK) 2500 { 2501 win_skip("ITfInputProcessorProfileMgr is not supported.\n"); 2502 return; 2503 } 2504 ok(hres == S_OK, "Could not get ITfInputProcessorProfileMgr iface: %08x\n", hres); 2505 2506 hres = ITfInputProcessorProfileMgr_EnumProfiles(ipp_mgr, 0, &enum_profiles); 2507 ok(hres == S_OK, "EnumProfiles failed: %08x\n", hres); 2508 2509 IEnumTfInputProcessorProfiles_Release(enum_profiles); 2510 2511 ITfInputProcessorProfileMgr_Release(ipp_mgr); 2512 } 2513 2514 static DWORD WINAPI test_MultiThreadApartment_Thread(void *param) { 2515 ITfThreadMgrEx *thmgr; 2516 ITfSource *source; 2517 DWORD cookie; 2518 HRESULT hr; 2519 2520 hr = CoInitializeEx(NULL, COINIT_MULTITHREADED); 2521 ok(SUCCEEDED(hr), "Failed to initialize multi-threaded apartment\n"); 2522 2523 hr = CoCreateInstance(&CLSID_TF_ThreadMgr, NULL, CLSCTX_INPROC_SERVER, &IID_ITfThreadMgrEx, (LPVOID *)&thmgr); 2524 ok(SUCCEEDED(hr), "Failed to create ITfThreadMgrEx instance\n"); 2525 2526 #ifdef __REACTOS__ 2527 // See CORE-16797 2528 if (!SUCCEEDED(hr)) 2529 goto err_out; 2530 #endif 2531 2532 hr = ITfThreadMgrEx_QueryInterface(thmgr, &IID_ITfSource, (LPVOID *)&source); 2533 ok(SUCCEEDED(hr), "Failed to query ITfSource interface\n"); 2534 2535 hr = ITfSource_AdviseSink(source, &IID_ITfUIElementSink, (IUnknown*)&TfUIElementSink, &cookie); 2536 ok(hr == REGDB_E_IIDNOTREG /* native */ || hr == E_NOINTERFACE /* wine */, 2537 "Advise ITfUIElementSink should return marshalling failure: %08x\n", hr); 2538 2539 hr = ITfSource_Release(source); 2540 ok(SUCCEEDED(hr), "Failed to Release source\n"); 2541 2542 hr = ITfThreadMgrEx_Release(thmgr); 2543 ok(SUCCEEDED(hr), "Failed to Release thread manager\n"); 2544 #ifdef __REACTOS__ 2545 err_out: 2546 #endif 2547 2548 CoUninitialize(); 2549 2550 return 0xdeadcafe; 2551 } 2552 2553 static void test_MultiThreadApartment(void) 2554 { 2555 DWORD ret; 2556 HANDLE thread; 2557 2558 thread = CreateThread(0, 0, test_MultiThreadApartment_Thread, 0, 0, 0); 2559 ok(thread != NULL, "Failed to create test thread\n"); 2560 2561 ret = WaitForSingleObject(thread, INFINITE); 2562 ok(ret == WAIT_OBJECT_0, "Failed to wait for thread completion\n"); 2563 2564 GetExitCodeThread(thread, &ret); 2565 ok(ret == 0xdeadcafe, "Thread terminated in an unexpected way\n"); 2566 2567 CloseHandle(thread); 2568 } 2569 2570 START_TEST(inputprocessor) 2571 { 2572 if (SUCCEEDED(initialize())) 2573 { 2574 test_Register(); 2575 test_RegisterCategory(); 2576 Sleep(2000); /* Win7 needs some time before the registrations become active */ 2577 processPendingMessages(); 2578 test_EnumLanguageProfiles(); 2579 test_EnumInputProcessorInfo(); 2580 test_Enable(); 2581 test_ThreadMgrAdviseSinks(); 2582 test_Activate(); 2583 test_startSession(); 2584 test_DocumentMgrAdviseSinks(); 2585 test_TfGuidAtom(); 2586 test_ClientId(); 2587 test_KeystrokeMgr(); 2588 test_TStoApplicationText(); 2589 test_Compartments(); 2590 test_AssociateFocus(); 2591 test_endSession(); 2592 test_FindClosestCategory(); 2593 test_Disable(); 2594 test_ThreadMgrUnadviseSinks(); 2595 test_DocumentMgrUnadviseSinks(); 2596 test_UnregisterCategory(); 2597 test_Unregister(); 2598 test_profile_mgr(); 2599 test_MultiThreadApartment(); 2600 2601 ITextStoreACPSink_Release(ACPSink); 2602 ITfDocumentMgr_Release(g_dm); 2603 } 2604 else 2605 skip("Unable to create InputProcessor\n"); 2606 cleanup(); 2607 } 2608