1 /* 2 * Marshaling Tests 3 * 4 * Copyright 2004 Robert Shearman 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 #define _WIN32_DCOM 22 #define COBJMACROS 23 #define CONST_VTABLE 24 25 #include <stdarg.h> 26 #include <stdio.h> 27 28 #include "windef.h" 29 #include "winbase.h" 30 #include "objbase.h" 31 #include "olectl.h" 32 #include "shlguid.h" 33 #include "shobjidl.h" 34 35 #include "wine/test.h" 36 #include "wine/heap.h" 37 38 #define DEFINE_EXPECT(func) \ 39 static BOOL expect_ ## func = FALSE, called_ ## func = FALSE 40 41 #define SET_EXPECT(func) \ 42 expect_ ## func = TRUE 43 44 #define CHECK_EXPECT2(func) \ 45 do { \ 46 ok(expect_ ##func, "unexpected call " #func "\n"); \ 47 called_ ## func = TRUE; \ 48 }while(0) 49 50 #define CHECK_EXPECT(func) \ 51 do { \ 52 CHECK_EXPECT2(func); \ 53 expect_ ## func = FALSE; \ 54 }while(0) 55 56 #define CHECK_CALLED(func) \ 57 do { \ 58 ok(called_ ## func, "expected " #func "\n"); \ 59 expect_ ## func = called_ ## func = FALSE; \ 60 }while(0) 61 62 static const GUID CLSID_WineTestPSFactoryBuffer = { 0x22222222, 0x1234, 0x1234, { 0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0 } }; 63 static const GUID CLSID_DfMarshal = { 0x0000030b, 0x0000, 0x0000, { 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46 } }; 64 65 /* functions that are not present on all versions of Windows */ 66 static HRESULT (WINAPI * pCoInitializeEx)(LPVOID lpReserved, DWORD dwCoInit); 67 static HRESULT (WINAPI *pDllGetClassObject)(REFCLSID,REFIID,LPVOID); 68 69 /* helper macros to make tests a bit leaner */ 70 #define ok_more_than_one_lock() ok(cLocks > 0, "Number of locks should be > 0, but actually is %d\n", cLocks) 71 #define ok_no_locks() ok(cLocks == 0, "Number of locks should be 0, but actually is %d\n", cLocks) 72 #define ok_ole_success(hr, func) ok(hr == S_OK, #func " failed with error 0x%08x\n", hr) 73 #define ok_non_zero_external_conn() do {if (with_external_conn) ok(external_connections, "got no external connections\n");} while(0); 74 #define ok_zero_external_conn() do {if (with_external_conn) ok(!external_connections, "got %d external connections\n", external_connections);} while(0); 75 #define ok_last_release_closes(b) do {if (with_external_conn) ok(last_release_closes == b, "got %d expected %d\n", last_release_closes, b);} while(0); 76 77 #define OBJREF_SIGNATURE (0x574f454d) 78 #define OBJREF_STANDARD (0x1) 79 #define OBJREF_CUSTOM (0x4) 80 81 typedef struct tagDUALSTRINGARRAY { 82 unsigned short wNumEntries; 83 unsigned short wSecurityOffset; 84 unsigned short aStringArray[1]; 85 } DUALSTRINGARRAY; 86 87 typedef UINT64 OXID; 88 typedef UINT64 OID; 89 typedef GUID IPID; 90 91 typedef struct tagSTDOBJREF { 92 ULONG flags; 93 ULONG cPublicRefs; 94 OXID oxid; 95 OID oid; 96 IPID ipid; 97 } STDOBJREF; 98 99 typedef struct tagOBJREF { 100 ULONG signature; 101 ULONG flags; 102 GUID iid; 103 union { 104 struct OR_STANDARD { 105 STDOBJREF std; 106 DUALSTRINGARRAY saResAddr; 107 } u_standard; 108 struct OR_HANDLER { 109 STDOBJREF std; 110 CLSID clsid; 111 DUALSTRINGARRAY saResAddr; 112 } u_handler; 113 struct OR_CUSTOM { 114 CLSID clsid; 115 ULONG cbExtension; 116 ULONG size; 117 byte *pData; 118 } u_custom; 119 } u_objref; 120 } OBJREF; 121 122 static const IID IID_IWineTest = 123 { 124 0x5201163f, 125 0x8164, 126 0x4fd0, 127 {0xa1, 0xa2, 0x5d, 0x5a, 0x36, 0x54, 0xd3, 0xbd} 128 }; /* 5201163f-8164-4fd0-a1a2-5d5a3654d3bd */ 129 130 static const IID IID_IRemUnknown = 131 { 132 0x00000131, 133 0x0000, 134 0x0000, 135 {0xc0,0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46} 136 }; 137 138 #define EXTENTID_WineTest IID_IWineTest 139 #define CLSID_WineTest IID_IWineTest 140 141 static const CLSID CLSID_WineOOPTest = 142 { 143 0x5201163f, 144 0x8164, 145 0x4fd0, 146 {0xa1, 0xa2, 0x5d, 0x5a, 0x36, 0x54, 0xd3, 0xbd} 147 }; /* 5201163f-8164-4fd0-a1a2-5d5a3654d3bd */ 148 149 static void test_cocreateinstance_proxy(void) 150 { 151 IUnknown *pProxy; 152 IMultiQI *pMQI; 153 HRESULT hr; 154 155 pCoInitializeEx(NULL, COINIT_MULTITHREADED); 156 157 hr = CoCreateInstance(&CLSID_ShellDesktop, NULL, CLSCTX_INPROC, &IID_IUnknown, (void **)&pProxy); 158 ok_ole_success(hr, CoCreateInstance); 159 hr = IUnknown_QueryInterface(pProxy, &IID_IMultiQI, (void **)&pMQI); 160 ok(hr == S_OK, "created object is not a proxy, so was created in the wrong apartment\n"); 161 if (hr == S_OK) 162 IMultiQI_Release(pMQI); 163 IUnknown_Release(pProxy); 164 165 CoUninitialize(); 166 } 167 168 static const LARGE_INTEGER ullZero; 169 static LONG cLocks; 170 171 static void LockModule(void) 172 { 173 InterlockedIncrement(&cLocks); 174 } 175 176 static void UnlockModule(void) 177 { 178 InterlockedDecrement(&cLocks); 179 } 180 181 static BOOL with_external_conn; 182 static DWORD external_connections; 183 static BOOL last_release_closes; 184 185 static HRESULT WINAPI ExternalConnection_QueryInterface(IExternalConnection *iface, REFIID riid, void **ppv) 186 { 187 ok(0, "unexpected call\n"); 188 *ppv = NULL; 189 return E_NOINTERFACE; 190 } 191 192 static ULONG WINAPI ExternalConnection_AddRef(IExternalConnection *iface) 193 { 194 return 2; 195 } 196 197 static ULONG WINAPI ExternalConnection_Release(IExternalConnection *iface) 198 { 199 return 1; 200 } 201 202 static DWORD WINAPI ExternalConnection_AddConnection(IExternalConnection *iface, DWORD extconn, DWORD reserved) 203 { 204 trace("add connection\n"); 205 return ++external_connections; 206 } 207 208 209 static DWORD WINAPI ExternalConnection_ReleaseConnection(IExternalConnection *iface, DWORD extconn, 210 DWORD reserved, BOOL fLastReleaseCloses) 211 { 212 trace("release connection %d\n", fLastReleaseCloses); 213 last_release_closes = fLastReleaseCloses; 214 return --external_connections; 215 } 216 217 static const IExternalConnectionVtbl ExternalConnectionVtbl = { 218 ExternalConnection_QueryInterface, 219 ExternalConnection_AddRef, 220 ExternalConnection_Release, 221 ExternalConnection_AddConnection, 222 ExternalConnection_ReleaseConnection 223 }; 224 225 static IExternalConnection ExternalConnection = { &ExternalConnectionVtbl }; 226 227 228 static HRESULT WINAPI Test_IUnknown_QueryInterface( 229 LPUNKNOWN iface, 230 REFIID riid, 231 LPVOID *ppvObj) 232 { 233 if (ppvObj == NULL) return E_POINTER; 234 235 if (IsEqualGUID(riid, &IID_IUnknown)) 236 { 237 *ppvObj = iface; 238 IUnknown_AddRef(iface); 239 return S_OK; 240 } 241 242 *ppvObj = NULL; 243 return E_NOINTERFACE; 244 } 245 246 static ULONG WINAPI Test_IUnknown_AddRef(LPUNKNOWN iface) 247 { 248 LockModule(); 249 return 2; /* non-heap-based object */ 250 } 251 252 static ULONG WINAPI Test_IUnknown_Release(LPUNKNOWN iface) 253 { 254 UnlockModule(); 255 return 1; /* non-heap-based object */ 256 } 257 258 static const IUnknownVtbl TestUnknown_Vtbl = 259 { 260 Test_IUnknown_QueryInterface, 261 Test_IUnknown_AddRef, 262 Test_IUnknown_Release, 263 }; 264 265 static IUnknown Test_Unknown = { &TestUnknown_Vtbl }; 266 267 static ULONG WINAPI TestCrash_IUnknown_Release(LPUNKNOWN iface) 268 { 269 UnlockModule(); 270 if(!cLocks) { 271 trace("crashing...\n"); 272 *(int**)0xc = 0; 273 } 274 return 1; /* non-heap-based object */ 275 } 276 277 static const IUnknownVtbl TestCrashUnknown_Vtbl = 278 { 279 Test_IUnknown_QueryInterface, 280 Test_IUnknown_AddRef, 281 TestCrash_IUnknown_Release, 282 }; 283 284 static IUnknown TestCrash_Unknown = { &TestCrashUnknown_Vtbl }; 285 286 static HRESULT WINAPI Test_IClassFactory_QueryInterface( 287 LPCLASSFACTORY iface, 288 REFIID riid, 289 LPVOID *ppvObj) 290 { 291 if (ppvObj == NULL) return E_POINTER; 292 293 if (IsEqualGUID(riid, &IID_IUnknown) || 294 IsEqualGUID(riid, &IID_IClassFactory) || 295 /* the only other interface Wine is currently able to marshal (for testing two proxies) */ 296 IsEqualGUID(riid, &IID_IRemUnknown)) 297 { 298 *ppvObj = iface; 299 IClassFactory_AddRef(iface); 300 return S_OK; 301 } 302 303 if (with_external_conn && IsEqualGUID(riid, &IID_IExternalConnection)) 304 { 305 *ppvObj = &ExternalConnection; 306 return S_OK; 307 } 308 309 *ppvObj = NULL; 310 return E_NOINTERFACE; 311 } 312 313 static ULONG WINAPI Test_IClassFactory_AddRef(LPCLASSFACTORY iface) 314 { 315 LockModule(); 316 return 2; /* non-heap-based object */ 317 } 318 319 static ULONG WINAPI Test_IClassFactory_Release(LPCLASSFACTORY iface) 320 { 321 UnlockModule(); 322 return 1; /* non-heap-based object */ 323 } 324 325 static HRESULT WINAPI Test_IClassFactory_CreateInstance( 326 LPCLASSFACTORY iface, 327 LPUNKNOWN pUnkOuter, 328 REFIID riid, 329 LPVOID *ppvObj) 330 { 331 if (pUnkOuter) return CLASS_E_NOAGGREGATION; 332 return IUnknown_QueryInterface(&Test_Unknown, riid, ppvObj); 333 } 334 335 static HRESULT WINAPI Test_IClassFactory_LockServer( 336 LPCLASSFACTORY iface, 337 BOOL fLock) 338 { 339 return S_OK; 340 } 341 342 static const IClassFactoryVtbl TestClassFactory_Vtbl = 343 { 344 Test_IClassFactory_QueryInterface, 345 Test_IClassFactory_AddRef, 346 Test_IClassFactory_Release, 347 Test_IClassFactory_CreateInstance, 348 Test_IClassFactory_LockServer 349 }; 350 351 static IClassFactory Test_ClassFactory = { &TestClassFactory_Vtbl }; 352 353 DEFINE_EXPECT(Invoke); 354 DEFINE_EXPECT(CreateStub); 355 DEFINE_EXPECT(CreateProxy); 356 DEFINE_EXPECT(GetWindow); 357 DEFINE_EXPECT(Disconnect); 358 359 static HRESULT WINAPI OleWindow_QueryInterface(IOleWindow *iface, REFIID riid, void **ppv) 360 { 361 ok(0, "unexpected call %s\n", wine_dbgstr_guid(riid)); 362 *ppv = NULL; 363 return E_NOINTERFACE; 364 } 365 366 static ULONG WINAPI OleWindow_AddRef(IOleWindow *iface) 367 { 368 return 2; 369 } 370 371 static ULONG WINAPI OleWindow_Release(IOleWindow *iface) 372 { 373 return 1; 374 } 375 376 static HRESULT WINAPI OleWindow_GetWindow(IOleWindow *iface, HWND *hwnd) 377 { 378 CHECK_EXPECT(GetWindow); 379 *hwnd = (HWND)0xdeadbeef; 380 return S_OK; 381 } 382 383 static const IOleWindowVtbl OleWindowVtbl = { 384 OleWindow_QueryInterface, 385 OleWindow_AddRef, 386 OleWindow_Release, 387 OleWindow_GetWindow, 388 /* not needed */ 389 }; 390 391 static IOleWindow Test_OleWindow = { &OleWindowVtbl }; 392 393 static HRESULT WINAPI OleClientSite_QueryInterface(IOleClientSite *iface, REFIID riid, void **ppv) 394 { 395 if (IsEqualGUID(riid, &IID_IUnknown) || IsEqualGUID(riid, &IID_IOleClientSite)) 396 *ppv = iface; 397 else if (IsEqualGUID(riid, &IID_IOleWindow)) 398 *ppv = &Test_OleWindow; 399 else 400 { 401 *ppv = NULL; 402 return E_NOINTERFACE; 403 } 404 405 IUnknown_AddRef((IUnknown*)*ppv); 406 return S_OK; 407 } 408 409 static ULONG WINAPI OleClientSite_AddRef(IOleClientSite *iface) 410 { 411 return 2; 412 } 413 414 static ULONG WINAPI OleClientSite_Release(IOleClientSite *iface) 415 { 416 return 1; 417 } 418 419 static const IOleClientSiteVtbl OleClientSiteVtbl = { 420 OleClientSite_QueryInterface, 421 OleClientSite_AddRef, 422 OleClientSite_Release, 423 /* we don't need the rest, we never call it */ 424 }; 425 426 static IOleClientSite Test_OleClientSite = { &OleClientSiteVtbl }; 427 428 typedef struct { 429 IRpcStubBuffer IRpcStubBuffer_iface; 430 LONG ref; 431 IRpcStubBuffer *buffer; 432 } StubBufferWrapper; 433 434 static StubBufferWrapper *impl_from_IRpcStubBuffer(IRpcStubBuffer *iface) 435 { 436 return CONTAINING_RECORD(iface, StubBufferWrapper, IRpcStubBuffer_iface); 437 } 438 439 static HRESULT WINAPI RpcStubBuffer_QueryInterface(IRpcStubBuffer *iface, REFIID riid, void **ppv) 440 { 441 StubBufferWrapper *This = impl_from_IRpcStubBuffer(iface); 442 443 if(IsEqualGUID(&IID_IUnknown, riid) || IsEqualGUID(&IID_IRpcStubBuffer, riid)) { 444 *ppv = &This->IRpcStubBuffer_iface; 445 }else { 446 *ppv = NULL; 447 return E_NOINTERFACE; 448 } 449 450 IUnknown_AddRef((IUnknown*)*ppv); 451 return S_OK; 452 } 453 454 static ULONG WINAPI RpcStubBuffer_AddRef(IRpcStubBuffer *iface) 455 { 456 StubBufferWrapper *This = impl_from_IRpcStubBuffer(iface); 457 return InterlockedIncrement(&This->ref); 458 } 459 460 static ULONG WINAPI RpcStubBuffer_Release(IRpcStubBuffer *iface) 461 { 462 StubBufferWrapper *This = impl_from_IRpcStubBuffer(iface); 463 LONG ref = InterlockedDecrement(&This->ref); 464 if(!ref) { 465 IRpcStubBuffer_Release(This->buffer); 466 heap_free(This); 467 } 468 return ref; 469 } 470 471 static HRESULT WINAPI RpcStubBuffer_Connect(IRpcStubBuffer *iface, IUnknown *pUnkServer) 472 { 473 ok(0, "unexpected call\n"); 474 return E_NOTIMPL; 475 } 476 477 static void WINAPI RpcStubBuffer_Disconnect(IRpcStubBuffer *iface) 478 { 479 CHECK_EXPECT(Disconnect); 480 } 481 482 static HRESULT WINAPI RpcStubBuffer_Invoke(IRpcStubBuffer *iface, RPCOLEMESSAGE *_prpcmsg, 483 IRpcChannelBuffer *_pRpcChannelBuffer) 484 { 485 StubBufferWrapper *This = impl_from_IRpcStubBuffer(iface); 486 void *dest_context_data; 487 DWORD dest_context; 488 HRESULT hr; 489 490 CHECK_EXPECT(Invoke); 491 492 hr = IRpcChannelBuffer_GetDestCtx(_pRpcChannelBuffer, &dest_context, &dest_context_data); 493 ok(hr == S_OK, "GetDestCtx failed: %08x\n", hr); 494 ok(dest_context == MSHCTX_INPROC, "desc_context = %x\n", dest_context); 495 ok(!dest_context_data, "desc_context_data = %p\n", dest_context_data); 496 497 return IRpcStubBuffer_Invoke(This->buffer, _prpcmsg, _pRpcChannelBuffer); 498 } 499 500 static IRpcStubBuffer *WINAPI RpcStubBuffer_IsIIDSupported(IRpcStubBuffer *iface, REFIID riid) 501 { 502 ok(0, "unexpected call\n"); 503 return NULL; 504 } 505 506 static ULONG WINAPI RpcStubBuffer_CountRefs(IRpcStubBuffer *iface) 507 { 508 ok(0, "unexpected call\n"); 509 return E_NOTIMPL; 510 } 511 512 static HRESULT WINAPI RpcStubBuffer_DebugServerQueryInterface(IRpcStubBuffer *iface, void **ppv) 513 { 514 ok(0, "unexpected call\n"); 515 return E_NOTIMPL; 516 } 517 518 static void WINAPI RpcStubBuffer_DebugServerRelease(IRpcStubBuffer *iface, void *pv) 519 { 520 ok(0, "unexpected call\n"); 521 } 522 523 static const IRpcStubBufferVtbl RpcStubBufferVtbl = { 524 RpcStubBuffer_QueryInterface, 525 RpcStubBuffer_AddRef, 526 RpcStubBuffer_Release, 527 RpcStubBuffer_Connect, 528 RpcStubBuffer_Disconnect, 529 RpcStubBuffer_Invoke, 530 RpcStubBuffer_IsIIDSupported, 531 RpcStubBuffer_CountRefs, 532 RpcStubBuffer_DebugServerQueryInterface, 533 RpcStubBuffer_DebugServerRelease 534 }; 535 536 static IPSFactoryBuffer *ps_factory_buffer; 537 538 static HRESULT WINAPI PSFactoryBuffer_QueryInterface(IPSFactoryBuffer *iface, REFIID riid, void **ppv) 539 { 540 if (IsEqualIID(riid, &IID_IUnknown) || IsEqualIID(riid, &IID_IPSFactoryBuffer)) 541 *ppv = iface; 542 else 543 { 544 *ppv = NULL; 545 return E_NOINTERFACE; 546 } 547 IUnknown_AddRef((IUnknown*)*ppv); 548 return S_OK; 549 } 550 551 static ULONG WINAPI PSFactoryBuffer_AddRef(IPSFactoryBuffer *iface) 552 { 553 return 2; 554 } 555 556 static ULONG WINAPI PSFactoryBuffer_Release(IPSFactoryBuffer *iface) 557 { 558 return 1; 559 } 560 561 static HRESULT WINAPI PSFactoryBuffer_CreateProxy(IPSFactoryBuffer *iface, IUnknown *outer, 562 REFIID riid, IRpcProxyBuffer **ppProxy, void **ppv) 563 { 564 CHECK_EXPECT(CreateProxy); 565 return IPSFactoryBuffer_CreateProxy(ps_factory_buffer, outer, riid, ppProxy, ppv); 566 } 567 568 static HRESULT WINAPI PSFactoryBuffer_CreateStub(IPSFactoryBuffer *iface, REFIID riid, 569 IUnknown *server, IRpcStubBuffer **ppStub) 570 { 571 StubBufferWrapper *stub; 572 HRESULT hr; 573 574 CHECK_EXPECT(CreateStub); 575 576 ok(server == (IUnknown*)&Test_OleClientSite, "unexpected server %p\n", server); 577 578 stub = heap_alloc(sizeof(*stub)); 579 stub->IRpcStubBuffer_iface.lpVtbl = &RpcStubBufferVtbl; 580 stub->ref = 1; 581 582 hr = IPSFactoryBuffer_CreateStub(ps_factory_buffer, riid, server, &stub->buffer); 583 ok(hr == S_OK, "CreateStub failed: %08x\n", hr); 584 585 *ppStub = &stub->IRpcStubBuffer_iface; 586 return S_OK; 587 } 588 589 static IPSFactoryBufferVtbl PSFactoryBufferVtbl = 590 { 591 PSFactoryBuffer_QueryInterface, 592 PSFactoryBuffer_AddRef, 593 PSFactoryBuffer_Release, 594 PSFactoryBuffer_CreateProxy, 595 PSFactoryBuffer_CreateStub 596 }; 597 598 static IPSFactoryBuffer PSFactoryBuffer = { &PSFactoryBufferVtbl }; 599 600 #define RELEASEMARSHALDATA WM_USER 601 602 struct host_object_data 603 { 604 IStream *stream; 605 const IID *iid; 606 IUnknown *object; 607 MSHLFLAGS marshal_flags; 608 IMessageFilter *filter; 609 IUnknown *register_object; 610 const CLSID *register_clsid; 611 HANDLE marshal_event; 612 }; 613 614 #ifndef __REACTOS__ /* FIXME: Inspect */ 615 static IPSFactoryBuffer PSFactoryBuffer; 616 #endif 617 618 static DWORD CALLBACK host_object_proc(LPVOID p) 619 { 620 struct host_object_data *data = p; 621 DWORD registration_key; 622 HRESULT hr; 623 MSG msg; 624 625 pCoInitializeEx(NULL, COINIT_APARTMENTTHREADED); 626 627 if(data->register_object) { 628 hr = CoRegisterClassObject(data->register_clsid, data->register_object, 629 CLSCTX_INPROC_SERVER, REGCLS_MULTIPLEUSE, ®istration_key); 630 ok(hr == S_OK, "CoRegisterClassObject failed: %08x\n", hr); 631 } 632 633 if (data->filter) 634 { 635 IMessageFilter * prev_filter = NULL; 636 hr = CoRegisterMessageFilter(data->filter, &prev_filter); 637 if (prev_filter) IMessageFilter_Release(prev_filter); 638 ok_ole_success(hr, CoRegisterMessageFilter); 639 } 640 641 hr = CoMarshalInterface(data->stream, data->iid, data->object, MSHCTX_INPROC, NULL, data->marshal_flags); 642 ok_ole_success(hr, CoMarshalInterface); 643 644 /* force the message queue to be created before signaling parent thread */ 645 PeekMessageA(&msg, NULL, WM_USER, WM_USER, PM_NOREMOVE); 646 647 SetEvent(data->marshal_event); 648 649 while (GetMessageA(&msg, NULL, 0, 0)) 650 { 651 if (msg.hwnd == NULL && msg.message == RELEASEMARSHALDATA) 652 { 653 CoReleaseMarshalData(data->stream); 654 SetEvent((HANDLE)msg.lParam); 655 } 656 else 657 DispatchMessageA(&msg); 658 } 659 660 HeapFree(GetProcessHeap(), 0, data); 661 662 CoUninitialize(); 663 664 return hr; 665 } 666 667 static DWORD start_host_object2(struct host_object_data *object_data, HANDLE *thread) 668 { 669 DWORD tid = 0; 670 struct host_object_data *data; 671 672 data = HeapAlloc(GetProcessHeap(), 0, sizeof(*data)); 673 *data = *object_data; 674 data->marshal_event = CreateEventA(NULL, FALSE, FALSE, NULL); 675 *thread = CreateThread(NULL, 0, host_object_proc, data, 0, &tid); 676 677 /* wait for marshaling to complete before returning */ 678 ok( !WaitForSingleObject(data->marshal_event, 10000), "wait timed out\n" ); 679 CloseHandle(data->marshal_event); 680 681 return tid; 682 } 683 684 static DWORD start_host_object(IStream *stream, REFIID riid, IUnknown *object, MSHLFLAGS marshal_flags, HANDLE *thread) 685 { 686 struct host_object_data object_data = { stream, riid, object, marshal_flags }; 687 return start_host_object2(&object_data, thread); 688 } 689 690 /* asks thread to release the marshal data because it has to be done by the 691 * same thread that marshaled the interface in the first place. */ 692 static void release_host_object(DWORD tid, WPARAM wp) 693 { 694 HANDLE event = CreateEventA(NULL, FALSE, FALSE, NULL); 695 PostThreadMessageA(tid, RELEASEMARSHALDATA, wp, (LPARAM)event); 696 ok( !WaitForSingleObject(event, 10000), "wait timed out\n" ); 697 CloseHandle(event); 698 } 699 700 static void end_host_object(DWORD tid, HANDLE thread) 701 { 702 BOOL ret = PostThreadMessageA(tid, WM_QUIT, 0, 0); 703 ok(ret, "PostThreadMessage failed with error %d\n", GetLastError()); 704 /* be careful of races - don't return until hosting thread has terminated */ 705 ok( !WaitForSingleObject(thread, 10000), "wait timed out\n" ); 706 CloseHandle(thread); 707 } 708 709 /* tests failure case of interface not having a marshaler specified in the 710 * registry */ 711 static void test_no_marshaler(void) 712 { 713 IStream *pStream; 714 HRESULT hr; 715 716 hr = CreateStreamOnHGlobal(NULL, TRUE, &pStream); 717 ok_ole_success(hr, CreateStreamOnHGlobal); 718 hr = CoMarshalInterface(pStream, &IID_IWineTest, (IUnknown*)&Test_ClassFactory, MSHCTX_INPROC, NULL, MSHLFLAGS_NORMAL); 719 ok(hr == E_NOINTERFACE, "CoMarshalInterface should have returned E_NOINTERFACE instead of 0x%08x\n", hr); 720 721 IStream_Release(pStream); 722 } 723 724 /* tests normal marshal and then release without unmarshaling */ 725 static void test_normal_marshal_and_release(void) 726 { 727 HRESULT hr; 728 IStream *pStream = NULL; 729 730 cLocks = 0; 731 external_connections = 0; 732 733 hr = CreateStreamOnHGlobal(NULL, TRUE, &pStream); 734 ok_ole_success(hr, CreateStreamOnHGlobal); 735 hr = CoMarshalInterface(pStream, &IID_IClassFactory, (IUnknown*)&Test_ClassFactory, MSHCTX_INPROC, NULL, MSHLFLAGS_NORMAL); 736 ok_ole_success(hr, CoMarshalInterface); 737 738 ok_more_than_one_lock(); 739 ok_non_zero_external_conn(); 740 741 IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL); 742 hr = CoReleaseMarshalData(pStream); 743 ok_ole_success(hr, CoReleaseMarshalData); 744 IStream_Release(pStream); 745 746 ok_no_locks(); 747 ok_zero_external_conn(); 748 ok_last_release_closes(TRUE); 749 } 750 751 /* tests success case of a same-thread marshal and unmarshal */ 752 static void test_normal_marshal_and_unmarshal(void) 753 { 754 HRESULT hr; 755 IStream *pStream = NULL; 756 IUnknown *pProxy = NULL; 757 758 cLocks = 0; 759 external_connections = 0; 760 761 hr = CreateStreamOnHGlobal(NULL, TRUE, &pStream); 762 ok_ole_success(hr, CreateStreamOnHGlobal); 763 hr = CoMarshalInterface(pStream, &IID_IClassFactory, (IUnknown*)&Test_ClassFactory, MSHCTX_INPROC, NULL, MSHLFLAGS_NORMAL); 764 ok_ole_success(hr, CoMarshalInterface); 765 766 ok_more_than_one_lock(); 767 ok_non_zero_external_conn(); 768 769 IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL); 770 hr = CoUnmarshalInterface(pStream, &IID_IClassFactory, (void **)&pProxy); 771 ok_ole_success(hr, CoUnmarshalInterface); 772 IStream_Release(pStream); 773 774 ok_more_than_one_lock(); 775 ok_zero_external_conn(); 776 ok_last_release_closes(FALSE); 777 778 IUnknown_Release(pProxy); 779 780 ok_no_locks(); 781 } 782 783 /* tests failure case of unmarshaling a freed object */ 784 static void test_marshal_and_unmarshal_invalid(void) 785 { 786 HRESULT hr; 787 IStream *pStream = NULL; 788 IClassFactory *pProxy = NULL; 789 DWORD tid; 790 void * dummy; 791 HANDLE thread; 792 793 cLocks = 0; 794 external_connections = 0; 795 796 hr = CreateStreamOnHGlobal(NULL, TRUE, &pStream); 797 ok_ole_success(hr, CreateStreamOnHGlobal); 798 tid = start_host_object(pStream, &IID_IClassFactory, (IUnknown*)&Test_ClassFactory, MSHLFLAGS_NORMAL, &thread); 799 800 ok_more_than_one_lock(); 801 ok_non_zero_external_conn(); 802 803 IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL); 804 hr = CoReleaseMarshalData(pStream); 805 ok_ole_success(hr, CoReleaseMarshalData); 806 807 ok_no_locks(); 808 ok_zero_external_conn(); 809 ok_last_release_closes(TRUE); 810 811 IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL); 812 hr = CoUnmarshalInterface(pStream, &IID_IClassFactory, (void **)&pProxy); 813 todo_wine { ok_ole_success(hr, CoUnmarshalInterface); } 814 815 ok_no_locks(); 816 817 if (pProxy) 818 { 819 hr = IClassFactory_CreateInstance(pProxy, NULL, &IID_IUnknown, &dummy); 820 ok(hr == RPC_E_DISCONNECTED, "Remote call should have returned RPC_E_DISCONNECTED, instead of 0x%08x\n", hr); 821 822 IClassFactory_Release(pProxy); 823 } 824 825 IStream_Release(pStream); 826 827 end_host_object(tid, thread); 828 } 829 830 static void test_same_apartment_unmarshal_failure(void) 831 { 832 HRESULT hr; 833 IStream *pStream; 834 IUnknown *pProxy; 835 static const LARGE_INTEGER llZero; 836 837 cLocks = 0; 838 external_connections = 0; 839 840 hr = CreateStreamOnHGlobal(NULL, TRUE, &pStream); 841 ok_ole_success(hr, CreateStreamOnHGlobal); 842 843 hr = CoMarshalInterface(pStream, &IID_IUnknown, (IUnknown *)&Test_ClassFactory, MSHCTX_INPROC, NULL, MSHLFLAGS_NORMAL); 844 ok_ole_success(hr, CoMarshalInterface); 845 846 ok_more_than_one_lock(); 847 ok_non_zero_external_conn(); 848 849 hr = IStream_Seek(pStream, llZero, STREAM_SEEK_SET, NULL); 850 ok_ole_success(hr, IStream_Seek); 851 852 hr = CoUnmarshalInterface(pStream, &IID_IParseDisplayName, (void **)&pProxy); 853 ok(hr == E_NOINTERFACE, "CoUnmarshalInterface should have returned E_NOINTERFACE instead of 0x%08x\n", hr); 854 855 ok_no_locks(); 856 ok_zero_external_conn(); 857 ok_last_release_closes(FALSE); 858 859 IStream_Release(pStream); 860 } 861 862 /* tests success case of an interthread marshal */ 863 static void test_interthread_marshal_and_unmarshal(void) 864 { 865 HRESULT hr; 866 IStream *pStream = NULL; 867 IUnknown *pProxy = NULL; 868 DWORD tid; 869 HANDLE thread; 870 871 cLocks = 0; 872 external_connections = 0; 873 874 hr = CreateStreamOnHGlobal(NULL, TRUE, &pStream); 875 ok_ole_success(hr, CreateStreamOnHGlobal); 876 tid = start_host_object(pStream, &IID_IClassFactory, (IUnknown*)&Test_ClassFactory, MSHLFLAGS_NORMAL, &thread); 877 878 ok_more_than_one_lock(); 879 ok_non_zero_external_conn(); 880 881 IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL); 882 hr = CoUnmarshalInterface(pStream, &IID_IClassFactory, (void **)&pProxy); 883 ok_ole_success(hr, CoUnmarshalInterface); 884 IStream_Release(pStream); 885 886 ok_more_than_one_lock(); 887 ok_non_zero_external_conn(); 888 889 IUnknown_Release(pProxy); 890 891 ok_no_locks(); 892 ok_zero_external_conn(); 893 ok_last_release_closes(TRUE); 894 895 end_host_object(tid, thread); 896 } 897 898 /* the number of external references that Wine's proxy manager normally gives 899 * out, so we can test the border case of running out of references */ 900 #define NORMALEXTREFS 5 901 902 /* tests success case of an interthread marshal and then marshaling the proxy */ 903 static void test_proxy_marshal_and_unmarshal(void) 904 { 905 HRESULT hr; 906 IStream *pStream = NULL; 907 IUnknown *pProxy = NULL; 908 IUnknown *pProxy2 = NULL; 909 DWORD tid; 910 HANDLE thread; 911 int i; 912 913 cLocks = 0; 914 external_connections = 0; 915 916 hr = CreateStreamOnHGlobal(NULL, TRUE, &pStream); 917 ok_ole_success(hr, CreateStreamOnHGlobal); 918 tid = start_host_object(pStream, &IID_IClassFactory, (IUnknown*)&Test_ClassFactory, MSHLFLAGS_NORMAL, &thread); 919 920 ok_more_than_one_lock(); 921 ok_non_zero_external_conn(); 922 923 IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL); 924 hr = CoUnmarshalInterface(pStream, &IID_IClassFactory, (void **)&pProxy); 925 ok_ole_success(hr, CoUnmarshalInterface); 926 927 ok_more_than_one_lock(); 928 929 IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL); 930 /* marshal the proxy */ 931 hr = CoMarshalInterface(pStream, &IID_IClassFactory, pProxy, MSHCTX_INPROC, NULL, MSHLFLAGS_NORMAL); 932 ok_ole_success(hr, CoMarshalInterface); 933 934 ok_more_than_one_lock(); 935 936 /* marshal 5 more times to exhaust the normal external references of 5 */ 937 for (i = 0; i < NORMALEXTREFS; i++) 938 { 939 hr = CoMarshalInterface(pStream, &IID_IClassFactory, pProxy, MSHCTX_INPROC, NULL, MSHLFLAGS_NORMAL); 940 ok_ole_success(hr, CoMarshalInterface); 941 } 942 943 ok_more_than_one_lock(); 944 945 /* release the original proxy to test that we successfully keep the 946 * original object alive */ 947 IUnknown_Release(pProxy); 948 949 IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL); 950 hr = CoUnmarshalInterface(pStream, &IID_IClassFactory, (void **)&pProxy2); 951 ok_ole_success(hr, CoUnmarshalInterface); 952 953 ok_more_than_one_lock(); 954 ok_non_zero_external_conn(); 955 956 IUnknown_Release(pProxy2); 957 958 /* unmarshal all of the proxies to check that the object stub still exists */ 959 for (i = 0; i < NORMALEXTREFS; i++) 960 { 961 hr = CoUnmarshalInterface(pStream, &IID_IClassFactory, (void **)&pProxy2); 962 ok_ole_success(hr, CoUnmarshalInterface); 963 964 IUnknown_Release(pProxy2); 965 } 966 967 ok_no_locks(); 968 ok_zero_external_conn(); 969 ok_last_release_closes(TRUE); 970 971 IStream_Release(pStream); 972 973 end_host_object(tid, thread); 974 } 975 976 /* tests success case of an interthread marshal and then marshaling the proxy 977 * using an iid that hasn't previously been unmarshaled */ 978 static void test_proxy_marshal_and_unmarshal2(void) 979 { 980 HRESULT hr; 981 IStream *pStream = NULL; 982 IUnknown *pProxy = NULL; 983 IUnknown *pProxy2 = NULL; 984 DWORD tid; 985 HANDLE thread; 986 987 cLocks = 0; 988 external_connections = 0; 989 990 hr = CreateStreamOnHGlobal(NULL, TRUE, &pStream); 991 ok_ole_success(hr, CreateStreamOnHGlobal); 992 tid = start_host_object(pStream, &IID_IUnknown, (IUnknown*)&Test_ClassFactory, MSHLFLAGS_NORMAL, &thread); 993 994 ok_more_than_one_lock(); 995 ok_non_zero_external_conn(); 996 997 IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL); 998 hr = CoUnmarshalInterface(pStream, &IID_IUnknown, (void **)&pProxy); 999 ok_ole_success(hr, CoUnmarshalInterface); 1000 1001 ok_more_than_one_lock(); 1002 1003 IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL); 1004 /* marshal the proxy */ 1005 hr = CoMarshalInterface(pStream, &IID_IClassFactory, pProxy, MSHCTX_INPROC, NULL, MSHLFLAGS_NORMAL); 1006 ok_ole_success(hr, CoMarshalInterface); 1007 1008 ok_more_than_one_lock(); 1009 1010 IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL); 1011 /* unmarshal the second proxy to the object */ 1012 hr = CoUnmarshalInterface(pStream, &IID_IClassFactory, (void **)&pProxy2); 1013 ok_ole_success(hr, CoUnmarshalInterface); 1014 IStream_Release(pStream); 1015 1016 /* now the proxies should be as follows: 1017 * pProxy -> &Test_ClassFactory 1018 * pProxy2 -> &Test_ClassFactory 1019 * they should NOT be as follows: 1020 * pProxy -> &Test_ClassFactory 1021 * pProxy2 -> pProxy 1022 * the above can only really be tested by looking in +ole traces 1023 */ 1024 1025 ok_more_than_one_lock(); 1026 1027 IUnknown_Release(pProxy); 1028 1029 ok_more_than_one_lock(); 1030 ok_non_zero_external_conn(); 1031 1032 IUnknown_Release(pProxy2); 1033 1034 ok_no_locks(); 1035 ok_zero_external_conn(); 1036 ok_last_release_closes(TRUE); 1037 1038 end_host_object(tid, thread); 1039 } 1040 1041 /* tests success case of an interthread marshal and then table-weak-marshaling the proxy */ 1042 static void test_proxy_marshal_and_unmarshal_weak(void) 1043 { 1044 HRESULT hr; 1045 IStream *pStream = NULL; 1046 IUnknown *pProxy = NULL; 1047 IUnknown *pProxy2 = NULL; 1048 DWORD tid; 1049 HANDLE thread; 1050 1051 cLocks = 0; 1052 external_connections = 0; 1053 1054 hr = CreateStreamOnHGlobal(NULL, TRUE, &pStream); 1055 ok_ole_success(hr, CreateStreamOnHGlobal); 1056 tid = start_host_object(pStream, &IID_IClassFactory, (IUnknown*)&Test_ClassFactory, MSHLFLAGS_NORMAL, &thread); 1057 1058 ok_more_than_one_lock(); 1059 ok_non_zero_external_conn(); 1060 1061 IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL); 1062 hr = CoUnmarshalInterface(pStream, &IID_IClassFactory, (void **)&pProxy); 1063 ok_ole_success(hr, CoUnmarshalInterface); 1064 1065 ok_more_than_one_lock(); 1066 ok_non_zero_external_conn(); 1067 1068 IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL); 1069 /* marshal the proxy */ 1070 hr = CoMarshalInterface(pStream, &IID_IClassFactory, pProxy, MSHCTX_INPROC, NULL, MSHLFLAGS_TABLEWEAK); 1071 ok_ole_success(hr, CoMarshalInterface); 1072 1073 ok_more_than_one_lock(); 1074 ok_non_zero_external_conn(); 1075 1076 /* release the original proxy to test that we successfully keep the 1077 * original object alive */ 1078 IUnknown_Release(pProxy); 1079 1080 IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL); 1081 hr = CoUnmarshalInterface(pStream, &IID_IClassFactory, (void **)&pProxy2); 1082 todo_wine 1083 ok(hr == CO_E_OBJNOTREG, "CoUnmarshalInterface should return CO_E_OBJNOTREG instead of 0x%08x\n", hr); 1084 1085 ok_no_locks(); 1086 ok_zero_external_conn(); 1087 ok_last_release_closes(TRUE); 1088 1089 IStream_Release(pStream); 1090 1091 end_host_object(tid, thread); 1092 } 1093 1094 /* tests success case of an interthread marshal and then table-strong-marshaling the proxy */ 1095 static void test_proxy_marshal_and_unmarshal_strong(void) 1096 { 1097 HRESULT hr; 1098 IStream *pStream = NULL; 1099 IUnknown *pProxy = NULL; 1100 IUnknown *pProxy2 = NULL; 1101 DWORD tid; 1102 HANDLE thread; 1103 1104 cLocks = 0; 1105 external_connections = 0; 1106 1107 hr = CreateStreamOnHGlobal(NULL, TRUE, &pStream); 1108 ok_ole_success(hr, CreateStreamOnHGlobal); 1109 tid = start_host_object(pStream, &IID_IClassFactory, (IUnknown*)&Test_ClassFactory, MSHLFLAGS_NORMAL, &thread); 1110 1111 ok_more_than_one_lock(); 1112 ok_non_zero_external_conn(); 1113 1114 IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL); 1115 hr = CoUnmarshalInterface(pStream, &IID_IClassFactory, (void **)&pProxy); 1116 ok_ole_success(hr, CoUnmarshalInterface); 1117 1118 ok_more_than_one_lock(); 1119 ok_non_zero_external_conn(); 1120 1121 IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL); 1122 /* marshal the proxy */ 1123 hr = CoMarshalInterface(pStream, &IID_IClassFactory, pProxy, MSHCTX_INPROC, NULL, MSHLFLAGS_TABLESTRONG); 1124 ok(hr == S_OK /* WinNT */ || hr == E_INVALIDARG /* Win9x */, 1125 "CoMarshalInterface should have return S_OK or E_INVALIDARG instead of 0x%08x\n", hr); 1126 if (FAILED(hr)) 1127 { 1128 IUnknown_Release(pProxy); 1129 goto end; 1130 } 1131 1132 ok_more_than_one_lock(); 1133 ok_non_zero_external_conn(); 1134 1135 /* release the original proxy to test that we successfully keep the 1136 * original object alive */ 1137 IUnknown_Release(pProxy); 1138 1139 IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL); 1140 hr = CoUnmarshalInterface(pStream, &IID_IClassFactory, (void **)&pProxy2); 1141 ok_ole_success(hr, CoUnmarshalInterface); 1142 1143 ok_more_than_one_lock(); 1144 ok_non_zero_external_conn(); 1145 1146 IUnknown_Release(pProxy2); 1147 1148 ok_more_than_one_lock(); 1149 ok_non_zero_external_conn(); 1150 1151 end: 1152 IStream_Release(pStream); 1153 1154 end_host_object(tid, thread); 1155 1156 ok_no_locks(); 1157 todo_wine { 1158 ok_zero_external_conn(); 1159 ok_last_release_closes(FALSE); 1160 } 1161 } 1162 1163 /* tests that stubs are released when the containing apartment is destroyed */ 1164 static void test_marshal_stub_apartment_shutdown(void) 1165 { 1166 HRESULT hr; 1167 IStream *pStream = NULL; 1168 IUnknown *pProxy = NULL; 1169 DWORD tid; 1170 HANDLE thread; 1171 1172 cLocks = 0; 1173 external_connections = 0; 1174 1175 hr = CreateStreamOnHGlobal(NULL, TRUE, &pStream); 1176 ok_ole_success(hr, CreateStreamOnHGlobal); 1177 tid = start_host_object(pStream, &IID_IClassFactory, (IUnknown*)&Test_ClassFactory, MSHLFLAGS_NORMAL, &thread); 1178 1179 ok_more_than_one_lock(); 1180 ok_non_zero_external_conn(); 1181 1182 IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL); 1183 hr = CoUnmarshalInterface(pStream, &IID_IClassFactory, (void **)&pProxy); 1184 ok_ole_success(hr, CoUnmarshalInterface); 1185 IStream_Release(pStream); 1186 1187 ok_more_than_one_lock(); 1188 ok_non_zero_external_conn(); 1189 1190 end_host_object(tid, thread); 1191 1192 ok_no_locks(); 1193 todo_wine { 1194 ok_zero_external_conn(); 1195 ok_last_release_closes(FALSE); 1196 } 1197 1198 IUnknown_Release(pProxy); 1199 1200 ok_no_locks(); 1201 } 1202 1203 /* tests that proxies are released when the containing apartment is destroyed */ 1204 static void test_marshal_proxy_apartment_shutdown(void) 1205 { 1206 HRESULT hr; 1207 IStream *pStream = NULL; 1208 IClassFactory *proxy; 1209 IUnknown *unk; 1210 ULONG ref; 1211 DWORD tid; 1212 HANDLE thread; 1213 1214 cLocks = 0; 1215 external_connections = 0; 1216 1217 hr = CreateStreamOnHGlobal(NULL, TRUE, &pStream); 1218 ok_ole_success(hr, CreateStreamOnHGlobal); 1219 tid = start_host_object(pStream, &IID_IClassFactory, (IUnknown*)&Test_ClassFactory, MSHLFLAGS_NORMAL, &thread); 1220 1221 ok_more_than_one_lock(); 1222 ok_non_zero_external_conn(); 1223 1224 IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL); 1225 hr = CoUnmarshalInterface(pStream, &IID_IClassFactory, (void **)&proxy); 1226 ok_ole_success(hr, CoUnmarshalInterface); 1227 IStream_Release(pStream); 1228 1229 ok_more_than_one_lock(); 1230 ok_non_zero_external_conn(); 1231 1232 CoUninitialize(); 1233 1234 ok_no_locks(); 1235 ok_zero_external_conn(); 1236 ok_last_release_closes(TRUE); 1237 1238 hr = IClassFactory_CreateInstance(proxy, NULL, &IID_IUnknown, (void **)&unk); 1239 ok(hr == CO_E_OBJNOTCONNECTED, "got %#x\n", hr); 1240 1241 ref = IClassFactory_Release(proxy); 1242 ok(!ref, "got %d refs\n", ref); 1243 1244 ok_no_locks(); 1245 1246 end_host_object(tid, thread); 1247 1248 pCoInitializeEx(NULL, COINIT_APARTMENTTHREADED); 1249 } 1250 1251 /* tests that proxies are released when the containing mta apartment is destroyed */ 1252 static void test_marshal_proxy_mta_apartment_shutdown(void) 1253 { 1254 HRESULT hr; 1255 IStream *pStream = NULL; 1256 IUnknown *pProxy = NULL; 1257 DWORD tid; 1258 HANDLE thread; 1259 1260 CoUninitialize(); 1261 pCoInitializeEx(NULL, COINIT_MULTITHREADED); 1262 1263 cLocks = 0; 1264 external_connections = 0; 1265 1266 hr = CreateStreamOnHGlobal(NULL, TRUE, &pStream); 1267 ok_ole_success(hr, CreateStreamOnHGlobal); 1268 tid = start_host_object(pStream, &IID_IClassFactory, (IUnknown*)&Test_ClassFactory, MSHLFLAGS_NORMAL, &thread); 1269 1270 ok_more_than_one_lock(); 1271 ok_non_zero_external_conn(); 1272 1273 IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL); 1274 hr = CoUnmarshalInterface(pStream, &IID_IClassFactory, (void **)&pProxy); 1275 ok_ole_success(hr, CoUnmarshalInterface); 1276 IStream_Release(pStream); 1277 1278 ok_more_than_one_lock(); 1279 ok_non_zero_external_conn(); 1280 1281 CoUninitialize(); 1282 1283 ok_no_locks(); 1284 ok_zero_external_conn(); 1285 ok_last_release_closes(TRUE); 1286 1287 IUnknown_Release(pProxy); 1288 1289 ok_no_locks(); 1290 1291 end_host_object(tid, thread); 1292 1293 pCoInitializeEx(NULL, COINIT_APARTMENTTHREADED); 1294 } 1295 1296 static void test_marshal_channel_buffer(void) 1297 { 1298 DWORD registration_key; 1299 IUnknown *proxy = NULL; 1300 IOleWindow *ole_window; 1301 HWND hwnd; 1302 CLSID clsid; 1303 DWORD tid; 1304 HANDLE thread; 1305 HRESULT hr; 1306 1307 struct host_object_data object_data = { NULL, &IID_IOleClientSite, (IUnknown*)&Test_OleClientSite, 1308 MSHLFLAGS_NORMAL, NULL, (IUnknown*)&PSFactoryBuffer, 1309 &CLSID_WineTestPSFactoryBuffer }; 1310 1311 cLocks = 0; 1312 external_connections = 0; 1313 1314 hr = CoGetPSClsid(&IID_IOleWindow, &clsid); 1315 ok_ole_success(hr, "CoGetPSClsid"); 1316 1317 hr = CoGetClassObject(&clsid, CLSCTX_INPROC_SERVER, NULL, &IID_IPSFactoryBuffer, 1318 (void **)&ps_factory_buffer); 1319 ok_ole_success(hr, "CoGetClassObject"); 1320 1321 hr = CreateStreamOnHGlobal(NULL, TRUE, &object_data.stream); 1322 ok_ole_success(hr, CreateStreamOnHGlobal); 1323 tid = start_host_object2(&object_data, &thread); 1324 1325 IStream_Seek(object_data.stream, ullZero, STREAM_SEEK_SET, NULL); 1326 hr = CoUnmarshalInterface(object_data.stream, &IID_IUnknown, (void **)&proxy); 1327 ok_ole_success(hr, CoUnmarshalInterface); 1328 IStream_Release(object_data.stream); 1329 1330 hr = CoRegisterClassObject(&CLSID_WineTestPSFactoryBuffer, (IUnknown *)&PSFactoryBuffer, 1331 CLSCTX_INPROC_SERVER, REGCLS_MULTIPLEUSE, ®istration_key); 1332 ok(hr == S_OK, "CoRegisterClassObject failed: %08x\n", hr); 1333 1334 hr = CoRegisterPSClsid(&IID_IOleWindow, &CLSID_WineTestPSFactoryBuffer); 1335 ok(hr == S_OK, "CoRegisterPSClsid failed: %08x\n", hr); 1336 1337 SET_EXPECT(CreateStub); 1338 SET_EXPECT(CreateProxy); 1339 hr = IUnknown_QueryInterface(proxy, &IID_IOleWindow, (void**)&ole_window); 1340 ok(hr == S_OK, "Could not get IOleWindow iface: %08x\n", hr); 1341 CHECK_CALLED(CreateStub); 1342 CHECK_CALLED(CreateProxy); 1343 1344 SET_EXPECT(Invoke); 1345 SET_EXPECT(GetWindow); 1346 hr = IOleWindow_GetWindow(ole_window, &hwnd); 1347 ok(hr == S_OK, "GetWindow failed: %08x\n", hr); 1348 ok((DWORD)(DWORD_PTR)hwnd == 0xdeadbeef, "hwnd = %p\n", hwnd); 1349 CHECK_CALLED(Invoke); 1350 CHECK_CALLED(GetWindow); 1351 1352 IOleWindow_Release(ole_window); 1353 1354 SET_EXPECT(Disconnect); 1355 IUnknown_Release(proxy); 1356 todo_wine 1357 CHECK_CALLED(Disconnect); 1358 1359 hr = CoRevokeClassObject(registration_key); 1360 ok(hr == S_OK, "CoRevokeClassObject failed: %08x\n", hr); 1361 1362 end_host_object(tid, thread); 1363 } 1364 1365 static const CLSID *unmarshal_class; 1366 DEFINE_EXPECT(CustomMarshal_GetUnmarshalClass); 1367 DEFINE_EXPECT(CustomMarshal_GetMarshalSizeMax); 1368 DEFINE_EXPECT(CustomMarshal_MarshalInterface); 1369 1370 static HRESULT WINAPI CustomMarshal_QueryInterface(IMarshal *iface, REFIID riid, void **ppv) 1371 { 1372 if (IsEqualIID(riid, &IID_IUnknown) || IsEqualIID(riid, &IID_IMarshal)) { 1373 *ppv = iface; 1374 } 1375 else 1376 { 1377 *ppv = NULL; 1378 return E_NOINTERFACE; 1379 } 1380 IUnknown_AddRef((IUnknown*)*ppv); 1381 return S_OK; 1382 } 1383 1384 static ULONG WINAPI CustomMarshal_AddRef(IMarshal *iface) 1385 { 1386 return 2; 1387 } 1388 1389 static ULONG WINAPI CustomMarshal_Release(IMarshal *iface) 1390 { 1391 return 1; 1392 } 1393 1394 static HRESULT WINAPI CustomMarshal_GetUnmarshalClass(IMarshal *iface, REFIID riid, 1395 void *pv, DWORD dwDestContext, void *pvDestContext, DWORD mshlflags, CLSID *clsid) 1396 { 1397 CHECK_EXPECT(CustomMarshal_GetUnmarshalClass); 1398 *clsid = *unmarshal_class; 1399 return S_OK; 1400 } 1401 1402 static HRESULT WINAPI CustomMarshal_GetMarshalSizeMax(IMarshal *iface, REFIID riid, 1403 void *pv, DWORD dwDestContext, void *pvDestContext, DWORD mshlflags, DWORD *size) 1404 { 1405 CHECK_EXPECT(CustomMarshal_GetMarshalSizeMax); 1406 ok(size != NULL, "size = NULL\n"); 1407 1408 *size = 0; 1409 return S_OK; 1410 } 1411 1412 static HRESULT WINAPI CustomMarshal_MarshalInterface(IMarshal *iface, IStream *stream, 1413 REFIID riid, void *pv, DWORD dwDestContext, void *pvDestContext, DWORD mshlflags) 1414 { 1415 IMarshal *std_marshal; 1416 STATSTG stat; 1417 HRESULT hr; 1418 1419 CHECK_EXPECT(CustomMarshal_MarshalInterface); 1420 1421 if(unmarshal_class != &CLSID_StdMarshal) 1422 return S_OK; 1423 1424 hr = IStream_Stat(stream, &stat, STATFLAG_DEFAULT); 1425 ok_ole_success(hr, IStream_Stat); 1426 ok(U(stat.cbSize).LowPart == 0, "stream is not empty (%d)\n", U(stat.cbSize).LowPart); 1427 ok(U(stat.cbSize).HighPart == 0, "stream is not empty (%d)\n", U(stat.cbSize).HighPart); 1428 1429 hr = CoGetStandardMarshal(riid, (IUnknown*)iface, 1430 dwDestContext, NULL, mshlflags, &std_marshal); 1431 ok_ole_success(hr, CoGetStandardMarshal); 1432 hr = IMarshal_MarshalInterface(std_marshal, stream, riid, pv, 1433 dwDestContext, pvDestContext, mshlflags); 1434 ok_ole_success(hr, IMarshal_MarshalInterface); 1435 IMarshal_Release(std_marshal); 1436 1437 return S_OK; 1438 } 1439 1440 static HRESULT WINAPI CustomMarshal_UnmarshalInterface(IMarshal *iface, 1441 IStream *stream, REFIID riid, void **ppv) 1442 { 1443 ok(0, "unexpected call\n"); 1444 return E_NOTIMPL; 1445 } 1446 1447 static HRESULT WINAPI CustomMarshal_ReleaseMarshalData(IMarshal *iface, IStream *stream) 1448 { 1449 ok(0, "unexpected call\n"); 1450 return E_NOTIMPL; 1451 } 1452 1453 static HRESULT WINAPI CustomMarshal_DisconnectObject(IMarshal *iface, DWORD res) 1454 { 1455 ok(0, "unexpected call\n"); 1456 return E_NOTIMPL; 1457 } 1458 1459 static IMarshalVtbl CustomMarshalVtbl = 1460 { 1461 CustomMarshal_QueryInterface, 1462 CustomMarshal_AddRef, 1463 CustomMarshal_Release, 1464 CustomMarshal_GetUnmarshalClass, 1465 CustomMarshal_GetMarshalSizeMax, 1466 CustomMarshal_MarshalInterface, 1467 CustomMarshal_UnmarshalInterface, 1468 CustomMarshal_ReleaseMarshalData, 1469 CustomMarshal_DisconnectObject 1470 }; 1471 1472 static IMarshal CustomMarshal = { &CustomMarshalVtbl }; 1473 1474 static void test_StdMarshal_custom_marshaling(void) 1475 { 1476 IStream *stream; 1477 IUnknown *unk; 1478 DWORD size; 1479 HRESULT hr; 1480 1481 hr = CreateStreamOnHGlobal(NULL, TRUE, &stream); 1482 ok_ole_success(hr, CreateStreamOnHGlobal); 1483 1484 unmarshal_class = &CLSID_StdMarshal; 1485 SET_EXPECT(CustomMarshal_GetUnmarshalClass); 1486 SET_EXPECT(CustomMarshal_MarshalInterface); 1487 hr = CoMarshalInterface(stream, &IID_IUnknown, (IUnknown*)&CustomMarshal, 1488 MSHCTX_INPROC, NULL, MSHLFLAGS_NORMAL); 1489 ok_ole_success(hr, CoMarshalInterface); 1490 CHECK_CALLED(CustomMarshal_GetUnmarshalClass); 1491 CHECK_CALLED(CustomMarshal_MarshalInterface); 1492 1493 hr = IStream_Seek(stream, ullZero, STREAM_SEEK_SET, NULL); 1494 ok_ole_success(hr, IStream_Seek); 1495 hr = CoUnmarshalInterface(stream, &IID_IUnknown, (void**)&unk); 1496 ok_ole_success(hr, CoUnmarshalInterface); 1497 ok(unk == (IUnknown*)&CustomMarshal, "unk != &CustomMarshal\n"); 1498 IUnknown_Release(unk); 1499 IStream_Release(stream); 1500 1501 hr = CreateStreamOnHGlobal(NULL, TRUE, &stream); 1502 ok_ole_success(hr, CreateStreamOnHGlobal); 1503 1504 SET_EXPECT(CustomMarshal_GetUnmarshalClass); 1505 SET_EXPECT(CustomMarshal_MarshalInterface); 1506 hr = CoMarshalInterface(stream, &IID_IUnknown, (IUnknown*)&CustomMarshal, 1507 MSHCTX_INPROC, NULL, MSHLFLAGS_NORMAL); 1508 ok_ole_success(hr, CoMarshalInterface); 1509 CHECK_CALLED(CustomMarshal_GetUnmarshalClass); 1510 CHECK_CALLED(CustomMarshal_MarshalInterface); 1511 1512 hr = IStream_Seek(stream, ullZero, STREAM_SEEK_SET, NULL); 1513 ok_ole_success(hr, IStream_Seek); 1514 hr = CoReleaseMarshalData(stream); 1515 ok_ole_success(hr, CoReleaseMarshalData); 1516 IStream_Release(stream); 1517 1518 SET_EXPECT(CustomMarshal_GetMarshalSizeMax); 1519 hr = CoGetMarshalSizeMax(&size, &IID_IUnknown, (IUnknown*)&CustomMarshal, 1520 MSHCTX_INPROC, NULL, MSHLFLAGS_NORMAL); 1521 ok_ole_success(hr, CoGetMarshalSizeMax); 1522 CHECK_CALLED(CustomMarshal_GetMarshalSizeMax); 1523 ok(size == sizeof(OBJREF), "size = %d, expected %d\n", size, (int)sizeof(OBJREF)); 1524 } 1525 1526 static void test_DfMarshal_custom_marshaling(void) 1527 { 1528 DWORD size, read; 1529 IStream *stream; 1530 OBJREF objref; 1531 HRESULT hr; 1532 1533 hr = CreateStreamOnHGlobal(NULL, TRUE, &stream); 1534 ok_ole_success(hr, CreateStreamOnHGlobal); 1535 1536 unmarshal_class = &CLSID_DfMarshal; 1537 SET_EXPECT(CustomMarshal_GetUnmarshalClass); 1538 SET_EXPECT(CustomMarshal_GetMarshalSizeMax); 1539 SET_EXPECT(CustomMarshal_MarshalInterface); 1540 hr = CoMarshalInterface(stream, &IID_IUnknown, (IUnknown*)&CustomMarshal, 1541 MSHCTX_INPROC, NULL, MSHLFLAGS_NORMAL); 1542 ok_ole_success(hr, CoMarshalInterface); 1543 CHECK_CALLED(CustomMarshal_GetUnmarshalClass); 1544 CHECK_CALLED(CustomMarshal_GetMarshalSizeMax); 1545 CHECK_CALLED(CustomMarshal_MarshalInterface); 1546 1547 hr = IStream_Seek(stream, ullZero, STREAM_SEEK_SET, NULL); 1548 ok_ole_success(hr, IStream_Seek); 1549 size = FIELD_OFFSET(OBJREF, u_objref.u_custom.pData); 1550 hr = IStream_Read(stream, &objref, size, &read); 1551 ok_ole_success(hr, IStream_Read); 1552 ok(read == size, "read = %d, expected %d\n", read, size); 1553 ok(objref.signature == OBJREF_SIGNATURE, "objref.signature = %x\n", 1554 objref.signature); 1555 ok(objref.flags == OBJREF_CUSTOM, "objref.flags = %x\n", objref.flags); 1556 ok(IsEqualIID(&objref.iid, &IID_IUnknown), "objref.iid = %s\n", 1557 wine_dbgstr_guid(&objref.iid)); 1558 ok(IsEqualIID(&objref.u_objref.u_custom.clsid, &CLSID_DfMarshal), 1559 "custom.clsid = %s\n", wine_dbgstr_guid(&objref.u_objref.u_custom.clsid)); 1560 ok(!objref.u_objref.u_custom.cbExtension, "custom.cbExtension = %d\n", 1561 objref.u_objref.u_custom.cbExtension); 1562 ok(!objref.u_objref.u_custom.size, "custom.size = %d\n", 1563 objref.u_objref.u_custom.size); 1564 1565 IStream_Release(stream); 1566 1567 SET_EXPECT(CustomMarshal_GetMarshalSizeMax); 1568 hr = CoGetMarshalSizeMax(&size, &IID_IUnknown, (IUnknown*)&CustomMarshal, 1569 MSHCTX_INPROC, NULL, MSHLFLAGS_NORMAL); 1570 ok_ole_success(hr, CoGetMarshalSizeMax); 1571 CHECK_CALLED(CustomMarshal_GetMarshalSizeMax); 1572 ok(size == sizeof(OBJREF), "size = %d, expected %d\n", size, (int)sizeof(OBJREF)); 1573 } 1574 1575 static void test_CoGetStandardMarshal(void) 1576 { 1577 DUALSTRINGARRAY *dualstringarr; 1578 STDOBJREF *stdobjref; 1579 OBJREF objref; 1580 IMarshal *marshal; 1581 DWORD size, read; 1582 IStream *stream; 1583 IUnknown *unk; 1584 CLSID clsid; 1585 HRESULT hr; 1586 1587 hr = CreateStreamOnHGlobal(NULL, TRUE, &stream); 1588 ok_ole_success(hr, CreateStreamOnHGlobal); 1589 1590 hr = CoGetStandardMarshal(&IID_IUnknown, &Test_Unknown, 1591 MSHCTX_INPROC, NULL, MSHLFLAGS_NORMAL, &marshal); 1592 ok_ole_success(hr, CoGetStandardMarshal); 1593 1594 hr = IMarshal_GetUnmarshalClass(marshal, &IID_IUnknown, &Test_Unknown, 1595 MSHCTX_INPROC, NULL, MSHLFLAGS_NORMAL, &clsid); 1596 ok_ole_success(hr, IMarshal_GetUnmarshalClass); 1597 ok(IsEqualGUID(&clsid, &CLSID_StdMarshal), "clsid = %s\n", wine_dbgstr_guid(&clsid)); 1598 1599 hr = IMarshal_GetMarshalSizeMax(marshal, &IID_IUnknown, &Test_Unknown, 1600 MSHCTX_INPROC, NULL, MSHLFLAGS_NORMAL, &size); 1601 ok_ole_success(hr, IMarshal_GetMarshalSizeMax); 1602 hr = CoGetMarshalSizeMax(&read, &IID_IUnknown, &Test_Unknown, 1603 MSHCTX_INPROC, NULL, MSHLFLAGS_NORMAL); 1604 ok_ole_success(hr, CoGetMarshalSizeMax); 1605 ok(size == read, "IMarshal_GetMarshalSizeMax size = %d, expected %d\n", size, read); 1606 1607 hr = IMarshal_MarshalInterface(marshal, stream, &IID_IUnknown, 1608 &Test_Unknown, MSHCTX_INPROC, NULL, MSHLFLAGS_NORMAL); 1609 ok_ole_success(hr, IMarshal_MarshalInterface); 1610 1611 hr = IStream_Seek(stream, ullZero, STREAM_SEEK_SET, NULL); 1612 ok_ole_success(hr, IStream_Seek); 1613 size = FIELD_OFFSET(OBJREF, u_objref.u_standard.saResAddr.aStringArray); 1614 hr = IStream_Read(stream, &objref, size, &read); 1615 ok_ole_success(hr, IStream_Read); 1616 ok(read == size, "read = %d, expected %d\n", read, size); 1617 ok(objref.signature == OBJREF_SIGNATURE, "objref.signature = %x\n", 1618 objref.signature); 1619 ok(objref.flags == OBJREF_STANDARD, "objref.flags = %x\n", objref.flags); 1620 ok(IsEqualIID(&objref.iid, &IID_IUnknown), "objref.iid = %s\n", 1621 wine_dbgstr_guid(&objref.iid)); 1622 stdobjref = &objref.u_objref.u_standard.std; 1623 ok(stdobjref->flags == 0, "stdobjref.flags = %d\n", stdobjref->flags); 1624 ok(stdobjref->cPublicRefs == 5, "stdobjref.cPublicRefs = %d\n", 1625 stdobjref->cPublicRefs); 1626 dualstringarr = &objref.u_objref.u_standard.saResAddr; 1627 ok(dualstringarr->wNumEntries == 0, "dualstringarr.wNumEntries = %d\n", 1628 dualstringarr->wNumEntries); 1629 ok(dualstringarr->wSecurityOffset == 0, "dualstringarr.wSecurityOffset = %d\n", 1630 dualstringarr->wSecurityOffset); 1631 1632 hr = IStream_Seek(stream, ullZero, STREAM_SEEK_SET, NULL); 1633 ok_ole_success(hr, IStream_Seek); 1634 hr = IMarshal_UnmarshalInterface(marshal, stream, &IID_IUnknown, (void**)&unk); 1635 ok_ole_success(hr, IMarshal_UnmarshalInterface); 1636 IUnknown_Release(unk); 1637 1638 hr = IStream_Seek(stream, ullZero, STREAM_SEEK_SET, NULL); 1639 ok_ole_success(hr, IStream_Seek); 1640 hr = IMarshal_MarshalInterface(marshal, stream, &IID_IUnknown, 1641 &Test_Unknown, MSHCTX_INPROC, NULL, MSHLFLAGS_NORMAL); 1642 ok_ole_success(hr, IMarshal_MarshalInterface); 1643 1644 hr = IStream_Seek(stream, ullZero, STREAM_SEEK_SET, NULL); 1645 ok_ole_success(hr, IStream_Seek); 1646 hr = IMarshal_ReleaseMarshalData(marshal, stream); 1647 ok_ole_success(hr, IMarshal_ReleaseMarshalData); 1648 IStream_Release(stream); 1649 1650 IMarshal_Release(marshal); 1651 } 1652 struct ncu_params 1653 { 1654 LPSTREAM stream; 1655 HANDLE marshal_event; 1656 HANDLE unmarshal_event; 1657 }; 1658 1659 /* helper for test_no_couninitialize_server */ 1660 static DWORD CALLBACK no_couninitialize_server_proc(LPVOID p) 1661 { 1662 struct ncu_params *ncu_params = p; 1663 HRESULT hr; 1664 1665 pCoInitializeEx(NULL, COINIT_MULTITHREADED); 1666 1667 hr = CoMarshalInterface(ncu_params->stream, &IID_IClassFactory, (IUnknown*)&Test_ClassFactory, MSHCTX_INPROC, NULL, MSHLFLAGS_NORMAL); 1668 ok_ole_success(hr, CoMarshalInterface); 1669 1670 SetEvent(ncu_params->marshal_event); 1671 1672 ok( !WaitForSingleObject(ncu_params->unmarshal_event, 10000), "wait timed out\n" ); 1673 1674 /* die without calling CoUninitialize */ 1675 1676 return 0; 1677 } 1678 1679 /* tests apartment that an apartment with a stub is released without deadlock 1680 * if the owning thread exits */ 1681 static void test_no_couninitialize_server(void) 1682 { 1683 HRESULT hr; 1684 IStream *pStream = NULL; 1685 IUnknown *pProxy = NULL; 1686 DWORD tid; 1687 HANDLE thread; 1688 struct ncu_params ncu_params; 1689 1690 cLocks = 0; 1691 external_connections = 0; 1692 1693 ncu_params.marshal_event = CreateEventA(NULL, TRUE, FALSE, NULL); 1694 ncu_params.unmarshal_event = CreateEventA(NULL, TRUE, FALSE, NULL); 1695 1696 hr = CreateStreamOnHGlobal(NULL, TRUE, &pStream); 1697 ok_ole_success(hr, CreateStreamOnHGlobal); 1698 ncu_params.stream = pStream; 1699 1700 thread = CreateThread(NULL, 0, no_couninitialize_server_proc, &ncu_params, 0, &tid); 1701 1702 ok( !WaitForSingleObject(ncu_params.marshal_event, 10000), "wait timed out\n" ); 1703 ok_more_than_one_lock(); 1704 ok_non_zero_external_conn(); 1705 1706 IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL); 1707 hr = CoUnmarshalInterface(pStream, &IID_IClassFactory, (void **)&pProxy); 1708 ok_ole_success(hr, CoUnmarshalInterface); 1709 IStream_Release(pStream); 1710 1711 ok_more_than_one_lock(); 1712 ok_non_zero_external_conn(); 1713 1714 SetEvent(ncu_params.unmarshal_event); 1715 ok( !WaitForSingleObject(thread, 10000), "wait timed out\n" ); 1716 1717 ok_no_locks(); 1718 todo_wine { 1719 ok_zero_external_conn(); 1720 ok_last_release_closes(FALSE); 1721 } 1722 1723 CloseHandle(thread); 1724 CloseHandle(ncu_params.marshal_event); 1725 CloseHandle(ncu_params.unmarshal_event); 1726 1727 IUnknown_Release(pProxy); 1728 1729 ok_no_locks(); 1730 } 1731 1732 /* STA -> STA call during DLL_THREAD_DETACH */ 1733 static DWORD CALLBACK no_couninitialize_client_proc(LPVOID p) 1734 { 1735 struct ncu_params *ncu_params = p; 1736 HRESULT hr; 1737 IUnknown *pProxy = NULL; 1738 1739 pCoInitializeEx(NULL, COINIT_APARTMENTTHREADED); 1740 1741 hr = CoUnmarshalInterface(ncu_params->stream, &IID_IClassFactory, (void **)&pProxy); 1742 ok_ole_success(hr, CoUnmarshalInterface); 1743 IStream_Release(ncu_params->stream); 1744 1745 ok_more_than_one_lock(); 1746 1747 /* die without calling CoUninitialize */ 1748 1749 return 0; 1750 } 1751 1752 /* tests STA -> STA call during DLL_THREAD_DETACH doesn't deadlock */ 1753 static void test_no_couninitialize_client(void) 1754 { 1755 HRESULT hr; 1756 IStream *pStream = NULL; 1757 DWORD tid; 1758 DWORD host_tid; 1759 HANDLE thread; 1760 HANDLE host_thread; 1761 struct ncu_params ncu_params; 1762 1763 cLocks = 0; 1764 external_connections = 0; 1765 1766 hr = CreateStreamOnHGlobal(NULL, TRUE, &pStream); 1767 ok_ole_success(hr, CreateStreamOnHGlobal); 1768 ncu_params.stream = pStream; 1769 1770 /* NOTE: assumes start_host_object uses an STA to host the object, as MTAs 1771 * always deadlock when called from within DllMain */ 1772 host_tid = start_host_object(pStream, &IID_IClassFactory, (IUnknown *)&Test_ClassFactory, MSHLFLAGS_NORMAL, &host_thread); 1773 IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL); 1774 1775 ok_more_than_one_lock(); 1776 ok_non_zero_external_conn(); 1777 1778 thread = CreateThread(NULL, 0, no_couninitialize_client_proc, &ncu_params, 0, &tid); 1779 1780 ok( !WaitForSingleObject(thread, 10000), "wait timed out\n" ); 1781 CloseHandle(thread); 1782 1783 ok_no_locks(); 1784 ok_zero_external_conn(); 1785 ok_last_release_closes(TRUE); 1786 1787 end_host_object(host_tid, host_thread); 1788 } 1789 1790 static BOOL crash_thread_success; 1791 1792 static DWORD CALLBACK crash_couninitialize_proc(void *p) 1793 { 1794 IStream *stream; 1795 HRESULT hr; 1796 1797 cLocks = 0; 1798 1799 CoInitialize(NULL); 1800 1801 hr = CreateStreamOnHGlobal(NULL, TRUE, &stream); 1802 ok_ole_success(hr, CreateStreamOnHGlobal); 1803 1804 hr = CoMarshalInterface(stream, &IID_IUnknown, &TestCrash_Unknown, MSHCTX_INPROC, NULL, MSHLFLAGS_NORMAL); 1805 ok_ole_success(hr, CoMarshalInterface); 1806 1807 IStream_Seek(stream, ullZero, STREAM_SEEK_SET, NULL); 1808 1809 hr = CoReleaseMarshalData(stream); 1810 ok_ole_success(hr, CoReleaseMarshalData); 1811 1812 ok_no_locks(); 1813 1814 hr = CoMarshalInterface(stream, &IID_IUnknown, &TestCrash_Unknown, MSHCTX_INPROC, NULL, MSHLFLAGS_NORMAL); 1815 ok_ole_success(hr, CoMarshalInterface); 1816 1817 ok_more_than_one_lock(); 1818 1819 trace("CoUninitialize >>>\n"); 1820 CoUninitialize(); 1821 trace("CoUninitialize <<<\n"); 1822 1823 ok_no_locks(); 1824 1825 IStream_Release(stream); 1826 crash_thread_success = TRUE; 1827 return 0; 1828 } 1829 1830 static void test_crash_couninitialize(void) 1831 { 1832 HANDLE thread; 1833 DWORD tid; 1834 1835 if(!GetProcAddress(GetModuleHandleA("kernel32.dll"), "CreateActCtxW")) { 1836 win_skip("Skipping crash tests on win2k.\n"); 1837 return; 1838 } 1839 1840 crash_thread_success = FALSE; 1841 thread = CreateThread(NULL, 0, crash_couninitialize_proc, NULL, 0, &tid); 1842 ok(!WaitForSingleObject(thread, 10000), "wait timed out\n"); 1843 CloseHandle(thread); 1844 ok(crash_thread_success, "Crash thread failed\n"); 1845 } 1846 1847 /* tests success case of a same-thread table-weak marshal, unmarshal, unmarshal */ 1848 static void test_tableweak_marshal_and_unmarshal_twice(void) 1849 { 1850 HRESULT hr; 1851 IStream *pStream = NULL; 1852 IUnknown *pProxy1 = NULL; 1853 IUnknown *pProxy2 = NULL; 1854 DWORD tid; 1855 HANDLE thread; 1856 1857 cLocks = 0; 1858 external_connections = 0; 1859 1860 hr = CreateStreamOnHGlobal(NULL, TRUE, &pStream); 1861 ok_ole_success(hr, CreateStreamOnHGlobal); 1862 tid = start_host_object(pStream, &IID_IClassFactory, (IUnknown*)&Test_ClassFactory, MSHLFLAGS_TABLEWEAK, &thread); 1863 1864 ok_more_than_one_lock(); 1865 ok_zero_external_conn(); 1866 1867 IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL); 1868 hr = CoUnmarshalInterface(pStream, &IID_IClassFactory, (void **)&pProxy1); 1869 ok_ole_success(hr, CoUnmarshalInterface); 1870 1871 ok_more_than_one_lock(); 1872 ok_non_zero_external_conn(); 1873 1874 IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL); 1875 hr = CoUnmarshalInterface(pStream, &IID_IClassFactory, (void **)&pProxy2); 1876 ok_ole_success(hr, CoUnmarshalInterface); 1877 1878 ok_more_than_one_lock(); 1879 1880 IUnknown_Release(pProxy1); 1881 ok_non_zero_external_conn(); 1882 IUnknown_Release(pProxy2); 1883 ok_zero_external_conn(); 1884 ok_last_release_closes(TRUE); 1885 1886 /* When IExternalConnection is present COM's lifetime management 1887 * behaviour is altered; the remaining weak ref prevents stub shutdown. */ 1888 if (with_external_conn) 1889 { 1890 ok_more_than_one_lock(); 1891 IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL); 1892 release_host_object(tid, 0); 1893 } 1894 1895 /* Without IExternalConnection this line is shows the difference between weak and strong table marshaling 1896 * weak has cLocks == 0, strong has cLocks > 0. */ 1897 ok_no_locks(); 1898 1899 IStream_Release(pStream); 1900 end_host_object(tid, thread); 1901 } 1902 1903 /* tests releasing after unmarshaling one object */ 1904 static void test_tableweak_marshal_releasedata1(void) 1905 { 1906 HRESULT hr; 1907 IStream *pStream = NULL; 1908 IUnknown *pProxy1 = NULL; 1909 IUnknown *pProxy2 = NULL; 1910 DWORD tid; 1911 HANDLE thread; 1912 1913 cLocks = 0; 1914 external_connections = 0; 1915 1916 hr = CreateStreamOnHGlobal(NULL, TRUE, &pStream); 1917 ok_ole_success(hr, CreateStreamOnHGlobal); 1918 tid = start_host_object(pStream, &IID_IClassFactory, (IUnknown*)&Test_ClassFactory, MSHLFLAGS_TABLEWEAK, &thread); 1919 1920 ok_more_than_one_lock(); 1921 ok_zero_external_conn(); 1922 1923 IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL); 1924 hr = CoUnmarshalInterface(pStream, &IID_IClassFactory, (void **)&pProxy1); 1925 ok_ole_success(hr, CoUnmarshalInterface); 1926 1927 ok_more_than_one_lock(); 1928 ok_non_zero_external_conn(); 1929 1930 /* release the remaining reference on the object by calling 1931 * CoReleaseMarshalData in the hosting thread */ 1932 IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL); 1933 release_host_object(tid, 0); 1934 1935 ok_more_than_one_lock(); 1936 ok_non_zero_external_conn(); 1937 1938 IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL); 1939 hr = CoUnmarshalInterface(pStream, &IID_IClassFactory, (void **)&pProxy2); 1940 ok_ole_success(hr, CoUnmarshalInterface); 1941 IStream_Release(pStream); 1942 1943 ok_more_than_one_lock(); 1944 ok_non_zero_external_conn(); 1945 1946 IUnknown_Release(pProxy1); 1947 1948 if (pProxy2) 1949 { 1950 ok_non_zero_external_conn(); 1951 IUnknown_Release(pProxy2); 1952 } 1953 1954 /* this line is shows the difference between weak and strong table marshaling: 1955 * weak has cLocks == 0 1956 * strong has cLocks > 0 */ 1957 ok_no_locks(); 1958 ok_zero_external_conn(); 1959 ok_last_release_closes(TRUE); 1960 1961 end_host_object(tid, thread); 1962 } 1963 1964 /* tests releasing after unmarshaling one object */ 1965 static void test_tableweak_marshal_releasedata2(void) 1966 { 1967 HRESULT hr; 1968 IStream *pStream = NULL; 1969 IUnknown *pProxy = NULL; 1970 DWORD tid; 1971 HANDLE thread; 1972 1973 cLocks = 0; 1974 external_connections = 0; 1975 1976 hr = CreateStreamOnHGlobal(NULL, TRUE, &pStream); 1977 ok_ole_success(hr, CreateStreamOnHGlobal); 1978 tid = start_host_object(pStream, &IID_IClassFactory, (IUnknown*)&Test_ClassFactory, MSHLFLAGS_TABLEWEAK, &thread); 1979 1980 ok_more_than_one_lock(); 1981 ok_zero_external_conn(); 1982 1983 /* release the remaining reference on the object by calling 1984 * CoReleaseMarshalData in the hosting thread */ 1985 IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL); 1986 release_host_object(tid, 0); 1987 1988 ok_no_locks(); 1989 1990 IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL); 1991 hr = CoUnmarshalInterface(pStream, &IID_IClassFactory, (void **)&pProxy); 1992 todo_wine 1993 { 1994 ok(hr == CO_E_OBJNOTREG, 1995 "CoUnmarshalInterface should have failed with CO_E_OBJNOTREG, but returned 0x%08x instead\n", 1996 hr); 1997 } 1998 IStream_Release(pStream); 1999 2000 ok_no_locks(); 2001 ok_zero_external_conn(); 2002 2003 end_host_object(tid, thread); 2004 } 2005 2006 struct duo_marshal_data 2007 { 2008 MSHLFLAGS marshal_flags1, marshal_flags2; 2009 IStream *pStream1, *pStream2; 2010 HANDLE hReadyEvent; 2011 HANDLE hQuitEvent; 2012 }; 2013 2014 static DWORD CALLBACK duo_marshal_thread_proc(void *p) 2015 { 2016 HRESULT hr; 2017 struct duo_marshal_data *data = p; 2018 HANDLE hQuitEvent = data->hQuitEvent; 2019 MSG msg; 2020 2021 pCoInitializeEx(NULL, COINIT_APARTMENTTHREADED); 2022 2023 hr = CoMarshalInterface(data->pStream1, &IID_IClassFactory, (IUnknown*)&Test_ClassFactory, MSHCTX_INPROC, NULL, data->marshal_flags1); 2024 ok_ole_success(hr, "CoMarshalInterface"); 2025 2026 hr = CoMarshalInterface(data->pStream2, &IID_IClassFactory, (IUnknown*)&Test_ClassFactory, MSHCTX_INPROC, NULL, data->marshal_flags2); 2027 ok_ole_success(hr, "CoMarshalInterface"); 2028 2029 /* force the message queue to be created before signaling parent thread */ 2030 PeekMessageA(&msg, NULL, WM_USER, WM_USER, PM_NOREMOVE); 2031 2032 SetEvent(data->hReadyEvent); 2033 2034 while (WAIT_OBJECT_0 + 1 == MsgWaitForMultipleObjects(1, &hQuitEvent, FALSE, 10000, QS_ALLINPUT)) 2035 { 2036 while (PeekMessageA(&msg, NULL, 0, 0, PM_REMOVE)) 2037 { 2038 if (msg.hwnd == NULL && msg.message == RELEASEMARSHALDATA) 2039 { 2040 CoReleaseMarshalData(msg.wParam == 1 ? data->pStream1 : data->pStream2); 2041 SetEvent((HANDLE)msg.lParam); 2042 } 2043 else 2044 DispatchMessageA(&msg); 2045 } 2046 } 2047 CloseHandle(hQuitEvent); 2048 2049 CoUninitialize(); 2050 2051 return 0; 2052 } 2053 2054 /* tests interaction between table-weak and normal marshalling of an object */ 2055 static void test_tableweak_and_normal_marshal_and_unmarshal(void) 2056 { 2057 HRESULT hr; 2058 IUnknown *pProxyWeak = NULL; 2059 IUnknown *pProxyNormal = NULL; 2060 DWORD tid; 2061 HANDLE thread; 2062 struct duo_marshal_data data; 2063 2064 cLocks = 0; 2065 external_connections = 0; 2066 2067 data.hReadyEvent = CreateEventA(NULL, FALSE, FALSE, NULL); 2068 data.hQuitEvent = CreateEventA(NULL, FALSE, FALSE, NULL); 2069 data.marshal_flags1 = MSHLFLAGS_TABLEWEAK; 2070 data.marshal_flags2 = MSHLFLAGS_NORMAL; 2071 hr = CreateStreamOnHGlobal(NULL, TRUE, &data.pStream1); 2072 ok_ole_success(hr, CreateStreamOnHGlobal); 2073 hr = CreateStreamOnHGlobal(NULL, TRUE, &data.pStream2); 2074 ok_ole_success(hr, CreateStreamOnHGlobal); 2075 2076 thread = CreateThread(NULL, 0, duo_marshal_thread_proc, &data, 0, &tid); 2077 ok( !WaitForSingleObject(data.hReadyEvent, 10000), "wait timed out\n" ); 2078 CloseHandle(data.hReadyEvent); 2079 2080 ok_more_than_one_lock(); 2081 ok_non_zero_external_conn(); 2082 2083 /* weak */ 2084 IStream_Seek(data.pStream1, ullZero, STREAM_SEEK_SET, NULL); 2085 hr = CoUnmarshalInterface(data.pStream1, &IID_IClassFactory, (void **)&pProxyWeak); 2086 ok_ole_success(hr, CoUnmarshalInterface); 2087 2088 ok_more_than_one_lock(); 2089 2090 /* normal */ 2091 IStream_Seek(data.pStream2, ullZero, STREAM_SEEK_SET, NULL); 2092 hr = CoUnmarshalInterface(data.pStream2, &IID_IClassFactory, (void **)&pProxyNormal); 2093 ok_ole_success(hr, CoUnmarshalInterface); 2094 2095 ok_more_than_one_lock(); 2096 2097 IUnknown_Release(pProxyNormal); 2098 2099 ok_more_than_one_lock(); 2100 ok_non_zero_external_conn(); 2101 2102 IUnknown_Release(pProxyWeak); 2103 2104 ok_zero_external_conn(); 2105 ok_last_release_closes(TRUE); 2106 2107 /* When IExternalConnection is present COM's lifetime management 2108 * behaviour is altered; the remaining weak ref prevents stub shutdown. */ 2109 if (with_external_conn) 2110 { 2111 ok_more_than_one_lock(); 2112 IStream_Seek(data.pStream1, ullZero, STREAM_SEEK_SET, NULL); 2113 release_host_object(tid, 1); 2114 } 2115 ok_no_locks(); 2116 2117 IStream_Release(data.pStream1); 2118 IStream_Release(data.pStream2); 2119 2120 SetEvent(data.hQuitEvent); 2121 ok( !WaitForSingleObject(thread, 10000), "wait timed out\n" ); 2122 CloseHandle(thread); 2123 } 2124 2125 static void test_tableweak_and_normal_marshal_and_releasedata(void) 2126 { 2127 HRESULT hr; 2128 DWORD tid; 2129 HANDLE thread; 2130 struct duo_marshal_data data; 2131 2132 cLocks = 0; 2133 external_connections = 0; 2134 2135 data.hReadyEvent = CreateEventA(NULL, FALSE, FALSE, NULL); 2136 data.hQuitEvent = CreateEventA(NULL, FALSE, FALSE, NULL); 2137 data.marshal_flags1 = MSHLFLAGS_TABLEWEAK; 2138 data.marshal_flags2 = MSHLFLAGS_NORMAL; 2139 hr = CreateStreamOnHGlobal(NULL, TRUE, &data.pStream1); 2140 ok_ole_success(hr, CreateStreamOnHGlobal); 2141 hr = CreateStreamOnHGlobal(NULL, TRUE, &data.pStream2); 2142 ok_ole_success(hr, CreateStreamOnHGlobal); 2143 2144 thread = CreateThread(NULL, 0, duo_marshal_thread_proc, &data, 0, &tid); 2145 ok( !WaitForSingleObject(data.hReadyEvent, 10000), "wait timed out\n" ); 2146 CloseHandle(data.hReadyEvent); 2147 2148 ok_more_than_one_lock(); 2149 ok_non_zero_external_conn(); 2150 2151 /* release normal - which in the non-external conn case will free the object despite the weak ref. */ 2152 IStream_Seek(data.pStream2, ullZero, STREAM_SEEK_SET, NULL); 2153 release_host_object(tid, 2); 2154 2155 ok_zero_external_conn(); 2156 ok_last_release_closes(TRUE); 2157 2158 if (with_external_conn) 2159 { 2160 ok_more_than_one_lock(); 2161 IStream_Seek(data.pStream1, ullZero, STREAM_SEEK_SET, NULL); 2162 release_host_object(tid, 1); 2163 } 2164 2165 ok_no_locks(); 2166 2167 IStream_Release(data.pStream1); 2168 IStream_Release(data.pStream2); 2169 2170 SetEvent(data.hQuitEvent); 2171 ok( !WaitForSingleObject(thread, 10000), "wait timed out\n" ); 2172 CloseHandle(thread); 2173 } 2174 2175 static void test_two_tableweak_marshal_and_releasedata(void) 2176 { 2177 HRESULT hr; 2178 DWORD tid; 2179 HANDLE thread; 2180 struct duo_marshal_data data; 2181 2182 cLocks = 0; 2183 external_connections = 0; 2184 2185 data.hReadyEvent = CreateEventA(NULL, FALSE, FALSE, NULL); 2186 data.hQuitEvent = CreateEventA(NULL, FALSE, FALSE, NULL); 2187 data.marshal_flags1 = MSHLFLAGS_TABLEWEAK; 2188 data.marshal_flags2 = MSHLFLAGS_TABLEWEAK; 2189 hr = CreateStreamOnHGlobal(NULL, TRUE, &data.pStream1); 2190 ok_ole_success(hr, CreateStreamOnHGlobal); 2191 hr = CreateStreamOnHGlobal(NULL, TRUE, &data.pStream2); 2192 ok_ole_success(hr, CreateStreamOnHGlobal); 2193 2194 thread = CreateThread(NULL, 0, duo_marshal_thread_proc, &data, 0, &tid); 2195 ok( !WaitForSingleObject(data.hReadyEvent, 10000), "wait timed out\n" ); 2196 CloseHandle(data.hReadyEvent); 2197 2198 ok_more_than_one_lock(); 2199 ok_zero_external_conn(); 2200 2201 /* release one weak ref - the remaining weak ref will keep the obj alive */ 2202 IStream_Seek(data.pStream1, ullZero, STREAM_SEEK_SET, NULL); 2203 release_host_object(tid, 1); 2204 2205 ok_more_than_one_lock(); 2206 2207 IStream_Seek(data.pStream2, ullZero, STREAM_SEEK_SET, NULL); 2208 release_host_object(tid, 2); 2209 2210 ok_no_locks(); 2211 2212 IStream_Release(data.pStream1); 2213 IStream_Release(data.pStream2); 2214 2215 SetEvent(data.hQuitEvent); 2216 ok( !WaitForSingleObject(thread, 10000), "wait timed out\n" ); 2217 CloseHandle(thread); 2218 } 2219 2220 /* tests success case of a same-thread table-strong marshal, unmarshal, unmarshal */ 2221 static void test_tablestrong_marshal_and_unmarshal_twice(void) 2222 { 2223 HRESULT hr; 2224 IStream *pStream = NULL; 2225 IUnknown *pProxy1 = NULL; 2226 IUnknown *pProxy2 = NULL; 2227 DWORD tid; 2228 HANDLE thread; 2229 2230 cLocks = 0; 2231 external_connections = 0; 2232 2233 hr = CreateStreamOnHGlobal(NULL, TRUE, &pStream); 2234 ok_ole_success(hr, CreateStreamOnHGlobal); 2235 tid = start_host_object(pStream, &IID_IClassFactory, (IUnknown*)&Test_ClassFactory, MSHLFLAGS_TABLESTRONG, &thread); 2236 2237 ok_more_than_one_lock(); 2238 ok_non_zero_external_conn(); 2239 2240 IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL); 2241 hr = CoUnmarshalInterface(pStream, &IID_IClassFactory, (void **)&pProxy1); 2242 ok_ole_success(hr, CoUnmarshalInterface); 2243 2244 ok_more_than_one_lock(); 2245 2246 IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL); 2247 hr = CoUnmarshalInterface(pStream, &IID_IClassFactory, (void **)&pProxy2); 2248 ok_ole_success(hr, CoUnmarshalInterface); 2249 2250 ok_more_than_one_lock(); 2251 2252 if (pProxy1) IUnknown_Release(pProxy1); 2253 if (pProxy2) IUnknown_Release(pProxy2); 2254 2255 /* this line is shows the difference between weak and strong table marshaling: 2256 * weak has cLocks == 0 2257 * strong has cLocks > 0 */ 2258 ok_more_than_one_lock(); 2259 2260 /* release the remaining reference on the object by calling 2261 * CoReleaseMarshalData in the hosting thread */ 2262 IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL); 2263 release_host_object(tid, 0); 2264 IStream_Release(pStream); 2265 2266 ok_no_locks(); 2267 ok_zero_external_conn(); 2268 ok_last_release_closes(TRUE); 2269 2270 end_host_object(tid, thread); 2271 } 2272 2273 /* tests CoLockObjectExternal */ 2274 static void test_lock_object_external(void) 2275 { 2276 HRESULT hr; 2277 IStream *pStream = NULL; 2278 2279 cLocks = 0; 2280 external_connections = 0; 2281 2282 /* test the stub manager creation aspect of CoLockObjectExternal when the 2283 * object hasn't been marshaled yet */ 2284 CoLockObjectExternal((IUnknown*)&Test_ClassFactory, TRUE, TRUE); 2285 2286 ok_more_than_one_lock(); 2287 ok_non_zero_external_conn(); 2288 2289 CoDisconnectObject((IUnknown*)&Test_ClassFactory, 0); 2290 2291 ok_no_locks(); 2292 ok_non_zero_external_conn(); 2293 external_connections = 0; 2294 2295 /* test our empty stub manager being handled correctly in 2296 * CoMarshalInterface */ 2297 CoLockObjectExternal((IUnknown*)&Test_ClassFactory, TRUE, TRUE); 2298 2299 hr = CreateStreamOnHGlobal(NULL, TRUE, &pStream); 2300 ok_ole_success(hr, CreateStreamOnHGlobal); 2301 hr = CoMarshalInterface(pStream, &IID_IClassFactory, (IUnknown*)&Test_ClassFactory, MSHCTX_INPROC, NULL, MSHLFLAGS_NORMAL); 2302 ok_ole_success(hr, CoMarshalInterface); 2303 2304 CoLockObjectExternal((IUnknown*)&Test_ClassFactory, TRUE, TRUE); 2305 2306 ok_more_than_one_lock(); 2307 ok_non_zero_external_conn(); 2308 2309 IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL); 2310 hr = CoReleaseMarshalData(pStream); 2311 ok_ole_success(hr, CoReleaseMarshalData); 2312 IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL); 2313 2314 ok_more_than_one_lock(); 2315 ok_non_zero_external_conn(); 2316 ok_last_release_closes(TRUE); 2317 2318 CoLockObjectExternal((IUnknown*)&Test_ClassFactory, FALSE, TRUE); 2319 2320 ok_more_than_one_lock(); 2321 ok_non_zero_external_conn(); 2322 ok_last_release_closes(TRUE); 2323 2324 CoLockObjectExternal((IUnknown*)&Test_ClassFactory, FALSE, TRUE); 2325 2326 ok_no_locks(); 2327 ok_zero_external_conn(); 2328 ok_last_release_closes(TRUE); 2329 2330 /* test CoLockObjectExternal releases reference to object with 2331 * fLastUnlockReleases as TRUE and there are only strong references on 2332 * the object */ 2333 CoLockObjectExternal((IUnknown*)&Test_ClassFactory, TRUE, FALSE); 2334 2335 ok_more_than_one_lock(); 2336 ok_non_zero_external_conn(); 2337 2338 CoLockObjectExternal((IUnknown*)&Test_ClassFactory, FALSE, FALSE); 2339 2340 ok_no_locks(); 2341 ok_zero_external_conn(); 2342 ok_last_release_closes(FALSE); 2343 2344 /* test CoLockObjectExternal doesn't release the last reference to an 2345 * object with fLastUnlockReleases as TRUE and there is a weak reference 2346 * on the object */ 2347 hr = CoMarshalInterface(pStream, &IID_IClassFactory, (IUnknown*)&Test_ClassFactory, MSHCTX_INPROC, NULL, MSHLFLAGS_TABLEWEAK); 2348 ok_ole_success(hr, CoMarshalInterface); 2349 2350 ok_more_than_one_lock(); 2351 ok_zero_external_conn(); 2352 2353 CoLockObjectExternal((IUnknown*)&Test_ClassFactory, TRUE, FALSE); 2354 2355 ok_more_than_one_lock(); 2356 ok_non_zero_external_conn(); 2357 2358 CoLockObjectExternal((IUnknown*)&Test_ClassFactory, FALSE, FALSE); 2359 2360 ok_more_than_one_lock(); 2361 ok_zero_external_conn(); 2362 ok_last_release_closes(FALSE); 2363 2364 CoDisconnectObject((IUnknown*)&Test_ClassFactory, 0); 2365 2366 ok_no_locks(); 2367 2368 IStream_Release(pStream); 2369 } 2370 2371 /* tests disconnecting stubs */ 2372 static void test_disconnect_stub(void) 2373 { 2374 HRESULT hr; 2375 IStream *pStream = NULL; 2376 2377 cLocks = 0; 2378 external_connections = 0; 2379 2380 hr = CreateStreamOnHGlobal(NULL, TRUE, &pStream); 2381 ok_ole_success(hr, CreateStreamOnHGlobal); 2382 hr = CoMarshalInterface(pStream, &IID_IClassFactory, (IUnknown*)&Test_ClassFactory, MSHCTX_INPROC, NULL, MSHLFLAGS_NORMAL); 2383 ok_ole_success(hr, CoMarshalInterface); 2384 2385 ok_non_zero_external_conn(); 2386 2387 CoLockObjectExternal((IUnknown*)&Test_ClassFactory, TRUE, TRUE); 2388 2389 ok_more_than_one_lock(); 2390 ok_non_zero_external_conn(); 2391 2392 IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL); 2393 hr = CoReleaseMarshalData(pStream); 2394 ok_ole_success(hr, CoReleaseMarshalData); 2395 IStream_Release(pStream); 2396 2397 ok_more_than_one_lock(); 2398 ok_non_zero_external_conn(); 2399 2400 CoDisconnectObject((IUnknown*)&Test_ClassFactory, 0); 2401 2402 ok_no_locks(); 2403 ok_non_zero_external_conn(); 2404 2405 hr = CoDisconnectObject(NULL, 0); 2406 ok( hr == E_INVALIDARG, "wrong status %x\n", hr ); 2407 } 2408 2409 /* tests failure case of a same-thread marshal and unmarshal twice */ 2410 static void test_normal_marshal_and_unmarshal_twice(void) 2411 { 2412 HRESULT hr; 2413 IStream *pStream = NULL; 2414 IUnknown *pProxy1 = NULL; 2415 IUnknown *pProxy2 = NULL; 2416 2417 cLocks = 0; 2418 external_connections = 0; 2419 2420 hr = CreateStreamOnHGlobal(NULL, TRUE, &pStream); 2421 ok_ole_success(hr, CreateStreamOnHGlobal); 2422 hr = CoMarshalInterface(pStream, &IID_IClassFactory, (IUnknown*)&Test_ClassFactory, MSHCTX_INPROC, NULL, MSHLFLAGS_NORMAL); 2423 ok_ole_success(hr, CoMarshalInterface); 2424 2425 ok_more_than_one_lock(); 2426 ok_non_zero_external_conn(); 2427 2428 IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL); 2429 hr = CoUnmarshalInterface(pStream, &IID_IClassFactory, (void **)&pProxy1); 2430 ok_ole_success(hr, CoUnmarshalInterface); 2431 2432 ok_more_than_one_lock(); 2433 ok_zero_external_conn(); 2434 ok_last_release_closes(FALSE); 2435 2436 IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL); 2437 hr = CoUnmarshalInterface(pStream, &IID_IClassFactory, (void **)&pProxy2); 2438 ok(hr == CO_E_OBJNOTCONNECTED, 2439 "CoUnmarshalInterface should have failed with error CO_E_OBJNOTCONNECTED for double unmarshal, instead of 0x%08x\n", hr); 2440 2441 IStream_Release(pStream); 2442 2443 ok_more_than_one_lock(); 2444 2445 IUnknown_Release(pProxy1); 2446 2447 ok_no_locks(); 2448 } 2449 2450 /* tests success case of marshaling and unmarshaling an HRESULT */ 2451 static void test_hresult_marshaling(void) 2452 { 2453 HRESULT hr; 2454 HRESULT hr_marshaled = 0; 2455 IStream *pStream = NULL; 2456 static const HRESULT E_DEADBEEF = 0xdeadbeef; 2457 2458 hr = CreateStreamOnHGlobal(NULL, TRUE, &pStream); 2459 ok_ole_success(hr, CreateStreamOnHGlobal); 2460 2461 hr = CoMarshalHresult(pStream, E_DEADBEEF); 2462 ok_ole_success(hr, CoMarshalHresult); 2463 2464 IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL); 2465 hr = IStream_Read(pStream, &hr_marshaled, sizeof(HRESULT), NULL); 2466 ok_ole_success(hr, IStream_Read); 2467 2468 ok(hr_marshaled == E_DEADBEEF, "Didn't marshal HRESULT as expected: got value 0x%08x instead\n", hr_marshaled); 2469 2470 hr_marshaled = 0; 2471 IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL); 2472 hr = CoUnmarshalHresult(pStream, &hr_marshaled); 2473 ok_ole_success(hr, CoUnmarshalHresult); 2474 2475 ok(hr_marshaled == E_DEADBEEF, "Didn't marshal HRESULT as expected: got value 0x%08x instead\n", hr_marshaled); 2476 2477 IStream_Release(pStream); 2478 } 2479 2480 2481 /* helper for test_proxy_used_in_wrong_thread */ 2482 static DWORD CALLBACK bad_thread_proc(LPVOID p) 2483 { 2484 IClassFactory * cf = p; 2485 HRESULT hr; 2486 IUnknown * proxy = NULL; 2487 2488 hr = IClassFactory_CreateInstance(cf, NULL, &IID_IUnknown, (LPVOID*)&proxy); 2489 todo_wine 2490 ok(hr == CO_E_NOTINITIALIZED, 2491 "COM should have failed with CO_E_NOTINITIALIZED on using proxy without apartment, but instead returned 0x%08x\n", 2492 hr); 2493 2494 hr = IClassFactory_QueryInterface(cf, &IID_IMultiQI, (LPVOID *)&proxy); 2495 /* Win9x returns S_OK, whilst NT returns RPC_E_WRONG_THREAD */ 2496 trace("call to proxy's QueryInterface for local interface without apartment returned 0x%08x\n", hr); 2497 if (SUCCEEDED(hr)) 2498 IUnknown_Release(proxy); 2499 2500 hr = IClassFactory_QueryInterface(cf, &IID_IStream, (LPVOID *)&proxy); 2501 /* Win9x returns E_NOINTERFACE, whilst NT returns RPC_E_WRONG_THREAD */ 2502 trace("call to proxy's QueryInterface without apartment returned 0x%08x\n", hr); 2503 if (SUCCEEDED(hr)) 2504 IUnknown_Release(proxy); 2505 2506 pCoInitializeEx(NULL, COINIT_MULTITHREADED); 2507 2508 hr = IClassFactory_CreateInstance(cf, NULL, &IID_IUnknown, (LPVOID*)&proxy); 2509 if (proxy) IUnknown_Release(proxy); 2510 ok(hr == RPC_E_WRONG_THREAD, 2511 "COM should have failed with RPC_E_WRONG_THREAD on using proxy from wrong apartment, but instead returned 0x%08x\n", 2512 hr); 2513 2514 hr = IClassFactory_QueryInterface(cf, &IID_IStream, (LPVOID *)&proxy); 2515 /* Win9x returns E_NOINTERFACE, whilst NT returns RPC_E_WRONG_THREAD */ 2516 trace("call to proxy's QueryInterface from wrong apartment returned 0x%08x\n", hr); 2517 2518 /* now be really bad and release the proxy from the wrong apartment */ 2519 IClassFactory_Release(cf); 2520 2521 CoUninitialize(); 2522 2523 return 0; 2524 } 2525 2526 /* tests failure case of a using a proxy in the wrong apartment */ 2527 static void test_proxy_used_in_wrong_thread(void) 2528 { 2529 HRESULT hr; 2530 IStream *pStream = NULL; 2531 IUnknown *pProxy = NULL; 2532 DWORD tid, tid2; 2533 HANDLE thread; 2534 HANDLE host_thread; 2535 2536 cLocks = 0; 2537 2538 hr = CreateStreamOnHGlobal(NULL, TRUE, &pStream); 2539 ok_ole_success(hr, CreateStreamOnHGlobal); 2540 tid = start_host_object(pStream, &IID_IClassFactory, (IUnknown*)&Test_ClassFactory, MSHLFLAGS_NORMAL, &host_thread); 2541 2542 ok_more_than_one_lock(); 2543 2544 IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL); 2545 hr = CoUnmarshalInterface(pStream, &IID_IClassFactory, (void **)&pProxy); 2546 ok_ole_success(hr, CoUnmarshalInterface); 2547 IStream_Release(pStream); 2548 2549 ok_more_than_one_lock(); 2550 2551 /* do a call that will fail, but result in IRemUnknown being used by the proxy */ 2552 IUnknown_QueryInterface(pProxy, &IID_IStream, (LPVOID *)&pStream); 2553 2554 /* create a thread that we can misbehave in */ 2555 thread = CreateThread(NULL, 0, bad_thread_proc, pProxy, 0, &tid2); 2556 2557 ok( !WaitForSingleObject(thread, 10000), "wait timed out\n" ); 2558 CloseHandle(thread); 2559 2560 /* do release statement on Win9x that we should have done above */ 2561 if (!GetProcAddress(GetModuleHandleA("ole32"), "CoRegisterSurrogateEx")) 2562 IUnknown_Release(pProxy); 2563 2564 ok_no_locks(); 2565 2566 end_host_object(tid, host_thread); 2567 } 2568 2569 static HRESULT WINAPI MessageFilter_QueryInterface(IMessageFilter *iface, REFIID riid, void ** ppvObj) 2570 { 2571 if (ppvObj == NULL) return E_POINTER; 2572 2573 if (IsEqualGUID(riid, &IID_IUnknown) || 2574 IsEqualGUID(riid, &IID_IClassFactory)) 2575 { 2576 *ppvObj = iface; 2577 IMessageFilter_AddRef(iface); 2578 return S_OK; 2579 } 2580 2581 return E_NOINTERFACE; 2582 } 2583 2584 static ULONG WINAPI MessageFilter_AddRef(IMessageFilter *iface) 2585 { 2586 return 2; /* non-heap object */ 2587 } 2588 2589 static ULONG WINAPI MessageFilter_Release(IMessageFilter *iface) 2590 { 2591 return 1; /* non-heap object */ 2592 } 2593 2594 static DWORD WINAPI MessageFilter_HandleInComingCall( 2595 IMessageFilter *iface, 2596 DWORD dwCallType, 2597 HTASK threadIDCaller, 2598 DWORD dwTickCount, 2599 LPINTERFACEINFO lpInterfaceInfo) 2600 { 2601 static int callcount = 0; 2602 DWORD ret; 2603 trace("HandleInComingCall\n"); 2604 switch (callcount) 2605 { 2606 case 0: 2607 ret = SERVERCALL_REJECTED; 2608 break; 2609 case 1: 2610 ret = SERVERCALL_RETRYLATER; 2611 break; 2612 default: 2613 ret = SERVERCALL_ISHANDLED; 2614 break; 2615 } 2616 callcount++; 2617 return ret; 2618 } 2619 2620 static DWORD WINAPI MessageFilter_RetryRejectedCall( 2621 IMessageFilter *iface, 2622 HTASK threadIDCallee, 2623 DWORD dwTickCount, 2624 DWORD dwRejectType) 2625 { 2626 trace("RetryRejectedCall\n"); 2627 return 0; 2628 } 2629 2630 static DWORD WINAPI MessageFilter_MessagePending( 2631 IMessageFilter *iface, 2632 HTASK threadIDCallee, 2633 DWORD dwTickCount, 2634 DWORD dwPendingType) 2635 { 2636 trace("MessagePending\n"); 2637 return PENDINGMSG_WAITNOPROCESS; 2638 } 2639 2640 static const IMessageFilterVtbl MessageFilter_Vtbl = 2641 { 2642 MessageFilter_QueryInterface, 2643 MessageFilter_AddRef, 2644 MessageFilter_Release, 2645 MessageFilter_HandleInComingCall, 2646 MessageFilter_RetryRejectedCall, 2647 MessageFilter_MessagePending 2648 }; 2649 2650 static IMessageFilter MessageFilter = { &MessageFilter_Vtbl }; 2651 2652 static void test_message_filter(void) 2653 { 2654 HRESULT hr; 2655 IClassFactory *cf = NULL; 2656 DWORD tid; 2657 IUnknown *proxy = NULL; 2658 IMessageFilter *prev_filter = NULL; 2659 HANDLE thread; 2660 2661 struct host_object_data object_data = { NULL, &IID_IClassFactory, (IUnknown*)&Test_ClassFactory, 2662 MSHLFLAGS_NORMAL, &MessageFilter }; 2663 2664 cLocks = 0; 2665 2666 hr = CreateStreamOnHGlobal(NULL, TRUE, &object_data.stream); 2667 ok_ole_success(hr, CreateStreamOnHGlobal); 2668 tid = start_host_object2(&object_data, &thread); 2669 2670 ok_more_than_one_lock(); 2671 2672 IStream_Seek(object_data.stream, ullZero, STREAM_SEEK_SET, NULL); 2673 hr = CoUnmarshalInterface(object_data.stream, &IID_IClassFactory, (void **)&cf); 2674 ok_ole_success(hr, CoUnmarshalInterface); 2675 IStream_Release(object_data.stream); 2676 2677 ok_more_than_one_lock(); 2678 2679 hr = IClassFactory_CreateInstance(cf, NULL, &IID_IUnknown, (LPVOID*)&proxy); 2680 ok(hr == RPC_E_CALL_REJECTED, "Call should have returned RPC_E_CALL_REJECTED, but return 0x%08x instead\n", hr); 2681 if (proxy) IUnknown_Release(proxy); 2682 proxy = NULL; 2683 2684 hr = CoRegisterMessageFilter(&MessageFilter, &prev_filter); 2685 ok_ole_success(hr, CoRegisterMessageFilter); 2686 2687 hr = IClassFactory_CreateInstance(cf, NULL, &IID_IUnknown, (LPVOID*)&proxy); 2688 ok_ole_success(hr, IClassFactory_CreateInstance); 2689 2690 IUnknown_Release(proxy); 2691 2692 IClassFactory_Release(cf); 2693 2694 ok_no_locks(); 2695 2696 end_host_object(tid, thread); 2697 2698 hr = CoRegisterMessageFilter(prev_filter, NULL); 2699 ok_ole_success(hr, CoRegisterMessageFilter); 2700 } 2701 2702 /* test failure case of trying to unmarshal from bad stream */ 2703 static void test_bad_marshal_stream(void) 2704 { 2705 HRESULT hr; 2706 IStream *pStream = NULL; 2707 2708 hr = CreateStreamOnHGlobal(NULL, TRUE, &pStream); 2709 ok_ole_success(hr, CreateStreamOnHGlobal); 2710 hr = CoMarshalInterface(pStream, &IID_IClassFactory, (IUnknown*)&Test_ClassFactory, MSHCTX_INPROC, NULL, MSHLFLAGS_NORMAL); 2711 ok_ole_success(hr, CoMarshalInterface); 2712 2713 ok_more_than_one_lock(); 2714 2715 /* try to read beyond end of stream */ 2716 hr = CoReleaseMarshalData(pStream); 2717 ok(hr == STG_E_READFAULT, "Should have failed with STG_E_READFAULT, but returned 0x%08x instead\n", hr); 2718 2719 /* now release for real */ 2720 IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL); 2721 hr = CoReleaseMarshalData(pStream); 2722 ok_ole_success(hr, CoReleaseMarshalData); 2723 2724 IStream_Release(pStream); 2725 } 2726 2727 /* tests that proxies implement certain interfaces */ 2728 static void test_proxy_interfaces(void) 2729 { 2730 HRESULT hr; 2731 IStream *pStream = NULL; 2732 IUnknown *pProxy = NULL; 2733 IUnknown *pOtherUnknown = NULL; 2734 DWORD tid; 2735 HANDLE thread; 2736 2737 cLocks = 0; 2738 2739 hr = CreateStreamOnHGlobal(NULL, TRUE, &pStream); 2740 ok_ole_success(hr, CreateStreamOnHGlobal); 2741 tid = start_host_object(pStream, &IID_IClassFactory, (IUnknown*)&Test_ClassFactory, MSHLFLAGS_NORMAL, &thread); 2742 2743 ok_more_than_one_lock(); 2744 2745 IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL); 2746 hr = CoUnmarshalInterface(pStream, &IID_IUnknown, (void **)&pProxy); 2747 ok_ole_success(hr, CoUnmarshalInterface); 2748 IStream_Release(pStream); 2749 2750 ok_more_than_one_lock(); 2751 2752 hr = IUnknown_QueryInterface(pProxy, &IID_IUnknown, (LPVOID*)&pOtherUnknown); 2753 ok_ole_success(hr, IUnknown_QueryInterface IID_IUnknown); 2754 if (hr == S_OK) IUnknown_Release(pOtherUnknown); 2755 2756 hr = IUnknown_QueryInterface(pProxy, &IID_IClientSecurity, (LPVOID*)&pOtherUnknown); 2757 ok_ole_success(hr, IUnknown_QueryInterface IID_IClientSecurity); 2758 if (hr == S_OK) IUnknown_Release(pOtherUnknown); 2759 2760 hr = IUnknown_QueryInterface(pProxy, &IID_IMultiQI, (LPVOID*)&pOtherUnknown); 2761 ok_ole_success(hr, IUnknown_QueryInterface IID_IMultiQI); 2762 if (hr == S_OK) IUnknown_Release(pOtherUnknown); 2763 2764 hr = IUnknown_QueryInterface(pProxy, &IID_IMarshal, (LPVOID*)&pOtherUnknown); 2765 ok_ole_success(hr, IUnknown_QueryInterface IID_IMarshal); 2766 if (hr == S_OK) IUnknown_Release(pOtherUnknown); 2767 2768 /* IMarshal2 is also supported on NT-based systems, but is pretty much 2769 * useless as it has no more methods over IMarshal that it inherits from. */ 2770 2771 IUnknown_Release(pProxy); 2772 2773 ok_no_locks(); 2774 2775 end_host_object(tid, thread); 2776 } 2777 2778 typedef struct 2779 { 2780 IUnknown IUnknown_iface; 2781 ULONG refs; 2782 } HeapUnknown; 2783 2784 static inline HeapUnknown *impl_from_IUnknown(IUnknown *iface) 2785 { 2786 return CONTAINING_RECORD(iface, HeapUnknown, IUnknown_iface); 2787 } 2788 2789 static HRESULT WINAPI HeapUnknown_QueryInterface(IUnknown *iface, REFIID riid, void **ppv) 2790 { 2791 if (IsEqualIID(riid, &IID_IUnknown)) 2792 { 2793 IUnknown_AddRef(iface); 2794 *ppv = iface; 2795 return S_OK; 2796 } 2797 *ppv = NULL; 2798 return E_NOINTERFACE; 2799 } 2800 2801 static ULONG WINAPI HeapUnknown_AddRef(IUnknown *iface) 2802 { 2803 HeapUnknown *This = impl_from_IUnknown(iface); 2804 return InterlockedIncrement((LONG*)&This->refs); 2805 } 2806 2807 static ULONG WINAPI HeapUnknown_Release(IUnknown *iface) 2808 { 2809 HeapUnknown *This = impl_from_IUnknown(iface); 2810 ULONG refs = InterlockedDecrement((LONG*)&This->refs); 2811 if (!refs) HeapFree(GetProcessHeap(), 0, This); 2812 return refs; 2813 } 2814 2815 static const IUnknownVtbl HeapUnknown_Vtbl = 2816 { 2817 HeapUnknown_QueryInterface, 2818 HeapUnknown_AddRef, 2819 HeapUnknown_Release 2820 }; 2821 2822 static void test_proxybuffer(REFIID riid) 2823 { 2824 HRESULT hr; 2825 IPSFactoryBuffer *psfb; 2826 IRpcProxyBuffer *proxy; 2827 LPVOID lpvtbl; 2828 ULONG refs; 2829 CLSID clsid; 2830 HeapUnknown *pUnkOuter = HeapAlloc(GetProcessHeap(), 0, sizeof(*pUnkOuter)); 2831 2832 pUnkOuter->IUnknown_iface.lpVtbl = &HeapUnknown_Vtbl; 2833 pUnkOuter->refs = 1; 2834 2835 hr = CoGetPSClsid(riid, &clsid); 2836 ok_ole_success(hr, CoGetPSClsid); 2837 2838 hr = CoGetClassObject(&clsid, CLSCTX_INPROC_SERVER, NULL, &IID_IPSFactoryBuffer, (LPVOID*)&psfb); 2839 ok_ole_success(hr, CoGetClassObject); 2840 2841 hr = IPSFactoryBuffer_CreateProxy(psfb, &pUnkOuter->IUnknown_iface, riid, &proxy, &lpvtbl); 2842 ok_ole_success(hr, IPSFactoryBuffer_CreateProxy); 2843 ok(lpvtbl != NULL, "IPSFactoryBuffer_CreateProxy succeeded, but returned a NULL vtable!\n"); 2844 2845 /* release our reference to the outer unknown object - the PS factory 2846 * buffer will have AddRef's it in the CreateProxy call */ 2847 refs = IUnknown_Release(&pUnkOuter->IUnknown_iface); 2848 ok(refs == 1, "Ref count of outer unknown should have been 1 instead of %d\n", refs); 2849 2850 /* Not checking return, unreliable on native. Maybe it leaks references? */ 2851 IPSFactoryBuffer_Release(psfb); 2852 2853 refs = IUnknown_Release((IUnknown *)lpvtbl); 2854 ok(refs == 0, "Ref-count leak of %d on IRpcProxyBuffer\n", refs); 2855 2856 refs = IRpcProxyBuffer_Release(proxy); 2857 ok(refs == 0, "Ref-count leak of %d on IRpcProxyBuffer\n", refs); 2858 } 2859 2860 static void test_stubbuffer(REFIID riid) 2861 { 2862 HRESULT hr; 2863 IPSFactoryBuffer *psfb; 2864 IRpcStubBuffer *stub; 2865 ULONG refs; 2866 CLSID clsid; 2867 2868 cLocks = 0; 2869 2870 hr = CoGetPSClsid(riid, &clsid); 2871 ok_ole_success(hr, CoGetPSClsid); 2872 2873 hr = CoGetClassObject(&clsid, CLSCTX_INPROC_SERVER, NULL, &IID_IPSFactoryBuffer, (LPVOID*)&psfb); 2874 ok_ole_success(hr, CoGetClassObject); 2875 2876 hr = IPSFactoryBuffer_CreateStub(psfb, riid, (IUnknown*)&Test_ClassFactory, &stub); 2877 ok_ole_success(hr, IPSFactoryBuffer_CreateStub); 2878 2879 /* Not checking return, unreliable on native. Maybe it leaks references? */ 2880 IPSFactoryBuffer_Release(psfb); 2881 2882 ok_more_than_one_lock(); 2883 2884 IRpcStubBuffer_Disconnect(stub); 2885 2886 ok_no_locks(); 2887 2888 refs = IRpcStubBuffer_Release(stub); 2889 ok(refs == 0, "Ref-count leak of %d on IRpcProxyBuffer\n", refs); 2890 } 2891 2892 static HWND hwnd_app; 2893 2894 static HRESULT WINAPI TestRE_IClassFactory_CreateInstance( 2895 LPCLASSFACTORY iface, 2896 LPUNKNOWN pUnkOuter, 2897 REFIID riid, 2898 LPVOID *ppvObj) 2899 { 2900 DWORD_PTR res; 2901 if (IsEqualIID(riid, &IID_IWineTest)) 2902 { 2903 BOOL ret = SendMessageTimeoutA(hwnd_app, WM_NULL, 0, 0, SMTO_BLOCK, 5000, &res); 2904 ok(ret, "Timed out sending a message to originating window during RPC call\n"); 2905 } 2906 *ppvObj = NULL; 2907 return S_FALSE; 2908 } 2909 2910 static const IClassFactoryVtbl TestREClassFactory_Vtbl = 2911 { 2912 Test_IClassFactory_QueryInterface, 2913 Test_IClassFactory_AddRef, 2914 Test_IClassFactory_Release, 2915 TestRE_IClassFactory_CreateInstance, 2916 Test_IClassFactory_LockServer 2917 }; 2918 2919 static IClassFactory TestRE_ClassFactory = { &TestREClassFactory_Vtbl }; 2920 2921 static LRESULT CALLBACK window_proc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam) 2922 { 2923 switch (msg) 2924 { 2925 case WM_USER: 2926 { 2927 HRESULT hr; 2928 IStream *pStream = NULL; 2929 IClassFactory *proxy = NULL; 2930 IUnknown *object; 2931 DWORD tid; 2932 HANDLE thread; 2933 2934 cLocks = 0; 2935 2936 hr = CreateStreamOnHGlobal(NULL, TRUE, &pStream); 2937 ok_ole_success(hr, CreateStreamOnHGlobal); 2938 tid = start_host_object(pStream, &IID_IClassFactory, (IUnknown*)&TestRE_ClassFactory, MSHLFLAGS_NORMAL, &thread); 2939 2940 ok_more_than_one_lock(); 2941 2942 IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL); 2943 hr = CoUnmarshalInterface(pStream, &IID_IClassFactory, (void **)&proxy); 2944 ok_ole_success(hr, CoReleaseMarshalData); 2945 IStream_Release(pStream); 2946 2947 ok_more_than_one_lock(); 2948 2949 /* note the use of the magic IID_IWineTest value to tell remote thread 2950 * to try to send a message back to us */ 2951 hr = IClassFactory_CreateInstance(proxy, NULL, &IID_IWineTest, (void **)&object); 2952 ok(hr == S_FALSE, "expected S_FALSE, got %d\n", hr); 2953 2954 IClassFactory_Release(proxy); 2955 2956 ok_no_locks(); 2957 2958 end_host_object(tid, thread); 2959 2960 PostMessageA(hwnd, WM_QUIT, 0, 0); 2961 2962 return 0; 2963 } 2964 case WM_USER+1: 2965 { 2966 HRESULT hr; 2967 IStream *pStream = NULL; 2968 IClassFactory *proxy = NULL; 2969 IUnknown *object; 2970 DWORD tid; 2971 HANDLE thread; 2972 2973 cLocks = 0; 2974 2975 hr = CreateStreamOnHGlobal(NULL, TRUE, &pStream); 2976 ok_ole_success(hr, CreateStreamOnHGlobal); 2977 tid = start_host_object(pStream, &IID_IClassFactory, (IUnknown*)&TestRE_ClassFactory, MSHLFLAGS_NORMAL, &thread); 2978 2979 ok_more_than_one_lock(); 2980 2981 IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL); 2982 hr = CoUnmarshalInterface(pStream, &IID_IClassFactory, (void **)&proxy); 2983 ok_ole_success(hr, CoReleaseMarshalData); 2984 IStream_Release(pStream); 2985 2986 ok_more_than_one_lock(); 2987 2988 /* post quit message before a doing a COM call to show that a pending 2989 * WM_QUIT message doesn't stop the call from succeeding */ 2990 PostMessageA(hwnd, WM_QUIT, 0, 0); 2991 hr = IClassFactory_CreateInstance(proxy, NULL, &IID_IUnknown, (void **)&object); 2992 ok(hr == S_FALSE, "IClassFactory_CreateInstance returned 0x%08x, expected S_FALSE\n", hr); 2993 2994 IClassFactory_Release(proxy); 2995 2996 ok_no_locks(); 2997 2998 end_host_object(tid, thread); 2999 3000 return 0; 3001 } 3002 case WM_USER+2: 3003 { 3004 HRESULT hr; 3005 IStream *pStream = NULL; 3006 IClassFactory *proxy = NULL; 3007 IUnknown *object; 3008 DWORD tid; 3009 HANDLE thread; 3010 3011 hr = CreateStreamOnHGlobal(NULL, TRUE, &pStream); 3012 ok_ole_success(hr, CreateStreamOnHGlobal); 3013 tid = start_host_object(pStream, &IID_IClassFactory, (IUnknown*)&Test_ClassFactory, MSHLFLAGS_NORMAL, &thread); 3014 3015 IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL); 3016 hr = CoUnmarshalInterface(pStream, &IID_IClassFactory, (void **)&proxy); 3017 ok_ole_success(hr, CoReleaseMarshalData); 3018 IStream_Release(pStream); 3019 3020 /* shows that COM calls executed during the processing of sent 3021 * messages should fail */ 3022 hr = IClassFactory_CreateInstance(proxy, NULL, &IID_IUnknown, (void **)&object); 3023 ok(hr == RPC_E_CANTCALLOUT_ININPUTSYNCCALL, 3024 "COM call during processing of sent message should return RPC_E_CANTCALLOUT_ININPUTSYNCCALL instead of 0x%08x\n", hr); 3025 3026 IClassFactory_Release(proxy); 3027 3028 end_host_object(tid, thread); 3029 3030 PostQuitMessage(0); 3031 3032 return 0; 3033 } 3034 default: 3035 return DefWindowProcA(hwnd, msg, wparam, lparam); 3036 } 3037 } 3038 3039 static void register_test_window(void) 3040 { 3041 WNDCLASSA wndclass; 3042 3043 memset(&wndclass, 0, sizeof(wndclass)); 3044 wndclass.lpfnWndProc = window_proc; 3045 wndclass.lpszClassName = "WineCOMTest"; 3046 RegisterClassA(&wndclass); 3047 } 3048 3049 static void test_message_reentrancy(void) 3050 { 3051 MSG msg; 3052 3053 hwnd_app = CreateWindowA("WineCOMTest", NULL, 0, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, NULL, NULL, NULL, 0); 3054 ok(hwnd_app != NULL, "Window creation failed\n"); 3055 3056 /* start message re-entrancy test */ 3057 PostMessageA(hwnd_app, WM_USER, 0, 0); 3058 3059 while (GetMessageA(&msg, NULL, 0, 0)) 3060 { 3061 TranslateMessage(&msg); 3062 DispatchMessageA(&msg); 3063 } 3064 DestroyWindow(hwnd_app); 3065 } 3066 3067 static HRESULT WINAPI TestMsg_IClassFactory_CreateInstance( 3068 LPCLASSFACTORY iface, 3069 LPUNKNOWN pUnkOuter, 3070 REFIID riid, 3071 LPVOID *ppvObj) 3072 { 3073 *ppvObj = NULL; 3074 SendMessageA(hwnd_app, WM_USER+2, 0, 0); 3075 return S_OK; 3076 } 3077 3078 static IClassFactoryVtbl TestMsgClassFactory_Vtbl = 3079 { 3080 Test_IClassFactory_QueryInterface, 3081 Test_IClassFactory_AddRef, 3082 Test_IClassFactory_Release, 3083 TestMsg_IClassFactory_CreateInstance, 3084 Test_IClassFactory_LockServer 3085 }; 3086 3087 static IClassFactory TestMsg_ClassFactory = { &TestMsgClassFactory_Vtbl }; 3088 3089 static void test_call_from_message(void) 3090 { 3091 MSG msg; 3092 IStream *pStream; 3093 HRESULT hr; 3094 IClassFactory *proxy; 3095 DWORD tid; 3096 HANDLE thread; 3097 IUnknown *object; 3098 3099 hwnd_app = CreateWindowA("WineCOMTest", NULL, 0, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, NULL, NULL, NULL, 0); 3100 ok(hwnd_app != NULL, "Window creation failed\n"); 3101 3102 hr = CreateStreamOnHGlobal(NULL, TRUE, &pStream); 3103 ok_ole_success(hr, CreateStreamOnHGlobal); 3104 tid = start_host_object(pStream, &IID_IClassFactory, (IUnknown*)&TestMsg_ClassFactory, MSHLFLAGS_NORMAL, &thread); 3105 3106 ok_more_than_one_lock(); 3107 3108 IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL); 3109 hr = CoUnmarshalInterface(pStream, &IID_IClassFactory, (void **)&proxy); 3110 ok_ole_success(hr, CoReleaseMarshalData); 3111 IStream_Release(pStream); 3112 3113 ok_more_than_one_lock(); 3114 3115 /* start message re-entrancy test */ 3116 hr = IClassFactory_CreateInstance(proxy, NULL, &IID_IUnknown, (void **)&object); 3117 ok_ole_success(hr, IClassFactory_CreateInstance); 3118 3119 IClassFactory_Release(proxy); 3120 3121 ok_no_locks(); 3122 3123 end_host_object(tid, thread); 3124 3125 while (GetMessageA(&msg, NULL, 0, 0)) 3126 { 3127 TranslateMessage(&msg); 3128 DispatchMessageA(&msg); 3129 } 3130 DestroyWindow(hwnd_app); 3131 } 3132 3133 static void test_WM_QUIT_handling(void) 3134 { 3135 MSG msg; 3136 3137 hwnd_app = CreateWindowA("WineCOMTest", NULL, 0, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, NULL, NULL, NULL, 0); 3138 ok(hwnd_app != NULL, "Window creation failed\n"); 3139 3140 /* start WM_QUIT handling test */ 3141 PostMessageA(hwnd_app, WM_USER+1, 0, 0); 3142 3143 while (GetMessageA(&msg, NULL, 0, 0)) 3144 { 3145 TranslateMessage(&msg); 3146 DispatchMessageA(&msg); 3147 } 3148 } 3149 3150 static SIZE_T round_global_size(SIZE_T size) 3151 { 3152 static SIZE_T global_size_alignment = -1; 3153 if (global_size_alignment == -1) 3154 { 3155 void *p = GlobalAlloc(GMEM_FIXED, 1); 3156 global_size_alignment = GlobalSize(p); 3157 GlobalFree(p); 3158 } 3159 3160 return ((size + global_size_alignment - 1) & ~(global_size_alignment - 1)); 3161 } 3162 3163 static void test_freethreadedmarshaldata(IStream *pStream, MSHCTX mshctx, void *ptr, DWORD mshlflags) 3164 { 3165 HGLOBAL hglobal; 3166 DWORD size; 3167 char *marshal_data; 3168 HRESULT hr; 3169 3170 hr = GetHGlobalFromStream(pStream, &hglobal); 3171 ok_ole_success(hr, GetHGlobalFromStream); 3172 3173 size = GlobalSize(hglobal); 3174 3175 marshal_data = GlobalLock(hglobal); 3176 3177 if (mshctx == MSHCTX_INPROC) 3178 { 3179 DWORD expected_size = round_global_size(3*sizeof(DWORD) + sizeof(GUID)); 3180 ok(size == expected_size || 3181 broken(size == (2*sizeof(DWORD))) /* Win9x & NT4 */, 3182 "size should have been %d instead of %d\n", expected_size, size); 3183 3184 ok(*(DWORD *)marshal_data == mshlflags, "expected 0x%x, but got 0x%x for mshctx\n", mshlflags, *(DWORD *)marshal_data); 3185 marshal_data += sizeof(DWORD); 3186 ok(*(void **)marshal_data == ptr, "expected %p, but got %p for mshctx\n", ptr, *(void **)marshal_data); 3187 marshal_data += sizeof(void *); 3188 if (sizeof(void*) == 4 && size >= 3*sizeof(DWORD)) 3189 { 3190 ok(*(DWORD *)marshal_data == 0, "expected 0x0, but got 0x%x\n", *(DWORD *)marshal_data); 3191 marshal_data += sizeof(DWORD); 3192 } 3193 if (size >= 3*sizeof(DWORD) + sizeof(GUID)) 3194 { 3195 trace("got guid data: %s\n", wine_dbgstr_guid((GUID *)marshal_data)); 3196 } 3197 } 3198 else 3199 { 3200 ok(size > sizeof(DWORD), "size should have been > sizeof(DWORD), not %d\n", size); 3201 ok(*(DWORD *)marshal_data == 0x574f454d /* MEOW */, 3202 "marshal data should be filled by standard marshal and start with MEOW signature\n"); 3203 } 3204 3205 GlobalUnlock(hglobal); 3206 } 3207 3208 static void test_freethreadedmarshaler(void) 3209 { 3210 HRESULT hr; 3211 IUnknown *pFTUnknown; 3212 IMarshal *pFTMarshal; 3213 IStream *pStream; 3214 IUnknown *pProxy; 3215 static const LARGE_INTEGER llZero; 3216 CLSID clsid; 3217 3218 cLocks = 0; 3219 hr = CoCreateFreeThreadedMarshaler(NULL, &pFTUnknown); 3220 ok_ole_success(hr, CoCreateFreeThreadedMarshaler); 3221 hr = IUnknown_QueryInterface(pFTUnknown, &IID_IMarshal, (void **)&pFTMarshal); 3222 ok_ole_success(hr, IUnknown_QueryInterface); 3223 IUnknown_Release(pFTUnknown); 3224 3225 hr = CreateStreamOnHGlobal(NULL, TRUE, &pStream); 3226 ok_ole_success(hr, CreateStreamOnHGlobal); 3227 3228 /* inproc normal marshaling */ 3229 3230 hr = IMarshal_GetUnmarshalClass(pFTMarshal, &IID_IClassFactory, 3231 &Test_ClassFactory, MSHCTX_INPROC, NULL, MSHLFLAGS_NORMAL, &clsid); 3232 ok_ole_success(hr, IMarshal_GetUnmarshalClass); 3233 ok(IsEqualIID(&clsid, &CLSID_InProcFreeMarshaler), "clsid = %s\n", 3234 wine_dbgstr_guid(&clsid)); 3235 3236 hr = IMarshal_MarshalInterface(pFTMarshal, pStream, &IID_IClassFactory, 3237 &Test_ClassFactory, MSHCTX_INPROC, NULL, MSHLFLAGS_NORMAL); 3238 ok_ole_success(hr, IMarshal_MarshalInterface); 3239 3240 ok_more_than_one_lock(); 3241 3242 test_freethreadedmarshaldata(pStream, MSHCTX_INPROC, &Test_ClassFactory, MSHLFLAGS_NORMAL); 3243 3244 IStream_Seek(pStream, llZero, STREAM_SEEK_SET, NULL); 3245 hr = IMarshal_UnmarshalInterface(pFTMarshal, pStream, &IID_IUnknown, (void **)&pProxy); 3246 ok_ole_success(hr, IMarshal_UnmarshalInterface); 3247 3248 IUnknown_Release(pProxy); 3249 3250 ok_no_locks(); 3251 3252 /* inproc table-strong marshaling */ 3253 3254 IStream_Seek(pStream, llZero, STREAM_SEEK_SET, NULL); 3255 hr = IMarshal_MarshalInterface(pFTMarshal, pStream, &IID_IClassFactory, 3256 (IUnknown*)&Test_ClassFactory, MSHCTX_INPROC, (void *)0xdeadbeef, 3257 MSHLFLAGS_TABLESTRONG); 3258 ok_ole_success(hr, IMarshal_MarshalInterface); 3259 3260 ok_more_than_one_lock(); 3261 3262 test_freethreadedmarshaldata(pStream, MSHCTX_INPROC, &Test_ClassFactory, MSHLFLAGS_TABLESTRONG); 3263 3264 IStream_Seek(pStream, llZero, STREAM_SEEK_SET, NULL); 3265 hr = IMarshal_UnmarshalInterface(pFTMarshal, pStream, &IID_IUnknown, (void **)&pProxy); 3266 ok_ole_success(hr, IMarshal_UnmarshalInterface); 3267 3268 IUnknown_Release(pProxy); 3269 3270 ok_more_than_one_lock(); 3271 3272 IStream_Seek(pStream, llZero, STREAM_SEEK_SET, NULL); 3273 hr = IMarshal_ReleaseMarshalData(pFTMarshal, pStream); 3274 ok_ole_success(hr, IMarshal_ReleaseMarshalData); 3275 3276 ok_no_locks(); 3277 3278 /* inproc table-weak marshaling */ 3279 3280 IStream_Seek(pStream, llZero, STREAM_SEEK_SET, NULL); 3281 hr = IMarshal_MarshalInterface(pFTMarshal, pStream, &IID_IClassFactory, 3282 (IUnknown*)&Test_ClassFactory, MSHCTX_INPROC, (void *)0xdeadbeef, 3283 MSHLFLAGS_TABLEWEAK); 3284 ok_ole_success(hr, IMarshal_MarshalInterface); 3285 3286 ok_no_locks(); 3287 3288 test_freethreadedmarshaldata(pStream, MSHCTX_INPROC, &Test_ClassFactory, MSHLFLAGS_TABLEWEAK); 3289 3290 IStream_Seek(pStream, llZero, STREAM_SEEK_SET, NULL); 3291 hr = IMarshal_UnmarshalInterface(pFTMarshal, pStream, &IID_IUnknown, (void **)&pProxy); 3292 ok_ole_success(hr, IMarshal_UnmarshalInterface); 3293 3294 ok_more_than_one_lock(); 3295 3296 IUnknown_Release(pProxy); 3297 3298 ok_no_locks(); 3299 3300 /* inproc normal marshaling (for extraordinary cases) */ 3301 3302 IStream_Seek(pStream, llZero, STREAM_SEEK_SET, NULL); 3303 hr = IMarshal_MarshalInterface(pFTMarshal, pStream, &IID_IClassFactory, 3304 &Test_ClassFactory, MSHCTX_INPROC, NULL, MSHLFLAGS_NORMAL); 3305 ok_ole_success(hr, IMarshal_MarshalInterface); 3306 3307 ok_more_than_one_lock(); 3308 3309 /* this call shows that DisconnectObject does nothing */ 3310 hr = IMarshal_DisconnectObject(pFTMarshal, 0); 3311 ok_ole_success(hr, IMarshal_DisconnectObject); 3312 3313 ok_more_than_one_lock(); 3314 3315 IStream_Seek(pStream, llZero, STREAM_SEEK_SET, NULL); 3316 hr = IMarshal_ReleaseMarshalData(pFTMarshal, pStream); 3317 ok_ole_success(hr, IMarshal_ReleaseMarshalData); 3318 3319 ok_no_locks(); 3320 3321 /* doesn't enforce marshaling rules here and allows us to unmarshal the 3322 * interface, even though it was freed above */ 3323 IStream_Seek(pStream, llZero, STREAM_SEEK_SET, NULL); 3324 hr = IMarshal_UnmarshalInterface(pFTMarshal, pStream, &IID_IUnknown, (void **)&pProxy); 3325 ok_ole_success(hr, IMarshal_UnmarshalInterface); 3326 3327 ok_no_locks(); 3328 3329 /* local normal marshaling */ 3330 3331 hr = IMarshal_GetUnmarshalClass(pFTMarshal, &IID_IClassFactory, 3332 &Test_ClassFactory, MSHCTX_LOCAL, NULL, MSHLFLAGS_NORMAL, &clsid); 3333 ok_ole_success(hr, IMarshal_GetUnmarshalClass); 3334 ok(IsEqualIID(&clsid, &CLSID_StdMarshal), "clsid = %s\n", 3335 wine_dbgstr_guid(&clsid)); 3336 3337 IStream_Seek(pStream, llZero, STREAM_SEEK_SET, NULL); 3338 hr = IMarshal_MarshalInterface(pFTMarshal, pStream, &IID_IClassFactory, &Test_ClassFactory, MSHCTX_LOCAL, NULL, MSHLFLAGS_NORMAL); 3339 ok_ole_success(hr, IMarshal_MarshalInterface); 3340 3341 ok_more_than_one_lock(); 3342 3343 test_freethreadedmarshaldata(pStream, MSHCTX_LOCAL, &Test_ClassFactory, MSHLFLAGS_NORMAL); 3344 3345 IStream_Seek(pStream, llZero, STREAM_SEEK_SET, NULL); 3346 hr = CoReleaseMarshalData(pStream); 3347 ok_ole_success(hr, CoReleaseMarshalData); 3348 3349 ok_no_locks(); 3350 3351 IStream_Release(pStream); 3352 IMarshal_Release(pFTMarshal); 3353 } 3354 3355 static HRESULT reg_unreg_wine_test_class(BOOL Register) 3356 { 3357 HRESULT hr; 3358 char buffer[256]; 3359 LPOLESTR pszClsid; 3360 HKEY hkey; 3361 DWORD dwDisposition; 3362 DWORD error; 3363 3364 hr = StringFromCLSID(&CLSID_WineTest, &pszClsid); 3365 ok_ole_success(hr, "StringFromCLSID"); 3366 strcpy(buffer, "CLSID\\"); 3367 WideCharToMultiByte(CP_ACP, 0, pszClsid, -1, buffer + strlen(buffer), sizeof(buffer) - strlen(buffer), NULL, NULL); 3368 CoTaskMemFree(pszClsid); 3369 strcat(buffer, "\\InprocHandler32"); 3370 if (Register) 3371 { 3372 error = RegCreateKeyExA(HKEY_CLASSES_ROOT, buffer, 0, NULL, 0, KEY_SET_VALUE, NULL, &hkey, &dwDisposition); 3373 if (error == ERROR_ACCESS_DENIED) 3374 { 3375 skip("Not authorized to modify the Classes key\n"); 3376 return E_FAIL; 3377 } 3378 ok(error == ERROR_SUCCESS, "RegCreateKeyEx failed with error %d\n", error); 3379 if (error != ERROR_SUCCESS) hr = E_FAIL; 3380 error = RegSetValueExA(hkey, NULL, 0, REG_SZ, (const unsigned char *)"\"ole32.dll\"", strlen("\"ole32.dll\"") + 1); 3381 ok(error == ERROR_SUCCESS, "RegSetValueEx failed with error %d\n", error); 3382 if (error != ERROR_SUCCESS) hr = E_FAIL; 3383 RegCloseKey(hkey); 3384 } 3385 else 3386 { 3387 RegDeleteKeyA(HKEY_CLASSES_ROOT, buffer); 3388 *strrchr(buffer, '\\') = '\0'; 3389 RegDeleteKeyA(HKEY_CLASSES_ROOT, buffer); 3390 } 3391 return hr; 3392 } 3393 3394 static void test_inproc_handler(void) 3395 { 3396 HRESULT hr; 3397 IUnknown *pObject; 3398 IUnknown *pObject2; 3399 3400 if (FAILED(reg_unreg_wine_test_class(TRUE))) 3401 return; 3402 3403 hr = CoCreateInstance(&CLSID_WineTest, NULL, CLSCTX_INPROC_HANDLER, &IID_IUnknown, (void **)&pObject); 3404 ok_ole_success(hr, "CoCreateInstance"); 3405 3406 if (SUCCEEDED(hr)) 3407 { 3408 hr = IUnknown_QueryInterface(pObject, &IID_IWineTest, (void **)&pObject2); 3409 ok(hr == E_NOINTERFACE, "IUnknown_QueryInterface on handler for invalid interface returned 0x%08x instead of E_NOINTERFACE\n", hr); 3410 3411 /* it's a handler as it supports IOleObject */ 3412 hr = IUnknown_QueryInterface(pObject, &IID_IOleObject, (void **)&pObject2); 3413 ok_ole_success(hr, "IUnknown_QueryInterface(&IID_IOleObject)"); 3414 IUnknown_Release(pObject2); 3415 3416 IUnknown_Release(pObject); 3417 } 3418 3419 reg_unreg_wine_test_class(FALSE); 3420 } 3421 3422 static HRESULT WINAPI Test_SMI_QueryInterface( 3423 IStdMarshalInfo *iface, 3424 REFIID riid, 3425 LPVOID *ppvObj) 3426 { 3427 if (ppvObj == NULL) return E_POINTER; 3428 3429 if (IsEqualGUID(riid, &IID_IUnknown) || 3430 IsEqualGUID(riid, &IID_IStdMarshalInfo)) 3431 { 3432 *ppvObj = iface; 3433 IStdMarshalInfo_AddRef(iface); 3434 return S_OK; 3435 } 3436 3437 return E_NOINTERFACE; 3438 } 3439 3440 static ULONG WINAPI Test_SMI_AddRef(IStdMarshalInfo *iface) 3441 { 3442 LockModule(); 3443 return 2; /* non-heap-based object */ 3444 } 3445 3446 static ULONG WINAPI Test_SMI_Release(IStdMarshalInfo *iface) 3447 { 3448 UnlockModule(); 3449 return 1; /* non-heap-based object */ 3450 } 3451 3452 static HRESULT WINAPI Test_SMI_GetClassForHandler( 3453 IStdMarshalInfo *iface, 3454 DWORD dwDestContext, 3455 void *pvDestContext, 3456 CLSID *pClsid) 3457 { 3458 *pClsid = CLSID_WineTest; 3459 return S_OK; 3460 } 3461 3462 static const IStdMarshalInfoVtbl Test_SMI_Vtbl = 3463 { 3464 Test_SMI_QueryInterface, 3465 Test_SMI_AddRef, 3466 Test_SMI_Release, 3467 Test_SMI_GetClassForHandler 3468 }; 3469 3470 static IStdMarshalInfo Test_SMI = {&Test_SMI_Vtbl}; 3471 3472 static void test_handler_marshaling(void) 3473 { 3474 HRESULT hr; 3475 IStream *pStream = NULL; 3476 IUnknown *pProxy = NULL; 3477 IUnknown *pObject; 3478 DWORD tid; 3479 HANDLE thread; 3480 static const LARGE_INTEGER ullZero; 3481 3482 if (FAILED(reg_unreg_wine_test_class(TRUE))) 3483 return; 3484 cLocks = 0; 3485 3486 hr = CreateStreamOnHGlobal(NULL, TRUE, &pStream); 3487 ok_ole_success(hr, "CreateStreamOnHGlobal"); 3488 tid = start_host_object(pStream, &IID_IUnknown, (IUnknown*)&Test_SMI, MSHLFLAGS_NORMAL, &thread); 3489 3490 ok_more_than_one_lock(); 3491 3492 IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL); 3493 hr = CoUnmarshalInterface(pStream, &IID_IUnknown, (void **)&pProxy); 3494 ok_ole_success(hr, "CoUnmarshalInterface"); 3495 IStream_Release(pStream); 3496 3497 if(hr == S_OK) 3498 { 3499 ok_more_than_one_lock(); 3500 3501 hr = IUnknown_QueryInterface(pProxy, &IID_IWineTest, (void **)&pObject); 3502 ok(hr == E_NOINTERFACE, "IUnknown_QueryInterface with unknown IID should have returned E_NOINTERFACE instead of 0x%08x\n", hr); 3503 3504 /* it's a handler as it supports IOleObject */ 3505 hr = IUnknown_QueryInterface(pProxy, &IID_IOleObject, (void **)&pObject); 3506 todo_wine 3507 ok_ole_success(hr, "IUnknown_QueryInterface(&IID_IOleObject)"); 3508 if (SUCCEEDED(hr)) IUnknown_Release(pObject); 3509 3510 IUnknown_Release(pProxy); 3511 3512 ok_no_locks(); 3513 } 3514 3515 end_host_object(tid, thread); 3516 reg_unreg_wine_test_class(FALSE); 3517 3518 /* FIXME: test IPersist interface has the same effect as IStdMarshalInfo */ 3519 } 3520 3521 3522 static void test_client_security(void) 3523 { 3524 HRESULT hr; 3525 IStream *pStream = NULL; 3526 IClassFactory *pProxy = NULL; 3527 IUnknown *pProxy2 = NULL; 3528 IUnknown *pUnknown1 = NULL; 3529 IUnknown *pUnknown2 = NULL; 3530 IClientSecurity *pCliSec = NULL; 3531 IMarshal *pMarshal; 3532 DWORD tid; 3533 HANDLE thread; 3534 static const LARGE_INTEGER ullZero; 3535 DWORD dwAuthnSvc; 3536 DWORD dwAuthzSvc; 3537 OLECHAR *pServerPrincName; 3538 DWORD dwAuthnLevel; 3539 DWORD dwImpLevel; 3540 void *pAuthInfo; 3541 DWORD dwCapabilities; 3542 void *pv; 3543 3544 cLocks = 0; 3545 3546 hr = CreateStreamOnHGlobal(NULL, TRUE, &pStream); 3547 ok_ole_success(hr, "CreateStreamOnHGlobal"); 3548 tid = start_host_object(pStream, &IID_IClassFactory, (IUnknown*)&Test_ClassFactory, MSHLFLAGS_NORMAL, &thread); 3549 3550 IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL); 3551 hr = CoUnmarshalInterface(pStream, &IID_IClassFactory, (void **)&pProxy); 3552 ok_ole_success(hr, "CoUnmarshalInterface"); 3553 IStream_Release(pStream); 3554 3555 hr = IClassFactory_QueryInterface(pProxy, &IID_IUnknown, (LPVOID*)&pUnknown1); 3556 ok_ole_success(hr, "IUnknown_QueryInterface IID_IUnknown"); 3557 3558 hr = IClassFactory_QueryInterface(pProxy, &IID_IRemUnknown, (LPVOID*)&pProxy2); 3559 ok_ole_success(hr, "IUnknown_QueryInterface IID_IStream"); 3560 3561 hr = IUnknown_QueryInterface(pProxy2, &IID_IUnknown, (LPVOID*)&pUnknown2); 3562 ok_ole_success(hr, "IUnknown_QueryInterface IID_IUnknown"); 3563 3564 ok(pUnknown1 == pUnknown2, "both proxy's IUnknowns should be the same - %p, %p\n", pUnknown1, pUnknown2); 3565 3566 hr = IClassFactory_QueryInterface(pProxy, &IID_IMarshal, (LPVOID*)&pMarshal); 3567 ok_ole_success(hr, "IUnknown_QueryInterface IID_IMarshal"); 3568 3569 hr = IClassFactory_QueryInterface(pProxy, &IID_IClientSecurity, (LPVOID*)&pCliSec); 3570 ok_ole_success(hr, "IUnknown_QueryInterface IID_IClientSecurity"); 3571 3572 hr = IClientSecurity_QueryBlanket(pCliSec, (IUnknown *)pProxy, NULL, NULL, NULL, NULL, NULL, NULL, NULL); 3573 todo_wine ok_ole_success(hr, "IClientSecurity_QueryBlanket (all NULLs)"); 3574 3575 hr = IClientSecurity_QueryBlanket(pCliSec, (IUnknown *)pMarshal, NULL, NULL, NULL, NULL, NULL, NULL, NULL); 3576 todo_wine ok(hr == E_NOINTERFACE, "IClientSecurity_QueryBlanket with local interface should have returned E_NOINTERFACE instead of 0x%08x\n", hr); 3577 3578 hr = IClientSecurity_QueryBlanket(pCliSec, (IUnknown *)pProxy, &dwAuthnSvc, &dwAuthzSvc, &pServerPrincName, &dwAuthnLevel, &dwImpLevel, &pAuthInfo, &dwCapabilities); 3579 todo_wine ok_ole_success(hr, "IClientSecurity_QueryBlanket"); 3580 3581 hr = IClientSecurity_SetBlanket(pCliSec, (IUnknown *)pProxy, dwAuthnSvc, dwAuthzSvc, pServerPrincName, dwAuthnLevel, RPC_C_IMP_LEVEL_IMPERSONATE, pAuthInfo, dwCapabilities); 3582 todo_wine ok_ole_success(hr, "IClientSecurity_SetBlanket"); 3583 3584 hr = IClassFactory_CreateInstance(pProxy, NULL, &IID_IWineTest, &pv); 3585 ok(hr == E_NOINTERFACE, "COM call should have succeeded instead of returning 0x%08x\n", hr); 3586 3587 hr = IClientSecurity_SetBlanket(pCliSec, (IUnknown *)pMarshal, dwAuthnSvc, dwAuthzSvc, pServerPrincName, dwAuthnLevel, dwImpLevel, pAuthInfo, dwCapabilities); 3588 todo_wine ok(hr == E_NOINTERFACE, "IClientSecurity_SetBlanket with local interface should have returned E_NOINTERFACE instead of 0x%08x\n", hr); 3589 3590 hr = IClientSecurity_SetBlanket(pCliSec, (IUnknown *)pProxy, 0xdeadbeef, dwAuthzSvc, pServerPrincName, dwAuthnLevel, dwImpLevel, pAuthInfo, dwCapabilities); 3591 todo_wine ok(hr == E_INVALIDARG, "IClientSecurity_SetBlanke with invalid dwAuthnSvc should have returned E_INVALIDARG instead of 0x%08x\n", hr); 3592 3593 CoTaskMemFree(pServerPrincName); 3594 3595 hr = IClientSecurity_QueryBlanket(pCliSec, pUnknown1, &dwAuthnSvc, &dwAuthzSvc, &pServerPrincName, &dwAuthnLevel, &dwImpLevel, &pAuthInfo, &dwCapabilities); 3596 todo_wine ok_ole_success(hr, "IClientSecurity_QueryBlanket(IUnknown)"); 3597 3598 CoTaskMemFree(pServerPrincName); 3599 3600 IClassFactory_Release(pProxy); 3601 IUnknown_Release(pProxy2); 3602 IUnknown_Release(pUnknown1); 3603 IUnknown_Release(pUnknown2); 3604 IMarshal_Release(pMarshal); 3605 IClientSecurity_Release(pCliSec); 3606 3607 end_host_object(tid, thread); 3608 } 3609 3610 static HANDLE heventShutdown; 3611 3612 static void LockModuleOOP(void) 3613 { 3614 InterlockedIncrement(&cLocks); /* for test purposes only */ 3615 CoAddRefServerProcess(); 3616 } 3617 3618 static void UnlockModuleOOP(void) 3619 { 3620 InterlockedDecrement(&cLocks); /* for test purposes only */ 3621 if (!CoReleaseServerProcess()) 3622 SetEvent(heventShutdown); 3623 } 3624 3625 static HWND hwnd_app; 3626 3627 struct local_server 3628 { 3629 IPersist IPersist_iface; /* a nice short interface */ 3630 }; 3631 3632 static HRESULT WINAPI local_server_QueryInterface(IPersist *iface, REFIID iid, void **obj) 3633 { 3634 *obj = NULL; 3635 3636 if (IsEqualGUID(iid, &IID_IUnknown) || 3637 IsEqualGUID(iid, &IID_IPersist)) 3638 *obj = iface; 3639 3640 if (*obj) 3641 { 3642 IPersist_AddRef(iface); 3643 return S_OK; 3644 } 3645 return E_NOINTERFACE; 3646 } 3647 3648 static ULONG WINAPI local_server_AddRef(IPersist *iface) 3649 { 3650 return 2; 3651 } 3652 3653 static ULONG WINAPI local_server_Release(IPersist *iface) 3654 { 3655 return 1; 3656 } 3657 3658 static HRESULT WINAPI local_server_GetClassID(IPersist *iface, CLSID *clsid) 3659 { 3660 HRESULT hr; 3661 3662 *clsid = IID_IUnknown; 3663 3664 /* Test calling CoDisconnectObject within a COM call */ 3665 hr = CoDisconnectObject((IUnknown *)iface, 0); 3666 ok(hr == S_OK, "got %08x\n", hr); 3667 3668 /* Initialize and uninitialize the apartment to show that we 3669 * remain in the autojoined mta */ 3670 hr = pCoInitializeEx( NULL, COINIT_MULTITHREADED ); 3671 ok( hr == S_FALSE, "got %08x\n", hr ); 3672 CoUninitialize(); 3673 3674 return S_OK; 3675 } 3676 3677 static const IPersistVtbl local_server_persist_vtbl = 3678 { 3679 local_server_QueryInterface, 3680 local_server_AddRef, 3681 local_server_Release, 3682 local_server_GetClassID 3683 }; 3684 3685 struct local_server local_server_class = 3686 { 3687 {&local_server_persist_vtbl} 3688 }; 3689 3690 static HRESULT WINAPI TestOOP_IClassFactory_QueryInterface( 3691 LPCLASSFACTORY iface, 3692 REFIID riid, 3693 LPVOID *ppvObj) 3694 { 3695 if (ppvObj == NULL) return E_POINTER; 3696 3697 if (IsEqualGUID(riid, &IID_IUnknown) || 3698 IsEqualGUID(riid, &IID_IClassFactory)) 3699 { 3700 *ppvObj = iface; 3701 IClassFactory_AddRef(iface); 3702 return S_OK; 3703 } 3704 3705 return E_NOINTERFACE; 3706 } 3707 3708 static ULONG WINAPI TestOOP_IClassFactory_AddRef(LPCLASSFACTORY iface) 3709 { 3710 return 2; /* non-heap-based object */ 3711 } 3712 3713 static ULONG WINAPI TestOOP_IClassFactory_Release(LPCLASSFACTORY iface) 3714 { 3715 return 1; /* non-heap-based object */ 3716 } 3717 3718 static HRESULT WINAPI TestOOP_IClassFactory_CreateInstance( 3719 LPCLASSFACTORY iface, 3720 LPUNKNOWN pUnkOuter, 3721 REFIID riid, 3722 LPVOID *ppvObj) 3723 { 3724 IPersist *persist = &local_server_class.IPersist_iface; 3725 HRESULT hr; 3726 IPersist_AddRef( persist ); 3727 hr = IPersist_QueryInterface( persist, riid, ppvObj ); 3728 IPersist_Release( persist ); 3729 return hr; 3730 } 3731 3732 static HRESULT WINAPI TestOOP_IClassFactory_LockServer( 3733 LPCLASSFACTORY iface, 3734 BOOL fLock) 3735 { 3736 if (fLock) 3737 LockModuleOOP(); 3738 else 3739 UnlockModuleOOP(); 3740 return S_OK; 3741 } 3742 3743 static const IClassFactoryVtbl TestClassFactoryOOP_Vtbl = 3744 { 3745 TestOOP_IClassFactory_QueryInterface, 3746 TestOOP_IClassFactory_AddRef, 3747 TestOOP_IClassFactory_Release, 3748 TestOOP_IClassFactory_CreateInstance, 3749 TestOOP_IClassFactory_LockServer 3750 }; 3751 3752 static IClassFactory TestOOP_ClassFactory = { &TestClassFactoryOOP_Vtbl }; 3753 3754 static void test_register_local_server(void) 3755 { 3756 DWORD cookie; 3757 HRESULT hr; 3758 HANDLE ready_event; 3759 DWORD wait; 3760 HANDLE handles[2]; 3761 3762 heventShutdown = CreateEventA(NULL, TRUE, FALSE, NULL); 3763 ready_event = CreateEventA(NULL, FALSE, FALSE, "Wine COM Test Ready Event"); 3764 handles[0] = CreateEventA(NULL, FALSE, FALSE, "Wine COM Test Quit Event"); 3765 handles[1] = CreateEventA(NULL, FALSE, FALSE, "Wine COM Test Repeat Event"); 3766 3767 again: 3768 hr = CoRegisterClassObject(&CLSID_WineOOPTest, (IUnknown *)&TestOOP_ClassFactory, 3769 CLSCTX_LOCAL_SERVER, REGCLS_SINGLEUSE, &cookie); 3770 ok_ole_success(hr, CoRegisterClassObject); 3771 3772 SetEvent(ready_event); 3773 3774 do 3775 { 3776 wait = MsgWaitForMultipleObjects(2, handles, FALSE, 30000, QS_ALLINPUT); 3777 if (wait == WAIT_OBJECT_0+2) 3778 { 3779 MSG msg; 3780 3781 if (PeekMessageA(&msg, NULL, 0, 0, PM_REMOVE)) 3782 { 3783 trace("Message 0x%x\n", msg.message); 3784 TranslateMessage(&msg); 3785 DispatchMessageA(&msg); 3786 } 3787 } 3788 else if (wait == WAIT_OBJECT_0+1) 3789 { 3790 hr = CoRevokeClassObject(cookie); 3791 ok_ole_success(hr, CoRevokeClassObject); 3792 goto again; 3793 } 3794 } 3795 while (wait == WAIT_OBJECT_0+2); 3796 3797 ok( wait == WAIT_OBJECT_0, "quit event wait timed out\n" ); 3798 hr = CoRevokeClassObject(cookie); 3799 ok_ole_success(hr, CoRevokeClassObject); 3800 CloseHandle(handles[0]); 3801 CloseHandle(handles[1]); 3802 } 3803 3804 static HANDLE create_target_process(const char *arg) 3805 { 3806 char **argv; 3807 char cmdline[MAX_PATH]; 3808 BOOL ret; 3809 PROCESS_INFORMATION pi; 3810 STARTUPINFOA si = { 0 }; 3811 si.cb = sizeof(si); 3812 3813 pi.hThread = NULL; 3814 pi.hProcess = NULL; 3815 winetest_get_mainargs( &argv ); 3816 sprintf(cmdline, "\"%s\" %s %s", argv[0], argv[1], arg); 3817 ret = CreateProcessA(argv[0], cmdline, NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi); 3818 ok(ret, "CreateProcess failed with error: %u\n", GetLastError()); 3819 if (pi.hThread) CloseHandle(pi.hThread); 3820 return pi.hProcess; 3821 } 3822 3823 /* tests functions commonly used by out of process COM servers */ 3824 static void test_local_server(void) 3825 { 3826 DWORD cookie; 3827 HRESULT hr; 3828 IClassFactory * cf; 3829 IPersist *persist; 3830 DWORD ret; 3831 HANDLE process; 3832 HANDLE quit_event; 3833 HANDLE ready_event; 3834 HANDLE repeat_event; 3835 CLSID clsid; 3836 3837 heventShutdown = CreateEventA(NULL, TRUE, FALSE, NULL); 3838 3839 cLocks = 0; 3840 3841 /* Start the object suspended */ 3842 hr = CoRegisterClassObject(&CLSID_WineOOPTest, (IUnknown *)&TestOOP_ClassFactory, 3843 CLSCTX_LOCAL_SERVER, REGCLS_MULTIPLEUSE | REGCLS_SUSPENDED, &cookie); 3844 ok_ole_success(hr, CoRegisterClassObject); 3845 3846 /* ... and CoGetClassObject does not find it and fails when it looks for the 3847 * class in the registry */ 3848 hr = CoGetClassObject(&CLSID_WineOOPTest, CLSCTX_INPROC_SERVER, 3849 NULL, &IID_IClassFactory, (LPVOID*)&cf); 3850 ok(hr == REGDB_E_CLASSNOTREG || /* NT */ 3851 hr == S_OK /* Win9x */, 3852 "CoGetClassObject should have returned REGDB_E_CLASSNOTREG instead of 0x%08x\n", hr); 3853 3854 /* Resume the object suspended above ... */ 3855 hr = CoResumeClassObjects(); 3856 ok_ole_success(hr, CoResumeClassObjects); 3857 3858 /* ... and now it should succeed */ 3859 hr = CoGetClassObject(&CLSID_WineOOPTest, CLSCTX_INPROC_SERVER, 3860 NULL, &IID_IClassFactory, (LPVOID*)&cf); 3861 ok_ole_success(hr, CoGetClassObject); 3862 3863 /* Now check the locking is working */ 3864 /* NOTE: we are accessing the class directly, not through a proxy */ 3865 3866 ok_no_locks(); 3867 3868 hr = IClassFactory_LockServer(cf, TRUE); 3869 ok_ole_success(hr, IClassFactory_LockServer); 3870 3871 ok_more_than_one_lock(); 3872 3873 IClassFactory_LockServer(cf, FALSE); 3874 ok_ole_success(hr, IClassFactory_LockServer); 3875 3876 ok_no_locks(); 3877 3878 IClassFactory_Release(cf); 3879 3880 /* wait for shutdown signal */ 3881 ret = WaitForSingleObject(heventShutdown, 0); 3882 ok(ret != WAIT_TIMEOUT, "Server didn't shut down\n"); 3883 3884 /* try to connect again after SCM has suspended registered class objects */ 3885 hr = CoGetClassObject(&CLSID_WineOOPTest, CLSCTX_INPROC_SERVER | CLSCTX_LOCAL_SERVER, NULL, 3886 &IID_IClassFactory, (LPVOID*)&cf); 3887 ok(hr == CO_E_SERVER_STOPPING || /* NT */ 3888 hr == REGDB_E_CLASSNOTREG || /* win2k */ 3889 hr == S_OK /* Win9x */, 3890 "CoGetClassObject should have returned CO_E_SERVER_STOPPING or REGDB_E_CLASSNOTREG instead of 0x%08x\n", hr); 3891 3892 hr = CoRevokeClassObject(cookie); 3893 ok_ole_success(hr, CoRevokeClassObject); 3894 3895 CloseHandle(heventShutdown); 3896 3897 process = create_target_process("-Embedding"); 3898 ok(process != NULL, "couldn't start local server process, error was %d\n", GetLastError()); 3899 3900 ready_event = CreateEventA(NULL, FALSE, FALSE, "Wine COM Test Ready Event"); 3901 ok( !WaitForSingleObject(ready_event, 10000), "wait timed out\n" ); 3902 3903 hr = CoCreateInstance(&CLSID_WineOOPTest, NULL, CLSCTX_LOCAL_SERVER, &IID_IPersist, (void **)&persist); 3904 ok_ole_success(hr, CoCreateInstance); 3905 3906 IPersist_Release(persist); 3907 3908 hr = CoCreateInstance(&CLSID_WineOOPTest, NULL, CLSCTX_LOCAL_SERVER, &IID_IPersist, (void **)&persist); 3909 ok(hr == REGDB_E_CLASSNOTREG, "Second CoCreateInstance on REGCLS_SINGLEUSE object should have failed\n"); 3910 3911 /* Re-register the class and try calling CoDisconnectObject from within a call to that object */ 3912 repeat_event = CreateEventA(NULL, FALSE, FALSE, "Wine COM Test Repeat Event"); 3913 SetEvent(repeat_event); 3914 CloseHandle(repeat_event); 3915 3916 ok( !WaitForSingleObject(ready_event, 10000), "wait timed out\n" ); 3917 CloseHandle(ready_event); 3918 3919 hr = CoCreateInstance(&CLSID_WineOOPTest, NULL, CLSCTX_LOCAL_SERVER, &IID_IPersist, (void **)&persist); 3920 ok_ole_success(hr, CoCreateInstance); 3921 3922 /* GetClassID will call CoDisconnectObject */ 3923 IPersist_GetClassID(persist, &clsid); 3924 IPersist_Release(persist); 3925 3926 quit_event = CreateEventA(NULL, FALSE, FALSE, "Wine COM Test Quit Event"); 3927 SetEvent(quit_event); 3928 3929 winetest_wait_child_process( process ); 3930 CloseHandle(quit_event); 3931 CloseHandle(process); 3932 } 3933 3934 struct git_params 3935 { 3936 DWORD cookie; 3937 IGlobalInterfaceTable *git; 3938 }; 3939 3940 static DWORD CALLBACK get_global_interface_proc(LPVOID pv) 3941 { 3942 HRESULT hr; 3943 struct git_params *params = pv; 3944 IClassFactory *cf; 3945 3946 hr = IGlobalInterfaceTable_GetInterfaceFromGlobal(params->git, params->cookie, &IID_IClassFactory, (void **)&cf); 3947 ok(hr == CO_E_NOTINITIALIZED || 3948 broken(hr == E_UNEXPECTED) /* win2k */ || 3949 broken(hr == S_OK) /* NT 4 */, 3950 "IGlobalInterfaceTable_GetInterfaceFromGlobal should have failed with error CO_E_NOTINITIALIZED or E_UNEXPECTED instead of 0x%08x\n", 3951 hr); 3952 if (hr == S_OK) 3953 IClassFactory_Release(cf); 3954 3955 CoInitialize(NULL); 3956 3957 hr = IGlobalInterfaceTable_GetInterfaceFromGlobal(params->git, params->cookie, &IID_IClassFactory, (void **)&cf); 3958 ok_ole_success(hr, IGlobalInterfaceTable_GetInterfaceFromGlobal); 3959 3960 IClassFactory_Release(cf); 3961 3962 CoUninitialize(); 3963 3964 return hr; 3965 } 3966 3967 static void test_globalinterfacetable(void) 3968 { 3969 HRESULT hr; 3970 IGlobalInterfaceTable *git; 3971 DWORD cookie; 3972 HANDLE thread; 3973 DWORD tid; 3974 struct git_params params; 3975 DWORD ret; 3976 IUnknown *object; 3977 IClassFactory *cf; 3978 ULONG ref; 3979 3980 trace("test_globalinterfacetable\n"); 3981 cLocks = 0; 3982 3983 hr = pDllGetClassObject(&CLSID_StdGlobalInterfaceTable, &IID_IClassFactory, (void**)&cf); 3984 ok(hr == S_OK, "got 0x%08x\n", hr); 3985 3986 hr = IClassFactory_QueryInterface(cf, &IID_IGlobalInterfaceTable, (void**)&object); 3987 ok(hr == E_NOINTERFACE, "got 0x%08x\n", hr); 3988 3989 IClassFactory_Release(cf); 3990 3991 hr = CoCreateInstance(&CLSID_StdGlobalInterfaceTable, NULL, CLSCTX_INPROC_SERVER, &IID_IGlobalInterfaceTable, (void **)&git); 3992 ok_ole_success(hr, CoCreateInstance); 3993 3994 ref = IGlobalInterfaceTable_AddRef(git); 3995 ok(ref == 1, "ref=%d\n", ref); 3996 ref = IGlobalInterfaceTable_AddRef(git); 3997 ok(ref == 1, "ref=%d\n", ref); 3998 3999 ref = IGlobalInterfaceTable_Release(git); 4000 ok(ref == 1, "ref=%d\n", ref); 4001 ref = IGlobalInterfaceTable_Release(git); 4002 ok(ref == 1, "ref=%d\n", ref); 4003 4004 hr = IGlobalInterfaceTable_RegisterInterfaceInGlobal(git, (IUnknown *)&Test_ClassFactory, &IID_IClassFactory, &cookie); 4005 ok_ole_success(hr, IGlobalInterfaceTable_RegisterInterfaceInGlobal); 4006 4007 ok_more_than_one_lock(); 4008 4009 params.cookie = cookie; 4010 params.git = git; 4011 /* note: params is on stack so we MUST wait for get_global_interface_proc 4012 * to exit before we can return */ 4013 thread = CreateThread(NULL, 0, get_global_interface_proc, ¶ms, 0, &tid); 4014 4015 ret = MsgWaitForMultipleObjects(1, &thread, FALSE, 10000, QS_ALLINPUT); 4016 while (ret == WAIT_OBJECT_0 + 1) 4017 { 4018 MSG msg; 4019 while (PeekMessageA(&msg, NULL, 0, 0, PM_REMOVE)) 4020 DispatchMessageA(&msg); 4021 ret = MsgWaitForMultipleObjects(1, &thread, FALSE, 10000, QS_ALLINPUT); 4022 } 4023 4024 CloseHandle(thread); 4025 4026 /* test getting interface from global with different iid */ 4027 hr = IGlobalInterfaceTable_GetInterfaceFromGlobal(git, cookie, &IID_IUnknown, (void **)&object); 4028 ok_ole_success(hr, IGlobalInterfaceTable_GetInterfaceFromGlobal); 4029 IUnknown_Release(object); 4030 4031 /* test getting interface from global with same iid */ 4032 hr = IGlobalInterfaceTable_GetInterfaceFromGlobal(git, cookie, &IID_IClassFactory, (void **)&object); 4033 ok_ole_success(hr, IGlobalInterfaceTable_GetInterfaceFromGlobal); 4034 IUnknown_Release(object); 4035 4036 hr = IGlobalInterfaceTable_RevokeInterfaceFromGlobal(git, cookie); 4037 ok_ole_success(hr, IGlobalInterfaceTable_RevokeInterfaceFromGlobal); 4038 4039 ok_no_locks(); 4040 4041 IGlobalInterfaceTable_Release(git); 4042 } 4043 4044 static void test_manualresetevent(void) 4045 { 4046 ISynchronizeHandle *sync_handle; 4047 ISynchronize *psync1, *psync2; 4048 IUnknown *punk; 4049 HANDLE handle; 4050 LONG ref; 4051 HRESULT hr; 4052 4053 hr = CoCreateInstance(&CLSID_ManualResetEvent, NULL, CLSCTX_INPROC_SERVER, &IID_IUnknown, (void**)&punk); 4054 ok(hr == S_OK, "Got 0x%08x\n", hr); 4055 ok(!!punk, "Got NULL.\n"); 4056 IUnknown_Release(punk); 4057 4058 hr = CoCreateInstance(&CLSID_ManualResetEvent, NULL, CLSCTX_INPROC_SERVER, &IID_ISynchronize, (void**)&psync1); 4059 ok(hr == S_OK, "Got 0x%08x\n", hr); 4060 ok(!!psync1, "Got NULL.\n"); 4061 4062 hr = ISynchronize_Wait(psync1, 0, 5); 4063 ok(hr == RPC_S_CALLPENDING, "Got 0x%08x\n", hr); 4064 4065 hr = ISynchronize_Reset(psync1); 4066 ok(hr == S_OK, "Got 0x%08x\n", hr); 4067 hr = ISynchronize_Signal(psync1); 4068 ok(hr == S_OK, "Got 0x%08x\n", hr); 4069 hr = ISynchronize_Wait(psync1, 0, 5); 4070 ok(hr == S_OK, "Got 0x%08x\n", hr); 4071 hr = ISynchronize_Wait(psync1, 0, 5); 4072 ok(hr == S_OK, "Got 0x%08x\n", hr); 4073 hr = ISynchronize_Reset(psync1); 4074 ok(hr == S_OK, "Got 0x%08x\n", hr); 4075 hr = ISynchronize_Wait(psync1, 0, 5); 4076 ok(hr == RPC_S_CALLPENDING, "Got 0x%08x\n", hr); 4077 4078 hr = CoCreateInstance(&CLSID_ManualResetEvent, NULL, CLSCTX_INPROC_SERVER, &IID_ISynchronize, (void**)&psync2); 4079 ok(hr == S_OK, "Got 0x%08x\n", hr); 4080 ok(!!psync2, "Got NULL.\n"); 4081 ok(psync1 != psync2, "psync1 == psync2.\n"); 4082 4083 hr = ISynchronize_QueryInterface(psync2, &IID_ISynchronizeHandle, (void**)&sync_handle); 4084 ok(hr == S_OK, "QueryInterface(IID_ISynchronizeHandle) failed: %08x\n", hr); 4085 4086 handle = NULL; 4087 hr = ISynchronizeHandle_GetHandle(sync_handle, &handle); 4088 ok(hr == S_OK, "GetHandle failed: %08x\n", hr); 4089 ok(handle != NULL && handle != INVALID_HANDLE_VALUE, "handle = %p\n", handle); 4090 4091 ISynchronizeHandle_Release(sync_handle); 4092 4093 hr = ISynchronize_Wait(psync2, 0, 5); 4094 ok(hr == RPC_S_CALLPENDING, "Got 0x%08x\n", hr); 4095 4096 hr = ISynchronize_Reset(psync1); 4097 ok(hr == S_OK, "Got 0x%08x\n", hr); 4098 hr = ISynchronize_Reset(psync2); 4099 ok(hr == S_OK, "Got 0x%08x\n", hr); 4100 hr = ISynchronize_Signal(psync1); 4101 ok(hr == S_OK, "Got 0x%08x\n", hr); 4102 hr = ISynchronize_Wait(psync2, 0, 5); 4103 ok(hr == RPC_S_CALLPENDING, "Got 0x%08x\n", hr); 4104 4105 ref = ISynchronize_AddRef(psync1); 4106 ok(ref == 2, "Got ref: %d\n", ref); 4107 ref = ISynchronize_AddRef(psync1); 4108 ok(ref == 3, "Got ref: %d\n", ref); 4109 ref = ISynchronize_Release(psync1); 4110 ok(ref == 2, "Got nonzero ref: %d\n", ref); 4111 ref = ISynchronize_Release(psync2); 4112 ok(!ref, "Got nonzero ref: %d\n", ref); 4113 ref = ISynchronize_Release(psync1); 4114 ok(ref == 1, "Got nonzero ref: %d\n", ref); 4115 ref = ISynchronize_Release(psync1); 4116 ok(!ref, "Got nonzero ref: %d\n", ref); 4117 } 4118 4119 static DWORD CALLBACK implicit_mta_unmarshal_proc(void *param) 4120 { 4121 IStream *stream = param; 4122 IClassFactory *cf; 4123 IUnknown *proxy; 4124 HRESULT hr; 4125 4126 IStream_Seek(stream, ullZero, STREAM_SEEK_SET, NULL); 4127 hr = CoUnmarshalInterface(stream, &IID_IClassFactory, (void **)&cf); 4128 ok_ole_success(hr, CoUnmarshalInterface); 4129 4130 hr = IClassFactory_CreateInstance(cf, NULL, &IID_IUnknown, (void **)&proxy); 4131 ok_ole_success(hr, IClassFactory_CreateInstance); 4132 4133 IUnknown_Release(proxy); 4134 4135 /* But if we initialize an STA in this apartment, it becomes the wrong one. */ 4136 CoInitializeEx(NULL, COINIT_APARTMENTTHREADED); 4137 4138 hr = IClassFactory_CreateInstance(cf, NULL, &IID_IUnknown, (void **)&proxy); 4139 ok(hr == RPC_E_WRONG_THREAD, "got %#x\n", hr); 4140 4141 CoUninitialize(); 4142 4143 ok_more_than_one_lock(); 4144 ok_non_zero_external_conn(); 4145 4146 IClassFactory_Release(cf); 4147 4148 ok_no_locks(); 4149 ok_zero_external_conn(); 4150 ok_last_release_closes(TRUE); 4151 return 0; 4152 } 4153 4154 static DWORD CALLBACK implicit_mta_use_proc(void *param) 4155 { 4156 IClassFactory *cf = param; 4157 IUnknown *proxy; 4158 HRESULT hr; 4159 4160 hr = IClassFactory_CreateInstance(cf, NULL, &IID_IUnknown, (void **)&proxy); 4161 ok_ole_success(hr, IClassFactory_CreateInstance); 4162 4163 IUnknown_Release(proxy); 4164 4165 /* But if we initialize an STA in this apartment, it becomes the wrong one. */ 4166 CoInitializeEx(NULL, COINIT_APARTMENTTHREADED); 4167 4168 hr = IClassFactory_CreateInstance(cf, NULL, &IID_IUnknown, (void **)&proxy); 4169 ok(hr == RPC_E_WRONG_THREAD, "got %#x\n", hr); 4170 4171 CoUninitialize(); 4172 return 0; 4173 } 4174 4175 struct implicit_mta_marshal_data 4176 { 4177 IStream *stream; 4178 HANDLE start; 4179 HANDLE stop; 4180 }; 4181 4182 static DWORD CALLBACK implicit_mta_marshal_proc(void *param) 4183 { 4184 struct implicit_mta_marshal_data *data = param; 4185 HRESULT hr; 4186 4187 hr = CoMarshalInterface(data->stream, &IID_IClassFactory, 4188 (IUnknown *)&Test_ClassFactory, MSHCTX_INPROC, NULL, MSHLFLAGS_NORMAL); 4189 ok_ole_success(hr, CoMarshalInterface); 4190 4191 SetEvent(data->start); 4192 4193 ok(!WaitForSingleObject(data->stop, 1000), "wait failed\n"); 4194 return 0; 4195 } 4196 4197 static void test_implicit_mta(void) 4198 { 4199 struct implicit_mta_marshal_data data; 4200 HANDLE host_thread, thread; 4201 IClassFactory *cf; 4202 IUnknown *proxy; 4203 IStream *stream; 4204 HRESULT hr; 4205 DWORD tid; 4206 4207 cLocks = 0; 4208 external_connections = 0; 4209 4210 CoInitializeEx(NULL, COINIT_MULTITHREADED); 4211 4212 /* Firstly: we can unmarshal and use an object while in the implicit MTA. */ 4213 hr = CreateStreamOnHGlobal(NULL, TRUE, &stream); 4214 ok_ole_success(hr, CreateStreamOnHGlobal); 4215 tid = start_host_object(stream, &IID_IClassFactory, (IUnknown *)&Test_ClassFactory, MSHLFLAGS_NORMAL, &host_thread); 4216 4217 ok_more_than_one_lock(); 4218 ok_non_zero_external_conn(); 4219 4220 thread = CreateThread(NULL, 0, implicit_mta_unmarshal_proc, stream, 0, NULL); 4221 ok(!WaitForSingleObject(thread, 1000), "wait failed\n"); 4222 CloseHandle(thread); 4223 4224 IStream_Release(stream); 4225 end_host_object(tid, host_thread); 4226 4227 /* Secondly: we can unmarshal an object into the real MTA and then use it 4228 * from the implicit MTA. */ 4229 hr = CreateStreamOnHGlobal(NULL, TRUE, &stream); 4230 ok_ole_success(hr, CreateStreamOnHGlobal); 4231 tid = start_host_object(stream, &IID_IClassFactory, (IUnknown *)&Test_ClassFactory, MSHLFLAGS_NORMAL, &host_thread); 4232 4233 ok_more_than_one_lock(); 4234 ok_non_zero_external_conn(); 4235 4236 IStream_Seek(stream, ullZero, STREAM_SEEK_SET, NULL); 4237 hr = CoUnmarshalInterface(stream, &IID_IClassFactory, (void **)&cf); 4238 ok_ole_success(hr, CoUnmarshalInterface); 4239 4240 thread = CreateThread(NULL, 0, implicit_mta_use_proc, cf, 0, NULL); 4241 ok(!WaitForSingleObject(thread, 1000), "wait failed\n"); 4242 CloseHandle(thread); 4243 4244 IClassFactory_Release(cf); 4245 IStream_Release(stream); 4246 4247 ok_no_locks(); 4248 ok_non_zero_external_conn(); 4249 ok_last_release_closes(TRUE); 4250 4251 end_host_object(tid, host_thread); 4252 4253 /* Thirdly: we can marshal an object from the implicit MTA and then 4254 * unmarshal it into the real one. */ 4255 data.start = CreateEventA(NULL, FALSE, FALSE, NULL); 4256 data.stop = CreateEventA(NULL, FALSE, FALSE, NULL); 4257 4258 hr = CreateStreamOnHGlobal(NULL, TRUE, &data.stream); 4259 ok_ole_success(hr, CreateStreamOnHGlobal); 4260 4261 thread = CreateThread(NULL, 0, implicit_mta_marshal_proc, &data, 0, NULL); 4262 ok(!WaitForSingleObject(data.start, 1000), "wait failed\n"); 4263 4264 IStream_Seek(data.stream, ullZero, STREAM_SEEK_SET, NULL); 4265 hr = CoUnmarshalInterface(data.stream, &IID_IClassFactory, (void **)&cf); 4266 ok_ole_success(hr, CoUnmarshalInterface); 4267 4268 hr = IClassFactory_CreateInstance(cf, NULL, &IID_IUnknown, (void **)&proxy); 4269 ok_ole_success(hr, IClassFactory_CreateInstance); 4270 4271 IUnknown_Release(proxy); 4272 4273 SetEvent(data.stop); 4274 ok(!WaitForSingleObject(thread, 1000), "wait failed\n"); 4275 CloseHandle(thread); 4276 4277 IStream_Release(data.stream); 4278 4279 CoUninitialize(); 4280 } 4281 4282 static const char *debugstr_iid(REFIID riid) 4283 { 4284 static char name[256]; 4285 HKEY hkeyInterface; 4286 WCHAR bufferW[39]; 4287 char buffer[39]; 4288 LONG name_size = sizeof(name); 4289 StringFromGUID2(riid, bufferW, ARRAY_SIZE(bufferW)); 4290 WideCharToMultiByte(CP_ACP, 0, bufferW, ARRAY_SIZE(bufferW), buffer, sizeof(buffer), NULL, NULL); 4291 if (RegOpenKeyExA(HKEY_CLASSES_ROOT, "Interface", 0, KEY_QUERY_VALUE, &hkeyInterface) != ERROR_SUCCESS) 4292 { 4293 memcpy(name, buffer, sizeof(buffer)); 4294 goto done; 4295 } 4296 if (RegQueryValueA(hkeyInterface, buffer, name, &name_size) != ERROR_SUCCESS) 4297 { 4298 memcpy(name, buffer, sizeof(buffer)); 4299 goto done; 4300 } 4301 RegCloseKey(hkeyInterface); 4302 done: 4303 return name; 4304 } 4305 4306 static HRESULT WINAPI TestChannelHook_QueryInterface(IChannelHook *iface, REFIID riid, void **ppv) 4307 { 4308 if (IsEqualIID(riid, &IID_IUnknown) || IsEqualIID(riid, &IID_IChannelHook)) 4309 { 4310 *ppv = iface; 4311 IChannelHook_AddRef(iface); 4312 return S_OK; 4313 } 4314 4315 *ppv = NULL; 4316 return E_NOINTERFACE; 4317 } 4318 4319 static ULONG WINAPI TestChannelHook_AddRef(IChannelHook *iface) 4320 { 4321 return 2; 4322 } 4323 4324 static ULONG WINAPI TestChannelHook_Release(IChannelHook *iface) 4325 { 4326 return 1; 4327 } 4328 4329 static BOOL new_hook_struct; 4330 static int method, server_tid; 4331 static GUID causality; 4332 4333 struct new_hook_info 4334 { 4335 IID iid; 4336 GUID causality; 4337 DWORD server_pid; 4338 DWORD server_tid; 4339 WORD method; 4340 }; 4341 4342 static void WINAPI TestChannelHook_ClientGetSize( 4343 IChannelHook *iface, 4344 REFGUID uExtent, 4345 REFIID riid, 4346 ULONG *pDataSize ) 4347 { 4348 SChannelHookCallInfo *info = (SChannelHookCallInfo *)riid; 4349 trace("TestChannelHook_ClientGetSize\n"); 4350 trace("\t%s\n", debugstr_iid(riid)); 4351 if (info->cbSize != sizeof(*info)) 4352 new_hook_struct = TRUE; 4353 4354 if (!new_hook_struct) 4355 { 4356 ok(info->cbSize == sizeof(*info), "cbSize was %d instead of %d\n", info->cbSize, (int)sizeof(*info)); 4357 ok(info->dwServerPid == GetCurrentProcessId(), "dwServerPid was 0x%x instead of 0x%x\n", info->dwServerPid, GetCurrentProcessId()); 4358 ok(info->iMethod == method, "iMethod was %d should be %d\n", info->iMethod, method); 4359 ok(!info->pObject, "pObject should be NULL\n"); 4360 if (method == 3) 4361 causality = info->uCausality; 4362 else 4363 ok(IsEqualGUID(&info->uCausality, &causality), "causality wasn't correct\n"); 4364 } 4365 else 4366 { 4367 struct new_hook_info *new_info = (struct new_hook_info *)riid; 4368 ok(new_info->server_pid == GetCurrentProcessId(), "server pid was 0x%x instead of 0x%x\n", new_info->server_pid, 4369 GetCurrentProcessId()); 4370 ok(new_info->server_tid == server_tid, "server tid was 0x%x instead of 0x%x\n", new_info->server_tid, 4371 server_tid); 4372 ok(new_info->method == method, "method was %d instead of %d\n", new_info->method, method); 4373 if (method == 3) 4374 causality = new_info->causality; 4375 else 4376 ok(IsEqualGUID(&new_info->causality, &causality), "causality wasn't correct\n"); 4377 } 4378 4379 ok(IsEqualGUID(uExtent, &EXTENTID_WineTest), "uExtent wasn't correct\n"); 4380 4381 *pDataSize = 1; 4382 } 4383 4384 static void WINAPI TestChannelHook_ClientFillBuffer( 4385 IChannelHook *iface, 4386 REFGUID uExtent, 4387 REFIID riid, 4388 ULONG *pDataSize, 4389 void *pDataBuffer ) 4390 { 4391 SChannelHookCallInfo *info = (SChannelHookCallInfo *)riid; 4392 trace("TestChannelHook_ClientFillBuffer\n"); 4393 4394 if (!new_hook_struct) 4395 { 4396 ok(info->cbSize == sizeof(*info), "cbSize was %d instead of %d\n", info->cbSize, (int)sizeof(*info)); 4397 ok(info->dwServerPid == GetCurrentProcessId(), "dwServerPid was 0x%x instead of 0x%x\n", info->dwServerPid, GetCurrentProcessId()); 4398 ok(info->iMethod == method, "iMethod was %d should be %d\n", info->iMethod, method); 4399 ok(!info->pObject, "pObject should be NULL\n"); 4400 ok(IsEqualGUID(&info->uCausality, &causality), "causality wasn't correct\n"); 4401 } 4402 else 4403 { 4404 struct new_hook_info *new_info = (struct new_hook_info *)riid; 4405 ok(new_info->server_pid == GetCurrentProcessId(), "server pid was 0x%x instead of 0x%x\n", new_info->server_pid, 4406 GetCurrentProcessId()); 4407 ok(new_info->server_tid == server_tid, "server tid was 0x%x instead of 0x%x\n", new_info->server_tid, 4408 server_tid); 4409 ok(new_info->method == method, "method was %d instead of %d\n", new_info->method, method); 4410 ok(IsEqualGUID(&new_info->causality, &causality), "causality wasn't correct\n"); 4411 } 4412 4413 ok(IsEqualGUID(uExtent, &EXTENTID_WineTest), "uExtent wasn't correct\n"); 4414 4415 *(unsigned char *)pDataBuffer = 0xcc; 4416 *pDataSize = 1; 4417 } 4418 4419 static void WINAPI TestChannelHook_ClientNotify( 4420 IChannelHook *iface, 4421 REFGUID uExtent, 4422 REFIID riid, 4423 ULONG cbDataSize, 4424 void *pDataBuffer, 4425 DWORD lDataRep, 4426 HRESULT hrFault ) 4427 { 4428 SChannelHookCallInfo *info = (SChannelHookCallInfo *)riid; 4429 trace("TestChannelHook_ClientNotify hrFault = 0x%08x\n", hrFault); 4430 4431 if (!new_hook_struct) 4432 { 4433 ok(info->cbSize == sizeof(*info), "cbSize was %d instead of %d\n", info->cbSize, (int)sizeof(*info)); 4434 ok(info->dwServerPid == GetCurrentProcessId(), "dwServerPid was 0x%x instead of 0x%x\n", info->dwServerPid, GetCurrentProcessId()); 4435 ok(info->iMethod == method, "iMethod was %d should be %d\n", info->iMethod, method); 4436 todo_wine { 4437 ok(info->pObject != NULL, "pObject shouldn't be NULL\n"); 4438 } 4439 ok(IsEqualGUID(&info->uCausality, &causality), "causality wasn't correct\n"); 4440 } 4441 else 4442 { 4443 struct new_hook_info *new_info = (struct new_hook_info *)riid; 4444 ok(new_info->server_pid == GetCurrentProcessId(), "server pid was 0x%x instead of 0x%x\n", new_info->server_pid, 4445 GetCurrentProcessId()); 4446 ok(new_info->server_tid == server_tid, "server tid was 0x%x instead of 0x%x\n", new_info->server_tid, 4447 server_tid); 4448 ok(new_info->method == method, "method was %d instead of %d\n", new_info->method, method); 4449 ok(IsEqualGUID(&new_info->causality, &causality), "causality wasn't correct\n"); 4450 } 4451 4452 ok(IsEqualGUID(uExtent, &EXTENTID_WineTest), "uExtent wasn't correct\n"); 4453 } 4454 4455 static void WINAPI TestChannelHook_ServerNotify( 4456 IChannelHook *iface, 4457 REFGUID uExtent, 4458 REFIID riid, 4459 ULONG cbDataSize, 4460 void *pDataBuffer, 4461 DWORD lDataRep ) 4462 { 4463 SChannelHookCallInfo *info = (SChannelHookCallInfo *)riid; 4464 trace("TestChannelHook_ServerNotify\n"); 4465 4466 if (!new_hook_struct) 4467 { 4468 ok(info->cbSize == sizeof(*info), "cbSize was %d instead of %d\n", info->cbSize, (int)sizeof(*info)); 4469 ok(info->dwServerPid == GetCurrentProcessId(), "dwServerPid was 0x%x instead of 0x%x\n", info->dwServerPid, GetCurrentProcessId()); 4470 ok(info->iMethod == method, "iMethod was %d should be %d\n", info->iMethod, method); 4471 ok(info->pObject != NULL, "pObject shouldn't be NULL\n"); 4472 ok(IsEqualGUID(&info->uCausality, &causality), "causality wasn't correct\n"); 4473 } 4474 else 4475 { 4476 struct new_hook_info *new_info = (struct new_hook_info *)riid; 4477 ok(new_info->server_pid == GetCurrentProcessId(), "server pid was 0x%x instead of 0x%x\n", new_info->server_pid, 4478 GetCurrentProcessId()); 4479 ok(new_info->server_tid == server_tid, "server tid was 0x%x instead of 0x%x\n", new_info->server_tid, 4480 server_tid); 4481 ok(new_info->method == method, "method was %d instead of %d\n", new_info->method, method); 4482 ok(IsEqualGUID(&new_info->causality, &causality), "causality wasn't correct\n"); 4483 } 4484 4485 ok(cbDataSize == 1, "cbDataSize should have been 1 instead of %d\n", cbDataSize); 4486 ok(*(unsigned char *)pDataBuffer == 0xcc, "pDataBuffer should have contained 0xcc instead of 0x%x\n", *(unsigned char *)pDataBuffer); 4487 ok(IsEqualGUID(uExtent, &EXTENTID_WineTest), "uExtent wasn't correct\n"); 4488 } 4489 4490 static void WINAPI TestChannelHook_ServerGetSize( 4491 IChannelHook *iface, 4492 REFGUID uExtent, 4493 REFIID riid, 4494 HRESULT hrFault, 4495 ULONG *pDataSize ) 4496 { 4497 SChannelHookCallInfo *info = (SChannelHookCallInfo *)riid; 4498 trace("TestChannelHook_ServerGetSize\n"); 4499 trace("\t%s\n", debugstr_iid(riid)); 4500 if (!new_hook_struct) 4501 { 4502 ok(info->cbSize == sizeof(*info), "cbSize was %d instead of %d\n", info->cbSize, (int)sizeof(*info)); 4503 ok(info->dwServerPid == GetCurrentProcessId(), "dwServerPid was 0x%x instead of 0x%x\n", info->dwServerPid, GetCurrentProcessId()); 4504 ok(info->iMethod == method, "iMethod was %d should be %d\n", info->iMethod, method); 4505 ok(info->pObject != NULL, "pObject shouldn't be NULL\n"); 4506 ok(IsEqualGUID(&info->uCausality, &causality), "causality wasn't correct\n"); 4507 } 4508 else 4509 { 4510 struct new_hook_info *new_info = (struct new_hook_info *)riid; 4511 ok(new_info->server_pid == GetCurrentProcessId(), "server pid was 0x%x instead of 0x%x\n", new_info->server_pid, 4512 GetCurrentProcessId()); 4513 ok(new_info->server_tid == server_tid, "server tid was 0x%x instead of 0x%x\n", new_info->server_tid, 4514 server_tid); 4515 ok(new_info->method == method, "method was %d instead of %d\n", new_info->method, method); 4516 ok(IsEqualGUID(&new_info->causality, &causality), "causality wasn't correct\n"); 4517 } 4518 4519 ok(IsEqualGUID(uExtent, &EXTENTID_WineTest), "uExtent wasn't correct\n"); 4520 if (hrFault != S_OK) 4521 trace("\thrFault = 0x%08x\n", hrFault); 4522 4523 *pDataSize = 0; 4524 } 4525 4526 static void WINAPI TestChannelHook_ServerFillBuffer( 4527 IChannelHook *iface, 4528 REFGUID uExtent, 4529 REFIID riid, 4530 ULONG *pDataSize, 4531 void *pDataBuffer, 4532 HRESULT hrFault ) 4533 { 4534 trace("TestChannelHook_ServerFillBuffer\n"); 4535 ok(0, "TestChannelHook_ServerFillBuffer shouldn't be called\n"); 4536 } 4537 4538 static const IChannelHookVtbl TestChannelHookVtbl = 4539 { 4540 TestChannelHook_QueryInterface, 4541 TestChannelHook_AddRef, 4542 TestChannelHook_Release, 4543 TestChannelHook_ClientGetSize, 4544 TestChannelHook_ClientFillBuffer, 4545 TestChannelHook_ClientNotify, 4546 TestChannelHook_ServerNotify, 4547 TestChannelHook_ServerGetSize, 4548 TestChannelHook_ServerFillBuffer, 4549 }; 4550 4551 static IChannelHook TestChannelHook = { &TestChannelHookVtbl }; 4552 4553 static void test_channel_hook(void) 4554 { 4555 IClassFactory *cf = NULL; 4556 DWORD tid; 4557 IUnknown *proxy = NULL; 4558 HANDLE thread; 4559 HRESULT hr; 4560 4561 struct host_object_data object_data = { NULL, &IID_IClassFactory, (IUnknown*)&Test_ClassFactory, 4562 MSHLFLAGS_NORMAL, &MessageFilter }; 4563 4564 hr = CoRegisterChannelHook(&EXTENTID_WineTest, &TestChannelHook); 4565 ok_ole_success(hr, CoRegisterChannelHook); 4566 4567 hr = CoRegisterMessageFilter(&MessageFilter, NULL); 4568 ok_ole_success(hr, CoRegisterMessageFilter); 4569 4570 cLocks = 0; 4571 4572 hr = CreateStreamOnHGlobal(NULL, TRUE, &object_data.stream); 4573 ok_ole_success(hr, CreateStreamOnHGlobal); 4574 tid = start_host_object2(&object_data, &thread); 4575 server_tid = tid; 4576 4577 ok_more_than_one_lock(); 4578 4579 IStream_Seek(object_data.stream, ullZero, STREAM_SEEK_SET, NULL); 4580 hr = CoUnmarshalInterface(object_data.stream, &IID_IClassFactory, (void **)&cf); 4581 ok_ole_success(hr, CoUnmarshalInterface); 4582 IStream_Release(object_data.stream); 4583 4584 ok_more_than_one_lock(); 4585 4586 method = 3; 4587 hr = IClassFactory_CreateInstance(cf, NULL, &IID_IUnknown, (LPVOID*)&proxy); 4588 ok_ole_success(hr, IClassFactory_CreateInstance); 4589 4590 method = 5; 4591 IUnknown_Release(proxy); 4592 4593 IClassFactory_Release(cf); 4594 4595 ok_no_locks(); 4596 4597 end_host_object(tid, thread); 4598 4599 hr = CoRegisterMessageFilter(NULL, NULL); 4600 ok_ole_success(hr, CoRegisterMessageFilter); 4601 } 4602 4603 START_TEST(marshal) 4604 { 4605 HMODULE hOle32 = GetModuleHandleA("ole32"); 4606 int argc; 4607 char **argv; 4608 4609 if (!GetProcAddress(hOle32, "CoRegisterSurrogateEx")) { 4610 win_skip("skipping test on win9x\n"); 4611 return; 4612 } 4613 4614 pCoInitializeEx = (void*)GetProcAddress(hOle32, "CoInitializeEx"); 4615 pDllGetClassObject = (void*)GetProcAddress(hOle32, "DllGetClassObject"); 4616 4617 argc = winetest_get_mainargs( &argv ); 4618 if (argc > 2 && (!strcmp(argv[2], "-Embedding"))) 4619 { 4620 pCoInitializeEx(NULL, COINIT_MULTITHREADED); 4621 test_register_local_server(); 4622 CoUninitialize(); 4623 4624 return; 4625 } 4626 4627 register_test_window(); 4628 4629 test_cocreateinstance_proxy(); 4630 test_implicit_mta(); 4631 4632 pCoInitializeEx(NULL, COINIT_APARTMENTTHREADED); 4633 4634 /* FIXME: test CoCreateInstanceEx */ 4635 4636 /* lifecycle management and marshaling tests */ 4637 do 4638 { 4639 test_no_marshaler(); 4640 test_normal_marshal_and_release(); 4641 test_normal_marshal_and_unmarshal(); 4642 test_marshal_and_unmarshal_invalid(); 4643 test_same_apartment_unmarshal_failure(); 4644 test_interthread_marshal_and_unmarshal(); 4645 test_proxy_marshal_and_unmarshal(); 4646 test_proxy_marshal_and_unmarshal2(); 4647 test_proxy_marshal_and_unmarshal_weak(); 4648 test_proxy_marshal_and_unmarshal_strong(); 4649 test_marshal_stub_apartment_shutdown(); 4650 test_marshal_proxy_apartment_shutdown(); 4651 test_marshal_proxy_mta_apartment_shutdown(); 4652 test_no_couninitialize_server(); 4653 test_no_couninitialize_client(); 4654 test_tableweak_marshal_and_unmarshal_twice(); 4655 test_tableweak_marshal_releasedata1(); 4656 test_tableweak_marshal_releasedata2(); 4657 test_tableweak_and_normal_marshal_and_unmarshal(); 4658 test_tableweak_and_normal_marshal_and_releasedata(); 4659 test_two_tableweak_marshal_and_releasedata(); 4660 test_tablestrong_marshal_and_unmarshal_twice(); 4661 test_lock_object_external(); 4662 test_disconnect_stub(); 4663 test_normal_marshal_and_unmarshal_twice(); 4664 4665 with_external_conn = !with_external_conn; 4666 } while (with_external_conn); 4667 4668 test_marshal_channel_buffer(); 4669 test_StdMarshal_custom_marshaling(); 4670 test_DfMarshal_custom_marshaling(); 4671 test_CoGetStandardMarshal(); 4672 test_hresult_marshaling(); 4673 test_proxy_used_in_wrong_thread(); 4674 test_message_filter(); 4675 test_bad_marshal_stream(); 4676 test_proxy_interfaces(); 4677 test_stubbuffer(&IID_IClassFactory); 4678 test_proxybuffer(&IID_IClassFactory); 4679 test_message_reentrancy(); 4680 test_call_from_message(); 4681 test_WM_QUIT_handling(); 4682 test_freethreadedmarshaler(); 4683 test_inproc_handler(); 4684 test_handler_marshaling(); 4685 test_client_security(); 4686 4687 test_local_server(); 4688 4689 test_globalinterfacetable(); 4690 test_manualresetevent(); 4691 test_crash_couninitialize(); 4692 4693 /* must be last test as channel hooks can't be unregistered */ 4694 test_channel_hook(); 4695 4696 CoUninitialize(); 4697 } 4698