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 #ifndef __REACTOS__ /* FIXME: Inspect */
573 static IPSFactoryBuffer PSFactoryBuffer
;
576 static DWORD CALLBACK
host_object_proc(LPVOID p
)
578 struct host_object_data
*data
= p
;
579 DWORD registration_key
;
583 pCoInitializeEx(NULL
, COINIT_APARTMENTTHREADED
);
585 if(data
->register_object
) {
586 hr
= CoRegisterClassObject(data
->register_clsid
, data
->register_object
,
587 CLSCTX_INPROC_SERVER
, REGCLS_MULTIPLEUSE
, ®istration_key
);
588 ok(hr
== S_OK
, "CoRegisterClassObject failed: %08x\n", hr
);
593 IMessageFilter
* prev_filter
= NULL
;
594 hr
= CoRegisterMessageFilter(data
->filter
, &prev_filter
);
595 if (prev_filter
) IMessageFilter_Release(prev_filter
);
596 ok_ole_success(hr
, CoRegisterMessageFilter
);
599 hr
= CoMarshalInterface(data
->stream
, data
->iid
, data
->object
, MSHCTX_INPROC
, NULL
, data
->marshal_flags
);
600 ok_ole_success(hr
, CoMarshalInterface
);
602 /* force the message queue to be created before signaling parent thread */
603 PeekMessageA(&msg
, NULL
, WM_USER
, WM_USER
, PM_NOREMOVE
);
605 SetEvent(data
->marshal_event
);
607 while (GetMessageA(&msg
, NULL
, 0, 0))
609 if (msg
.hwnd
== NULL
&& msg
.message
== RELEASEMARSHALDATA
)
611 CoReleaseMarshalData(data
->stream
);
612 SetEvent((HANDLE
)msg
.lParam
);
615 DispatchMessageA(&msg
);
618 HeapFree(GetProcessHeap(), 0, data
);
625 static DWORD
start_host_object2(struct host_object_data
*object_data
, HANDLE
*thread
)
628 struct host_object_data
*data
;
630 data
= HeapAlloc(GetProcessHeap(), 0, sizeof(*data
));
631 *data
= *object_data
;
632 data
->marshal_event
= CreateEventA(NULL
, FALSE
, FALSE
, NULL
);
633 *thread
= CreateThread(NULL
, 0, host_object_proc
, data
, 0, &tid
);
635 /* wait for marshaling to complete before returning */
636 ok( !WaitForSingleObject(data
->marshal_event
, 10000), "wait timed out\n" );
637 CloseHandle(data
->marshal_event
);
642 static DWORD
start_host_object(IStream
*stream
, REFIID riid
, IUnknown
*object
, MSHLFLAGS marshal_flags
, HANDLE
*thread
)
644 struct host_object_data object_data
= { stream
, riid
, object
, marshal_flags
};
645 return start_host_object2(&object_data
, thread
);
648 /* asks thread to release the marshal data because it has to be done by the
649 * same thread that marshaled the interface in the first place. */
650 static void release_host_object(DWORD tid
, WPARAM wp
)
652 HANDLE event
= CreateEventA(NULL
, FALSE
, FALSE
, NULL
);
653 PostThreadMessageA(tid
, RELEASEMARSHALDATA
, wp
, (LPARAM
)event
);
654 ok( !WaitForSingleObject(event
, 10000), "wait timed out\n" );
658 static void end_host_object(DWORD tid
, HANDLE thread
)
660 BOOL ret
= PostThreadMessageA(tid
, WM_QUIT
, 0, 0);
661 ok(ret
, "PostThreadMessage failed with error %d\n", GetLastError());
662 /* be careful of races - don't return until hosting thread has terminated */
663 ok( !WaitForSingleObject(thread
, 10000), "wait timed out\n" );
667 /* tests failure case of interface not having a marshaler specified in the
669 static void test_no_marshaler(void)
674 hr
= CreateStreamOnHGlobal(NULL
, TRUE
, &pStream
);
675 ok_ole_success(hr
, CreateStreamOnHGlobal
);
676 hr
= CoMarshalInterface(pStream
, &IID_IWineTest
, (IUnknown
*)&Test_ClassFactory
, MSHCTX_INPROC
, NULL
, MSHLFLAGS_NORMAL
);
677 ok(hr
== E_NOINTERFACE
, "CoMarshalInterface should have returned E_NOINTERFACE instead of 0x%08x\n", hr
);
679 IStream_Release(pStream
);
682 /* tests normal marshal and then release without unmarshaling */
683 static void test_normal_marshal_and_release(void)
686 IStream
*pStream
= NULL
;
689 external_connections
= 0;
691 hr
= CreateStreamOnHGlobal(NULL
, TRUE
, &pStream
);
692 ok_ole_success(hr
, CreateStreamOnHGlobal
);
693 hr
= CoMarshalInterface(pStream
, &IID_IClassFactory
, (IUnknown
*)&Test_ClassFactory
, MSHCTX_INPROC
, NULL
, MSHLFLAGS_NORMAL
);
694 ok_ole_success(hr
, CoMarshalInterface
);
696 ok_more_than_one_lock();
697 ok_non_zero_external_conn();
699 IStream_Seek(pStream
, ullZero
, STREAM_SEEK_SET
, NULL
);
700 hr
= CoReleaseMarshalData(pStream
);
701 ok_ole_success(hr
, CoReleaseMarshalData
);
702 IStream_Release(pStream
);
705 ok_zero_external_conn();
706 ok_last_release_closes(TRUE
);
709 /* tests success case of a same-thread marshal and unmarshal */
710 static void test_normal_marshal_and_unmarshal(void)
713 IStream
*pStream
= NULL
;
714 IUnknown
*pProxy
= NULL
;
717 external_connections
= 0;
719 hr
= CreateStreamOnHGlobal(NULL
, TRUE
, &pStream
);
720 ok_ole_success(hr
, CreateStreamOnHGlobal
);
721 hr
= CoMarshalInterface(pStream
, &IID_IClassFactory
, (IUnknown
*)&Test_ClassFactory
, MSHCTX_INPROC
, NULL
, MSHLFLAGS_NORMAL
);
722 ok_ole_success(hr
, CoMarshalInterface
);
724 ok_more_than_one_lock();
725 ok_non_zero_external_conn();
727 IStream_Seek(pStream
, ullZero
, STREAM_SEEK_SET
, NULL
);
728 hr
= CoUnmarshalInterface(pStream
, &IID_IClassFactory
, (void **)&pProxy
);
729 ok_ole_success(hr
, CoUnmarshalInterface
);
730 IStream_Release(pStream
);
732 ok_more_than_one_lock();
733 ok_zero_external_conn();
734 ok_last_release_closes(FALSE
);
736 IUnknown_Release(pProxy
);
741 /* tests failure case of unmarshaling a freed object */
742 static void test_marshal_and_unmarshal_invalid(void)
745 IStream
*pStream
= NULL
;
746 IClassFactory
*pProxy
= NULL
;
752 external_connections
= 0;
754 hr
= CreateStreamOnHGlobal(NULL
, TRUE
, &pStream
);
755 ok_ole_success(hr
, CreateStreamOnHGlobal
);
756 tid
= start_host_object(pStream
, &IID_IClassFactory
, (IUnknown
*)&Test_ClassFactory
, MSHLFLAGS_NORMAL
, &thread
);
758 ok_more_than_one_lock();
759 ok_non_zero_external_conn();
761 IStream_Seek(pStream
, ullZero
, STREAM_SEEK_SET
, NULL
);
762 hr
= CoReleaseMarshalData(pStream
);
763 ok_ole_success(hr
, CoReleaseMarshalData
);
766 ok_zero_external_conn();
767 ok_last_release_closes(TRUE
);
769 IStream_Seek(pStream
, ullZero
, STREAM_SEEK_SET
, NULL
);
770 hr
= CoUnmarshalInterface(pStream
, &IID_IClassFactory
, (void **)&pProxy
);
771 todo_wine
{ ok_ole_success(hr
, CoUnmarshalInterface
); }
777 hr
= IClassFactory_CreateInstance(pProxy
, NULL
, &IID_IUnknown
, &dummy
);
778 ok(hr
== RPC_E_DISCONNECTED
, "Remote call should have returned RPC_E_DISCONNECTED, instead of 0x%08x\n", hr
);
780 IClassFactory_Release(pProxy
);
783 IStream_Release(pStream
);
785 end_host_object(tid
, thread
);
788 static void test_same_apartment_unmarshal_failure(void)
793 static const LARGE_INTEGER llZero
;
796 external_connections
= 0;
798 hr
= CreateStreamOnHGlobal(NULL
, TRUE
, &pStream
);
799 ok_ole_success(hr
, CreateStreamOnHGlobal
);
801 hr
= CoMarshalInterface(pStream
, &IID_IUnknown
, (IUnknown
*)&Test_ClassFactory
, MSHCTX_INPROC
, NULL
, MSHLFLAGS_NORMAL
);
802 ok_ole_success(hr
, CoMarshalInterface
);
804 ok_more_than_one_lock();
805 ok_non_zero_external_conn();
807 hr
= IStream_Seek(pStream
, llZero
, STREAM_SEEK_SET
, NULL
);
808 ok_ole_success(hr
, IStream_Seek
);
810 hr
= CoUnmarshalInterface(pStream
, &IID_IParseDisplayName
, (void **)&pProxy
);
811 ok(hr
== E_NOINTERFACE
, "CoUnmarshalInterface should have returned E_NOINTERFACE instead of 0x%08x\n", hr
);
814 ok_zero_external_conn();
815 ok_last_release_closes(FALSE
);
817 IStream_Release(pStream
);
820 /* tests success case of an interthread marshal */
821 static void test_interthread_marshal_and_unmarshal(void)
824 IStream
*pStream
= NULL
;
825 IUnknown
*pProxy
= NULL
;
830 external_connections
= 0;
832 hr
= CreateStreamOnHGlobal(NULL
, TRUE
, &pStream
);
833 ok_ole_success(hr
, CreateStreamOnHGlobal
);
834 tid
= start_host_object(pStream
, &IID_IClassFactory
, (IUnknown
*)&Test_ClassFactory
, MSHLFLAGS_NORMAL
, &thread
);
836 ok_more_than_one_lock();
837 ok_non_zero_external_conn();
839 IStream_Seek(pStream
, ullZero
, STREAM_SEEK_SET
, NULL
);
840 hr
= CoUnmarshalInterface(pStream
, &IID_IClassFactory
, (void **)&pProxy
);
841 ok_ole_success(hr
, CoUnmarshalInterface
);
842 IStream_Release(pStream
);
844 ok_more_than_one_lock();
845 ok_non_zero_external_conn();
847 IUnknown_Release(pProxy
);
850 ok_zero_external_conn();
851 ok_last_release_closes(TRUE
);
853 end_host_object(tid
, thread
);
856 /* the number of external references that Wine's proxy manager normally gives
857 * out, so we can test the border case of running out of references */
858 #define NORMALEXTREFS 5
860 /* tests success case of an interthread marshal and then marshaling the proxy */
861 static void test_proxy_marshal_and_unmarshal(void)
864 IStream
*pStream
= NULL
;
865 IUnknown
*pProxy
= NULL
;
866 IUnknown
*pProxy2
= NULL
;
872 external_connections
= 0;
874 hr
= CreateStreamOnHGlobal(NULL
, TRUE
, &pStream
);
875 ok_ole_success(hr
, CreateStreamOnHGlobal
);
876 tid
= start_host_object(pStream
, &IID_IClassFactory
, (IUnknown
*)&Test_ClassFactory
, MSHLFLAGS_NORMAL
, &thread
);
878 ok_more_than_one_lock();
879 ok_non_zero_external_conn();
881 IStream_Seek(pStream
, ullZero
, STREAM_SEEK_SET
, NULL
);
882 hr
= CoUnmarshalInterface(pStream
, &IID_IClassFactory
, (void **)&pProxy
);
883 ok_ole_success(hr
, CoUnmarshalInterface
);
885 ok_more_than_one_lock();
887 IStream_Seek(pStream
, ullZero
, STREAM_SEEK_SET
, NULL
);
888 /* marshal the proxy */
889 hr
= CoMarshalInterface(pStream
, &IID_IClassFactory
, pProxy
, MSHCTX_INPROC
, NULL
, MSHLFLAGS_NORMAL
);
890 ok_ole_success(hr
, CoMarshalInterface
);
892 ok_more_than_one_lock();
894 /* marshal 5 more times to exhaust the normal external references of 5 */
895 for (i
= 0; i
< NORMALEXTREFS
; i
++)
897 hr
= CoMarshalInterface(pStream
, &IID_IClassFactory
, pProxy
, MSHCTX_INPROC
, NULL
, MSHLFLAGS_NORMAL
);
898 ok_ole_success(hr
, CoMarshalInterface
);
901 ok_more_than_one_lock();
903 /* release the original proxy to test that we successfully keep the
904 * original object alive */
905 IUnknown_Release(pProxy
);
907 IStream_Seek(pStream
, ullZero
, STREAM_SEEK_SET
, NULL
);
908 hr
= CoUnmarshalInterface(pStream
, &IID_IClassFactory
, (void **)&pProxy2
);
909 ok_ole_success(hr
, CoUnmarshalInterface
);
911 ok_more_than_one_lock();
912 ok_non_zero_external_conn();
914 IUnknown_Release(pProxy2
);
916 /* unmarshal all of the proxies to check that the object stub still exists */
917 for (i
= 0; i
< NORMALEXTREFS
; i
++)
919 hr
= CoUnmarshalInterface(pStream
, &IID_IClassFactory
, (void **)&pProxy2
);
920 ok_ole_success(hr
, CoUnmarshalInterface
);
922 IUnknown_Release(pProxy2
);
926 ok_zero_external_conn();
927 ok_last_release_closes(TRUE
);
929 IStream_Release(pStream
);
931 end_host_object(tid
, thread
);
934 /* tests success case of an interthread marshal and then marshaling the proxy
935 * using an iid that hasn't previously been unmarshaled */
936 static void test_proxy_marshal_and_unmarshal2(void)
939 IStream
*pStream
= NULL
;
940 IUnknown
*pProxy
= NULL
;
941 IUnknown
*pProxy2
= NULL
;
946 external_connections
= 0;
948 hr
= CreateStreamOnHGlobal(NULL
, TRUE
, &pStream
);
949 ok_ole_success(hr
, CreateStreamOnHGlobal
);
950 tid
= start_host_object(pStream
, &IID_IUnknown
, (IUnknown
*)&Test_ClassFactory
, MSHLFLAGS_NORMAL
, &thread
);
952 ok_more_than_one_lock();
953 ok_non_zero_external_conn();
955 IStream_Seek(pStream
, ullZero
, STREAM_SEEK_SET
, NULL
);
956 hr
= CoUnmarshalInterface(pStream
, &IID_IUnknown
, (void **)&pProxy
);
957 ok_ole_success(hr
, CoUnmarshalInterface
);
959 ok_more_than_one_lock();
961 IStream_Seek(pStream
, ullZero
, STREAM_SEEK_SET
, NULL
);
962 /* marshal the proxy */
963 hr
= CoMarshalInterface(pStream
, &IID_IClassFactory
, pProxy
, MSHCTX_INPROC
, NULL
, MSHLFLAGS_NORMAL
);
964 ok_ole_success(hr
, CoMarshalInterface
);
966 ok_more_than_one_lock();
968 IStream_Seek(pStream
, ullZero
, STREAM_SEEK_SET
, NULL
);
969 /* unmarshal the second proxy to the object */
970 hr
= CoUnmarshalInterface(pStream
, &IID_IClassFactory
, (void **)&pProxy2
);
971 ok_ole_success(hr
, CoUnmarshalInterface
);
972 IStream_Release(pStream
);
974 /* now the proxies should be as follows:
975 * pProxy -> &Test_ClassFactory
976 * pProxy2 -> &Test_ClassFactory
977 * they should NOT be as follows:
978 * pProxy -> &Test_ClassFactory
980 * the above can only really be tested by looking in +ole traces
983 ok_more_than_one_lock();
985 IUnknown_Release(pProxy
);
987 ok_more_than_one_lock();
988 ok_non_zero_external_conn();
990 IUnknown_Release(pProxy2
);
993 ok_zero_external_conn();
994 ok_last_release_closes(TRUE
);
996 end_host_object(tid
, thread
);
999 /* tests success case of an interthread marshal and then table-weak-marshaling the proxy */
1000 static void test_proxy_marshal_and_unmarshal_weak(void)
1003 IStream
*pStream
= NULL
;
1004 IUnknown
*pProxy
= NULL
;
1005 IUnknown
*pProxy2
= NULL
;
1010 external_connections
= 0;
1012 hr
= CreateStreamOnHGlobal(NULL
, TRUE
, &pStream
);
1013 ok_ole_success(hr
, CreateStreamOnHGlobal
);
1014 tid
= start_host_object(pStream
, &IID_IClassFactory
, (IUnknown
*)&Test_ClassFactory
, MSHLFLAGS_NORMAL
, &thread
);
1016 ok_more_than_one_lock();
1017 ok_non_zero_external_conn();
1019 IStream_Seek(pStream
, ullZero
, STREAM_SEEK_SET
, NULL
);
1020 hr
= CoUnmarshalInterface(pStream
, &IID_IClassFactory
, (void **)&pProxy
);
1021 ok_ole_success(hr
, CoUnmarshalInterface
);
1023 ok_more_than_one_lock();
1024 ok_non_zero_external_conn();
1026 IStream_Seek(pStream
, ullZero
, STREAM_SEEK_SET
, NULL
);
1027 /* marshal the proxy */
1028 hr
= CoMarshalInterface(pStream
, &IID_IClassFactory
, pProxy
, MSHCTX_INPROC
, NULL
, MSHLFLAGS_TABLEWEAK
);
1029 ok_ole_success(hr
, CoMarshalInterface
);
1031 ok_more_than_one_lock();
1032 ok_non_zero_external_conn();
1034 /* release the original proxy to test that we successfully keep the
1035 * original object alive */
1036 IUnknown_Release(pProxy
);
1038 IStream_Seek(pStream
, ullZero
, STREAM_SEEK_SET
, NULL
);
1039 hr
= CoUnmarshalInterface(pStream
, &IID_IClassFactory
, (void **)&pProxy2
);
1041 ok(hr
== CO_E_OBJNOTREG
, "CoUnmarshalInterface should return CO_E_OBJNOTREG instead of 0x%08x\n", hr
);
1044 ok_zero_external_conn();
1045 ok_last_release_closes(TRUE
);
1047 IStream_Release(pStream
);
1049 end_host_object(tid
, thread
);
1052 /* tests success case of an interthread marshal and then table-strong-marshaling the proxy */
1053 static void test_proxy_marshal_and_unmarshal_strong(void)
1056 IStream
*pStream
= NULL
;
1057 IUnknown
*pProxy
= NULL
;
1058 IUnknown
*pProxy2
= NULL
;
1063 external_connections
= 0;
1065 hr
= CreateStreamOnHGlobal(NULL
, TRUE
, &pStream
);
1066 ok_ole_success(hr
, CreateStreamOnHGlobal
);
1067 tid
= start_host_object(pStream
, &IID_IClassFactory
, (IUnknown
*)&Test_ClassFactory
, MSHLFLAGS_NORMAL
, &thread
);
1069 ok_more_than_one_lock();
1070 ok_non_zero_external_conn();
1072 IStream_Seek(pStream
, ullZero
, STREAM_SEEK_SET
, NULL
);
1073 hr
= CoUnmarshalInterface(pStream
, &IID_IClassFactory
, (void **)&pProxy
);
1074 ok_ole_success(hr
, CoUnmarshalInterface
);
1076 ok_more_than_one_lock();
1077 ok_non_zero_external_conn();
1079 IStream_Seek(pStream
, ullZero
, STREAM_SEEK_SET
, NULL
);
1080 /* marshal the proxy */
1081 hr
= CoMarshalInterface(pStream
, &IID_IClassFactory
, pProxy
, MSHCTX_INPROC
, NULL
, MSHLFLAGS_TABLESTRONG
);
1082 ok(hr
== S_OK
/* WinNT */ || hr
== E_INVALIDARG
/* Win9x */,
1083 "CoMarshalInterface should have return S_OK or E_INVALIDARG instead of 0x%08x\n", hr
);
1086 IUnknown_Release(pProxy
);
1090 ok_more_than_one_lock();
1091 ok_non_zero_external_conn();
1093 /* release the original proxy to test that we successfully keep the
1094 * original object alive */
1095 IUnknown_Release(pProxy
);
1097 IStream_Seek(pStream
, ullZero
, STREAM_SEEK_SET
, NULL
);
1098 hr
= CoUnmarshalInterface(pStream
, &IID_IClassFactory
, (void **)&pProxy2
);
1099 ok_ole_success(hr
, CoUnmarshalInterface
);
1101 ok_more_than_one_lock();
1102 ok_non_zero_external_conn();
1104 IUnknown_Release(pProxy2
);
1106 ok_more_than_one_lock();
1107 ok_non_zero_external_conn();
1110 IStream_Release(pStream
);
1112 end_host_object(tid
, thread
);
1116 ok_zero_external_conn();
1117 ok_last_release_closes(FALSE
);
1121 /* tests that stubs are released when the containing apartment is destroyed */
1122 static void test_marshal_stub_apartment_shutdown(void)
1125 IStream
*pStream
= NULL
;
1126 IUnknown
*pProxy
= NULL
;
1131 external_connections
= 0;
1133 hr
= CreateStreamOnHGlobal(NULL
, TRUE
, &pStream
);
1134 ok_ole_success(hr
, CreateStreamOnHGlobal
);
1135 tid
= start_host_object(pStream
, &IID_IClassFactory
, (IUnknown
*)&Test_ClassFactory
, MSHLFLAGS_NORMAL
, &thread
);
1137 ok_more_than_one_lock();
1138 ok_non_zero_external_conn();
1140 IStream_Seek(pStream
, ullZero
, STREAM_SEEK_SET
, NULL
);
1141 hr
= CoUnmarshalInterface(pStream
, &IID_IClassFactory
, (void **)&pProxy
);
1142 ok_ole_success(hr
, CoUnmarshalInterface
);
1143 IStream_Release(pStream
);
1145 ok_more_than_one_lock();
1146 ok_non_zero_external_conn();
1148 end_host_object(tid
, thread
);
1152 ok_zero_external_conn();
1153 ok_last_release_closes(FALSE
);
1156 IUnknown_Release(pProxy
);
1161 /* tests that proxies are released when the containing apartment is destroyed */
1162 static void test_marshal_proxy_apartment_shutdown(void)
1165 IStream
*pStream
= NULL
;
1166 IUnknown
*pProxy
= NULL
;
1171 external_connections
= 0;
1173 hr
= CreateStreamOnHGlobal(NULL
, TRUE
, &pStream
);
1174 ok_ole_success(hr
, CreateStreamOnHGlobal
);
1175 tid
= start_host_object(pStream
, &IID_IClassFactory
, (IUnknown
*)&Test_ClassFactory
, MSHLFLAGS_NORMAL
, &thread
);
1177 ok_more_than_one_lock();
1178 ok_non_zero_external_conn();
1180 IStream_Seek(pStream
, ullZero
, STREAM_SEEK_SET
, NULL
);
1181 hr
= CoUnmarshalInterface(pStream
, &IID_IClassFactory
, (void **)&pProxy
);
1182 ok_ole_success(hr
, CoUnmarshalInterface
);
1183 IStream_Release(pStream
);
1185 ok_more_than_one_lock();
1186 ok_non_zero_external_conn();
1191 ok_zero_external_conn();
1192 ok_last_release_closes(TRUE
);
1194 IUnknown_Release(pProxy
);
1198 end_host_object(tid
, thread
);
1200 pCoInitializeEx(NULL
, COINIT_APARTMENTTHREADED
);
1203 /* tests that proxies are released when the containing mta apartment is destroyed */
1204 static void test_marshal_proxy_mta_apartment_shutdown(void)
1207 IStream
*pStream
= NULL
;
1208 IUnknown
*pProxy
= NULL
;
1213 pCoInitializeEx(NULL
, COINIT_MULTITHREADED
);
1216 external_connections
= 0;
1218 hr
= CreateStreamOnHGlobal(NULL
, TRUE
, &pStream
);
1219 ok_ole_success(hr
, CreateStreamOnHGlobal
);
1220 tid
= start_host_object(pStream
, &IID_IClassFactory
, (IUnknown
*)&Test_ClassFactory
, MSHLFLAGS_NORMAL
, &thread
);
1222 ok_more_than_one_lock();
1223 ok_non_zero_external_conn();
1225 IStream_Seek(pStream
, ullZero
, STREAM_SEEK_SET
, NULL
);
1226 hr
= CoUnmarshalInterface(pStream
, &IID_IClassFactory
, (void **)&pProxy
);
1227 ok_ole_success(hr
, CoUnmarshalInterface
);
1228 IStream_Release(pStream
);
1230 ok_more_than_one_lock();
1231 ok_non_zero_external_conn();
1236 ok_zero_external_conn();
1237 ok_last_release_closes(TRUE
);
1239 IUnknown_Release(pProxy
);
1243 end_host_object(tid
, thread
);
1245 pCoInitializeEx(NULL
, COINIT_APARTMENTTHREADED
);
1248 static void test_marshal_channel_buffer(void)
1250 DWORD registration_key
;
1251 IUnknown
*proxy
= NULL
;
1252 IOleWindow
*ole_window
;
1259 struct host_object_data object_data
= { NULL
, &IID_IOleClientSite
, (IUnknown
*)&Test_OleClientSite
,
1260 MSHLFLAGS_NORMAL
, NULL
, (IUnknown
*)&PSFactoryBuffer
,
1261 &CLSID_WineTestPSFactoryBuffer
};
1264 external_connections
= 0;
1266 hr
= CoGetPSClsid(&IID_IOleWindow
, &clsid
);
1267 ok_ole_success(hr
, "CoGetPSClsid");
1269 hr
= CoGetClassObject(&clsid
, CLSCTX_INPROC_SERVER
, NULL
, &IID_IPSFactoryBuffer
,
1270 (void **)&ps_factory_buffer
);
1271 ok_ole_success(hr
, "CoGetClassObject");
1273 hr
= CreateStreamOnHGlobal(NULL
, TRUE
, &object_data
.stream
);
1274 ok_ole_success(hr
, CreateStreamOnHGlobal
);
1275 tid
= start_host_object2(&object_data
, &thread
);
1277 IStream_Seek(object_data
.stream
, ullZero
, STREAM_SEEK_SET
, NULL
);
1278 hr
= CoUnmarshalInterface(object_data
.stream
, &IID_IUnknown
, (void **)&proxy
);
1279 ok_ole_success(hr
, CoUnmarshalInterface
);
1280 IStream_Release(object_data
.stream
);
1282 hr
= CoRegisterClassObject(&CLSID_WineTestPSFactoryBuffer
, (IUnknown
*)&PSFactoryBuffer
,
1283 CLSCTX_INPROC_SERVER
, REGCLS_MULTIPLEUSE
, ®istration_key
);
1284 ok(hr
== S_OK
, "CoRegisterClassObject failed: %08x\n", hr
);
1286 hr
= CoRegisterPSClsid(&IID_IOleWindow
, &CLSID_WineTestPSFactoryBuffer
);
1287 ok(hr
== S_OK
, "CoRegisterPSClsid failed: %08x\n", hr
);
1289 SET_EXPECT(CreateStub
);
1290 SET_EXPECT(CreateProxy
);
1291 hr
= IUnknown_QueryInterface(proxy
, &IID_IOleWindow
, (void**)&ole_window
);
1292 ok(hr
== S_OK
, "Could not get IOleWindow iface: %08x\n", hr
);
1293 CHECK_CALLED(CreateStub
);
1294 CHECK_CALLED(CreateProxy
);
1297 SET_EXPECT(GetWindow
);
1298 hr
= IOleWindow_GetWindow(ole_window
, &hwnd
);
1299 ok(hr
== S_OK
, "GetWindow failed: %08x\n", hr
);
1300 ok(hwnd
== (HWND
)0xdeadbeef, "hwnd = %p\n", hwnd
);
1301 CHECK_CALLED(Invoke
);
1302 CHECK_CALLED(GetWindow
);
1304 IOleWindow_Release(ole_window
);
1306 SET_EXPECT(Disconnect
);
1307 IUnknown_Release(proxy
);
1309 CHECK_CALLED(Disconnect
);
1311 hr
= CoRevokeClassObject(registration_key
);
1312 ok(hr
== S_OK
, "CoRevokeClassObject failed: %08x\n", hr
);
1314 end_host_object(tid
, thread
);
1320 HANDLE marshal_event
;
1321 HANDLE unmarshal_event
;
1324 /* helper for test_no_couninitialize_server */
1325 static DWORD CALLBACK
no_couninitialize_server_proc(LPVOID p
)
1327 struct ncu_params
*ncu_params
= p
;
1330 pCoInitializeEx(NULL
, COINIT_MULTITHREADED
);
1332 hr
= CoMarshalInterface(ncu_params
->stream
, &IID_IClassFactory
, (IUnknown
*)&Test_ClassFactory
, MSHCTX_INPROC
, NULL
, MSHLFLAGS_NORMAL
);
1333 ok_ole_success(hr
, CoMarshalInterface
);
1335 SetEvent(ncu_params
->marshal_event
);
1337 ok( !WaitForSingleObject(ncu_params
->unmarshal_event
, 10000), "wait timed out\n" );
1339 /* die without calling CoUninitialize */
1344 /* tests apartment that an apartment with a stub is released without deadlock
1345 * if the owning thread exits */
1346 static void test_no_couninitialize_server(void)
1349 IStream
*pStream
= NULL
;
1350 IUnknown
*pProxy
= NULL
;
1353 struct ncu_params ncu_params
;
1356 external_connections
= 0;
1358 ncu_params
.marshal_event
= CreateEventA(NULL
, TRUE
, FALSE
, NULL
);
1359 ncu_params
.unmarshal_event
= CreateEventA(NULL
, TRUE
, FALSE
, NULL
);
1361 hr
= CreateStreamOnHGlobal(NULL
, TRUE
, &pStream
);
1362 ok_ole_success(hr
, CreateStreamOnHGlobal
);
1363 ncu_params
.stream
= pStream
;
1365 thread
= CreateThread(NULL
, 0, no_couninitialize_server_proc
, &ncu_params
, 0, &tid
);
1367 ok( !WaitForSingleObject(ncu_params
.marshal_event
, 10000), "wait timed out\n" );
1368 ok_more_than_one_lock();
1369 ok_non_zero_external_conn();
1371 IStream_Seek(pStream
, ullZero
, STREAM_SEEK_SET
, NULL
);
1372 hr
= CoUnmarshalInterface(pStream
, &IID_IClassFactory
, (void **)&pProxy
);
1373 ok_ole_success(hr
, CoUnmarshalInterface
);
1374 IStream_Release(pStream
);
1376 ok_more_than_one_lock();
1377 ok_non_zero_external_conn();
1379 SetEvent(ncu_params
.unmarshal_event
);
1380 ok( !WaitForSingleObject(thread
, 10000), "wait timed out\n" );
1384 ok_zero_external_conn();
1385 ok_last_release_closes(FALSE
);
1388 CloseHandle(thread
);
1389 CloseHandle(ncu_params
.marshal_event
);
1390 CloseHandle(ncu_params
.unmarshal_event
);
1392 IUnknown_Release(pProxy
);
1397 /* STA -> STA call during DLL_THREAD_DETACH */
1398 static DWORD CALLBACK
no_couninitialize_client_proc(LPVOID p
)
1400 struct ncu_params
*ncu_params
= p
;
1402 IUnknown
*pProxy
= NULL
;
1404 pCoInitializeEx(NULL
, COINIT_APARTMENTTHREADED
);
1406 hr
= CoUnmarshalInterface(ncu_params
->stream
, &IID_IClassFactory
, (void **)&pProxy
);
1407 ok_ole_success(hr
, CoUnmarshalInterface
);
1408 IStream_Release(ncu_params
->stream
);
1410 ok_more_than_one_lock();
1412 /* die without calling CoUninitialize */
1417 /* tests STA -> STA call during DLL_THREAD_DETACH doesn't deadlock */
1418 static void test_no_couninitialize_client(void)
1421 IStream
*pStream
= NULL
;
1426 struct ncu_params ncu_params
;
1429 external_connections
= 0;
1431 hr
= CreateStreamOnHGlobal(NULL
, TRUE
, &pStream
);
1432 ok_ole_success(hr
, CreateStreamOnHGlobal
);
1433 ncu_params
.stream
= pStream
;
1435 /* NOTE: assumes start_host_object uses an STA to host the object, as MTAs
1436 * always deadlock when called from within DllMain */
1437 host_tid
= start_host_object(pStream
, &IID_IClassFactory
, (IUnknown
*)&Test_ClassFactory
, MSHLFLAGS_NORMAL
, &host_thread
);
1438 IStream_Seek(pStream
, ullZero
, STREAM_SEEK_SET
, NULL
);
1440 ok_more_than_one_lock();
1441 ok_non_zero_external_conn();
1443 thread
= CreateThread(NULL
, 0, no_couninitialize_client_proc
, &ncu_params
, 0, &tid
);
1445 ok( !WaitForSingleObject(thread
, 10000), "wait timed out\n" );
1446 CloseHandle(thread
);
1449 ok_zero_external_conn();
1450 ok_last_release_closes(TRUE
);
1452 end_host_object(host_tid
, host_thread
);
1455 static BOOL crash_thread_success
;
1457 static DWORD CALLBACK
crash_couninitialize_proc(void *p
)
1466 hr
= CreateStreamOnHGlobal(NULL
, TRUE
, &stream
);
1467 ok_ole_success(hr
, CreateStreamOnHGlobal
);
1469 hr
= CoMarshalInterface(stream
, &IID_IUnknown
, &TestCrash_Unknown
, MSHCTX_INPROC
, NULL
, MSHLFLAGS_NORMAL
);
1470 ok_ole_success(hr
, CoMarshalInterface
);
1472 IStream_Seek(stream
, ullZero
, STREAM_SEEK_SET
, NULL
);
1474 hr
= CoReleaseMarshalData(stream
);
1475 ok_ole_success(hr
, CoReleaseMarshalData
);
1479 hr
= CoMarshalInterface(stream
, &IID_IUnknown
, &TestCrash_Unknown
, MSHCTX_INPROC
, NULL
, MSHLFLAGS_NORMAL
);
1480 ok_ole_success(hr
, CoMarshalInterface
);
1482 ok_more_than_one_lock();
1484 trace("CoUninitialize >>>\n");
1486 trace("CoUninitialize <<<\n");
1490 IStream_Release(stream
);
1491 crash_thread_success
= TRUE
;
1495 static void test_crash_couninitialize(void)
1500 if(!GetProcAddress(GetModuleHandleA("kernel32.dll"), "CreateActCtxW")) {
1501 win_skip("Skipping crash tests on win2k.\n");
1505 crash_thread_success
= FALSE
;
1506 thread
= CreateThread(NULL
, 0, crash_couninitialize_proc
, NULL
, 0, &tid
);
1507 ok(!WaitForSingleObject(thread
, 10000), "wait timed out\n");
1508 CloseHandle(thread
);
1509 ok(crash_thread_success
, "Crash thread failed\n");
1512 /* tests success case of a same-thread table-weak marshal, unmarshal, unmarshal */
1513 static void test_tableweak_marshal_and_unmarshal_twice(void)
1516 IStream
*pStream
= NULL
;
1517 IUnknown
*pProxy1
= NULL
;
1518 IUnknown
*pProxy2
= NULL
;
1523 external_connections
= 0;
1525 hr
= CreateStreamOnHGlobal(NULL
, TRUE
, &pStream
);
1526 ok_ole_success(hr
, CreateStreamOnHGlobal
);
1527 tid
= start_host_object(pStream
, &IID_IClassFactory
, (IUnknown
*)&Test_ClassFactory
, MSHLFLAGS_TABLEWEAK
, &thread
);
1529 ok_more_than_one_lock();
1530 ok_zero_external_conn();
1532 IStream_Seek(pStream
, ullZero
, STREAM_SEEK_SET
, NULL
);
1533 hr
= CoUnmarshalInterface(pStream
, &IID_IClassFactory
, (void **)&pProxy1
);
1534 ok_ole_success(hr
, CoUnmarshalInterface
);
1536 ok_more_than_one_lock();
1537 ok_non_zero_external_conn();
1539 IStream_Seek(pStream
, ullZero
, STREAM_SEEK_SET
, NULL
);
1540 hr
= CoUnmarshalInterface(pStream
, &IID_IClassFactory
, (void **)&pProxy2
);
1541 ok_ole_success(hr
, CoUnmarshalInterface
);
1543 ok_more_than_one_lock();
1545 IUnknown_Release(pProxy1
);
1546 ok_non_zero_external_conn();
1547 IUnknown_Release(pProxy2
);
1548 ok_zero_external_conn();
1549 ok_last_release_closes(TRUE
);
1551 /* When IExternalConnection is present COM's lifetime management
1552 * behaviour is altered; the remaining weak ref prevents stub shutdown. */
1553 if (with_external_conn
)
1555 ok_more_than_one_lock();
1556 IStream_Seek(pStream
, ullZero
, STREAM_SEEK_SET
, NULL
);
1557 release_host_object(tid
, 0);
1560 /* Without IExternalConnection this line is shows the difference between weak and strong table marshaling
1561 * weak has cLocks == 0, strong has cLocks > 0. */
1564 IStream_Release(pStream
);
1565 end_host_object(tid
, thread
);
1568 /* tests releasing after unmarshaling one object */
1569 static void test_tableweak_marshal_releasedata1(void)
1572 IStream
*pStream
= NULL
;
1573 IUnknown
*pProxy1
= NULL
;
1574 IUnknown
*pProxy2
= NULL
;
1579 external_connections
= 0;
1581 hr
= CreateStreamOnHGlobal(NULL
, TRUE
, &pStream
);
1582 ok_ole_success(hr
, CreateStreamOnHGlobal
);
1583 tid
= start_host_object(pStream
, &IID_IClassFactory
, (IUnknown
*)&Test_ClassFactory
, MSHLFLAGS_TABLEWEAK
, &thread
);
1585 ok_more_than_one_lock();
1586 ok_zero_external_conn();
1588 IStream_Seek(pStream
, ullZero
, STREAM_SEEK_SET
, NULL
);
1589 hr
= CoUnmarshalInterface(pStream
, &IID_IClassFactory
, (void **)&pProxy1
);
1590 ok_ole_success(hr
, CoUnmarshalInterface
);
1592 ok_more_than_one_lock();
1593 ok_non_zero_external_conn();
1595 /* release the remaining reference on the object by calling
1596 * CoReleaseMarshalData in the hosting thread */
1597 IStream_Seek(pStream
, ullZero
, STREAM_SEEK_SET
, NULL
);
1598 release_host_object(tid
, 0);
1600 ok_more_than_one_lock();
1601 ok_non_zero_external_conn();
1603 IStream_Seek(pStream
, ullZero
, STREAM_SEEK_SET
, NULL
);
1604 hr
= CoUnmarshalInterface(pStream
, &IID_IClassFactory
, (void **)&pProxy2
);
1605 ok_ole_success(hr
, CoUnmarshalInterface
);
1606 IStream_Release(pStream
);
1608 ok_more_than_one_lock();
1609 ok_non_zero_external_conn();
1611 IUnknown_Release(pProxy1
);
1615 ok_non_zero_external_conn();
1616 IUnknown_Release(pProxy2
);
1619 /* this line is shows the difference between weak and strong table marshaling:
1620 * weak has cLocks == 0
1621 * strong has cLocks > 0 */
1623 ok_zero_external_conn();
1624 ok_last_release_closes(TRUE
);
1626 end_host_object(tid
, thread
);
1629 /* tests releasing after unmarshaling one object */
1630 static void test_tableweak_marshal_releasedata2(void)
1633 IStream
*pStream
= NULL
;
1634 IUnknown
*pProxy
= NULL
;
1639 external_connections
= 0;
1641 hr
= CreateStreamOnHGlobal(NULL
, TRUE
, &pStream
);
1642 ok_ole_success(hr
, CreateStreamOnHGlobal
);
1643 tid
= start_host_object(pStream
, &IID_IClassFactory
, (IUnknown
*)&Test_ClassFactory
, MSHLFLAGS_TABLEWEAK
, &thread
);
1645 ok_more_than_one_lock();
1646 ok_zero_external_conn();
1648 /* release the remaining reference on the object by calling
1649 * CoReleaseMarshalData in the hosting thread */
1650 IStream_Seek(pStream
, ullZero
, STREAM_SEEK_SET
, NULL
);
1651 release_host_object(tid
, 0);
1655 IStream_Seek(pStream
, ullZero
, STREAM_SEEK_SET
, NULL
);
1656 hr
= CoUnmarshalInterface(pStream
, &IID_IClassFactory
, (void **)&pProxy
);
1659 ok(hr
== CO_E_OBJNOTREG
,
1660 "CoUnmarshalInterface should have failed with CO_E_OBJNOTREG, but returned 0x%08x instead\n",
1663 IStream_Release(pStream
);
1666 ok_zero_external_conn();
1668 end_host_object(tid
, thread
);
1671 struct duo_marshal_data
1673 MSHLFLAGS marshal_flags1
, marshal_flags2
;
1674 IStream
*pStream1
, *pStream2
;
1679 static DWORD CALLBACK
duo_marshal_thread_proc(void *p
)
1682 struct duo_marshal_data
*data
= p
;
1683 HANDLE hQuitEvent
= data
->hQuitEvent
;
1686 pCoInitializeEx(NULL
, COINIT_APARTMENTTHREADED
);
1688 hr
= CoMarshalInterface(data
->pStream1
, &IID_IClassFactory
, (IUnknown
*)&Test_ClassFactory
, MSHCTX_INPROC
, NULL
, data
->marshal_flags1
);
1689 ok_ole_success(hr
, "CoMarshalInterface");
1691 hr
= CoMarshalInterface(data
->pStream2
, &IID_IClassFactory
, (IUnknown
*)&Test_ClassFactory
, MSHCTX_INPROC
, NULL
, data
->marshal_flags2
);
1692 ok_ole_success(hr
, "CoMarshalInterface");
1694 /* force the message queue to be created before signaling parent thread */
1695 PeekMessageA(&msg
, NULL
, WM_USER
, WM_USER
, PM_NOREMOVE
);
1697 SetEvent(data
->hReadyEvent
);
1699 while (WAIT_OBJECT_0
+ 1 == MsgWaitForMultipleObjects(1, &hQuitEvent
, FALSE
, 10000, QS_ALLINPUT
))
1701 while (PeekMessageA(&msg
, NULL
, 0, 0, PM_REMOVE
))
1703 if (msg
.hwnd
== NULL
&& msg
.message
== RELEASEMARSHALDATA
)
1705 CoReleaseMarshalData(msg
.wParam
== 1 ? data
->pStream1
: data
->pStream2
);
1706 SetEvent((HANDLE
)msg
.lParam
);
1709 DispatchMessageA(&msg
);
1712 CloseHandle(hQuitEvent
);
1719 /* tests interaction between table-weak and normal marshalling of an object */
1720 static void test_tableweak_and_normal_marshal_and_unmarshal(void)
1723 IUnknown
*pProxyWeak
= NULL
;
1724 IUnknown
*pProxyNormal
= NULL
;
1727 struct duo_marshal_data data
;
1730 external_connections
= 0;
1732 data
.hReadyEvent
= CreateEventA(NULL
, FALSE
, FALSE
, NULL
);
1733 data
.hQuitEvent
= CreateEventA(NULL
, FALSE
, FALSE
, NULL
);
1734 data
.marshal_flags1
= MSHLFLAGS_TABLEWEAK
;
1735 data
.marshal_flags2
= MSHLFLAGS_NORMAL
;
1736 hr
= CreateStreamOnHGlobal(NULL
, TRUE
, &data
.pStream1
);
1737 ok_ole_success(hr
, CreateStreamOnHGlobal
);
1738 hr
= CreateStreamOnHGlobal(NULL
, TRUE
, &data
.pStream2
);
1739 ok_ole_success(hr
, CreateStreamOnHGlobal
);
1741 thread
= CreateThread(NULL
, 0, duo_marshal_thread_proc
, &data
, 0, &tid
);
1742 ok( !WaitForSingleObject(data
.hReadyEvent
, 10000), "wait timed out\n" );
1743 CloseHandle(data
.hReadyEvent
);
1745 ok_more_than_one_lock();
1746 ok_non_zero_external_conn();
1749 IStream_Seek(data
.pStream1
, ullZero
, STREAM_SEEK_SET
, NULL
);
1750 hr
= CoUnmarshalInterface(data
.pStream1
, &IID_IClassFactory
, (void **)&pProxyWeak
);
1751 ok_ole_success(hr
, CoUnmarshalInterface
);
1753 ok_more_than_one_lock();
1756 IStream_Seek(data
.pStream2
, ullZero
, STREAM_SEEK_SET
, NULL
);
1757 hr
= CoUnmarshalInterface(data
.pStream2
, &IID_IClassFactory
, (void **)&pProxyNormal
);
1758 ok_ole_success(hr
, CoUnmarshalInterface
);
1760 ok_more_than_one_lock();
1762 IUnknown_Release(pProxyNormal
);
1764 ok_more_than_one_lock();
1765 ok_non_zero_external_conn();
1767 IUnknown_Release(pProxyWeak
);
1769 ok_zero_external_conn();
1770 ok_last_release_closes(TRUE
);
1772 /* When IExternalConnection is present COM's lifetime management
1773 * behaviour is altered; the remaining weak ref prevents stub shutdown. */
1774 if (with_external_conn
)
1776 ok_more_than_one_lock();
1777 IStream_Seek(data
.pStream1
, ullZero
, STREAM_SEEK_SET
, NULL
);
1778 release_host_object(tid
, 1);
1782 IStream_Release(data
.pStream1
);
1783 IStream_Release(data
.pStream2
);
1785 SetEvent(data
.hQuitEvent
);
1786 ok( !WaitForSingleObject(thread
, 10000), "wait timed out\n" );
1787 CloseHandle(thread
);
1790 static void test_tableweak_and_normal_marshal_and_releasedata(void)
1795 struct duo_marshal_data data
;
1798 external_connections
= 0;
1800 data
.hReadyEvent
= CreateEventA(NULL
, FALSE
, FALSE
, NULL
);
1801 data
.hQuitEvent
= CreateEventA(NULL
, FALSE
, FALSE
, NULL
);
1802 data
.marshal_flags1
= MSHLFLAGS_TABLEWEAK
;
1803 data
.marshal_flags2
= MSHLFLAGS_NORMAL
;
1804 hr
= CreateStreamOnHGlobal(NULL
, TRUE
, &data
.pStream1
);
1805 ok_ole_success(hr
, CreateStreamOnHGlobal
);
1806 hr
= CreateStreamOnHGlobal(NULL
, TRUE
, &data
.pStream2
);
1807 ok_ole_success(hr
, CreateStreamOnHGlobal
);
1809 thread
= CreateThread(NULL
, 0, duo_marshal_thread_proc
, &data
, 0, &tid
);
1810 ok( !WaitForSingleObject(data
.hReadyEvent
, 10000), "wait timed out\n" );
1811 CloseHandle(data
.hReadyEvent
);
1813 ok_more_than_one_lock();
1814 ok_non_zero_external_conn();
1816 /* release normal - which in the non-external conn case will free the object despite the weak ref. */
1817 IStream_Seek(data
.pStream2
, ullZero
, STREAM_SEEK_SET
, NULL
);
1818 release_host_object(tid
, 2);
1820 ok_zero_external_conn();
1821 ok_last_release_closes(TRUE
);
1823 if (with_external_conn
)
1825 ok_more_than_one_lock();
1826 IStream_Seek(data
.pStream1
, ullZero
, STREAM_SEEK_SET
, NULL
);
1827 release_host_object(tid
, 1);
1832 IStream_Release(data
.pStream1
);
1833 IStream_Release(data
.pStream2
);
1835 SetEvent(data
.hQuitEvent
);
1836 ok( !WaitForSingleObject(thread
, 10000), "wait timed out\n" );
1837 CloseHandle(thread
);
1840 static void test_two_tableweak_marshal_and_releasedata(void)
1845 struct duo_marshal_data data
;
1848 external_connections
= 0;
1850 data
.hReadyEvent
= CreateEventA(NULL
, FALSE
, FALSE
, NULL
);
1851 data
.hQuitEvent
= CreateEventA(NULL
, FALSE
, FALSE
, NULL
);
1852 data
.marshal_flags1
= MSHLFLAGS_TABLEWEAK
;
1853 data
.marshal_flags2
= MSHLFLAGS_TABLEWEAK
;
1854 hr
= CreateStreamOnHGlobal(NULL
, TRUE
, &data
.pStream1
);
1855 ok_ole_success(hr
, CreateStreamOnHGlobal
);
1856 hr
= CreateStreamOnHGlobal(NULL
, TRUE
, &data
.pStream2
);
1857 ok_ole_success(hr
, CreateStreamOnHGlobal
);
1859 thread
= CreateThread(NULL
, 0, duo_marshal_thread_proc
, &data
, 0, &tid
);
1860 ok( !WaitForSingleObject(data
.hReadyEvent
, 10000), "wait timed out\n" );
1861 CloseHandle(data
.hReadyEvent
);
1863 ok_more_than_one_lock();
1864 ok_zero_external_conn();
1866 /* release one weak ref - the remaining weak ref will keep the obj alive */
1867 IStream_Seek(data
.pStream1
, ullZero
, STREAM_SEEK_SET
, NULL
);
1868 release_host_object(tid
, 1);
1870 ok_more_than_one_lock();
1872 IStream_Seek(data
.pStream2
, ullZero
, STREAM_SEEK_SET
, NULL
);
1873 release_host_object(tid
, 2);
1877 IStream_Release(data
.pStream1
);
1878 IStream_Release(data
.pStream2
);
1880 SetEvent(data
.hQuitEvent
);
1881 ok( !WaitForSingleObject(thread
, 10000), "wait timed out\n" );
1882 CloseHandle(thread
);
1885 /* tests success case of a same-thread table-strong marshal, unmarshal, unmarshal */
1886 static void test_tablestrong_marshal_and_unmarshal_twice(void)
1889 IStream
*pStream
= NULL
;
1890 IUnknown
*pProxy1
= NULL
;
1891 IUnknown
*pProxy2
= NULL
;
1896 external_connections
= 0;
1898 hr
= CreateStreamOnHGlobal(NULL
, TRUE
, &pStream
);
1899 ok_ole_success(hr
, CreateStreamOnHGlobal
);
1900 tid
= start_host_object(pStream
, &IID_IClassFactory
, (IUnknown
*)&Test_ClassFactory
, MSHLFLAGS_TABLESTRONG
, &thread
);
1902 ok_more_than_one_lock();
1903 ok_non_zero_external_conn();
1905 IStream_Seek(pStream
, ullZero
, STREAM_SEEK_SET
, NULL
);
1906 hr
= CoUnmarshalInterface(pStream
, &IID_IClassFactory
, (void **)&pProxy1
);
1907 ok_ole_success(hr
, CoUnmarshalInterface
);
1909 ok_more_than_one_lock();
1911 IStream_Seek(pStream
, ullZero
, STREAM_SEEK_SET
, NULL
);
1912 hr
= CoUnmarshalInterface(pStream
, &IID_IClassFactory
, (void **)&pProxy2
);
1913 ok_ole_success(hr
, CoUnmarshalInterface
);
1915 ok_more_than_one_lock();
1917 if (pProxy1
) IUnknown_Release(pProxy1
);
1918 if (pProxy2
) IUnknown_Release(pProxy2
);
1920 /* this line is shows the difference between weak and strong table marshaling:
1921 * weak has cLocks == 0
1922 * strong has cLocks > 0 */
1923 ok_more_than_one_lock();
1925 /* release the remaining reference on the object by calling
1926 * CoReleaseMarshalData in the hosting thread */
1927 IStream_Seek(pStream
, ullZero
, STREAM_SEEK_SET
, NULL
);
1928 release_host_object(tid
, 0);
1929 IStream_Release(pStream
);
1932 ok_zero_external_conn();
1933 ok_last_release_closes(TRUE
);
1935 end_host_object(tid
, thread
);
1938 /* tests CoLockObjectExternal */
1939 static void test_lock_object_external(void)
1942 IStream
*pStream
= NULL
;
1945 external_connections
= 0;
1947 /* test the stub manager creation aspect of CoLockObjectExternal when the
1948 * object hasn't been marshaled yet */
1949 CoLockObjectExternal((IUnknown
*)&Test_ClassFactory
, TRUE
, TRUE
);
1951 ok_more_than_one_lock();
1952 ok_non_zero_external_conn();
1954 CoDisconnectObject((IUnknown
*)&Test_ClassFactory
, 0);
1957 ok_non_zero_external_conn();
1958 external_connections
= 0;
1960 /* test our empty stub manager being handled correctly in
1961 * CoMarshalInterface */
1962 CoLockObjectExternal((IUnknown
*)&Test_ClassFactory
, TRUE
, TRUE
);
1964 hr
= CreateStreamOnHGlobal(NULL
, TRUE
, &pStream
);
1965 ok_ole_success(hr
, CreateStreamOnHGlobal
);
1966 hr
= CoMarshalInterface(pStream
, &IID_IClassFactory
, (IUnknown
*)&Test_ClassFactory
, MSHCTX_INPROC
, NULL
, MSHLFLAGS_NORMAL
);
1967 ok_ole_success(hr
, CoMarshalInterface
);
1969 CoLockObjectExternal((IUnknown
*)&Test_ClassFactory
, TRUE
, TRUE
);
1971 ok_more_than_one_lock();
1972 ok_non_zero_external_conn();
1974 IStream_Seek(pStream
, ullZero
, STREAM_SEEK_SET
, NULL
);
1975 hr
= CoReleaseMarshalData(pStream
);
1976 ok_ole_success(hr
, CoReleaseMarshalData
);
1977 IStream_Seek(pStream
, ullZero
, STREAM_SEEK_SET
, NULL
);
1979 ok_more_than_one_lock();
1980 ok_non_zero_external_conn();
1981 ok_last_release_closes(TRUE
);
1983 CoLockObjectExternal((IUnknown
*)&Test_ClassFactory
, FALSE
, TRUE
);
1985 ok_more_than_one_lock();
1986 ok_non_zero_external_conn();
1987 ok_last_release_closes(TRUE
);
1989 CoLockObjectExternal((IUnknown
*)&Test_ClassFactory
, FALSE
, TRUE
);
1992 ok_zero_external_conn();
1993 ok_last_release_closes(TRUE
);
1995 /* test CoLockObjectExternal releases reference to object with
1996 * fLastUnlockReleases as TRUE and there are only strong references on
1998 CoLockObjectExternal((IUnknown
*)&Test_ClassFactory
, TRUE
, FALSE
);
2000 ok_more_than_one_lock();
2001 ok_non_zero_external_conn();
2003 CoLockObjectExternal((IUnknown
*)&Test_ClassFactory
, FALSE
, FALSE
);
2006 ok_zero_external_conn();
2007 ok_last_release_closes(FALSE
);
2009 /* test CoLockObjectExternal doesn't release the last reference to an
2010 * object with fLastUnlockReleases as TRUE and there is a weak reference
2012 hr
= CoMarshalInterface(pStream
, &IID_IClassFactory
, (IUnknown
*)&Test_ClassFactory
, MSHCTX_INPROC
, NULL
, MSHLFLAGS_TABLEWEAK
);
2013 ok_ole_success(hr
, CoMarshalInterface
);
2015 ok_more_than_one_lock();
2016 ok_zero_external_conn();
2018 CoLockObjectExternal((IUnknown
*)&Test_ClassFactory
, TRUE
, FALSE
);
2020 ok_more_than_one_lock();
2021 ok_non_zero_external_conn();
2023 CoLockObjectExternal((IUnknown
*)&Test_ClassFactory
, FALSE
, FALSE
);
2025 ok_more_than_one_lock();
2026 ok_zero_external_conn();
2027 ok_last_release_closes(FALSE
);
2029 CoDisconnectObject((IUnknown
*)&Test_ClassFactory
, 0);
2033 IStream_Release(pStream
);
2036 /* tests disconnecting stubs */
2037 static void test_disconnect_stub(void)
2040 IStream
*pStream
= NULL
;
2043 external_connections
= 0;
2045 hr
= CreateStreamOnHGlobal(NULL
, TRUE
, &pStream
);
2046 ok_ole_success(hr
, CreateStreamOnHGlobal
);
2047 hr
= CoMarshalInterface(pStream
, &IID_IClassFactory
, (IUnknown
*)&Test_ClassFactory
, MSHCTX_INPROC
, NULL
, MSHLFLAGS_NORMAL
);
2048 ok_ole_success(hr
, CoMarshalInterface
);
2050 ok_non_zero_external_conn();
2052 CoLockObjectExternal((IUnknown
*)&Test_ClassFactory
, TRUE
, TRUE
);
2054 ok_more_than_one_lock();
2055 ok_non_zero_external_conn();
2057 IStream_Seek(pStream
, ullZero
, STREAM_SEEK_SET
, NULL
);
2058 hr
= CoReleaseMarshalData(pStream
);
2059 ok_ole_success(hr
, CoReleaseMarshalData
);
2060 IStream_Release(pStream
);
2062 ok_more_than_one_lock();
2063 ok_non_zero_external_conn();
2065 CoDisconnectObject((IUnknown
*)&Test_ClassFactory
, 0);
2068 ok_non_zero_external_conn();
2070 hr
= CoDisconnectObject(NULL
, 0);
2071 ok( hr
== E_INVALIDARG
, "wrong status %x\n", hr
);
2074 /* tests failure case of a same-thread marshal and unmarshal twice */
2075 static void test_normal_marshal_and_unmarshal_twice(void)
2078 IStream
*pStream
= NULL
;
2079 IUnknown
*pProxy1
= NULL
;
2080 IUnknown
*pProxy2
= NULL
;
2083 external_connections
= 0;
2085 hr
= CreateStreamOnHGlobal(NULL
, TRUE
, &pStream
);
2086 ok_ole_success(hr
, CreateStreamOnHGlobal
);
2087 hr
= CoMarshalInterface(pStream
, &IID_IClassFactory
, (IUnknown
*)&Test_ClassFactory
, MSHCTX_INPROC
, NULL
, MSHLFLAGS_NORMAL
);
2088 ok_ole_success(hr
, CoMarshalInterface
);
2090 ok_more_than_one_lock();
2091 ok_non_zero_external_conn();
2093 IStream_Seek(pStream
, ullZero
, STREAM_SEEK_SET
, NULL
);
2094 hr
= CoUnmarshalInterface(pStream
, &IID_IClassFactory
, (void **)&pProxy1
);
2095 ok_ole_success(hr
, CoUnmarshalInterface
);
2097 ok_more_than_one_lock();
2098 ok_zero_external_conn();
2099 ok_last_release_closes(FALSE
);
2101 IStream_Seek(pStream
, ullZero
, STREAM_SEEK_SET
, NULL
);
2102 hr
= CoUnmarshalInterface(pStream
, &IID_IClassFactory
, (void **)&pProxy2
);
2103 ok(hr
== CO_E_OBJNOTCONNECTED
,
2104 "CoUnmarshalInterface should have failed with error CO_E_OBJNOTCONNECTED for double unmarshal, instead of 0x%08x\n", hr
);
2106 IStream_Release(pStream
);
2108 ok_more_than_one_lock();
2110 IUnknown_Release(pProxy1
);
2115 /* tests success case of marshaling and unmarshaling an HRESULT */
2116 static void test_hresult_marshaling(void)
2119 HRESULT hr_marshaled
= 0;
2120 IStream
*pStream
= NULL
;
2121 static const HRESULT E_DEADBEEF
= 0xdeadbeef;
2123 hr
= CreateStreamOnHGlobal(NULL
, TRUE
, &pStream
);
2124 ok_ole_success(hr
, CreateStreamOnHGlobal
);
2126 hr
= CoMarshalHresult(pStream
, E_DEADBEEF
);
2127 ok_ole_success(hr
, CoMarshalHresult
);
2129 IStream_Seek(pStream
, ullZero
, STREAM_SEEK_SET
, NULL
);
2130 hr
= IStream_Read(pStream
, &hr_marshaled
, sizeof(HRESULT
), NULL
);
2131 ok_ole_success(hr
, IStream_Read
);
2133 ok(hr_marshaled
== E_DEADBEEF
, "Didn't marshal HRESULT as expected: got value 0x%08x instead\n", hr_marshaled
);
2136 IStream_Seek(pStream
, ullZero
, STREAM_SEEK_SET
, NULL
);
2137 hr
= CoUnmarshalHresult(pStream
, &hr_marshaled
);
2138 ok_ole_success(hr
, CoUnmarshalHresult
);
2140 ok(hr_marshaled
== E_DEADBEEF
, "Didn't marshal HRESULT as expected: got value 0x%08x instead\n", hr_marshaled
);
2142 IStream_Release(pStream
);
2146 /* helper for test_proxy_used_in_wrong_thread */
2147 static DWORD CALLBACK
bad_thread_proc(LPVOID p
)
2149 IClassFactory
* cf
= p
;
2151 IUnknown
* proxy
= NULL
;
2153 hr
= IClassFactory_CreateInstance(cf
, NULL
, &IID_IUnknown
, (LPVOID
*)&proxy
);
2155 ok(hr
== CO_E_NOTINITIALIZED
,
2156 "COM should have failed with CO_E_NOTINITIALIZED on using proxy without apartment, but instead returned 0x%08x\n",
2159 hr
= IClassFactory_QueryInterface(cf
, &IID_IMultiQI
, (LPVOID
*)&proxy
);
2160 /* Win9x returns S_OK, whilst NT returns RPC_E_WRONG_THREAD */
2161 trace("call to proxy's QueryInterface for local interface without apartment returned 0x%08x\n", hr
);
2163 IUnknown_Release(proxy
);
2165 hr
= IClassFactory_QueryInterface(cf
, &IID_IStream
, (LPVOID
*)&proxy
);
2166 /* Win9x returns E_NOINTERFACE, whilst NT returns RPC_E_WRONG_THREAD */
2167 trace("call to proxy's QueryInterface without apartment returned 0x%08x\n", hr
);
2169 IUnknown_Release(proxy
);
2171 pCoInitializeEx(NULL
, COINIT_MULTITHREADED
);
2173 hr
= IClassFactory_CreateInstance(cf
, NULL
, &IID_IUnknown
, (LPVOID
*)&proxy
);
2174 if (proxy
) IUnknown_Release(proxy
);
2175 ok(hr
== RPC_E_WRONG_THREAD
,
2176 "COM should have failed with RPC_E_WRONG_THREAD on using proxy from wrong apartment, but instead returned 0x%08x\n",
2179 hr
= IClassFactory_QueryInterface(cf
, &IID_IStream
, (LPVOID
*)&proxy
);
2180 /* Win9x returns E_NOINTERFACE, whilst NT returns RPC_E_WRONG_THREAD */
2181 trace("call to proxy's QueryInterface from wrong apartment returned 0x%08x\n", hr
);
2183 /* now be really bad and release the proxy from the wrong apartment */
2184 IClassFactory_Release(cf
);
2191 /* tests failure case of a using a proxy in the wrong apartment */
2192 static void test_proxy_used_in_wrong_thread(void)
2195 IStream
*pStream
= NULL
;
2196 IUnknown
*pProxy
= NULL
;
2203 hr
= CreateStreamOnHGlobal(NULL
, TRUE
, &pStream
);
2204 ok_ole_success(hr
, CreateStreamOnHGlobal
);
2205 tid
= start_host_object(pStream
, &IID_IClassFactory
, (IUnknown
*)&Test_ClassFactory
, MSHLFLAGS_NORMAL
, &host_thread
);
2207 ok_more_than_one_lock();
2209 IStream_Seek(pStream
, ullZero
, STREAM_SEEK_SET
, NULL
);
2210 hr
= CoUnmarshalInterface(pStream
, &IID_IClassFactory
, (void **)&pProxy
);
2211 ok_ole_success(hr
, CoUnmarshalInterface
);
2212 IStream_Release(pStream
);
2214 ok_more_than_one_lock();
2216 /* do a call that will fail, but result in IRemUnknown being used by the proxy */
2217 IUnknown_QueryInterface(pProxy
, &IID_IStream
, (LPVOID
*)&pStream
);
2219 /* create a thread that we can misbehave in */
2220 thread
= CreateThread(NULL
, 0, bad_thread_proc
, pProxy
, 0, &tid2
);
2222 ok( !WaitForSingleObject(thread
, 10000), "wait timed out\n" );
2223 CloseHandle(thread
);
2225 /* do release statement on Win9x that we should have done above */
2226 if (!GetProcAddress(GetModuleHandleA("ole32"), "CoRegisterSurrogateEx"))
2227 IUnknown_Release(pProxy
);
2231 end_host_object(tid
, host_thread
);
2234 static HRESULT WINAPI
MessageFilter_QueryInterface(IMessageFilter
*iface
, REFIID riid
, void ** ppvObj
)
2236 if (ppvObj
== NULL
) return E_POINTER
;
2238 if (IsEqualGUID(riid
, &IID_IUnknown
) ||
2239 IsEqualGUID(riid
, &IID_IClassFactory
))
2242 IMessageFilter_AddRef(iface
);
2246 return E_NOINTERFACE
;
2249 static ULONG WINAPI
MessageFilter_AddRef(IMessageFilter
*iface
)
2251 return 2; /* non-heap object */
2254 static ULONG WINAPI
MessageFilter_Release(IMessageFilter
*iface
)
2256 return 1; /* non-heap object */
2259 static DWORD WINAPI
MessageFilter_HandleInComingCall(
2260 IMessageFilter
*iface
,
2262 HTASK threadIDCaller
,
2264 LPINTERFACEINFO lpInterfaceInfo
)
2266 static int callcount
= 0;
2268 trace("HandleInComingCall\n");
2272 ret
= SERVERCALL_REJECTED
;
2275 ret
= SERVERCALL_RETRYLATER
;
2278 ret
= SERVERCALL_ISHANDLED
;
2285 static DWORD WINAPI
MessageFilter_RetryRejectedCall(
2286 IMessageFilter
*iface
,
2287 HTASK threadIDCallee
,
2291 trace("RetryRejectedCall\n");
2295 static DWORD WINAPI
MessageFilter_MessagePending(
2296 IMessageFilter
*iface
,
2297 HTASK threadIDCallee
,
2299 DWORD dwPendingType
)
2301 trace("MessagePending\n");
2302 return PENDINGMSG_WAITNOPROCESS
;
2305 static const IMessageFilterVtbl MessageFilter_Vtbl
=
2307 MessageFilter_QueryInterface
,
2308 MessageFilter_AddRef
,
2309 MessageFilter_Release
,
2310 MessageFilter_HandleInComingCall
,
2311 MessageFilter_RetryRejectedCall
,
2312 MessageFilter_MessagePending
2315 static IMessageFilter MessageFilter
= { &MessageFilter_Vtbl
};
2317 static void test_message_filter(void)
2320 IClassFactory
*cf
= NULL
;
2322 IUnknown
*proxy
= NULL
;
2323 IMessageFilter
*prev_filter
= NULL
;
2326 struct host_object_data object_data
= { NULL
, &IID_IClassFactory
, (IUnknown
*)&Test_ClassFactory
,
2327 MSHLFLAGS_NORMAL
, &MessageFilter
};
2331 hr
= CreateStreamOnHGlobal(NULL
, TRUE
, &object_data
.stream
);
2332 ok_ole_success(hr
, CreateStreamOnHGlobal
);
2333 tid
= start_host_object2(&object_data
, &thread
);
2335 ok_more_than_one_lock();
2337 IStream_Seek(object_data
.stream
, ullZero
, STREAM_SEEK_SET
, NULL
);
2338 hr
= CoUnmarshalInterface(object_data
.stream
, &IID_IClassFactory
, (void **)&cf
);
2339 ok_ole_success(hr
, CoUnmarshalInterface
);
2340 IStream_Release(object_data
.stream
);
2342 ok_more_than_one_lock();
2344 hr
= IClassFactory_CreateInstance(cf
, NULL
, &IID_IUnknown
, (LPVOID
*)&proxy
);
2345 ok(hr
== RPC_E_CALL_REJECTED
, "Call should have returned RPC_E_CALL_REJECTED, but return 0x%08x instead\n", hr
);
2346 if (proxy
) IUnknown_Release(proxy
);
2349 hr
= CoRegisterMessageFilter(&MessageFilter
, &prev_filter
);
2350 ok_ole_success(hr
, CoRegisterMessageFilter
);
2352 hr
= IClassFactory_CreateInstance(cf
, NULL
, &IID_IUnknown
, (LPVOID
*)&proxy
);
2353 ok_ole_success(hr
, IClassFactory_CreateInstance
);
2355 IUnknown_Release(proxy
);
2357 IClassFactory_Release(cf
);
2361 end_host_object(tid
, thread
);
2363 hr
= CoRegisterMessageFilter(prev_filter
, NULL
);
2364 ok_ole_success(hr
, CoRegisterMessageFilter
);
2367 /* test failure case of trying to unmarshal from bad stream */
2368 static void test_bad_marshal_stream(void)
2371 IStream
*pStream
= NULL
;
2373 hr
= CreateStreamOnHGlobal(NULL
, TRUE
, &pStream
);
2374 ok_ole_success(hr
, CreateStreamOnHGlobal
);
2375 hr
= CoMarshalInterface(pStream
, &IID_IClassFactory
, (IUnknown
*)&Test_ClassFactory
, MSHCTX_INPROC
, NULL
, MSHLFLAGS_NORMAL
);
2376 ok_ole_success(hr
, CoMarshalInterface
);
2378 ok_more_than_one_lock();
2380 /* try to read beyond end of stream */
2381 hr
= CoReleaseMarshalData(pStream
);
2382 ok(hr
== STG_E_READFAULT
, "Should have failed with STG_E_READFAULT, but returned 0x%08x instead\n", hr
);
2384 /* now release for real */
2385 IStream_Seek(pStream
, ullZero
, STREAM_SEEK_SET
, NULL
);
2386 hr
= CoReleaseMarshalData(pStream
);
2387 ok_ole_success(hr
, CoReleaseMarshalData
);
2389 IStream_Release(pStream
);
2392 /* tests that proxies implement certain interfaces */
2393 static void test_proxy_interfaces(void)
2396 IStream
*pStream
= NULL
;
2397 IUnknown
*pProxy
= NULL
;
2398 IUnknown
*pOtherUnknown
= NULL
;
2404 hr
= CreateStreamOnHGlobal(NULL
, TRUE
, &pStream
);
2405 ok_ole_success(hr
, CreateStreamOnHGlobal
);
2406 tid
= start_host_object(pStream
, &IID_IClassFactory
, (IUnknown
*)&Test_ClassFactory
, MSHLFLAGS_NORMAL
, &thread
);
2408 ok_more_than_one_lock();
2410 IStream_Seek(pStream
, ullZero
, STREAM_SEEK_SET
, NULL
);
2411 hr
= CoUnmarshalInterface(pStream
, &IID_IUnknown
, (void **)&pProxy
);
2412 ok_ole_success(hr
, CoUnmarshalInterface
);
2413 IStream_Release(pStream
);
2415 ok_more_than_one_lock();
2417 hr
= IUnknown_QueryInterface(pProxy
, &IID_IUnknown
, (LPVOID
*)&pOtherUnknown
);
2418 ok_ole_success(hr
, IUnknown_QueryInterface IID_IUnknown
);
2419 if (hr
== S_OK
) IUnknown_Release(pOtherUnknown
);
2421 hr
= IUnknown_QueryInterface(pProxy
, &IID_IClientSecurity
, (LPVOID
*)&pOtherUnknown
);
2422 ok_ole_success(hr
, IUnknown_QueryInterface IID_IClientSecurity
);
2423 if (hr
== S_OK
) IUnknown_Release(pOtherUnknown
);
2425 hr
= IUnknown_QueryInterface(pProxy
, &IID_IMultiQI
, (LPVOID
*)&pOtherUnknown
);
2426 ok_ole_success(hr
, IUnknown_QueryInterface IID_IMultiQI
);
2427 if (hr
== S_OK
) IUnknown_Release(pOtherUnknown
);
2429 hr
= IUnknown_QueryInterface(pProxy
, &IID_IMarshal
, (LPVOID
*)&pOtherUnknown
);
2430 ok_ole_success(hr
, IUnknown_QueryInterface IID_IMarshal
);
2431 if (hr
== S_OK
) IUnknown_Release(pOtherUnknown
);
2433 /* IMarshal2 is also supported on NT-based systems, but is pretty much
2434 * useless as it has no more methods over IMarshal that it inherits from. */
2436 IUnknown_Release(pProxy
);
2440 end_host_object(tid
, thread
);
2445 IUnknown IUnknown_iface
;
2449 static inline HeapUnknown
*impl_from_IUnknown(IUnknown
*iface
)
2451 return CONTAINING_RECORD(iface
, HeapUnknown
, IUnknown_iface
);
2454 static HRESULT WINAPI
HeapUnknown_QueryInterface(IUnknown
*iface
, REFIID riid
, void **ppv
)
2456 if (IsEqualIID(riid
, &IID_IUnknown
))
2458 IUnknown_AddRef(iface
);
2463 return E_NOINTERFACE
;
2466 static ULONG WINAPI
HeapUnknown_AddRef(IUnknown
*iface
)
2468 HeapUnknown
*This
= impl_from_IUnknown(iface
);
2469 return InterlockedIncrement((LONG
*)&This
->refs
);
2472 static ULONG WINAPI
HeapUnknown_Release(IUnknown
*iface
)
2474 HeapUnknown
*This
= impl_from_IUnknown(iface
);
2475 ULONG refs
= InterlockedDecrement((LONG
*)&This
->refs
);
2476 if (!refs
) HeapFree(GetProcessHeap(), 0, This
);
2480 static const IUnknownVtbl HeapUnknown_Vtbl
=
2482 HeapUnknown_QueryInterface
,
2487 static void test_proxybuffer(REFIID riid
)
2490 IPSFactoryBuffer
*psfb
;
2491 IRpcProxyBuffer
*proxy
;
2495 HeapUnknown
*pUnkOuter
= HeapAlloc(GetProcessHeap(), 0, sizeof(*pUnkOuter
));
2497 pUnkOuter
->IUnknown_iface
.lpVtbl
= &HeapUnknown_Vtbl
;
2498 pUnkOuter
->refs
= 1;
2500 hr
= CoGetPSClsid(riid
, &clsid
);
2501 ok_ole_success(hr
, CoGetPSClsid
);
2503 hr
= CoGetClassObject(&clsid
, CLSCTX_INPROC_SERVER
, NULL
, &IID_IPSFactoryBuffer
, (LPVOID
*)&psfb
);
2504 ok_ole_success(hr
, CoGetClassObject
);
2506 hr
= IPSFactoryBuffer_CreateProxy(psfb
, &pUnkOuter
->IUnknown_iface
, riid
, &proxy
, &lpvtbl
);
2507 ok_ole_success(hr
, IPSFactoryBuffer_CreateProxy
);
2508 ok(lpvtbl
!= NULL
, "IPSFactoryBuffer_CreateProxy succeeded, but returned a NULL vtable!\n");
2510 /* release our reference to the outer unknown object - the PS factory
2511 * buffer will have AddRef's it in the CreateProxy call */
2512 refs
= IUnknown_Release(&pUnkOuter
->IUnknown_iface
);
2513 ok(refs
== 1, "Ref count of outer unknown should have been 1 instead of %d\n", refs
);
2515 /* Not checking return, unreliable on native. Maybe it leaks references? */
2516 IPSFactoryBuffer_Release(psfb
);
2518 refs
= IUnknown_Release((IUnknown
*)lpvtbl
);
2519 ok(refs
== 0, "Ref-count leak of %d on IRpcProxyBuffer\n", refs
);
2521 refs
= IRpcProxyBuffer_Release(proxy
);
2522 ok(refs
== 0, "Ref-count leak of %d on IRpcProxyBuffer\n", refs
);
2525 static void test_stubbuffer(REFIID riid
)
2528 IPSFactoryBuffer
*psfb
;
2529 IRpcStubBuffer
*stub
;
2535 hr
= CoGetPSClsid(riid
, &clsid
);
2536 ok_ole_success(hr
, CoGetPSClsid
);
2538 hr
= CoGetClassObject(&clsid
, CLSCTX_INPROC_SERVER
, NULL
, &IID_IPSFactoryBuffer
, (LPVOID
*)&psfb
);
2539 ok_ole_success(hr
, CoGetClassObject
);
2541 hr
= IPSFactoryBuffer_CreateStub(psfb
, riid
, (IUnknown
*)&Test_ClassFactory
, &stub
);
2542 ok_ole_success(hr
, IPSFactoryBuffer_CreateStub
);
2544 /* Not checking return, unreliable on native. Maybe it leaks references? */
2545 IPSFactoryBuffer_Release(psfb
);
2547 ok_more_than_one_lock();
2549 IRpcStubBuffer_Disconnect(stub
);
2553 refs
= IRpcStubBuffer_Release(stub
);
2554 ok(refs
== 0, "Ref-count leak of %d on IRpcProxyBuffer\n", refs
);
2557 static HWND hwnd_app
;
2559 static HRESULT WINAPI
TestRE_IClassFactory_CreateInstance(
2560 LPCLASSFACTORY iface
,
2561 LPUNKNOWN pUnkOuter
,
2566 if (IsEqualIID(riid
, &IID_IWineTest
))
2568 BOOL ret
= SendMessageTimeoutA(hwnd_app
, WM_NULL
, 0, 0, SMTO_BLOCK
, 5000, &res
);
2569 ok(ret
, "Timed out sending a message to originating window during RPC call\n");
2575 static const IClassFactoryVtbl TestREClassFactory_Vtbl
=
2577 Test_IClassFactory_QueryInterface
,
2578 Test_IClassFactory_AddRef
,
2579 Test_IClassFactory_Release
,
2580 TestRE_IClassFactory_CreateInstance
,
2581 Test_IClassFactory_LockServer
2584 static IClassFactory TestRE_ClassFactory
= { &TestREClassFactory_Vtbl
};
2586 static LRESULT CALLBACK
window_proc(HWND hwnd
, UINT msg
, WPARAM wparam
, LPARAM lparam
)
2593 IStream
*pStream
= NULL
;
2594 IClassFactory
*proxy
= NULL
;
2601 hr
= CreateStreamOnHGlobal(NULL
, TRUE
, &pStream
);
2602 ok_ole_success(hr
, CreateStreamOnHGlobal
);
2603 tid
= start_host_object(pStream
, &IID_IClassFactory
, (IUnknown
*)&TestRE_ClassFactory
, MSHLFLAGS_NORMAL
, &thread
);
2605 ok_more_than_one_lock();
2607 IStream_Seek(pStream
, ullZero
, STREAM_SEEK_SET
, NULL
);
2608 hr
= CoUnmarshalInterface(pStream
, &IID_IClassFactory
, (void **)&proxy
);
2609 ok_ole_success(hr
, CoReleaseMarshalData
);
2610 IStream_Release(pStream
);
2612 ok_more_than_one_lock();
2614 /* note the use of the magic IID_IWineTest value to tell remote thread
2615 * to try to send a message back to us */
2616 hr
= IClassFactory_CreateInstance(proxy
, NULL
, &IID_IWineTest
, (void **)&object
);
2617 ok(hr
== S_FALSE
, "expected S_FALSE, got %d\n", hr
);
2619 IClassFactory_Release(proxy
);
2623 end_host_object(tid
, thread
);
2625 PostMessageA(hwnd
, WM_QUIT
, 0, 0);
2632 IStream
*pStream
= NULL
;
2633 IClassFactory
*proxy
= NULL
;
2640 hr
= CreateStreamOnHGlobal(NULL
, TRUE
, &pStream
);
2641 ok_ole_success(hr
, CreateStreamOnHGlobal
);
2642 tid
= start_host_object(pStream
, &IID_IClassFactory
, (IUnknown
*)&TestRE_ClassFactory
, MSHLFLAGS_NORMAL
, &thread
);
2644 ok_more_than_one_lock();
2646 IStream_Seek(pStream
, ullZero
, STREAM_SEEK_SET
, NULL
);
2647 hr
= CoUnmarshalInterface(pStream
, &IID_IClassFactory
, (void **)&proxy
);
2648 ok_ole_success(hr
, CoReleaseMarshalData
);
2649 IStream_Release(pStream
);
2651 ok_more_than_one_lock();
2653 /* post quit message before a doing a COM call to show that a pending
2654 * WM_QUIT message doesn't stop the call from succeeding */
2655 PostMessageA(hwnd
, WM_QUIT
, 0, 0);
2656 hr
= IClassFactory_CreateInstance(proxy
, NULL
, &IID_IUnknown
, (void **)&object
);
2657 ok(hr
== S_FALSE
, "IClassFactory_CreateInstance returned 0x%08x, expected S_FALSE\n", hr
);
2659 IClassFactory_Release(proxy
);
2663 end_host_object(tid
, thread
);
2670 IStream
*pStream
= NULL
;
2671 IClassFactory
*proxy
= NULL
;
2676 hr
= CreateStreamOnHGlobal(NULL
, TRUE
, &pStream
);
2677 ok_ole_success(hr
, CreateStreamOnHGlobal
);
2678 tid
= start_host_object(pStream
, &IID_IClassFactory
, (IUnknown
*)&Test_ClassFactory
, MSHLFLAGS_NORMAL
, &thread
);
2680 IStream_Seek(pStream
, ullZero
, STREAM_SEEK_SET
, NULL
);
2681 hr
= CoUnmarshalInterface(pStream
, &IID_IClassFactory
, (void **)&proxy
);
2682 ok_ole_success(hr
, CoReleaseMarshalData
);
2683 IStream_Release(pStream
);
2685 /* shows that COM calls executed during the processing of sent
2686 * messages should fail */
2687 hr
= IClassFactory_CreateInstance(proxy
, NULL
, &IID_IUnknown
, (void **)&object
);
2688 ok(hr
== RPC_E_CANTCALLOUT_ININPUTSYNCCALL
,
2689 "COM call during processing of sent message should return RPC_E_CANTCALLOUT_ININPUTSYNCCALL instead of 0x%08x\n", hr
);
2691 IClassFactory_Release(proxy
);
2693 end_host_object(tid
, thread
);
2700 return DefWindowProcA(hwnd
, msg
, wparam
, lparam
);
2704 static void register_test_window(void)
2708 memset(&wndclass
, 0, sizeof(wndclass
));
2709 wndclass
.lpfnWndProc
= window_proc
;
2710 wndclass
.lpszClassName
= "WineCOMTest";
2711 RegisterClassA(&wndclass
);
2714 static void test_message_reentrancy(void)
2718 hwnd_app
= CreateWindowA("WineCOMTest", NULL
, 0, CW_USEDEFAULT
, CW_USEDEFAULT
, CW_USEDEFAULT
, CW_USEDEFAULT
, NULL
, NULL
, NULL
, 0);
2719 ok(hwnd_app
!= NULL
, "Window creation failed\n");
2721 /* start message re-entrancy test */
2722 PostMessageA(hwnd_app
, WM_USER
, 0, 0);
2724 while (GetMessageA(&msg
, NULL
, 0, 0))
2726 TranslateMessage(&msg
);
2727 DispatchMessageA(&msg
);
2729 DestroyWindow(hwnd_app
);
2732 static HRESULT WINAPI
TestMsg_IClassFactory_CreateInstance(
2733 LPCLASSFACTORY iface
,
2734 LPUNKNOWN pUnkOuter
,
2739 SendMessageA(hwnd_app
, WM_USER
+2, 0, 0);
2743 static IClassFactoryVtbl TestMsgClassFactory_Vtbl
=
2745 Test_IClassFactory_QueryInterface
,
2746 Test_IClassFactory_AddRef
,
2747 Test_IClassFactory_Release
,
2748 TestMsg_IClassFactory_CreateInstance
,
2749 Test_IClassFactory_LockServer
2752 static IClassFactory TestMsg_ClassFactory
= { &TestMsgClassFactory_Vtbl
};
2754 static void test_call_from_message(void)
2759 IClassFactory
*proxy
;
2764 hwnd_app
= CreateWindowA("WineCOMTest", NULL
, 0, CW_USEDEFAULT
, CW_USEDEFAULT
, CW_USEDEFAULT
, CW_USEDEFAULT
, NULL
, NULL
, NULL
, 0);
2765 ok(hwnd_app
!= NULL
, "Window creation failed\n");
2767 hr
= CreateStreamOnHGlobal(NULL
, TRUE
, &pStream
);
2768 ok_ole_success(hr
, CreateStreamOnHGlobal
);
2769 tid
= start_host_object(pStream
, &IID_IClassFactory
, (IUnknown
*)&TestMsg_ClassFactory
, MSHLFLAGS_NORMAL
, &thread
);
2771 ok_more_than_one_lock();
2773 IStream_Seek(pStream
, ullZero
, STREAM_SEEK_SET
, NULL
);
2774 hr
= CoUnmarshalInterface(pStream
, &IID_IClassFactory
, (void **)&proxy
);
2775 ok_ole_success(hr
, CoReleaseMarshalData
);
2776 IStream_Release(pStream
);
2778 ok_more_than_one_lock();
2780 /* start message re-entrancy test */
2781 hr
= IClassFactory_CreateInstance(proxy
, NULL
, &IID_IUnknown
, (void **)&object
);
2782 ok_ole_success(hr
, IClassFactory_CreateInstance
);
2784 IClassFactory_Release(proxy
);
2788 end_host_object(tid
, thread
);
2790 while (GetMessageA(&msg
, NULL
, 0, 0))
2792 TranslateMessage(&msg
);
2793 DispatchMessageA(&msg
);
2795 DestroyWindow(hwnd_app
);
2798 static void test_WM_QUIT_handling(void)
2802 hwnd_app
= CreateWindowA("WineCOMTest", NULL
, 0, CW_USEDEFAULT
, CW_USEDEFAULT
, CW_USEDEFAULT
, CW_USEDEFAULT
, NULL
, NULL
, NULL
, 0);
2803 ok(hwnd_app
!= NULL
, "Window creation failed\n");
2805 /* start WM_QUIT handling test */
2806 PostMessageA(hwnd_app
, WM_USER
+1, 0, 0);
2808 while (GetMessageA(&msg
, NULL
, 0, 0))
2810 TranslateMessage(&msg
);
2811 DispatchMessageA(&msg
);
2815 static SIZE_T
round_global_size(SIZE_T size
)
2817 static SIZE_T global_size_alignment
= -1;
2818 if (global_size_alignment
== -1)
2820 void *p
= GlobalAlloc(GMEM_FIXED
, 1);
2821 global_size_alignment
= GlobalSize(p
);
2825 return ((size
+ global_size_alignment
- 1) & ~(global_size_alignment
- 1));
2828 static void test_freethreadedmarshaldata(IStream
*pStream
, MSHCTX mshctx
, void *ptr
, DWORD mshlflags
)
2835 hr
= GetHGlobalFromStream(pStream
, &hglobal
);
2836 ok_ole_success(hr
, GetHGlobalFromStream
);
2838 size
= GlobalSize(hglobal
);
2840 marshal_data
= GlobalLock(hglobal
);
2842 if (mshctx
== MSHCTX_INPROC
)
2844 DWORD expected_size
= round_global_size(3*sizeof(DWORD
) + sizeof(GUID
));
2845 ok(size
== expected_size
||
2846 broken(size
== (2*sizeof(DWORD
))) /* Win9x & NT4 */,
2847 "size should have been %d instead of %d\n", expected_size
, size
);
2849 ok(*(DWORD
*)marshal_data
== mshlflags
, "expected 0x%x, but got 0x%x for mshctx\n", mshlflags
, *(DWORD
*)marshal_data
);
2850 marshal_data
+= sizeof(DWORD
);
2851 ok(*(void **)marshal_data
== ptr
, "expected %p, but got %p for mshctx\n", ptr
, *(void **)marshal_data
);
2852 marshal_data
+= sizeof(void *);
2853 if (sizeof(void*) == 4 && size
>= 3*sizeof(DWORD
))
2855 ok(*(DWORD
*)marshal_data
== 0, "expected 0x0, but got 0x%x\n", *(DWORD
*)marshal_data
);
2856 marshal_data
+= sizeof(DWORD
);
2858 if (size
>= 3*sizeof(DWORD
) + sizeof(GUID
))
2860 trace("got guid data: %s\n", wine_dbgstr_guid((GUID
*)marshal_data
));
2865 ok(size
> sizeof(DWORD
), "size should have been > sizeof(DWORD), not %d\n", size
);
2866 ok(*(DWORD
*)marshal_data
== 0x574f454d /* MEOW */,
2867 "marshal data should be filled by standard marshal and start with MEOW signature\n");
2870 GlobalUnlock(hglobal
);
2873 static void test_freethreadedmarshaler(void)
2876 IUnknown
*pFTUnknown
;
2877 IMarshal
*pFTMarshal
;
2880 static const LARGE_INTEGER llZero
;
2883 hr
= CoCreateFreeThreadedMarshaler(NULL
, &pFTUnknown
);
2884 ok_ole_success(hr
, CoCreateFreeThreadedMarshaler
);
2885 hr
= IUnknown_QueryInterface(pFTUnknown
, &IID_IMarshal
, (void **)&pFTMarshal
);
2886 ok_ole_success(hr
, IUnknown_QueryInterface
);
2887 IUnknown_Release(pFTUnknown
);
2889 hr
= CreateStreamOnHGlobal(NULL
, TRUE
, &pStream
);
2890 ok_ole_success(hr
, CreateStreamOnHGlobal
);
2892 /* inproc normal marshaling */
2894 hr
= IMarshal_MarshalInterface(pFTMarshal
, pStream
, &IID_IClassFactory
,
2895 &Test_ClassFactory
, MSHCTX_INPROC
, NULL
, MSHLFLAGS_NORMAL
);
2896 ok_ole_success(hr
, IMarshal_MarshalInterface
);
2898 ok_more_than_one_lock();
2900 test_freethreadedmarshaldata(pStream
, MSHCTX_INPROC
, &Test_ClassFactory
, MSHLFLAGS_NORMAL
);
2902 IStream_Seek(pStream
, llZero
, STREAM_SEEK_SET
, NULL
);
2903 hr
= IMarshal_UnmarshalInterface(pFTMarshal
, pStream
, &IID_IUnknown
, (void **)&pProxy
);
2904 ok_ole_success(hr
, IMarshal_UnmarshalInterface
);
2906 IUnknown_Release(pProxy
);
2910 /* native doesn't allow us to unmarshal or release the stream data,
2911 * presumably because it wants us to call CoMarshalInterface instead */
2914 /* local normal marshaling */
2916 IStream_Seek(pStream
, llZero
, STREAM_SEEK_SET
, NULL
);
2917 hr
= IMarshal_MarshalInterface(pFTMarshal
, pStream
, &IID_IClassFactory
, &Test_ClassFactory
, MSHCTX_LOCAL
, NULL
, MSHLFLAGS_NORMAL
);
2918 ok_ole_success(hr
, IMarshal_MarshalInterface
);
2920 ok_more_than_one_lock();
2922 test_freethreadedmarshaldata(pStream
, MSHCTX_LOCAL
, &Test_ClassFactory
, MSHLFLAGS_NORMAL
);
2924 IStream_Seek(pStream
, llZero
, STREAM_SEEK_SET
, NULL
);
2925 hr
= IMarshal_ReleaseMarshalData(pFTMarshal
, pStream
);
2926 ok_ole_success(hr
, IMarshal_ReleaseMarshalData
);
2931 /* inproc table-strong marshaling */
2933 IStream_Seek(pStream
, llZero
, STREAM_SEEK_SET
, NULL
);
2934 hr
= IMarshal_MarshalInterface(pFTMarshal
, pStream
, &IID_IClassFactory
,
2935 (IUnknown
*)&Test_ClassFactory
, MSHCTX_INPROC
, (void *)0xdeadbeef,
2936 MSHLFLAGS_TABLESTRONG
);
2937 ok_ole_success(hr
, IMarshal_MarshalInterface
);
2939 ok_more_than_one_lock();
2941 test_freethreadedmarshaldata(pStream
, MSHCTX_INPROC
, &Test_ClassFactory
, MSHLFLAGS_TABLESTRONG
);
2943 IStream_Seek(pStream
, llZero
, STREAM_SEEK_SET
, NULL
);
2944 hr
= IMarshal_UnmarshalInterface(pFTMarshal
, pStream
, &IID_IUnknown
, (void **)&pProxy
);
2945 ok_ole_success(hr
, IMarshal_UnmarshalInterface
);
2947 IUnknown_Release(pProxy
);
2949 ok_more_than_one_lock();
2951 IStream_Seek(pStream
, llZero
, STREAM_SEEK_SET
, NULL
);
2952 hr
= IMarshal_ReleaseMarshalData(pFTMarshal
, pStream
);
2953 ok_ole_success(hr
, IMarshal_ReleaseMarshalData
);
2957 /* inproc table-weak marshaling */
2959 IStream_Seek(pStream
, llZero
, STREAM_SEEK_SET
, NULL
);
2960 hr
= IMarshal_MarshalInterface(pFTMarshal
, pStream
, &IID_IClassFactory
,
2961 (IUnknown
*)&Test_ClassFactory
, MSHCTX_INPROC
, (void *)0xdeadbeef,
2962 MSHLFLAGS_TABLEWEAK
);
2963 ok_ole_success(hr
, IMarshal_MarshalInterface
);
2967 test_freethreadedmarshaldata(pStream
, MSHCTX_INPROC
, &Test_ClassFactory
, MSHLFLAGS_TABLEWEAK
);
2969 IStream_Seek(pStream
, llZero
, STREAM_SEEK_SET
, NULL
);
2970 hr
= IMarshal_UnmarshalInterface(pFTMarshal
, pStream
, &IID_IUnknown
, (void **)&pProxy
);
2971 ok_ole_success(hr
, IMarshal_UnmarshalInterface
);
2973 ok_more_than_one_lock();
2975 IUnknown_Release(pProxy
);
2979 /* inproc normal marshaling (for extraordinary cases) */
2981 IStream_Seek(pStream
, llZero
, STREAM_SEEK_SET
, NULL
);
2982 hr
= IMarshal_MarshalInterface(pFTMarshal
, pStream
, &IID_IClassFactory
,
2983 &Test_ClassFactory
, MSHCTX_INPROC
, NULL
, MSHLFLAGS_NORMAL
);
2984 ok_ole_success(hr
, IMarshal_MarshalInterface
);
2986 ok_more_than_one_lock();
2988 /* this call shows that DisconnectObject does nothing */
2989 hr
= IMarshal_DisconnectObject(pFTMarshal
, 0);
2990 ok_ole_success(hr
, IMarshal_DisconnectObject
);
2992 ok_more_than_one_lock();
2994 IStream_Seek(pStream
, llZero
, STREAM_SEEK_SET
, NULL
);
2995 hr
= IMarshal_ReleaseMarshalData(pFTMarshal
, pStream
);
2996 ok_ole_success(hr
, IMarshal_ReleaseMarshalData
);
3000 /* doesn't enforce marshaling rules here and allows us to unmarshal the
3001 * interface, even though it was freed above */
3002 IStream_Seek(pStream
, llZero
, STREAM_SEEK_SET
, NULL
);
3003 hr
= IMarshal_UnmarshalInterface(pFTMarshal
, pStream
, &IID_IUnknown
, (void **)&pProxy
);
3004 ok_ole_success(hr
, IMarshal_UnmarshalInterface
);
3008 IStream_Release(pStream
);
3009 IMarshal_Release(pFTMarshal
);
3012 static HRESULT
reg_unreg_wine_test_class(BOOL Register
)
3018 DWORD dwDisposition
;
3021 hr
= StringFromCLSID(&CLSID_WineTest
, &pszClsid
);
3022 ok_ole_success(hr
, "StringFromCLSID");
3023 strcpy(buffer
, "CLSID\\");
3024 WideCharToMultiByte(CP_ACP
, 0, pszClsid
, -1, buffer
+ strlen(buffer
), sizeof(buffer
) - strlen(buffer
), NULL
, NULL
);
3025 CoTaskMemFree(pszClsid
);
3026 strcat(buffer
, "\\InprocHandler32");
3029 error
= RegCreateKeyExA(HKEY_CLASSES_ROOT
, buffer
, 0, NULL
, 0, KEY_SET_VALUE
, NULL
, &hkey
, &dwDisposition
);
3030 if (error
== ERROR_ACCESS_DENIED
)
3032 skip("Not authorized to modify the Classes key\n");
3035 ok(error
== ERROR_SUCCESS
, "RegCreateKeyEx failed with error %d\n", error
);
3036 if (error
!= ERROR_SUCCESS
) hr
= E_FAIL
;
3037 error
= RegSetValueExA(hkey
, NULL
, 0, REG_SZ
, (const unsigned char *)"\"ole32.dll\"", strlen("\"ole32.dll\"") + 1);
3038 ok(error
== ERROR_SUCCESS
, "RegSetValueEx failed with error %d\n", error
);
3039 if (error
!= ERROR_SUCCESS
) hr
= E_FAIL
;
3044 RegDeleteKeyA(HKEY_CLASSES_ROOT
, buffer
);
3045 *strrchr(buffer
, '\\') = '\0';
3046 RegDeleteKeyA(HKEY_CLASSES_ROOT
, buffer
);
3051 static void test_inproc_handler(void)
3057 if (FAILED(reg_unreg_wine_test_class(TRUE
)))
3060 hr
= CoCreateInstance(&CLSID_WineTest
, NULL
, CLSCTX_INPROC_HANDLER
, &IID_IUnknown
, (void **)&pObject
);
3061 ok_ole_success(hr
, "CoCreateInstance");
3065 hr
= IUnknown_QueryInterface(pObject
, &IID_IWineTest
, (void **)&pObject2
);
3066 ok(hr
== E_NOINTERFACE
, "IUnknown_QueryInterface on handler for invalid interface returned 0x%08x instead of E_NOINTERFACE\n", hr
);
3068 /* it's a handler as it supports IOleObject */
3069 hr
= IUnknown_QueryInterface(pObject
, &IID_IOleObject
, (void **)&pObject2
);
3070 ok_ole_success(hr
, "IUnknown_QueryInterface(&IID_IOleObject)");
3071 IUnknown_Release(pObject2
);
3073 IUnknown_Release(pObject
);
3076 reg_unreg_wine_test_class(FALSE
);
3079 static HRESULT WINAPI
Test_SMI_QueryInterface(
3080 IStdMarshalInfo
*iface
,
3084 if (ppvObj
== NULL
) return E_POINTER
;
3086 if (IsEqualGUID(riid
, &IID_IUnknown
) ||
3087 IsEqualGUID(riid
, &IID_IStdMarshalInfo
))
3090 IStdMarshalInfo_AddRef(iface
);
3094 return E_NOINTERFACE
;
3097 static ULONG WINAPI
Test_SMI_AddRef(IStdMarshalInfo
*iface
)
3100 return 2; /* non-heap-based object */
3103 static ULONG WINAPI
Test_SMI_Release(IStdMarshalInfo
*iface
)
3106 return 1; /* non-heap-based object */
3109 static HRESULT WINAPI
Test_SMI_GetClassForHandler(
3110 IStdMarshalInfo
*iface
,
3111 DWORD dwDestContext
,
3112 void *pvDestContext
,
3115 *pClsid
= CLSID_WineTest
;
3119 static const IStdMarshalInfoVtbl Test_SMI_Vtbl
=
3121 Test_SMI_QueryInterface
,
3124 Test_SMI_GetClassForHandler
3127 static IStdMarshalInfo Test_SMI
= {&Test_SMI_Vtbl
};
3129 static void test_handler_marshaling(void)
3132 IStream
*pStream
= NULL
;
3133 IUnknown
*pProxy
= NULL
;
3137 static const LARGE_INTEGER ullZero
;
3139 if (FAILED(reg_unreg_wine_test_class(TRUE
)))
3143 hr
= CreateStreamOnHGlobal(NULL
, TRUE
, &pStream
);
3144 ok_ole_success(hr
, "CreateStreamOnHGlobal");
3145 tid
= start_host_object(pStream
, &IID_IUnknown
, (IUnknown
*)&Test_SMI
, MSHLFLAGS_NORMAL
, &thread
);
3147 ok_more_than_one_lock();
3149 IStream_Seek(pStream
, ullZero
, STREAM_SEEK_SET
, NULL
);
3150 hr
= CoUnmarshalInterface(pStream
, &IID_IUnknown
, (void **)&pProxy
);
3151 ok_ole_success(hr
, "CoUnmarshalInterface");
3152 IStream_Release(pStream
);
3156 ok_more_than_one_lock();
3158 hr
= IUnknown_QueryInterface(pProxy
, &IID_IWineTest
, (void **)&pObject
);
3159 ok(hr
== E_NOINTERFACE
, "IUnknown_QueryInterface with unknown IID should have returned E_NOINTERFACE instead of 0x%08x\n", hr
);
3161 /* it's a handler as it supports IOleObject */
3162 hr
= IUnknown_QueryInterface(pProxy
, &IID_IOleObject
, (void **)&pObject
);
3164 ok_ole_success(hr
, "IUnknown_QueryInterface(&IID_IOleObject)");
3165 if (SUCCEEDED(hr
)) IUnknown_Release(pObject
);
3167 IUnknown_Release(pProxy
);
3172 end_host_object(tid
, thread
);
3173 reg_unreg_wine_test_class(FALSE
);
3175 /* FIXME: test IPersist interface has the same effect as IStdMarshalInfo */
3179 static void test_client_security(void)
3182 IStream
*pStream
= NULL
;
3183 IClassFactory
*pProxy
= NULL
;
3184 IUnknown
*pProxy2
= NULL
;
3185 IUnknown
*pUnknown1
= NULL
;
3186 IUnknown
*pUnknown2
= NULL
;
3187 IClientSecurity
*pCliSec
= NULL
;
3191 static const LARGE_INTEGER ullZero
;
3194 OLECHAR
*pServerPrincName
;
3198 DWORD dwCapabilities
;
3203 hr
= CreateStreamOnHGlobal(NULL
, TRUE
, &pStream
);
3204 ok_ole_success(hr
, "CreateStreamOnHGlobal");
3205 tid
= start_host_object(pStream
, &IID_IClassFactory
, (IUnknown
*)&Test_ClassFactory
, MSHLFLAGS_NORMAL
, &thread
);
3207 IStream_Seek(pStream
, ullZero
, STREAM_SEEK_SET
, NULL
);
3208 hr
= CoUnmarshalInterface(pStream
, &IID_IClassFactory
, (void **)&pProxy
);
3209 ok_ole_success(hr
, "CoUnmarshalInterface");
3210 IStream_Release(pStream
);
3212 hr
= IClassFactory_QueryInterface(pProxy
, &IID_IUnknown
, (LPVOID
*)&pUnknown1
);
3213 ok_ole_success(hr
, "IUnknown_QueryInterface IID_IUnknown");
3215 hr
= IClassFactory_QueryInterface(pProxy
, &IID_IRemUnknown
, (LPVOID
*)&pProxy2
);
3216 ok_ole_success(hr
, "IUnknown_QueryInterface IID_IStream");
3218 hr
= IUnknown_QueryInterface(pProxy2
, &IID_IUnknown
, (LPVOID
*)&pUnknown2
);
3219 ok_ole_success(hr
, "IUnknown_QueryInterface IID_IUnknown");
3221 ok(pUnknown1
== pUnknown2
, "both proxy's IUnknowns should be the same - %p, %p\n", pUnknown1
, pUnknown2
);
3223 hr
= IClassFactory_QueryInterface(pProxy
, &IID_IMarshal
, (LPVOID
*)&pMarshal
);
3224 ok_ole_success(hr
, "IUnknown_QueryInterface IID_IMarshal");
3226 hr
= IClassFactory_QueryInterface(pProxy
, &IID_IClientSecurity
, (LPVOID
*)&pCliSec
);
3227 ok_ole_success(hr
, "IUnknown_QueryInterface IID_IClientSecurity");
3229 hr
= IClientSecurity_QueryBlanket(pCliSec
, (IUnknown
*)pProxy
, NULL
, NULL
, NULL
, NULL
, NULL
, NULL
, NULL
);
3230 todo_wine
ok_ole_success(hr
, "IClientSecurity_QueryBlanket (all NULLs)");
3232 hr
= IClientSecurity_QueryBlanket(pCliSec
, (IUnknown
*)pMarshal
, NULL
, NULL
, NULL
, NULL
, NULL
, NULL
, NULL
);
3233 todo_wine
ok(hr
== E_NOINTERFACE
, "IClientSecurity_QueryBlanket with local interface should have returned E_NOINTERFACE instead of 0x%08x\n", hr
);
3235 hr
= IClientSecurity_QueryBlanket(pCliSec
, (IUnknown
*)pProxy
, &dwAuthnSvc
, &dwAuthzSvc
, &pServerPrincName
, &dwAuthnLevel
, &dwImpLevel
, &pAuthInfo
, &dwCapabilities
);
3236 todo_wine
ok_ole_success(hr
, "IClientSecurity_QueryBlanket");
3238 hr
= IClientSecurity_SetBlanket(pCliSec
, (IUnknown
*)pProxy
, dwAuthnSvc
, dwAuthzSvc
, pServerPrincName
, dwAuthnLevel
, RPC_C_IMP_LEVEL_IMPERSONATE
, pAuthInfo
, dwCapabilities
);
3239 todo_wine
ok_ole_success(hr
, "IClientSecurity_SetBlanket");
3241 hr
= IClassFactory_CreateInstance(pProxy
, NULL
, &IID_IWineTest
, &pv
);
3242 ok(hr
== E_NOINTERFACE
, "COM call should have succeeded instead of returning 0x%08x\n", hr
);
3244 hr
= IClientSecurity_SetBlanket(pCliSec
, (IUnknown
*)pMarshal
, dwAuthnSvc
, dwAuthzSvc
, pServerPrincName
, dwAuthnLevel
, dwImpLevel
, pAuthInfo
, dwCapabilities
);
3245 todo_wine
ok(hr
== E_NOINTERFACE
, "IClientSecurity_SetBlanket with local interface should have returned E_NOINTERFACE instead of 0x%08x\n", hr
);
3247 hr
= IClientSecurity_SetBlanket(pCliSec
, (IUnknown
*)pProxy
, 0xdeadbeef, dwAuthzSvc
, pServerPrincName
, dwAuthnLevel
, dwImpLevel
, pAuthInfo
, dwCapabilities
);
3248 todo_wine
ok(hr
== E_INVALIDARG
, "IClientSecurity_SetBlanke with invalid dwAuthnSvc should have returned E_INVALIDARG instead of 0x%08x\n", hr
);
3250 CoTaskMemFree(pServerPrincName
);
3252 hr
= IClientSecurity_QueryBlanket(pCliSec
, pUnknown1
, &dwAuthnSvc
, &dwAuthzSvc
, &pServerPrincName
, &dwAuthnLevel
, &dwImpLevel
, &pAuthInfo
, &dwCapabilities
);
3253 todo_wine
ok_ole_success(hr
, "IClientSecurity_QueryBlanket(IUnknown)");
3255 CoTaskMemFree(pServerPrincName
);
3257 IClassFactory_Release(pProxy
);
3258 IUnknown_Release(pProxy2
);
3259 IUnknown_Release(pUnknown1
);
3260 IUnknown_Release(pUnknown2
);
3261 IMarshal_Release(pMarshal
);
3262 IClientSecurity_Release(pCliSec
);
3264 end_host_object(tid
, thread
);
3267 static HANDLE heventShutdown
;
3269 static void LockModuleOOP(void)
3271 InterlockedIncrement(&cLocks
); /* for test purposes only */
3272 CoAddRefServerProcess();
3275 static void UnlockModuleOOP(void)
3277 InterlockedDecrement(&cLocks
); /* for test purposes only */
3278 if (!CoReleaseServerProcess())
3279 SetEvent(heventShutdown
);
3282 static HWND hwnd_app
;
3286 IPersist IPersist_iface
; /* a nice short interface */
3289 static HRESULT WINAPI
local_server_QueryInterface(IPersist
*iface
, REFIID iid
, void **obj
)
3293 if (IsEqualGUID(iid
, &IID_IUnknown
) ||
3294 IsEqualGUID(iid
, &IID_IPersist
))
3299 IPersist_AddRef(iface
);
3302 return E_NOINTERFACE
;
3305 static ULONG WINAPI
local_server_AddRef(IPersist
*iface
)
3310 static ULONG WINAPI
local_server_Release(IPersist
*iface
)
3315 static HRESULT WINAPI
local_server_GetClassID(IPersist
*iface
, CLSID
*clsid
)
3319 *clsid
= IID_IUnknown
;
3321 /* Test calling CoDisconnectObject within a COM call */
3322 hr
= CoDisconnectObject((IUnknown
*)iface
, 0);
3323 ok(hr
== S_OK
, "got %08x\n", hr
);
3325 /* Initialize and uninitialize the apartment to show that we
3326 * remain in the autojoined mta */
3327 hr
= pCoInitializeEx( NULL
, COINIT_MULTITHREADED
);
3328 ok( hr
== S_FALSE
, "got %08x\n", hr
);
3334 static const IPersistVtbl local_server_persist_vtbl
=
3336 local_server_QueryInterface
,
3337 local_server_AddRef
,
3338 local_server_Release
,
3339 local_server_GetClassID
3342 struct local_server local_server_class
=
3344 {&local_server_persist_vtbl
}
3347 static HRESULT WINAPI
TestOOP_IClassFactory_QueryInterface(
3348 LPCLASSFACTORY iface
,
3352 if (ppvObj
== NULL
) return E_POINTER
;
3354 if (IsEqualGUID(riid
, &IID_IUnknown
) ||
3355 IsEqualGUID(riid
, &IID_IClassFactory
))
3358 IClassFactory_AddRef(iface
);
3362 return E_NOINTERFACE
;
3365 static ULONG WINAPI
TestOOP_IClassFactory_AddRef(LPCLASSFACTORY iface
)
3367 return 2; /* non-heap-based object */
3370 static ULONG WINAPI
TestOOP_IClassFactory_Release(LPCLASSFACTORY iface
)
3372 return 1; /* non-heap-based object */
3375 static HRESULT WINAPI
TestOOP_IClassFactory_CreateInstance(
3376 LPCLASSFACTORY iface
,
3377 LPUNKNOWN pUnkOuter
,
3381 IPersist
*persist
= &local_server_class
.IPersist_iface
;
3383 IPersist_AddRef( persist
);
3384 hr
= IPersist_QueryInterface( persist
, riid
, ppvObj
);
3385 IPersist_Release( persist
);
3389 static HRESULT WINAPI
TestOOP_IClassFactory_LockServer(
3390 LPCLASSFACTORY iface
,
3400 static const IClassFactoryVtbl TestClassFactoryOOP_Vtbl
=
3402 TestOOP_IClassFactory_QueryInterface
,
3403 TestOOP_IClassFactory_AddRef
,
3404 TestOOP_IClassFactory_Release
,
3405 TestOOP_IClassFactory_CreateInstance
,
3406 TestOOP_IClassFactory_LockServer
3409 static IClassFactory TestOOP_ClassFactory
= { &TestClassFactoryOOP_Vtbl
};
3411 static void test_register_local_server(void)
3419 heventShutdown
= CreateEventA(NULL
, TRUE
, FALSE
, NULL
);
3420 ready_event
= CreateEventA(NULL
, FALSE
, FALSE
, "Wine COM Test Ready Event");
3421 handles
[0] = CreateEventA(NULL
, FALSE
, FALSE
, "Wine COM Test Quit Event");
3422 handles
[1] = CreateEventA(NULL
, FALSE
, FALSE
, "Wine COM Test Repeat Event");
3425 hr
= CoRegisterClassObject(&CLSID_WineOOPTest
, (IUnknown
*)&TestOOP_ClassFactory
,
3426 CLSCTX_LOCAL_SERVER
, REGCLS_SINGLEUSE
, &cookie
);
3427 ok_ole_success(hr
, CoRegisterClassObject
);
3429 SetEvent(ready_event
);
3433 wait
= MsgWaitForMultipleObjects(2, handles
, FALSE
, 30000, QS_ALLINPUT
);
3434 if (wait
== WAIT_OBJECT_0
+2)
3438 if (PeekMessageA(&msg
, NULL
, 0, 0, PM_REMOVE
))
3440 trace("Message 0x%x\n", msg
.message
);
3441 TranslateMessage(&msg
);
3442 DispatchMessageA(&msg
);
3445 else if (wait
== WAIT_OBJECT_0
+1)
3447 hr
= CoRevokeClassObject(cookie
);
3448 ok_ole_success(hr
, CoRevokeClassObject
);
3452 while (wait
== WAIT_OBJECT_0
+2);
3454 ok( wait
== WAIT_OBJECT_0
, "quit event wait timed out\n" );
3455 hr
= CoRevokeClassObject(cookie
);
3456 ok_ole_success(hr
, CoRevokeClassObject
);
3457 CloseHandle(handles
[0]);
3458 CloseHandle(handles
[1]);
3461 static HANDLE
create_target_process(const char *arg
)
3464 char cmdline
[MAX_PATH
];
3466 PROCESS_INFORMATION pi
;
3467 STARTUPINFOA si
= { 0 };
3472 winetest_get_mainargs( &argv
);
3473 sprintf(cmdline
, "\"%s\" %s %s", argv
[0], argv
[1], arg
);
3474 ret
= CreateProcessA(argv
[0], cmdline
, NULL
, NULL
, FALSE
, 0, NULL
, NULL
, &si
, &pi
);
3475 ok(ret
, "CreateProcess failed with error: %u\n", GetLastError());
3476 if (pi
.hThread
) CloseHandle(pi
.hThread
);
3480 /* tests functions commonly used by out of process COM servers */
3481 static void test_local_server(void)
3491 HANDLE repeat_event
;
3494 heventShutdown
= CreateEventA(NULL
, TRUE
, FALSE
, NULL
);
3498 /* Start the object suspended */
3499 hr
= CoRegisterClassObject(&CLSID_WineOOPTest
, (IUnknown
*)&TestOOP_ClassFactory
,
3500 CLSCTX_LOCAL_SERVER
, REGCLS_MULTIPLEUSE
| REGCLS_SUSPENDED
, &cookie
);
3501 ok_ole_success(hr
, CoRegisterClassObject
);
3503 /* ... and CoGetClassObject does not find it and fails when it looks for the
3504 * class in the registry */
3505 hr
= CoGetClassObject(&CLSID_WineOOPTest
, CLSCTX_INPROC_SERVER
,
3506 NULL
, &IID_IClassFactory
, (LPVOID
*)&cf
);
3507 ok(hr
== REGDB_E_CLASSNOTREG
|| /* NT */
3508 hr
== S_OK
/* Win9x */,
3509 "CoGetClassObject should have returned REGDB_E_CLASSNOTREG instead of 0x%08x\n", hr
);
3511 /* Resume the object suspended above ... */
3512 hr
= CoResumeClassObjects();
3513 ok_ole_success(hr
, CoResumeClassObjects
);
3515 /* ... and now it should succeed */
3516 hr
= CoGetClassObject(&CLSID_WineOOPTest
, CLSCTX_INPROC_SERVER
,
3517 NULL
, &IID_IClassFactory
, (LPVOID
*)&cf
);
3518 ok_ole_success(hr
, CoGetClassObject
);
3520 /* Now check the locking is working */
3521 /* NOTE: we are accessing the class directly, not through a proxy */
3525 hr
= IClassFactory_LockServer(cf
, TRUE
);
3526 ok_ole_success(hr
, IClassFactory_LockServer
);
3528 ok_more_than_one_lock();
3530 IClassFactory_LockServer(cf
, FALSE
);
3531 ok_ole_success(hr
, IClassFactory_LockServer
);
3535 IClassFactory_Release(cf
);
3537 /* wait for shutdown signal */
3538 ret
= WaitForSingleObject(heventShutdown
, 0);
3539 ok(ret
!= WAIT_TIMEOUT
, "Server didn't shut down\n");
3541 /* try to connect again after SCM has suspended registered class objects */
3542 hr
= CoGetClassObject(&CLSID_WineOOPTest
, CLSCTX_INPROC_SERVER
| CLSCTX_LOCAL_SERVER
, NULL
,
3543 &IID_IClassFactory
, (LPVOID
*)&cf
);
3544 ok(hr
== CO_E_SERVER_STOPPING
|| /* NT */
3545 hr
== REGDB_E_CLASSNOTREG
|| /* win2k */
3546 hr
== S_OK
/* Win9x */,
3547 "CoGetClassObject should have returned CO_E_SERVER_STOPPING or REGDB_E_CLASSNOTREG instead of 0x%08x\n", hr
);
3549 hr
= CoRevokeClassObject(cookie
);
3550 ok_ole_success(hr
, CoRevokeClassObject
);
3552 CloseHandle(heventShutdown
);
3554 process
= create_target_process("-Embedding");
3555 ok(process
!= NULL
, "couldn't start local server process, error was %d\n", GetLastError());
3557 ready_event
= CreateEventA(NULL
, FALSE
, FALSE
, "Wine COM Test Ready Event");
3558 ok( !WaitForSingleObject(ready_event
, 10000), "wait timed out\n" );
3560 hr
= CoCreateInstance(&CLSID_WineOOPTest
, NULL
, CLSCTX_LOCAL_SERVER
, &IID_IPersist
, (void **)&persist
);
3561 ok_ole_success(hr
, CoCreateInstance
);
3563 IPersist_Release(persist
);
3565 hr
= CoCreateInstance(&CLSID_WineOOPTest
, NULL
, CLSCTX_LOCAL_SERVER
, &IID_IPersist
, (void **)&persist
);
3566 ok(hr
== REGDB_E_CLASSNOTREG
, "Second CoCreateInstance on REGCLS_SINGLEUSE object should have failed\n");
3568 /* Re-register the class and try calling CoDisconnectObject from within a call to that object */
3569 repeat_event
= CreateEventA(NULL
, FALSE
, FALSE
, "Wine COM Test Repeat Event");
3570 SetEvent(repeat_event
);
3571 CloseHandle(repeat_event
);
3573 ok( !WaitForSingleObject(ready_event
, 10000), "wait timed out\n" );
3574 CloseHandle(ready_event
);
3576 hr
= CoCreateInstance(&CLSID_WineOOPTest
, NULL
, CLSCTX_LOCAL_SERVER
, &IID_IPersist
, (void **)&persist
);
3577 ok_ole_success(hr
, CoCreateInstance
);
3579 /* GetClassID will call CoDisconnectObject */
3580 IPersist_GetClassID(persist
, &clsid
);
3581 IPersist_Release(persist
);
3583 quit_event
= CreateEventA(NULL
, FALSE
, FALSE
, "Wine COM Test Quit Event");
3584 SetEvent(quit_event
);
3586 winetest_wait_child_process( process
);
3587 CloseHandle(quit_event
);
3588 CloseHandle(process
);
3594 IGlobalInterfaceTable
*git
;
3597 static DWORD CALLBACK
get_global_interface_proc(LPVOID pv
)
3600 struct git_params
*params
= pv
;
3603 hr
= IGlobalInterfaceTable_GetInterfaceFromGlobal(params
->git
, params
->cookie
, &IID_IClassFactory
, (void **)&cf
);
3604 ok(hr
== CO_E_NOTINITIALIZED
||
3605 broken(hr
== E_UNEXPECTED
) /* win2k */ ||
3606 broken(hr
== S_OK
) /* NT 4 */,
3607 "IGlobalInterfaceTable_GetInterfaceFromGlobal should have failed with error CO_E_NOTINITIALIZED or E_UNEXPECTED instead of 0x%08x\n",
3610 IClassFactory_Release(cf
);
3614 hr
= IGlobalInterfaceTable_GetInterfaceFromGlobal(params
->git
, params
->cookie
, &IID_IClassFactory
, (void **)&cf
);
3615 ok_ole_success(hr
, IGlobalInterfaceTable_GetInterfaceFromGlobal
);
3617 IClassFactory_Release(cf
);
3624 static void test_globalinterfacetable(void)
3627 IGlobalInterfaceTable
*git
;
3631 struct git_params params
;
3637 trace("test_globalinterfacetable\n");
3640 hr
= pDllGetClassObject(&CLSID_StdGlobalInterfaceTable
, &IID_IClassFactory
, (void**)&cf
);
3641 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3643 hr
= IClassFactory_QueryInterface(cf
, &IID_IGlobalInterfaceTable
, (void**)&object
);
3644 ok(hr
== E_NOINTERFACE
, "got 0x%08x\n", hr
);
3646 IClassFactory_Release(cf
);
3648 hr
= CoCreateInstance(&CLSID_StdGlobalInterfaceTable
, NULL
, CLSCTX_INPROC_SERVER
, &IID_IGlobalInterfaceTable
, (void **)&git
);
3649 ok_ole_success(hr
, CoCreateInstance
);
3651 ref
= IGlobalInterfaceTable_AddRef(git
);
3652 ok(ref
== 1, "ref=%d\n", ref
);
3653 ref
= IGlobalInterfaceTable_AddRef(git
);
3654 ok(ref
== 1, "ref=%d\n", ref
);
3656 ref
= IGlobalInterfaceTable_Release(git
);
3657 ok(ref
== 1, "ref=%d\n", ref
);
3658 ref
= IGlobalInterfaceTable_Release(git
);
3659 ok(ref
== 1, "ref=%d\n", ref
);
3661 hr
= IGlobalInterfaceTable_RegisterInterfaceInGlobal(git
, (IUnknown
*)&Test_ClassFactory
, &IID_IClassFactory
, &cookie
);
3662 ok_ole_success(hr
, IGlobalInterfaceTable_RegisterInterfaceInGlobal
);
3664 ok_more_than_one_lock();
3666 params
.cookie
= cookie
;
3668 /* note: params is on stack so we MUST wait for get_global_interface_proc
3669 * to exit before we can return */
3670 thread
= CreateThread(NULL
, 0, get_global_interface_proc
, ¶ms
, 0, &tid
);
3672 ret
= MsgWaitForMultipleObjects(1, &thread
, FALSE
, 10000, QS_ALLINPUT
);
3673 while (ret
== WAIT_OBJECT_0
+ 1)
3676 while (PeekMessageA(&msg
, NULL
, 0, 0, PM_REMOVE
))
3677 DispatchMessageA(&msg
);
3678 ret
= MsgWaitForMultipleObjects(1, &thread
, FALSE
, 10000, QS_ALLINPUT
);
3681 CloseHandle(thread
);
3683 /* test getting interface from global with different iid */
3684 hr
= IGlobalInterfaceTable_GetInterfaceFromGlobal(git
, cookie
, &IID_IUnknown
, (void **)&object
);
3685 ok_ole_success(hr
, IGlobalInterfaceTable_GetInterfaceFromGlobal
);
3686 IUnknown_Release(object
);
3688 /* test getting interface from global with same iid */
3689 hr
= IGlobalInterfaceTable_GetInterfaceFromGlobal(git
, cookie
, &IID_IClassFactory
, (void **)&object
);
3690 ok_ole_success(hr
, IGlobalInterfaceTable_GetInterfaceFromGlobal
);
3691 IUnknown_Release(object
);
3693 hr
= IGlobalInterfaceTable_RevokeInterfaceFromGlobal(git
, cookie
);
3694 ok_ole_success(hr
, IGlobalInterfaceTable_RevokeInterfaceFromGlobal
);
3698 IGlobalInterfaceTable_Release(git
);
3701 static void test_manualresetevent(void)
3703 ISynchronizeHandle
*sync_handle
;
3704 ISynchronize
*psync1
, *psync2
;
3710 hr
= CoCreateInstance(&CLSID_ManualResetEvent
, NULL
, CLSCTX_INPROC_SERVER
, &IID_IUnknown
, (void**)&punk
);
3711 ok(hr
== S_OK
, "Got 0x%08x\n", hr
);
3712 ok(!!punk
, "Got NULL.\n");
3713 IUnknown_Release(punk
);
3715 hr
= CoCreateInstance(&CLSID_ManualResetEvent
, NULL
, CLSCTX_INPROC_SERVER
, &IID_ISynchronize
, (void**)&psync1
);
3716 ok(hr
== S_OK
, "Got 0x%08x\n", hr
);
3717 ok(!!psync1
, "Got NULL.\n");
3719 hr
= ISynchronize_Wait(psync1
, 0, 5);
3720 ok(hr
== RPC_S_CALLPENDING
, "Got 0x%08x\n", hr
);
3722 hr
= ISynchronize_Reset(psync1
);
3723 ok(hr
== S_OK
, "Got 0x%08x\n", hr
);
3724 hr
= ISynchronize_Signal(psync1
);
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_Wait(psync1
, 0, 5);
3729 ok(hr
== S_OK
, "Got 0x%08x\n", hr
);
3730 hr
= ISynchronize_Reset(psync1
);
3731 ok(hr
== S_OK
, "Got 0x%08x\n", hr
);
3732 hr
= ISynchronize_Wait(psync1
, 0, 5);
3733 ok(hr
== RPC_S_CALLPENDING
, "Got 0x%08x\n", hr
);
3735 hr
= CoCreateInstance(&CLSID_ManualResetEvent
, NULL
, CLSCTX_INPROC_SERVER
, &IID_ISynchronize
, (void**)&psync2
);
3736 ok(hr
== S_OK
, "Got 0x%08x\n", hr
);
3737 ok(!!psync2
, "Got NULL.\n");
3738 ok(psync1
!= psync2
, "psync1 == psync2.\n");
3740 hr
= ISynchronize_QueryInterface(psync2
, &IID_ISynchronizeHandle
, (void**)&sync_handle
);
3741 ok(hr
== S_OK
, "QueryInterface(IID_ISynchronizeHandle) failed: %08x\n", hr
);
3744 hr
= ISynchronizeHandle_GetHandle(sync_handle
, &handle
);
3745 ok(hr
== S_OK
, "GetHandle failed: %08x\n", hr
);
3746 ok(handle
!= NULL
&& handle
!= INVALID_HANDLE_VALUE
, "handle = %p\n", handle
);
3748 ISynchronizeHandle_Release(sync_handle
);
3750 hr
= ISynchronize_Wait(psync2
, 0, 5);
3751 ok(hr
== RPC_S_CALLPENDING
, "Got 0x%08x\n", hr
);
3753 hr
= ISynchronize_Reset(psync1
);
3754 ok(hr
== S_OK
, "Got 0x%08x\n", hr
);
3755 hr
= ISynchronize_Reset(psync2
);
3756 ok(hr
== S_OK
, "Got 0x%08x\n", hr
);
3757 hr
= ISynchronize_Signal(psync1
);
3758 ok(hr
== S_OK
, "Got 0x%08x\n", hr
);
3759 hr
= ISynchronize_Wait(psync2
, 0, 5);
3760 ok(hr
== RPC_S_CALLPENDING
, "Got 0x%08x\n", hr
);
3762 ref
= ISynchronize_AddRef(psync1
);
3763 ok(ref
== 2, "Got ref: %d\n", ref
);
3764 ref
= ISynchronize_AddRef(psync1
);
3765 ok(ref
== 3, "Got ref: %d\n", ref
);
3766 ref
= ISynchronize_Release(psync1
);
3767 ok(ref
== 2, "Got nonzero ref: %d\n", ref
);
3768 ref
= ISynchronize_Release(psync2
);
3769 ok(!ref
, "Got nonzero ref: %d\n", ref
);
3770 ref
= ISynchronize_Release(psync1
);
3771 ok(ref
== 1, "Got nonzero ref: %d\n", ref
);
3772 ref
= ISynchronize_Release(psync1
);
3773 ok(!ref
, "Got nonzero ref: %d\n", ref
);
3776 static DWORD CALLBACK
implicit_mta_unmarshal_proc(void *param
)
3778 IStream
*stream
= param
;
3783 IStream_Seek(stream
, ullZero
, STREAM_SEEK_SET
, NULL
);
3784 hr
= CoUnmarshalInterface(stream
, &IID_IClassFactory
, (void **)&cf
);
3785 ok_ole_success(hr
, CoUnmarshalInterface
);
3787 hr
= IClassFactory_CreateInstance(cf
, NULL
, &IID_IUnknown
, (void **)&proxy
);
3788 ok_ole_success(hr
, IClassFactory_CreateInstance
);
3790 IUnknown_Release(proxy
);
3792 /* But if we initialize an STA in this apartment, it becomes the wrong one. */
3793 CoInitializeEx(NULL
, COINIT_APARTMENTTHREADED
);
3795 hr
= IClassFactory_CreateInstance(cf
, NULL
, &IID_IUnknown
, (void **)&proxy
);
3796 ok(hr
== RPC_E_WRONG_THREAD
, "got %#x\n", hr
);
3800 ok_more_than_one_lock();
3801 ok_non_zero_external_conn();
3803 IClassFactory_Release(cf
);
3806 ok_zero_external_conn();
3807 ok_last_release_closes(TRUE
);
3811 static DWORD CALLBACK
implicit_mta_use_proc(void *param
)
3813 IClassFactory
*cf
= param
;
3817 hr
= IClassFactory_CreateInstance(cf
, NULL
, &IID_IUnknown
, (void **)&proxy
);
3818 ok_ole_success(hr
, IClassFactory_CreateInstance
);
3820 IUnknown_Release(proxy
);
3822 /* But if we initialize an STA in this apartment, it becomes the wrong one. */
3823 CoInitializeEx(NULL
, COINIT_APARTMENTTHREADED
);
3825 hr
= IClassFactory_CreateInstance(cf
, NULL
, &IID_IUnknown
, (void **)&proxy
);
3826 ok(hr
== RPC_E_WRONG_THREAD
, "got %#x\n", hr
);
3832 struct implicit_mta_marshal_data
3839 static DWORD CALLBACK
implicit_mta_marshal_proc(void *param
)
3841 struct implicit_mta_marshal_data
*data
= param
;
3844 hr
= CoMarshalInterface(data
->stream
, &IID_IClassFactory
,
3845 (IUnknown
*)&Test_ClassFactory
, MSHCTX_INPROC
, NULL
, MSHLFLAGS_NORMAL
);
3846 ok_ole_success(hr
, CoMarshalInterface
);
3848 SetEvent(data
->start
);
3850 ok(!WaitForSingleObject(data
->stop
, 1000), "wait failed\n");
3854 static void test_implicit_mta(void)
3856 struct implicit_mta_marshal_data data
;
3857 HANDLE host_thread
, thread
;
3865 external_connections
= 0;
3867 CoInitializeEx(NULL
, COINIT_MULTITHREADED
);
3869 /* Firstly: we can unmarshal and use an object while in the implicit MTA. */
3870 hr
= CreateStreamOnHGlobal(NULL
, TRUE
, &stream
);
3871 ok_ole_success(hr
, CreateStreamOnHGlobal
);
3872 tid
= start_host_object(stream
, &IID_IClassFactory
, (IUnknown
*)&Test_ClassFactory
, MSHLFLAGS_NORMAL
, &host_thread
);
3874 ok_more_than_one_lock();
3875 ok_non_zero_external_conn();
3877 thread
= CreateThread(NULL
, 0, implicit_mta_unmarshal_proc
, stream
, 0, NULL
);
3878 ok(!WaitForSingleObject(thread
, 1000), "wait failed\n");
3879 CloseHandle(thread
);
3881 IStream_Release(stream
);
3882 end_host_object(tid
, host_thread
);
3884 /* Secondly: we can unmarshal an object into the real MTA and then use it
3885 * from the implicit MTA. */
3886 hr
= CreateStreamOnHGlobal(NULL
, TRUE
, &stream
);
3887 ok_ole_success(hr
, CreateStreamOnHGlobal
);
3888 tid
= start_host_object(stream
, &IID_IClassFactory
, (IUnknown
*)&Test_ClassFactory
, MSHLFLAGS_NORMAL
, &host_thread
);
3890 ok_more_than_one_lock();
3891 ok_non_zero_external_conn();
3893 IStream_Seek(stream
, ullZero
, STREAM_SEEK_SET
, NULL
);
3894 hr
= CoUnmarshalInterface(stream
, &IID_IClassFactory
, (void **)&cf
);
3895 ok_ole_success(hr
, CoUnmarshalInterface
);
3897 thread
= CreateThread(NULL
, 0, implicit_mta_use_proc
, cf
, 0, NULL
);
3898 ok(!WaitForSingleObject(thread
, 1000), "wait failed\n");
3899 CloseHandle(thread
);
3901 IClassFactory_Release(cf
);
3902 IStream_Release(stream
);
3905 ok_non_zero_external_conn();
3906 ok_last_release_closes(TRUE
);
3908 end_host_object(tid
, host_thread
);
3910 /* Thirdly: we can marshal an object from the implicit MTA and then
3911 * unmarshal it into the real one. */
3912 data
.start
= CreateEventA(NULL
, FALSE
, FALSE
, NULL
);
3913 data
.stop
= CreateEventA(NULL
, FALSE
, FALSE
, NULL
);
3915 hr
= CreateStreamOnHGlobal(NULL
, TRUE
, &data
.stream
);
3916 ok_ole_success(hr
, CreateStreamOnHGlobal
);
3918 thread
= CreateThread(NULL
, 0, implicit_mta_marshal_proc
, &data
, 0, NULL
);
3919 ok(!WaitForSingleObject(data
.start
, 1000), "wait failed\n");
3921 IStream_Seek(data
.stream
, ullZero
, STREAM_SEEK_SET
, NULL
);
3922 hr
= CoUnmarshalInterface(data
.stream
, &IID_IClassFactory
, (void **)&cf
);
3923 ok_ole_success(hr
, CoUnmarshalInterface
);
3925 hr
= IClassFactory_CreateInstance(cf
, NULL
, &IID_IUnknown
, (void **)&proxy
);
3926 ok_ole_success(hr
, IClassFactory_CreateInstance
);
3928 IUnknown_Release(proxy
);
3930 SetEvent(data
.stop
);
3931 ok(!WaitForSingleObject(thread
, 1000), "wait failed\n");
3932 CloseHandle(thread
);
3934 IStream_Release(data
.stream
);
3939 static const char *debugstr_iid(REFIID riid
)
3941 static char name
[256];
3945 LONG name_size
= sizeof(name
);
3946 StringFromGUID2(riid
, bufferW
, sizeof(bufferW
)/sizeof(bufferW
[0]));
3947 WideCharToMultiByte(CP_ACP
, 0, bufferW
, sizeof(bufferW
)/sizeof(bufferW
[0]), buffer
, sizeof(buffer
), NULL
, NULL
);
3948 if (RegOpenKeyExA(HKEY_CLASSES_ROOT
, "Interface", 0, KEY_QUERY_VALUE
, &hkeyInterface
) != ERROR_SUCCESS
)
3950 memcpy(name
, buffer
, sizeof(buffer
));
3953 if (RegQueryValueA(hkeyInterface
, buffer
, name
, &name_size
) != ERROR_SUCCESS
)
3955 memcpy(name
, buffer
, sizeof(buffer
));
3958 RegCloseKey(hkeyInterface
);
3963 static HRESULT WINAPI
TestChannelHook_QueryInterface(IChannelHook
*iface
, REFIID riid
, void **ppv
)
3965 if (IsEqualIID(riid
, &IID_IUnknown
) || IsEqualIID(riid
, &IID_IChannelHook
))
3968 IChannelHook_AddRef(iface
);
3973 return E_NOINTERFACE
;
3976 static ULONG WINAPI
TestChannelHook_AddRef(IChannelHook
*iface
)
3981 static ULONG WINAPI
TestChannelHook_Release(IChannelHook
*iface
)
3986 static BOOL new_hook_struct
;
3987 static int method
, server_tid
;
3988 static GUID causality
;
3990 struct new_hook_info
3999 static void WINAPI
TestChannelHook_ClientGetSize(
4000 IChannelHook
*iface
,
4005 SChannelHookCallInfo
*info
= (SChannelHookCallInfo
*)riid
;
4006 trace("TestChannelHook_ClientGetSize\n");
4007 trace("\t%s\n", debugstr_iid(riid
));
4008 if (info
->cbSize
!= sizeof(*info
))
4009 new_hook_struct
= TRUE
;
4011 if (!new_hook_struct
)
4013 ok(info
->cbSize
== sizeof(*info
), "cbSize was %d instead of %d\n", info
->cbSize
, (int)sizeof(*info
));
4014 ok(info
->dwServerPid
== GetCurrentProcessId(), "dwServerPid was 0x%x instead of 0x%x\n", info
->dwServerPid
, GetCurrentProcessId());
4015 ok(info
->iMethod
== method
, "iMethod was %d should be %d\n", info
->iMethod
, method
);
4016 ok(!info
->pObject
, "pObject should be NULL\n");
4018 causality
= info
->uCausality
;
4020 ok(IsEqualGUID(&info
->uCausality
, &causality
), "causality wasn't correct\n");
4024 struct new_hook_info
*new_info
= (struct new_hook_info
*)riid
;
4025 ok(new_info
->server_pid
== GetCurrentProcessId(), "server pid was 0x%x instead of 0x%x\n", new_info
->server_pid
,
4026 GetCurrentProcessId());
4027 ok(new_info
->server_tid
== server_tid
, "server tid was 0x%x instead of 0x%x\n", new_info
->server_tid
,
4029 ok(new_info
->method
== method
, "method was %d instead of %d\n", new_info
->method
, method
);
4031 causality
= new_info
->causality
;
4033 ok(IsEqualGUID(&new_info
->causality
, &causality
), "causality wasn't correct\n");
4036 ok(IsEqualGUID(uExtent
, &EXTENTID_WineTest
), "uExtent wasn't correct\n");
4041 static void WINAPI
TestChannelHook_ClientFillBuffer(
4042 IChannelHook
*iface
,
4048 SChannelHookCallInfo
*info
= (SChannelHookCallInfo
*)riid
;
4049 trace("TestChannelHook_ClientFillBuffer\n");
4051 if (!new_hook_struct
)
4053 ok(info
->cbSize
== sizeof(*info
), "cbSize was %d instead of %d\n", info
->cbSize
, (int)sizeof(*info
));
4054 ok(info
->dwServerPid
== GetCurrentProcessId(), "dwServerPid was 0x%x instead of 0x%x\n", info
->dwServerPid
, GetCurrentProcessId());
4055 ok(info
->iMethod
== method
, "iMethod was %d should be %d\n", info
->iMethod
, method
);
4056 ok(!info
->pObject
, "pObject should be NULL\n");
4057 ok(IsEqualGUID(&info
->uCausality
, &causality
), "causality wasn't correct\n");
4061 struct new_hook_info
*new_info
= (struct new_hook_info
*)riid
;
4062 ok(new_info
->server_pid
== GetCurrentProcessId(), "server pid was 0x%x instead of 0x%x\n", new_info
->server_pid
,
4063 GetCurrentProcessId());
4064 ok(new_info
->server_tid
== server_tid
, "server tid was 0x%x instead of 0x%x\n", new_info
->server_tid
,
4066 ok(new_info
->method
== method
, "method was %d instead of %d\n", new_info
->method
, method
);
4067 ok(IsEqualGUID(&new_info
->causality
, &causality
), "causality wasn't correct\n");
4070 ok(IsEqualGUID(uExtent
, &EXTENTID_WineTest
), "uExtent wasn't correct\n");
4072 *(unsigned char *)pDataBuffer
= 0xcc;
4076 static void WINAPI
TestChannelHook_ClientNotify(
4077 IChannelHook
*iface
,
4085 SChannelHookCallInfo
*info
= (SChannelHookCallInfo
*)riid
;
4086 trace("TestChannelHook_ClientNotify hrFault = 0x%08x\n", hrFault
);
4088 if (!new_hook_struct
)
4090 ok(info
->cbSize
== sizeof(*info
), "cbSize was %d instead of %d\n", info
->cbSize
, (int)sizeof(*info
));
4091 ok(info
->dwServerPid
== GetCurrentProcessId(), "dwServerPid was 0x%x instead of 0x%x\n", info
->dwServerPid
, GetCurrentProcessId());
4092 ok(info
->iMethod
== method
, "iMethod was %d should be %d\n", info
->iMethod
, method
);
4094 ok(info
->pObject
!= NULL
, "pObject shouldn't be NULL\n");
4096 ok(IsEqualGUID(&info
->uCausality
, &causality
), "causality wasn't correct\n");
4100 struct new_hook_info
*new_info
= (struct new_hook_info
*)riid
;
4101 ok(new_info
->server_pid
== GetCurrentProcessId(), "server pid was 0x%x instead of 0x%x\n", new_info
->server_pid
,
4102 GetCurrentProcessId());
4103 ok(new_info
->server_tid
== server_tid
, "server tid was 0x%x instead of 0x%x\n", new_info
->server_tid
,
4105 ok(new_info
->method
== method
, "method was %d instead of %d\n", new_info
->method
, method
);
4106 ok(IsEqualGUID(&new_info
->causality
, &causality
), "causality wasn't correct\n");
4109 ok(IsEqualGUID(uExtent
, &EXTENTID_WineTest
), "uExtent wasn't correct\n");
4112 static void WINAPI
TestChannelHook_ServerNotify(
4113 IChannelHook
*iface
,
4120 SChannelHookCallInfo
*info
= (SChannelHookCallInfo
*)riid
;
4121 trace("TestChannelHook_ServerNotify\n");
4123 if (!new_hook_struct
)
4125 ok(info
->cbSize
== sizeof(*info
), "cbSize was %d instead of %d\n", info
->cbSize
, (int)sizeof(*info
));
4126 ok(info
->dwServerPid
== GetCurrentProcessId(), "dwServerPid was 0x%x instead of 0x%x\n", info
->dwServerPid
, GetCurrentProcessId());
4127 ok(info
->iMethod
== method
, "iMethod was %d should be %d\n", info
->iMethod
, method
);
4128 ok(info
->pObject
!= NULL
, "pObject shouldn't be NULL\n");
4129 ok(IsEqualGUID(&info
->uCausality
, &causality
), "causality wasn't correct\n");
4133 struct new_hook_info
*new_info
= (struct new_hook_info
*)riid
;
4134 ok(new_info
->server_pid
== GetCurrentProcessId(), "server pid was 0x%x instead of 0x%x\n", new_info
->server_pid
,
4135 GetCurrentProcessId());
4136 ok(new_info
->server_tid
== server_tid
, "server tid was 0x%x instead of 0x%x\n", new_info
->server_tid
,
4138 ok(new_info
->method
== method
, "method was %d instead of %d\n", new_info
->method
, method
);
4139 ok(IsEqualGUID(&new_info
->causality
, &causality
), "causality wasn't correct\n");
4142 ok(cbDataSize
== 1, "cbDataSize should have been 1 instead of %d\n", cbDataSize
);
4143 ok(*(unsigned char *)pDataBuffer
== 0xcc, "pDataBuffer should have contained 0xcc instead of 0x%x\n", *(unsigned char *)pDataBuffer
);
4144 ok(IsEqualGUID(uExtent
, &EXTENTID_WineTest
), "uExtent wasn't correct\n");
4147 static void WINAPI
TestChannelHook_ServerGetSize(
4148 IChannelHook
*iface
,
4154 SChannelHookCallInfo
*info
= (SChannelHookCallInfo
*)riid
;
4155 trace("TestChannelHook_ServerGetSize\n");
4156 trace("\t%s\n", debugstr_iid(riid
));
4157 if (!new_hook_struct
)
4159 ok(info
->cbSize
== sizeof(*info
), "cbSize was %d instead of %d\n", info
->cbSize
, (int)sizeof(*info
));
4160 ok(info
->dwServerPid
== GetCurrentProcessId(), "dwServerPid was 0x%x instead of 0x%x\n", info
->dwServerPid
, GetCurrentProcessId());
4161 ok(info
->iMethod
== method
, "iMethod was %d should be %d\n", info
->iMethod
, method
);
4162 ok(info
->pObject
!= NULL
, "pObject shouldn't be NULL\n");
4163 ok(IsEqualGUID(&info
->uCausality
, &causality
), "causality wasn't correct\n");
4167 struct new_hook_info
*new_info
= (struct new_hook_info
*)riid
;
4168 ok(new_info
->server_pid
== GetCurrentProcessId(), "server pid was 0x%x instead of 0x%x\n", new_info
->server_pid
,
4169 GetCurrentProcessId());
4170 ok(new_info
->server_tid
== server_tid
, "server tid was 0x%x instead of 0x%x\n", new_info
->server_tid
,
4172 ok(new_info
->method
== method
, "method was %d instead of %d\n", new_info
->method
, method
);
4173 ok(IsEqualGUID(&new_info
->causality
, &causality
), "causality wasn't correct\n");
4176 ok(IsEqualGUID(uExtent
, &EXTENTID_WineTest
), "uExtent wasn't correct\n");
4177 if (hrFault
!= S_OK
)
4178 trace("\thrFault = 0x%08x\n", hrFault
);
4183 static void WINAPI
TestChannelHook_ServerFillBuffer(
4184 IChannelHook
*iface
,
4191 trace("TestChannelHook_ServerFillBuffer\n");
4192 ok(0, "TestChannelHook_ServerFillBuffer shouldn't be called\n");
4195 static const IChannelHookVtbl TestChannelHookVtbl
=
4197 TestChannelHook_QueryInterface
,
4198 TestChannelHook_AddRef
,
4199 TestChannelHook_Release
,
4200 TestChannelHook_ClientGetSize
,
4201 TestChannelHook_ClientFillBuffer
,
4202 TestChannelHook_ClientNotify
,
4203 TestChannelHook_ServerNotify
,
4204 TestChannelHook_ServerGetSize
,
4205 TestChannelHook_ServerFillBuffer
,
4208 static IChannelHook TestChannelHook
= { &TestChannelHookVtbl
};
4210 static void test_channel_hook(void)
4212 IClassFactory
*cf
= NULL
;
4214 IUnknown
*proxy
= NULL
;
4218 struct host_object_data object_data
= { NULL
, &IID_IClassFactory
, (IUnknown
*)&Test_ClassFactory
,
4219 MSHLFLAGS_NORMAL
, &MessageFilter
};
4221 hr
= CoRegisterChannelHook(&EXTENTID_WineTest
, &TestChannelHook
);
4222 ok_ole_success(hr
, CoRegisterChannelHook
);
4224 hr
= CoRegisterMessageFilter(&MessageFilter
, NULL
);
4225 ok_ole_success(hr
, CoRegisterMessageFilter
);
4229 hr
= CreateStreamOnHGlobal(NULL
, TRUE
, &object_data
.stream
);
4230 ok_ole_success(hr
, CreateStreamOnHGlobal
);
4231 tid
= start_host_object2(&object_data
, &thread
);
4234 ok_more_than_one_lock();
4236 IStream_Seek(object_data
.stream
, ullZero
, STREAM_SEEK_SET
, NULL
);
4237 hr
= CoUnmarshalInterface(object_data
.stream
, &IID_IClassFactory
, (void **)&cf
);
4238 ok_ole_success(hr
, CoUnmarshalInterface
);
4239 IStream_Release(object_data
.stream
);
4241 ok_more_than_one_lock();
4244 hr
= IClassFactory_CreateInstance(cf
, NULL
, &IID_IUnknown
, (LPVOID
*)&proxy
);
4245 ok_ole_success(hr
, IClassFactory_CreateInstance
);
4248 IUnknown_Release(proxy
);
4250 IClassFactory_Release(cf
);
4254 end_host_object(tid
, thread
);
4256 hr
= CoRegisterMessageFilter(NULL
, NULL
);
4257 ok_ole_success(hr
, CoRegisterMessageFilter
);
4262 HMODULE hOle32
= GetModuleHandleA("ole32");
4266 if (!GetProcAddress(hOle32
, "CoRegisterSurrogateEx")) {
4267 win_skip("skipping test on win9x\n");
4271 pCoInitializeEx
= (void*)GetProcAddress(hOle32
, "CoInitializeEx");
4272 pDllGetClassObject
= (void*)GetProcAddress(hOle32
, "DllGetClassObject");
4274 argc
= winetest_get_mainargs( &argv
);
4275 if (argc
> 2 && (!strcmp(argv
[2], "-Embedding")))
4277 pCoInitializeEx(NULL
, COINIT_MULTITHREADED
);
4278 test_register_local_server();
4284 register_test_window();
4286 test_cocreateinstance_proxy();
4287 test_implicit_mta();
4289 pCoInitializeEx(NULL
, COINIT_APARTMENTTHREADED
);
4291 /* FIXME: test CoCreateInstanceEx */
4293 /* lifecycle management and marshaling tests */
4296 test_no_marshaler();
4297 test_normal_marshal_and_release();
4298 test_normal_marshal_and_unmarshal();
4299 test_marshal_and_unmarshal_invalid();
4300 test_same_apartment_unmarshal_failure();
4301 test_interthread_marshal_and_unmarshal();
4302 test_proxy_marshal_and_unmarshal();
4303 test_proxy_marshal_and_unmarshal2();
4304 test_proxy_marshal_and_unmarshal_weak();
4305 test_proxy_marshal_and_unmarshal_strong();
4306 test_marshal_stub_apartment_shutdown();
4307 test_marshal_proxy_apartment_shutdown();
4308 test_marshal_proxy_mta_apartment_shutdown();
4309 test_no_couninitialize_server();
4310 test_no_couninitialize_client();
4311 test_tableweak_marshal_and_unmarshal_twice();
4312 test_tableweak_marshal_releasedata1();
4313 test_tableweak_marshal_releasedata2();
4314 test_tableweak_and_normal_marshal_and_unmarshal();
4315 test_tableweak_and_normal_marshal_and_releasedata();
4316 test_two_tableweak_marshal_and_releasedata();
4317 test_tablestrong_marshal_and_unmarshal_twice();
4318 test_lock_object_external();
4319 test_disconnect_stub();
4320 test_normal_marshal_and_unmarshal_twice();
4322 with_external_conn
= !with_external_conn
;
4323 } while (with_external_conn
);
4325 test_marshal_channel_buffer();
4326 test_hresult_marshaling();
4327 test_proxy_used_in_wrong_thread();
4328 test_message_filter();
4329 test_bad_marshal_stream();
4330 test_proxy_interfaces();
4331 test_stubbuffer(&IID_IClassFactory
);
4332 test_proxybuffer(&IID_IClassFactory
);
4333 test_message_reentrancy();
4334 test_call_from_message();
4335 test_WM_QUIT_handling();
4336 test_freethreadedmarshaler();
4337 test_inproc_handler();
4338 test_handler_marshaling();
4339 test_client_security();
4341 test_local_server();
4343 test_globalinterfacetable();
4344 test_manualresetevent();
4345 test_crash_couninitialize();
4347 /* must be last test as channel hooks can't be unregistered */
4348 test_channel_hook();