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((IUnknown*)&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 IUnknown *pProxy = NULL; 1209 DWORD tid; 1210 HANDLE thread; 1211 1212 cLocks = 0; 1213 external_connections = 0; 1214 1215 hr = CreateStreamOnHGlobal(NULL, TRUE, &pStream); 1216 ok_ole_success(hr, CreateStreamOnHGlobal); 1217 tid = start_host_object(pStream, &IID_IClassFactory, (IUnknown*)&Test_ClassFactory, MSHLFLAGS_NORMAL, &thread); 1218 1219 ok_more_than_one_lock(); 1220 ok_non_zero_external_conn(); 1221 1222 IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL); 1223 hr = CoUnmarshalInterface(pStream, &IID_IClassFactory, (void **)&pProxy); 1224 ok_ole_success(hr, CoUnmarshalInterface); 1225 IStream_Release(pStream); 1226 1227 ok_more_than_one_lock(); 1228 ok_non_zero_external_conn(); 1229 1230 CoUninitialize(); 1231 1232 ok_no_locks(); 1233 ok_zero_external_conn(); 1234 ok_last_release_closes(TRUE); 1235 1236 IUnknown_Release(pProxy); 1237 1238 ok_no_locks(); 1239 1240 end_host_object(tid, thread); 1241 1242 pCoInitializeEx(NULL, COINIT_APARTMENTTHREADED); 1243 } 1244 1245 /* tests that proxies are released when the containing mta apartment is destroyed */ 1246 static void test_marshal_proxy_mta_apartment_shutdown(void) 1247 { 1248 HRESULT hr; 1249 IStream *pStream = NULL; 1250 IUnknown *pProxy = NULL; 1251 DWORD tid; 1252 HANDLE thread; 1253 1254 CoUninitialize(); 1255 pCoInitializeEx(NULL, COINIT_MULTITHREADED); 1256 1257 cLocks = 0; 1258 external_connections = 0; 1259 1260 hr = CreateStreamOnHGlobal(NULL, TRUE, &pStream); 1261 ok_ole_success(hr, CreateStreamOnHGlobal); 1262 tid = start_host_object(pStream, &IID_IClassFactory, (IUnknown*)&Test_ClassFactory, MSHLFLAGS_NORMAL, &thread); 1263 1264 ok_more_than_one_lock(); 1265 ok_non_zero_external_conn(); 1266 1267 IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL); 1268 hr = CoUnmarshalInterface(pStream, &IID_IClassFactory, (void **)&pProxy); 1269 ok_ole_success(hr, CoUnmarshalInterface); 1270 IStream_Release(pStream); 1271 1272 ok_more_than_one_lock(); 1273 ok_non_zero_external_conn(); 1274 1275 CoUninitialize(); 1276 1277 ok_no_locks(); 1278 ok_zero_external_conn(); 1279 ok_last_release_closes(TRUE); 1280 1281 IUnknown_Release(pProxy); 1282 1283 ok_no_locks(); 1284 1285 end_host_object(tid, thread); 1286 1287 pCoInitializeEx(NULL, COINIT_APARTMENTTHREADED); 1288 } 1289 1290 static void test_marshal_channel_buffer(void) 1291 { 1292 DWORD registration_key; 1293 IUnknown *proxy = NULL; 1294 IOleWindow *ole_window; 1295 HWND hwnd; 1296 CLSID clsid; 1297 DWORD tid; 1298 HANDLE thread; 1299 HRESULT hr; 1300 1301 struct host_object_data object_data = { NULL, &IID_IOleClientSite, (IUnknown*)&Test_OleClientSite, 1302 MSHLFLAGS_NORMAL, NULL, (IUnknown*)&PSFactoryBuffer, 1303 &CLSID_WineTestPSFactoryBuffer }; 1304 1305 cLocks = 0; 1306 external_connections = 0; 1307 1308 hr = CoGetPSClsid(&IID_IOleWindow, &clsid); 1309 ok_ole_success(hr, "CoGetPSClsid"); 1310 1311 hr = CoGetClassObject(&clsid, CLSCTX_INPROC_SERVER, NULL, &IID_IPSFactoryBuffer, 1312 (void **)&ps_factory_buffer); 1313 ok_ole_success(hr, "CoGetClassObject"); 1314 1315 hr = CreateStreamOnHGlobal(NULL, TRUE, &object_data.stream); 1316 ok_ole_success(hr, CreateStreamOnHGlobal); 1317 tid = start_host_object2(&object_data, &thread); 1318 1319 IStream_Seek(object_data.stream, ullZero, STREAM_SEEK_SET, NULL); 1320 hr = CoUnmarshalInterface(object_data.stream, &IID_IUnknown, (void **)&proxy); 1321 ok_ole_success(hr, CoUnmarshalInterface); 1322 IStream_Release(object_data.stream); 1323 1324 hr = CoRegisterClassObject(&CLSID_WineTestPSFactoryBuffer, (IUnknown *)&PSFactoryBuffer, 1325 CLSCTX_INPROC_SERVER, REGCLS_MULTIPLEUSE, ®istration_key); 1326 ok(hr == S_OK, "CoRegisterClassObject failed: %08x\n", hr); 1327 1328 hr = CoRegisterPSClsid(&IID_IOleWindow, &CLSID_WineTestPSFactoryBuffer); 1329 ok(hr == S_OK, "CoRegisterPSClsid failed: %08x\n", hr); 1330 1331 SET_EXPECT(CreateStub); 1332 SET_EXPECT(CreateProxy); 1333 hr = IUnknown_QueryInterface(proxy, &IID_IOleWindow, (void**)&ole_window); 1334 ok(hr == S_OK, "Could not get IOleWindow iface: %08x\n", hr); 1335 CHECK_CALLED(CreateStub); 1336 CHECK_CALLED(CreateProxy); 1337 1338 SET_EXPECT(Invoke); 1339 SET_EXPECT(GetWindow); 1340 hr = IOleWindow_GetWindow(ole_window, &hwnd); 1341 ok(hr == S_OK, "GetWindow failed: %08x\n", hr); 1342 ok((DWORD)(DWORD_PTR)hwnd == 0xdeadbeef, "hwnd = %p\n", hwnd); 1343 CHECK_CALLED(Invoke); 1344 CHECK_CALLED(GetWindow); 1345 1346 IOleWindow_Release(ole_window); 1347 1348 SET_EXPECT(Disconnect); 1349 IUnknown_Release(proxy); 1350 todo_wine 1351 CHECK_CALLED(Disconnect); 1352 1353 hr = CoRevokeClassObject(registration_key); 1354 ok(hr == S_OK, "CoRevokeClassObject failed: %08x\n", hr); 1355 1356 end_host_object(tid, thread); 1357 } 1358 1359 static const CLSID *unmarshal_class; 1360 DEFINE_EXPECT(CustomMarshal_GetUnmarshalClass); 1361 DEFINE_EXPECT(CustomMarshal_GetMarshalSizeMax); 1362 DEFINE_EXPECT(CustomMarshal_MarshalInterface); 1363 1364 static HRESULT WINAPI CustomMarshal_QueryInterface(IMarshal *iface, REFIID riid, void **ppv) 1365 { 1366 if (IsEqualIID(riid, &IID_IUnknown) || IsEqualIID(riid, &IID_IMarshal)) { 1367 *ppv = iface; 1368 } 1369 else 1370 { 1371 *ppv = NULL; 1372 return E_NOINTERFACE; 1373 } 1374 IUnknown_AddRef((IUnknown*)*ppv); 1375 return S_OK; 1376 } 1377 1378 static ULONG WINAPI CustomMarshal_AddRef(IMarshal *iface) 1379 { 1380 return 2; 1381 } 1382 1383 static ULONG WINAPI CustomMarshal_Release(IMarshal *iface) 1384 { 1385 return 1; 1386 } 1387 1388 static HRESULT WINAPI CustomMarshal_GetUnmarshalClass(IMarshal *iface, REFIID riid, 1389 void *pv, DWORD dwDestContext, void *pvDestContext, DWORD mshlflags, CLSID *clsid) 1390 { 1391 CHECK_EXPECT(CustomMarshal_GetUnmarshalClass); 1392 *clsid = *unmarshal_class; 1393 return S_OK; 1394 } 1395 1396 static HRESULT WINAPI CustomMarshal_GetMarshalSizeMax(IMarshal *iface, REFIID riid, 1397 void *pv, DWORD dwDestContext, void *pvDestContext, DWORD mshlflags, DWORD *size) 1398 { 1399 CHECK_EXPECT(CustomMarshal_GetMarshalSizeMax); 1400 ok(size != NULL, "size = NULL\n"); 1401 1402 *size = 0; 1403 return S_OK; 1404 } 1405 1406 static HRESULT WINAPI CustomMarshal_MarshalInterface(IMarshal *iface, IStream *stream, 1407 REFIID riid, void *pv, DWORD dwDestContext, void *pvDestContext, DWORD mshlflags) 1408 { 1409 IMarshal *std_marshal; 1410 STATSTG stat; 1411 HRESULT hr; 1412 1413 CHECK_EXPECT(CustomMarshal_MarshalInterface); 1414 1415 if(unmarshal_class != &CLSID_StdMarshal) 1416 return S_OK; 1417 1418 hr = IStream_Stat(stream, &stat, STATFLAG_DEFAULT); 1419 ok_ole_success(hr, IStream_Stat); 1420 ok(U(stat.cbSize).LowPart == 0, "stream is not empty (%d)\n", U(stat.cbSize).LowPart); 1421 ok(U(stat.cbSize).HighPart == 0, "stream is not empty (%d)\n", U(stat.cbSize).HighPart); 1422 1423 hr = CoGetStandardMarshal(riid, (IUnknown*)iface, 1424 dwDestContext, NULL, mshlflags, &std_marshal); 1425 ok_ole_success(hr, CoGetStandardMarshal); 1426 hr = IMarshal_MarshalInterface(std_marshal, stream, riid, pv, 1427 dwDestContext, pvDestContext, mshlflags); 1428 ok_ole_success(hr, IMarshal_MarshalInterface); 1429 IMarshal_Release(std_marshal); 1430 1431 return S_OK; 1432 } 1433 1434 static HRESULT WINAPI CustomMarshal_UnmarshalInterface(IMarshal *iface, 1435 IStream *stream, REFIID riid, void **ppv) 1436 { 1437 ok(0, "unexpected call\n"); 1438 return E_NOTIMPL; 1439 } 1440 1441 static HRESULT WINAPI CustomMarshal_ReleaseMarshalData(IMarshal *iface, IStream *stream) 1442 { 1443 ok(0, "unexpected call\n"); 1444 return E_NOTIMPL; 1445 } 1446 1447 static HRESULT WINAPI CustomMarshal_DisconnectObject(IMarshal *iface, DWORD res) 1448 { 1449 ok(0, "unexpected call\n"); 1450 return E_NOTIMPL; 1451 } 1452 1453 static IMarshalVtbl CustomMarshalVtbl = 1454 { 1455 CustomMarshal_QueryInterface, 1456 CustomMarshal_AddRef, 1457 CustomMarshal_Release, 1458 CustomMarshal_GetUnmarshalClass, 1459 CustomMarshal_GetMarshalSizeMax, 1460 CustomMarshal_MarshalInterface, 1461 CustomMarshal_UnmarshalInterface, 1462 CustomMarshal_ReleaseMarshalData, 1463 CustomMarshal_DisconnectObject 1464 }; 1465 1466 static IMarshal CustomMarshal = { &CustomMarshalVtbl }; 1467 1468 static void test_StdMarshal_custom_marshaling(void) 1469 { 1470 IStream *stream; 1471 IUnknown *unk; 1472 DWORD size; 1473 HRESULT hr; 1474 1475 hr = CreateStreamOnHGlobal(NULL, TRUE, &stream); 1476 ok_ole_success(hr, CreateStreamOnHGlobal); 1477 1478 unmarshal_class = &CLSID_StdMarshal; 1479 SET_EXPECT(CustomMarshal_GetUnmarshalClass); 1480 SET_EXPECT(CustomMarshal_MarshalInterface); 1481 hr = CoMarshalInterface(stream, &IID_IUnknown, (IUnknown*)&CustomMarshal, 1482 MSHCTX_INPROC, NULL, MSHLFLAGS_NORMAL); 1483 ok_ole_success(hr, CoMarshalInterface); 1484 CHECK_CALLED(CustomMarshal_GetUnmarshalClass); 1485 CHECK_CALLED(CustomMarshal_MarshalInterface); 1486 1487 hr = IStream_Seek(stream, ullZero, STREAM_SEEK_SET, NULL); 1488 ok_ole_success(hr, IStream_Seek); 1489 hr = CoUnmarshalInterface(stream, &IID_IUnknown, (void**)&unk); 1490 ok_ole_success(hr, CoUnmarshalInterface); 1491 ok(unk == (IUnknown*)&CustomMarshal, "unk != &CustomMarshal\n"); 1492 IUnknown_Release(unk); 1493 IStream_Release(stream); 1494 1495 hr = CreateStreamOnHGlobal(NULL, TRUE, &stream); 1496 ok_ole_success(hr, CreateStreamOnHGlobal); 1497 1498 SET_EXPECT(CustomMarshal_GetUnmarshalClass); 1499 SET_EXPECT(CustomMarshal_MarshalInterface); 1500 hr = CoMarshalInterface(stream, &IID_IUnknown, (IUnknown*)&CustomMarshal, 1501 MSHCTX_INPROC, NULL, MSHLFLAGS_NORMAL); 1502 ok_ole_success(hr, CoMarshalInterface); 1503 CHECK_CALLED(CustomMarshal_GetUnmarshalClass); 1504 CHECK_CALLED(CustomMarshal_MarshalInterface); 1505 1506 hr = IStream_Seek(stream, ullZero, STREAM_SEEK_SET, NULL); 1507 ok_ole_success(hr, IStream_Seek); 1508 hr = CoReleaseMarshalData(stream); 1509 ok_ole_success(hr, CoReleaseMarshalData); 1510 IStream_Release(stream); 1511 1512 SET_EXPECT(CustomMarshal_GetMarshalSizeMax); 1513 hr = CoGetMarshalSizeMax(&size, &IID_IUnknown, (IUnknown*)&CustomMarshal, 1514 MSHCTX_INPROC, NULL, MSHLFLAGS_NORMAL); 1515 ok_ole_success(hr, CoGetMarshalSizeMax); 1516 CHECK_CALLED(CustomMarshal_GetMarshalSizeMax); 1517 ok(size == sizeof(OBJREF), "size = %d, expected %d\n", size, (int)sizeof(OBJREF)); 1518 } 1519 1520 static void test_DfMarshal_custom_marshaling(void) 1521 { 1522 DWORD size, read; 1523 IStream *stream; 1524 OBJREF objref; 1525 HRESULT hr; 1526 1527 hr = CreateStreamOnHGlobal(NULL, TRUE, &stream); 1528 ok_ole_success(hr, CreateStreamOnHGlobal); 1529 1530 unmarshal_class = &CLSID_DfMarshal; 1531 SET_EXPECT(CustomMarshal_GetUnmarshalClass); 1532 SET_EXPECT(CustomMarshal_GetMarshalSizeMax); 1533 SET_EXPECT(CustomMarshal_MarshalInterface); 1534 hr = CoMarshalInterface(stream, &IID_IUnknown, (IUnknown*)&CustomMarshal, 1535 MSHCTX_INPROC, NULL, MSHLFLAGS_NORMAL); 1536 ok_ole_success(hr, CoMarshalInterface); 1537 CHECK_CALLED(CustomMarshal_GetUnmarshalClass); 1538 CHECK_CALLED(CustomMarshal_GetMarshalSizeMax); 1539 CHECK_CALLED(CustomMarshal_MarshalInterface); 1540 1541 hr = IStream_Seek(stream, ullZero, STREAM_SEEK_SET, NULL); 1542 ok_ole_success(hr, IStream_Seek); 1543 size = FIELD_OFFSET(OBJREF, u_objref.u_custom.pData); 1544 hr = IStream_Read(stream, &objref, size, &read); 1545 ok_ole_success(hr, IStream_Read); 1546 ok(read == size, "read = %d, expected %d\n", read, size); 1547 ok(objref.signature == OBJREF_SIGNATURE, "objref.signature = %x\n", 1548 objref.signature); 1549 ok(objref.flags == OBJREF_CUSTOM, "objref.flags = %x\n", objref.flags); 1550 ok(IsEqualIID(&objref.iid, &IID_IUnknown), "objref.iid = %s\n", 1551 wine_dbgstr_guid(&objref.iid)); 1552 ok(IsEqualIID(&objref.u_objref.u_custom.clsid, &CLSID_DfMarshal), 1553 "custom.clsid = %s\n", wine_dbgstr_guid(&objref.u_objref.u_custom.clsid)); 1554 ok(!objref.u_objref.u_custom.cbExtension, "custom.cbExtension = %d\n", 1555 objref.u_objref.u_custom.cbExtension); 1556 ok(!objref.u_objref.u_custom.size, "custom.size = %d\n", 1557 objref.u_objref.u_custom.size); 1558 1559 IStream_Release(stream); 1560 1561 SET_EXPECT(CustomMarshal_GetMarshalSizeMax); 1562 hr = CoGetMarshalSizeMax(&size, &IID_IUnknown, (IUnknown*)&CustomMarshal, 1563 MSHCTX_INPROC, NULL, MSHLFLAGS_NORMAL); 1564 ok_ole_success(hr, CoGetMarshalSizeMax); 1565 CHECK_CALLED(CustomMarshal_GetMarshalSizeMax); 1566 ok(size == sizeof(OBJREF), "size = %d, expected %d\n", size, (int)sizeof(OBJREF)); 1567 } 1568 1569 static void test_CoGetStandardMarshal(void) 1570 { 1571 DUALSTRINGARRAY *dualstringarr; 1572 STDOBJREF *stdobjref; 1573 OBJREF objref; 1574 IMarshal *marshal; 1575 DWORD size, read; 1576 IStream *stream; 1577 IUnknown *unk; 1578 CLSID clsid; 1579 HRESULT hr; 1580 1581 hr = CreateStreamOnHGlobal(NULL, TRUE, &stream); 1582 ok_ole_success(hr, CreateStreamOnHGlobal); 1583 1584 hr = CoGetStandardMarshal(&IID_IUnknown, &Test_Unknown, 1585 MSHCTX_INPROC, NULL, MSHLFLAGS_NORMAL, &marshal); 1586 ok_ole_success(hr, CoGetStandardMarshal); 1587 1588 hr = IMarshal_GetUnmarshalClass(marshal, &IID_IUnknown, &Test_Unknown, 1589 MSHCTX_INPROC, NULL, MSHLFLAGS_NORMAL, &clsid); 1590 ok_ole_success(hr, IMarshal_GetUnmarshalClass); 1591 ok(IsEqualGUID(&clsid, &CLSID_StdMarshal), "clsid = %s\n", wine_dbgstr_guid(&clsid)); 1592 1593 hr = IMarshal_GetMarshalSizeMax(marshal, &IID_IUnknown, &Test_Unknown, 1594 MSHCTX_INPROC, NULL, MSHLFLAGS_NORMAL, &size); 1595 ok_ole_success(hr, IMarshal_GetMarshalSizeMax); 1596 hr = CoGetMarshalSizeMax(&read, &IID_IUnknown, &Test_Unknown, 1597 MSHCTX_INPROC, NULL, MSHLFLAGS_NORMAL); 1598 ok_ole_success(hr, CoGetMarshalSizeMax); 1599 ok(size == read, "IMarshal_GetMarshalSizeMax size = %d, expected %d\n", size, read); 1600 1601 hr = IMarshal_MarshalInterface(marshal, stream, &IID_IUnknown, 1602 &Test_Unknown, MSHCTX_INPROC, NULL, MSHLFLAGS_NORMAL); 1603 ok_ole_success(hr, IMarshal_MarshalInterface); 1604 1605 hr = IStream_Seek(stream, ullZero, STREAM_SEEK_SET, NULL); 1606 ok_ole_success(hr, IStream_Seek); 1607 size = FIELD_OFFSET(OBJREF, u_objref.u_standard.saResAddr.aStringArray); 1608 hr = IStream_Read(stream, &objref, size, &read); 1609 ok_ole_success(hr, IStream_Read); 1610 ok(read == size, "read = %d, expected %d\n", read, size); 1611 ok(objref.signature == OBJREF_SIGNATURE, "objref.signature = %x\n", 1612 objref.signature); 1613 ok(objref.flags == OBJREF_STANDARD, "objref.flags = %x\n", objref.flags); 1614 ok(IsEqualIID(&objref.iid, &IID_IUnknown), "objref.iid = %s\n", 1615 wine_dbgstr_guid(&objref.iid)); 1616 stdobjref = &objref.u_objref.u_standard.std; 1617 ok(stdobjref->flags == 0, "stdobjref.flags = %d\n", stdobjref->flags); 1618 ok(stdobjref->cPublicRefs == 5, "stdobjref.cPublicRefs = %d\n", 1619 stdobjref->cPublicRefs); 1620 dualstringarr = &objref.u_objref.u_standard.saResAddr; 1621 ok(dualstringarr->wNumEntries == 0, "dualstringarr.wNumEntries = %d\n", 1622 dualstringarr->wNumEntries); 1623 ok(dualstringarr->wSecurityOffset == 0, "dualstringarr.wSecurityOffset = %d\n", 1624 dualstringarr->wSecurityOffset); 1625 1626 hr = IStream_Seek(stream, ullZero, STREAM_SEEK_SET, NULL); 1627 ok_ole_success(hr, IStream_Seek); 1628 hr = IMarshal_UnmarshalInterface(marshal, stream, &IID_IUnknown, (void**)&unk); 1629 ok_ole_success(hr, IMarshal_UnmarshalInterface); 1630 IUnknown_Release(unk); 1631 1632 hr = IStream_Seek(stream, ullZero, STREAM_SEEK_SET, NULL); 1633 ok_ole_success(hr, IStream_Seek); 1634 hr = IMarshal_MarshalInterface(marshal, stream, &IID_IUnknown, 1635 &Test_Unknown, MSHCTX_INPROC, NULL, MSHLFLAGS_NORMAL); 1636 ok_ole_success(hr, IMarshal_MarshalInterface); 1637 1638 hr = IStream_Seek(stream, ullZero, STREAM_SEEK_SET, NULL); 1639 ok_ole_success(hr, IStream_Seek); 1640 hr = IMarshal_ReleaseMarshalData(marshal, stream); 1641 ok_ole_success(hr, IMarshal_ReleaseMarshalData); 1642 IStream_Release(stream); 1643 1644 IMarshal_Release(marshal); 1645 } 1646 struct ncu_params 1647 { 1648 LPSTREAM stream; 1649 HANDLE marshal_event; 1650 HANDLE unmarshal_event; 1651 }; 1652 1653 /* helper for test_no_couninitialize_server */ 1654 static DWORD CALLBACK no_couninitialize_server_proc(LPVOID p) 1655 { 1656 struct ncu_params *ncu_params = p; 1657 HRESULT hr; 1658 1659 pCoInitializeEx(NULL, COINIT_MULTITHREADED); 1660 1661 hr = CoMarshalInterface(ncu_params->stream, &IID_IClassFactory, (IUnknown*)&Test_ClassFactory, MSHCTX_INPROC, NULL, MSHLFLAGS_NORMAL); 1662 ok_ole_success(hr, CoMarshalInterface); 1663 1664 SetEvent(ncu_params->marshal_event); 1665 1666 ok( !WaitForSingleObject(ncu_params->unmarshal_event, 10000), "wait timed out\n" ); 1667 1668 /* die without calling CoUninitialize */ 1669 1670 return 0; 1671 } 1672 1673 /* tests apartment that an apartment with a stub is released without deadlock 1674 * if the owning thread exits */ 1675 static void test_no_couninitialize_server(void) 1676 { 1677 HRESULT hr; 1678 IStream *pStream = NULL; 1679 IUnknown *pProxy = NULL; 1680 DWORD tid; 1681 HANDLE thread; 1682 struct ncu_params ncu_params; 1683 1684 cLocks = 0; 1685 external_connections = 0; 1686 1687 ncu_params.marshal_event = CreateEventA(NULL, TRUE, FALSE, NULL); 1688 ncu_params.unmarshal_event = CreateEventA(NULL, TRUE, FALSE, NULL); 1689 1690 hr = CreateStreamOnHGlobal(NULL, TRUE, &pStream); 1691 ok_ole_success(hr, CreateStreamOnHGlobal); 1692 ncu_params.stream = pStream; 1693 1694 thread = CreateThread(NULL, 0, no_couninitialize_server_proc, &ncu_params, 0, &tid); 1695 1696 ok( !WaitForSingleObject(ncu_params.marshal_event, 10000), "wait timed out\n" ); 1697 ok_more_than_one_lock(); 1698 ok_non_zero_external_conn(); 1699 1700 IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL); 1701 hr = CoUnmarshalInterface(pStream, &IID_IClassFactory, (void **)&pProxy); 1702 ok_ole_success(hr, CoUnmarshalInterface); 1703 IStream_Release(pStream); 1704 1705 ok_more_than_one_lock(); 1706 ok_non_zero_external_conn(); 1707 1708 SetEvent(ncu_params.unmarshal_event); 1709 ok( !WaitForSingleObject(thread, 10000), "wait timed out\n" ); 1710 1711 ok_no_locks(); 1712 todo_wine { 1713 ok_zero_external_conn(); 1714 ok_last_release_closes(FALSE); 1715 } 1716 1717 CloseHandle(thread); 1718 CloseHandle(ncu_params.marshal_event); 1719 CloseHandle(ncu_params.unmarshal_event); 1720 1721 IUnknown_Release(pProxy); 1722 1723 ok_no_locks(); 1724 } 1725 1726 /* STA -> STA call during DLL_THREAD_DETACH */ 1727 static DWORD CALLBACK no_couninitialize_client_proc(LPVOID p) 1728 { 1729 struct ncu_params *ncu_params = p; 1730 HRESULT hr; 1731 IUnknown *pProxy = NULL; 1732 1733 pCoInitializeEx(NULL, COINIT_APARTMENTTHREADED); 1734 1735 hr = CoUnmarshalInterface(ncu_params->stream, &IID_IClassFactory, (void **)&pProxy); 1736 ok_ole_success(hr, CoUnmarshalInterface); 1737 IStream_Release(ncu_params->stream); 1738 1739 ok_more_than_one_lock(); 1740 1741 /* die without calling CoUninitialize */ 1742 1743 return 0; 1744 } 1745 1746 /* tests STA -> STA call during DLL_THREAD_DETACH doesn't deadlock */ 1747 static void test_no_couninitialize_client(void) 1748 { 1749 HRESULT hr; 1750 IStream *pStream = NULL; 1751 DWORD tid; 1752 DWORD host_tid; 1753 HANDLE thread; 1754 HANDLE host_thread; 1755 struct ncu_params ncu_params; 1756 1757 cLocks = 0; 1758 external_connections = 0; 1759 1760 hr = CreateStreamOnHGlobal(NULL, TRUE, &pStream); 1761 ok_ole_success(hr, CreateStreamOnHGlobal); 1762 ncu_params.stream = pStream; 1763 1764 /* NOTE: assumes start_host_object uses an STA to host the object, as MTAs 1765 * always deadlock when called from within DllMain */ 1766 host_tid = start_host_object(pStream, &IID_IClassFactory, (IUnknown *)&Test_ClassFactory, MSHLFLAGS_NORMAL, &host_thread); 1767 IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL); 1768 1769 ok_more_than_one_lock(); 1770 ok_non_zero_external_conn(); 1771 1772 thread = CreateThread(NULL, 0, no_couninitialize_client_proc, &ncu_params, 0, &tid); 1773 1774 ok( !WaitForSingleObject(thread, 10000), "wait timed out\n" ); 1775 CloseHandle(thread); 1776 1777 ok_no_locks(); 1778 ok_zero_external_conn(); 1779 ok_last_release_closes(TRUE); 1780 1781 end_host_object(host_tid, host_thread); 1782 } 1783 1784 static BOOL crash_thread_success; 1785 1786 static DWORD CALLBACK crash_couninitialize_proc(void *p) 1787 { 1788 IStream *stream; 1789 HRESULT hr; 1790 1791 cLocks = 0; 1792 1793 CoInitialize(NULL); 1794 1795 hr = CreateStreamOnHGlobal(NULL, TRUE, &stream); 1796 ok_ole_success(hr, CreateStreamOnHGlobal); 1797 1798 hr = CoMarshalInterface(stream, &IID_IUnknown, &TestCrash_Unknown, MSHCTX_INPROC, NULL, MSHLFLAGS_NORMAL); 1799 ok_ole_success(hr, CoMarshalInterface); 1800 1801 IStream_Seek(stream, ullZero, STREAM_SEEK_SET, NULL); 1802 1803 hr = CoReleaseMarshalData(stream); 1804 ok_ole_success(hr, CoReleaseMarshalData); 1805 1806 ok_no_locks(); 1807 1808 hr = CoMarshalInterface(stream, &IID_IUnknown, &TestCrash_Unknown, MSHCTX_INPROC, NULL, MSHLFLAGS_NORMAL); 1809 ok_ole_success(hr, CoMarshalInterface); 1810 1811 ok_more_than_one_lock(); 1812 1813 trace("CoUninitialize >>>\n"); 1814 CoUninitialize(); 1815 trace("CoUninitialize <<<\n"); 1816 1817 ok_no_locks(); 1818 1819 IStream_Release(stream); 1820 crash_thread_success = TRUE; 1821 return 0; 1822 } 1823 1824 static void test_crash_couninitialize(void) 1825 { 1826 HANDLE thread; 1827 DWORD tid; 1828 1829 if(!GetProcAddress(GetModuleHandleA("kernel32.dll"), "CreateActCtxW")) { 1830 win_skip("Skipping crash tests on win2k.\n"); 1831 return; 1832 } 1833 1834 crash_thread_success = FALSE; 1835 thread = CreateThread(NULL, 0, crash_couninitialize_proc, NULL, 0, &tid); 1836 ok(!WaitForSingleObject(thread, 10000), "wait timed out\n"); 1837 CloseHandle(thread); 1838 ok(crash_thread_success, "Crash thread failed\n"); 1839 } 1840 1841 /* tests success case of a same-thread table-weak marshal, unmarshal, unmarshal */ 1842 static void test_tableweak_marshal_and_unmarshal_twice(void) 1843 { 1844 HRESULT hr; 1845 IStream *pStream = NULL; 1846 IUnknown *pProxy1 = NULL; 1847 IUnknown *pProxy2 = NULL; 1848 DWORD tid; 1849 HANDLE thread; 1850 1851 cLocks = 0; 1852 external_connections = 0; 1853 1854 hr = CreateStreamOnHGlobal(NULL, TRUE, &pStream); 1855 ok_ole_success(hr, CreateStreamOnHGlobal); 1856 tid = start_host_object(pStream, &IID_IClassFactory, (IUnknown*)&Test_ClassFactory, MSHLFLAGS_TABLEWEAK, &thread); 1857 1858 ok_more_than_one_lock(); 1859 ok_zero_external_conn(); 1860 1861 IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL); 1862 hr = CoUnmarshalInterface(pStream, &IID_IClassFactory, (void **)&pProxy1); 1863 ok_ole_success(hr, CoUnmarshalInterface); 1864 1865 ok_more_than_one_lock(); 1866 ok_non_zero_external_conn(); 1867 1868 IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL); 1869 hr = CoUnmarshalInterface(pStream, &IID_IClassFactory, (void **)&pProxy2); 1870 ok_ole_success(hr, CoUnmarshalInterface); 1871 1872 ok_more_than_one_lock(); 1873 1874 IUnknown_Release(pProxy1); 1875 ok_non_zero_external_conn(); 1876 IUnknown_Release(pProxy2); 1877 ok_zero_external_conn(); 1878 ok_last_release_closes(TRUE); 1879 1880 /* When IExternalConnection is present COM's lifetime management 1881 * behaviour is altered; the remaining weak ref prevents stub shutdown. */ 1882 if (with_external_conn) 1883 { 1884 ok_more_than_one_lock(); 1885 IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL); 1886 release_host_object(tid, 0); 1887 } 1888 1889 /* Without IExternalConnection this line is shows the difference between weak and strong table marshaling 1890 * weak has cLocks == 0, strong has cLocks > 0. */ 1891 ok_no_locks(); 1892 1893 IStream_Release(pStream); 1894 end_host_object(tid, thread); 1895 } 1896 1897 /* tests releasing after unmarshaling one object */ 1898 static void test_tableweak_marshal_releasedata1(void) 1899 { 1900 HRESULT hr; 1901 IStream *pStream = NULL; 1902 IUnknown *pProxy1 = NULL; 1903 IUnknown *pProxy2 = NULL; 1904 DWORD tid; 1905 HANDLE thread; 1906 1907 cLocks = 0; 1908 external_connections = 0; 1909 1910 hr = CreateStreamOnHGlobal(NULL, TRUE, &pStream); 1911 ok_ole_success(hr, CreateStreamOnHGlobal); 1912 tid = start_host_object(pStream, &IID_IClassFactory, (IUnknown*)&Test_ClassFactory, MSHLFLAGS_TABLEWEAK, &thread); 1913 1914 ok_more_than_one_lock(); 1915 ok_zero_external_conn(); 1916 1917 IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL); 1918 hr = CoUnmarshalInterface(pStream, &IID_IClassFactory, (void **)&pProxy1); 1919 ok_ole_success(hr, CoUnmarshalInterface); 1920 1921 ok_more_than_one_lock(); 1922 ok_non_zero_external_conn(); 1923 1924 /* release the remaining reference on the object by calling 1925 * CoReleaseMarshalData in the hosting thread */ 1926 IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL); 1927 release_host_object(tid, 0); 1928 1929 ok_more_than_one_lock(); 1930 ok_non_zero_external_conn(); 1931 1932 IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL); 1933 hr = CoUnmarshalInterface(pStream, &IID_IClassFactory, (void **)&pProxy2); 1934 ok_ole_success(hr, CoUnmarshalInterface); 1935 IStream_Release(pStream); 1936 1937 ok_more_than_one_lock(); 1938 ok_non_zero_external_conn(); 1939 1940 IUnknown_Release(pProxy1); 1941 1942 if (pProxy2) 1943 { 1944 ok_non_zero_external_conn(); 1945 IUnknown_Release(pProxy2); 1946 } 1947 1948 /* this line is shows the difference between weak and strong table marshaling: 1949 * weak has cLocks == 0 1950 * strong has cLocks > 0 */ 1951 ok_no_locks(); 1952 ok_zero_external_conn(); 1953 ok_last_release_closes(TRUE); 1954 1955 end_host_object(tid, thread); 1956 } 1957 1958 /* tests releasing after unmarshaling one object */ 1959 static void test_tableweak_marshal_releasedata2(void) 1960 { 1961 HRESULT hr; 1962 IStream *pStream = NULL; 1963 IUnknown *pProxy = NULL; 1964 DWORD tid; 1965 HANDLE thread; 1966 1967 cLocks = 0; 1968 external_connections = 0; 1969 1970 hr = CreateStreamOnHGlobal(NULL, TRUE, &pStream); 1971 ok_ole_success(hr, CreateStreamOnHGlobal); 1972 tid = start_host_object(pStream, &IID_IClassFactory, (IUnknown*)&Test_ClassFactory, MSHLFLAGS_TABLEWEAK, &thread); 1973 1974 ok_more_than_one_lock(); 1975 ok_zero_external_conn(); 1976 1977 /* release the remaining reference on the object by calling 1978 * CoReleaseMarshalData in the hosting thread */ 1979 IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL); 1980 release_host_object(tid, 0); 1981 1982 ok_no_locks(); 1983 1984 IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL); 1985 hr = CoUnmarshalInterface(pStream, &IID_IClassFactory, (void **)&pProxy); 1986 todo_wine 1987 { 1988 ok(hr == CO_E_OBJNOTREG, 1989 "CoUnmarshalInterface should have failed with CO_E_OBJNOTREG, but returned 0x%08x instead\n", 1990 hr); 1991 } 1992 IStream_Release(pStream); 1993 1994 ok_no_locks(); 1995 ok_zero_external_conn(); 1996 1997 end_host_object(tid, thread); 1998 } 1999 2000 struct duo_marshal_data 2001 { 2002 MSHLFLAGS marshal_flags1, marshal_flags2; 2003 IStream *pStream1, *pStream2; 2004 HANDLE hReadyEvent; 2005 HANDLE hQuitEvent; 2006 }; 2007 2008 static DWORD CALLBACK duo_marshal_thread_proc(void *p) 2009 { 2010 HRESULT hr; 2011 struct duo_marshal_data *data = p; 2012 HANDLE hQuitEvent = data->hQuitEvent; 2013 MSG msg; 2014 2015 pCoInitializeEx(NULL, COINIT_APARTMENTTHREADED); 2016 2017 hr = CoMarshalInterface(data->pStream1, &IID_IClassFactory, (IUnknown*)&Test_ClassFactory, MSHCTX_INPROC, NULL, data->marshal_flags1); 2018 ok_ole_success(hr, "CoMarshalInterface"); 2019 2020 hr = CoMarshalInterface(data->pStream2, &IID_IClassFactory, (IUnknown*)&Test_ClassFactory, MSHCTX_INPROC, NULL, data->marshal_flags2); 2021 ok_ole_success(hr, "CoMarshalInterface"); 2022 2023 /* force the message queue to be created before signaling parent thread */ 2024 PeekMessageA(&msg, NULL, WM_USER, WM_USER, PM_NOREMOVE); 2025 2026 SetEvent(data->hReadyEvent); 2027 2028 while (WAIT_OBJECT_0 + 1 == MsgWaitForMultipleObjects(1, &hQuitEvent, FALSE, 10000, QS_ALLINPUT)) 2029 { 2030 while (PeekMessageA(&msg, NULL, 0, 0, PM_REMOVE)) 2031 { 2032 if (msg.hwnd == NULL && msg.message == RELEASEMARSHALDATA) 2033 { 2034 CoReleaseMarshalData(msg.wParam == 1 ? data->pStream1 : data->pStream2); 2035 SetEvent((HANDLE)msg.lParam); 2036 } 2037 else 2038 DispatchMessageA(&msg); 2039 } 2040 } 2041 CloseHandle(hQuitEvent); 2042 2043 CoUninitialize(); 2044 2045 return 0; 2046 } 2047 2048 /* tests interaction between table-weak and normal marshalling of an object */ 2049 static void test_tableweak_and_normal_marshal_and_unmarshal(void) 2050 { 2051 HRESULT hr; 2052 IUnknown *pProxyWeak = NULL; 2053 IUnknown *pProxyNormal = NULL; 2054 DWORD tid; 2055 HANDLE thread; 2056 struct duo_marshal_data data; 2057 2058 cLocks = 0; 2059 external_connections = 0; 2060 2061 data.hReadyEvent = CreateEventA(NULL, FALSE, FALSE, NULL); 2062 data.hQuitEvent = CreateEventA(NULL, FALSE, FALSE, NULL); 2063 data.marshal_flags1 = MSHLFLAGS_TABLEWEAK; 2064 data.marshal_flags2 = MSHLFLAGS_NORMAL; 2065 hr = CreateStreamOnHGlobal(NULL, TRUE, &data.pStream1); 2066 ok_ole_success(hr, CreateStreamOnHGlobal); 2067 hr = CreateStreamOnHGlobal(NULL, TRUE, &data.pStream2); 2068 ok_ole_success(hr, CreateStreamOnHGlobal); 2069 2070 thread = CreateThread(NULL, 0, duo_marshal_thread_proc, &data, 0, &tid); 2071 ok( !WaitForSingleObject(data.hReadyEvent, 10000), "wait timed out\n" ); 2072 CloseHandle(data.hReadyEvent); 2073 2074 ok_more_than_one_lock(); 2075 ok_non_zero_external_conn(); 2076 2077 /* weak */ 2078 IStream_Seek(data.pStream1, ullZero, STREAM_SEEK_SET, NULL); 2079 hr = CoUnmarshalInterface(data.pStream1, &IID_IClassFactory, (void **)&pProxyWeak); 2080 ok_ole_success(hr, CoUnmarshalInterface); 2081 2082 ok_more_than_one_lock(); 2083 2084 /* normal */ 2085 IStream_Seek(data.pStream2, ullZero, STREAM_SEEK_SET, NULL); 2086 hr = CoUnmarshalInterface(data.pStream2, &IID_IClassFactory, (void **)&pProxyNormal); 2087 ok_ole_success(hr, CoUnmarshalInterface); 2088 2089 ok_more_than_one_lock(); 2090 2091 IUnknown_Release(pProxyNormal); 2092 2093 ok_more_than_one_lock(); 2094 ok_non_zero_external_conn(); 2095 2096 IUnknown_Release(pProxyWeak); 2097 2098 ok_zero_external_conn(); 2099 ok_last_release_closes(TRUE); 2100 2101 /* When IExternalConnection is present COM's lifetime management 2102 * behaviour is altered; the remaining weak ref prevents stub shutdown. */ 2103 if (with_external_conn) 2104 { 2105 ok_more_than_one_lock(); 2106 IStream_Seek(data.pStream1, ullZero, STREAM_SEEK_SET, NULL); 2107 release_host_object(tid, 1); 2108 } 2109 ok_no_locks(); 2110 2111 IStream_Release(data.pStream1); 2112 IStream_Release(data.pStream2); 2113 2114 SetEvent(data.hQuitEvent); 2115 ok( !WaitForSingleObject(thread, 10000), "wait timed out\n" ); 2116 CloseHandle(thread); 2117 } 2118 2119 static void test_tableweak_and_normal_marshal_and_releasedata(void) 2120 { 2121 HRESULT hr; 2122 DWORD tid; 2123 HANDLE thread; 2124 struct duo_marshal_data data; 2125 2126 cLocks = 0; 2127 external_connections = 0; 2128 2129 data.hReadyEvent = CreateEventA(NULL, FALSE, FALSE, NULL); 2130 data.hQuitEvent = CreateEventA(NULL, FALSE, FALSE, NULL); 2131 data.marshal_flags1 = MSHLFLAGS_TABLEWEAK; 2132 data.marshal_flags2 = MSHLFLAGS_NORMAL; 2133 hr = CreateStreamOnHGlobal(NULL, TRUE, &data.pStream1); 2134 ok_ole_success(hr, CreateStreamOnHGlobal); 2135 hr = CreateStreamOnHGlobal(NULL, TRUE, &data.pStream2); 2136 ok_ole_success(hr, CreateStreamOnHGlobal); 2137 2138 thread = CreateThread(NULL, 0, duo_marshal_thread_proc, &data, 0, &tid); 2139 ok( !WaitForSingleObject(data.hReadyEvent, 10000), "wait timed out\n" ); 2140 CloseHandle(data.hReadyEvent); 2141 2142 ok_more_than_one_lock(); 2143 ok_non_zero_external_conn(); 2144 2145 /* release normal - which in the non-external conn case will free the object despite the weak ref. */ 2146 IStream_Seek(data.pStream2, ullZero, STREAM_SEEK_SET, NULL); 2147 release_host_object(tid, 2); 2148 2149 ok_zero_external_conn(); 2150 ok_last_release_closes(TRUE); 2151 2152 if (with_external_conn) 2153 { 2154 ok_more_than_one_lock(); 2155 IStream_Seek(data.pStream1, ullZero, STREAM_SEEK_SET, NULL); 2156 release_host_object(tid, 1); 2157 } 2158 2159 ok_no_locks(); 2160 2161 IStream_Release(data.pStream1); 2162 IStream_Release(data.pStream2); 2163 2164 SetEvent(data.hQuitEvent); 2165 ok( !WaitForSingleObject(thread, 10000), "wait timed out\n" ); 2166 CloseHandle(thread); 2167 } 2168 2169 static void test_two_tableweak_marshal_and_releasedata(void) 2170 { 2171 HRESULT hr; 2172 DWORD tid; 2173 HANDLE thread; 2174 struct duo_marshal_data data; 2175 2176 cLocks = 0; 2177 external_connections = 0; 2178 2179 data.hReadyEvent = CreateEventA(NULL, FALSE, FALSE, NULL); 2180 data.hQuitEvent = CreateEventA(NULL, FALSE, FALSE, NULL); 2181 data.marshal_flags1 = MSHLFLAGS_TABLEWEAK; 2182 data.marshal_flags2 = MSHLFLAGS_TABLEWEAK; 2183 hr = CreateStreamOnHGlobal(NULL, TRUE, &data.pStream1); 2184 ok_ole_success(hr, CreateStreamOnHGlobal); 2185 hr = CreateStreamOnHGlobal(NULL, TRUE, &data.pStream2); 2186 ok_ole_success(hr, CreateStreamOnHGlobal); 2187 2188 thread = CreateThread(NULL, 0, duo_marshal_thread_proc, &data, 0, &tid); 2189 ok( !WaitForSingleObject(data.hReadyEvent, 10000), "wait timed out\n" ); 2190 CloseHandle(data.hReadyEvent); 2191 2192 ok_more_than_one_lock(); 2193 ok_zero_external_conn(); 2194 2195 /* release one weak ref - the remaining weak ref will keep the obj alive */ 2196 IStream_Seek(data.pStream1, ullZero, STREAM_SEEK_SET, NULL); 2197 release_host_object(tid, 1); 2198 2199 ok_more_than_one_lock(); 2200 2201 IStream_Seek(data.pStream2, ullZero, STREAM_SEEK_SET, NULL); 2202 release_host_object(tid, 2); 2203 2204 ok_no_locks(); 2205 2206 IStream_Release(data.pStream1); 2207 IStream_Release(data.pStream2); 2208 2209 SetEvent(data.hQuitEvent); 2210 ok( !WaitForSingleObject(thread, 10000), "wait timed out\n" ); 2211 CloseHandle(thread); 2212 } 2213 2214 /* tests success case of a same-thread table-strong marshal, unmarshal, unmarshal */ 2215 static void test_tablestrong_marshal_and_unmarshal_twice(void) 2216 { 2217 HRESULT hr; 2218 IStream *pStream = NULL; 2219 IUnknown *pProxy1 = NULL; 2220 IUnknown *pProxy2 = NULL; 2221 DWORD tid; 2222 HANDLE thread; 2223 2224 cLocks = 0; 2225 external_connections = 0; 2226 2227 hr = CreateStreamOnHGlobal(NULL, TRUE, &pStream); 2228 ok_ole_success(hr, CreateStreamOnHGlobal); 2229 tid = start_host_object(pStream, &IID_IClassFactory, (IUnknown*)&Test_ClassFactory, MSHLFLAGS_TABLESTRONG, &thread); 2230 2231 ok_more_than_one_lock(); 2232 ok_non_zero_external_conn(); 2233 2234 IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL); 2235 hr = CoUnmarshalInterface(pStream, &IID_IClassFactory, (void **)&pProxy1); 2236 ok_ole_success(hr, CoUnmarshalInterface); 2237 2238 ok_more_than_one_lock(); 2239 2240 IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL); 2241 hr = CoUnmarshalInterface(pStream, &IID_IClassFactory, (void **)&pProxy2); 2242 ok_ole_success(hr, CoUnmarshalInterface); 2243 2244 ok_more_than_one_lock(); 2245 2246 if (pProxy1) IUnknown_Release(pProxy1); 2247 if (pProxy2) IUnknown_Release(pProxy2); 2248 2249 /* this line is shows the difference between weak and strong table marshaling: 2250 * weak has cLocks == 0 2251 * strong has cLocks > 0 */ 2252 ok_more_than_one_lock(); 2253 2254 /* release the remaining reference on the object by calling 2255 * CoReleaseMarshalData in the hosting thread */ 2256 IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL); 2257 release_host_object(tid, 0); 2258 IStream_Release(pStream); 2259 2260 ok_no_locks(); 2261 ok_zero_external_conn(); 2262 ok_last_release_closes(TRUE); 2263 2264 end_host_object(tid, thread); 2265 } 2266 2267 /* tests CoLockObjectExternal */ 2268 static void test_lock_object_external(void) 2269 { 2270 HRESULT hr; 2271 IStream *pStream = NULL; 2272 2273 cLocks = 0; 2274 external_connections = 0; 2275 2276 /* test the stub manager creation aspect of CoLockObjectExternal when the 2277 * object hasn't been marshaled yet */ 2278 CoLockObjectExternal((IUnknown*)&Test_ClassFactory, TRUE, TRUE); 2279 2280 ok_more_than_one_lock(); 2281 ok_non_zero_external_conn(); 2282 2283 CoDisconnectObject((IUnknown*)&Test_ClassFactory, 0); 2284 2285 ok_no_locks(); 2286 ok_non_zero_external_conn(); 2287 external_connections = 0; 2288 2289 /* test our empty stub manager being handled correctly in 2290 * CoMarshalInterface */ 2291 CoLockObjectExternal((IUnknown*)&Test_ClassFactory, TRUE, TRUE); 2292 2293 hr = CreateStreamOnHGlobal(NULL, TRUE, &pStream); 2294 ok_ole_success(hr, CreateStreamOnHGlobal); 2295 hr = CoMarshalInterface(pStream, &IID_IClassFactory, (IUnknown*)&Test_ClassFactory, MSHCTX_INPROC, NULL, MSHLFLAGS_NORMAL); 2296 ok_ole_success(hr, CoMarshalInterface); 2297 2298 CoLockObjectExternal((IUnknown*)&Test_ClassFactory, TRUE, TRUE); 2299 2300 ok_more_than_one_lock(); 2301 ok_non_zero_external_conn(); 2302 2303 IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL); 2304 hr = CoReleaseMarshalData(pStream); 2305 ok_ole_success(hr, CoReleaseMarshalData); 2306 IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL); 2307 2308 ok_more_than_one_lock(); 2309 ok_non_zero_external_conn(); 2310 ok_last_release_closes(TRUE); 2311 2312 CoLockObjectExternal((IUnknown*)&Test_ClassFactory, FALSE, TRUE); 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_no_locks(); 2321 ok_zero_external_conn(); 2322 ok_last_release_closes(TRUE); 2323 2324 /* test CoLockObjectExternal releases reference to object with 2325 * fLastUnlockReleases as TRUE and there are only strong references on 2326 * the object */ 2327 CoLockObjectExternal((IUnknown*)&Test_ClassFactory, TRUE, FALSE); 2328 2329 ok_more_than_one_lock(); 2330 ok_non_zero_external_conn(); 2331 2332 CoLockObjectExternal((IUnknown*)&Test_ClassFactory, FALSE, FALSE); 2333 2334 ok_no_locks(); 2335 ok_zero_external_conn(); 2336 ok_last_release_closes(FALSE); 2337 2338 /* test CoLockObjectExternal doesn't release the last reference to an 2339 * object with fLastUnlockReleases as TRUE and there is a weak reference 2340 * on the object */ 2341 hr = CoMarshalInterface(pStream, &IID_IClassFactory, (IUnknown*)&Test_ClassFactory, MSHCTX_INPROC, NULL, MSHLFLAGS_TABLEWEAK); 2342 ok_ole_success(hr, CoMarshalInterface); 2343 2344 ok_more_than_one_lock(); 2345 ok_zero_external_conn(); 2346 2347 CoLockObjectExternal((IUnknown*)&Test_ClassFactory, TRUE, FALSE); 2348 2349 ok_more_than_one_lock(); 2350 ok_non_zero_external_conn(); 2351 2352 CoLockObjectExternal((IUnknown*)&Test_ClassFactory, FALSE, FALSE); 2353 2354 ok_more_than_one_lock(); 2355 ok_zero_external_conn(); 2356 ok_last_release_closes(FALSE); 2357 2358 CoDisconnectObject((IUnknown*)&Test_ClassFactory, 0); 2359 2360 ok_no_locks(); 2361 2362 IStream_Release(pStream); 2363 } 2364 2365 /* tests disconnecting stubs */ 2366 static void test_disconnect_stub(void) 2367 { 2368 HRESULT hr; 2369 IStream *pStream = NULL; 2370 2371 cLocks = 0; 2372 external_connections = 0; 2373 2374 hr = CreateStreamOnHGlobal(NULL, TRUE, &pStream); 2375 ok_ole_success(hr, CreateStreamOnHGlobal); 2376 hr = CoMarshalInterface(pStream, &IID_IClassFactory, (IUnknown*)&Test_ClassFactory, MSHCTX_INPROC, NULL, MSHLFLAGS_NORMAL); 2377 ok_ole_success(hr, CoMarshalInterface); 2378 2379 ok_non_zero_external_conn(); 2380 2381 CoLockObjectExternal((IUnknown*)&Test_ClassFactory, TRUE, TRUE); 2382 2383 ok_more_than_one_lock(); 2384 ok_non_zero_external_conn(); 2385 2386 IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL); 2387 hr = CoReleaseMarshalData(pStream); 2388 ok_ole_success(hr, CoReleaseMarshalData); 2389 IStream_Release(pStream); 2390 2391 ok_more_than_one_lock(); 2392 ok_non_zero_external_conn(); 2393 2394 CoDisconnectObject((IUnknown*)&Test_ClassFactory, 0); 2395 2396 ok_no_locks(); 2397 ok_non_zero_external_conn(); 2398 2399 hr = CoDisconnectObject(NULL, 0); 2400 ok( hr == E_INVALIDARG, "wrong status %x\n", hr ); 2401 } 2402 2403 /* tests failure case of a same-thread marshal and unmarshal twice */ 2404 static void test_normal_marshal_and_unmarshal_twice(void) 2405 { 2406 HRESULT hr; 2407 IStream *pStream = NULL; 2408 IUnknown *pProxy1 = NULL; 2409 IUnknown *pProxy2 = NULL; 2410 2411 cLocks = 0; 2412 external_connections = 0; 2413 2414 hr = CreateStreamOnHGlobal(NULL, TRUE, &pStream); 2415 ok_ole_success(hr, CreateStreamOnHGlobal); 2416 hr = CoMarshalInterface(pStream, &IID_IClassFactory, (IUnknown*)&Test_ClassFactory, MSHCTX_INPROC, NULL, MSHLFLAGS_NORMAL); 2417 ok_ole_success(hr, CoMarshalInterface); 2418 2419 ok_more_than_one_lock(); 2420 ok_non_zero_external_conn(); 2421 2422 IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL); 2423 hr = CoUnmarshalInterface(pStream, &IID_IClassFactory, (void **)&pProxy1); 2424 ok_ole_success(hr, CoUnmarshalInterface); 2425 2426 ok_more_than_one_lock(); 2427 ok_zero_external_conn(); 2428 ok_last_release_closes(FALSE); 2429 2430 IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL); 2431 hr = CoUnmarshalInterface(pStream, &IID_IClassFactory, (void **)&pProxy2); 2432 ok(hr == CO_E_OBJNOTCONNECTED, 2433 "CoUnmarshalInterface should have failed with error CO_E_OBJNOTCONNECTED for double unmarshal, instead of 0x%08x\n", hr); 2434 2435 IStream_Release(pStream); 2436 2437 ok_more_than_one_lock(); 2438 2439 IUnknown_Release(pProxy1); 2440 2441 ok_no_locks(); 2442 } 2443 2444 /* tests success case of marshaling and unmarshaling an HRESULT */ 2445 static void test_hresult_marshaling(void) 2446 { 2447 HRESULT hr; 2448 HRESULT hr_marshaled = 0; 2449 IStream *pStream = NULL; 2450 static const HRESULT E_DEADBEEF = 0xdeadbeef; 2451 2452 hr = CreateStreamOnHGlobal(NULL, TRUE, &pStream); 2453 ok_ole_success(hr, CreateStreamOnHGlobal); 2454 2455 hr = CoMarshalHresult(pStream, E_DEADBEEF); 2456 ok_ole_success(hr, CoMarshalHresult); 2457 2458 IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL); 2459 hr = IStream_Read(pStream, &hr_marshaled, sizeof(HRESULT), NULL); 2460 ok_ole_success(hr, IStream_Read); 2461 2462 ok(hr_marshaled == E_DEADBEEF, "Didn't marshal HRESULT as expected: got value 0x%08x instead\n", hr_marshaled); 2463 2464 hr_marshaled = 0; 2465 IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL); 2466 hr = CoUnmarshalHresult(pStream, &hr_marshaled); 2467 ok_ole_success(hr, CoUnmarshalHresult); 2468 2469 ok(hr_marshaled == E_DEADBEEF, "Didn't marshal HRESULT as expected: got value 0x%08x instead\n", hr_marshaled); 2470 2471 IStream_Release(pStream); 2472 } 2473 2474 2475 /* helper for test_proxy_used_in_wrong_thread */ 2476 static DWORD CALLBACK bad_thread_proc(LPVOID p) 2477 { 2478 IClassFactory * cf = p; 2479 HRESULT hr; 2480 IUnknown * proxy = NULL; 2481 2482 hr = IClassFactory_CreateInstance(cf, NULL, &IID_IUnknown, (LPVOID*)&proxy); 2483 todo_wine 2484 ok(hr == CO_E_NOTINITIALIZED, 2485 "COM should have failed with CO_E_NOTINITIALIZED on using proxy without apartment, but instead returned 0x%08x\n", 2486 hr); 2487 2488 hr = IClassFactory_QueryInterface(cf, &IID_IMultiQI, (LPVOID *)&proxy); 2489 /* Win9x returns S_OK, whilst NT returns RPC_E_WRONG_THREAD */ 2490 trace("call to proxy's QueryInterface for local interface without apartment returned 0x%08x\n", hr); 2491 if (SUCCEEDED(hr)) 2492 IUnknown_Release(proxy); 2493 2494 hr = IClassFactory_QueryInterface(cf, &IID_IStream, (LPVOID *)&proxy); 2495 /* Win9x returns E_NOINTERFACE, whilst NT returns RPC_E_WRONG_THREAD */ 2496 trace("call to proxy's QueryInterface without apartment returned 0x%08x\n", hr); 2497 if (SUCCEEDED(hr)) 2498 IUnknown_Release(proxy); 2499 2500 pCoInitializeEx(NULL, COINIT_MULTITHREADED); 2501 2502 hr = IClassFactory_CreateInstance(cf, NULL, &IID_IUnknown, (LPVOID*)&proxy); 2503 if (proxy) IUnknown_Release(proxy); 2504 ok(hr == RPC_E_WRONG_THREAD, 2505 "COM should have failed with RPC_E_WRONG_THREAD on using proxy from wrong apartment, but instead returned 0x%08x\n", 2506 hr); 2507 2508 hr = IClassFactory_QueryInterface(cf, &IID_IStream, (LPVOID *)&proxy); 2509 /* Win9x returns E_NOINTERFACE, whilst NT returns RPC_E_WRONG_THREAD */ 2510 trace("call to proxy's QueryInterface from wrong apartment returned 0x%08x\n", hr); 2511 2512 /* now be really bad and release the proxy from the wrong apartment */ 2513 IClassFactory_Release(cf); 2514 2515 CoUninitialize(); 2516 2517 return 0; 2518 } 2519 2520 /* tests failure case of a using a proxy in the wrong apartment */ 2521 static void test_proxy_used_in_wrong_thread(void) 2522 { 2523 HRESULT hr; 2524 IStream *pStream = NULL; 2525 IUnknown *pProxy = NULL; 2526 DWORD tid, tid2; 2527 HANDLE thread; 2528 HANDLE host_thread; 2529 2530 cLocks = 0; 2531 2532 hr = CreateStreamOnHGlobal(NULL, TRUE, &pStream); 2533 ok_ole_success(hr, CreateStreamOnHGlobal); 2534 tid = start_host_object(pStream, &IID_IClassFactory, (IUnknown*)&Test_ClassFactory, MSHLFLAGS_NORMAL, &host_thread); 2535 2536 ok_more_than_one_lock(); 2537 2538 IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL); 2539 hr = CoUnmarshalInterface(pStream, &IID_IClassFactory, (void **)&pProxy); 2540 ok_ole_success(hr, CoUnmarshalInterface); 2541 IStream_Release(pStream); 2542 2543 ok_more_than_one_lock(); 2544 2545 /* do a call that will fail, but result in IRemUnknown being used by the proxy */ 2546 IUnknown_QueryInterface(pProxy, &IID_IStream, (LPVOID *)&pStream); 2547 2548 /* create a thread that we can misbehave in */ 2549 thread = CreateThread(NULL, 0, bad_thread_proc, pProxy, 0, &tid2); 2550 2551 ok( !WaitForSingleObject(thread, 10000), "wait timed out\n" ); 2552 CloseHandle(thread); 2553 2554 /* do release statement on Win9x that we should have done above */ 2555 if (!GetProcAddress(GetModuleHandleA("ole32"), "CoRegisterSurrogateEx")) 2556 IUnknown_Release(pProxy); 2557 2558 ok_no_locks(); 2559 2560 end_host_object(tid, host_thread); 2561 } 2562 2563 static HRESULT WINAPI MessageFilter_QueryInterface(IMessageFilter *iface, REFIID riid, void ** ppvObj) 2564 { 2565 if (ppvObj == NULL) return E_POINTER; 2566 2567 if (IsEqualGUID(riid, &IID_IUnknown) || 2568 IsEqualGUID(riid, &IID_IClassFactory)) 2569 { 2570 *ppvObj = iface; 2571 IMessageFilter_AddRef(iface); 2572 return S_OK; 2573 } 2574 2575 return E_NOINTERFACE; 2576 } 2577 2578 static ULONG WINAPI MessageFilter_AddRef(IMessageFilter *iface) 2579 { 2580 return 2; /* non-heap object */ 2581 } 2582 2583 static ULONG WINAPI MessageFilter_Release(IMessageFilter *iface) 2584 { 2585 return 1; /* non-heap object */ 2586 } 2587 2588 static DWORD WINAPI MessageFilter_HandleInComingCall( 2589 IMessageFilter *iface, 2590 DWORD dwCallType, 2591 HTASK threadIDCaller, 2592 DWORD dwTickCount, 2593 LPINTERFACEINFO lpInterfaceInfo) 2594 { 2595 static int callcount = 0; 2596 DWORD ret; 2597 trace("HandleInComingCall\n"); 2598 switch (callcount) 2599 { 2600 case 0: 2601 ret = SERVERCALL_REJECTED; 2602 break; 2603 case 1: 2604 ret = SERVERCALL_RETRYLATER; 2605 break; 2606 default: 2607 ret = SERVERCALL_ISHANDLED; 2608 break; 2609 } 2610 callcount++; 2611 return ret; 2612 } 2613 2614 static DWORD WINAPI MessageFilter_RetryRejectedCall( 2615 IMessageFilter *iface, 2616 HTASK threadIDCallee, 2617 DWORD dwTickCount, 2618 DWORD dwRejectType) 2619 { 2620 trace("RetryRejectedCall\n"); 2621 return 0; 2622 } 2623 2624 static DWORD WINAPI MessageFilter_MessagePending( 2625 IMessageFilter *iface, 2626 HTASK threadIDCallee, 2627 DWORD dwTickCount, 2628 DWORD dwPendingType) 2629 { 2630 trace("MessagePending\n"); 2631 return PENDINGMSG_WAITNOPROCESS; 2632 } 2633 2634 static const IMessageFilterVtbl MessageFilter_Vtbl = 2635 { 2636 MessageFilter_QueryInterface, 2637 MessageFilter_AddRef, 2638 MessageFilter_Release, 2639 MessageFilter_HandleInComingCall, 2640 MessageFilter_RetryRejectedCall, 2641 MessageFilter_MessagePending 2642 }; 2643 2644 static IMessageFilter MessageFilter = { &MessageFilter_Vtbl }; 2645 2646 static void test_message_filter(void) 2647 { 2648 HRESULT hr; 2649 IClassFactory *cf = NULL; 2650 DWORD tid; 2651 IUnknown *proxy = NULL; 2652 IMessageFilter *prev_filter = NULL; 2653 HANDLE thread; 2654 2655 struct host_object_data object_data = { NULL, &IID_IClassFactory, (IUnknown*)&Test_ClassFactory, 2656 MSHLFLAGS_NORMAL, &MessageFilter }; 2657 2658 cLocks = 0; 2659 2660 hr = CreateStreamOnHGlobal(NULL, TRUE, &object_data.stream); 2661 ok_ole_success(hr, CreateStreamOnHGlobal); 2662 tid = start_host_object2(&object_data, &thread); 2663 2664 ok_more_than_one_lock(); 2665 2666 IStream_Seek(object_data.stream, ullZero, STREAM_SEEK_SET, NULL); 2667 hr = CoUnmarshalInterface(object_data.stream, &IID_IClassFactory, (void **)&cf); 2668 ok_ole_success(hr, CoUnmarshalInterface); 2669 IStream_Release(object_data.stream); 2670 2671 ok_more_than_one_lock(); 2672 2673 hr = IClassFactory_CreateInstance(cf, NULL, &IID_IUnknown, (LPVOID*)&proxy); 2674 ok(hr == RPC_E_CALL_REJECTED, "Call should have returned RPC_E_CALL_REJECTED, but return 0x%08x instead\n", hr); 2675 if (proxy) IUnknown_Release(proxy); 2676 proxy = NULL; 2677 2678 hr = CoRegisterMessageFilter(&MessageFilter, &prev_filter); 2679 ok_ole_success(hr, CoRegisterMessageFilter); 2680 2681 hr = IClassFactory_CreateInstance(cf, NULL, &IID_IUnknown, (LPVOID*)&proxy); 2682 ok_ole_success(hr, IClassFactory_CreateInstance); 2683 2684 IUnknown_Release(proxy); 2685 2686 IClassFactory_Release(cf); 2687 2688 ok_no_locks(); 2689 2690 end_host_object(tid, thread); 2691 2692 hr = CoRegisterMessageFilter(prev_filter, NULL); 2693 ok_ole_success(hr, CoRegisterMessageFilter); 2694 } 2695 2696 /* test failure case of trying to unmarshal from bad stream */ 2697 static void test_bad_marshal_stream(void) 2698 { 2699 HRESULT hr; 2700 IStream *pStream = NULL; 2701 2702 hr = CreateStreamOnHGlobal(NULL, TRUE, &pStream); 2703 ok_ole_success(hr, CreateStreamOnHGlobal); 2704 hr = CoMarshalInterface(pStream, &IID_IClassFactory, (IUnknown*)&Test_ClassFactory, MSHCTX_INPROC, NULL, MSHLFLAGS_NORMAL); 2705 ok_ole_success(hr, CoMarshalInterface); 2706 2707 ok_more_than_one_lock(); 2708 2709 /* try to read beyond end of stream */ 2710 hr = CoReleaseMarshalData(pStream); 2711 ok(hr == STG_E_READFAULT, "Should have failed with STG_E_READFAULT, but returned 0x%08x instead\n", hr); 2712 2713 /* now release for real */ 2714 IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL); 2715 hr = CoReleaseMarshalData(pStream); 2716 ok_ole_success(hr, CoReleaseMarshalData); 2717 2718 IStream_Release(pStream); 2719 } 2720 2721 /* tests that proxies implement certain interfaces */ 2722 static void test_proxy_interfaces(void) 2723 { 2724 HRESULT hr; 2725 IStream *pStream = NULL; 2726 IUnknown *pProxy = NULL; 2727 IUnknown *pOtherUnknown = NULL; 2728 DWORD tid; 2729 HANDLE thread; 2730 2731 cLocks = 0; 2732 2733 hr = CreateStreamOnHGlobal(NULL, TRUE, &pStream); 2734 ok_ole_success(hr, CreateStreamOnHGlobal); 2735 tid = start_host_object(pStream, &IID_IClassFactory, (IUnknown*)&Test_ClassFactory, MSHLFLAGS_NORMAL, &thread); 2736 2737 ok_more_than_one_lock(); 2738 2739 IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL); 2740 hr = CoUnmarshalInterface(pStream, &IID_IUnknown, (void **)&pProxy); 2741 ok_ole_success(hr, CoUnmarshalInterface); 2742 IStream_Release(pStream); 2743 2744 ok_more_than_one_lock(); 2745 2746 hr = IUnknown_QueryInterface(pProxy, &IID_IUnknown, (LPVOID*)&pOtherUnknown); 2747 ok_ole_success(hr, IUnknown_QueryInterface IID_IUnknown); 2748 if (hr == S_OK) IUnknown_Release(pOtherUnknown); 2749 2750 hr = IUnknown_QueryInterface(pProxy, &IID_IClientSecurity, (LPVOID*)&pOtherUnknown); 2751 ok_ole_success(hr, IUnknown_QueryInterface IID_IClientSecurity); 2752 if (hr == S_OK) IUnknown_Release(pOtherUnknown); 2753 2754 hr = IUnknown_QueryInterface(pProxy, &IID_IMultiQI, (LPVOID*)&pOtherUnknown); 2755 ok_ole_success(hr, IUnknown_QueryInterface IID_IMultiQI); 2756 if (hr == S_OK) IUnknown_Release(pOtherUnknown); 2757 2758 hr = IUnknown_QueryInterface(pProxy, &IID_IMarshal, (LPVOID*)&pOtherUnknown); 2759 ok_ole_success(hr, IUnknown_QueryInterface IID_IMarshal); 2760 if (hr == S_OK) IUnknown_Release(pOtherUnknown); 2761 2762 /* IMarshal2 is also supported on NT-based systems, but is pretty much 2763 * useless as it has no more methods over IMarshal that it inherits from. */ 2764 2765 IUnknown_Release(pProxy); 2766 2767 ok_no_locks(); 2768 2769 end_host_object(tid, thread); 2770 } 2771 2772 typedef struct 2773 { 2774 IUnknown IUnknown_iface; 2775 ULONG refs; 2776 } HeapUnknown; 2777 2778 static inline HeapUnknown *impl_from_IUnknown(IUnknown *iface) 2779 { 2780 return CONTAINING_RECORD(iface, HeapUnknown, IUnknown_iface); 2781 } 2782 2783 static HRESULT WINAPI HeapUnknown_QueryInterface(IUnknown *iface, REFIID riid, void **ppv) 2784 { 2785 if (IsEqualIID(riid, &IID_IUnknown)) 2786 { 2787 IUnknown_AddRef(iface); 2788 *ppv = iface; 2789 return S_OK; 2790 } 2791 *ppv = NULL; 2792 return E_NOINTERFACE; 2793 } 2794 2795 static ULONG WINAPI HeapUnknown_AddRef(IUnknown *iface) 2796 { 2797 HeapUnknown *This = impl_from_IUnknown(iface); 2798 return InterlockedIncrement((LONG*)&This->refs); 2799 } 2800 2801 static ULONG WINAPI HeapUnknown_Release(IUnknown *iface) 2802 { 2803 HeapUnknown *This = impl_from_IUnknown(iface); 2804 ULONG refs = InterlockedDecrement((LONG*)&This->refs); 2805 if (!refs) HeapFree(GetProcessHeap(), 0, This); 2806 return refs; 2807 } 2808 2809 static const IUnknownVtbl HeapUnknown_Vtbl = 2810 { 2811 HeapUnknown_QueryInterface, 2812 HeapUnknown_AddRef, 2813 HeapUnknown_Release 2814 }; 2815 2816 static void test_proxybuffer(REFIID riid) 2817 { 2818 HRESULT hr; 2819 IPSFactoryBuffer *psfb; 2820 IRpcProxyBuffer *proxy; 2821 LPVOID lpvtbl; 2822 ULONG refs; 2823 CLSID clsid; 2824 HeapUnknown *pUnkOuter = HeapAlloc(GetProcessHeap(), 0, sizeof(*pUnkOuter)); 2825 2826 pUnkOuter->IUnknown_iface.lpVtbl = &HeapUnknown_Vtbl; 2827 pUnkOuter->refs = 1; 2828 2829 hr = CoGetPSClsid(riid, &clsid); 2830 ok_ole_success(hr, CoGetPSClsid); 2831 2832 hr = CoGetClassObject(&clsid, CLSCTX_INPROC_SERVER, NULL, &IID_IPSFactoryBuffer, (LPVOID*)&psfb); 2833 ok_ole_success(hr, CoGetClassObject); 2834 2835 hr = IPSFactoryBuffer_CreateProxy(psfb, &pUnkOuter->IUnknown_iface, riid, &proxy, &lpvtbl); 2836 ok_ole_success(hr, IPSFactoryBuffer_CreateProxy); 2837 ok(lpvtbl != NULL, "IPSFactoryBuffer_CreateProxy succeeded, but returned a NULL vtable!\n"); 2838 2839 /* release our reference to the outer unknown object - the PS factory 2840 * buffer will have AddRef's it in the CreateProxy call */ 2841 refs = IUnknown_Release(&pUnkOuter->IUnknown_iface); 2842 ok(refs == 1, "Ref count of outer unknown should have been 1 instead of %d\n", refs); 2843 2844 /* Not checking return, unreliable on native. Maybe it leaks references? */ 2845 IPSFactoryBuffer_Release(psfb); 2846 2847 refs = IUnknown_Release((IUnknown *)lpvtbl); 2848 ok(refs == 0, "Ref-count leak of %d on IRpcProxyBuffer\n", refs); 2849 2850 refs = IRpcProxyBuffer_Release(proxy); 2851 ok(refs == 0, "Ref-count leak of %d on IRpcProxyBuffer\n", refs); 2852 } 2853 2854 static void test_stubbuffer(REFIID riid) 2855 { 2856 HRESULT hr; 2857 IPSFactoryBuffer *psfb; 2858 IRpcStubBuffer *stub; 2859 ULONG refs; 2860 CLSID clsid; 2861 2862 cLocks = 0; 2863 2864 hr = CoGetPSClsid(riid, &clsid); 2865 ok_ole_success(hr, CoGetPSClsid); 2866 2867 hr = CoGetClassObject(&clsid, CLSCTX_INPROC_SERVER, NULL, &IID_IPSFactoryBuffer, (LPVOID*)&psfb); 2868 ok_ole_success(hr, CoGetClassObject); 2869 2870 hr = IPSFactoryBuffer_CreateStub(psfb, riid, (IUnknown*)&Test_ClassFactory, &stub); 2871 ok_ole_success(hr, IPSFactoryBuffer_CreateStub); 2872 2873 /* Not checking return, unreliable on native. Maybe it leaks references? */ 2874 IPSFactoryBuffer_Release(psfb); 2875 2876 ok_more_than_one_lock(); 2877 2878 IRpcStubBuffer_Disconnect(stub); 2879 2880 ok_no_locks(); 2881 2882 refs = IRpcStubBuffer_Release(stub); 2883 ok(refs == 0, "Ref-count leak of %d on IRpcProxyBuffer\n", refs); 2884 } 2885 2886 static HWND hwnd_app; 2887 2888 static HRESULT WINAPI TestRE_IClassFactory_CreateInstance( 2889 LPCLASSFACTORY iface, 2890 LPUNKNOWN pUnkOuter, 2891 REFIID riid, 2892 LPVOID *ppvObj) 2893 { 2894 DWORD_PTR res; 2895 if (IsEqualIID(riid, &IID_IWineTest)) 2896 { 2897 BOOL ret = SendMessageTimeoutA(hwnd_app, WM_NULL, 0, 0, SMTO_BLOCK, 5000, &res); 2898 ok(ret, "Timed out sending a message to originating window during RPC call\n"); 2899 } 2900 *ppvObj = NULL; 2901 return S_FALSE; 2902 } 2903 2904 static const IClassFactoryVtbl TestREClassFactory_Vtbl = 2905 { 2906 Test_IClassFactory_QueryInterface, 2907 Test_IClassFactory_AddRef, 2908 Test_IClassFactory_Release, 2909 TestRE_IClassFactory_CreateInstance, 2910 Test_IClassFactory_LockServer 2911 }; 2912 2913 static IClassFactory TestRE_ClassFactory = { &TestREClassFactory_Vtbl }; 2914 2915 static LRESULT CALLBACK window_proc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam) 2916 { 2917 switch (msg) 2918 { 2919 case WM_USER: 2920 { 2921 HRESULT hr; 2922 IStream *pStream = NULL; 2923 IClassFactory *proxy = NULL; 2924 IUnknown *object; 2925 DWORD tid; 2926 HANDLE thread; 2927 2928 cLocks = 0; 2929 2930 hr = CreateStreamOnHGlobal(NULL, TRUE, &pStream); 2931 ok_ole_success(hr, CreateStreamOnHGlobal); 2932 tid = start_host_object(pStream, &IID_IClassFactory, (IUnknown*)&TestRE_ClassFactory, MSHLFLAGS_NORMAL, &thread); 2933 2934 ok_more_than_one_lock(); 2935 2936 IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL); 2937 hr = CoUnmarshalInterface(pStream, &IID_IClassFactory, (void **)&proxy); 2938 ok_ole_success(hr, CoReleaseMarshalData); 2939 IStream_Release(pStream); 2940 2941 ok_more_than_one_lock(); 2942 2943 /* note the use of the magic IID_IWineTest value to tell remote thread 2944 * to try to send a message back to us */ 2945 hr = IClassFactory_CreateInstance(proxy, NULL, &IID_IWineTest, (void **)&object); 2946 ok(hr == S_FALSE, "expected S_FALSE, got %d\n", hr); 2947 2948 IClassFactory_Release(proxy); 2949 2950 ok_no_locks(); 2951 2952 end_host_object(tid, thread); 2953 2954 PostMessageA(hwnd, WM_QUIT, 0, 0); 2955 2956 return 0; 2957 } 2958 case WM_USER+1: 2959 { 2960 HRESULT hr; 2961 IStream *pStream = NULL; 2962 IClassFactory *proxy = NULL; 2963 IUnknown *object; 2964 DWORD tid; 2965 HANDLE thread; 2966 2967 cLocks = 0; 2968 2969 hr = CreateStreamOnHGlobal(NULL, TRUE, &pStream); 2970 ok_ole_success(hr, CreateStreamOnHGlobal); 2971 tid = start_host_object(pStream, &IID_IClassFactory, (IUnknown*)&TestRE_ClassFactory, MSHLFLAGS_NORMAL, &thread); 2972 2973 ok_more_than_one_lock(); 2974 2975 IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL); 2976 hr = CoUnmarshalInterface(pStream, &IID_IClassFactory, (void **)&proxy); 2977 ok_ole_success(hr, CoReleaseMarshalData); 2978 IStream_Release(pStream); 2979 2980 ok_more_than_one_lock(); 2981 2982 /* post quit message before a doing a COM call to show that a pending 2983 * WM_QUIT message doesn't stop the call from succeeding */ 2984 PostMessageA(hwnd, WM_QUIT, 0, 0); 2985 hr = IClassFactory_CreateInstance(proxy, NULL, &IID_IUnknown, (void **)&object); 2986 ok(hr == S_FALSE, "IClassFactory_CreateInstance returned 0x%08x, expected S_FALSE\n", hr); 2987 2988 IClassFactory_Release(proxy); 2989 2990 ok_no_locks(); 2991 2992 end_host_object(tid, thread); 2993 2994 return 0; 2995 } 2996 case WM_USER+2: 2997 { 2998 HRESULT hr; 2999 IStream *pStream = NULL; 3000 IClassFactory *proxy = NULL; 3001 IUnknown *object; 3002 DWORD tid; 3003 HANDLE thread; 3004 3005 hr = CreateStreamOnHGlobal(NULL, TRUE, &pStream); 3006 ok_ole_success(hr, CreateStreamOnHGlobal); 3007 tid = start_host_object(pStream, &IID_IClassFactory, (IUnknown*)&Test_ClassFactory, MSHLFLAGS_NORMAL, &thread); 3008 3009 IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL); 3010 hr = CoUnmarshalInterface(pStream, &IID_IClassFactory, (void **)&proxy); 3011 ok_ole_success(hr, CoReleaseMarshalData); 3012 IStream_Release(pStream); 3013 3014 /* shows that COM calls executed during the processing of sent 3015 * messages should fail */ 3016 hr = IClassFactory_CreateInstance(proxy, NULL, &IID_IUnknown, (void **)&object); 3017 ok(hr == RPC_E_CANTCALLOUT_ININPUTSYNCCALL, 3018 "COM call during processing of sent message should return RPC_E_CANTCALLOUT_ININPUTSYNCCALL instead of 0x%08x\n", hr); 3019 3020 IClassFactory_Release(proxy); 3021 3022 end_host_object(tid, thread); 3023 3024 PostQuitMessage(0); 3025 3026 return 0; 3027 } 3028 default: 3029 return DefWindowProcA(hwnd, msg, wparam, lparam); 3030 } 3031 } 3032 3033 static void register_test_window(void) 3034 { 3035 WNDCLASSA wndclass; 3036 3037 memset(&wndclass, 0, sizeof(wndclass)); 3038 wndclass.lpfnWndProc = window_proc; 3039 wndclass.lpszClassName = "WineCOMTest"; 3040 RegisterClassA(&wndclass); 3041 } 3042 3043 static void test_message_reentrancy(void) 3044 { 3045 MSG msg; 3046 3047 hwnd_app = CreateWindowA("WineCOMTest", NULL, 0, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, NULL, NULL, NULL, 0); 3048 ok(hwnd_app != NULL, "Window creation failed\n"); 3049 3050 /* start message re-entrancy test */ 3051 PostMessageA(hwnd_app, WM_USER, 0, 0); 3052 3053 while (GetMessageA(&msg, NULL, 0, 0)) 3054 { 3055 TranslateMessage(&msg); 3056 DispatchMessageA(&msg); 3057 } 3058 DestroyWindow(hwnd_app); 3059 } 3060 3061 static HRESULT WINAPI TestMsg_IClassFactory_CreateInstance( 3062 LPCLASSFACTORY iface, 3063 LPUNKNOWN pUnkOuter, 3064 REFIID riid, 3065 LPVOID *ppvObj) 3066 { 3067 *ppvObj = NULL; 3068 SendMessageA(hwnd_app, WM_USER+2, 0, 0); 3069 return S_OK; 3070 } 3071 3072 static IClassFactoryVtbl TestMsgClassFactory_Vtbl = 3073 { 3074 Test_IClassFactory_QueryInterface, 3075 Test_IClassFactory_AddRef, 3076 Test_IClassFactory_Release, 3077 TestMsg_IClassFactory_CreateInstance, 3078 Test_IClassFactory_LockServer 3079 }; 3080 3081 static IClassFactory TestMsg_ClassFactory = { &TestMsgClassFactory_Vtbl }; 3082 3083 static void test_call_from_message(void) 3084 { 3085 MSG msg; 3086 IStream *pStream; 3087 HRESULT hr; 3088 IClassFactory *proxy; 3089 DWORD tid; 3090 HANDLE thread; 3091 IUnknown *object; 3092 3093 hwnd_app = CreateWindowA("WineCOMTest", NULL, 0, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, NULL, NULL, NULL, 0); 3094 ok(hwnd_app != NULL, "Window creation failed\n"); 3095 3096 hr = CreateStreamOnHGlobal(NULL, TRUE, &pStream); 3097 ok_ole_success(hr, CreateStreamOnHGlobal); 3098 tid = start_host_object(pStream, &IID_IClassFactory, (IUnknown*)&TestMsg_ClassFactory, MSHLFLAGS_NORMAL, &thread); 3099 3100 ok_more_than_one_lock(); 3101 3102 IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL); 3103 hr = CoUnmarshalInterface(pStream, &IID_IClassFactory, (void **)&proxy); 3104 ok_ole_success(hr, CoReleaseMarshalData); 3105 IStream_Release(pStream); 3106 3107 ok_more_than_one_lock(); 3108 3109 /* start message re-entrancy test */ 3110 hr = IClassFactory_CreateInstance(proxy, NULL, &IID_IUnknown, (void **)&object); 3111 ok_ole_success(hr, IClassFactory_CreateInstance); 3112 3113 IClassFactory_Release(proxy); 3114 3115 ok_no_locks(); 3116 3117 end_host_object(tid, thread); 3118 3119 while (GetMessageA(&msg, NULL, 0, 0)) 3120 { 3121 TranslateMessage(&msg); 3122 DispatchMessageA(&msg); 3123 } 3124 DestroyWindow(hwnd_app); 3125 } 3126 3127 static void test_WM_QUIT_handling(void) 3128 { 3129 MSG msg; 3130 3131 hwnd_app = CreateWindowA("WineCOMTest", NULL, 0, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, NULL, NULL, NULL, 0); 3132 ok(hwnd_app != NULL, "Window creation failed\n"); 3133 3134 /* start WM_QUIT handling test */ 3135 PostMessageA(hwnd_app, WM_USER+1, 0, 0); 3136 3137 while (GetMessageA(&msg, NULL, 0, 0)) 3138 { 3139 TranslateMessage(&msg); 3140 DispatchMessageA(&msg); 3141 } 3142 } 3143 3144 static SIZE_T round_global_size(SIZE_T size) 3145 { 3146 static SIZE_T global_size_alignment = -1; 3147 if (global_size_alignment == -1) 3148 { 3149 void *p = GlobalAlloc(GMEM_FIXED, 1); 3150 global_size_alignment = GlobalSize(p); 3151 GlobalFree(p); 3152 } 3153 3154 return ((size + global_size_alignment - 1) & ~(global_size_alignment - 1)); 3155 } 3156 3157 static void test_freethreadedmarshaldata(IStream *pStream, MSHCTX mshctx, void *ptr, DWORD mshlflags) 3158 { 3159 HGLOBAL hglobal; 3160 DWORD size; 3161 char *marshal_data; 3162 HRESULT hr; 3163 3164 hr = GetHGlobalFromStream(pStream, &hglobal); 3165 ok_ole_success(hr, GetHGlobalFromStream); 3166 3167 size = GlobalSize(hglobal); 3168 3169 marshal_data = GlobalLock(hglobal); 3170 3171 if (mshctx == MSHCTX_INPROC) 3172 { 3173 DWORD expected_size = round_global_size(3*sizeof(DWORD) + sizeof(GUID)); 3174 ok(size == expected_size || 3175 broken(size == (2*sizeof(DWORD))) /* Win9x & NT4 */, 3176 "size should have been %d instead of %d\n", expected_size, size); 3177 3178 ok(*(DWORD *)marshal_data == mshlflags, "expected 0x%x, but got 0x%x for mshctx\n", mshlflags, *(DWORD *)marshal_data); 3179 marshal_data += sizeof(DWORD); 3180 ok(*(void **)marshal_data == ptr, "expected %p, but got %p for mshctx\n", ptr, *(void **)marshal_data); 3181 marshal_data += sizeof(void *); 3182 if (sizeof(void*) == 4 && size >= 3*sizeof(DWORD)) 3183 { 3184 ok(*(DWORD *)marshal_data == 0, "expected 0x0, but got 0x%x\n", *(DWORD *)marshal_data); 3185 marshal_data += sizeof(DWORD); 3186 } 3187 if (size >= 3*sizeof(DWORD) + sizeof(GUID)) 3188 { 3189 trace("got guid data: %s\n", wine_dbgstr_guid((GUID *)marshal_data)); 3190 } 3191 } 3192 else 3193 { 3194 ok(size > sizeof(DWORD), "size should have been > sizeof(DWORD), not %d\n", size); 3195 ok(*(DWORD *)marshal_data == 0x574f454d /* MEOW */, 3196 "marshal data should be filled by standard marshal and start with MEOW signature\n"); 3197 } 3198 3199 GlobalUnlock(hglobal); 3200 } 3201 3202 static void test_freethreadedmarshaler(void) 3203 { 3204 HRESULT hr; 3205 IUnknown *pFTUnknown; 3206 IMarshal *pFTMarshal; 3207 IStream *pStream; 3208 IUnknown *pProxy; 3209 static const LARGE_INTEGER llZero; 3210 CLSID clsid; 3211 3212 cLocks = 0; 3213 hr = CoCreateFreeThreadedMarshaler(NULL, &pFTUnknown); 3214 ok_ole_success(hr, CoCreateFreeThreadedMarshaler); 3215 hr = IUnknown_QueryInterface(pFTUnknown, &IID_IMarshal, (void **)&pFTMarshal); 3216 ok_ole_success(hr, IUnknown_QueryInterface); 3217 IUnknown_Release(pFTUnknown); 3218 3219 hr = CreateStreamOnHGlobal(NULL, TRUE, &pStream); 3220 ok_ole_success(hr, CreateStreamOnHGlobal); 3221 3222 /* inproc normal marshaling */ 3223 3224 hr = IMarshal_GetUnmarshalClass(pFTMarshal, &IID_IClassFactory, 3225 &Test_ClassFactory, MSHCTX_INPROC, NULL, MSHLFLAGS_NORMAL, &clsid); 3226 ok_ole_success(hr, IMarshal_GetUnmarshalClass); 3227 ok(IsEqualIID(&clsid, &CLSID_InProcFreeMarshaler), "clsid = %s\n", 3228 wine_dbgstr_guid(&clsid)); 3229 3230 hr = IMarshal_MarshalInterface(pFTMarshal, pStream, &IID_IClassFactory, 3231 &Test_ClassFactory, MSHCTX_INPROC, NULL, MSHLFLAGS_NORMAL); 3232 ok_ole_success(hr, IMarshal_MarshalInterface); 3233 3234 ok_more_than_one_lock(); 3235 3236 test_freethreadedmarshaldata(pStream, MSHCTX_INPROC, &Test_ClassFactory, MSHLFLAGS_NORMAL); 3237 3238 IStream_Seek(pStream, llZero, STREAM_SEEK_SET, NULL); 3239 hr = IMarshal_UnmarshalInterface(pFTMarshal, pStream, &IID_IUnknown, (void **)&pProxy); 3240 ok_ole_success(hr, IMarshal_UnmarshalInterface); 3241 3242 IUnknown_Release(pProxy); 3243 3244 ok_no_locks(); 3245 3246 /* inproc table-strong marshaling */ 3247 3248 IStream_Seek(pStream, llZero, STREAM_SEEK_SET, NULL); 3249 hr = IMarshal_MarshalInterface(pFTMarshal, pStream, &IID_IClassFactory, 3250 (IUnknown*)&Test_ClassFactory, MSHCTX_INPROC, (void *)0xdeadbeef, 3251 MSHLFLAGS_TABLESTRONG); 3252 ok_ole_success(hr, IMarshal_MarshalInterface); 3253 3254 ok_more_than_one_lock(); 3255 3256 test_freethreadedmarshaldata(pStream, MSHCTX_INPROC, &Test_ClassFactory, MSHLFLAGS_TABLESTRONG); 3257 3258 IStream_Seek(pStream, llZero, STREAM_SEEK_SET, NULL); 3259 hr = IMarshal_UnmarshalInterface(pFTMarshal, pStream, &IID_IUnknown, (void **)&pProxy); 3260 ok_ole_success(hr, IMarshal_UnmarshalInterface); 3261 3262 IUnknown_Release(pProxy); 3263 3264 ok_more_than_one_lock(); 3265 3266 IStream_Seek(pStream, llZero, STREAM_SEEK_SET, NULL); 3267 hr = IMarshal_ReleaseMarshalData(pFTMarshal, pStream); 3268 ok_ole_success(hr, IMarshal_ReleaseMarshalData); 3269 3270 ok_no_locks(); 3271 3272 /* inproc table-weak marshaling */ 3273 3274 IStream_Seek(pStream, llZero, STREAM_SEEK_SET, NULL); 3275 hr = IMarshal_MarshalInterface(pFTMarshal, pStream, &IID_IClassFactory, 3276 (IUnknown*)&Test_ClassFactory, MSHCTX_INPROC, (void *)0xdeadbeef, 3277 MSHLFLAGS_TABLEWEAK); 3278 ok_ole_success(hr, IMarshal_MarshalInterface); 3279 3280 ok_no_locks(); 3281 3282 test_freethreadedmarshaldata(pStream, MSHCTX_INPROC, &Test_ClassFactory, MSHLFLAGS_TABLEWEAK); 3283 3284 IStream_Seek(pStream, llZero, STREAM_SEEK_SET, NULL); 3285 hr = IMarshal_UnmarshalInterface(pFTMarshal, pStream, &IID_IUnknown, (void **)&pProxy); 3286 ok_ole_success(hr, IMarshal_UnmarshalInterface); 3287 3288 ok_more_than_one_lock(); 3289 3290 IUnknown_Release(pProxy); 3291 3292 ok_no_locks(); 3293 3294 /* inproc normal marshaling (for extraordinary cases) */ 3295 3296 IStream_Seek(pStream, llZero, STREAM_SEEK_SET, NULL); 3297 hr = IMarshal_MarshalInterface(pFTMarshal, pStream, &IID_IClassFactory, 3298 &Test_ClassFactory, MSHCTX_INPROC, NULL, MSHLFLAGS_NORMAL); 3299 ok_ole_success(hr, IMarshal_MarshalInterface); 3300 3301 ok_more_than_one_lock(); 3302 3303 /* this call shows that DisconnectObject does nothing */ 3304 hr = IMarshal_DisconnectObject(pFTMarshal, 0); 3305 ok_ole_success(hr, IMarshal_DisconnectObject); 3306 3307 ok_more_than_one_lock(); 3308 3309 IStream_Seek(pStream, llZero, STREAM_SEEK_SET, NULL); 3310 hr = IMarshal_ReleaseMarshalData(pFTMarshal, pStream); 3311 ok_ole_success(hr, IMarshal_ReleaseMarshalData); 3312 3313 ok_no_locks(); 3314 3315 /* doesn't enforce marshaling rules here and allows us to unmarshal the 3316 * interface, even though it was freed above */ 3317 IStream_Seek(pStream, llZero, STREAM_SEEK_SET, NULL); 3318 hr = IMarshal_UnmarshalInterface(pFTMarshal, pStream, &IID_IUnknown, (void **)&pProxy); 3319 ok_ole_success(hr, IMarshal_UnmarshalInterface); 3320 3321 ok_no_locks(); 3322 3323 /* local normal marshaling */ 3324 3325 hr = IMarshal_GetUnmarshalClass(pFTMarshal, &IID_IClassFactory, 3326 &Test_ClassFactory, MSHCTX_LOCAL, NULL, MSHLFLAGS_NORMAL, &clsid); 3327 ok_ole_success(hr, IMarshal_GetUnmarshalClass); 3328 ok(IsEqualIID(&clsid, &CLSID_StdMarshal), "clsid = %s\n", 3329 wine_dbgstr_guid(&clsid)); 3330 3331 IStream_Seek(pStream, llZero, STREAM_SEEK_SET, NULL); 3332 hr = IMarshal_MarshalInterface(pFTMarshal, pStream, &IID_IClassFactory, &Test_ClassFactory, MSHCTX_LOCAL, NULL, MSHLFLAGS_NORMAL); 3333 ok_ole_success(hr, IMarshal_MarshalInterface); 3334 3335 ok_more_than_one_lock(); 3336 3337 test_freethreadedmarshaldata(pStream, MSHCTX_LOCAL, &Test_ClassFactory, MSHLFLAGS_NORMAL); 3338 3339 IStream_Seek(pStream, llZero, STREAM_SEEK_SET, NULL); 3340 hr = CoReleaseMarshalData(pStream); 3341 ok_ole_success(hr, CoReleaseMarshalData); 3342 3343 ok_no_locks(); 3344 3345 IStream_Release(pStream); 3346 IMarshal_Release(pFTMarshal); 3347 } 3348 3349 static HRESULT reg_unreg_wine_test_class(BOOL Register) 3350 { 3351 HRESULT hr; 3352 char buffer[256]; 3353 LPOLESTR pszClsid; 3354 HKEY hkey; 3355 DWORD dwDisposition; 3356 DWORD error; 3357 3358 hr = StringFromCLSID(&CLSID_WineTest, &pszClsid); 3359 ok_ole_success(hr, "StringFromCLSID"); 3360 strcpy(buffer, "CLSID\\"); 3361 WideCharToMultiByte(CP_ACP, 0, pszClsid, -1, buffer + strlen(buffer), sizeof(buffer) - strlen(buffer), NULL, NULL); 3362 CoTaskMemFree(pszClsid); 3363 strcat(buffer, "\\InprocHandler32"); 3364 if (Register) 3365 { 3366 error = RegCreateKeyExA(HKEY_CLASSES_ROOT, buffer, 0, NULL, 0, KEY_SET_VALUE, NULL, &hkey, &dwDisposition); 3367 if (error == ERROR_ACCESS_DENIED) 3368 { 3369 skip("Not authorized to modify the Classes key\n"); 3370 return E_FAIL; 3371 } 3372 ok(error == ERROR_SUCCESS, "RegCreateKeyEx failed with error %d\n", error); 3373 if (error != ERROR_SUCCESS) hr = E_FAIL; 3374 error = RegSetValueExA(hkey, NULL, 0, REG_SZ, (const unsigned char *)"\"ole32.dll\"", strlen("\"ole32.dll\"") + 1); 3375 ok(error == ERROR_SUCCESS, "RegSetValueEx failed with error %d\n", error); 3376 if (error != ERROR_SUCCESS) hr = E_FAIL; 3377 RegCloseKey(hkey); 3378 } 3379 else 3380 { 3381 RegDeleteKeyA(HKEY_CLASSES_ROOT, buffer); 3382 *strrchr(buffer, '\\') = '\0'; 3383 RegDeleteKeyA(HKEY_CLASSES_ROOT, buffer); 3384 } 3385 return hr; 3386 } 3387 3388 static void test_inproc_handler(void) 3389 { 3390 HRESULT hr; 3391 IUnknown *pObject; 3392 IUnknown *pObject2; 3393 3394 if (FAILED(reg_unreg_wine_test_class(TRUE))) 3395 return; 3396 3397 hr = CoCreateInstance(&CLSID_WineTest, NULL, CLSCTX_INPROC_HANDLER, &IID_IUnknown, (void **)&pObject); 3398 ok_ole_success(hr, "CoCreateInstance"); 3399 3400 if (SUCCEEDED(hr)) 3401 { 3402 hr = IUnknown_QueryInterface(pObject, &IID_IWineTest, (void **)&pObject2); 3403 ok(hr == E_NOINTERFACE, "IUnknown_QueryInterface on handler for invalid interface returned 0x%08x instead of E_NOINTERFACE\n", hr); 3404 3405 /* it's a handler as it supports IOleObject */ 3406 hr = IUnknown_QueryInterface(pObject, &IID_IOleObject, (void **)&pObject2); 3407 ok_ole_success(hr, "IUnknown_QueryInterface(&IID_IOleObject)"); 3408 IUnknown_Release(pObject2); 3409 3410 IUnknown_Release(pObject); 3411 } 3412 3413 reg_unreg_wine_test_class(FALSE); 3414 } 3415 3416 static HRESULT WINAPI Test_SMI_QueryInterface( 3417 IStdMarshalInfo *iface, 3418 REFIID riid, 3419 LPVOID *ppvObj) 3420 { 3421 if (ppvObj == NULL) return E_POINTER; 3422 3423 if (IsEqualGUID(riid, &IID_IUnknown) || 3424 IsEqualGUID(riid, &IID_IStdMarshalInfo)) 3425 { 3426 *ppvObj = iface; 3427 IStdMarshalInfo_AddRef(iface); 3428 return S_OK; 3429 } 3430 3431 return E_NOINTERFACE; 3432 } 3433 3434 static ULONG WINAPI Test_SMI_AddRef(IStdMarshalInfo *iface) 3435 { 3436 LockModule(); 3437 return 2; /* non-heap-based object */ 3438 } 3439 3440 static ULONG WINAPI Test_SMI_Release(IStdMarshalInfo *iface) 3441 { 3442 UnlockModule(); 3443 return 1; /* non-heap-based object */ 3444 } 3445 3446 static HRESULT WINAPI Test_SMI_GetClassForHandler( 3447 IStdMarshalInfo *iface, 3448 DWORD dwDestContext, 3449 void *pvDestContext, 3450 CLSID *pClsid) 3451 { 3452 *pClsid = CLSID_WineTest; 3453 return S_OK; 3454 } 3455 3456 static const IStdMarshalInfoVtbl Test_SMI_Vtbl = 3457 { 3458 Test_SMI_QueryInterface, 3459 Test_SMI_AddRef, 3460 Test_SMI_Release, 3461 Test_SMI_GetClassForHandler 3462 }; 3463 3464 static IStdMarshalInfo Test_SMI = {&Test_SMI_Vtbl}; 3465 3466 static void test_handler_marshaling(void) 3467 { 3468 HRESULT hr; 3469 IStream *pStream = NULL; 3470 IUnknown *pProxy = NULL; 3471 IUnknown *pObject; 3472 DWORD tid; 3473 HANDLE thread; 3474 static const LARGE_INTEGER ullZero; 3475 3476 if (FAILED(reg_unreg_wine_test_class(TRUE))) 3477 return; 3478 cLocks = 0; 3479 3480 hr = CreateStreamOnHGlobal(NULL, TRUE, &pStream); 3481 ok_ole_success(hr, "CreateStreamOnHGlobal"); 3482 tid = start_host_object(pStream, &IID_IUnknown, (IUnknown*)&Test_SMI, MSHLFLAGS_NORMAL, &thread); 3483 3484 ok_more_than_one_lock(); 3485 3486 IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL); 3487 hr = CoUnmarshalInterface(pStream, &IID_IUnknown, (void **)&pProxy); 3488 ok_ole_success(hr, "CoUnmarshalInterface"); 3489 IStream_Release(pStream); 3490 3491 if(hr == S_OK) 3492 { 3493 ok_more_than_one_lock(); 3494 3495 hr = IUnknown_QueryInterface(pProxy, &IID_IWineTest, (void **)&pObject); 3496 ok(hr == E_NOINTERFACE, "IUnknown_QueryInterface with unknown IID should have returned E_NOINTERFACE instead of 0x%08x\n", hr); 3497 3498 /* it's a handler as it supports IOleObject */ 3499 hr = IUnknown_QueryInterface(pProxy, &IID_IOleObject, (void **)&pObject); 3500 todo_wine 3501 ok_ole_success(hr, "IUnknown_QueryInterface(&IID_IOleObject)"); 3502 if (SUCCEEDED(hr)) IUnknown_Release(pObject); 3503 3504 IUnknown_Release(pProxy); 3505 3506 ok_no_locks(); 3507 } 3508 3509 end_host_object(tid, thread); 3510 reg_unreg_wine_test_class(FALSE); 3511 3512 /* FIXME: test IPersist interface has the same effect as IStdMarshalInfo */ 3513 } 3514 3515 3516 static void test_client_security(void) 3517 { 3518 HRESULT hr; 3519 IStream *pStream = NULL; 3520 IClassFactory *pProxy = NULL; 3521 IUnknown *pProxy2 = NULL; 3522 IUnknown *pUnknown1 = NULL; 3523 IUnknown *pUnknown2 = NULL; 3524 IClientSecurity *pCliSec = NULL; 3525 IMarshal *pMarshal; 3526 DWORD tid; 3527 HANDLE thread; 3528 static const LARGE_INTEGER ullZero; 3529 DWORD dwAuthnSvc; 3530 DWORD dwAuthzSvc; 3531 OLECHAR *pServerPrincName; 3532 DWORD dwAuthnLevel; 3533 DWORD dwImpLevel; 3534 void *pAuthInfo; 3535 DWORD dwCapabilities; 3536 void *pv; 3537 3538 cLocks = 0; 3539 3540 hr = CreateStreamOnHGlobal(NULL, TRUE, &pStream); 3541 ok_ole_success(hr, "CreateStreamOnHGlobal"); 3542 tid = start_host_object(pStream, &IID_IClassFactory, (IUnknown*)&Test_ClassFactory, MSHLFLAGS_NORMAL, &thread); 3543 3544 IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL); 3545 hr = CoUnmarshalInterface(pStream, &IID_IClassFactory, (void **)&pProxy); 3546 ok_ole_success(hr, "CoUnmarshalInterface"); 3547 IStream_Release(pStream); 3548 3549 hr = IClassFactory_QueryInterface(pProxy, &IID_IUnknown, (LPVOID*)&pUnknown1); 3550 ok_ole_success(hr, "IUnknown_QueryInterface IID_IUnknown"); 3551 3552 hr = IClassFactory_QueryInterface(pProxy, &IID_IRemUnknown, (LPVOID*)&pProxy2); 3553 ok_ole_success(hr, "IUnknown_QueryInterface IID_IStream"); 3554 3555 hr = IUnknown_QueryInterface(pProxy2, &IID_IUnknown, (LPVOID*)&pUnknown2); 3556 ok_ole_success(hr, "IUnknown_QueryInterface IID_IUnknown"); 3557 3558 ok(pUnknown1 == pUnknown2, "both proxy's IUnknowns should be the same - %p, %p\n", pUnknown1, pUnknown2); 3559 3560 hr = IClassFactory_QueryInterface(pProxy, &IID_IMarshal, (LPVOID*)&pMarshal); 3561 ok_ole_success(hr, "IUnknown_QueryInterface IID_IMarshal"); 3562 3563 hr = IClassFactory_QueryInterface(pProxy, &IID_IClientSecurity, (LPVOID*)&pCliSec); 3564 ok_ole_success(hr, "IUnknown_QueryInterface IID_IClientSecurity"); 3565 3566 hr = IClientSecurity_QueryBlanket(pCliSec, (IUnknown *)pProxy, NULL, NULL, NULL, NULL, NULL, NULL, NULL); 3567 todo_wine ok_ole_success(hr, "IClientSecurity_QueryBlanket (all NULLs)"); 3568 3569 hr = IClientSecurity_QueryBlanket(pCliSec, (IUnknown *)pMarshal, NULL, NULL, NULL, NULL, NULL, NULL, NULL); 3570 todo_wine ok(hr == E_NOINTERFACE, "IClientSecurity_QueryBlanket with local interface should have returned E_NOINTERFACE instead of 0x%08x\n", hr); 3571 3572 hr = IClientSecurity_QueryBlanket(pCliSec, (IUnknown *)pProxy, &dwAuthnSvc, &dwAuthzSvc, &pServerPrincName, &dwAuthnLevel, &dwImpLevel, &pAuthInfo, &dwCapabilities); 3573 todo_wine ok_ole_success(hr, "IClientSecurity_QueryBlanket"); 3574 3575 hr = IClientSecurity_SetBlanket(pCliSec, (IUnknown *)pProxy, dwAuthnSvc, dwAuthzSvc, pServerPrincName, dwAuthnLevel, RPC_C_IMP_LEVEL_IMPERSONATE, pAuthInfo, dwCapabilities); 3576 todo_wine ok_ole_success(hr, "IClientSecurity_SetBlanket"); 3577 3578 hr = IClassFactory_CreateInstance(pProxy, NULL, &IID_IWineTest, &pv); 3579 ok(hr == E_NOINTERFACE, "COM call should have succeeded instead of returning 0x%08x\n", hr); 3580 3581 hr = IClientSecurity_SetBlanket(pCliSec, (IUnknown *)pMarshal, dwAuthnSvc, dwAuthzSvc, pServerPrincName, dwAuthnLevel, dwImpLevel, pAuthInfo, dwCapabilities); 3582 todo_wine ok(hr == E_NOINTERFACE, "IClientSecurity_SetBlanket with local interface should have returned E_NOINTERFACE instead of 0x%08x\n", hr); 3583 3584 hr = IClientSecurity_SetBlanket(pCliSec, (IUnknown *)pProxy, 0xdeadbeef, dwAuthzSvc, pServerPrincName, dwAuthnLevel, dwImpLevel, pAuthInfo, dwCapabilities); 3585 todo_wine ok(hr == E_INVALIDARG, "IClientSecurity_SetBlanke with invalid dwAuthnSvc should have returned E_INVALIDARG instead of 0x%08x\n", hr); 3586 3587 CoTaskMemFree(pServerPrincName); 3588 3589 hr = IClientSecurity_QueryBlanket(pCliSec, pUnknown1, &dwAuthnSvc, &dwAuthzSvc, &pServerPrincName, &dwAuthnLevel, &dwImpLevel, &pAuthInfo, &dwCapabilities); 3590 todo_wine ok_ole_success(hr, "IClientSecurity_QueryBlanket(IUnknown)"); 3591 3592 CoTaskMemFree(pServerPrincName); 3593 3594 IClassFactory_Release(pProxy); 3595 IUnknown_Release(pProxy2); 3596 IUnknown_Release(pUnknown1); 3597 IUnknown_Release(pUnknown2); 3598 IMarshal_Release(pMarshal); 3599 IClientSecurity_Release(pCliSec); 3600 3601 end_host_object(tid, thread); 3602 } 3603 3604 static HANDLE heventShutdown; 3605 3606 static void LockModuleOOP(void) 3607 { 3608 InterlockedIncrement(&cLocks); /* for test purposes only */ 3609 CoAddRefServerProcess(); 3610 } 3611 3612 static void UnlockModuleOOP(void) 3613 { 3614 InterlockedDecrement(&cLocks); /* for test purposes only */ 3615 if (!CoReleaseServerProcess()) 3616 SetEvent(heventShutdown); 3617 } 3618 3619 static HWND hwnd_app; 3620 3621 struct local_server 3622 { 3623 IPersist IPersist_iface; /* a nice short interface */ 3624 }; 3625 3626 static HRESULT WINAPI local_server_QueryInterface(IPersist *iface, REFIID iid, void **obj) 3627 { 3628 *obj = NULL; 3629 3630 if (IsEqualGUID(iid, &IID_IUnknown) || 3631 IsEqualGUID(iid, &IID_IPersist)) 3632 *obj = iface; 3633 3634 if (*obj) 3635 { 3636 IPersist_AddRef(iface); 3637 return S_OK; 3638 } 3639 return E_NOINTERFACE; 3640 } 3641 3642 static ULONG WINAPI local_server_AddRef(IPersist *iface) 3643 { 3644 return 2; 3645 } 3646 3647 static ULONG WINAPI local_server_Release(IPersist *iface) 3648 { 3649 return 1; 3650 } 3651 3652 static HRESULT WINAPI local_server_GetClassID(IPersist *iface, CLSID *clsid) 3653 { 3654 HRESULT hr; 3655 3656 *clsid = IID_IUnknown; 3657 3658 /* Test calling CoDisconnectObject within a COM call */ 3659 hr = CoDisconnectObject((IUnknown *)iface, 0); 3660 ok(hr == S_OK, "got %08x\n", hr); 3661 3662 /* Initialize and uninitialize the apartment to show that we 3663 * remain in the autojoined mta */ 3664 hr = pCoInitializeEx( NULL, COINIT_MULTITHREADED ); 3665 ok( hr == S_FALSE, "got %08x\n", hr ); 3666 CoUninitialize(); 3667 3668 return S_OK; 3669 } 3670 3671 static const IPersistVtbl local_server_persist_vtbl = 3672 { 3673 local_server_QueryInterface, 3674 local_server_AddRef, 3675 local_server_Release, 3676 local_server_GetClassID 3677 }; 3678 3679 struct local_server local_server_class = 3680 { 3681 {&local_server_persist_vtbl} 3682 }; 3683 3684 static HRESULT WINAPI TestOOP_IClassFactory_QueryInterface( 3685 LPCLASSFACTORY iface, 3686 REFIID riid, 3687 LPVOID *ppvObj) 3688 { 3689 if (ppvObj == NULL) return E_POINTER; 3690 3691 if (IsEqualGUID(riid, &IID_IUnknown) || 3692 IsEqualGUID(riid, &IID_IClassFactory)) 3693 { 3694 *ppvObj = iface; 3695 IClassFactory_AddRef(iface); 3696 return S_OK; 3697 } 3698 3699 return E_NOINTERFACE; 3700 } 3701 3702 static ULONG WINAPI TestOOP_IClassFactory_AddRef(LPCLASSFACTORY iface) 3703 { 3704 return 2; /* non-heap-based object */ 3705 } 3706 3707 static ULONG WINAPI TestOOP_IClassFactory_Release(LPCLASSFACTORY iface) 3708 { 3709 return 1; /* non-heap-based object */ 3710 } 3711 3712 static HRESULT WINAPI TestOOP_IClassFactory_CreateInstance( 3713 LPCLASSFACTORY iface, 3714 LPUNKNOWN pUnkOuter, 3715 REFIID riid, 3716 LPVOID *ppvObj) 3717 { 3718 IPersist *persist = &local_server_class.IPersist_iface; 3719 HRESULT hr; 3720 IPersist_AddRef( persist ); 3721 hr = IPersist_QueryInterface( persist, riid, ppvObj ); 3722 IPersist_Release( persist ); 3723 return hr; 3724 } 3725 3726 static HRESULT WINAPI TestOOP_IClassFactory_LockServer( 3727 LPCLASSFACTORY iface, 3728 BOOL fLock) 3729 { 3730 if (fLock) 3731 LockModuleOOP(); 3732 else 3733 UnlockModuleOOP(); 3734 return S_OK; 3735 } 3736 3737 static const IClassFactoryVtbl TestClassFactoryOOP_Vtbl = 3738 { 3739 TestOOP_IClassFactory_QueryInterface, 3740 TestOOP_IClassFactory_AddRef, 3741 TestOOP_IClassFactory_Release, 3742 TestOOP_IClassFactory_CreateInstance, 3743 TestOOP_IClassFactory_LockServer 3744 }; 3745 3746 static IClassFactory TestOOP_ClassFactory = { &TestClassFactoryOOP_Vtbl }; 3747 3748 static void test_register_local_server(void) 3749 { 3750 DWORD cookie; 3751 HRESULT hr; 3752 HANDLE ready_event; 3753 DWORD wait; 3754 HANDLE handles[2]; 3755 3756 heventShutdown = CreateEventA(NULL, TRUE, FALSE, NULL); 3757 ready_event = CreateEventA(NULL, FALSE, FALSE, "Wine COM Test Ready Event"); 3758 handles[0] = CreateEventA(NULL, FALSE, FALSE, "Wine COM Test Quit Event"); 3759 handles[1] = CreateEventA(NULL, FALSE, FALSE, "Wine COM Test Repeat Event"); 3760 3761 again: 3762 hr = CoRegisterClassObject(&CLSID_WineOOPTest, (IUnknown *)&TestOOP_ClassFactory, 3763 CLSCTX_LOCAL_SERVER, REGCLS_SINGLEUSE, &cookie); 3764 ok_ole_success(hr, CoRegisterClassObject); 3765 3766 SetEvent(ready_event); 3767 3768 do 3769 { 3770 wait = MsgWaitForMultipleObjects(2, handles, FALSE, 30000, QS_ALLINPUT); 3771 if (wait == WAIT_OBJECT_0+2) 3772 { 3773 MSG msg; 3774 3775 if (PeekMessageA(&msg, NULL, 0, 0, PM_REMOVE)) 3776 { 3777 trace("Message 0x%x\n", msg.message); 3778 TranslateMessage(&msg); 3779 DispatchMessageA(&msg); 3780 } 3781 } 3782 else if (wait == WAIT_OBJECT_0+1) 3783 { 3784 hr = CoRevokeClassObject(cookie); 3785 ok_ole_success(hr, CoRevokeClassObject); 3786 goto again; 3787 } 3788 } 3789 while (wait == WAIT_OBJECT_0+2); 3790 3791 ok( wait == WAIT_OBJECT_0, "quit event wait timed out\n" ); 3792 hr = CoRevokeClassObject(cookie); 3793 ok_ole_success(hr, CoRevokeClassObject); 3794 CloseHandle(handles[0]); 3795 CloseHandle(handles[1]); 3796 } 3797 3798 static HANDLE create_target_process(const char *arg) 3799 { 3800 char **argv; 3801 char cmdline[MAX_PATH]; 3802 BOOL ret; 3803 PROCESS_INFORMATION pi; 3804 STARTUPINFOA si = { 0 }; 3805 si.cb = sizeof(si); 3806 3807 pi.hThread = NULL; 3808 pi.hProcess = NULL; 3809 winetest_get_mainargs( &argv ); 3810 sprintf(cmdline, "\"%s\" %s %s", argv[0], argv[1], arg); 3811 ret = CreateProcessA(argv[0], cmdline, NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi); 3812 ok(ret, "CreateProcess failed with error: %u\n", GetLastError()); 3813 if (pi.hThread) CloseHandle(pi.hThread); 3814 return pi.hProcess; 3815 } 3816 3817 /* tests functions commonly used by out of process COM servers */ 3818 static void test_local_server(void) 3819 { 3820 DWORD cookie; 3821 HRESULT hr; 3822 IClassFactory * cf; 3823 IPersist *persist; 3824 DWORD ret; 3825 HANDLE process; 3826 HANDLE quit_event; 3827 HANDLE ready_event; 3828 HANDLE repeat_event; 3829 CLSID clsid; 3830 3831 heventShutdown = CreateEventA(NULL, TRUE, FALSE, NULL); 3832 3833 cLocks = 0; 3834 3835 /* Start the object suspended */ 3836 hr = CoRegisterClassObject(&CLSID_WineOOPTest, (IUnknown *)&TestOOP_ClassFactory, 3837 CLSCTX_LOCAL_SERVER, REGCLS_MULTIPLEUSE | REGCLS_SUSPENDED, &cookie); 3838 ok_ole_success(hr, CoRegisterClassObject); 3839 3840 /* ... and CoGetClassObject does not find it and fails when it looks for the 3841 * class in the registry */ 3842 hr = CoGetClassObject(&CLSID_WineOOPTest, CLSCTX_INPROC_SERVER, 3843 NULL, &IID_IClassFactory, (LPVOID*)&cf); 3844 ok(hr == REGDB_E_CLASSNOTREG || /* NT */ 3845 hr == S_OK /* Win9x */, 3846 "CoGetClassObject should have returned REGDB_E_CLASSNOTREG instead of 0x%08x\n", hr); 3847 3848 /* Resume the object suspended above ... */ 3849 hr = CoResumeClassObjects(); 3850 ok_ole_success(hr, CoResumeClassObjects); 3851 3852 /* ... and now it should succeed */ 3853 hr = CoGetClassObject(&CLSID_WineOOPTest, CLSCTX_INPROC_SERVER, 3854 NULL, &IID_IClassFactory, (LPVOID*)&cf); 3855 ok_ole_success(hr, CoGetClassObject); 3856 3857 /* Now check the locking is working */ 3858 /* NOTE: we are accessing the class directly, not through a proxy */ 3859 3860 ok_no_locks(); 3861 3862 hr = IClassFactory_LockServer(cf, TRUE); 3863 ok_ole_success(hr, IClassFactory_LockServer); 3864 3865 ok_more_than_one_lock(); 3866 3867 IClassFactory_LockServer(cf, FALSE); 3868 ok_ole_success(hr, IClassFactory_LockServer); 3869 3870 ok_no_locks(); 3871 3872 IClassFactory_Release(cf); 3873 3874 /* wait for shutdown signal */ 3875 ret = WaitForSingleObject(heventShutdown, 0); 3876 ok(ret != WAIT_TIMEOUT, "Server didn't shut down\n"); 3877 3878 /* try to connect again after SCM has suspended registered class objects */ 3879 hr = CoGetClassObject(&CLSID_WineOOPTest, CLSCTX_INPROC_SERVER | CLSCTX_LOCAL_SERVER, NULL, 3880 &IID_IClassFactory, (LPVOID*)&cf); 3881 ok(hr == CO_E_SERVER_STOPPING || /* NT */ 3882 hr == REGDB_E_CLASSNOTREG || /* win2k */ 3883 hr == S_OK /* Win9x */, 3884 "CoGetClassObject should have returned CO_E_SERVER_STOPPING or REGDB_E_CLASSNOTREG instead of 0x%08x\n", hr); 3885 3886 hr = CoRevokeClassObject(cookie); 3887 ok_ole_success(hr, CoRevokeClassObject); 3888 3889 CloseHandle(heventShutdown); 3890 3891 process = create_target_process("-Embedding"); 3892 ok(process != NULL, "couldn't start local server process, error was %d\n", GetLastError()); 3893 3894 ready_event = CreateEventA(NULL, FALSE, FALSE, "Wine COM Test Ready Event"); 3895 ok( !WaitForSingleObject(ready_event, 10000), "wait timed out\n" ); 3896 3897 hr = CoCreateInstance(&CLSID_WineOOPTest, NULL, CLSCTX_LOCAL_SERVER, &IID_IPersist, (void **)&persist); 3898 ok_ole_success(hr, CoCreateInstance); 3899 3900 IPersist_Release(persist); 3901 3902 hr = CoCreateInstance(&CLSID_WineOOPTest, NULL, CLSCTX_LOCAL_SERVER, &IID_IPersist, (void **)&persist); 3903 ok(hr == REGDB_E_CLASSNOTREG, "Second CoCreateInstance on REGCLS_SINGLEUSE object should have failed\n"); 3904 3905 /* Re-register the class and try calling CoDisconnectObject from within a call to that object */ 3906 repeat_event = CreateEventA(NULL, FALSE, FALSE, "Wine COM Test Repeat Event"); 3907 SetEvent(repeat_event); 3908 CloseHandle(repeat_event); 3909 3910 ok( !WaitForSingleObject(ready_event, 10000), "wait timed out\n" ); 3911 CloseHandle(ready_event); 3912 3913 hr = CoCreateInstance(&CLSID_WineOOPTest, NULL, CLSCTX_LOCAL_SERVER, &IID_IPersist, (void **)&persist); 3914 ok_ole_success(hr, CoCreateInstance); 3915 3916 /* GetClassID will call CoDisconnectObject */ 3917 IPersist_GetClassID(persist, &clsid); 3918 IPersist_Release(persist); 3919 3920 quit_event = CreateEventA(NULL, FALSE, FALSE, "Wine COM Test Quit Event"); 3921 SetEvent(quit_event); 3922 3923 winetest_wait_child_process( process ); 3924 CloseHandle(quit_event); 3925 CloseHandle(process); 3926 } 3927 3928 struct git_params 3929 { 3930 DWORD cookie; 3931 IGlobalInterfaceTable *git; 3932 }; 3933 3934 static DWORD CALLBACK get_global_interface_proc(LPVOID pv) 3935 { 3936 HRESULT hr; 3937 struct git_params *params = pv; 3938 IClassFactory *cf; 3939 3940 hr = IGlobalInterfaceTable_GetInterfaceFromGlobal(params->git, params->cookie, &IID_IClassFactory, (void **)&cf); 3941 ok(hr == CO_E_NOTINITIALIZED || 3942 broken(hr == E_UNEXPECTED) /* win2k */ || 3943 broken(hr == S_OK) /* NT 4 */, 3944 "IGlobalInterfaceTable_GetInterfaceFromGlobal should have failed with error CO_E_NOTINITIALIZED or E_UNEXPECTED instead of 0x%08x\n", 3945 hr); 3946 if (hr == S_OK) 3947 IClassFactory_Release(cf); 3948 3949 CoInitialize(NULL); 3950 3951 hr = IGlobalInterfaceTable_GetInterfaceFromGlobal(params->git, params->cookie, &IID_IClassFactory, (void **)&cf); 3952 ok_ole_success(hr, IGlobalInterfaceTable_GetInterfaceFromGlobal); 3953 3954 IClassFactory_Release(cf); 3955 3956 CoUninitialize(); 3957 3958 return hr; 3959 } 3960 3961 static void test_globalinterfacetable(void) 3962 { 3963 HRESULT hr; 3964 IGlobalInterfaceTable *git; 3965 DWORD cookie; 3966 HANDLE thread; 3967 DWORD tid; 3968 struct git_params params; 3969 DWORD ret; 3970 IUnknown *object; 3971 IClassFactory *cf; 3972 ULONG ref; 3973 3974 trace("test_globalinterfacetable\n"); 3975 cLocks = 0; 3976 3977 hr = pDllGetClassObject(&CLSID_StdGlobalInterfaceTable, &IID_IClassFactory, (void**)&cf); 3978 ok(hr == S_OK, "got 0x%08x\n", hr); 3979 3980 hr = IClassFactory_QueryInterface(cf, &IID_IGlobalInterfaceTable, (void**)&object); 3981 ok(hr == E_NOINTERFACE, "got 0x%08x\n", hr); 3982 3983 IClassFactory_Release(cf); 3984 3985 hr = CoCreateInstance(&CLSID_StdGlobalInterfaceTable, NULL, CLSCTX_INPROC_SERVER, &IID_IGlobalInterfaceTable, (void **)&git); 3986 ok_ole_success(hr, CoCreateInstance); 3987 3988 ref = IGlobalInterfaceTable_AddRef(git); 3989 ok(ref == 1, "ref=%d\n", ref); 3990 ref = IGlobalInterfaceTable_AddRef(git); 3991 ok(ref == 1, "ref=%d\n", ref); 3992 3993 ref = IGlobalInterfaceTable_Release(git); 3994 ok(ref == 1, "ref=%d\n", ref); 3995 ref = IGlobalInterfaceTable_Release(git); 3996 ok(ref == 1, "ref=%d\n", ref); 3997 3998 hr = IGlobalInterfaceTable_RegisterInterfaceInGlobal(git, (IUnknown *)&Test_ClassFactory, &IID_IClassFactory, &cookie); 3999 ok_ole_success(hr, IGlobalInterfaceTable_RegisterInterfaceInGlobal); 4000 4001 ok_more_than_one_lock(); 4002 4003 params.cookie = cookie; 4004 params.git = git; 4005 /* note: params is on stack so we MUST wait for get_global_interface_proc 4006 * to exit before we can return */ 4007 thread = CreateThread(NULL, 0, get_global_interface_proc, ¶ms, 0, &tid); 4008 4009 ret = MsgWaitForMultipleObjects(1, &thread, FALSE, 10000, QS_ALLINPUT); 4010 while (ret == WAIT_OBJECT_0 + 1) 4011 { 4012 MSG msg; 4013 while (PeekMessageA(&msg, NULL, 0, 0, PM_REMOVE)) 4014 DispatchMessageA(&msg); 4015 ret = MsgWaitForMultipleObjects(1, &thread, FALSE, 10000, QS_ALLINPUT); 4016 } 4017 4018 CloseHandle(thread); 4019 4020 /* test getting interface from global with different iid */ 4021 hr = IGlobalInterfaceTable_GetInterfaceFromGlobal(git, cookie, &IID_IUnknown, (void **)&object); 4022 ok_ole_success(hr, IGlobalInterfaceTable_GetInterfaceFromGlobal); 4023 IUnknown_Release(object); 4024 4025 /* test getting interface from global with same iid */ 4026 hr = IGlobalInterfaceTable_GetInterfaceFromGlobal(git, cookie, &IID_IClassFactory, (void **)&object); 4027 ok_ole_success(hr, IGlobalInterfaceTable_GetInterfaceFromGlobal); 4028 IUnknown_Release(object); 4029 4030 hr = IGlobalInterfaceTable_RevokeInterfaceFromGlobal(git, cookie); 4031 ok_ole_success(hr, IGlobalInterfaceTable_RevokeInterfaceFromGlobal); 4032 4033 ok_no_locks(); 4034 4035 IGlobalInterfaceTable_Release(git); 4036 } 4037 4038 static void test_manualresetevent(void) 4039 { 4040 ISynchronizeHandle *sync_handle; 4041 ISynchronize *psync1, *psync2; 4042 IUnknown *punk; 4043 HANDLE handle; 4044 LONG ref; 4045 HRESULT hr; 4046 4047 hr = CoCreateInstance(&CLSID_ManualResetEvent, NULL, CLSCTX_INPROC_SERVER, &IID_IUnknown, (void**)&punk); 4048 ok(hr == S_OK, "Got 0x%08x\n", hr); 4049 ok(!!punk, "Got NULL.\n"); 4050 IUnknown_Release(punk); 4051 4052 hr = CoCreateInstance(&CLSID_ManualResetEvent, NULL, CLSCTX_INPROC_SERVER, &IID_ISynchronize, (void**)&psync1); 4053 ok(hr == S_OK, "Got 0x%08x\n", hr); 4054 ok(!!psync1, "Got NULL.\n"); 4055 4056 hr = ISynchronize_Wait(psync1, 0, 5); 4057 ok(hr == RPC_S_CALLPENDING, "Got 0x%08x\n", hr); 4058 4059 hr = ISynchronize_Reset(psync1); 4060 ok(hr == S_OK, "Got 0x%08x\n", hr); 4061 hr = ISynchronize_Signal(psync1); 4062 ok(hr == S_OK, "Got 0x%08x\n", hr); 4063 hr = ISynchronize_Wait(psync1, 0, 5); 4064 ok(hr == S_OK, "Got 0x%08x\n", hr); 4065 hr = ISynchronize_Wait(psync1, 0, 5); 4066 ok(hr == S_OK, "Got 0x%08x\n", hr); 4067 hr = ISynchronize_Reset(psync1); 4068 ok(hr == S_OK, "Got 0x%08x\n", hr); 4069 hr = ISynchronize_Wait(psync1, 0, 5); 4070 ok(hr == RPC_S_CALLPENDING, "Got 0x%08x\n", hr); 4071 4072 hr = CoCreateInstance(&CLSID_ManualResetEvent, NULL, CLSCTX_INPROC_SERVER, &IID_ISynchronize, (void**)&psync2); 4073 ok(hr == S_OK, "Got 0x%08x\n", hr); 4074 ok(!!psync2, "Got NULL.\n"); 4075 ok(psync1 != psync2, "psync1 == psync2.\n"); 4076 4077 hr = ISynchronize_QueryInterface(psync2, &IID_ISynchronizeHandle, (void**)&sync_handle); 4078 ok(hr == S_OK, "QueryInterface(IID_ISynchronizeHandle) failed: %08x\n", hr); 4079 4080 handle = NULL; 4081 hr = ISynchronizeHandle_GetHandle(sync_handle, &handle); 4082 ok(hr == S_OK, "GetHandle failed: %08x\n", hr); 4083 ok(handle != NULL && handle != INVALID_HANDLE_VALUE, "handle = %p\n", handle); 4084 4085 ISynchronizeHandle_Release(sync_handle); 4086 4087 hr = ISynchronize_Wait(psync2, 0, 5); 4088 ok(hr == RPC_S_CALLPENDING, "Got 0x%08x\n", hr); 4089 4090 hr = ISynchronize_Reset(psync1); 4091 ok(hr == S_OK, "Got 0x%08x\n", hr); 4092 hr = ISynchronize_Reset(psync2); 4093 ok(hr == S_OK, "Got 0x%08x\n", hr); 4094 hr = ISynchronize_Signal(psync1); 4095 ok(hr == S_OK, "Got 0x%08x\n", hr); 4096 hr = ISynchronize_Wait(psync2, 0, 5); 4097 ok(hr == RPC_S_CALLPENDING, "Got 0x%08x\n", hr); 4098 4099 ref = ISynchronize_AddRef(psync1); 4100 ok(ref == 2, "Got ref: %d\n", ref); 4101 ref = ISynchronize_AddRef(psync1); 4102 ok(ref == 3, "Got ref: %d\n", ref); 4103 ref = ISynchronize_Release(psync1); 4104 ok(ref == 2, "Got nonzero ref: %d\n", ref); 4105 ref = ISynchronize_Release(psync2); 4106 ok(!ref, "Got nonzero ref: %d\n", ref); 4107 ref = ISynchronize_Release(psync1); 4108 ok(ref == 1, "Got nonzero ref: %d\n", ref); 4109 ref = ISynchronize_Release(psync1); 4110 ok(!ref, "Got nonzero ref: %d\n", ref); 4111 } 4112 4113 static DWORD CALLBACK implicit_mta_unmarshal_proc(void *param) 4114 { 4115 IStream *stream = param; 4116 IClassFactory *cf; 4117 IUnknown *proxy; 4118 HRESULT hr; 4119 4120 IStream_Seek(stream, ullZero, STREAM_SEEK_SET, NULL); 4121 hr = CoUnmarshalInterface(stream, &IID_IClassFactory, (void **)&cf); 4122 ok_ole_success(hr, CoUnmarshalInterface); 4123 4124 hr = IClassFactory_CreateInstance(cf, NULL, &IID_IUnknown, (void **)&proxy); 4125 ok_ole_success(hr, IClassFactory_CreateInstance); 4126 4127 IUnknown_Release(proxy); 4128 4129 /* But if we initialize an STA in this apartment, it becomes the wrong one. */ 4130 CoInitializeEx(NULL, COINIT_APARTMENTTHREADED); 4131 4132 hr = IClassFactory_CreateInstance(cf, NULL, &IID_IUnknown, (void **)&proxy); 4133 ok(hr == RPC_E_WRONG_THREAD, "got %#x\n", hr); 4134 4135 CoUninitialize(); 4136 4137 ok_more_than_one_lock(); 4138 ok_non_zero_external_conn(); 4139 4140 IClassFactory_Release(cf); 4141 4142 ok_no_locks(); 4143 ok_zero_external_conn(); 4144 ok_last_release_closes(TRUE); 4145 return 0; 4146 } 4147 4148 static DWORD CALLBACK implicit_mta_use_proc(void *param) 4149 { 4150 IClassFactory *cf = param; 4151 IUnknown *proxy; 4152 HRESULT hr; 4153 4154 hr = IClassFactory_CreateInstance(cf, NULL, &IID_IUnknown, (void **)&proxy); 4155 ok_ole_success(hr, IClassFactory_CreateInstance); 4156 4157 IUnknown_Release(proxy); 4158 4159 /* But if we initialize an STA in this apartment, it becomes the wrong one. */ 4160 CoInitializeEx(NULL, COINIT_APARTMENTTHREADED); 4161 4162 hr = IClassFactory_CreateInstance(cf, NULL, &IID_IUnknown, (void **)&proxy); 4163 ok(hr == RPC_E_WRONG_THREAD, "got %#x\n", hr); 4164 4165 CoUninitialize(); 4166 return 0; 4167 } 4168 4169 struct implicit_mta_marshal_data 4170 { 4171 IStream *stream; 4172 HANDLE start; 4173 HANDLE stop; 4174 }; 4175 4176 static DWORD CALLBACK implicit_mta_marshal_proc(void *param) 4177 { 4178 struct implicit_mta_marshal_data *data = param; 4179 HRESULT hr; 4180 4181 hr = CoMarshalInterface(data->stream, &IID_IClassFactory, 4182 (IUnknown *)&Test_ClassFactory, MSHCTX_INPROC, NULL, MSHLFLAGS_NORMAL); 4183 ok_ole_success(hr, CoMarshalInterface); 4184 4185 SetEvent(data->start); 4186 4187 ok(!WaitForSingleObject(data->stop, 1000), "wait failed\n"); 4188 return 0; 4189 } 4190 4191 static void test_implicit_mta(void) 4192 { 4193 struct implicit_mta_marshal_data data; 4194 HANDLE host_thread, thread; 4195 IClassFactory *cf; 4196 IUnknown *proxy; 4197 IStream *stream; 4198 HRESULT hr; 4199 DWORD tid; 4200 4201 cLocks = 0; 4202 external_connections = 0; 4203 4204 CoInitializeEx(NULL, COINIT_MULTITHREADED); 4205 4206 /* Firstly: we can unmarshal and use an object while in the implicit MTA. */ 4207 hr = CreateStreamOnHGlobal(NULL, TRUE, &stream); 4208 ok_ole_success(hr, CreateStreamOnHGlobal); 4209 tid = start_host_object(stream, &IID_IClassFactory, (IUnknown *)&Test_ClassFactory, MSHLFLAGS_NORMAL, &host_thread); 4210 4211 ok_more_than_one_lock(); 4212 ok_non_zero_external_conn(); 4213 4214 thread = CreateThread(NULL, 0, implicit_mta_unmarshal_proc, stream, 0, NULL); 4215 ok(!WaitForSingleObject(thread, 1000), "wait failed\n"); 4216 CloseHandle(thread); 4217 4218 IStream_Release(stream); 4219 end_host_object(tid, host_thread); 4220 4221 /* Secondly: we can unmarshal an object into the real MTA and then use it 4222 * from the implicit MTA. */ 4223 hr = CreateStreamOnHGlobal(NULL, TRUE, &stream); 4224 ok_ole_success(hr, CreateStreamOnHGlobal); 4225 tid = start_host_object(stream, &IID_IClassFactory, (IUnknown *)&Test_ClassFactory, MSHLFLAGS_NORMAL, &host_thread); 4226 4227 ok_more_than_one_lock(); 4228 ok_non_zero_external_conn(); 4229 4230 IStream_Seek(stream, ullZero, STREAM_SEEK_SET, NULL); 4231 hr = CoUnmarshalInterface(stream, &IID_IClassFactory, (void **)&cf); 4232 ok_ole_success(hr, CoUnmarshalInterface); 4233 4234 thread = CreateThread(NULL, 0, implicit_mta_use_proc, cf, 0, NULL); 4235 ok(!WaitForSingleObject(thread, 1000), "wait failed\n"); 4236 CloseHandle(thread); 4237 4238 IClassFactory_Release(cf); 4239 IStream_Release(stream); 4240 4241 ok_no_locks(); 4242 ok_non_zero_external_conn(); 4243 ok_last_release_closes(TRUE); 4244 4245 end_host_object(tid, host_thread); 4246 4247 /* Thirdly: we can marshal an object from the implicit MTA and then 4248 * unmarshal it into the real one. */ 4249 data.start = CreateEventA(NULL, FALSE, FALSE, NULL); 4250 data.stop = CreateEventA(NULL, FALSE, FALSE, NULL); 4251 4252 hr = CreateStreamOnHGlobal(NULL, TRUE, &data.stream); 4253 ok_ole_success(hr, CreateStreamOnHGlobal); 4254 4255 thread = CreateThread(NULL, 0, implicit_mta_marshal_proc, &data, 0, NULL); 4256 ok(!WaitForSingleObject(data.start, 1000), "wait failed\n"); 4257 4258 IStream_Seek(data.stream, ullZero, STREAM_SEEK_SET, NULL); 4259 hr = CoUnmarshalInterface(data.stream, &IID_IClassFactory, (void **)&cf); 4260 ok_ole_success(hr, CoUnmarshalInterface); 4261 4262 hr = IClassFactory_CreateInstance(cf, NULL, &IID_IUnknown, (void **)&proxy); 4263 ok_ole_success(hr, IClassFactory_CreateInstance); 4264 4265 IUnknown_Release(proxy); 4266 4267 SetEvent(data.stop); 4268 ok(!WaitForSingleObject(thread, 1000), "wait failed\n"); 4269 CloseHandle(thread); 4270 4271 IStream_Release(data.stream); 4272 4273 CoUninitialize(); 4274 } 4275 4276 static const char *debugstr_iid(REFIID riid) 4277 { 4278 static char name[256]; 4279 HKEY hkeyInterface; 4280 WCHAR bufferW[39]; 4281 char buffer[39]; 4282 LONG name_size = sizeof(name); 4283 StringFromGUID2(riid, bufferW, ARRAY_SIZE(bufferW)); 4284 WideCharToMultiByte(CP_ACP, 0, bufferW, ARRAY_SIZE(bufferW), buffer, sizeof(buffer), NULL, NULL); 4285 if (RegOpenKeyExA(HKEY_CLASSES_ROOT, "Interface", 0, KEY_QUERY_VALUE, &hkeyInterface) != ERROR_SUCCESS) 4286 { 4287 memcpy(name, buffer, sizeof(buffer)); 4288 goto done; 4289 } 4290 if (RegQueryValueA(hkeyInterface, buffer, name, &name_size) != ERROR_SUCCESS) 4291 { 4292 memcpy(name, buffer, sizeof(buffer)); 4293 goto done; 4294 } 4295 RegCloseKey(hkeyInterface); 4296 done: 4297 return name; 4298 } 4299 4300 static HRESULT WINAPI TestChannelHook_QueryInterface(IChannelHook *iface, REFIID riid, void **ppv) 4301 { 4302 if (IsEqualIID(riid, &IID_IUnknown) || IsEqualIID(riid, &IID_IChannelHook)) 4303 { 4304 *ppv = iface; 4305 IChannelHook_AddRef(iface); 4306 return S_OK; 4307 } 4308 4309 *ppv = NULL; 4310 return E_NOINTERFACE; 4311 } 4312 4313 static ULONG WINAPI TestChannelHook_AddRef(IChannelHook *iface) 4314 { 4315 return 2; 4316 } 4317 4318 static ULONG WINAPI TestChannelHook_Release(IChannelHook *iface) 4319 { 4320 return 1; 4321 } 4322 4323 static BOOL new_hook_struct; 4324 static int method, server_tid; 4325 static GUID causality; 4326 4327 struct new_hook_info 4328 { 4329 IID iid; 4330 GUID causality; 4331 DWORD server_pid; 4332 DWORD server_tid; 4333 WORD method; 4334 }; 4335 4336 static void WINAPI TestChannelHook_ClientGetSize( 4337 IChannelHook *iface, 4338 REFGUID uExtent, 4339 REFIID riid, 4340 ULONG *pDataSize ) 4341 { 4342 SChannelHookCallInfo *info = (SChannelHookCallInfo *)riid; 4343 trace("TestChannelHook_ClientGetSize\n"); 4344 trace("\t%s\n", debugstr_iid(riid)); 4345 if (info->cbSize != sizeof(*info)) 4346 new_hook_struct = TRUE; 4347 4348 if (!new_hook_struct) 4349 { 4350 ok(info->cbSize == sizeof(*info), "cbSize was %d instead of %d\n", info->cbSize, (int)sizeof(*info)); 4351 ok(info->dwServerPid == GetCurrentProcessId(), "dwServerPid was 0x%x instead of 0x%x\n", info->dwServerPid, GetCurrentProcessId()); 4352 ok(info->iMethod == method, "iMethod was %d should be %d\n", info->iMethod, method); 4353 ok(!info->pObject, "pObject should be NULL\n"); 4354 if (method == 3) 4355 causality = info->uCausality; 4356 else 4357 ok(IsEqualGUID(&info->uCausality, &causality), "causality wasn't correct\n"); 4358 } 4359 else 4360 { 4361 struct new_hook_info *new_info = (struct new_hook_info *)riid; 4362 ok(new_info->server_pid == GetCurrentProcessId(), "server pid was 0x%x instead of 0x%x\n", new_info->server_pid, 4363 GetCurrentProcessId()); 4364 ok(new_info->server_tid == server_tid, "server tid was 0x%x instead of 0x%x\n", new_info->server_tid, 4365 server_tid); 4366 ok(new_info->method == method, "method was %d instead of %d\n", new_info->method, method); 4367 if (method == 3) 4368 causality = new_info->causality; 4369 else 4370 ok(IsEqualGUID(&new_info->causality, &causality), "causality wasn't correct\n"); 4371 } 4372 4373 ok(IsEqualGUID(uExtent, &EXTENTID_WineTest), "uExtent wasn't correct\n"); 4374 4375 *pDataSize = 1; 4376 } 4377 4378 static void WINAPI TestChannelHook_ClientFillBuffer( 4379 IChannelHook *iface, 4380 REFGUID uExtent, 4381 REFIID riid, 4382 ULONG *pDataSize, 4383 void *pDataBuffer ) 4384 { 4385 SChannelHookCallInfo *info = (SChannelHookCallInfo *)riid; 4386 trace("TestChannelHook_ClientFillBuffer\n"); 4387 4388 if (!new_hook_struct) 4389 { 4390 ok(info->cbSize == sizeof(*info), "cbSize was %d instead of %d\n", info->cbSize, (int)sizeof(*info)); 4391 ok(info->dwServerPid == GetCurrentProcessId(), "dwServerPid was 0x%x instead of 0x%x\n", info->dwServerPid, GetCurrentProcessId()); 4392 ok(info->iMethod == method, "iMethod was %d should be %d\n", info->iMethod, method); 4393 ok(!info->pObject, "pObject should be NULL\n"); 4394 ok(IsEqualGUID(&info->uCausality, &causality), "causality wasn't correct\n"); 4395 } 4396 else 4397 { 4398 struct new_hook_info *new_info = (struct new_hook_info *)riid; 4399 ok(new_info->server_pid == GetCurrentProcessId(), "server pid was 0x%x instead of 0x%x\n", new_info->server_pid, 4400 GetCurrentProcessId()); 4401 ok(new_info->server_tid == server_tid, "server tid was 0x%x instead of 0x%x\n", new_info->server_tid, 4402 server_tid); 4403 ok(new_info->method == method, "method was %d instead of %d\n", new_info->method, method); 4404 ok(IsEqualGUID(&new_info->causality, &causality), "causality wasn't correct\n"); 4405 } 4406 4407 ok(IsEqualGUID(uExtent, &EXTENTID_WineTest), "uExtent wasn't correct\n"); 4408 4409 *(unsigned char *)pDataBuffer = 0xcc; 4410 *pDataSize = 1; 4411 } 4412 4413 static void WINAPI TestChannelHook_ClientNotify( 4414 IChannelHook *iface, 4415 REFGUID uExtent, 4416 REFIID riid, 4417 ULONG cbDataSize, 4418 void *pDataBuffer, 4419 DWORD lDataRep, 4420 HRESULT hrFault ) 4421 { 4422 SChannelHookCallInfo *info = (SChannelHookCallInfo *)riid; 4423 trace("TestChannelHook_ClientNotify hrFault = 0x%08x\n", hrFault); 4424 4425 if (!new_hook_struct) 4426 { 4427 ok(info->cbSize == sizeof(*info), "cbSize was %d instead of %d\n", info->cbSize, (int)sizeof(*info)); 4428 ok(info->dwServerPid == GetCurrentProcessId(), "dwServerPid was 0x%x instead of 0x%x\n", info->dwServerPid, GetCurrentProcessId()); 4429 ok(info->iMethod == method, "iMethod was %d should be %d\n", info->iMethod, method); 4430 todo_wine { 4431 ok(info->pObject != NULL, "pObject shouldn't be NULL\n"); 4432 } 4433 ok(IsEqualGUID(&info->uCausality, &causality), "causality wasn't correct\n"); 4434 } 4435 else 4436 { 4437 struct new_hook_info *new_info = (struct new_hook_info *)riid; 4438 ok(new_info->server_pid == GetCurrentProcessId(), "server pid was 0x%x instead of 0x%x\n", new_info->server_pid, 4439 GetCurrentProcessId()); 4440 ok(new_info->server_tid == server_tid, "server tid was 0x%x instead of 0x%x\n", new_info->server_tid, 4441 server_tid); 4442 ok(new_info->method == method, "method was %d instead of %d\n", new_info->method, method); 4443 ok(IsEqualGUID(&new_info->causality, &causality), "causality wasn't correct\n"); 4444 } 4445 4446 ok(IsEqualGUID(uExtent, &EXTENTID_WineTest), "uExtent wasn't correct\n"); 4447 } 4448 4449 static void WINAPI TestChannelHook_ServerNotify( 4450 IChannelHook *iface, 4451 REFGUID uExtent, 4452 REFIID riid, 4453 ULONG cbDataSize, 4454 void *pDataBuffer, 4455 DWORD lDataRep ) 4456 { 4457 SChannelHookCallInfo *info = (SChannelHookCallInfo *)riid; 4458 trace("TestChannelHook_ServerNotify\n"); 4459 4460 if (!new_hook_struct) 4461 { 4462 ok(info->cbSize == sizeof(*info), "cbSize was %d instead of %d\n", info->cbSize, (int)sizeof(*info)); 4463 ok(info->dwServerPid == GetCurrentProcessId(), "dwServerPid was 0x%x instead of 0x%x\n", info->dwServerPid, GetCurrentProcessId()); 4464 ok(info->iMethod == method, "iMethod was %d should be %d\n", info->iMethod, method); 4465 ok(info->pObject != NULL, "pObject shouldn't be NULL\n"); 4466 ok(IsEqualGUID(&info->uCausality, &causality), "causality wasn't correct\n"); 4467 } 4468 else 4469 { 4470 struct new_hook_info *new_info = (struct new_hook_info *)riid; 4471 ok(new_info->server_pid == GetCurrentProcessId(), "server pid was 0x%x instead of 0x%x\n", new_info->server_pid, 4472 GetCurrentProcessId()); 4473 ok(new_info->server_tid == server_tid, "server tid was 0x%x instead of 0x%x\n", new_info->server_tid, 4474 server_tid); 4475 ok(new_info->method == method, "method was %d instead of %d\n", new_info->method, method); 4476 ok(IsEqualGUID(&new_info->causality, &causality), "causality wasn't correct\n"); 4477 } 4478 4479 ok(cbDataSize == 1, "cbDataSize should have been 1 instead of %d\n", cbDataSize); 4480 ok(*(unsigned char *)pDataBuffer == 0xcc, "pDataBuffer should have contained 0xcc instead of 0x%x\n", *(unsigned char *)pDataBuffer); 4481 ok(IsEqualGUID(uExtent, &EXTENTID_WineTest), "uExtent wasn't correct\n"); 4482 } 4483 4484 static void WINAPI TestChannelHook_ServerGetSize( 4485 IChannelHook *iface, 4486 REFGUID uExtent, 4487 REFIID riid, 4488 HRESULT hrFault, 4489 ULONG *pDataSize ) 4490 { 4491 SChannelHookCallInfo *info = (SChannelHookCallInfo *)riid; 4492 trace("TestChannelHook_ServerGetSize\n"); 4493 trace("\t%s\n", debugstr_iid(riid)); 4494 if (!new_hook_struct) 4495 { 4496 ok(info->cbSize == sizeof(*info), "cbSize was %d instead of %d\n", info->cbSize, (int)sizeof(*info)); 4497 ok(info->dwServerPid == GetCurrentProcessId(), "dwServerPid was 0x%x instead of 0x%x\n", info->dwServerPid, GetCurrentProcessId()); 4498 ok(info->iMethod == method, "iMethod was %d should be %d\n", info->iMethod, method); 4499 ok(info->pObject != NULL, "pObject shouldn't be NULL\n"); 4500 ok(IsEqualGUID(&info->uCausality, &causality), "causality wasn't correct\n"); 4501 } 4502 else 4503 { 4504 struct new_hook_info *new_info = (struct new_hook_info *)riid; 4505 ok(new_info->server_pid == GetCurrentProcessId(), "server pid was 0x%x instead of 0x%x\n", new_info->server_pid, 4506 GetCurrentProcessId()); 4507 ok(new_info->server_tid == server_tid, "server tid was 0x%x instead of 0x%x\n", new_info->server_tid, 4508 server_tid); 4509 ok(new_info->method == method, "method was %d instead of %d\n", new_info->method, method); 4510 ok(IsEqualGUID(&new_info->causality, &causality), "causality wasn't correct\n"); 4511 } 4512 4513 ok(IsEqualGUID(uExtent, &EXTENTID_WineTest), "uExtent wasn't correct\n"); 4514 if (hrFault != S_OK) 4515 trace("\thrFault = 0x%08x\n", hrFault); 4516 4517 *pDataSize = 0; 4518 } 4519 4520 static void WINAPI TestChannelHook_ServerFillBuffer( 4521 IChannelHook *iface, 4522 REFGUID uExtent, 4523 REFIID riid, 4524 ULONG *pDataSize, 4525 void *pDataBuffer, 4526 HRESULT hrFault ) 4527 { 4528 trace("TestChannelHook_ServerFillBuffer\n"); 4529 ok(0, "TestChannelHook_ServerFillBuffer shouldn't be called\n"); 4530 } 4531 4532 static const IChannelHookVtbl TestChannelHookVtbl = 4533 { 4534 TestChannelHook_QueryInterface, 4535 TestChannelHook_AddRef, 4536 TestChannelHook_Release, 4537 TestChannelHook_ClientGetSize, 4538 TestChannelHook_ClientFillBuffer, 4539 TestChannelHook_ClientNotify, 4540 TestChannelHook_ServerNotify, 4541 TestChannelHook_ServerGetSize, 4542 TestChannelHook_ServerFillBuffer, 4543 }; 4544 4545 static IChannelHook TestChannelHook = { &TestChannelHookVtbl }; 4546 4547 static void test_channel_hook(void) 4548 { 4549 IClassFactory *cf = NULL; 4550 DWORD tid; 4551 IUnknown *proxy = NULL; 4552 HANDLE thread; 4553 HRESULT hr; 4554 4555 struct host_object_data object_data = { NULL, &IID_IClassFactory, (IUnknown*)&Test_ClassFactory, 4556 MSHLFLAGS_NORMAL, &MessageFilter }; 4557 4558 hr = CoRegisterChannelHook(&EXTENTID_WineTest, &TestChannelHook); 4559 ok_ole_success(hr, CoRegisterChannelHook); 4560 4561 hr = CoRegisterMessageFilter(&MessageFilter, NULL); 4562 ok_ole_success(hr, CoRegisterMessageFilter); 4563 4564 cLocks = 0; 4565 4566 hr = CreateStreamOnHGlobal(NULL, TRUE, &object_data.stream); 4567 ok_ole_success(hr, CreateStreamOnHGlobal); 4568 tid = start_host_object2(&object_data, &thread); 4569 server_tid = tid; 4570 4571 ok_more_than_one_lock(); 4572 4573 IStream_Seek(object_data.stream, ullZero, STREAM_SEEK_SET, NULL); 4574 hr = CoUnmarshalInterface(object_data.stream, &IID_IClassFactory, (void **)&cf); 4575 ok_ole_success(hr, CoUnmarshalInterface); 4576 IStream_Release(object_data.stream); 4577 4578 ok_more_than_one_lock(); 4579 4580 method = 3; 4581 hr = IClassFactory_CreateInstance(cf, NULL, &IID_IUnknown, (LPVOID*)&proxy); 4582 ok_ole_success(hr, IClassFactory_CreateInstance); 4583 4584 method = 5; 4585 IUnknown_Release(proxy); 4586 4587 IClassFactory_Release(cf); 4588 4589 ok_no_locks(); 4590 4591 end_host_object(tid, thread); 4592 4593 hr = CoRegisterMessageFilter(NULL, NULL); 4594 ok_ole_success(hr, CoRegisterMessageFilter); 4595 } 4596 4597 START_TEST(marshal) 4598 { 4599 HMODULE hOle32 = GetModuleHandleA("ole32"); 4600 int argc; 4601 char **argv; 4602 4603 if (!GetProcAddress(hOle32, "CoRegisterSurrogateEx")) { 4604 win_skip("skipping test on win9x\n"); 4605 return; 4606 } 4607 4608 pCoInitializeEx = (void*)GetProcAddress(hOle32, "CoInitializeEx"); 4609 pDllGetClassObject = (void*)GetProcAddress(hOle32, "DllGetClassObject"); 4610 4611 argc = winetest_get_mainargs( &argv ); 4612 if (argc > 2 && (!strcmp(argv[2], "-Embedding"))) 4613 { 4614 pCoInitializeEx(NULL, COINIT_MULTITHREADED); 4615 test_register_local_server(); 4616 CoUninitialize(); 4617 4618 return; 4619 } 4620 4621 register_test_window(); 4622 4623 test_cocreateinstance_proxy(); 4624 test_implicit_mta(); 4625 4626 pCoInitializeEx(NULL, COINIT_APARTMENTTHREADED); 4627 4628 /* FIXME: test CoCreateInstanceEx */ 4629 4630 /* lifecycle management and marshaling tests */ 4631 do 4632 { 4633 test_no_marshaler(); 4634 test_normal_marshal_and_release(); 4635 test_normal_marshal_and_unmarshal(); 4636 test_marshal_and_unmarshal_invalid(); 4637 test_same_apartment_unmarshal_failure(); 4638 test_interthread_marshal_and_unmarshal(); 4639 test_proxy_marshal_and_unmarshal(); 4640 test_proxy_marshal_and_unmarshal2(); 4641 test_proxy_marshal_and_unmarshal_weak(); 4642 test_proxy_marshal_and_unmarshal_strong(); 4643 test_marshal_stub_apartment_shutdown(); 4644 test_marshal_proxy_apartment_shutdown(); 4645 test_marshal_proxy_mta_apartment_shutdown(); 4646 test_no_couninitialize_server(); 4647 test_no_couninitialize_client(); 4648 test_tableweak_marshal_and_unmarshal_twice(); 4649 test_tableweak_marshal_releasedata1(); 4650 test_tableweak_marshal_releasedata2(); 4651 test_tableweak_and_normal_marshal_and_unmarshal(); 4652 test_tableweak_and_normal_marshal_and_releasedata(); 4653 test_two_tableweak_marshal_and_releasedata(); 4654 test_tablestrong_marshal_and_unmarshal_twice(); 4655 test_lock_object_external(); 4656 test_disconnect_stub(); 4657 test_normal_marshal_and_unmarshal_twice(); 4658 4659 with_external_conn = !with_external_conn; 4660 } while (with_external_conn); 4661 4662 test_marshal_channel_buffer(); 4663 test_StdMarshal_custom_marshaling(); 4664 test_DfMarshal_custom_marshaling(); 4665 test_CoGetStandardMarshal(); 4666 test_hresult_marshaling(); 4667 test_proxy_used_in_wrong_thread(); 4668 test_message_filter(); 4669 test_bad_marshal_stream(); 4670 test_proxy_interfaces(); 4671 test_stubbuffer(&IID_IClassFactory); 4672 test_proxybuffer(&IID_IClassFactory); 4673 test_message_reentrancy(); 4674 test_call_from_message(); 4675 test_WM_QUIT_handling(); 4676 test_freethreadedmarshaler(); 4677 test_inproc_handler(); 4678 test_handler_marshaling(); 4679 test_client_security(); 4680 4681 test_local_server(); 4682 4683 test_globalinterfacetable(); 4684 test_manualresetevent(); 4685 test_crash_couninitialize(); 4686 4687 /* must be last test as channel hooks can't be unregistered */ 4688 test_channel_hook(); 4689 4690 CoUninitialize(); 4691 } 4692