4 * Copyright 2004 Robert Shearman
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.
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.
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
36 #include "wine/test.h"
37 #include "wine/heap.h"
39 #define DEFINE_EXPECT(func) \
40 static BOOL expect_ ## func = FALSE, called_ ## func = FALSE
42 #define SET_EXPECT(func) \
43 expect_ ## func = TRUE
45 #define CHECK_EXPECT2(func) \
47 ok(expect_ ##func, "unexpected call " #func "\n"); \
48 called_ ## func = TRUE; \
51 #define CHECK_EXPECT(func) \
53 CHECK_EXPECT2(func); \
54 expect_ ## func = FALSE; \
57 #define CHECK_CALLED(func) \
59 ok(called_ ## func, "expected " #func "\n"); \
60 expect_ ## func = called_ ## func = FALSE; \
63 DEFINE_GUID(CLSID_StdGlobalInterfaceTable
,0x00000323,0x0000,0x0000,0xc0,0x00,0x00,0x00,0x00,0x00,0x00,0x46);
64 DEFINE_GUID(CLSID_ManualResetEvent
, 0x0000032c,0x0000,0x0000,0xc0,0x00,0x00,0x00,0x00,0x00,0x00,0x46);
66 static const GUID CLSID_WineTestPSFactoryBuffer
= { 0x22222222, 0x1234, 0x1234, { 0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0 } };
68 /* functions that are not present on all versions of Windows */
69 static HRESULT (WINAPI
* pCoInitializeEx
)(LPVOID lpReserved
, DWORD dwCoInit
);
70 static HRESULT (WINAPI
*pDllGetClassObject
)(REFCLSID
,REFIID
,LPVOID
);
72 /* helper macros to make tests a bit leaner */
73 #define ok_more_than_one_lock() ok(cLocks > 0, "Number of locks should be > 0, but actually is %d\n", cLocks)
74 #define ok_no_locks() ok(cLocks == 0, "Number of locks should be 0, but actually is %d\n", cLocks)
75 #define ok_ole_success(hr, func) ok(hr == S_OK, #func " failed with error 0x%08x\n", hr)
76 #define ok_non_zero_external_conn() do {if (with_external_conn) ok(external_connections, "got no external connections\n");} while(0);
77 #define ok_zero_external_conn() do {if (with_external_conn) ok(!external_connections, "got %d external connections\n", external_connections);} while(0);
78 #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);
80 static const IID IID_IWineTest
=
85 {0xa1, 0xa2, 0x5d, 0x5a, 0x36, 0x54, 0xd3, 0xbd}
86 }; /* 5201163f-8164-4fd0-a1a2-5d5a3654d3bd */
88 static const IID IID_IRemUnknown
=
93 {0xc0,0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46}
96 #define EXTENTID_WineTest IID_IWineTest
97 #define CLSID_WineTest IID_IWineTest
99 static const CLSID CLSID_WineOOPTest
=
104 {0xa1, 0xa2, 0x5d, 0x5a, 0x36, 0x54, 0xd3, 0xbd}
105 }; /* 5201163f-8164-4fd0-a1a2-5d5a3654d3bd */
107 static void test_cocreateinstance_proxy(void)
113 pCoInitializeEx(NULL
, COINIT_MULTITHREADED
);
115 hr
= CoCreateInstance(&CLSID_ShellDesktop
, NULL
, CLSCTX_INPROC
, &IID_IUnknown
, (void **)&pProxy
);
116 ok_ole_success(hr
, CoCreateInstance
);
117 hr
= IUnknown_QueryInterface(pProxy
, &IID_IMultiQI
, (void **)&pMQI
);
118 ok(hr
== S_OK
, "created object is not a proxy, so was created in the wrong apartment\n");
120 IMultiQI_Release(pMQI
);
121 IUnknown_Release(pProxy
);
126 static const LARGE_INTEGER ullZero
;
129 static void LockModule(void)
131 InterlockedIncrement(&cLocks
);
134 static void UnlockModule(void)
136 InterlockedDecrement(&cLocks
);
139 static BOOL with_external_conn
;
140 static DWORD external_connections
;
141 static BOOL last_release_closes
;
143 static HRESULT WINAPI
ExternalConnection_QueryInterface(IExternalConnection
*iface
, REFIID riid
, void **ppv
)
145 ok(0, "unexpected call\n");
147 return E_NOINTERFACE
;
150 static ULONG WINAPI
ExternalConnection_AddRef(IExternalConnection
*iface
)
155 static ULONG WINAPI
ExternalConnection_Release(IExternalConnection
*iface
)
160 static DWORD WINAPI
ExternalConnection_AddConnection(IExternalConnection
*iface
, DWORD extconn
, DWORD reserved
)
162 trace("add connection\n");
163 return ++external_connections
;
167 static DWORD WINAPI
ExternalConnection_ReleaseConnection(IExternalConnection
*iface
, DWORD extconn
,
168 DWORD reserved
, BOOL fLastReleaseCloses
)
170 trace("release connection %d\n", fLastReleaseCloses
);
171 last_release_closes
= fLastReleaseCloses
;
172 return --external_connections
;
175 static const IExternalConnectionVtbl ExternalConnectionVtbl
= {
176 ExternalConnection_QueryInterface
,
177 ExternalConnection_AddRef
,
178 ExternalConnection_Release
,
179 ExternalConnection_AddConnection
,
180 ExternalConnection_ReleaseConnection
183 static IExternalConnection ExternalConnection
= { &ExternalConnectionVtbl
};
186 static HRESULT WINAPI
Test_IUnknown_QueryInterface(
191 if (ppvObj
== NULL
) return E_POINTER
;
193 if (IsEqualGUID(riid
, &IID_IUnknown
))
196 IUnknown_AddRef(iface
);
201 return E_NOINTERFACE
;
204 static ULONG WINAPI
Test_IUnknown_AddRef(LPUNKNOWN iface
)
207 return 2; /* non-heap-based object */
210 static ULONG WINAPI
Test_IUnknown_Release(LPUNKNOWN iface
)
213 return 1; /* non-heap-based object */
216 static const IUnknownVtbl TestUnknown_Vtbl
=
218 Test_IUnknown_QueryInterface
,
219 Test_IUnknown_AddRef
,
220 Test_IUnknown_Release
,
223 static IUnknown Test_Unknown
= { &TestUnknown_Vtbl
};
225 static ULONG WINAPI
TestCrash_IUnknown_Release(LPUNKNOWN iface
)
229 trace("crashing...\n");
232 return 1; /* non-heap-based object */
235 static const IUnknownVtbl TestCrashUnknown_Vtbl
=
237 Test_IUnknown_QueryInterface
,
238 Test_IUnknown_AddRef
,
239 TestCrash_IUnknown_Release
,
242 static IUnknown TestCrash_Unknown
= { &TestCrashUnknown_Vtbl
};
244 static HRESULT WINAPI
Test_IClassFactory_QueryInterface(
245 LPCLASSFACTORY iface
,
249 if (ppvObj
== NULL
) return E_POINTER
;
251 if (IsEqualGUID(riid
, &IID_IUnknown
) ||
252 IsEqualGUID(riid
, &IID_IClassFactory
) ||
253 /* the only other interface Wine is currently able to marshal (for testing two proxies) */
254 IsEqualGUID(riid
, &IID_IRemUnknown
))
257 IClassFactory_AddRef(iface
);
261 if (with_external_conn
&& IsEqualGUID(riid
, &IID_IExternalConnection
))
263 *ppvObj
= &ExternalConnection
;
268 return E_NOINTERFACE
;
271 static ULONG WINAPI
Test_IClassFactory_AddRef(LPCLASSFACTORY iface
)
274 return 2; /* non-heap-based object */
277 static ULONG WINAPI
Test_IClassFactory_Release(LPCLASSFACTORY iface
)
280 return 1; /* non-heap-based object */
283 static HRESULT WINAPI
Test_IClassFactory_CreateInstance(
284 LPCLASSFACTORY iface
,
289 if (pUnkOuter
) return CLASS_E_NOAGGREGATION
;
290 return IUnknown_QueryInterface((IUnknown
*)&Test_Unknown
, riid
, ppvObj
);
293 static HRESULT WINAPI
Test_IClassFactory_LockServer(
294 LPCLASSFACTORY iface
,
300 static const IClassFactoryVtbl TestClassFactory_Vtbl
=
302 Test_IClassFactory_QueryInterface
,
303 Test_IClassFactory_AddRef
,
304 Test_IClassFactory_Release
,
305 Test_IClassFactory_CreateInstance
,
306 Test_IClassFactory_LockServer
309 static IClassFactory Test_ClassFactory
= { &TestClassFactory_Vtbl
};
311 DEFINE_EXPECT(Invoke
);
312 DEFINE_EXPECT(CreateStub
);
313 DEFINE_EXPECT(CreateProxy
);
314 DEFINE_EXPECT(GetWindow
);
315 DEFINE_EXPECT(Disconnect
);
317 static HRESULT WINAPI
OleWindow_QueryInterface(IOleWindow
*iface
, REFIID riid
, void **ppv
)
319 ok(0, "unexpected call %s\n", wine_dbgstr_guid(riid
));
321 return E_NOINTERFACE
;
324 static ULONG WINAPI
OleWindow_AddRef(IOleWindow
*iface
)
329 static ULONG WINAPI
OleWindow_Release(IOleWindow
*iface
)
334 static HRESULT WINAPI
OleWindow_GetWindow(IOleWindow
*iface
, HWND
*hwnd
)
336 CHECK_EXPECT(GetWindow
);
337 *hwnd
= (HWND
)0xdeadbeef;
341 static const IOleWindowVtbl OleWindowVtbl
= {
342 OleWindow_QueryInterface
,
349 static IOleWindow Test_OleWindow
= { &OleWindowVtbl
};
351 static HRESULT WINAPI
OleClientSite_QueryInterface(IOleClientSite
*iface
, REFIID riid
, void **ppv
)
353 if (IsEqualGUID(riid
, &IID_IUnknown
) || IsEqualGUID(riid
, &IID_IOleClientSite
))
355 else if (IsEqualGUID(riid
, &IID_IOleWindow
))
356 *ppv
= &Test_OleWindow
;
360 return E_NOINTERFACE
;
363 IUnknown_AddRef((IUnknown
*)*ppv
);
367 static ULONG WINAPI
OleClientSite_AddRef(IOleClientSite
*iface
)
372 static ULONG WINAPI
OleClientSite_Release(IOleClientSite
*iface
)
377 static const IOleClientSiteVtbl OleClientSiteVtbl
= {
378 OleClientSite_QueryInterface
,
379 OleClientSite_AddRef
,
380 OleClientSite_Release
,
381 /* we don't need the rest, we never call it */
384 static IOleClientSite Test_OleClientSite
= { &OleClientSiteVtbl
};
387 IRpcStubBuffer IRpcStubBuffer_iface
;
389 IRpcStubBuffer
*buffer
;
392 static StubBufferWrapper
*impl_from_IRpcStubBuffer(IRpcStubBuffer
*iface
)
394 return CONTAINING_RECORD(iface
, StubBufferWrapper
, IRpcStubBuffer_iface
);
397 static HRESULT WINAPI
RpcStubBuffer_QueryInterface(IRpcStubBuffer
*iface
, REFIID riid
, void **ppv
)
399 StubBufferWrapper
*This
= impl_from_IRpcStubBuffer(iface
);
401 if(IsEqualGUID(&IID_IUnknown
, riid
) || IsEqualGUID(&IID_IRpcStubBuffer
, riid
)) {
402 *ppv
= &This
->IRpcStubBuffer_iface
;
405 return E_NOINTERFACE
;
408 IUnknown_AddRef((IUnknown
*)*ppv
);
412 static ULONG WINAPI
RpcStubBuffer_AddRef(IRpcStubBuffer
*iface
)
414 StubBufferWrapper
*This
= impl_from_IRpcStubBuffer(iface
);
415 return InterlockedIncrement(&This
->ref
);
418 static ULONG WINAPI
RpcStubBuffer_Release(IRpcStubBuffer
*iface
)
420 StubBufferWrapper
*This
= impl_from_IRpcStubBuffer(iface
);
421 LONG ref
= InterlockedDecrement(&This
->ref
);
423 IRpcStubBuffer_Release(This
->buffer
);
429 static HRESULT WINAPI
RpcStubBuffer_Connect(IRpcStubBuffer
*iface
, IUnknown
*pUnkServer
)
431 ok(0, "unexpected call\n");
435 static void WINAPI
RpcStubBuffer_Disconnect(IRpcStubBuffer
*iface
)
437 CHECK_EXPECT(Disconnect
);
440 static HRESULT WINAPI
RpcStubBuffer_Invoke(IRpcStubBuffer
*iface
, RPCOLEMESSAGE
*_prpcmsg
,
441 IRpcChannelBuffer
*_pRpcChannelBuffer
)
443 StubBufferWrapper
*This
= impl_from_IRpcStubBuffer(iface
);
444 void *dest_context_data
;
448 CHECK_EXPECT(Invoke
);
450 hr
= IRpcChannelBuffer_GetDestCtx(_pRpcChannelBuffer
, &dest_context
, &dest_context_data
);
451 ok(hr
== S_OK
, "GetDestCtx failed: %08x\n", hr
);
452 ok(dest_context
== MSHCTX_INPROC
, "desc_context = %x\n", dest_context
);
453 ok(!dest_context_data
, "desc_context_data = %p\n", dest_context_data
);
455 return IRpcStubBuffer_Invoke(This
->buffer
, _prpcmsg
, _pRpcChannelBuffer
);
458 static IRpcStubBuffer
*WINAPI
RpcStubBuffer_IsIIDSupported(IRpcStubBuffer
*iface
, REFIID riid
)
460 ok(0, "unexpected call\n");
464 static ULONG WINAPI
RpcStubBuffer_CountRefs(IRpcStubBuffer
*iface
)
466 ok(0, "unexpected call\n");
470 static HRESULT WINAPI
RpcStubBuffer_DebugServerQueryInterface(IRpcStubBuffer
*iface
, void **ppv
)
472 ok(0, "unexpected call\n");
476 static void WINAPI
RpcStubBuffer_DebugServerRelease(IRpcStubBuffer
*iface
, void *pv
)
478 ok(0, "unexpected call\n");
481 static const IRpcStubBufferVtbl RpcStubBufferVtbl
= {
482 RpcStubBuffer_QueryInterface
,
483 RpcStubBuffer_AddRef
,
484 RpcStubBuffer_Release
,
485 RpcStubBuffer_Connect
,
486 RpcStubBuffer_Disconnect
,
487 RpcStubBuffer_Invoke
,
488 RpcStubBuffer_IsIIDSupported
,
489 RpcStubBuffer_CountRefs
,
490 RpcStubBuffer_DebugServerQueryInterface
,
491 RpcStubBuffer_DebugServerRelease
494 static IPSFactoryBuffer
*ps_factory_buffer
;
496 static HRESULT WINAPI
PSFactoryBuffer_QueryInterface(IPSFactoryBuffer
*iface
, REFIID riid
, void **ppv
)
498 if (IsEqualIID(riid
, &IID_IUnknown
) || IsEqualIID(riid
, &IID_IPSFactoryBuffer
))
503 return E_NOINTERFACE
;
505 IUnknown_AddRef((IUnknown
*)*ppv
);
509 static ULONG WINAPI
PSFactoryBuffer_AddRef(IPSFactoryBuffer
*iface
)
514 static ULONG WINAPI
PSFactoryBuffer_Release(IPSFactoryBuffer
*iface
)
519 static HRESULT WINAPI
PSFactoryBuffer_CreateProxy(IPSFactoryBuffer
*iface
, IUnknown
*outer
,
520 REFIID riid
, IRpcProxyBuffer
**ppProxy
, void **ppv
)
522 CHECK_EXPECT(CreateProxy
);
523 return IPSFactoryBuffer_CreateProxy(ps_factory_buffer
, outer
, riid
, ppProxy
, ppv
);
526 static HRESULT WINAPI
PSFactoryBuffer_CreateStub(IPSFactoryBuffer
*iface
, REFIID riid
,
527 IUnknown
*server
, IRpcStubBuffer
**ppStub
)
529 StubBufferWrapper
*stub
;
532 CHECK_EXPECT(CreateStub
);
534 ok(server
== (IUnknown
*)&Test_OleClientSite
, "unexpected server %p\n", server
);
536 stub
= heap_alloc(sizeof(*stub
));
537 stub
->IRpcStubBuffer_iface
.lpVtbl
= &RpcStubBufferVtbl
;
540 hr
= IPSFactoryBuffer_CreateStub(ps_factory_buffer
, riid
, server
, &stub
->buffer
);
541 ok(hr
== S_OK
, "CreateStub failed: %08x\n", hr
);
543 *ppStub
= &stub
->IRpcStubBuffer_iface
;
547 static IPSFactoryBufferVtbl PSFactoryBufferVtbl
=
549 PSFactoryBuffer_QueryInterface
,
550 PSFactoryBuffer_AddRef
,
551 PSFactoryBuffer_Release
,
552 PSFactoryBuffer_CreateProxy
,
553 PSFactoryBuffer_CreateStub
556 static IPSFactoryBuffer PSFactoryBuffer
= { &PSFactoryBufferVtbl
};
558 #define RELEASEMARSHALDATA WM_USER
560 struct host_object_data
565 MSHLFLAGS marshal_flags
;
566 IMessageFilter
*filter
;
567 IUnknown
*register_object
;
568 const CLSID
*register_clsid
;
569 HANDLE marshal_event
;
572 static IPSFactoryBuffer PSFactoryBuffer
;
574 static DWORD CALLBACK
host_object_proc(LPVOID p
)
576 struct host_object_data
*data
= p
;
577 DWORD registration_key
;
581 pCoInitializeEx(NULL
, COINIT_APARTMENTTHREADED
);
583 if(data
->register_object
) {
584 hr
= CoRegisterClassObject(data
->register_clsid
, data
->register_object
,
585 CLSCTX_INPROC_SERVER
, REGCLS_MULTIPLEUSE
, ®istration_key
);
586 ok(hr
== S_OK
, "CoRegisterClassObject failed: %08x\n", hr
);
591 IMessageFilter
* prev_filter
= NULL
;
592 hr
= CoRegisterMessageFilter(data
->filter
, &prev_filter
);
593 if (prev_filter
) IMessageFilter_Release(prev_filter
);
594 ok_ole_success(hr
, CoRegisterMessageFilter
);
597 hr
= CoMarshalInterface(data
->stream
, data
->iid
, data
->object
, MSHCTX_INPROC
, NULL
, data
->marshal_flags
);
598 ok_ole_success(hr
, CoMarshalInterface
);
600 /* force the message queue to be created before signaling parent thread */
601 PeekMessageA(&msg
, NULL
, WM_USER
, WM_USER
, PM_NOREMOVE
);
603 SetEvent(data
->marshal_event
);
605 while (GetMessageA(&msg
, NULL
, 0, 0))
607 if (msg
.hwnd
== NULL
&& msg
.message
== RELEASEMARSHALDATA
)
609 CoReleaseMarshalData(data
->stream
);
610 SetEvent((HANDLE
)msg
.lParam
);
613 DispatchMessageA(&msg
);
616 HeapFree(GetProcessHeap(), 0, data
);
623 static DWORD
start_host_object2(struct host_object_data
*object_data
, HANDLE
*thread
)
626 struct host_object_data
*data
;
628 data
= HeapAlloc(GetProcessHeap(), 0, sizeof(*data
));
629 *data
= *object_data
;
630 data
->marshal_event
= CreateEventA(NULL
, FALSE
, FALSE
, NULL
);
631 *thread
= CreateThread(NULL
, 0, host_object_proc
, data
, 0, &tid
);
633 /* wait for marshaling to complete before returning */
634 ok( !WaitForSingleObject(data
->marshal_event
, 10000), "wait timed out\n" );
635 CloseHandle(data
->marshal_event
);
640 static DWORD
start_host_object(IStream
*stream
, REFIID riid
, IUnknown
*object
, MSHLFLAGS marshal_flags
, HANDLE
*thread
)
642 struct host_object_data object_data
= { stream
, riid
, object
, marshal_flags
};
643 return start_host_object2(&object_data
, thread
);
646 /* asks thread to release the marshal data because it has to be done by the
647 * same thread that marshaled the interface in the first place. */
648 static void release_host_object(DWORD tid
, WPARAM wp
)
650 HANDLE event
= CreateEventA(NULL
, FALSE
, FALSE
, NULL
);
651 PostThreadMessageA(tid
, RELEASEMARSHALDATA
, wp
, (LPARAM
)event
);
652 ok( !WaitForSingleObject(event
, 10000), "wait timed out\n" );
656 static void end_host_object(DWORD tid
, HANDLE thread
)
658 BOOL ret
= PostThreadMessageA(tid
, WM_QUIT
, 0, 0);
659 ok(ret
, "PostThreadMessage failed with error %d\n", GetLastError());
660 /* be careful of races - don't return until hosting thread has terminated */
661 ok( !WaitForSingleObject(thread
, 10000), "wait timed out\n" );
665 /* tests failure case of interface not having a marshaler specified in the
667 static void test_no_marshaler(void)
672 hr
= CreateStreamOnHGlobal(NULL
, TRUE
, &pStream
);
673 ok_ole_success(hr
, CreateStreamOnHGlobal
);
674 hr
= CoMarshalInterface(pStream
, &IID_IWineTest
, (IUnknown
*)&Test_ClassFactory
, MSHCTX_INPROC
, NULL
, MSHLFLAGS_NORMAL
);
675 ok(hr
== E_NOINTERFACE
, "CoMarshalInterface should have returned E_NOINTERFACE instead of 0x%08x\n", hr
);
677 IStream_Release(pStream
);
680 /* tests normal marshal and then release without unmarshaling */
681 static void test_normal_marshal_and_release(void)
684 IStream
*pStream
= NULL
;
687 external_connections
= 0;
689 hr
= CreateStreamOnHGlobal(NULL
, TRUE
, &pStream
);
690 ok_ole_success(hr
, CreateStreamOnHGlobal
);
691 hr
= CoMarshalInterface(pStream
, &IID_IClassFactory
, (IUnknown
*)&Test_ClassFactory
, MSHCTX_INPROC
, NULL
, MSHLFLAGS_NORMAL
);
692 ok_ole_success(hr
, CoMarshalInterface
);
694 ok_more_than_one_lock();
695 ok_non_zero_external_conn();
697 IStream_Seek(pStream
, ullZero
, STREAM_SEEK_SET
, NULL
);
698 hr
= CoReleaseMarshalData(pStream
);
699 ok_ole_success(hr
, CoReleaseMarshalData
);
700 IStream_Release(pStream
);
703 ok_zero_external_conn();
704 ok_last_release_closes(TRUE
);
707 /* tests success case of a same-thread marshal and unmarshal */
708 static void test_normal_marshal_and_unmarshal(void)
711 IStream
*pStream
= NULL
;
712 IUnknown
*pProxy
= NULL
;
715 external_connections
= 0;
717 hr
= CreateStreamOnHGlobal(NULL
, TRUE
, &pStream
);
718 ok_ole_success(hr
, CreateStreamOnHGlobal
);
719 hr
= CoMarshalInterface(pStream
, &IID_IClassFactory
, (IUnknown
*)&Test_ClassFactory
, MSHCTX_INPROC
, NULL
, MSHLFLAGS_NORMAL
);
720 ok_ole_success(hr
, CoMarshalInterface
);
722 ok_more_than_one_lock();
723 ok_non_zero_external_conn();
725 IStream_Seek(pStream
, ullZero
, STREAM_SEEK_SET
, NULL
);
726 hr
= CoUnmarshalInterface(pStream
, &IID_IClassFactory
, (void **)&pProxy
);
727 ok_ole_success(hr
, CoUnmarshalInterface
);
728 IStream_Release(pStream
);
730 ok_more_than_one_lock();
731 ok_zero_external_conn();
732 ok_last_release_closes(FALSE
);
734 IUnknown_Release(pProxy
);
739 /* tests failure case of unmarshaling a freed object */
740 static void test_marshal_and_unmarshal_invalid(void)
743 IStream
*pStream
= NULL
;
744 IClassFactory
*pProxy
= NULL
;
750 external_connections
= 0;
752 hr
= CreateStreamOnHGlobal(NULL
, TRUE
, &pStream
);
753 ok_ole_success(hr
, CreateStreamOnHGlobal
);
754 tid
= start_host_object(pStream
, &IID_IClassFactory
, (IUnknown
*)&Test_ClassFactory
, MSHLFLAGS_NORMAL
, &thread
);
756 ok_more_than_one_lock();
757 ok_non_zero_external_conn();
759 IStream_Seek(pStream
, ullZero
, STREAM_SEEK_SET
, NULL
);
760 hr
= CoReleaseMarshalData(pStream
);
761 ok_ole_success(hr
, CoReleaseMarshalData
);
764 ok_zero_external_conn();
765 ok_last_release_closes(TRUE
);
767 IStream_Seek(pStream
, ullZero
, STREAM_SEEK_SET
, NULL
);
768 hr
= CoUnmarshalInterface(pStream
, &IID_IClassFactory
, (void **)&pProxy
);
769 todo_wine
{ ok_ole_success(hr
, CoUnmarshalInterface
); }
775 hr
= IClassFactory_CreateInstance(pProxy
, NULL
, &IID_IUnknown
, &dummy
);
776 ok(hr
== RPC_E_DISCONNECTED
, "Remote call should have returned RPC_E_DISCONNECTED, instead of 0x%08x\n", hr
);
778 IClassFactory_Release(pProxy
);
781 IStream_Release(pStream
);
783 end_host_object(tid
, thread
);
786 static void test_same_apartment_unmarshal_failure(void)
791 static const LARGE_INTEGER llZero
;
794 external_connections
= 0;
796 hr
= CreateStreamOnHGlobal(NULL
, TRUE
, &pStream
);
797 ok_ole_success(hr
, CreateStreamOnHGlobal
);
799 hr
= CoMarshalInterface(pStream
, &IID_IUnknown
, (IUnknown
*)&Test_ClassFactory
, MSHCTX_INPROC
, NULL
, MSHLFLAGS_NORMAL
);
800 ok_ole_success(hr
, CoMarshalInterface
);
802 ok_more_than_one_lock();
803 ok_non_zero_external_conn();
805 hr
= IStream_Seek(pStream
, llZero
, STREAM_SEEK_SET
, NULL
);
806 ok_ole_success(hr
, IStream_Seek
);
808 hr
= CoUnmarshalInterface(pStream
, &IID_IParseDisplayName
, (void **)&pProxy
);
809 ok(hr
== E_NOINTERFACE
, "CoUnmarshalInterface should have returned E_NOINTERFACE instead of 0x%08x\n", hr
);
812 ok_zero_external_conn();
813 ok_last_release_closes(FALSE
);
815 IStream_Release(pStream
);
818 /* tests success case of an interthread marshal */
819 static void test_interthread_marshal_and_unmarshal(void)
822 IStream
*pStream
= NULL
;
823 IUnknown
*pProxy
= NULL
;
828 external_connections
= 0;
830 hr
= CreateStreamOnHGlobal(NULL
, TRUE
, &pStream
);
831 ok_ole_success(hr
, CreateStreamOnHGlobal
);
832 tid
= start_host_object(pStream
, &IID_IClassFactory
, (IUnknown
*)&Test_ClassFactory
, MSHLFLAGS_NORMAL
, &thread
);
834 ok_more_than_one_lock();
835 ok_non_zero_external_conn();
837 IStream_Seek(pStream
, ullZero
, STREAM_SEEK_SET
, NULL
);
838 hr
= CoUnmarshalInterface(pStream
, &IID_IClassFactory
, (void **)&pProxy
);
839 ok_ole_success(hr
, CoUnmarshalInterface
);
840 IStream_Release(pStream
);
842 ok_more_than_one_lock();
843 ok_non_zero_external_conn();
845 IUnknown_Release(pProxy
);
848 ok_zero_external_conn();
849 ok_last_release_closes(TRUE
);
851 end_host_object(tid
, thread
);
854 /* the number of external references that Wine's proxy manager normally gives
855 * out, so we can test the border case of running out of references */
856 #define NORMALEXTREFS 5
858 /* tests success case of an interthread marshal and then marshaling the proxy */
859 static void test_proxy_marshal_and_unmarshal(void)
862 IStream
*pStream
= NULL
;
863 IUnknown
*pProxy
= NULL
;
864 IUnknown
*pProxy2
= NULL
;
870 external_connections
= 0;
872 hr
= CreateStreamOnHGlobal(NULL
, TRUE
, &pStream
);
873 ok_ole_success(hr
, CreateStreamOnHGlobal
);
874 tid
= start_host_object(pStream
, &IID_IClassFactory
, (IUnknown
*)&Test_ClassFactory
, MSHLFLAGS_NORMAL
, &thread
);
876 ok_more_than_one_lock();
877 ok_non_zero_external_conn();
879 IStream_Seek(pStream
, ullZero
, STREAM_SEEK_SET
, NULL
);
880 hr
= CoUnmarshalInterface(pStream
, &IID_IClassFactory
, (void **)&pProxy
);
881 ok_ole_success(hr
, CoUnmarshalInterface
);
883 ok_more_than_one_lock();
885 IStream_Seek(pStream
, ullZero
, STREAM_SEEK_SET
, NULL
);
886 /* marshal the proxy */
887 hr
= CoMarshalInterface(pStream
, &IID_IClassFactory
, pProxy
, MSHCTX_INPROC
, NULL
, MSHLFLAGS_NORMAL
);
888 ok_ole_success(hr
, CoMarshalInterface
);
890 ok_more_than_one_lock();
892 /* marshal 5 more times to exhaust the normal external references of 5 */
893 for (i
= 0; i
< NORMALEXTREFS
; i
++)
895 hr
= CoMarshalInterface(pStream
, &IID_IClassFactory
, pProxy
, MSHCTX_INPROC
, NULL
, MSHLFLAGS_NORMAL
);
896 ok_ole_success(hr
, CoMarshalInterface
);
899 ok_more_than_one_lock();
901 /* release the original proxy to test that we successfully keep the
902 * original object alive */
903 IUnknown_Release(pProxy
);
905 IStream_Seek(pStream
, ullZero
, STREAM_SEEK_SET
, NULL
);
906 hr
= CoUnmarshalInterface(pStream
, &IID_IClassFactory
, (void **)&pProxy2
);
907 ok_ole_success(hr
, CoUnmarshalInterface
);
909 ok_more_than_one_lock();
910 ok_non_zero_external_conn();
912 IUnknown_Release(pProxy2
);
914 /* unmarshal all of the proxies to check that the object stub still exists */
915 for (i
= 0; i
< NORMALEXTREFS
; i
++)
917 hr
= CoUnmarshalInterface(pStream
, &IID_IClassFactory
, (void **)&pProxy2
);
918 ok_ole_success(hr
, CoUnmarshalInterface
);
920 IUnknown_Release(pProxy2
);
924 ok_zero_external_conn();
925 ok_last_release_closes(TRUE
);
927 IStream_Release(pStream
);
929 end_host_object(tid
, thread
);
932 /* tests success case of an interthread marshal and then marshaling the proxy
933 * using an iid that hasn't previously been unmarshaled */
934 static void test_proxy_marshal_and_unmarshal2(void)
937 IStream
*pStream
= NULL
;
938 IUnknown
*pProxy
= NULL
;
939 IUnknown
*pProxy2
= NULL
;
944 external_connections
= 0;
946 hr
= CreateStreamOnHGlobal(NULL
, TRUE
, &pStream
);
947 ok_ole_success(hr
, CreateStreamOnHGlobal
);
948 tid
= start_host_object(pStream
, &IID_IUnknown
, (IUnknown
*)&Test_ClassFactory
, MSHLFLAGS_NORMAL
, &thread
);
950 ok_more_than_one_lock();
951 ok_non_zero_external_conn();
953 IStream_Seek(pStream
, ullZero
, STREAM_SEEK_SET
, NULL
);
954 hr
= CoUnmarshalInterface(pStream
, &IID_IUnknown
, (void **)&pProxy
);
955 ok_ole_success(hr
, CoUnmarshalInterface
);
957 ok_more_than_one_lock();
959 IStream_Seek(pStream
, ullZero
, STREAM_SEEK_SET
, NULL
);
960 /* marshal the proxy */
961 hr
= CoMarshalInterface(pStream
, &IID_IClassFactory
, pProxy
, MSHCTX_INPROC
, NULL
, MSHLFLAGS_NORMAL
);
962 ok_ole_success(hr
, CoMarshalInterface
);
964 ok_more_than_one_lock();
966 IStream_Seek(pStream
, ullZero
, STREAM_SEEK_SET
, NULL
);
967 /* unmarshal the second proxy to the object */
968 hr
= CoUnmarshalInterface(pStream
, &IID_IClassFactory
, (void **)&pProxy2
);
969 ok_ole_success(hr
, CoUnmarshalInterface
);
970 IStream_Release(pStream
);
972 /* now the proxies should be as follows:
973 * pProxy -> &Test_ClassFactory
974 * pProxy2 -> &Test_ClassFactory
975 * they should NOT be as follows:
976 * pProxy -> &Test_ClassFactory
978 * the above can only really be tested by looking in +ole traces
981 ok_more_than_one_lock();
983 IUnknown_Release(pProxy
);
985 ok_more_than_one_lock();
986 ok_non_zero_external_conn();
988 IUnknown_Release(pProxy2
);
991 ok_zero_external_conn();
992 ok_last_release_closes(TRUE
);
994 end_host_object(tid
, thread
);
997 /* tests success case of an interthread marshal and then table-weak-marshaling the proxy */
998 static void test_proxy_marshal_and_unmarshal_weak(void)
1001 IStream
*pStream
= NULL
;
1002 IUnknown
*pProxy
= NULL
;
1003 IUnknown
*pProxy2
= NULL
;
1008 external_connections
= 0;
1010 hr
= CreateStreamOnHGlobal(NULL
, TRUE
, &pStream
);
1011 ok_ole_success(hr
, CreateStreamOnHGlobal
);
1012 tid
= start_host_object(pStream
, &IID_IClassFactory
, (IUnknown
*)&Test_ClassFactory
, MSHLFLAGS_NORMAL
, &thread
);
1014 ok_more_than_one_lock();
1015 ok_non_zero_external_conn();
1017 IStream_Seek(pStream
, ullZero
, STREAM_SEEK_SET
, NULL
);
1018 hr
= CoUnmarshalInterface(pStream
, &IID_IClassFactory
, (void **)&pProxy
);
1019 ok_ole_success(hr
, CoUnmarshalInterface
);
1021 ok_more_than_one_lock();
1022 ok_non_zero_external_conn();
1024 IStream_Seek(pStream
, ullZero
, STREAM_SEEK_SET
, NULL
);
1025 /* marshal the proxy */
1026 hr
= CoMarshalInterface(pStream
, &IID_IClassFactory
, pProxy
, MSHCTX_INPROC
, NULL
, MSHLFLAGS_TABLEWEAK
);
1027 ok_ole_success(hr
, CoMarshalInterface
);
1029 ok_more_than_one_lock();
1030 ok_non_zero_external_conn();
1032 /* release the original proxy to test that we successfully keep the
1033 * original object alive */
1034 IUnknown_Release(pProxy
);
1036 IStream_Seek(pStream
, ullZero
, STREAM_SEEK_SET
, NULL
);
1037 hr
= CoUnmarshalInterface(pStream
, &IID_IClassFactory
, (void **)&pProxy2
);
1039 ok(hr
== CO_E_OBJNOTREG
, "CoUnmarshalInterface should return CO_E_OBJNOTREG instead of 0x%08x\n", hr
);
1042 ok_zero_external_conn();
1043 ok_last_release_closes(TRUE
);
1045 IStream_Release(pStream
);
1047 end_host_object(tid
, thread
);
1050 /* tests success case of an interthread marshal and then table-strong-marshaling the proxy */
1051 static void test_proxy_marshal_and_unmarshal_strong(void)
1054 IStream
*pStream
= NULL
;
1055 IUnknown
*pProxy
= NULL
;
1056 IUnknown
*pProxy2
= NULL
;
1061 external_connections
= 0;
1063 hr
= CreateStreamOnHGlobal(NULL
, TRUE
, &pStream
);
1064 ok_ole_success(hr
, CreateStreamOnHGlobal
);
1065 tid
= start_host_object(pStream
, &IID_IClassFactory
, (IUnknown
*)&Test_ClassFactory
, MSHLFLAGS_NORMAL
, &thread
);
1067 ok_more_than_one_lock();
1068 ok_non_zero_external_conn();
1070 IStream_Seek(pStream
, ullZero
, STREAM_SEEK_SET
, NULL
);
1071 hr
= CoUnmarshalInterface(pStream
, &IID_IClassFactory
, (void **)&pProxy
);
1072 ok_ole_success(hr
, CoUnmarshalInterface
);
1074 ok_more_than_one_lock();
1075 ok_non_zero_external_conn();
1077 IStream_Seek(pStream
, ullZero
, STREAM_SEEK_SET
, NULL
);
1078 /* marshal the proxy */
1079 hr
= CoMarshalInterface(pStream
, &IID_IClassFactory
, pProxy
, MSHCTX_INPROC
, NULL
, MSHLFLAGS_TABLESTRONG
);
1080 ok(hr
== S_OK
/* WinNT */ || hr
== E_INVALIDARG
/* Win9x */,
1081 "CoMarshalInterface should have return S_OK or E_INVALIDARG instead of 0x%08x\n", hr
);
1084 IUnknown_Release(pProxy
);
1088 ok_more_than_one_lock();
1089 ok_non_zero_external_conn();
1091 /* release the original proxy to test that we successfully keep the
1092 * original object alive */
1093 IUnknown_Release(pProxy
);
1095 IStream_Seek(pStream
, ullZero
, STREAM_SEEK_SET
, NULL
);
1096 hr
= CoUnmarshalInterface(pStream
, &IID_IClassFactory
, (void **)&pProxy2
);
1097 ok_ole_success(hr
, CoUnmarshalInterface
);
1099 ok_more_than_one_lock();
1100 ok_non_zero_external_conn();
1102 IUnknown_Release(pProxy2
);
1104 ok_more_than_one_lock();
1105 ok_non_zero_external_conn();
1108 IStream_Release(pStream
);
1110 end_host_object(tid
, thread
);
1114 ok_zero_external_conn();
1115 ok_last_release_closes(FALSE
);
1119 /* tests that stubs are released when the containing apartment is destroyed */
1120 static void test_marshal_stub_apartment_shutdown(void)
1123 IStream
*pStream
= NULL
;
1124 IUnknown
*pProxy
= NULL
;
1129 external_connections
= 0;
1131 hr
= CreateStreamOnHGlobal(NULL
, TRUE
, &pStream
);
1132 ok_ole_success(hr
, CreateStreamOnHGlobal
);
1133 tid
= start_host_object(pStream
, &IID_IClassFactory
, (IUnknown
*)&Test_ClassFactory
, MSHLFLAGS_NORMAL
, &thread
);
1135 ok_more_than_one_lock();
1136 ok_non_zero_external_conn();
1138 IStream_Seek(pStream
, ullZero
, STREAM_SEEK_SET
, NULL
);
1139 hr
= CoUnmarshalInterface(pStream
, &IID_IClassFactory
, (void **)&pProxy
);
1140 ok_ole_success(hr
, CoUnmarshalInterface
);
1141 IStream_Release(pStream
);
1143 ok_more_than_one_lock();
1144 ok_non_zero_external_conn();
1146 end_host_object(tid
, thread
);
1150 ok_zero_external_conn();
1151 ok_last_release_closes(FALSE
);
1154 IUnknown_Release(pProxy
);
1159 /* tests that proxies are released when the containing apartment is destroyed */
1160 static void test_marshal_proxy_apartment_shutdown(void)
1163 IStream
*pStream
= NULL
;
1164 IUnknown
*pProxy
= NULL
;
1169 external_connections
= 0;
1171 hr
= CreateStreamOnHGlobal(NULL
, TRUE
, &pStream
);
1172 ok_ole_success(hr
, CreateStreamOnHGlobal
);
1173 tid
= start_host_object(pStream
, &IID_IClassFactory
, (IUnknown
*)&Test_ClassFactory
, MSHLFLAGS_NORMAL
, &thread
);
1175 ok_more_than_one_lock();
1176 ok_non_zero_external_conn();
1178 IStream_Seek(pStream
, ullZero
, STREAM_SEEK_SET
, NULL
);
1179 hr
= CoUnmarshalInterface(pStream
, &IID_IClassFactory
, (void **)&pProxy
);
1180 ok_ole_success(hr
, CoUnmarshalInterface
);
1181 IStream_Release(pStream
);
1183 ok_more_than_one_lock();
1184 ok_non_zero_external_conn();
1189 ok_zero_external_conn();
1190 ok_last_release_closes(TRUE
);
1192 IUnknown_Release(pProxy
);
1196 end_host_object(tid
, thread
);
1198 pCoInitializeEx(NULL
, COINIT_APARTMENTTHREADED
);
1201 /* tests that proxies are released when the containing mta apartment is destroyed */
1202 static void test_marshal_proxy_mta_apartment_shutdown(void)
1205 IStream
*pStream
= NULL
;
1206 IUnknown
*pProxy
= NULL
;
1211 pCoInitializeEx(NULL
, COINIT_MULTITHREADED
);
1214 external_connections
= 0;
1216 hr
= CreateStreamOnHGlobal(NULL
, TRUE
, &pStream
);
1217 ok_ole_success(hr
, CreateStreamOnHGlobal
);
1218 tid
= start_host_object(pStream
, &IID_IClassFactory
, (IUnknown
*)&Test_ClassFactory
, MSHLFLAGS_NORMAL
, &thread
);
1220 ok_more_than_one_lock();
1221 ok_non_zero_external_conn();
1223 IStream_Seek(pStream
, ullZero
, STREAM_SEEK_SET
, NULL
);
1224 hr
= CoUnmarshalInterface(pStream
, &IID_IClassFactory
, (void **)&pProxy
);
1225 ok_ole_success(hr
, CoUnmarshalInterface
);
1226 IStream_Release(pStream
);
1228 ok_more_than_one_lock();
1229 ok_non_zero_external_conn();
1234 ok_zero_external_conn();
1235 ok_last_release_closes(TRUE
);
1237 IUnknown_Release(pProxy
);
1241 end_host_object(tid
, thread
);
1243 pCoInitializeEx(NULL
, COINIT_APARTMENTTHREADED
);
1246 static void test_marshal_channel_buffer(void)
1248 DWORD registration_key
;
1249 IUnknown
*proxy
= NULL
;
1250 IOleWindow
*ole_window
;
1257 struct host_object_data object_data
= { NULL
, &IID_IOleClientSite
, (IUnknown
*)&Test_OleClientSite
,
1258 MSHLFLAGS_NORMAL
, NULL
, (IUnknown
*)&PSFactoryBuffer
,
1259 &CLSID_WineTestPSFactoryBuffer
};
1262 external_connections
= 0;
1264 hr
= CoGetPSClsid(&IID_IOleWindow
, &clsid
);
1265 ok_ole_success(hr
, "CoGetPSClsid");
1267 hr
= CoGetClassObject(&clsid
, CLSCTX_INPROC_SERVER
, NULL
, &IID_IPSFactoryBuffer
,
1268 (void **)&ps_factory_buffer
);
1269 ok_ole_success(hr
, "CoGetClassObject");
1271 hr
= CreateStreamOnHGlobal(NULL
, TRUE
, &object_data
.stream
);
1272 ok_ole_success(hr
, CreateStreamOnHGlobal
);
1273 tid
= start_host_object2(&object_data
, &thread
);
1275 IStream_Seek(object_data
.stream
, ullZero
, STREAM_SEEK_SET
, NULL
);
1276 hr
= CoUnmarshalInterface(object_data
.stream
, &IID_IUnknown
, (void **)&proxy
);
1277 ok_ole_success(hr
, CoUnmarshalInterface
);
1278 IStream_Release(object_data
.stream
);
1280 hr
= CoRegisterClassObject(&CLSID_WineTestPSFactoryBuffer
, (IUnknown
*)&PSFactoryBuffer
,
1281 CLSCTX_INPROC_SERVER
, REGCLS_MULTIPLEUSE
, ®istration_key
);
1282 ok(hr
== S_OK
, "CoRegisterClassObject failed: %08x\n", hr
);
1284 hr
= CoRegisterPSClsid(&IID_IOleWindow
, &CLSID_WineTestPSFactoryBuffer
);
1285 ok(hr
== S_OK
, "CoRegisterPSClsid failed: %08x\n", hr
);
1287 SET_EXPECT(CreateStub
);
1288 SET_EXPECT(CreateProxy
);
1289 hr
= IUnknown_QueryInterface(proxy
, &IID_IOleWindow
, (void**)&ole_window
);
1290 ok(hr
== S_OK
, "Could not get IOleWindow iface: %08x\n", hr
);
1291 CHECK_CALLED(CreateStub
);
1292 CHECK_CALLED(CreateProxy
);
1295 SET_EXPECT(GetWindow
);
1296 hr
= IOleWindow_GetWindow(ole_window
, &hwnd
);
1297 ok(hr
== S_OK
, "GetWindow failed: %08x\n", hr
);
1298 ok((DWORD
)(DWORD_PTR
)hwnd
== 0xdeadbeef, "hwnd = %p\n", hwnd
);
1299 CHECK_CALLED(Invoke
);
1300 CHECK_CALLED(GetWindow
);
1302 IOleWindow_Release(ole_window
);
1304 SET_EXPECT(Disconnect
);
1305 IUnknown_Release(proxy
);
1307 CHECK_CALLED(Disconnect
);
1309 hr
= CoRevokeClassObject(registration_key
);
1310 ok(hr
== S_OK
, "CoRevokeClassObject failed: %08x\n", hr
);
1312 end_host_object(tid
, thread
);
1318 HANDLE marshal_event
;
1319 HANDLE unmarshal_event
;
1322 /* helper for test_no_couninitialize_server */
1323 static DWORD CALLBACK
no_couninitialize_server_proc(LPVOID p
)
1325 struct ncu_params
*ncu_params
= p
;
1328 pCoInitializeEx(NULL
, COINIT_MULTITHREADED
);
1330 hr
= CoMarshalInterface(ncu_params
->stream
, &IID_IClassFactory
, (IUnknown
*)&Test_ClassFactory
, MSHCTX_INPROC
, NULL
, MSHLFLAGS_NORMAL
);
1331 ok_ole_success(hr
, CoMarshalInterface
);
1333 SetEvent(ncu_params
->marshal_event
);
1335 ok( !WaitForSingleObject(ncu_params
->unmarshal_event
, 10000), "wait timed out\n" );
1337 /* die without calling CoUninitialize */
1342 /* tests apartment that an apartment with a stub is released without deadlock
1343 * if the owning thread exits */
1344 static void test_no_couninitialize_server(void)
1347 IStream
*pStream
= NULL
;
1348 IUnknown
*pProxy
= NULL
;
1351 struct ncu_params ncu_params
;
1354 external_connections
= 0;
1356 ncu_params
.marshal_event
= CreateEventA(NULL
, TRUE
, FALSE
, NULL
);
1357 ncu_params
.unmarshal_event
= CreateEventA(NULL
, TRUE
, FALSE
, NULL
);
1359 hr
= CreateStreamOnHGlobal(NULL
, TRUE
, &pStream
);
1360 ok_ole_success(hr
, CreateStreamOnHGlobal
);
1361 ncu_params
.stream
= pStream
;
1363 thread
= CreateThread(NULL
, 0, no_couninitialize_server_proc
, &ncu_params
, 0, &tid
);
1365 ok( !WaitForSingleObject(ncu_params
.marshal_event
, 10000), "wait timed out\n" );
1366 ok_more_than_one_lock();
1367 ok_non_zero_external_conn();
1369 IStream_Seek(pStream
, ullZero
, STREAM_SEEK_SET
, NULL
);
1370 hr
= CoUnmarshalInterface(pStream
, &IID_IClassFactory
, (void **)&pProxy
);
1371 ok_ole_success(hr
, CoUnmarshalInterface
);
1372 IStream_Release(pStream
);
1374 ok_more_than_one_lock();
1375 ok_non_zero_external_conn();
1377 SetEvent(ncu_params
.unmarshal_event
);
1378 ok( !WaitForSingleObject(thread
, 10000), "wait timed out\n" );
1382 ok_zero_external_conn();
1383 ok_last_release_closes(FALSE
);
1386 CloseHandle(thread
);
1387 CloseHandle(ncu_params
.marshal_event
);
1388 CloseHandle(ncu_params
.unmarshal_event
);
1390 IUnknown_Release(pProxy
);
1395 /* STA -> STA call during DLL_THREAD_DETACH */
1396 static DWORD CALLBACK
no_couninitialize_client_proc(LPVOID p
)
1398 struct ncu_params
*ncu_params
= p
;
1400 IUnknown
*pProxy
= NULL
;
1402 pCoInitializeEx(NULL
, COINIT_APARTMENTTHREADED
);
1404 hr
= CoUnmarshalInterface(ncu_params
->stream
, &IID_IClassFactory
, (void **)&pProxy
);
1405 ok_ole_success(hr
, CoUnmarshalInterface
);
1406 IStream_Release(ncu_params
->stream
);
1408 ok_more_than_one_lock();
1410 /* die without calling CoUninitialize */
1415 /* tests STA -> STA call during DLL_THREAD_DETACH doesn't deadlock */
1416 static void test_no_couninitialize_client(void)
1419 IStream
*pStream
= NULL
;
1424 struct ncu_params ncu_params
;
1427 external_connections
= 0;
1429 hr
= CreateStreamOnHGlobal(NULL
, TRUE
, &pStream
);
1430 ok_ole_success(hr
, CreateStreamOnHGlobal
);
1431 ncu_params
.stream
= pStream
;
1433 /* NOTE: assumes start_host_object uses an STA to host the object, as MTAs
1434 * always deadlock when called from within DllMain */
1435 host_tid
= start_host_object(pStream
, &IID_IClassFactory
, (IUnknown
*)&Test_ClassFactory
, MSHLFLAGS_NORMAL
, &host_thread
);
1436 IStream_Seek(pStream
, ullZero
, STREAM_SEEK_SET
, NULL
);
1438 ok_more_than_one_lock();
1439 ok_non_zero_external_conn();
1441 thread
= CreateThread(NULL
, 0, no_couninitialize_client_proc
, &ncu_params
, 0, &tid
);
1443 ok( !WaitForSingleObject(thread
, 10000), "wait timed out\n" );
1444 CloseHandle(thread
);
1447 ok_zero_external_conn();
1448 ok_last_release_closes(TRUE
);
1450 end_host_object(host_tid
, host_thread
);
1453 static BOOL crash_thread_success
;
1455 static DWORD CALLBACK
crash_couninitialize_proc(void *p
)
1464 hr
= CreateStreamOnHGlobal(NULL
, TRUE
, &stream
);
1465 ok_ole_success(hr
, CreateStreamOnHGlobal
);
1467 hr
= CoMarshalInterface(stream
, &IID_IUnknown
, &TestCrash_Unknown
, MSHCTX_INPROC
, NULL
, MSHLFLAGS_NORMAL
);
1468 ok_ole_success(hr
, CoMarshalInterface
);
1470 IStream_Seek(stream
, ullZero
, STREAM_SEEK_SET
, NULL
);
1472 hr
= CoReleaseMarshalData(stream
);
1473 ok_ole_success(hr
, CoReleaseMarshalData
);
1477 hr
= CoMarshalInterface(stream
, &IID_IUnknown
, &TestCrash_Unknown
, MSHCTX_INPROC
, NULL
, MSHLFLAGS_NORMAL
);
1478 ok_ole_success(hr
, CoMarshalInterface
);
1480 ok_more_than_one_lock();
1482 trace("CoUninitialize >>>\n");
1484 trace("CoUninitialize <<<\n");
1488 IStream_Release(stream
);
1489 crash_thread_success
= TRUE
;
1493 static void test_crash_couninitialize(void)
1498 if(!GetProcAddress(GetModuleHandleA("kernel32.dll"), "CreateActCtxW")) {
1499 win_skip("Skipping crash tests on win2k.\n");
1503 crash_thread_success
= FALSE
;
1504 thread
= CreateThread(NULL
, 0, crash_couninitialize_proc
, NULL
, 0, &tid
);
1505 ok(!WaitForSingleObject(thread
, 10000), "wait timed out\n");
1506 CloseHandle(thread
);
1507 ok(crash_thread_success
, "Crash thread failed\n");
1510 /* tests success case of a same-thread table-weak marshal, unmarshal, unmarshal */
1511 static void test_tableweak_marshal_and_unmarshal_twice(void)
1514 IStream
*pStream
= NULL
;
1515 IUnknown
*pProxy1
= NULL
;
1516 IUnknown
*pProxy2
= NULL
;
1521 external_connections
= 0;
1523 hr
= CreateStreamOnHGlobal(NULL
, TRUE
, &pStream
);
1524 ok_ole_success(hr
, CreateStreamOnHGlobal
);
1525 tid
= start_host_object(pStream
, &IID_IClassFactory
, (IUnknown
*)&Test_ClassFactory
, MSHLFLAGS_TABLEWEAK
, &thread
);
1527 ok_more_than_one_lock();
1528 ok_zero_external_conn();
1530 IStream_Seek(pStream
, ullZero
, STREAM_SEEK_SET
, NULL
);
1531 hr
= CoUnmarshalInterface(pStream
, &IID_IClassFactory
, (void **)&pProxy1
);
1532 ok_ole_success(hr
, CoUnmarshalInterface
);
1534 ok_more_than_one_lock();
1535 ok_non_zero_external_conn();
1537 IStream_Seek(pStream
, ullZero
, STREAM_SEEK_SET
, NULL
);
1538 hr
= CoUnmarshalInterface(pStream
, &IID_IClassFactory
, (void **)&pProxy2
);
1539 ok_ole_success(hr
, CoUnmarshalInterface
);
1541 ok_more_than_one_lock();
1543 IUnknown_Release(pProxy1
);
1544 ok_non_zero_external_conn();
1545 IUnknown_Release(pProxy2
);
1546 ok_zero_external_conn();
1547 ok_last_release_closes(TRUE
);
1549 /* When IExternalConnection is present COM's lifetime management
1550 * behaviour is altered; the remaining weak ref prevents stub shutdown. */
1551 if (with_external_conn
)
1553 ok_more_than_one_lock();
1554 IStream_Seek(pStream
, ullZero
, STREAM_SEEK_SET
, NULL
);
1555 release_host_object(tid
, 0);
1558 /* Without IExternalConnection this line is shows the difference between weak and strong table marshaling
1559 * weak has cLocks == 0, strong has cLocks > 0. */
1562 IStream_Release(pStream
);
1563 end_host_object(tid
, thread
);
1566 /* tests releasing after unmarshaling one object */
1567 static void test_tableweak_marshal_releasedata1(void)
1570 IStream
*pStream
= NULL
;
1571 IUnknown
*pProxy1
= NULL
;
1572 IUnknown
*pProxy2
= NULL
;
1577 external_connections
= 0;
1579 hr
= CreateStreamOnHGlobal(NULL
, TRUE
, &pStream
);
1580 ok_ole_success(hr
, CreateStreamOnHGlobal
);
1581 tid
= start_host_object(pStream
, &IID_IClassFactory
, (IUnknown
*)&Test_ClassFactory
, MSHLFLAGS_TABLEWEAK
, &thread
);
1583 ok_more_than_one_lock();
1584 ok_zero_external_conn();
1586 IStream_Seek(pStream
, ullZero
, STREAM_SEEK_SET
, NULL
);
1587 hr
= CoUnmarshalInterface(pStream
, &IID_IClassFactory
, (void **)&pProxy1
);
1588 ok_ole_success(hr
, CoUnmarshalInterface
);
1590 ok_more_than_one_lock();
1591 ok_non_zero_external_conn();
1593 /* release the remaining reference on the object by calling
1594 * CoReleaseMarshalData in the hosting thread */
1595 IStream_Seek(pStream
, ullZero
, STREAM_SEEK_SET
, NULL
);
1596 release_host_object(tid
, 0);
1598 ok_more_than_one_lock();
1599 ok_non_zero_external_conn();
1601 IStream_Seek(pStream
, ullZero
, STREAM_SEEK_SET
, NULL
);
1602 hr
= CoUnmarshalInterface(pStream
, &IID_IClassFactory
, (void **)&pProxy2
);
1603 ok_ole_success(hr
, CoUnmarshalInterface
);
1604 IStream_Release(pStream
);
1606 ok_more_than_one_lock();
1607 ok_non_zero_external_conn();
1609 IUnknown_Release(pProxy1
);
1613 ok_non_zero_external_conn();
1614 IUnknown_Release(pProxy2
);
1617 /* this line is shows the difference between weak and strong table marshaling:
1618 * weak has cLocks == 0
1619 * strong has cLocks > 0 */
1621 ok_zero_external_conn();
1622 ok_last_release_closes(TRUE
);
1624 end_host_object(tid
, thread
);
1627 /* tests releasing after unmarshaling one object */
1628 static void test_tableweak_marshal_releasedata2(void)
1631 IStream
*pStream
= NULL
;
1632 IUnknown
*pProxy
= NULL
;
1637 external_connections
= 0;
1639 hr
= CreateStreamOnHGlobal(NULL
, TRUE
, &pStream
);
1640 ok_ole_success(hr
, CreateStreamOnHGlobal
);
1641 tid
= start_host_object(pStream
, &IID_IClassFactory
, (IUnknown
*)&Test_ClassFactory
, MSHLFLAGS_TABLEWEAK
, &thread
);
1643 ok_more_than_one_lock();
1644 ok_zero_external_conn();
1646 /* release the remaining reference on the object by calling
1647 * CoReleaseMarshalData in the hosting thread */
1648 IStream_Seek(pStream
, ullZero
, STREAM_SEEK_SET
, NULL
);
1649 release_host_object(tid
, 0);
1653 IStream_Seek(pStream
, ullZero
, STREAM_SEEK_SET
, NULL
);
1654 hr
= CoUnmarshalInterface(pStream
, &IID_IClassFactory
, (void **)&pProxy
);
1657 ok(hr
== CO_E_OBJNOTREG
,
1658 "CoUnmarshalInterface should have failed with CO_E_OBJNOTREG, but returned 0x%08x instead\n",
1661 IStream_Release(pStream
);
1664 ok_zero_external_conn();
1666 end_host_object(tid
, thread
);
1669 struct duo_marshal_data
1671 MSHLFLAGS marshal_flags1
, marshal_flags2
;
1672 IStream
*pStream1
, *pStream2
;
1677 static DWORD CALLBACK
duo_marshal_thread_proc(void *p
)
1680 struct duo_marshal_data
*data
= p
;
1681 HANDLE hQuitEvent
= data
->hQuitEvent
;
1684 pCoInitializeEx(NULL
, COINIT_APARTMENTTHREADED
);
1686 hr
= CoMarshalInterface(data
->pStream1
, &IID_IClassFactory
, (IUnknown
*)&Test_ClassFactory
, MSHCTX_INPROC
, NULL
, data
->marshal_flags1
);
1687 ok_ole_success(hr
, "CoMarshalInterface");
1689 hr
= CoMarshalInterface(data
->pStream2
, &IID_IClassFactory
, (IUnknown
*)&Test_ClassFactory
, MSHCTX_INPROC
, NULL
, data
->marshal_flags2
);
1690 ok_ole_success(hr
, "CoMarshalInterface");
1692 /* force the message queue to be created before signaling parent thread */
1693 PeekMessageA(&msg
, NULL
, WM_USER
, WM_USER
, PM_NOREMOVE
);
1695 SetEvent(data
->hReadyEvent
);
1697 while (WAIT_OBJECT_0
+ 1 == MsgWaitForMultipleObjects(1, &hQuitEvent
, FALSE
, 10000, QS_ALLINPUT
))
1699 while (PeekMessageA(&msg
, NULL
, 0, 0, PM_REMOVE
))
1701 if (msg
.hwnd
== NULL
&& msg
.message
== RELEASEMARSHALDATA
)
1703 CoReleaseMarshalData(msg
.wParam
== 1 ? data
->pStream1
: data
->pStream2
);
1704 SetEvent((HANDLE
)msg
.lParam
);
1707 DispatchMessageA(&msg
);
1710 CloseHandle(hQuitEvent
);
1717 /* tests interaction between table-weak and normal marshalling of an object */
1718 static void test_tableweak_and_normal_marshal_and_unmarshal(void)
1721 IUnknown
*pProxyWeak
= NULL
;
1722 IUnknown
*pProxyNormal
= NULL
;
1725 struct duo_marshal_data data
;
1728 external_connections
= 0;
1730 data
.hReadyEvent
= CreateEventA(NULL
, FALSE
, FALSE
, NULL
);
1731 data
.hQuitEvent
= CreateEventA(NULL
, FALSE
, FALSE
, NULL
);
1732 data
.marshal_flags1
= MSHLFLAGS_TABLEWEAK
;
1733 data
.marshal_flags2
= MSHLFLAGS_NORMAL
;
1734 hr
= CreateStreamOnHGlobal(NULL
, TRUE
, &data
.pStream1
);
1735 ok_ole_success(hr
, CreateStreamOnHGlobal
);
1736 hr
= CreateStreamOnHGlobal(NULL
, TRUE
, &data
.pStream2
);
1737 ok_ole_success(hr
, CreateStreamOnHGlobal
);
1739 thread
= CreateThread(NULL
, 0, duo_marshal_thread_proc
, &data
, 0, &tid
);
1740 ok( !WaitForSingleObject(data
.hReadyEvent
, 10000), "wait timed out\n" );
1741 CloseHandle(data
.hReadyEvent
);
1743 ok_more_than_one_lock();
1744 ok_non_zero_external_conn();
1747 IStream_Seek(data
.pStream1
, ullZero
, STREAM_SEEK_SET
, NULL
);
1748 hr
= CoUnmarshalInterface(data
.pStream1
, &IID_IClassFactory
, (void **)&pProxyWeak
);
1749 ok_ole_success(hr
, CoUnmarshalInterface
);
1751 ok_more_than_one_lock();
1754 IStream_Seek(data
.pStream2
, ullZero
, STREAM_SEEK_SET
, NULL
);
1755 hr
= CoUnmarshalInterface(data
.pStream2
, &IID_IClassFactory
, (void **)&pProxyNormal
);
1756 ok_ole_success(hr
, CoUnmarshalInterface
);
1758 ok_more_than_one_lock();
1760 IUnknown_Release(pProxyNormal
);
1762 ok_more_than_one_lock();
1763 ok_non_zero_external_conn();
1765 IUnknown_Release(pProxyWeak
);
1767 ok_zero_external_conn();
1768 ok_last_release_closes(TRUE
);
1770 /* When IExternalConnection is present COM's lifetime management
1771 * behaviour is altered; the remaining weak ref prevents stub shutdown. */
1772 if (with_external_conn
)
1774 ok_more_than_one_lock();
1775 IStream_Seek(data
.pStream1
, ullZero
, STREAM_SEEK_SET
, NULL
);
1776 release_host_object(tid
, 1);
1780 IStream_Release(data
.pStream1
);
1781 IStream_Release(data
.pStream2
);
1783 SetEvent(data
.hQuitEvent
);
1784 ok( !WaitForSingleObject(thread
, 10000), "wait timed out\n" );
1785 CloseHandle(thread
);
1788 static void test_tableweak_and_normal_marshal_and_releasedata(void)
1793 struct duo_marshal_data data
;
1796 external_connections
= 0;
1798 data
.hReadyEvent
= CreateEventA(NULL
, FALSE
, FALSE
, NULL
);
1799 data
.hQuitEvent
= CreateEventA(NULL
, FALSE
, FALSE
, NULL
);
1800 data
.marshal_flags1
= MSHLFLAGS_TABLEWEAK
;
1801 data
.marshal_flags2
= MSHLFLAGS_NORMAL
;
1802 hr
= CreateStreamOnHGlobal(NULL
, TRUE
, &data
.pStream1
);
1803 ok_ole_success(hr
, CreateStreamOnHGlobal
);
1804 hr
= CreateStreamOnHGlobal(NULL
, TRUE
, &data
.pStream2
);
1805 ok_ole_success(hr
, CreateStreamOnHGlobal
);
1807 thread
= CreateThread(NULL
, 0, duo_marshal_thread_proc
, &data
, 0, &tid
);
1808 ok( !WaitForSingleObject(data
.hReadyEvent
, 10000), "wait timed out\n" );
1809 CloseHandle(data
.hReadyEvent
);
1811 ok_more_than_one_lock();
1812 ok_non_zero_external_conn();
1814 /* release normal - which in the non-external conn case will free the object despite the weak ref. */
1815 IStream_Seek(data
.pStream2
, ullZero
, STREAM_SEEK_SET
, NULL
);
1816 release_host_object(tid
, 2);
1818 ok_zero_external_conn();
1819 ok_last_release_closes(TRUE
);
1821 if (with_external_conn
)
1823 ok_more_than_one_lock();
1824 IStream_Seek(data
.pStream1
, ullZero
, STREAM_SEEK_SET
, NULL
);
1825 release_host_object(tid
, 1);
1830 IStream_Release(data
.pStream1
);
1831 IStream_Release(data
.pStream2
);
1833 SetEvent(data
.hQuitEvent
);
1834 ok( !WaitForSingleObject(thread
, 10000), "wait timed out\n" );
1835 CloseHandle(thread
);
1838 static void test_two_tableweak_marshal_and_releasedata(void)
1843 struct duo_marshal_data data
;
1846 external_connections
= 0;
1848 data
.hReadyEvent
= CreateEventA(NULL
, FALSE
, FALSE
, NULL
);
1849 data
.hQuitEvent
= CreateEventA(NULL
, FALSE
, FALSE
, NULL
);
1850 data
.marshal_flags1
= MSHLFLAGS_TABLEWEAK
;
1851 data
.marshal_flags2
= MSHLFLAGS_TABLEWEAK
;
1852 hr
= CreateStreamOnHGlobal(NULL
, TRUE
, &data
.pStream1
);
1853 ok_ole_success(hr
, CreateStreamOnHGlobal
);
1854 hr
= CreateStreamOnHGlobal(NULL
, TRUE
, &data
.pStream2
);
1855 ok_ole_success(hr
, CreateStreamOnHGlobal
);
1857 thread
= CreateThread(NULL
, 0, duo_marshal_thread_proc
, &data
, 0, &tid
);
1858 ok( !WaitForSingleObject(data
.hReadyEvent
, 10000), "wait timed out\n" );
1859 CloseHandle(data
.hReadyEvent
);
1861 ok_more_than_one_lock();
1862 ok_zero_external_conn();
1864 /* release one weak ref - the remaining weak ref will keep the obj alive */
1865 IStream_Seek(data
.pStream1
, ullZero
, STREAM_SEEK_SET
, NULL
);
1866 release_host_object(tid
, 1);
1868 ok_more_than_one_lock();
1870 IStream_Seek(data
.pStream2
, ullZero
, STREAM_SEEK_SET
, NULL
);
1871 release_host_object(tid
, 2);
1875 IStream_Release(data
.pStream1
);
1876 IStream_Release(data
.pStream2
);
1878 SetEvent(data
.hQuitEvent
);
1879 ok( !WaitForSingleObject(thread
, 10000), "wait timed out\n" );
1880 CloseHandle(thread
);
1883 /* tests success case of a same-thread table-strong marshal, unmarshal, unmarshal */
1884 static void test_tablestrong_marshal_and_unmarshal_twice(void)
1887 IStream
*pStream
= NULL
;
1888 IUnknown
*pProxy1
= NULL
;
1889 IUnknown
*pProxy2
= NULL
;
1894 external_connections
= 0;
1896 hr
= CreateStreamOnHGlobal(NULL
, TRUE
, &pStream
);
1897 ok_ole_success(hr
, CreateStreamOnHGlobal
);
1898 tid
= start_host_object(pStream
, &IID_IClassFactory
, (IUnknown
*)&Test_ClassFactory
, MSHLFLAGS_TABLESTRONG
, &thread
);
1900 ok_more_than_one_lock();
1901 ok_non_zero_external_conn();
1903 IStream_Seek(pStream
, ullZero
, STREAM_SEEK_SET
, NULL
);
1904 hr
= CoUnmarshalInterface(pStream
, &IID_IClassFactory
, (void **)&pProxy1
);
1905 ok_ole_success(hr
, CoUnmarshalInterface
);
1907 ok_more_than_one_lock();
1909 IStream_Seek(pStream
, ullZero
, STREAM_SEEK_SET
, NULL
);
1910 hr
= CoUnmarshalInterface(pStream
, &IID_IClassFactory
, (void **)&pProxy2
);
1911 ok_ole_success(hr
, CoUnmarshalInterface
);
1913 ok_more_than_one_lock();
1915 if (pProxy1
) IUnknown_Release(pProxy1
);
1916 if (pProxy2
) IUnknown_Release(pProxy2
);
1918 /* this line is shows the difference between weak and strong table marshaling:
1919 * weak has cLocks == 0
1920 * strong has cLocks > 0 */
1921 ok_more_than_one_lock();
1923 /* release the remaining reference on the object by calling
1924 * CoReleaseMarshalData in the hosting thread */
1925 IStream_Seek(pStream
, ullZero
, STREAM_SEEK_SET
, NULL
);
1926 release_host_object(tid
, 0);
1927 IStream_Release(pStream
);
1930 ok_zero_external_conn();
1931 ok_last_release_closes(TRUE
);
1933 end_host_object(tid
, thread
);
1936 /* tests CoLockObjectExternal */
1937 static void test_lock_object_external(void)
1940 IStream
*pStream
= NULL
;
1943 external_connections
= 0;
1945 /* test the stub manager creation aspect of CoLockObjectExternal when the
1946 * object hasn't been marshaled yet */
1947 CoLockObjectExternal((IUnknown
*)&Test_ClassFactory
, TRUE
, TRUE
);
1949 ok_more_than_one_lock();
1950 ok_non_zero_external_conn();
1952 CoDisconnectObject((IUnknown
*)&Test_ClassFactory
, 0);
1955 ok_non_zero_external_conn();
1956 external_connections
= 0;
1958 /* test our empty stub manager being handled correctly in
1959 * CoMarshalInterface */
1960 CoLockObjectExternal((IUnknown
*)&Test_ClassFactory
, TRUE
, TRUE
);
1962 hr
= CreateStreamOnHGlobal(NULL
, TRUE
, &pStream
);
1963 ok_ole_success(hr
, CreateStreamOnHGlobal
);
1964 hr
= CoMarshalInterface(pStream
, &IID_IClassFactory
, (IUnknown
*)&Test_ClassFactory
, MSHCTX_INPROC
, NULL
, MSHLFLAGS_NORMAL
);
1965 ok_ole_success(hr
, CoMarshalInterface
);
1967 CoLockObjectExternal((IUnknown
*)&Test_ClassFactory
, TRUE
, TRUE
);
1969 ok_more_than_one_lock();
1970 ok_non_zero_external_conn();
1972 IStream_Seek(pStream
, ullZero
, STREAM_SEEK_SET
, NULL
);
1973 hr
= CoReleaseMarshalData(pStream
);
1974 ok_ole_success(hr
, CoReleaseMarshalData
);
1975 IStream_Seek(pStream
, ullZero
, STREAM_SEEK_SET
, NULL
);
1977 ok_more_than_one_lock();
1978 ok_non_zero_external_conn();
1979 ok_last_release_closes(TRUE
);
1981 CoLockObjectExternal((IUnknown
*)&Test_ClassFactory
, FALSE
, TRUE
);
1983 ok_more_than_one_lock();
1984 ok_non_zero_external_conn();
1985 ok_last_release_closes(TRUE
);
1987 CoLockObjectExternal((IUnknown
*)&Test_ClassFactory
, FALSE
, TRUE
);
1990 ok_zero_external_conn();
1991 ok_last_release_closes(TRUE
);
1993 /* test CoLockObjectExternal releases reference to object with
1994 * fLastUnlockReleases as TRUE and there are only strong references on
1996 CoLockObjectExternal((IUnknown
*)&Test_ClassFactory
, TRUE
, FALSE
);
1998 ok_more_than_one_lock();
1999 ok_non_zero_external_conn();
2001 CoLockObjectExternal((IUnknown
*)&Test_ClassFactory
, FALSE
, FALSE
);
2004 ok_zero_external_conn();
2005 ok_last_release_closes(FALSE
);
2007 /* test CoLockObjectExternal doesn't release the last reference to an
2008 * object with fLastUnlockReleases as TRUE and there is a weak reference
2010 hr
= CoMarshalInterface(pStream
, &IID_IClassFactory
, (IUnknown
*)&Test_ClassFactory
, MSHCTX_INPROC
, NULL
, MSHLFLAGS_TABLEWEAK
);
2011 ok_ole_success(hr
, CoMarshalInterface
);
2013 ok_more_than_one_lock();
2014 ok_zero_external_conn();
2016 CoLockObjectExternal((IUnknown
*)&Test_ClassFactory
, TRUE
, FALSE
);
2018 ok_more_than_one_lock();
2019 ok_non_zero_external_conn();
2021 CoLockObjectExternal((IUnknown
*)&Test_ClassFactory
, FALSE
, FALSE
);
2023 ok_more_than_one_lock();
2024 ok_zero_external_conn();
2025 ok_last_release_closes(FALSE
);
2027 CoDisconnectObject((IUnknown
*)&Test_ClassFactory
, 0);
2031 IStream_Release(pStream
);
2034 /* tests disconnecting stubs */
2035 static void test_disconnect_stub(void)
2038 IStream
*pStream
= NULL
;
2041 external_connections
= 0;
2043 hr
= CreateStreamOnHGlobal(NULL
, TRUE
, &pStream
);
2044 ok_ole_success(hr
, CreateStreamOnHGlobal
);
2045 hr
= CoMarshalInterface(pStream
, &IID_IClassFactory
, (IUnknown
*)&Test_ClassFactory
, MSHCTX_INPROC
, NULL
, MSHLFLAGS_NORMAL
);
2046 ok_ole_success(hr
, CoMarshalInterface
);
2048 ok_non_zero_external_conn();
2050 CoLockObjectExternal((IUnknown
*)&Test_ClassFactory
, TRUE
, TRUE
);
2052 ok_more_than_one_lock();
2053 ok_non_zero_external_conn();
2055 IStream_Seek(pStream
, ullZero
, STREAM_SEEK_SET
, NULL
);
2056 hr
= CoReleaseMarshalData(pStream
);
2057 ok_ole_success(hr
, CoReleaseMarshalData
);
2058 IStream_Release(pStream
);
2060 ok_more_than_one_lock();
2061 ok_non_zero_external_conn();
2063 CoDisconnectObject((IUnknown
*)&Test_ClassFactory
, 0);
2066 ok_non_zero_external_conn();
2068 hr
= CoDisconnectObject(NULL
, 0);
2069 ok( hr
== E_INVALIDARG
, "wrong status %x\n", hr
);
2072 /* tests failure case of a same-thread marshal and unmarshal twice */
2073 static void test_normal_marshal_and_unmarshal_twice(void)
2076 IStream
*pStream
= NULL
;
2077 IUnknown
*pProxy1
= NULL
;
2078 IUnknown
*pProxy2
= NULL
;
2081 external_connections
= 0;
2083 hr
= CreateStreamOnHGlobal(NULL
, TRUE
, &pStream
);
2084 ok_ole_success(hr
, CreateStreamOnHGlobal
);
2085 hr
= CoMarshalInterface(pStream
, &IID_IClassFactory
, (IUnknown
*)&Test_ClassFactory
, MSHCTX_INPROC
, NULL
, MSHLFLAGS_NORMAL
);
2086 ok_ole_success(hr
, CoMarshalInterface
);
2088 ok_more_than_one_lock();
2089 ok_non_zero_external_conn();
2091 IStream_Seek(pStream
, ullZero
, STREAM_SEEK_SET
, NULL
);
2092 hr
= CoUnmarshalInterface(pStream
, &IID_IClassFactory
, (void **)&pProxy1
);
2093 ok_ole_success(hr
, CoUnmarshalInterface
);
2095 ok_more_than_one_lock();
2096 ok_zero_external_conn();
2097 ok_last_release_closes(FALSE
);
2099 IStream_Seek(pStream
, ullZero
, STREAM_SEEK_SET
, NULL
);
2100 hr
= CoUnmarshalInterface(pStream
, &IID_IClassFactory
, (void **)&pProxy2
);
2101 ok(hr
== CO_E_OBJNOTCONNECTED
,
2102 "CoUnmarshalInterface should have failed with error CO_E_OBJNOTCONNECTED for double unmarshal, instead of 0x%08x\n", hr
);
2104 IStream_Release(pStream
);
2106 ok_more_than_one_lock();
2108 IUnknown_Release(pProxy1
);
2113 /* tests success case of marshaling and unmarshaling an HRESULT */
2114 static void test_hresult_marshaling(void)
2117 HRESULT hr_marshaled
= 0;
2118 IStream
*pStream
= NULL
;
2119 static const HRESULT E_DEADBEEF
= 0xdeadbeef;
2121 hr
= CreateStreamOnHGlobal(NULL
, TRUE
, &pStream
);
2122 ok_ole_success(hr
, CreateStreamOnHGlobal
);
2124 hr
= CoMarshalHresult(pStream
, E_DEADBEEF
);
2125 ok_ole_success(hr
, CoMarshalHresult
);
2127 IStream_Seek(pStream
, ullZero
, STREAM_SEEK_SET
, NULL
);
2128 hr
= IStream_Read(pStream
, &hr_marshaled
, sizeof(HRESULT
), NULL
);
2129 ok_ole_success(hr
, IStream_Read
);
2131 ok(hr_marshaled
== E_DEADBEEF
, "Didn't marshal HRESULT as expected: got value 0x%08x instead\n", hr_marshaled
);
2134 IStream_Seek(pStream
, ullZero
, STREAM_SEEK_SET
, NULL
);
2135 hr
= CoUnmarshalHresult(pStream
, &hr_marshaled
);
2136 ok_ole_success(hr
, CoUnmarshalHresult
);
2138 ok(hr_marshaled
== E_DEADBEEF
, "Didn't marshal HRESULT as expected: got value 0x%08x instead\n", hr_marshaled
);
2140 IStream_Release(pStream
);
2144 /* helper for test_proxy_used_in_wrong_thread */
2145 static DWORD CALLBACK
bad_thread_proc(LPVOID p
)
2147 IClassFactory
* cf
= p
;
2149 IUnknown
* proxy
= NULL
;
2151 hr
= IClassFactory_CreateInstance(cf
, NULL
, &IID_IUnknown
, (LPVOID
*)&proxy
);
2153 ok(hr
== CO_E_NOTINITIALIZED
,
2154 "COM should have failed with CO_E_NOTINITIALIZED on using proxy without apartment, but instead returned 0x%08x\n",
2157 hr
= IClassFactory_QueryInterface(cf
, &IID_IMultiQI
, (LPVOID
*)&proxy
);
2158 /* Win9x returns S_OK, whilst NT returns RPC_E_WRONG_THREAD */
2159 trace("call to proxy's QueryInterface for local interface without apartment returned 0x%08x\n", hr
);
2161 IUnknown_Release(proxy
);
2163 hr
= IClassFactory_QueryInterface(cf
, &IID_IStream
, (LPVOID
*)&proxy
);
2164 /* Win9x returns E_NOINTERFACE, whilst NT returns RPC_E_WRONG_THREAD */
2165 trace("call to proxy's QueryInterface without apartment returned 0x%08x\n", hr
);
2167 IUnknown_Release(proxy
);
2169 pCoInitializeEx(NULL
, COINIT_MULTITHREADED
);
2171 hr
= IClassFactory_CreateInstance(cf
, NULL
, &IID_IUnknown
, (LPVOID
*)&proxy
);
2172 if (proxy
) IUnknown_Release(proxy
);
2173 ok(hr
== RPC_E_WRONG_THREAD
,
2174 "COM should have failed with RPC_E_WRONG_THREAD on using proxy from wrong apartment, but instead returned 0x%08x\n",
2177 hr
= IClassFactory_QueryInterface(cf
, &IID_IStream
, (LPVOID
*)&proxy
);
2178 /* Win9x returns E_NOINTERFACE, whilst NT returns RPC_E_WRONG_THREAD */
2179 trace("call to proxy's QueryInterface from wrong apartment returned 0x%08x\n", hr
);
2181 /* now be really bad and release the proxy from the wrong apartment */
2182 IClassFactory_Release(cf
);
2189 /* tests failure case of a using a proxy in the wrong apartment */
2190 static void test_proxy_used_in_wrong_thread(void)
2193 IStream
*pStream
= NULL
;
2194 IUnknown
*pProxy
= NULL
;
2201 hr
= CreateStreamOnHGlobal(NULL
, TRUE
, &pStream
);
2202 ok_ole_success(hr
, CreateStreamOnHGlobal
);
2203 tid
= start_host_object(pStream
, &IID_IClassFactory
, (IUnknown
*)&Test_ClassFactory
, MSHLFLAGS_NORMAL
, &host_thread
);
2205 ok_more_than_one_lock();
2207 IStream_Seek(pStream
, ullZero
, STREAM_SEEK_SET
, NULL
);
2208 hr
= CoUnmarshalInterface(pStream
, &IID_IClassFactory
, (void **)&pProxy
);
2209 ok_ole_success(hr
, CoUnmarshalInterface
);
2210 IStream_Release(pStream
);
2212 ok_more_than_one_lock();
2214 /* do a call that will fail, but result in IRemUnknown being used by the proxy */
2215 IUnknown_QueryInterface(pProxy
, &IID_IStream
, (LPVOID
*)&pStream
);
2217 /* create a thread that we can misbehave in */
2218 thread
= CreateThread(NULL
, 0, bad_thread_proc
, pProxy
, 0, &tid2
);
2220 ok( !WaitForSingleObject(thread
, 10000), "wait timed out\n" );
2221 CloseHandle(thread
);
2223 /* do release statement on Win9x that we should have done above */
2224 if (!GetProcAddress(GetModuleHandleA("ole32"), "CoRegisterSurrogateEx"))
2225 IUnknown_Release(pProxy
);
2229 end_host_object(tid
, host_thread
);
2232 static HRESULT WINAPI
MessageFilter_QueryInterface(IMessageFilter
*iface
, REFIID riid
, void ** ppvObj
)
2234 if (ppvObj
== NULL
) return E_POINTER
;
2236 if (IsEqualGUID(riid
, &IID_IUnknown
) ||
2237 IsEqualGUID(riid
, &IID_IClassFactory
))
2240 IMessageFilter_AddRef(iface
);
2244 return E_NOINTERFACE
;
2247 static ULONG WINAPI
MessageFilter_AddRef(IMessageFilter
*iface
)
2249 return 2; /* non-heap object */
2252 static ULONG WINAPI
MessageFilter_Release(IMessageFilter
*iface
)
2254 return 1; /* non-heap object */
2257 static DWORD WINAPI
MessageFilter_HandleInComingCall(
2258 IMessageFilter
*iface
,
2260 HTASK threadIDCaller
,
2262 LPINTERFACEINFO lpInterfaceInfo
)
2264 static int callcount
= 0;
2266 trace("HandleInComingCall\n");
2270 ret
= SERVERCALL_REJECTED
;
2273 ret
= SERVERCALL_RETRYLATER
;
2276 ret
= SERVERCALL_ISHANDLED
;
2283 static DWORD WINAPI
MessageFilter_RetryRejectedCall(
2284 IMessageFilter
*iface
,
2285 HTASK threadIDCallee
,
2289 trace("RetryRejectedCall\n");
2293 static DWORD WINAPI
MessageFilter_MessagePending(
2294 IMessageFilter
*iface
,
2295 HTASK threadIDCallee
,
2297 DWORD dwPendingType
)
2299 trace("MessagePending\n");
2300 return PENDINGMSG_WAITNOPROCESS
;
2303 static const IMessageFilterVtbl MessageFilter_Vtbl
=
2305 MessageFilter_QueryInterface
,
2306 MessageFilter_AddRef
,
2307 MessageFilter_Release
,
2308 MessageFilter_HandleInComingCall
,
2309 MessageFilter_RetryRejectedCall
,
2310 MessageFilter_MessagePending
2313 static IMessageFilter MessageFilter
= { &MessageFilter_Vtbl
};
2315 static void test_message_filter(void)
2318 IClassFactory
*cf
= NULL
;
2320 IUnknown
*proxy
= NULL
;
2321 IMessageFilter
*prev_filter
= NULL
;
2324 struct host_object_data object_data
= { NULL
, &IID_IClassFactory
, (IUnknown
*)&Test_ClassFactory
,
2325 MSHLFLAGS_NORMAL
, &MessageFilter
};
2329 hr
= CreateStreamOnHGlobal(NULL
, TRUE
, &object_data
.stream
);
2330 ok_ole_success(hr
, CreateStreamOnHGlobal
);
2331 tid
= start_host_object2(&object_data
, &thread
);
2333 ok_more_than_one_lock();
2335 IStream_Seek(object_data
.stream
, ullZero
, STREAM_SEEK_SET
, NULL
);
2336 hr
= CoUnmarshalInterface(object_data
.stream
, &IID_IClassFactory
, (void **)&cf
);
2337 ok_ole_success(hr
, CoUnmarshalInterface
);
2338 IStream_Release(object_data
.stream
);
2340 ok_more_than_one_lock();
2342 hr
= IClassFactory_CreateInstance(cf
, NULL
, &IID_IUnknown
, (LPVOID
*)&proxy
);
2343 ok(hr
== RPC_E_CALL_REJECTED
, "Call should have returned RPC_E_CALL_REJECTED, but return 0x%08x instead\n", hr
);
2344 if (proxy
) IUnknown_Release(proxy
);
2347 hr
= CoRegisterMessageFilter(&MessageFilter
, &prev_filter
);
2348 ok_ole_success(hr
, CoRegisterMessageFilter
);
2350 hr
= IClassFactory_CreateInstance(cf
, NULL
, &IID_IUnknown
, (LPVOID
*)&proxy
);
2351 ok_ole_success(hr
, IClassFactory_CreateInstance
);
2353 IUnknown_Release(proxy
);
2355 IClassFactory_Release(cf
);
2359 end_host_object(tid
, thread
);
2361 hr
= CoRegisterMessageFilter(prev_filter
, NULL
);
2362 ok_ole_success(hr
, CoRegisterMessageFilter
);
2365 /* test failure case of trying to unmarshal from bad stream */
2366 static void test_bad_marshal_stream(void)
2369 IStream
*pStream
= NULL
;
2371 hr
= CreateStreamOnHGlobal(NULL
, TRUE
, &pStream
);
2372 ok_ole_success(hr
, CreateStreamOnHGlobal
);
2373 hr
= CoMarshalInterface(pStream
, &IID_IClassFactory
, (IUnknown
*)&Test_ClassFactory
, MSHCTX_INPROC
, NULL
, MSHLFLAGS_NORMAL
);
2374 ok_ole_success(hr
, CoMarshalInterface
);
2376 ok_more_than_one_lock();
2378 /* try to read beyond end of stream */
2379 hr
= CoReleaseMarshalData(pStream
);
2380 ok(hr
== STG_E_READFAULT
, "Should have failed with STG_E_READFAULT, but returned 0x%08x instead\n", hr
);
2382 /* now release for real */
2383 IStream_Seek(pStream
, ullZero
, STREAM_SEEK_SET
, NULL
);
2384 hr
= CoReleaseMarshalData(pStream
);
2385 ok_ole_success(hr
, CoReleaseMarshalData
);
2387 IStream_Release(pStream
);
2390 /* tests that proxies implement certain interfaces */
2391 static void test_proxy_interfaces(void)
2394 IStream
*pStream
= NULL
;
2395 IUnknown
*pProxy
= NULL
;
2396 IUnknown
*pOtherUnknown
= NULL
;
2402 hr
= CreateStreamOnHGlobal(NULL
, TRUE
, &pStream
);
2403 ok_ole_success(hr
, CreateStreamOnHGlobal
);
2404 tid
= start_host_object(pStream
, &IID_IClassFactory
, (IUnknown
*)&Test_ClassFactory
, MSHLFLAGS_NORMAL
, &thread
);
2406 ok_more_than_one_lock();
2408 IStream_Seek(pStream
, ullZero
, STREAM_SEEK_SET
, NULL
);
2409 hr
= CoUnmarshalInterface(pStream
, &IID_IUnknown
, (void **)&pProxy
);
2410 ok_ole_success(hr
, CoUnmarshalInterface
);
2411 IStream_Release(pStream
);
2413 ok_more_than_one_lock();
2415 hr
= IUnknown_QueryInterface(pProxy
, &IID_IUnknown
, (LPVOID
*)&pOtherUnknown
);
2416 ok_ole_success(hr
, IUnknown_QueryInterface IID_IUnknown
);
2417 if (hr
== S_OK
) IUnknown_Release(pOtherUnknown
);
2419 hr
= IUnknown_QueryInterface(pProxy
, &IID_IClientSecurity
, (LPVOID
*)&pOtherUnknown
);
2420 ok_ole_success(hr
, IUnknown_QueryInterface IID_IClientSecurity
);
2421 if (hr
== S_OK
) IUnknown_Release(pOtherUnknown
);
2423 hr
= IUnknown_QueryInterface(pProxy
, &IID_IMultiQI
, (LPVOID
*)&pOtherUnknown
);
2424 ok_ole_success(hr
, IUnknown_QueryInterface IID_IMultiQI
);
2425 if (hr
== S_OK
) IUnknown_Release(pOtherUnknown
);
2427 hr
= IUnknown_QueryInterface(pProxy
, &IID_IMarshal
, (LPVOID
*)&pOtherUnknown
);
2428 ok_ole_success(hr
, IUnknown_QueryInterface IID_IMarshal
);
2429 if (hr
== S_OK
) IUnknown_Release(pOtherUnknown
);
2431 /* IMarshal2 is also supported on NT-based systems, but is pretty much
2432 * useless as it has no more methods over IMarshal that it inherits from. */
2434 IUnknown_Release(pProxy
);
2438 end_host_object(tid
, thread
);
2443 IUnknown IUnknown_iface
;
2447 static inline HeapUnknown
*impl_from_IUnknown(IUnknown
*iface
)
2449 return CONTAINING_RECORD(iface
, HeapUnknown
, IUnknown_iface
);
2452 static HRESULT WINAPI
HeapUnknown_QueryInterface(IUnknown
*iface
, REFIID riid
, void **ppv
)
2454 if (IsEqualIID(riid
, &IID_IUnknown
))
2456 IUnknown_AddRef(iface
);
2461 return E_NOINTERFACE
;
2464 static ULONG WINAPI
HeapUnknown_AddRef(IUnknown
*iface
)
2466 HeapUnknown
*This
= impl_from_IUnknown(iface
);
2467 return InterlockedIncrement((LONG
*)&This
->refs
);
2470 static ULONG WINAPI
HeapUnknown_Release(IUnknown
*iface
)
2472 HeapUnknown
*This
= impl_from_IUnknown(iface
);
2473 ULONG refs
= InterlockedDecrement((LONG
*)&This
->refs
);
2474 if (!refs
) HeapFree(GetProcessHeap(), 0, This
);
2478 static const IUnknownVtbl HeapUnknown_Vtbl
=
2480 HeapUnknown_QueryInterface
,
2485 static void test_proxybuffer(REFIID riid
)
2488 IPSFactoryBuffer
*psfb
;
2489 IRpcProxyBuffer
*proxy
;
2493 HeapUnknown
*pUnkOuter
= HeapAlloc(GetProcessHeap(), 0, sizeof(*pUnkOuter
));
2495 pUnkOuter
->IUnknown_iface
.lpVtbl
= &HeapUnknown_Vtbl
;
2496 pUnkOuter
->refs
= 1;
2498 hr
= CoGetPSClsid(riid
, &clsid
);
2499 ok_ole_success(hr
, CoGetPSClsid
);
2501 hr
= CoGetClassObject(&clsid
, CLSCTX_INPROC_SERVER
, NULL
, &IID_IPSFactoryBuffer
, (LPVOID
*)&psfb
);
2502 ok_ole_success(hr
, CoGetClassObject
);
2504 hr
= IPSFactoryBuffer_CreateProxy(psfb
, &pUnkOuter
->IUnknown_iface
, riid
, &proxy
, &lpvtbl
);
2505 ok_ole_success(hr
, IPSFactoryBuffer_CreateProxy
);
2506 ok(lpvtbl
!= NULL
, "IPSFactoryBuffer_CreateProxy succeeded, but returned a NULL vtable!\n");
2508 /* release our reference to the outer unknown object - the PS factory
2509 * buffer will have AddRef's it in the CreateProxy call */
2510 refs
= IUnknown_Release(&pUnkOuter
->IUnknown_iface
);
2511 ok(refs
== 1, "Ref count of outer unknown should have been 1 instead of %d\n", refs
);
2513 /* Not checking return, unreliable on native. Maybe it leaks references? */
2514 IPSFactoryBuffer_Release(psfb
);
2516 refs
= IUnknown_Release((IUnknown
*)lpvtbl
);
2517 ok(refs
== 0, "Ref-count leak of %d on IRpcProxyBuffer\n", refs
);
2519 refs
= IRpcProxyBuffer_Release(proxy
);
2520 ok(refs
== 0, "Ref-count leak of %d on IRpcProxyBuffer\n", refs
);
2523 static void test_stubbuffer(REFIID riid
)
2526 IPSFactoryBuffer
*psfb
;
2527 IRpcStubBuffer
*stub
;
2533 hr
= CoGetPSClsid(riid
, &clsid
);
2534 ok_ole_success(hr
, CoGetPSClsid
);
2536 hr
= CoGetClassObject(&clsid
, CLSCTX_INPROC_SERVER
, NULL
, &IID_IPSFactoryBuffer
, (LPVOID
*)&psfb
);
2537 ok_ole_success(hr
, CoGetClassObject
);
2539 hr
= IPSFactoryBuffer_CreateStub(psfb
, riid
, (IUnknown
*)&Test_ClassFactory
, &stub
);
2540 ok_ole_success(hr
, IPSFactoryBuffer_CreateStub
);
2542 /* Not checking return, unreliable on native. Maybe it leaks references? */
2543 IPSFactoryBuffer_Release(psfb
);
2545 ok_more_than_one_lock();
2547 IRpcStubBuffer_Disconnect(stub
);
2551 refs
= IRpcStubBuffer_Release(stub
);
2552 ok(refs
== 0, "Ref-count leak of %d on IRpcProxyBuffer\n", refs
);
2555 static HWND hwnd_app
;
2557 static HRESULT WINAPI
TestRE_IClassFactory_CreateInstance(
2558 LPCLASSFACTORY iface
,
2559 LPUNKNOWN pUnkOuter
,
2564 if (IsEqualIID(riid
, &IID_IWineTest
))
2566 BOOL ret
= SendMessageTimeoutA(hwnd_app
, WM_NULL
, 0, 0, SMTO_BLOCK
, 5000, &res
);
2567 ok(ret
, "Timed out sending a message to originating window during RPC call\n");
2573 static const IClassFactoryVtbl TestREClassFactory_Vtbl
=
2575 Test_IClassFactory_QueryInterface
,
2576 Test_IClassFactory_AddRef
,
2577 Test_IClassFactory_Release
,
2578 TestRE_IClassFactory_CreateInstance
,
2579 Test_IClassFactory_LockServer
2582 static IClassFactory TestRE_ClassFactory
= { &TestREClassFactory_Vtbl
};
2584 static LRESULT CALLBACK
window_proc(HWND hwnd
, UINT msg
, WPARAM wparam
, LPARAM lparam
)
2591 IStream
*pStream
= NULL
;
2592 IClassFactory
*proxy
= NULL
;
2599 hr
= CreateStreamOnHGlobal(NULL
, TRUE
, &pStream
);
2600 ok_ole_success(hr
, CreateStreamOnHGlobal
);
2601 tid
= start_host_object(pStream
, &IID_IClassFactory
, (IUnknown
*)&TestRE_ClassFactory
, MSHLFLAGS_NORMAL
, &thread
);
2603 ok_more_than_one_lock();
2605 IStream_Seek(pStream
, ullZero
, STREAM_SEEK_SET
, NULL
);
2606 hr
= CoUnmarshalInterface(pStream
, &IID_IClassFactory
, (void **)&proxy
);
2607 ok_ole_success(hr
, CoReleaseMarshalData
);
2608 IStream_Release(pStream
);
2610 ok_more_than_one_lock();
2612 /* note the use of the magic IID_IWineTest value to tell remote thread
2613 * to try to send a message back to us */
2614 hr
= IClassFactory_CreateInstance(proxy
, NULL
, &IID_IWineTest
, (void **)&object
);
2615 ok(hr
== S_FALSE
, "expected S_FALSE, got %d\n", hr
);
2617 IClassFactory_Release(proxy
);
2621 end_host_object(tid
, thread
);
2623 PostMessageA(hwnd
, WM_QUIT
, 0, 0);
2630 IStream
*pStream
= NULL
;
2631 IClassFactory
*proxy
= NULL
;
2638 hr
= CreateStreamOnHGlobal(NULL
, TRUE
, &pStream
);
2639 ok_ole_success(hr
, CreateStreamOnHGlobal
);
2640 tid
= start_host_object(pStream
, &IID_IClassFactory
, (IUnknown
*)&TestRE_ClassFactory
, MSHLFLAGS_NORMAL
, &thread
);
2642 ok_more_than_one_lock();
2644 IStream_Seek(pStream
, ullZero
, STREAM_SEEK_SET
, NULL
);
2645 hr
= CoUnmarshalInterface(pStream
, &IID_IClassFactory
, (void **)&proxy
);
2646 ok_ole_success(hr
, CoReleaseMarshalData
);
2647 IStream_Release(pStream
);
2649 ok_more_than_one_lock();
2651 /* post quit message before a doing a COM call to show that a pending
2652 * WM_QUIT message doesn't stop the call from succeeding */
2653 PostMessageA(hwnd
, WM_QUIT
, 0, 0);
2654 hr
= IClassFactory_CreateInstance(proxy
, NULL
, &IID_IUnknown
, (void **)&object
);
2655 ok(hr
== S_FALSE
, "IClassFactory_CreateInstance returned 0x%08x, expected S_FALSE\n", hr
);
2657 IClassFactory_Release(proxy
);
2661 end_host_object(tid
, thread
);
2668 IStream
*pStream
= NULL
;
2669 IClassFactory
*proxy
= NULL
;
2674 hr
= CreateStreamOnHGlobal(NULL
, TRUE
, &pStream
);
2675 ok_ole_success(hr
, CreateStreamOnHGlobal
);
2676 tid
= start_host_object(pStream
, &IID_IClassFactory
, (IUnknown
*)&Test_ClassFactory
, MSHLFLAGS_NORMAL
, &thread
);
2678 IStream_Seek(pStream
, ullZero
, STREAM_SEEK_SET
, NULL
);
2679 hr
= CoUnmarshalInterface(pStream
, &IID_IClassFactory
, (void **)&proxy
);
2680 ok_ole_success(hr
, CoReleaseMarshalData
);
2681 IStream_Release(pStream
);
2683 /* shows that COM calls executed during the processing of sent
2684 * messages should fail */
2685 hr
= IClassFactory_CreateInstance(proxy
, NULL
, &IID_IUnknown
, (void **)&object
);
2686 ok(hr
== RPC_E_CANTCALLOUT_ININPUTSYNCCALL
,
2687 "COM call during processing of sent message should return RPC_E_CANTCALLOUT_ININPUTSYNCCALL instead of 0x%08x\n", hr
);
2689 IClassFactory_Release(proxy
);
2691 end_host_object(tid
, thread
);
2698 return DefWindowProcA(hwnd
, msg
, wparam
, lparam
);
2702 static void register_test_window(void)
2706 memset(&wndclass
, 0, sizeof(wndclass
));
2707 wndclass
.lpfnWndProc
= window_proc
;
2708 wndclass
.lpszClassName
= "WineCOMTest";
2709 RegisterClassA(&wndclass
);
2712 static void test_message_reentrancy(void)
2716 hwnd_app
= CreateWindowA("WineCOMTest", NULL
, 0, CW_USEDEFAULT
, CW_USEDEFAULT
, CW_USEDEFAULT
, CW_USEDEFAULT
, NULL
, NULL
, NULL
, 0);
2717 ok(hwnd_app
!= NULL
, "Window creation failed\n");
2719 /* start message re-entrancy test */
2720 PostMessageA(hwnd_app
, WM_USER
, 0, 0);
2722 while (GetMessageA(&msg
, NULL
, 0, 0))
2724 TranslateMessage(&msg
);
2725 DispatchMessageA(&msg
);
2727 DestroyWindow(hwnd_app
);
2730 static HRESULT WINAPI
TestMsg_IClassFactory_CreateInstance(
2731 LPCLASSFACTORY iface
,
2732 LPUNKNOWN pUnkOuter
,
2737 SendMessageA(hwnd_app
, WM_USER
+2, 0, 0);
2741 static IClassFactoryVtbl TestMsgClassFactory_Vtbl
=
2743 Test_IClassFactory_QueryInterface
,
2744 Test_IClassFactory_AddRef
,
2745 Test_IClassFactory_Release
,
2746 TestMsg_IClassFactory_CreateInstance
,
2747 Test_IClassFactory_LockServer
2750 static IClassFactory TestMsg_ClassFactory
= { &TestMsgClassFactory_Vtbl
};
2752 static void test_call_from_message(void)
2757 IClassFactory
*proxy
;
2762 hwnd_app
= CreateWindowA("WineCOMTest", NULL
, 0, CW_USEDEFAULT
, CW_USEDEFAULT
, CW_USEDEFAULT
, CW_USEDEFAULT
, NULL
, NULL
, NULL
, 0);
2763 ok(hwnd_app
!= NULL
, "Window creation failed\n");
2765 hr
= CreateStreamOnHGlobal(NULL
, TRUE
, &pStream
);
2766 ok_ole_success(hr
, CreateStreamOnHGlobal
);
2767 tid
= start_host_object(pStream
, &IID_IClassFactory
, (IUnknown
*)&TestMsg_ClassFactory
, MSHLFLAGS_NORMAL
, &thread
);
2769 ok_more_than_one_lock();
2771 IStream_Seek(pStream
, ullZero
, STREAM_SEEK_SET
, NULL
);
2772 hr
= CoUnmarshalInterface(pStream
, &IID_IClassFactory
, (void **)&proxy
);
2773 ok_ole_success(hr
, CoReleaseMarshalData
);
2774 IStream_Release(pStream
);
2776 ok_more_than_one_lock();
2778 /* start message re-entrancy test */
2779 hr
= IClassFactory_CreateInstance(proxy
, NULL
, &IID_IUnknown
, (void **)&object
);
2780 ok_ole_success(hr
, IClassFactory_CreateInstance
);
2782 IClassFactory_Release(proxy
);
2786 end_host_object(tid
, thread
);
2788 while (GetMessageA(&msg
, NULL
, 0, 0))
2790 TranslateMessage(&msg
);
2791 DispatchMessageA(&msg
);
2793 DestroyWindow(hwnd_app
);
2796 static void test_WM_QUIT_handling(void)
2800 hwnd_app
= CreateWindowA("WineCOMTest", NULL
, 0, CW_USEDEFAULT
, CW_USEDEFAULT
, CW_USEDEFAULT
, CW_USEDEFAULT
, NULL
, NULL
, NULL
, 0);
2801 ok(hwnd_app
!= NULL
, "Window creation failed\n");
2803 /* start WM_QUIT handling test */
2804 PostMessageA(hwnd_app
, WM_USER
+1, 0, 0);
2806 while (GetMessageA(&msg
, NULL
, 0, 0))
2808 TranslateMessage(&msg
);
2809 DispatchMessageA(&msg
);
2813 static SIZE_T
round_global_size(SIZE_T size
)
2815 static SIZE_T global_size_alignment
= -1;
2816 if (global_size_alignment
== -1)
2818 void *p
= GlobalAlloc(GMEM_FIXED
, 1);
2819 global_size_alignment
= GlobalSize(p
);
2823 return ((size
+ global_size_alignment
- 1) & ~(global_size_alignment
- 1));
2826 static void test_freethreadedmarshaldata(IStream
*pStream
, MSHCTX mshctx
, void *ptr
, DWORD mshlflags
)
2833 hr
= GetHGlobalFromStream(pStream
, &hglobal
);
2834 ok_ole_success(hr
, GetHGlobalFromStream
);
2836 size
= GlobalSize(hglobal
);
2838 marshal_data
= GlobalLock(hglobal
);
2840 if (mshctx
== MSHCTX_INPROC
)
2842 DWORD expected_size
= round_global_size(3*sizeof(DWORD
) + sizeof(GUID
));
2843 ok(size
== expected_size
||
2844 broken(size
== (2*sizeof(DWORD
))) /* Win9x & NT4 */,
2845 "size should have been %d instead of %d\n", expected_size
, size
);
2847 ok(*(DWORD
*)marshal_data
== mshlflags
, "expected 0x%x, but got 0x%x for mshctx\n", mshlflags
, *(DWORD
*)marshal_data
);
2848 marshal_data
+= sizeof(DWORD
);
2849 ok(*(void **)marshal_data
== ptr
, "expected %p, but got %p for mshctx\n", ptr
, *(void **)marshal_data
);
2850 marshal_data
+= sizeof(void *);
2851 if (sizeof(void*) == 4 && size
>= 3*sizeof(DWORD
))
2853 ok(*(DWORD
*)marshal_data
== 0, "expected 0x0, but got 0x%x\n", *(DWORD
*)marshal_data
);
2854 marshal_data
+= sizeof(DWORD
);
2856 if (size
>= 3*sizeof(DWORD
) + sizeof(GUID
))
2858 trace("got guid data: %s\n", wine_dbgstr_guid((GUID
*)marshal_data
));
2863 ok(size
> sizeof(DWORD
), "size should have been > sizeof(DWORD), not %d\n", size
);
2864 ok(*(DWORD
*)marshal_data
== 0x574f454d /* MEOW */,
2865 "marshal data should be filled by standard marshal and start with MEOW signature\n");
2868 GlobalUnlock(hglobal
);
2871 static void test_freethreadedmarshaler(void)
2874 IUnknown
*pFTUnknown
;
2875 IMarshal
*pFTMarshal
;
2878 static const LARGE_INTEGER llZero
;
2881 hr
= CoCreateFreeThreadedMarshaler(NULL
, &pFTUnknown
);
2882 ok_ole_success(hr
, CoCreateFreeThreadedMarshaler
);
2883 hr
= IUnknown_QueryInterface(pFTUnknown
, &IID_IMarshal
, (void **)&pFTMarshal
);
2884 ok_ole_success(hr
, IUnknown_QueryInterface
);
2885 IUnknown_Release(pFTUnknown
);
2887 hr
= CreateStreamOnHGlobal(NULL
, TRUE
, &pStream
);
2888 ok_ole_success(hr
, CreateStreamOnHGlobal
);
2890 /* inproc normal marshaling */
2892 hr
= IMarshal_MarshalInterface(pFTMarshal
, pStream
, &IID_IClassFactory
,
2893 &Test_ClassFactory
, MSHCTX_INPROC
, NULL
, MSHLFLAGS_NORMAL
);
2894 ok_ole_success(hr
, IMarshal_MarshalInterface
);
2896 ok_more_than_one_lock();
2898 test_freethreadedmarshaldata(pStream
, MSHCTX_INPROC
, &Test_ClassFactory
, MSHLFLAGS_NORMAL
);
2900 IStream_Seek(pStream
, llZero
, STREAM_SEEK_SET
, NULL
);
2901 hr
= IMarshal_UnmarshalInterface(pFTMarshal
, pStream
, &IID_IUnknown
, (void **)&pProxy
);
2902 ok_ole_success(hr
, IMarshal_UnmarshalInterface
);
2904 IUnknown_Release(pProxy
);
2908 /* native doesn't allow us to unmarshal or release the stream data,
2909 * presumably because it wants us to call CoMarshalInterface instead */
2912 /* local normal marshaling */
2914 IStream_Seek(pStream
, llZero
, STREAM_SEEK_SET
, NULL
);
2915 hr
= IMarshal_MarshalInterface(pFTMarshal
, pStream
, &IID_IClassFactory
, &Test_ClassFactory
, MSHCTX_LOCAL
, NULL
, MSHLFLAGS_NORMAL
);
2916 ok_ole_success(hr
, IMarshal_MarshalInterface
);
2918 ok_more_than_one_lock();
2920 test_freethreadedmarshaldata(pStream
, MSHCTX_LOCAL
, &Test_ClassFactory
, MSHLFLAGS_NORMAL
);
2922 IStream_Seek(pStream
, llZero
, STREAM_SEEK_SET
, NULL
);
2923 hr
= IMarshal_ReleaseMarshalData(pFTMarshal
, pStream
);
2924 ok_ole_success(hr
, IMarshal_ReleaseMarshalData
);
2929 /* inproc table-strong marshaling */
2931 IStream_Seek(pStream
, llZero
, STREAM_SEEK_SET
, NULL
);
2932 hr
= IMarshal_MarshalInterface(pFTMarshal
, pStream
, &IID_IClassFactory
,
2933 (IUnknown
*)&Test_ClassFactory
, MSHCTX_INPROC
, (void *)0xdeadbeef,
2934 MSHLFLAGS_TABLESTRONG
);
2935 ok_ole_success(hr
, IMarshal_MarshalInterface
);
2937 ok_more_than_one_lock();
2939 test_freethreadedmarshaldata(pStream
, MSHCTX_INPROC
, &Test_ClassFactory
, MSHLFLAGS_TABLESTRONG
);
2941 IStream_Seek(pStream
, llZero
, STREAM_SEEK_SET
, NULL
);
2942 hr
= IMarshal_UnmarshalInterface(pFTMarshal
, pStream
, &IID_IUnknown
, (void **)&pProxy
);
2943 ok_ole_success(hr
, IMarshal_UnmarshalInterface
);
2945 IUnknown_Release(pProxy
);
2947 ok_more_than_one_lock();
2949 IStream_Seek(pStream
, llZero
, STREAM_SEEK_SET
, NULL
);
2950 hr
= IMarshal_ReleaseMarshalData(pFTMarshal
, pStream
);
2951 ok_ole_success(hr
, IMarshal_ReleaseMarshalData
);
2955 /* inproc table-weak marshaling */
2957 IStream_Seek(pStream
, llZero
, STREAM_SEEK_SET
, NULL
);
2958 hr
= IMarshal_MarshalInterface(pFTMarshal
, pStream
, &IID_IClassFactory
,
2959 (IUnknown
*)&Test_ClassFactory
, MSHCTX_INPROC
, (void *)0xdeadbeef,
2960 MSHLFLAGS_TABLEWEAK
);
2961 ok_ole_success(hr
, IMarshal_MarshalInterface
);
2965 test_freethreadedmarshaldata(pStream
, MSHCTX_INPROC
, &Test_ClassFactory
, MSHLFLAGS_TABLEWEAK
);
2967 IStream_Seek(pStream
, llZero
, STREAM_SEEK_SET
, NULL
);
2968 hr
= IMarshal_UnmarshalInterface(pFTMarshal
, pStream
, &IID_IUnknown
, (void **)&pProxy
);
2969 ok_ole_success(hr
, IMarshal_UnmarshalInterface
);
2971 ok_more_than_one_lock();
2973 IUnknown_Release(pProxy
);
2977 /* inproc normal marshaling (for extraordinary cases) */
2979 IStream_Seek(pStream
, llZero
, STREAM_SEEK_SET
, NULL
);
2980 hr
= IMarshal_MarshalInterface(pFTMarshal
, pStream
, &IID_IClassFactory
,
2981 &Test_ClassFactory
, MSHCTX_INPROC
, NULL
, MSHLFLAGS_NORMAL
);
2982 ok_ole_success(hr
, IMarshal_MarshalInterface
);
2984 ok_more_than_one_lock();
2986 /* this call shows that DisconnectObject does nothing */
2987 hr
= IMarshal_DisconnectObject(pFTMarshal
, 0);
2988 ok_ole_success(hr
, IMarshal_DisconnectObject
);
2990 ok_more_than_one_lock();
2992 IStream_Seek(pStream
, llZero
, STREAM_SEEK_SET
, NULL
);
2993 hr
= IMarshal_ReleaseMarshalData(pFTMarshal
, pStream
);
2994 ok_ole_success(hr
, IMarshal_ReleaseMarshalData
);
2998 /* doesn't enforce marshaling rules here and allows us to unmarshal the
2999 * interface, even though it was freed above */
3000 IStream_Seek(pStream
, llZero
, STREAM_SEEK_SET
, NULL
);
3001 hr
= IMarshal_UnmarshalInterface(pFTMarshal
, pStream
, &IID_IUnknown
, (void **)&pProxy
);
3002 ok_ole_success(hr
, IMarshal_UnmarshalInterface
);
3006 IStream_Release(pStream
);
3007 IMarshal_Release(pFTMarshal
);
3010 static HRESULT
reg_unreg_wine_test_class(BOOL Register
)
3016 DWORD dwDisposition
;
3019 hr
= StringFromCLSID(&CLSID_WineTest
, &pszClsid
);
3020 ok_ole_success(hr
, "StringFromCLSID");
3021 strcpy(buffer
, "CLSID\\");
3022 WideCharToMultiByte(CP_ACP
, 0, pszClsid
, -1, buffer
+ strlen(buffer
), sizeof(buffer
) - strlen(buffer
), NULL
, NULL
);
3023 CoTaskMemFree(pszClsid
);
3024 strcat(buffer
, "\\InprocHandler32");
3027 error
= RegCreateKeyExA(HKEY_CLASSES_ROOT
, buffer
, 0, NULL
, 0, KEY_SET_VALUE
, NULL
, &hkey
, &dwDisposition
);
3028 if (error
== ERROR_ACCESS_DENIED
)
3030 skip("Not authorized to modify the Classes key\n");
3033 ok(error
== ERROR_SUCCESS
, "RegCreateKeyEx failed with error %d\n", error
);
3034 if (error
!= ERROR_SUCCESS
) hr
= E_FAIL
;
3035 error
= RegSetValueExA(hkey
, NULL
, 0, REG_SZ
, (const unsigned char *)"\"ole32.dll\"", strlen("\"ole32.dll\"") + 1);
3036 ok(error
== ERROR_SUCCESS
, "RegSetValueEx failed with error %d\n", error
);
3037 if (error
!= ERROR_SUCCESS
) hr
= E_FAIL
;
3042 RegDeleteKeyA(HKEY_CLASSES_ROOT
, buffer
);
3043 *strrchr(buffer
, '\\') = '\0';
3044 RegDeleteKeyA(HKEY_CLASSES_ROOT
, buffer
);
3049 static void test_inproc_handler(void)
3055 if (FAILED(reg_unreg_wine_test_class(TRUE
)))
3058 hr
= CoCreateInstance(&CLSID_WineTest
, NULL
, CLSCTX_INPROC_HANDLER
, &IID_IUnknown
, (void **)&pObject
);
3059 ok_ole_success(hr
, "CoCreateInstance");
3063 hr
= IUnknown_QueryInterface(pObject
, &IID_IWineTest
, (void **)&pObject2
);
3064 ok(hr
== E_NOINTERFACE
, "IUnknown_QueryInterface on handler for invalid interface returned 0x%08x instead of E_NOINTERFACE\n", hr
);
3066 /* it's a handler as it supports IOleObject */
3067 hr
= IUnknown_QueryInterface(pObject
, &IID_IOleObject
, (void **)&pObject2
);
3068 ok_ole_success(hr
, "IUnknown_QueryInterface(&IID_IOleObject)");
3069 IUnknown_Release(pObject2
);
3071 IUnknown_Release(pObject
);
3074 reg_unreg_wine_test_class(FALSE
);
3077 static HRESULT WINAPI
Test_SMI_QueryInterface(
3078 IStdMarshalInfo
*iface
,
3082 if (ppvObj
== NULL
) return E_POINTER
;
3084 if (IsEqualGUID(riid
, &IID_IUnknown
) ||
3085 IsEqualGUID(riid
, &IID_IStdMarshalInfo
))
3088 IStdMarshalInfo_AddRef(iface
);
3092 return E_NOINTERFACE
;
3095 static ULONG WINAPI
Test_SMI_AddRef(IStdMarshalInfo
*iface
)
3098 return 2; /* non-heap-based object */
3101 static ULONG WINAPI
Test_SMI_Release(IStdMarshalInfo
*iface
)
3104 return 1; /* non-heap-based object */
3107 static HRESULT WINAPI
Test_SMI_GetClassForHandler(
3108 IStdMarshalInfo
*iface
,
3109 DWORD dwDestContext
,
3110 void *pvDestContext
,
3113 *pClsid
= CLSID_WineTest
;
3117 static const IStdMarshalInfoVtbl Test_SMI_Vtbl
=
3119 Test_SMI_QueryInterface
,
3122 Test_SMI_GetClassForHandler
3125 static IStdMarshalInfo Test_SMI
= {&Test_SMI_Vtbl
};
3127 static void test_handler_marshaling(void)
3130 IStream
*pStream
= NULL
;
3131 IUnknown
*pProxy
= NULL
;
3135 static const LARGE_INTEGER ullZero
;
3137 if (FAILED(reg_unreg_wine_test_class(TRUE
)))
3141 hr
= CreateStreamOnHGlobal(NULL
, TRUE
, &pStream
);
3142 ok_ole_success(hr
, "CreateStreamOnHGlobal");
3143 tid
= start_host_object(pStream
, &IID_IUnknown
, (IUnknown
*)&Test_SMI
, MSHLFLAGS_NORMAL
, &thread
);
3145 ok_more_than_one_lock();
3147 IStream_Seek(pStream
, ullZero
, STREAM_SEEK_SET
, NULL
);
3148 hr
= CoUnmarshalInterface(pStream
, &IID_IUnknown
, (void **)&pProxy
);
3149 ok_ole_success(hr
, "CoUnmarshalInterface");
3150 IStream_Release(pStream
);
3154 ok_more_than_one_lock();
3156 hr
= IUnknown_QueryInterface(pProxy
, &IID_IWineTest
, (void **)&pObject
);
3157 ok(hr
== E_NOINTERFACE
, "IUnknown_QueryInterface with unknown IID should have returned E_NOINTERFACE instead of 0x%08x\n", hr
);
3159 /* it's a handler as it supports IOleObject */
3160 hr
= IUnknown_QueryInterface(pProxy
, &IID_IOleObject
, (void **)&pObject
);
3162 ok_ole_success(hr
, "IUnknown_QueryInterface(&IID_IOleObject)");
3163 if (SUCCEEDED(hr
)) IUnknown_Release(pObject
);
3165 IUnknown_Release(pProxy
);
3170 end_host_object(tid
, thread
);
3171 reg_unreg_wine_test_class(FALSE
);
3173 /* FIXME: test IPersist interface has the same effect as IStdMarshalInfo */
3177 static void test_client_security(void)
3180 IStream
*pStream
= NULL
;
3181 IClassFactory
*pProxy
= NULL
;
3182 IUnknown
*pProxy2
= NULL
;
3183 IUnknown
*pUnknown1
= NULL
;
3184 IUnknown
*pUnknown2
= NULL
;
3185 IClientSecurity
*pCliSec
= NULL
;
3189 static const LARGE_INTEGER ullZero
;
3192 OLECHAR
*pServerPrincName
;
3196 DWORD dwCapabilities
;
3201 hr
= CreateStreamOnHGlobal(NULL
, TRUE
, &pStream
);
3202 ok_ole_success(hr
, "CreateStreamOnHGlobal");
3203 tid
= start_host_object(pStream
, &IID_IClassFactory
, (IUnknown
*)&Test_ClassFactory
, MSHLFLAGS_NORMAL
, &thread
);
3205 IStream_Seek(pStream
, ullZero
, STREAM_SEEK_SET
, NULL
);
3206 hr
= CoUnmarshalInterface(pStream
, &IID_IClassFactory
, (void **)&pProxy
);
3207 ok_ole_success(hr
, "CoUnmarshalInterface");
3208 IStream_Release(pStream
);
3210 hr
= IClassFactory_QueryInterface(pProxy
, &IID_IUnknown
, (LPVOID
*)&pUnknown1
);
3211 ok_ole_success(hr
, "IUnknown_QueryInterface IID_IUnknown");
3213 hr
= IClassFactory_QueryInterface(pProxy
, &IID_IRemUnknown
, (LPVOID
*)&pProxy2
);
3214 ok_ole_success(hr
, "IUnknown_QueryInterface IID_IStream");
3216 hr
= IUnknown_QueryInterface(pProxy2
, &IID_IUnknown
, (LPVOID
*)&pUnknown2
);
3217 ok_ole_success(hr
, "IUnknown_QueryInterface IID_IUnknown");
3219 ok(pUnknown1
== pUnknown2
, "both proxy's IUnknowns should be the same - %p, %p\n", pUnknown1
, pUnknown2
);
3221 hr
= IClassFactory_QueryInterface(pProxy
, &IID_IMarshal
, (LPVOID
*)&pMarshal
);
3222 ok_ole_success(hr
, "IUnknown_QueryInterface IID_IMarshal");
3224 hr
= IClassFactory_QueryInterface(pProxy
, &IID_IClientSecurity
, (LPVOID
*)&pCliSec
);
3225 ok_ole_success(hr
, "IUnknown_QueryInterface IID_IClientSecurity");
3227 hr
= IClientSecurity_QueryBlanket(pCliSec
, (IUnknown
*)pProxy
, NULL
, NULL
, NULL
, NULL
, NULL
, NULL
, NULL
);
3228 todo_wine
ok_ole_success(hr
, "IClientSecurity_QueryBlanket (all NULLs)");
3230 hr
= IClientSecurity_QueryBlanket(pCliSec
, (IUnknown
*)pMarshal
, NULL
, NULL
, NULL
, NULL
, NULL
, NULL
, NULL
);
3231 todo_wine
ok(hr
== E_NOINTERFACE
, "IClientSecurity_QueryBlanket with local interface should have returned E_NOINTERFACE instead of 0x%08x\n", hr
);
3233 hr
= IClientSecurity_QueryBlanket(pCliSec
, (IUnknown
*)pProxy
, &dwAuthnSvc
, &dwAuthzSvc
, &pServerPrincName
, &dwAuthnLevel
, &dwImpLevel
, &pAuthInfo
, &dwCapabilities
);
3234 todo_wine
ok_ole_success(hr
, "IClientSecurity_QueryBlanket");
3236 hr
= IClientSecurity_SetBlanket(pCliSec
, (IUnknown
*)pProxy
, dwAuthnSvc
, dwAuthzSvc
, pServerPrincName
, dwAuthnLevel
, RPC_C_IMP_LEVEL_IMPERSONATE
, pAuthInfo
, dwCapabilities
);
3237 todo_wine
ok_ole_success(hr
, "IClientSecurity_SetBlanket");
3239 hr
= IClassFactory_CreateInstance(pProxy
, NULL
, &IID_IWineTest
, &pv
);
3240 ok(hr
== E_NOINTERFACE
, "COM call should have succeeded instead of returning 0x%08x\n", hr
);
3242 hr
= IClientSecurity_SetBlanket(pCliSec
, (IUnknown
*)pMarshal
, dwAuthnSvc
, dwAuthzSvc
, pServerPrincName
, dwAuthnLevel
, dwImpLevel
, pAuthInfo
, dwCapabilities
);
3243 todo_wine
ok(hr
== E_NOINTERFACE
, "IClientSecurity_SetBlanket with local interface should have returned E_NOINTERFACE instead of 0x%08x\n", hr
);
3245 hr
= IClientSecurity_SetBlanket(pCliSec
, (IUnknown
*)pProxy
, 0xdeadbeef, dwAuthzSvc
, pServerPrincName
, dwAuthnLevel
, dwImpLevel
, pAuthInfo
, dwCapabilities
);
3246 todo_wine
ok(hr
== E_INVALIDARG
, "IClientSecurity_SetBlanke with invalid dwAuthnSvc should have returned E_INVALIDARG instead of 0x%08x\n", hr
);
3248 CoTaskMemFree(pServerPrincName
);
3250 hr
= IClientSecurity_QueryBlanket(pCliSec
, pUnknown1
, &dwAuthnSvc
, &dwAuthzSvc
, &pServerPrincName
, &dwAuthnLevel
, &dwImpLevel
, &pAuthInfo
, &dwCapabilities
);
3251 todo_wine
ok_ole_success(hr
, "IClientSecurity_QueryBlanket(IUnknown)");
3253 CoTaskMemFree(pServerPrincName
);
3255 IClassFactory_Release(pProxy
);
3256 IUnknown_Release(pProxy2
);
3257 IUnknown_Release(pUnknown1
);
3258 IUnknown_Release(pUnknown2
);
3259 IMarshal_Release(pMarshal
);
3260 IClientSecurity_Release(pCliSec
);
3262 end_host_object(tid
, thread
);
3265 static HANDLE heventShutdown
;
3267 static void LockModuleOOP(void)
3269 InterlockedIncrement(&cLocks
); /* for test purposes only */
3270 CoAddRefServerProcess();
3273 static void UnlockModuleOOP(void)
3275 InterlockedDecrement(&cLocks
); /* for test purposes only */
3276 if (!CoReleaseServerProcess())
3277 SetEvent(heventShutdown
);
3280 static HWND hwnd_app
;
3284 IPersist IPersist_iface
; /* a nice short interface */
3287 static HRESULT WINAPI
local_server_QueryInterface(IPersist
*iface
, REFIID iid
, void **obj
)
3291 if (IsEqualGUID(iid
, &IID_IUnknown
) ||
3292 IsEqualGUID(iid
, &IID_IPersist
))
3297 IPersist_AddRef(iface
);
3300 return E_NOINTERFACE
;
3303 static ULONG WINAPI
local_server_AddRef(IPersist
*iface
)
3308 static ULONG WINAPI
local_server_Release(IPersist
*iface
)
3313 static HRESULT WINAPI
local_server_GetClassID(IPersist
*iface
, CLSID
*clsid
)
3317 *clsid
= IID_IUnknown
;
3319 /* Test calling CoDisconnectObject within a COM call */
3320 hr
= CoDisconnectObject((IUnknown
*)iface
, 0);
3321 ok(hr
== S_OK
, "got %08x\n", hr
);
3323 /* Initialize and uninitialize the apartment to show that we
3324 * remain in the autojoined mta */
3325 hr
= pCoInitializeEx( NULL
, COINIT_MULTITHREADED
);
3326 ok( hr
== S_FALSE
, "got %08x\n", hr
);
3332 static const IPersistVtbl local_server_persist_vtbl
=
3334 local_server_QueryInterface
,
3335 local_server_AddRef
,
3336 local_server_Release
,
3337 local_server_GetClassID
3340 struct local_server local_server_class
=
3342 {&local_server_persist_vtbl
}
3345 static HRESULT WINAPI
TestOOP_IClassFactory_QueryInterface(
3346 LPCLASSFACTORY iface
,
3350 if (ppvObj
== NULL
) return E_POINTER
;
3352 if (IsEqualGUID(riid
, &IID_IUnknown
) ||
3353 IsEqualGUID(riid
, &IID_IClassFactory
))
3356 IClassFactory_AddRef(iface
);
3360 return E_NOINTERFACE
;
3363 static ULONG WINAPI
TestOOP_IClassFactory_AddRef(LPCLASSFACTORY iface
)
3365 return 2; /* non-heap-based object */
3368 static ULONG WINAPI
TestOOP_IClassFactory_Release(LPCLASSFACTORY iface
)
3370 return 1; /* non-heap-based object */
3373 static HRESULT WINAPI
TestOOP_IClassFactory_CreateInstance(
3374 LPCLASSFACTORY iface
,
3375 LPUNKNOWN pUnkOuter
,
3379 IPersist
*persist
= &local_server_class
.IPersist_iface
;
3381 IPersist_AddRef( persist
);
3382 hr
= IPersist_QueryInterface( persist
, riid
, ppvObj
);
3383 IPersist_Release( persist
);
3387 static HRESULT WINAPI
TestOOP_IClassFactory_LockServer(
3388 LPCLASSFACTORY iface
,
3398 static const IClassFactoryVtbl TestClassFactoryOOP_Vtbl
=
3400 TestOOP_IClassFactory_QueryInterface
,
3401 TestOOP_IClassFactory_AddRef
,
3402 TestOOP_IClassFactory_Release
,
3403 TestOOP_IClassFactory_CreateInstance
,
3404 TestOOP_IClassFactory_LockServer
3407 static IClassFactory TestOOP_ClassFactory
= { &TestClassFactoryOOP_Vtbl
};
3409 static void test_register_local_server(void)
3417 heventShutdown
= CreateEventA(NULL
, TRUE
, FALSE
, NULL
);
3418 ready_event
= CreateEventA(NULL
, FALSE
, FALSE
, "Wine COM Test Ready Event");
3419 handles
[0] = CreateEventA(NULL
, FALSE
, FALSE
, "Wine COM Test Quit Event");
3420 handles
[1] = CreateEventA(NULL
, FALSE
, FALSE
, "Wine COM Test Repeat Event");
3423 hr
= CoRegisterClassObject(&CLSID_WineOOPTest
, (IUnknown
*)&TestOOP_ClassFactory
,
3424 CLSCTX_LOCAL_SERVER
, REGCLS_SINGLEUSE
, &cookie
);
3425 ok_ole_success(hr
, CoRegisterClassObject
);
3427 SetEvent(ready_event
);
3431 wait
= MsgWaitForMultipleObjects(2, handles
, FALSE
, 30000, QS_ALLINPUT
);
3432 if (wait
== WAIT_OBJECT_0
+2)
3436 if (PeekMessageA(&msg
, NULL
, 0, 0, PM_REMOVE
))
3438 trace("Message 0x%x\n", msg
.message
);
3439 TranslateMessage(&msg
);
3440 DispatchMessageA(&msg
);
3443 else if (wait
== WAIT_OBJECT_0
+1)
3445 hr
= CoRevokeClassObject(cookie
);
3446 ok_ole_success(hr
, CoRevokeClassObject
);
3450 while (wait
== WAIT_OBJECT_0
+2);
3452 ok( wait
== WAIT_OBJECT_0
, "quit event wait timed out\n" );
3453 hr
= CoRevokeClassObject(cookie
);
3454 ok_ole_success(hr
, CoRevokeClassObject
);
3455 CloseHandle(handles
[0]);
3456 CloseHandle(handles
[1]);
3459 static HANDLE
create_target_process(const char *arg
)
3462 char cmdline
[MAX_PATH
];
3464 PROCESS_INFORMATION pi
;
3465 STARTUPINFOA si
= { 0 };
3470 winetest_get_mainargs( &argv
);
3471 sprintf(cmdline
, "\"%s\" %s %s", argv
[0], argv
[1], arg
);
3472 ret
= CreateProcessA(argv
[0], cmdline
, NULL
, NULL
, FALSE
, 0, NULL
, NULL
, &si
, &pi
);
3473 ok(ret
, "CreateProcess failed with error: %u\n", GetLastError());
3474 if (pi
.hThread
) CloseHandle(pi
.hThread
);
3478 /* tests functions commonly used by out of process COM servers */
3479 static void test_local_server(void)
3489 HANDLE repeat_event
;
3492 heventShutdown
= CreateEventA(NULL
, TRUE
, FALSE
, NULL
);
3496 /* Start the object suspended */
3497 hr
= CoRegisterClassObject(&CLSID_WineOOPTest
, (IUnknown
*)&TestOOP_ClassFactory
,
3498 CLSCTX_LOCAL_SERVER
, REGCLS_MULTIPLEUSE
| REGCLS_SUSPENDED
, &cookie
);
3499 ok_ole_success(hr
, CoRegisterClassObject
);
3501 /* ... and CoGetClassObject does not find it and fails when it looks for the
3502 * class in the registry */
3503 hr
= CoGetClassObject(&CLSID_WineOOPTest
, CLSCTX_INPROC_SERVER
,
3504 NULL
, &IID_IClassFactory
, (LPVOID
*)&cf
);
3505 ok(hr
== REGDB_E_CLASSNOTREG
|| /* NT */
3506 hr
== S_OK
/* Win9x */,
3507 "CoGetClassObject should have returned REGDB_E_CLASSNOTREG instead of 0x%08x\n", hr
);
3509 /* Resume the object suspended above ... */
3510 hr
= CoResumeClassObjects();
3511 ok_ole_success(hr
, CoResumeClassObjects
);
3513 /* ... and now it should succeed */
3514 hr
= CoGetClassObject(&CLSID_WineOOPTest
, CLSCTX_INPROC_SERVER
,
3515 NULL
, &IID_IClassFactory
, (LPVOID
*)&cf
);
3516 ok_ole_success(hr
, CoGetClassObject
);
3518 /* Now check the locking is working */
3519 /* NOTE: we are accessing the class directly, not through a proxy */
3523 hr
= IClassFactory_LockServer(cf
, TRUE
);
3524 ok_ole_success(hr
, IClassFactory_LockServer
);
3526 ok_more_than_one_lock();
3528 IClassFactory_LockServer(cf
, FALSE
);
3529 ok_ole_success(hr
, IClassFactory_LockServer
);
3533 IClassFactory_Release(cf
);
3535 /* wait for shutdown signal */
3536 ret
= WaitForSingleObject(heventShutdown
, 0);
3537 ok(ret
!= WAIT_TIMEOUT
, "Server didn't shut down\n");
3539 /* try to connect again after SCM has suspended registered class objects */
3540 hr
= CoGetClassObject(&CLSID_WineOOPTest
, CLSCTX_INPROC_SERVER
| CLSCTX_LOCAL_SERVER
, NULL
,
3541 &IID_IClassFactory
, (LPVOID
*)&cf
);
3542 ok(hr
== CO_E_SERVER_STOPPING
|| /* NT */
3543 hr
== REGDB_E_CLASSNOTREG
|| /* win2k */
3544 hr
== S_OK
/* Win9x */,
3545 "CoGetClassObject should have returned CO_E_SERVER_STOPPING or REGDB_E_CLASSNOTREG instead of 0x%08x\n", hr
);
3547 hr
= CoRevokeClassObject(cookie
);
3548 ok_ole_success(hr
, CoRevokeClassObject
);
3550 CloseHandle(heventShutdown
);
3552 process
= create_target_process("-Embedding");
3553 ok(process
!= NULL
, "couldn't start local server process, error was %d\n", GetLastError());
3555 ready_event
= CreateEventA(NULL
, FALSE
, FALSE
, "Wine COM Test Ready Event");
3556 ok( !WaitForSingleObject(ready_event
, 10000), "wait timed out\n" );
3558 hr
= CoCreateInstance(&CLSID_WineOOPTest
, NULL
, CLSCTX_LOCAL_SERVER
, &IID_IPersist
, (void **)&persist
);
3559 ok_ole_success(hr
, CoCreateInstance
);
3561 IPersist_Release(persist
);
3563 hr
= CoCreateInstance(&CLSID_WineOOPTest
, NULL
, CLSCTX_LOCAL_SERVER
, &IID_IPersist
, (void **)&persist
);
3564 ok(hr
== REGDB_E_CLASSNOTREG
, "Second CoCreateInstance on REGCLS_SINGLEUSE object should have failed\n");
3566 /* Re-register the class and try calling CoDisconnectObject from within a call to that object */
3567 repeat_event
= CreateEventA(NULL
, FALSE
, FALSE
, "Wine COM Test Repeat Event");
3568 SetEvent(repeat_event
);
3569 CloseHandle(repeat_event
);
3571 ok( !WaitForSingleObject(ready_event
, 10000), "wait timed out\n" );
3572 CloseHandle(ready_event
);
3574 hr
= CoCreateInstance(&CLSID_WineOOPTest
, NULL
, CLSCTX_LOCAL_SERVER
, &IID_IPersist
, (void **)&persist
);
3575 ok_ole_success(hr
, CoCreateInstance
);
3577 /* GetClassID will call CoDisconnectObject */
3578 IPersist_GetClassID(persist
, &clsid
);
3579 IPersist_Release(persist
);
3581 quit_event
= CreateEventA(NULL
, FALSE
, FALSE
, "Wine COM Test Quit Event");
3582 SetEvent(quit_event
);
3584 winetest_wait_child_process( process
);
3585 CloseHandle(quit_event
);
3586 CloseHandle(process
);
3592 IGlobalInterfaceTable
*git
;
3595 static DWORD CALLBACK
get_global_interface_proc(LPVOID pv
)
3598 struct git_params
*params
= pv
;
3601 hr
= IGlobalInterfaceTable_GetInterfaceFromGlobal(params
->git
, params
->cookie
, &IID_IClassFactory
, (void **)&cf
);
3602 ok(hr
== CO_E_NOTINITIALIZED
||
3603 broken(hr
== E_UNEXPECTED
) /* win2k */ ||
3604 broken(hr
== S_OK
) /* NT 4 */,
3605 "IGlobalInterfaceTable_GetInterfaceFromGlobal should have failed with error CO_E_NOTINITIALIZED or E_UNEXPECTED instead of 0x%08x\n",
3608 IClassFactory_Release(cf
);
3612 hr
= IGlobalInterfaceTable_GetInterfaceFromGlobal(params
->git
, params
->cookie
, &IID_IClassFactory
, (void **)&cf
);
3613 ok_ole_success(hr
, IGlobalInterfaceTable_GetInterfaceFromGlobal
);
3615 IClassFactory_Release(cf
);
3622 static void test_globalinterfacetable(void)
3625 IGlobalInterfaceTable
*git
;
3629 struct git_params params
;
3635 trace("test_globalinterfacetable\n");
3638 hr
= pDllGetClassObject(&CLSID_StdGlobalInterfaceTable
, &IID_IClassFactory
, (void**)&cf
);
3639 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3641 hr
= IClassFactory_QueryInterface(cf
, &IID_IGlobalInterfaceTable
, (void**)&object
);
3642 ok(hr
== E_NOINTERFACE
, "got 0x%08x\n", hr
);
3644 IClassFactory_Release(cf
);
3646 hr
= CoCreateInstance(&CLSID_StdGlobalInterfaceTable
, NULL
, CLSCTX_INPROC_SERVER
, &IID_IGlobalInterfaceTable
, (void **)&git
);
3647 ok_ole_success(hr
, CoCreateInstance
);
3649 ref
= IGlobalInterfaceTable_AddRef(git
);
3650 ok(ref
== 1, "ref=%d\n", ref
);
3651 ref
= IGlobalInterfaceTable_AddRef(git
);
3652 ok(ref
== 1, "ref=%d\n", ref
);
3654 ref
= IGlobalInterfaceTable_Release(git
);
3655 ok(ref
== 1, "ref=%d\n", ref
);
3656 ref
= IGlobalInterfaceTable_Release(git
);
3657 ok(ref
== 1, "ref=%d\n", ref
);
3659 hr
= IGlobalInterfaceTable_RegisterInterfaceInGlobal(git
, (IUnknown
*)&Test_ClassFactory
, &IID_IClassFactory
, &cookie
);
3660 ok_ole_success(hr
, IGlobalInterfaceTable_RegisterInterfaceInGlobal
);
3662 ok_more_than_one_lock();
3664 params
.cookie
= cookie
;
3666 /* note: params is on stack so we MUST wait for get_global_interface_proc
3667 * to exit before we can return */
3668 thread
= CreateThread(NULL
, 0, get_global_interface_proc
, ¶ms
, 0, &tid
);
3670 ret
= MsgWaitForMultipleObjects(1, &thread
, FALSE
, 10000, QS_ALLINPUT
);
3671 while (ret
== WAIT_OBJECT_0
+ 1)
3674 while (PeekMessageA(&msg
, NULL
, 0, 0, PM_REMOVE
))
3675 DispatchMessageA(&msg
);
3676 ret
= MsgWaitForMultipleObjects(1, &thread
, FALSE
, 10000, QS_ALLINPUT
);
3679 CloseHandle(thread
);
3681 /* test getting interface from global with different iid */
3682 hr
= IGlobalInterfaceTable_GetInterfaceFromGlobal(git
, cookie
, &IID_IUnknown
, (void **)&object
);
3683 ok_ole_success(hr
, IGlobalInterfaceTable_GetInterfaceFromGlobal
);
3684 IUnknown_Release(object
);
3686 /* test getting interface from global with same iid */
3687 hr
= IGlobalInterfaceTable_GetInterfaceFromGlobal(git
, cookie
, &IID_IClassFactory
, (void **)&object
);
3688 ok_ole_success(hr
, IGlobalInterfaceTable_GetInterfaceFromGlobal
);
3689 IUnknown_Release(object
);
3691 hr
= IGlobalInterfaceTable_RevokeInterfaceFromGlobal(git
, cookie
);
3692 ok_ole_success(hr
, IGlobalInterfaceTable_RevokeInterfaceFromGlobal
);
3696 IGlobalInterfaceTable_Release(git
);
3699 static void test_manualresetevent(void)
3701 ISynchronizeHandle
*sync_handle
;
3702 ISynchronize
*psync1
, *psync2
;
3708 hr
= CoCreateInstance(&CLSID_ManualResetEvent
, NULL
, CLSCTX_INPROC_SERVER
, &IID_IUnknown
, (void**)&punk
);
3709 ok(hr
== S_OK
, "Got 0x%08x\n", hr
);
3710 ok(!!punk
, "Got NULL.\n");
3711 IUnknown_Release(punk
);
3713 hr
= CoCreateInstance(&CLSID_ManualResetEvent
, NULL
, CLSCTX_INPROC_SERVER
, &IID_ISynchronize
, (void**)&psync1
);
3714 ok(hr
== S_OK
, "Got 0x%08x\n", hr
);
3715 ok(!!psync1
, "Got NULL.\n");
3717 hr
= ISynchronize_Wait(psync1
, 0, 5);
3718 ok(hr
== RPC_S_CALLPENDING
, "Got 0x%08x\n", hr
);
3720 hr
= ISynchronize_Reset(psync1
);
3721 ok(hr
== S_OK
, "Got 0x%08x\n", hr
);
3722 hr
= ISynchronize_Signal(psync1
);
3723 ok(hr
== S_OK
, "Got 0x%08x\n", hr
);
3724 hr
= ISynchronize_Wait(psync1
, 0, 5);
3725 ok(hr
== S_OK
, "Got 0x%08x\n", hr
);
3726 hr
= ISynchronize_Wait(psync1
, 0, 5);
3727 ok(hr
== S_OK
, "Got 0x%08x\n", hr
);
3728 hr
= ISynchronize_Reset(psync1
);
3729 ok(hr
== S_OK
, "Got 0x%08x\n", hr
);
3730 hr
= ISynchronize_Wait(psync1
, 0, 5);
3731 ok(hr
== RPC_S_CALLPENDING
, "Got 0x%08x\n", hr
);
3733 hr
= CoCreateInstance(&CLSID_ManualResetEvent
, NULL
, CLSCTX_INPROC_SERVER
, &IID_ISynchronize
, (void**)&psync2
);
3734 ok(hr
== S_OK
, "Got 0x%08x\n", hr
);
3735 ok(!!psync2
, "Got NULL.\n");
3736 ok(psync1
!= psync2
, "psync1 == psync2.\n");
3738 hr
= ISynchronize_QueryInterface(psync2
, &IID_ISynchronizeHandle
, (void**)&sync_handle
);
3739 ok(hr
== S_OK
, "QueryInterface(IID_ISynchronizeHandle) failed: %08x\n", hr
);
3742 hr
= ISynchronizeHandle_GetHandle(sync_handle
, &handle
);
3743 ok(hr
== S_OK
, "GetHandle failed: %08x\n", hr
);
3744 ok(handle
!= NULL
&& handle
!= INVALID_HANDLE_VALUE
, "handle = %p\n", handle
);
3746 ISynchronizeHandle_Release(sync_handle
);
3748 hr
= ISynchronize_Wait(psync2
, 0, 5);
3749 ok(hr
== RPC_S_CALLPENDING
, "Got 0x%08x\n", hr
);
3751 hr
= ISynchronize_Reset(psync1
);
3752 ok(hr
== S_OK
, "Got 0x%08x\n", hr
);
3753 hr
= ISynchronize_Reset(psync2
);
3754 ok(hr
== S_OK
, "Got 0x%08x\n", hr
);
3755 hr
= ISynchronize_Signal(psync1
);
3756 ok(hr
== S_OK
, "Got 0x%08x\n", hr
);
3757 hr
= ISynchronize_Wait(psync2
, 0, 5);
3758 ok(hr
== RPC_S_CALLPENDING
, "Got 0x%08x\n", hr
);
3760 ref
= ISynchronize_AddRef(psync1
);
3761 ok(ref
== 2, "Got ref: %d\n", ref
);
3762 ref
= ISynchronize_AddRef(psync1
);
3763 ok(ref
== 3, "Got ref: %d\n", ref
);
3764 ref
= ISynchronize_Release(psync1
);
3765 ok(ref
== 2, "Got nonzero ref: %d\n", ref
);
3766 ref
= ISynchronize_Release(psync2
);
3767 ok(!ref
, "Got nonzero ref: %d\n", ref
);
3768 ref
= ISynchronize_Release(psync1
);
3769 ok(ref
== 1, "Got nonzero ref: %d\n", ref
);
3770 ref
= ISynchronize_Release(psync1
);
3771 ok(!ref
, "Got nonzero ref: %d\n", ref
);
3774 static DWORD CALLBACK
implicit_mta_unmarshal_proc(void *param
)
3776 IStream
*stream
= param
;
3781 IStream_Seek(stream
, ullZero
, STREAM_SEEK_SET
, NULL
);
3782 hr
= CoUnmarshalInterface(stream
, &IID_IClassFactory
, (void **)&cf
);
3783 ok_ole_success(hr
, CoUnmarshalInterface
);
3785 hr
= IClassFactory_CreateInstance(cf
, NULL
, &IID_IUnknown
, (void **)&proxy
);
3786 ok_ole_success(hr
, IClassFactory_CreateInstance
);
3788 IUnknown_Release(proxy
);
3790 /* But if we initialize an STA in this apartment, it becomes the wrong one. */
3791 CoInitializeEx(NULL
, COINIT_APARTMENTTHREADED
);
3793 hr
= IClassFactory_CreateInstance(cf
, NULL
, &IID_IUnknown
, (void **)&proxy
);
3794 ok(hr
== RPC_E_WRONG_THREAD
, "got %#x\n", hr
);
3798 ok_more_than_one_lock();
3799 ok_non_zero_external_conn();
3801 IClassFactory_Release(cf
);
3804 ok_zero_external_conn();
3805 ok_last_release_closes(TRUE
);
3809 static DWORD CALLBACK
implicit_mta_use_proc(void *param
)
3811 IClassFactory
*cf
= param
;
3815 hr
= IClassFactory_CreateInstance(cf
, NULL
, &IID_IUnknown
, (void **)&proxy
);
3816 ok_ole_success(hr
, IClassFactory_CreateInstance
);
3818 IUnknown_Release(proxy
);
3820 /* But if we initialize an STA in this apartment, it becomes the wrong one. */
3821 CoInitializeEx(NULL
, COINIT_APARTMENTTHREADED
);
3823 hr
= IClassFactory_CreateInstance(cf
, NULL
, &IID_IUnknown
, (void **)&proxy
);
3824 ok(hr
== RPC_E_WRONG_THREAD
, "got %#x\n", hr
);
3830 struct implicit_mta_marshal_data
3837 static DWORD CALLBACK
implicit_mta_marshal_proc(void *param
)
3839 struct implicit_mta_marshal_data
*data
= param
;
3842 hr
= CoMarshalInterface(data
->stream
, &IID_IClassFactory
,
3843 (IUnknown
*)&Test_ClassFactory
, MSHCTX_INPROC
, NULL
, MSHLFLAGS_NORMAL
);
3844 ok_ole_success(hr
, CoMarshalInterface
);
3846 SetEvent(data
->start
);
3848 ok(!WaitForSingleObject(data
->stop
, 1000), "wait failed\n");
3852 static void test_implicit_mta(void)
3854 struct implicit_mta_marshal_data data
;
3855 HANDLE host_thread
, thread
;
3863 external_connections
= 0;
3865 CoInitializeEx(NULL
, COINIT_MULTITHREADED
);
3867 /* Firstly: we can unmarshal and use an object while in the implicit MTA. */
3868 hr
= CreateStreamOnHGlobal(NULL
, TRUE
, &stream
);
3869 ok_ole_success(hr
, CreateStreamOnHGlobal
);
3870 tid
= start_host_object(stream
, &IID_IClassFactory
, (IUnknown
*)&Test_ClassFactory
, MSHLFLAGS_NORMAL
, &host_thread
);
3872 ok_more_than_one_lock();
3873 ok_non_zero_external_conn();
3875 thread
= CreateThread(NULL
, 0, implicit_mta_unmarshal_proc
, stream
, 0, NULL
);
3876 ok(!WaitForSingleObject(thread
, 1000), "wait failed\n");
3877 CloseHandle(thread
);
3879 IStream_Release(stream
);
3880 end_host_object(tid
, host_thread
);
3882 /* Secondly: we can unmarshal an object into the real MTA and then use it
3883 * from the implicit MTA. */
3884 hr
= CreateStreamOnHGlobal(NULL
, TRUE
, &stream
);
3885 ok_ole_success(hr
, CreateStreamOnHGlobal
);
3886 tid
= start_host_object(stream
, &IID_IClassFactory
, (IUnknown
*)&Test_ClassFactory
, MSHLFLAGS_NORMAL
, &host_thread
);
3888 ok_more_than_one_lock();
3889 ok_non_zero_external_conn();
3891 IStream_Seek(stream
, ullZero
, STREAM_SEEK_SET
, NULL
);
3892 hr
= CoUnmarshalInterface(stream
, &IID_IClassFactory
, (void **)&cf
);
3893 ok_ole_success(hr
, CoUnmarshalInterface
);
3895 thread
= CreateThread(NULL
, 0, implicit_mta_use_proc
, cf
, 0, NULL
);
3896 ok(!WaitForSingleObject(thread
, 1000), "wait failed\n");
3897 CloseHandle(thread
);
3899 IClassFactory_Release(cf
);
3900 IStream_Release(stream
);
3903 ok_non_zero_external_conn();
3904 ok_last_release_closes(TRUE
);
3906 end_host_object(tid
, host_thread
);
3908 /* Thirdly: we can marshal an object from the implicit MTA and then
3909 * unmarshal it into the real one. */
3910 data
.start
= CreateEventA(NULL
, FALSE
, FALSE
, NULL
);
3911 data
.stop
= CreateEventA(NULL
, FALSE
, FALSE
, NULL
);
3913 hr
= CreateStreamOnHGlobal(NULL
, TRUE
, &data
.stream
);
3914 ok_ole_success(hr
, CreateStreamOnHGlobal
);
3916 thread
= CreateThread(NULL
, 0, implicit_mta_marshal_proc
, &data
, 0, NULL
);
3917 ok(!WaitForSingleObject(data
.start
, 1000), "wait failed\n");
3919 IStream_Seek(data
.stream
, ullZero
, STREAM_SEEK_SET
, NULL
);
3920 hr
= CoUnmarshalInterface(data
.stream
, &IID_IClassFactory
, (void **)&cf
);
3921 ok_ole_success(hr
, CoUnmarshalInterface
);
3923 hr
= IClassFactory_CreateInstance(cf
, NULL
, &IID_IUnknown
, (void **)&proxy
);
3924 ok_ole_success(hr
, IClassFactory_CreateInstance
);
3926 IUnknown_Release(proxy
);
3928 SetEvent(data
.stop
);
3929 ok(!WaitForSingleObject(thread
, 1000), "wait failed\n");
3930 CloseHandle(thread
);
3932 IStream_Release(data
.stream
);
3937 static const char *debugstr_iid(REFIID riid
)
3939 static char name
[256];
3943 LONG name_size
= sizeof(name
);
3944 StringFromGUID2(riid
, bufferW
, ARRAY_SIZE(bufferW
));
3945 WideCharToMultiByte(CP_ACP
, 0, bufferW
, ARRAY_SIZE(bufferW
), buffer
, sizeof(buffer
), NULL
, NULL
);
3946 if (RegOpenKeyExA(HKEY_CLASSES_ROOT
, "Interface", 0, KEY_QUERY_VALUE
, &hkeyInterface
) != ERROR_SUCCESS
)
3948 memcpy(name
, buffer
, sizeof(buffer
));
3951 if (RegQueryValueA(hkeyInterface
, buffer
, name
, &name_size
) != ERROR_SUCCESS
)
3953 memcpy(name
, buffer
, sizeof(buffer
));
3956 RegCloseKey(hkeyInterface
);
3961 static HRESULT WINAPI
TestChannelHook_QueryInterface(IChannelHook
*iface
, REFIID riid
, void **ppv
)
3963 if (IsEqualIID(riid
, &IID_IUnknown
) || IsEqualIID(riid
, &IID_IChannelHook
))
3966 IChannelHook_AddRef(iface
);
3971 return E_NOINTERFACE
;
3974 static ULONG WINAPI
TestChannelHook_AddRef(IChannelHook
*iface
)
3979 static ULONG WINAPI
TestChannelHook_Release(IChannelHook
*iface
)
3984 static BOOL new_hook_struct
;
3985 static int method
, server_tid
;
3986 static GUID causality
;
3988 struct new_hook_info
3997 static void WINAPI
TestChannelHook_ClientGetSize(
3998 IChannelHook
*iface
,
4003 SChannelHookCallInfo
*info
= (SChannelHookCallInfo
*)riid
;
4004 trace("TestChannelHook_ClientGetSize\n");
4005 trace("\t%s\n", debugstr_iid(riid
));
4006 if (info
->cbSize
!= sizeof(*info
))
4007 new_hook_struct
= TRUE
;
4009 if (!new_hook_struct
)
4011 ok(info
->cbSize
== sizeof(*info
), "cbSize was %d instead of %d\n", info
->cbSize
, (int)sizeof(*info
));
4012 ok(info
->dwServerPid
== GetCurrentProcessId(), "dwServerPid was 0x%x instead of 0x%x\n", info
->dwServerPid
, GetCurrentProcessId());
4013 ok(info
->iMethod
== method
, "iMethod was %d should be %d\n", info
->iMethod
, method
);
4014 ok(!info
->pObject
, "pObject should be NULL\n");
4016 causality
= info
->uCausality
;
4018 ok(IsEqualGUID(&info
->uCausality
, &causality
), "causality wasn't correct\n");
4022 struct new_hook_info
*new_info
= (struct new_hook_info
*)riid
;
4023 ok(new_info
->server_pid
== GetCurrentProcessId(), "server pid was 0x%x instead of 0x%x\n", new_info
->server_pid
,
4024 GetCurrentProcessId());
4025 ok(new_info
->server_tid
== server_tid
, "server tid was 0x%x instead of 0x%x\n", new_info
->server_tid
,
4027 ok(new_info
->method
== method
, "method was %d instead of %d\n", new_info
->method
, method
);
4029 causality
= new_info
->causality
;
4031 ok(IsEqualGUID(&new_info
->causality
, &causality
), "causality wasn't correct\n");
4034 ok(IsEqualGUID(uExtent
, &EXTENTID_WineTest
), "uExtent wasn't correct\n");
4039 static void WINAPI
TestChannelHook_ClientFillBuffer(
4040 IChannelHook
*iface
,
4046 SChannelHookCallInfo
*info
= (SChannelHookCallInfo
*)riid
;
4047 trace("TestChannelHook_ClientFillBuffer\n");
4049 if (!new_hook_struct
)
4051 ok(info
->cbSize
== sizeof(*info
), "cbSize was %d instead of %d\n", info
->cbSize
, (int)sizeof(*info
));
4052 ok(info
->dwServerPid
== GetCurrentProcessId(), "dwServerPid was 0x%x instead of 0x%x\n", info
->dwServerPid
, GetCurrentProcessId());
4053 ok(info
->iMethod
== method
, "iMethod was %d should be %d\n", info
->iMethod
, method
);
4054 ok(!info
->pObject
, "pObject should be NULL\n");
4055 ok(IsEqualGUID(&info
->uCausality
, &causality
), "causality wasn't correct\n");
4059 struct new_hook_info
*new_info
= (struct new_hook_info
*)riid
;
4060 ok(new_info
->server_pid
== GetCurrentProcessId(), "server pid was 0x%x instead of 0x%x\n", new_info
->server_pid
,
4061 GetCurrentProcessId());
4062 ok(new_info
->server_tid
== server_tid
, "server tid was 0x%x instead of 0x%x\n", new_info
->server_tid
,
4064 ok(new_info
->method
== method
, "method was %d instead of %d\n", new_info
->method
, method
);
4065 ok(IsEqualGUID(&new_info
->causality
, &causality
), "causality wasn't correct\n");
4068 ok(IsEqualGUID(uExtent
, &EXTENTID_WineTest
), "uExtent wasn't correct\n");
4070 *(unsigned char *)pDataBuffer
= 0xcc;
4074 static void WINAPI
TestChannelHook_ClientNotify(
4075 IChannelHook
*iface
,
4083 SChannelHookCallInfo
*info
= (SChannelHookCallInfo
*)riid
;
4084 trace("TestChannelHook_ClientNotify hrFault = 0x%08x\n", hrFault
);
4086 if (!new_hook_struct
)
4088 ok(info
->cbSize
== sizeof(*info
), "cbSize was %d instead of %d\n", info
->cbSize
, (int)sizeof(*info
));
4089 ok(info
->dwServerPid
== GetCurrentProcessId(), "dwServerPid was 0x%x instead of 0x%x\n", info
->dwServerPid
, GetCurrentProcessId());
4090 ok(info
->iMethod
== method
, "iMethod was %d should be %d\n", info
->iMethod
, method
);
4092 ok(info
->pObject
!= NULL
, "pObject shouldn't be NULL\n");
4094 ok(IsEqualGUID(&info
->uCausality
, &causality
), "causality wasn't correct\n");
4098 struct new_hook_info
*new_info
= (struct new_hook_info
*)riid
;
4099 ok(new_info
->server_pid
== GetCurrentProcessId(), "server pid was 0x%x instead of 0x%x\n", new_info
->server_pid
,
4100 GetCurrentProcessId());
4101 ok(new_info
->server_tid
== server_tid
, "server tid was 0x%x instead of 0x%x\n", new_info
->server_tid
,
4103 ok(new_info
->method
== method
, "method was %d instead of %d\n", new_info
->method
, method
);
4104 ok(IsEqualGUID(&new_info
->causality
, &causality
), "causality wasn't correct\n");
4107 ok(IsEqualGUID(uExtent
, &EXTENTID_WineTest
), "uExtent wasn't correct\n");
4110 static void WINAPI
TestChannelHook_ServerNotify(
4111 IChannelHook
*iface
,
4118 SChannelHookCallInfo
*info
= (SChannelHookCallInfo
*)riid
;
4119 trace("TestChannelHook_ServerNotify\n");
4121 if (!new_hook_struct
)
4123 ok(info
->cbSize
== sizeof(*info
), "cbSize was %d instead of %d\n", info
->cbSize
, (int)sizeof(*info
));
4124 ok(info
->dwServerPid
== GetCurrentProcessId(), "dwServerPid was 0x%x instead of 0x%x\n", info
->dwServerPid
, GetCurrentProcessId());
4125 ok(info
->iMethod
== method
, "iMethod was %d should be %d\n", info
->iMethod
, method
);
4126 ok(info
->pObject
!= NULL
, "pObject shouldn't be NULL\n");
4127 ok(IsEqualGUID(&info
->uCausality
, &causality
), "causality wasn't correct\n");
4131 struct new_hook_info
*new_info
= (struct new_hook_info
*)riid
;
4132 ok(new_info
->server_pid
== GetCurrentProcessId(), "server pid was 0x%x instead of 0x%x\n", new_info
->server_pid
,
4133 GetCurrentProcessId());
4134 ok(new_info
->server_tid
== server_tid
, "server tid was 0x%x instead of 0x%x\n", new_info
->server_tid
,
4136 ok(new_info
->method
== method
, "method was %d instead of %d\n", new_info
->method
, method
);
4137 ok(IsEqualGUID(&new_info
->causality
, &causality
), "causality wasn't correct\n");
4140 ok(cbDataSize
== 1, "cbDataSize should have been 1 instead of %d\n", cbDataSize
);
4141 ok(*(unsigned char *)pDataBuffer
== 0xcc, "pDataBuffer should have contained 0xcc instead of 0x%x\n", *(unsigned char *)pDataBuffer
);
4142 ok(IsEqualGUID(uExtent
, &EXTENTID_WineTest
), "uExtent wasn't correct\n");
4145 static void WINAPI
TestChannelHook_ServerGetSize(
4146 IChannelHook
*iface
,
4152 SChannelHookCallInfo
*info
= (SChannelHookCallInfo
*)riid
;
4153 trace("TestChannelHook_ServerGetSize\n");
4154 trace("\t%s\n", debugstr_iid(riid
));
4155 if (!new_hook_struct
)
4157 ok(info
->cbSize
== sizeof(*info
), "cbSize was %d instead of %d\n", info
->cbSize
, (int)sizeof(*info
));
4158 ok(info
->dwServerPid
== GetCurrentProcessId(), "dwServerPid was 0x%x instead of 0x%x\n", info
->dwServerPid
, GetCurrentProcessId());
4159 ok(info
->iMethod
== method
, "iMethod was %d should be %d\n", info
->iMethod
, method
);
4160 ok(info
->pObject
!= NULL
, "pObject shouldn't be NULL\n");
4161 ok(IsEqualGUID(&info
->uCausality
, &causality
), "causality wasn't correct\n");
4165 struct new_hook_info
*new_info
= (struct new_hook_info
*)riid
;
4166 ok(new_info
->server_pid
== GetCurrentProcessId(), "server pid was 0x%x instead of 0x%x\n", new_info
->server_pid
,
4167 GetCurrentProcessId());
4168 ok(new_info
->server_tid
== server_tid
, "server tid was 0x%x instead of 0x%x\n", new_info
->server_tid
,
4170 ok(new_info
->method
== method
, "method was %d instead of %d\n", new_info
->method
, method
);
4171 ok(IsEqualGUID(&new_info
->causality
, &causality
), "causality wasn't correct\n");
4174 ok(IsEqualGUID(uExtent
, &EXTENTID_WineTest
), "uExtent wasn't correct\n");
4175 if (hrFault
!= S_OK
)
4176 trace("\thrFault = 0x%08x\n", hrFault
);
4181 static void WINAPI
TestChannelHook_ServerFillBuffer(
4182 IChannelHook
*iface
,
4189 trace("TestChannelHook_ServerFillBuffer\n");
4190 ok(0, "TestChannelHook_ServerFillBuffer shouldn't be called\n");
4193 static const IChannelHookVtbl TestChannelHookVtbl
=
4195 TestChannelHook_QueryInterface
,
4196 TestChannelHook_AddRef
,
4197 TestChannelHook_Release
,
4198 TestChannelHook_ClientGetSize
,
4199 TestChannelHook_ClientFillBuffer
,
4200 TestChannelHook_ClientNotify
,
4201 TestChannelHook_ServerNotify
,
4202 TestChannelHook_ServerGetSize
,
4203 TestChannelHook_ServerFillBuffer
,
4206 static IChannelHook TestChannelHook
= { &TestChannelHookVtbl
};
4208 static void test_channel_hook(void)
4210 IClassFactory
*cf
= NULL
;
4212 IUnknown
*proxy
= NULL
;
4216 struct host_object_data object_data
= { NULL
, &IID_IClassFactory
, (IUnknown
*)&Test_ClassFactory
,
4217 MSHLFLAGS_NORMAL
, &MessageFilter
};
4219 hr
= CoRegisterChannelHook(&EXTENTID_WineTest
, &TestChannelHook
);
4220 ok_ole_success(hr
, CoRegisterChannelHook
);
4222 hr
= CoRegisterMessageFilter(&MessageFilter
, NULL
);
4223 ok_ole_success(hr
, CoRegisterMessageFilter
);
4227 hr
= CreateStreamOnHGlobal(NULL
, TRUE
, &object_data
.stream
);
4228 ok_ole_success(hr
, CreateStreamOnHGlobal
);
4229 tid
= start_host_object2(&object_data
, &thread
);
4232 ok_more_than_one_lock();
4234 IStream_Seek(object_data
.stream
, ullZero
, STREAM_SEEK_SET
, NULL
);
4235 hr
= CoUnmarshalInterface(object_data
.stream
, &IID_IClassFactory
, (void **)&cf
);
4236 ok_ole_success(hr
, CoUnmarshalInterface
);
4237 IStream_Release(object_data
.stream
);
4239 ok_more_than_one_lock();
4242 hr
= IClassFactory_CreateInstance(cf
, NULL
, &IID_IUnknown
, (LPVOID
*)&proxy
);
4243 ok_ole_success(hr
, IClassFactory_CreateInstance
);
4246 IUnknown_Release(proxy
);
4248 IClassFactory_Release(cf
);
4252 end_host_object(tid
, thread
);
4254 hr
= CoRegisterMessageFilter(NULL
, NULL
);
4255 ok_ole_success(hr
, CoRegisterMessageFilter
);
4260 HMODULE hOle32
= GetModuleHandleA("ole32");
4264 if (!GetProcAddress(hOle32
, "CoRegisterSurrogateEx")) {
4265 win_skip("skipping test on win9x\n");
4269 pCoInitializeEx
= (void*)GetProcAddress(hOle32
, "CoInitializeEx");
4270 pDllGetClassObject
= (void*)GetProcAddress(hOle32
, "DllGetClassObject");
4272 argc
= winetest_get_mainargs( &argv
);
4273 if (argc
> 2 && (!strcmp(argv
[2], "-Embedding")))
4275 pCoInitializeEx(NULL
, COINIT_MULTITHREADED
);
4276 test_register_local_server();
4282 register_test_window();
4284 test_cocreateinstance_proxy();
4285 test_implicit_mta();
4287 pCoInitializeEx(NULL
, COINIT_APARTMENTTHREADED
);
4289 /* FIXME: test CoCreateInstanceEx */
4291 /* lifecycle management and marshaling tests */
4294 test_no_marshaler();
4295 test_normal_marshal_and_release();
4296 test_normal_marshal_and_unmarshal();
4297 test_marshal_and_unmarshal_invalid();
4298 test_same_apartment_unmarshal_failure();
4299 test_interthread_marshal_and_unmarshal();
4300 test_proxy_marshal_and_unmarshal();
4301 test_proxy_marshal_and_unmarshal2();
4302 test_proxy_marshal_and_unmarshal_weak();
4303 test_proxy_marshal_and_unmarshal_strong();
4304 test_marshal_stub_apartment_shutdown();
4305 test_marshal_proxy_apartment_shutdown();
4306 test_marshal_proxy_mta_apartment_shutdown();
4307 test_no_couninitialize_server();
4308 test_no_couninitialize_client();
4309 test_tableweak_marshal_and_unmarshal_twice();
4310 test_tableweak_marshal_releasedata1();
4311 test_tableweak_marshal_releasedata2();
4312 test_tableweak_and_normal_marshal_and_unmarshal();
4313 test_tableweak_and_normal_marshal_and_releasedata();
4314 test_two_tableweak_marshal_and_releasedata();
4315 test_tablestrong_marshal_and_unmarshal_twice();
4316 test_lock_object_external();
4317 test_disconnect_stub();
4318 test_normal_marshal_and_unmarshal_twice();
4320 with_external_conn
= !with_external_conn
;
4321 } while (with_external_conn
);
4323 test_marshal_channel_buffer();
4324 test_hresult_marshaling();
4325 test_proxy_used_in_wrong_thread();
4326 test_message_filter();
4327 test_bad_marshal_stream();
4328 test_proxy_interfaces();
4329 test_stubbuffer(&IID_IClassFactory
);
4330 test_proxybuffer(&IID_IClassFactory
);
4331 test_message_reentrancy();
4332 test_call_from_message();
4333 test_WM_QUIT_handling();
4334 test_freethreadedmarshaler();
4335 test_inproc_handler();
4336 test_handler_marshaling();
4337 test_client_security();
4339 test_local_server();
4341 test_globalinterfacetable();
4342 test_manualresetevent();
4343 test_crash_couninitialize();
4345 /* must be last test as channel hooks can't be unregistered */
4346 test_channel_hook();