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
35 #include "wine/test.h"
36 #include "wine/heap.h"
38 #define DEFINE_EXPECT(func) \
39 static BOOL expect_ ## func = FALSE, called_ ## func = FALSE
41 #define SET_EXPECT(func) \
42 expect_ ## func = TRUE
44 #define CHECK_EXPECT2(func) \
46 ok(expect_ ##func, "unexpected call " #func "\n"); \
47 called_ ## func = TRUE; \
50 #define CHECK_EXPECT(func) \
52 CHECK_EXPECT2(func); \
53 expect_ ## func = FALSE; \
56 #define CHECK_CALLED(func) \
58 ok(called_ ## func, "expected " #func "\n"); \
59 expect_ ## func = called_ ## func = FALSE; \
62 static const GUID CLSID_WineTestPSFactoryBuffer
= { 0x22222222, 0x1234, 0x1234, { 0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0 } };
63 static const GUID CLSID_DfMarshal
= { 0x0000030b, 0x0000, 0x0000, { 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46 } };
64 static const GUID CLSID_ft_unmarshaler_1809
= {0x00000359, 0x0000, 0x0000, {0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46}};
66 /* functions that are not present on all versions of Windows */
67 static HRESULT (WINAPI
*pDllGetClassObject
)(REFCLSID
,REFIID
,LPVOID
);
69 /* helper macros to make tests a bit leaner */
70 #define ok_more_than_one_lock() ok(cLocks > 0, "Number of locks should be > 0, but actually is %d\n", cLocks)
71 #define ok_no_locks() ok(cLocks == 0, "Number of locks should be 0, but actually is %d\n", cLocks)
72 #define ok_ole_success(hr, func) ok(hr == S_OK, #func " failed with error 0x%08x\n", hr)
73 #define ok_non_zero_external_conn() do {if (with_external_conn) ok(external_connections, "got no external connections\n");} while(0);
74 #define ok_zero_external_conn() do {if (with_external_conn) ok(!external_connections, "got %d external connections\n", external_connections);} while(0);
75 #define ok_last_release_closes(b) do {if (with_external_conn) ok(last_release_closes == b, "got %d expected %d\n", last_release_closes, b);} while(0);
77 #define OBJREF_SIGNATURE (0x574f454d)
78 #define OBJREF_STANDARD (0x1)
79 #define OBJREF_CUSTOM (0x4)
81 typedef struct tagDUALSTRINGARRAY
{
82 unsigned short wNumEntries
;
83 unsigned short wSecurityOffset
;
84 unsigned short aStringArray
[1];
91 typedef struct tagSTDOBJREF
{
99 typedef struct tagOBJREF
{
106 DUALSTRINGARRAY saResAddr
;
111 DUALSTRINGARRAY saResAddr
;
122 static const IID IID_IWineTest
=
127 {0xa1, 0xa2, 0x5d, 0x5a, 0x36, 0x54, 0xd3, 0xbd}
128 }; /* 5201163f-8164-4fd0-a1a2-5d5a3654d3bd */
130 static const IID IID_IRemUnknown
=
135 {0xc0,0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46}
138 #define EXTENTID_WineTest IID_IWineTest
139 #define CLSID_WineTest IID_IWineTest
141 static const CLSID CLSID_WineOOPTest
=
146 {0xa1, 0xa2, 0x5d, 0x5a, 0x36, 0x54, 0xd3, 0xbd}
147 }; /* 5201163f-8164-4fd0-a1a2-5d5a3654d3bd */
149 static void test_cocreateinstance_proxy(void)
155 CoInitializeEx(NULL
, COINIT_MULTITHREADED
);
157 hr
= CoCreateInstance(&CLSID_ShellDesktop
, NULL
, CLSCTX_INPROC
, &IID_IUnknown
, (void **)&pProxy
);
158 ok_ole_success(hr
, CoCreateInstance
);
159 hr
= IUnknown_QueryInterface(pProxy
, &IID_IMultiQI
, (void **)&pMQI
);
160 ok(hr
== S_OK
, "created object is not a proxy, so was created in the wrong apartment\n");
162 IMultiQI_Release(pMQI
);
163 IUnknown_Release(pProxy
);
168 static const LARGE_INTEGER ullZero
;
171 static void LockModule(void)
173 InterlockedIncrement(&cLocks
);
176 static void UnlockModule(void)
178 InterlockedDecrement(&cLocks
);
181 static BOOL with_external_conn
;
182 static DWORD external_connections
;
183 static BOOL last_release_closes
;
185 static HRESULT WINAPI
ExternalConnection_QueryInterface(IExternalConnection
*iface
, REFIID riid
, void **ppv
)
187 ok(0, "unexpected call\n");
189 return E_NOINTERFACE
;
192 static ULONG WINAPI
ExternalConnection_AddRef(IExternalConnection
*iface
)
197 static ULONG WINAPI
ExternalConnection_Release(IExternalConnection
*iface
)
202 static DWORD WINAPI
ExternalConnection_AddConnection(IExternalConnection
*iface
, DWORD extconn
, DWORD reserved
)
204 if (winetest_debug
> 1) trace("add connection\n");
205 return ++external_connections
;
209 static DWORD WINAPI
ExternalConnection_ReleaseConnection(IExternalConnection
*iface
, DWORD extconn
,
210 DWORD reserved
, BOOL fLastReleaseCloses
)
212 if (winetest_debug
> 1) trace("release connection %d\n", fLastReleaseCloses
);
213 last_release_closes
= fLastReleaseCloses
;
214 return --external_connections
;
217 static const IExternalConnectionVtbl ExternalConnectionVtbl
= {
218 ExternalConnection_QueryInterface
,
219 ExternalConnection_AddRef
,
220 ExternalConnection_Release
,
221 ExternalConnection_AddConnection
,
222 ExternalConnection_ReleaseConnection
225 static IExternalConnection ExternalConnection
= { &ExternalConnectionVtbl
};
228 static HRESULT WINAPI
Test_IUnknown_QueryInterface(
233 if (ppvObj
== NULL
) return E_POINTER
;
235 if (IsEqualGUID(riid
, &IID_IUnknown
))
238 IUnknown_AddRef(iface
);
243 return E_NOINTERFACE
;
246 static ULONG WINAPI
Test_IUnknown_AddRef(LPUNKNOWN iface
)
249 return 2; /* non-heap-based object */
252 static ULONG WINAPI
Test_IUnknown_Release(LPUNKNOWN iface
)
255 return 1; /* non-heap-based object */
258 static const IUnknownVtbl TestUnknown_Vtbl
=
260 Test_IUnknown_QueryInterface
,
261 Test_IUnknown_AddRef
,
262 Test_IUnknown_Release
,
265 static IUnknown Test_Unknown
= { &TestUnknown_Vtbl
};
267 static ULONG WINAPI
TestCrash_IUnknown_Release(LPUNKNOWN iface
)
271 trace("crashing...\n");
274 return 1; /* non-heap-based object */
277 static const IUnknownVtbl TestCrashUnknown_Vtbl
=
279 Test_IUnknown_QueryInterface
,
280 Test_IUnknown_AddRef
,
281 TestCrash_IUnknown_Release
,
284 static IUnknown TestCrash_Unknown
= { &TestCrashUnknown_Vtbl
};
286 static HRESULT WINAPI
Test_IClassFactory_QueryInterface(
287 LPCLASSFACTORY iface
,
291 if (ppvObj
== NULL
) return E_POINTER
;
293 if (IsEqualGUID(riid
, &IID_IUnknown
) ||
294 IsEqualGUID(riid
, &IID_IClassFactory
) ||
295 /* the only other interface Wine is currently able to marshal (for testing two proxies) */
296 IsEqualGUID(riid
, &IID_IRemUnknown
))
299 IClassFactory_AddRef(iface
);
303 if (with_external_conn
&& IsEqualGUID(riid
, &IID_IExternalConnection
))
305 *ppvObj
= &ExternalConnection
;
310 return E_NOINTERFACE
;
313 static ULONG WINAPI
Test_IClassFactory_AddRef(LPCLASSFACTORY iface
)
316 return 2; /* non-heap-based object */
319 static ULONG WINAPI
Test_IClassFactory_Release(LPCLASSFACTORY iface
)
322 return 1; /* non-heap-based object */
325 static HRESULT WINAPI
Test_IClassFactory_CreateInstance(
326 LPCLASSFACTORY iface
,
331 if (pUnkOuter
) return CLASS_E_NOAGGREGATION
;
332 return IUnknown_QueryInterface(&Test_Unknown
, riid
, ppvObj
);
335 static HRESULT WINAPI
Test_IClassFactory_LockServer(
336 LPCLASSFACTORY iface
,
342 static const IClassFactoryVtbl TestClassFactory_Vtbl
=
344 Test_IClassFactory_QueryInterface
,
345 Test_IClassFactory_AddRef
,
346 Test_IClassFactory_Release
,
347 Test_IClassFactory_CreateInstance
,
348 Test_IClassFactory_LockServer
351 static IClassFactory Test_ClassFactory
= { &TestClassFactory_Vtbl
};
353 DEFINE_EXPECT(Invoke
);
354 DEFINE_EXPECT(CreateStub
);
355 DEFINE_EXPECT(CreateProxy
);
356 DEFINE_EXPECT(GetWindow
);
357 DEFINE_EXPECT(Disconnect
);
359 static HRESULT WINAPI
OleWindow_QueryInterface(IOleWindow
*iface
, REFIID riid
, void **ppv
)
361 ok(0, "unexpected call %s\n", wine_dbgstr_guid(riid
));
363 return E_NOINTERFACE
;
366 static ULONG WINAPI
OleWindow_AddRef(IOleWindow
*iface
)
371 static ULONG WINAPI
OleWindow_Release(IOleWindow
*iface
)
376 static HRESULT WINAPI
OleWindow_GetWindow(IOleWindow
*iface
, HWND
*hwnd
)
378 CHECK_EXPECT(GetWindow
);
379 *hwnd
= (HWND
)0xdeadbeef;
383 static const IOleWindowVtbl OleWindowVtbl
= {
384 OleWindow_QueryInterface
,
391 static IOleWindow Test_OleWindow
= { &OleWindowVtbl
};
393 static HRESULT WINAPI
OleClientSite_QueryInterface(IOleClientSite
*iface
, REFIID riid
, void **ppv
)
395 if (IsEqualGUID(riid
, &IID_IUnknown
) || IsEqualGUID(riid
, &IID_IOleClientSite
))
397 else if (IsEqualGUID(riid
, &IID_IOleWindow
))
398 *ppv
= &Test_OleWindow
;
402 return E_NOINTERFACE
;
405 IUnknown_AddRef((IUnknown
*)*ppv
);
409 static ULONG WINAPI
OleClientSite_AddRef(IOleClientSite
*iface
)
414 static ULONG WINAPI
OleClientSite_Release(IOleClientSite
*iface
)
419 static const IOleClientSiteVtbl OleClientSiteVtbl
= {
420 OleClientSite_QueryInterface
,
421 OleClientSite_AddRef
,
422 OleClientSite_Release
,
423 /* we don't need the rest, we never call it */
426 static IOleClientSite Test_OleClientSite
= { &OleClientSiteVtbl
};
429 IRpcStubBuffer IRpcStubBuffer_iface
;
431 IRpcStubBuffer
*buffer
;
434 static StubBufferWrapper
*impl_from_IRpcStubBuffer(IRpcStubBuffer
*iface
)
436 return CONTAINING_RECORD(iface
, StubBufferWrapper
, IRpcStubBuffer_iface
);
439 static HRESULT WINAPI
RpcStubBuffer_QueryInterface(IRpcStubBuffer
*iface
, REFIID riid
, void **ppv
)
441 StubBufferWrapper
*This
= impl_from_IRpcStubBuffer(iface
);
443 if(IsEqualGUID(&IID_IUnknown
, riid
) || IsEqualGUID(&IID_IRpcStubBuffer
, riid
)) {
444 *ppv
= &This
->IRpcStubBuffer_iface
;
447 return E_NOINTERFACE
;
450 IUnknown_AddRef((IUnknown
*)*ppv
);
454 static ULONG WINAPI
RpcStubBuffer_AddRef(IRpcStubBuffer
*iface
)
456 StubBufferWrapper
*This
= impl_from_IRpcStubBuffer(iface
);
457 return InterlockedIncrement(&This
->ref
);
460 static ULONG WINAPI
RpcStubBuffer_Release(IRpcStubBuffer
*iface
)
462 StubBufferWrapper
*This
= impl_from_IRpcStubBuffer(iface
);
463 LONG ref
= InterlockedDecrement(&This
->ref
);
465 IRpcStubBuffer_Release(This
->buffer
);
471 static HRESULT WINAPI
RpcStubBuffer_Connect(IRpcStubBuffer
*iface
, IUnknown
*pUnkServer
)
473 ok(0, "unexpected call\n");
477 static void WINAPI
RpcStubBuffer_Disconnect(IRpcStubBuffer
*iface
)
479 CHECK_EXPECT(Disconnect
);
482 static HRESULT WINAPI
RpcStubBuffer_Invoke(IRpcStubBuffer
*iface
, RPCOLEMESSAGE
*_prpcmsg
,
483 IRpcChannelBuffer
*_pRpcChannelBuffer
)
485 StubBufferWrapper
*This
= impl_from_IRpcStubBuffer(iface
);
486 void *dest_context_data
;
490 CHECK_EXPECT(Invoke
);
492 hr
= IRpcChannelBuffer_GetDestCtx(_pRpcChannelBuffer
, &dest_context
, &dest_context_data
);
493 ok(hr
== S_OK
, "GetDestCtx failed: %08x\n", hr
);
494 ok(dest_context
== MSHCTX_INPROC
, "desc_context = %x\n", dest_context
);
495 ok(!dest_context_data
, "desc_context_data = %p\n", dest_context_data
);
497 return IRpcStubBuffer_Invoke(This
->buffer
, _prpcmsg
, _pRpcChannelBuffer
);
500 static IRpcStubBuffer
*WINAPI
RpcStubBuffer_IsIIDSupported(IRpcStubBuffer
*iface
, REFIID riid
)
502 ok(0, "unexpected call\n");
506 static ULONG WINAPI
RpcStubBuffer_CountRefs(IRpcStubBuffer
*iface
)
508 ok(0, "unexpected call\n");
512 static HRESULT WINAPI
RpcStubBuffer_DebugServerQueryInterface(IRpcStubBuffer
*iface
, void **ppv
)
514 ok(0, "unexpected call\n");
518 static void WINAPI
RpcStubBuffer_DebugServerRelease(IRpcStubBuffer
*iface
, void *pv
)
520 ok(0, "unexpected call\n");
523 static const IRpcStubBufferVtbl RpcStubBufferVtbl
= {
524 RpcStubBuffer_QueryInterface
,
525 RpcStubBuffer_AddRef
,
526 RpcStubBuffer_Release
,
527 RpcStubBuffer_Connect
,
528 RpcStubBuffer_Disconnect
,
529 RpcStubBuffer_Invoke
,
530 RpcStubBuffer_IsIIDSupported
,
531 RpcStubBuffer_CountRefs
,
532 RpcStubBuffer_DebugServerQueryInterface
,
533 RpcStubBuffer_DebugServerRelease
536 static IPSFactoryBuffer
*ps_factory_buffer
;
538 static HRESULT WINAPI
PSFactoryBuffer_QueryInterface(IPSFactoryBuffer
*iface
, REFIID riid
, void **ppv
)
540 if (IsEqualIID(riid
, &IID_IUnknown
) || IsEqualIID(riid
, &IID_IPSFactoryBuffer
))
545 return E_NOINTERFACE
;
547 IUnknown_AddRef((IUnknown
*)*ppv
);
551 static ULONG WINAPI
PSFactoryBuffer_AddRef(IPSFactoryBuffer
*iface
)
556 static ULONG WINAPI
PSFactoryBuffer_Release(IPSFactoryBuffer
*iface
)
561 static HRESULT WINAPI
PSFactoryBuffer_CreateProxy(IPSFactoryBuffer
*iface
, IUnknown
*outer
,
562 REFIID riid
, IRpcProxyBuffer
**ppProxy
, void **ppv
)
564 CHECK_EXPECT(CreateProxy
);
565 return IPSFactoryBuffer_CreateProxy(ps_factory_buffer
, outer
, riid
, ppProxy
, ppv
);
568 static HRESULT WINAPI
PSFactoryBuffer_CreateStub(IPSFactoryBuffer
*iface
, REFIID riid
,
569 IUnknown
*server
, IRpcStubBuffer
**ppStub
)
571 StubBufferWrapper
*stub
;
574 CHECK_EXPECT(CreateStub
);
576 ok(server
== (IUnknown
*)&Test_OleClientSite
, "unexpected server %p\n", server
);
578 stub
= heap_alloc(sizeof(*stub
));
579 stub
->IRpcStubBuffer_iface
.lpVtbl
= &RpcStubBufferVtbl
;
582 hr
= IPSFactoryBuffer_CreateStub(ps_factory_buffer
, riid
, server
, &stub
->buffer
);
583 ok(hr
== S_OK
, "CreateStub failed: %08x\n", hr
);
585 *ppStub
= &stub
->IRpcStubBuffer_iface
;
589 static IPSFactoryBufferVtbl PSFactoryBufferVtbl
=
591 PSFactoryBuffer_QueryInterface
,
592 PSFactoryBuffer_AddRef
,
593 PSFactoryBuffer_Release
,
594 PSFactoryBuffer_CreateProxy
,
595 PSFactoryBuffer_CreateStub
598 static IPSFactoryBuffer PSFactoryBuffer
= { &PSFactoryBufferVtbl
};
600 #define RELEASEMARSHALDATA WM_USER
602 struct host_object_data
607 MSHLFLAGS marshal_flags
;
608 IMessageFilter
*filter
;
609 IUnknown
*register_object
;
610 const CLSID
*register_clsid
;
611 HANDLE marshal_event
;
614 static IPSFactoryBuffer PSFactoryBuffer
;
616 static DWORD CALLBACK
host_object_proc(LPVOID p
)
618 struct host_object_data
*data
= p
;
619 DWORD registration_key
;
623 CoInitializeEx(NULL
, COINIT_APARTMENTTHREADED
);
625 if(data
->register_object
) {
626 hr
= CoRegisterClassObject(data
->register_clsid
, data
->register_object
,
627 CLSCTX_INPROC_SERVER
, REGCLS_MULTIPLEUSE
, ®istration_key
);
628 ok(hr
== S_OK
, "CoRegisterClassObject failed: %08x\n", hr
);
633 IMessageFilter
* prev_filter
= NULL
;
634 hr
= CoRegisterMessageFilter(data
->filter
, &prev_filter
);
635 if (prev_filter
) IMessageFilter_Release(prev_filter
);
636 ok_ole_success(hr
, CoRegisterMessageFilter
);
639 hr
= CoMarshalInterface(data
->stream
, data
->iid
, data
->object
, MSHCTX_INPROC
, NULL
, data
->marshal_flags
);
640 ok_ole_success(hr
, CoMarshalInterface
);
642 /* force the message queue to be created before signaling parent thread */
643 PeekMessageA(&msg
, NULL
, WM_USER
, WM_USER
, PM_NOREMOVE
);
645 SetEvent(data
->marshal_event
);
647 while (GetMessageA(&msg
, NULL
, 0, 0))
649 if (msg
.hwnd
== NULL
&& msg
.message
== RELEASEMARSHALDATA
)
651 CoReleaseMarshalData(data
->stream
);
652 SetEvent((HANDLE
)msg
.lParam
);
655 DispatchMessageA(&msg
);
658 HeapFree(GetProcessHeap(), 0, data
);
665 static DWORD
start_host_object2(struct host_object_data
*object_data
, HANDLE
*thread
)
668 struct host_object_data
*data
;
670 data
= HeapAlloc(GetProcessHeap(), 0, sizeof(*data
));
671 *data
= *object_data
;
672 data
->marshal_event
= CreateEventA(NULL
, FALSE
, FALSE
, NULL
);
673 *thread
= CreateThread(NULL
, 0, host_object_proc
, data
, 0, &tid
);
675 /* wait for marshaling to complete before returning */
676 ok( !WaitForSingleObject(data
->marshal_event
, 10000), "wait timed out\n" );
677 CloseHandle(data
->marshal_event
);
682 static DWORD
start_host_object(IStream
*stream
, REFIID riid
, IUnknown
*object
, MSHLFLAGS marshal_flags
, HANDLE
*thread
)
684 struct host_object_data object_data
= { stream
, riid
, object
, marshal_flags
};
685 return start_host_object2(&object_data
, thread
);
688 /* asks thread to release the marshal data because it has to be done by the
689 * same thread that marshaled the interface in the first place. */
690 static void release_host_object(DWORD tid
, WPARAM wp
)
692 HANDLE event
= CreateEventA(NULL
, FALSE
, FALSE
, NULL
);
693 PostThreadMessageA(tid
, RELEASEMARSHALDATA
, wp
, (LPARAM
)event
);
694 ok( !WaitForSingleObject(event
, 10000), "wait timed out\n" );
698 static void end_host_object(DWORD tid
, HANDLE thread
)
700 BOOL ret
= PostThreadMessageA(tid
, WM_QUIT
, 0, 0);
701 ok(ret
, "PostThreadMessage failed with error %d\n", GetLastError());
702 /* be careful of races - don't return until hosting thread has terminated */
703 ok( !WaitForSingleObject(thread
, 10000), "wait timed out\n" );
707 /* tests failure case of interface not having a marshaler specified in the
709 static void test_no_marshaler(void)
714 hr
= CreateStreamOnHGlobal(NULL
, TRUE
, &pStream
);
715 ok_ole_success(hr
, CreateStreamOnHGlobal
);
716 hr
= CoMarshalInterface(pStream
, &IID_IWineTest
, (IUnknown
*)&Test_ClassFactory
, MSHCTX_INPROC
, NULL
, MSHLFLAGS_NORMAL
);
717 ok(hr
== E_NOINTERFACE
, "CoMarshalInterface should have returned E_NOINTERFACE instead of 0x%08x\n", hr
);
719 IStream_Release(pStream
);
722 /* tests normal marshal and then release without unmarshaling */
723 static void test_normal_marshal_and_release(void)
726 IStream
*pStream
= NULL
;
729 external_connections
= 0;
731 hr
= CreateStreamOnHGlobal(NULL
, TRUE
, &pStream
);
732 ok_ole_success(hr
, CreateStreamOnHGlobal
);
733 hr
= CoMarshalInterface(pStream
, &IID_IClassFactory
, (IUnknown
*)&Test_ClassFactory
, MSHCTX_INPROC
, NULL
, MSHLFLAGS_NORMAL
);
734 ok_ole_success(hr
, CoMarshalInterface
);
736 ok_more_than_one_lock();
737 ok_non_zero_external_conn();
739 IStream_Seek(pStream
, ullZero
, STREAM_SEEK_SET
, NULL
);
740 hr
= CoReleaseMarshalData(pStream
);
741 ok_ole_success(hr
, CoReleaseMarshalData
);
742 IStream_Release(pStream
);
745 ok_zero_external_conn();
746 ok_last_release_closes(TRUE
);
749 /* tests success case of a same-thread marshal and unmarshal */
750 static void test_normal_marshal_and_unmarshal(void)
753 IStream
*pStream
= NULL
;
754 IUnknown
*pProxy
= NULL
;
757 external_connections
= 0;
759 hr
= CreateStreamOnHGlobal(NULL
, TRUE
, &pStream
);
760 ok_ole_success(hr
, CreateStreamOnHGlobal
);
761 hr
= CoMarshalInterface(pStream
, &IID_IClassFactory
, (IUnknown
*)&Test_ClassFactory
, MSHCTX_INPROC
, NULL
, MSHLFLAGS_NORMAL
);
762 ok_ole_success(hr
, CoMarshalInterface
);
764 ok_more_than_one_lock();
765 ok_non_zero_external_conn();
767 IStream_Seek(pStream
, ullZero
, STREAM_SEEK_SET
, NULL
);
768 hr
= CoUnmarshalInterface(pStream
, &IID_IClassFactory
, (void **)&pProxy
);
769 ok_ole_success(hr
, CoUnmarshalInterface
);
770 IStream_Release(pStream
);
772 ok_more_than_one_lock();
773 ok_zero_external_conn();
774 ok_last_release_closes(FALSE
);
776 IUnknown_Release(pProxy
);
781 /* tests failure case of unmarshaling a freed object */
782 static void test_marshal_and_unmarshal_invalid(void)
785 IStream
*pStream
= NULL
;
786 IClassFactory
*pProxy
= NULL
;
792 external_connections
= 0;
794 hr
= CreateStreamOnHGlobal(NULL
, TRUE
, &pStream
);
795 ok_ole_success(hr
, CreateStreamOnHGlobal
);
796 tid
= start_host_object(pStream
, &IID_IClassFactory
, (IUnknown
*)&Test_ClassFactory
, MSHLFLAGS_NORMAL
, &thread
);
798 ok_more_than_one_lock();
799 ok_non_zero_external_conn();
801 IStream_Seek(pStream
, ullZero
, STREAM_SEEK_SET
, NULL
);
802 hr
= CoReleaseMarshalData(pStream
);
803 ok_ole_success(hr
, CoReleaseMarshalData
);
806 ok_zero_external_conn();
807 ok_last_release_closes(TRUE
);
809 IStream_Seek(pStream
, ullZero
, STREAM_SEEK_SET
, NULL
);
810 hr
= CoUnmarshalInterface(pStream
, &IID_IClassFactory
, (void **)&pProxy
);
811 todo_wine
{ ok_ole_success(hr
, CoUnmarshalInterface
); }
817 hr
= IClassFactory_CreateInstance(pProxy
, NULL
, &IID_IUnknown
, &dummy
);
818 ok(hr
== RPC_E_DISCONNECTED
, "Remote call should have returned RPC_E_DISCONNECTED, instead of 0x%08x\n", hr
);
820 IClassFactory_Release(pProxy
);
823 IStream_Release(pStream
);
825 end_host_object(tid
, thread
);
828 static void test_same_apartment_unmarshal_failure(void)
833 static const LARGE_INTEGER llZero
;
836 external_connections
= 0;
838 hr
= CreateStreamOnHGlobal(NULL
, TRUE
, &pStream
);
839 ok_ole_success(hr
, CreateStreamOnHGlobal
);
841 hr
= CoMarshalInterface(pStream
, &IID_IUnknown
, (IUnknown
*)&Test_ClassFactory
, MSHCTX_INPROC
, NULL
, MSHLFLAGS_NORMAL
);
842 ok_ole_success(hr
, CoMarshalInterface
);
844 ok_more_than_one_lock();
845 ok_non_zero_external_conn();
847 hr
= IStream_Seek(pStream
, llZero
, STREAM_SEEK_SET
, NULL
);
848 ok_ole_success(hr
, IStream_Seek
);
850 hr
= CoUnmarshalInterface(pStream
, &IID_IParseDisplayName
, (void **)&pProxy
);
851 ok(hr
== E_NOINTERFACE
, "CoUnmarshalInterface should have returned E_NOINTERFACE instead of 0x%08x\n", hr
);
854 ok_zero_external_conn();
855 ok_last_release_closes(FALSE
);
857 IStream_Release(pStream
);
860 /* tests success case of an interthread marshal */
861 static void test_interthread_marshal_and_unmarshal(void)
864 IStream
*pStream
= NULL
;
865 IUnknown
*pProxy
= NULL
;
870 external_connections
= 0;
872 hr
= CreateStreamOnHGlobal(NULL
, TRUE
, &pStream
);
873 ok_ole_success(hr
, CreateStreamOnHGlobal
);
874 tid
= start_host_object(pStream
, &IID_IClassFactory
, (IUnknown
*)&Test_ClassFactory
, MSHLFLAGS_NORMAL
, &thread
);
876 ok_more_than_one_lock();
877 ok_non_zero_external_conn();
879 IStream_Seek(pStream
, ullZero
, STREAM_SEEK_SET
, NULL
);
880 hr
= CoUnmarshalInterface(pStream
, &IID_IClassFactory
, (void **)&pProxy
);
881 ok_ole_success(hr
, CoUnmarshalInterface
);
882 IStream_Release(pStream
);
884 ok_more_than_one_lock();
885 ok_non_zero_external_conn();
887 IUnknown_Release(pProxy
);
890 ok_zero_external_conn();
891 ok_last_release_closes(TRUE
);
893 end_host_object(tid
, thread
);
896 /* the number of external references that Wine's proxy manager normally gives
897 * out, so we can test the border case of running out of references */
898 #define NORMALEXTREFS 5
900 /* tests success case of an interthread marshal and then marshaling the proxy */
901 static void test_proxy_marshal_and_unmarshal(void)
904 IStream
*pStream
= NULL
;
905 IUnknown
*pProxy
= NULL
;
906 IUnknown
*pProxy2
= NULL
;
912 external_connections
= 0;
914 hr
= CreateStreamOnHGlobal(NULL
, TRUE
, &pStream
);
915 ok_ole_success(hr
, CreateStreamOnHGlobal
);
916 tid
= start_host_object(pStream
, &IID_IClassFactory
, (IUnknown
*)&Test_ClassFactory
, MSHLFLAGS_NORMAL
, &thread
);
918 ok_more_than_one_lock();
919 ok_non_zero_external_conn();
921 IStream_Seek(pStream
, ullZero
, STREAM_SEEK_SET
, NULL
);
922 hr
= CoUnmarshalInterface(pStream
, &IID_IClassFactory
, (void **)&pProxy
);
923 ok_ole_success(hr
, CoUnmarshalInterface
);
925 ok_more_than_one_lock();
927 IStream_Seek(pStream
, ullZero
, STREAM_SEEK_SET
, NULL
);
928 /* marshal the proxy */
929 hr
= CoMarshalInterface(pStream
, &IID_IClassFactory
, pProxy
, MSHCTX_INPROC
, NULL
, MSHLFLAGS_NORMAL
);
930 ok_ole_success(hr
, CoMarshalInterface
);
932 ok_more_than_one_lock();
934 /* marshal 5 more times to exhaust the normal external references of 5 */
935 for (i
= 0; i
< NORMALEXTREFS
; i
++)
937 hr
= CoMarshalInterface(pStream
, &IID_IClassFactory
, pProxy
, MSHCTX_INPROC
, NULL
, MSHLFLAGS_NORMAL
);
938 ok_ole_success(hr
, CoMarshalInterface
);
941 ok_more_than_one_lock();
943 /* release the original proxy to test that we successfully keep the
944 * original object alive */
945 IUnknown_Release(pProxy
);
947 IStream_Seek(pStream
, ullZero
, STREAM_SEEK_SET
, NULL
);
948 hr
= CoUnmarshalInterface(pStream
, &IID_IClassFactory
, (void **)&pProxy2
);
949 ok_ole_success(hr
, CoUnmarshalInterface
);
951 ok_more_than_one_lock();
952 ok_non_zero_external_conn();
954 IUnknown_Release(pProxy2
);
956 /* unmarshal all of the proxies to check that the object stub still exists */
957 for (i
= 0; i
< NORMALEXTREFS
; i
++)
959 hr
= CoUnmarshalInterface(pStream
, &IID_IClassFactory
, (void **)&pProxy2
);
960 ok_ole_success(hr
, CoUnmarshalInterface
);
962 IUnknown_Release(pProxy2
);
966 ok_zero_external_conn();
967 ok_last_release_closes(TRUE
);
969 IStream_Release(pStream
);
971 end_host_object(tid
, thread
);
974 /* tests success case of an interthread marshal and then marshaling the proxy
975 * using an iid that hasn't previously been unmarshaled */
976 static void test_proxy_marshal_and_unmarshal2(void)
979 IStream
*pStream
= NULL
;
980 IUnknown
*pProxy
= NULL
;
981 IUnknown
*pProxy2
= NULL
;
986 external_connections
= 0;
988 hr
= CreateStreamOnHGlobal(NULL
, TRUE
, &pStream
);
989 ok_ole_success(hr
, CreateStreamOnHGlobal
);
990 tid
= start_host_object(pStream
, &IID_IUnknown
, (IUnknown
*)&Test_ClassFactory
, MSHLFLAGS_NORMAL
, &thread
);
992 ok_more_than_one_lock();
993 ok_non_zero_external_conn();
995 IStream_Seek(pStream
, ullZero
, STREAM_SEEK_SET
, NULL
);
996 hr
= CoUnmarshalInterface(pStream
, &IID_IUnknown
, (void **)&pProxy
);
997 ok_ole_success(hr
, CoUnmarshalInterface
);
999 ok_more_than_one_lock();
1001 IStream_Seek(pStream
, ullZero
, STREAM_SEEK_SET
, NULL
);
1002 /* marshal the proxy */
1003 hr
= CoMarshalInterface(pStream
, &IID_IClassFactory
, pProxy
, MSHCTX_INPROC
, NULL
, MSHLFLAGS_NORMAL
);
1004 ok_ole_success(hr
, CoMarshalInterface
);
1006 ok_more_than_one_lock();
1008 IStream_Seek(pStream
, ullZero
, STREAM_SEEK_SET
, NULL
);
1009 /* unmarshal the second proxy to the object */
1010 hr
= CoUnmarshalInterface(pStream
, &IID_IClassFactory
, (void **)&pProxy2
);
1011 ok_ole_success(hr
, CoUnmarshalInterface
);
1012 IStream_Release(pStream
);
1014 /* now the proxies should be as follows:
1015 * pProxy -> &Test_ClassFactory
1016 * pProxy2 -> &Test_ClassFactory
1017 * they should NOT be as follows:
1018 * pProxy -> &Test_ClassFactory
1020 * the above can only really be tested by looking in +ole traces
1023 ok_more_than_one_lock();
1025 IUnknown_Release(pProxy
);
1027 ok_more_than_one_lock();
1028 ok_non_zero_external_conn();
1030 IUnknown_Release(pProxy2
);
1033 ok_zero_external_conn();
1034 ok_last_release_closes(TRUE
);
1036 end_host_object(tid
, thread
);
1039 /* tests success case of an interthread marshal and then table-weak-marshaling the proxy */
1040 static void test_proxy_marshal_and_unmarshal_weak(void)
1043 IStream
*pStream
= NULL
;
1044 IUnknown
*pProxy
= NULL
;
1045 IUnknown
*pProxy2
= NULL
;
1050 external_connections
= 0;
1052 hr
= CreateStreamOnHGlobal(NULL
, TRUE
, &pStream
);
1053 ok_ole_success(hr
, CreateStreamOnHGlobal
);
1054 tid
= start_host_object(pStream
, &IID_IClassFactory
, (IUnknown
*)&Test_ClassFactory
, MSHLFLAGS_NORMAL
, &thread
);
1056 ok_more_than_one_lock();
1057 ok_non_zero_external_conn();
1059 IStream_Seek(pStream
, ullZero
, STREAM_SEEK_SET
, NULL
);
1060 hr
= CoUnmarshalInterface(pStream
, &IID_IClassFactory
, (void **)&pProxy
);
1061 ok_ole_success(hr
, CoUnmarshalInterface
);
1063 ok_more_than_one_lock();
1064 ok_non_zero_external_conn();
1066 IStream_Seek(pStream
, ullZero
, STREAM_SEEK_SET
, NULL
);
1067 /* marshal the proxy */
1068 hr
= CoMarshalInterface(pStream
, &IID_IClassFactory
, pProxy
, MSHCTX_INPROC
, NULL
, MSHLFLAGS_TABLEWEAK
);
1069 ok_ole_success(hr
, CoMarshalInterface
);
1071 ok_more_than_one_lock();
1072 ok_non_zero_external_conn();
1074 /* release the original proxy to test that we successfully keep the
1075 * original object alive */
1076 IUnknown_Release(pProxy
);
1078 IStream_Seek(pStream
, ullZero
, STREAM_SEEK_SET
, NULL
);
1079 hr
= CoUnmarshalInterface(pStream
, &IID_IClassFactory
, (void **)&pProxy2
);
1081 ok(hr
== CO_E_OBJNOTREG
, "CoUnmarshalInterface should return CO_E_OBJNOTREG instead of 0x%08x\n", hr
);
1084 ok_zero_external_conn();
1085 ok_last_release_closes(TRUE
);
1087 IStream_Release(pStream
);
1089 end_host_object(tid
, thread
);
1092 /* tests success case of an interthread marshal and then table-strong-marshaling the proxy */
1093 static void test_proxy_marshal_and_unmarshal_strong(void)
1096 IStream
*pStream
= NULL
;
1097 IUnknown
*pProxy
= NULL
;
1098 IUnknown
*pProxy2
= NULL
;
1103 external_connections
= 0;
1105 hr
= CreateStreamOnHGlobal(NULL
, TRUE
, &pStream
);
1106 ok_ole_success(hr
, CreateStreamOnHGlobal
);
1107 tid
= start_host_object(pStream
, &IID_IClassFactory
, (IUnknown
*)&Test_ClassFactory
, MSHLFLAGS_NORMAL
, &thread
);
1109 ok_more_than_one_lock();
1110 ok_non_zero_external_conn();
1112 IStream_Seek(pStream
, ullZero
, STREAM_SEEK_SET
, NULL
);
1113 hr
= CoUnmarshalInterface(pStream
, &IID_IClassFactory
, (void **)&pProxy
);
1114 ok_ole_success(hr
, CoUnmarshalInterface
);
1116 ok_more_than_one_lock();
1117 ok_non_zero_external_conn();
1119 IStream_Seek(pStream
, ullZero
, STREAM_SEEK_SET
, NULL
);
1120 /* marshal the proxy */
1121 hr
= CoMarshalInterface(pStream
, &IID_IClassFactory
, pProxy
, MSHCTX_INPROC
, NULL
, MSHLFLAGS_TABLESTRONG
);
1122 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
1124 ok_more_than_one_lock();
1125 ok_non_zero_external_conn();
1127 /* release the original proxy to test that we successfully keep the
1128 * original object alive */
1129 IUnknown_Release(pProxy
);
1131 IStream_Seek(pStream
, ullZero
, STREAM_SEEK_SET
, NULL
);
1132 hr
= CoUnmarshalInterface(pStream
, &IID_IClassFactory
, (void **)&pProxy2
);
1133 ok_ole_success(hr
, CoUnmarshalInterface
);
1135 ok_more_than_one_lock();
1136 ok_non_zero_external_conn();
1138 IUnknown_Release(pProxy2
);
1140 ok_more_than_one_lock();
1141 ok_non_zero_external_conn();
1143 IStream_Release(pStream
);
1145 end_host_object(tid
, thread
);
1149 ok_zero_external_conn();
1150 ok_last_release_closes(FALSE
);
1154 /* tests that stubs are released when the containing apartment is destroyed */
1155 static void test_marshal_stub_apartment_shutdown(void)
1158 IStream
*pStream
= NULL
;
1159 IUnknown
*pProxy
= NULL
;
1164 external_connections
= 0;
1166 hr
= CreateStreamOnHGlobal(NULL
, TRUE
, &pStream
);
1167 ok_ole_success(hr
, CreateStreamOnHGlobal
);
1168 tid
= start_host_object(pStream
, &IID_IClassFactory
, (IUnknown
*)&Test_ClassFactory
, MSHLFLAGS_NORMAL
, &thread
);
1170 ok_more_than_one_lock();
1171 ok_non_zero_external_conn();
1173 IStream_Seek(pStream
, ullZero
, STREAM_SEEK_SET
, NULL
);
1174 hr
= CoUnmarshalInterface(pStream
, &IID_IClassFactory
, (void **)&pProxy
);
1175 ok_ole_success(hr
, CoUnmarshalInterface
);
1176 IStream_Release(pStream
);
1178 ok_more_than_one_lock();
1179 ok_non_zero_external_conn();
1181 end_host_object(tid
, thread
);
1185 ok_zero_external_conn();
1186 ok_last_release_closes(FALSE
);
1189 IUnknown_Release(pProxy
);
1194 /* tests that proxies are released when the containing apartment is destroyed */
1195 static void test_marshal_proxy_apartment_shutdown(void)
1198 IStream
*pStream
= NULL
;
1199 IClassFactory
*proxy
;
1206 external_connections
= 0;
1208 hr
= CreateStreamOnHGlobal(NULL
, TRUE
, &pStream
);
1209 ok_ole_success(hr
, CreateStreamOnHGlobal
);
1210 tid
= start_host_object(pStream
, &IID_IClassFactory
, (IUnknown
*)&Test_ClassFactory
, MSHLFLAGS_NORMAL
, &thread
);
1212 ok_more_than_one_lock();
1213 ok_non_zero_external_conn();
1215 IStream_Seek(pStream
, ullZero
, STREAM_SEEK_SET
, NULL
);
1216 hr
= CoUnmarshalInterface(pStream
, &IID_IClassFactory
, (void **)&proxy
);
1217 ok_ole_success(hr
, CoUnmarshalInterface
);
1218 IStream_Release(pStream
);
1220 ok_more_than_one_lock();
1221 ok_non_zero_external_conn();
1226 ok_zero_external_conn();
1227 ok_last_release_closes(TRUE
);
1229 hr
= IClassFactory_CreateInstance(proxy
, NULL
, &IID_IUnknown
, (void **)&unk
);
1230 ok(hr
== CO_E_OBJNOTCONNECTED
, "got %#x\n", hr
);
1232 ref
= IClassFactory_Release(proxy
);
1233 ok(!ref
, "got %d refs\n", ref
);
1237 end_host_object(tid
, thread
);
1239 CoInitializeEx(NULL
, COINIT_APARTMENTTHREADED
);
1242 /* tests that proxies are released when the containing mta apartment is destroyed */
1243 static void test_marshal_proxy_mta_apartment_shutdown(void)
1246 IStream
*pStream
= NULL
;
1247 IUnknown
*pProxy
= NULL
;
1252 CoInitializeEx(NULL
, COINIT_MULTITHREADED
);
1255 external_connections
= 0;
1257 hr
= CreateStreamOnHGlobal(NULL
, TRUE
, &pStream
);
1258 ok_ole_success(hr
, CreateStreamOnHGlobal
);
1259 tid
= start_host_object(pStream
, &IID_IClassFactory
, (IUnknown
*)&Test_ClassFactory
, MSHLFLAGS_NORMAL
, &thread
);
1261 ok_more_than_one_lock();
1262 ok_non_zero_external_conn();
1264 IStream_Seek(pStream
, ullZero
, STREAM_SEEK_SET
, NULL
);
1265 hr
= CoUnmarshalInterface(pStream
, &IID_IClassFactory
, (void **)&pProxy
);
1266 ok_ole_success(hr
, CoUnmarshalInterface
);
1267 IStream_Release(pStream
);
1269 ok_more_than_one_lock();
1270 ok_non_zero_external_conn();
1275 ok_zero_external_conn();
1276 ok_last_release_closes(TRUE
);
1278 IUnknown_Release(pProxy
);
1282 end_host_object(tid
, thread
);
1284 CoInitializeEx(NULL
, COINIT_APARTMENTTHREADED
);
1287 static void test_marshal_channel_buffer(void)
1289 DWORD registration_key
;
1290 IUnknown
*proxy
= NULL
;
1291 IOleWindow
*ole_window
;
1298 struct host_object_data object_data
= { NULL
, &IID_IOleClientSite
, (IUnknown
*)&Test_OleClientSite
,
1299 MSHLFLAGS_NORMAL
, NULL
, (IUnknown
*)&PSFactoryBuffer
,
1300 &CLSID_WineTestPSFactoryBuffer
};
1303 external_connections
= 0;
1305 hr
= CoGetPSClsid(&IID_IOleWindow
, &clsid
);
1306 ok_ole_success(hr
, "CoGetPSClsid");
1308 hr
= CoGetClassObject(&clsid
, CLSCTX_INPROC_SERVER
, NULL
, &IID_IPSFactoryBuffer
,
1309 (void **)&ps_factory_buffer
);
1310 ok_ole_success(hr
, "CoGetClassObject");
1312 hr
= CreateStreamOnHGlobal(NULL
, TRUE
, &object_data
.stream
);
1313 ok_ole_success(hr
, CreateStreamOnHGlobal
);
1314 tid
= start_host_object2(&object_data
, &thread
);
1316 IStream_Seek(object_data
.stream
, ullZero
, STREAM_SEEK_SET
, NULL
);
1317 hr
= CoUnmarshalInterface(object_data
.stream
, &IID_IUnknown
, (void **)&proxy
);
1318 ok_ole_success(hr
, CoUnmarshalInterface
);
1319 IStream_Release(object_data
.stream
);
1321 hr
= CoRegisterClassObject(&CLSID_WineTestPSFactoryBuffer
, (IUnknown
*)&PSFactoryBuffer
,
1322 CLSCTX_INPROC_SERVER
, REGCLS_MULTIPLEUSE
, ®istration_key
);
1323 ok(hr
== S_OK
, "CoRegisterClassObject failed: %08x\n", hr
);
1325 hr
= CoRegisterPSClsid(&IID_IOleWindow
, &CLSID_WineTestPSFactoryBuffer
);
1326 ok(hr
== S_OK
, "CoRegisterPSClsid failed: %08x\n", hr
);
1328 SET_EXPECT(CreateStub
);
1329 SET_EXPECT(CreateProxy
);
1330 hr
= IUnknown_QueryInterface(proxy
, &IID_IOleWindow
, (void**)&ole_window
);
1331 ok(hr
== S_OK
, "Could not get IOleWindow iface: %08x\n", hr
);
1332 CHECK_CALLED(CreateStub
);
1333 CHECK_CALLED(CreateProxy
);
1336 SET_EXPECT(GetWindow
);
1337 hr
= IOleWindow_GetWindow(ole_window
, &hwnd
);
1338 ok(hr
== S_OK
, "GetWindow failed: %08x\n", hr
);
1339 ok((DWORD
)(DWORD_PTR
)hwnd
== 0xdeadbeef, "hwnd = %p\n", hwnd
);
1340 CHECK_CALLED(Invoke
);
1341 CHECK_CALLED(GetWindow
);
1343 IOleWindow_Release(ole_window
);
1345 SET_EXPECT(Disconnect
);
1346 IUnknown_Release(proxy
);
1348 CHECK_CALLED(Disconnect
);
1350 hr
= CoRevokeClassObject(registration_key
);
1351 ok(hr
== S_OK
, "CoRevokeClassObject failed: %08x\n", hr
);
1353 end_host_object(tid
, thread
);
1356 static const CLSID
*unmarshal_class
;
1357 DEFINE_EXPECT(CustomMarshal_GetUnmarshalClass
);
1358 DEFINE_EXPECT(CustomMarshal_GetMarshalSizeMax
);
1359 DEFINE_EXPECT(CustomMarshal_MarshalInterface
);
1361 static HRESULT WINAPI
CustomMarshal_QueryInterface(IMarshal
*iface
, REFIID riid
, void **ppv
)
1363 if (IsEqualIID(riid
, &IID_IUnknown
) || IsEqualIID(riid
, &IID_IMarshal
)) {
1369 return E_NOINTERFACE
;
1371 IUnknown_AddRef((IUnknown
*)*ppv
);
1375 static ULONG WINAPI
CustomMarshal_AddRef(IMarshal
*iface
)
1380 static ULONG WINAPI
CustomMarshal_Release(IMarshal
*iface
)
1385 static HRESULT WINAPI
CustomMarshal_GetUnmarshalClass(IMarshal
*iface
, REFIID riid
,
1386 void *pv
, DWORD dwDestContext
, void *pvDestContext
, DWORD mshlflags
, CLSID
*clsid
)
1388 CHECK_EXPECT2(CustomMarshal_GetUnmarshalClass
);
1389 *clsid
= *unmarshal_class
;
1393 static HRESULT WINAPI
CustomMarshal_GetMarshalSizeMax(IMarshal
*iface
, REFIID riid
,
1394 void *pv
, DWORD dwDestContext
, void *pvDestContext
, DWORD mshlflags
, DWORD
*size
)
1396 CHECK_EXPECT(CustomMarshal_GetMarshalSizeMax
);
1397 ok(size
!= NULL
, "size = NULL\n");
1403 static HRESULT WINAPI
CustomMarshal_MarshalInterface(IMarshal
*iface
, IStream
*stream
,
1404 REFIID riid
, void *pv
, DWORD dwDestContext
, void *pvDestContext
, DWORD mshlflags
)
1406 IMarshal
*std_marshal
;
1410 CHECK_EXPECT(CustomMarshal_MarshalInterface
);
1412 if(unmarshal_class
!= &CLSID_StdMarshal
)
1415 hr
= IStream_Stat(stream
, &stat
, STATFLAG_DEFAULT
);
1416 ok_ole_success(hr
, IStream_Stat
);
1417 ok(U(stat
.cbSize
).LowPart
== 0, "stream is not empty (%d)\n", U(stat
.cbSize
).LowPart
);
1418 ok(U(stat
.cbSize
).HighPart
== 0, "stream is not empty (%d)\n", U(stat
.cbSize
).HighPart
);
1420 hr
= CoGetStandardMarshal(riid
, (IUnknown
*)iface
,
1421 dwDestContext
, NULL
, mshlflags
, &std_marshal
);
1422 ok_ole_success(hr
, CoGetStandardMarshal
);
1423 hr
= IMarshal_MarshalInterface(std_marshal
, stream
, riid
, pv
,
1424 dwDestContext
, pvDestContext
, mshlflags
);
1425 ok_ole_success(hr
, IMarshal_MarshalInterface
);
1426 IMarshal_Release(std_marshal
);
1431 static HRESULT WINAPI
CustomMarshal_UnmarshalInterface(IMarshal
*iface
,
1432 IStream
*stream
, REFIID riid
, void **ppv
)
1434 ok(0, "unexpected call\n");
1438 static HRESULT WINAPI
CustomMarshal_ReleaseMarshalData(IMarshal
*iface
, IStream
*stream
)
1440 ok(0, "unexpected call\n");
1444 static HRESULT WINAPI
CustomMarshal_DisconnectObject(IMarshal
*iface
, DWORD res
)
1446 ok(0, "unexpected call\n");
1450 static IMarshalVtbl CustomMarshalVtbl
=
1452 CustomMarshal_QueryInterface
,
1453 CustomMarshal_AddRef
,
1454 CustomMarshal_Release
,
1455 CustomMarshal_GetUnmarshalClass
,
1456 CustomMarshal_GetMarshalSizeMax
,
1457 CustomMarshal_MarshalInterface
,
1458 CustomMarshal_UnmarshalInterface
,
1459 CustomMarshal_ReleaseMarshalData
,
1460 CustomMarshal_DisconnectObject
1463 static IMarshal CustomMarshal
= { &CustomMarshalVtbl
};
1465 static void test_StdMarshal_custom_marshaling(void)
1472 hr
= CreateStreamOnHGlobal(NULL
, TRUE
, &stream
);
1473 ok_ole_success(hr
, CreateStreamOnHGlobal
);
1475 unmarshal_class
= &CLSID_StdMarshal
;
1476 SET_EXPECT(CustomMarshal_GetUnmarshalClass
);
1477 SET_EXPECT(CustomMarshal_MarshalInterface
);
1478 hr
= CoMarshalInterface(stream
, &IID_IUnknown
, (IUnknown
*)&CustomMarshal
,
1479 MSHCTX_INPROC
, NULL
, MSHLFLAGS_NORMAL
);
1480 ok_ole_success(hr
, CoMarshalInterface
);
1481 CHECK_CALLED(CustomMarshal_GetUnmarshalClass
);
1482 CHECK_CALLED(CustomMarshal_MarshalInterface
);
1484 hr
= IStream_Seek(stream
, ullZero
, STREAM_SEEK_SET
, NULL
);
1485 ok_ole_success(hr
, IStream_Seek
);
1486 hr
= CoUnmarshalInterface(stream
, &IID_IUnknown
, (void**)&unk
);
1487 ok_ole_success(hr
, CoUnmarshalInterface
);
1488 ok(unk
== (IUnknown
*)&CustomMarshal
, "unk != &CustomMarshal\n");
1489 IUnknown_Release(unk
);
1490 IStream_Release(stream
);
1492 hr
= CreateStreamOnHGlobal(NULL
, TRUE
, &stream
);
1493 ok_ole_success(hr
, CreateStreamOnHGlobal
);
1495 SET_EXPECT(CustomMarshal_GetUnmarshalClass
);
1496 SET_EXPECT(CustomMarshal_MarshalInterface
);
1497 hr
= CoMarshalInterface(stream
, &IID_IUnknown
, (IUnknown
*)&CustomMarshal
,
1498 MSHCTX_INPROC
, NULL
, MSHLFLAGS_NORMAL
);
1499 ok_ole_success(hr
, CoMarshalInterface
);
1500 CHECK_CALLED(CustomMarshal_GetUnmarshalClass
);
1501 CHECK_CALLED(CustomMarshal_MarshalInterface
);
1503 hr
= IStream_Seek(stream
, ullZero
, STREAM_SEEK_SET
, NULL
);
1504 ok_ole_success(hr
, IStream_Seek
);
1505 hr
= CoReleaseMarshalData(stream
);
1506 ok_ole_success(hr
, CoReleaseMarshalData
);
1507 IStream_Release(stream
);
1509 SET_EXPECT(CustomMarshal_GetMarshalSizeMax
);
1510 hr
= CoGetMarshalSizeMax(&size
, &IID_IUnknown
, (IUnknown
*)&CustomMarshal
,
1511 MSHCTX_INPROC
, NULL
, MSHLFLAGS_NORMAL
);
1512 ok_ole_success(hr
, CoGetMarshalSizeMax
);
1513 CHECK_CALLED(CustomMarshal_GetMarshalSizeMax
);
1514 ok(size
== sizeof(OBJREF
), "size = %d, expected %d\n", size
, (int)sizeof(OBJREF
));
1517 static void test_DfMarshal_custom_marshaling(void)
1524 hr
= CreateStreamOnHGlobal(NULL
, TRUE
, &stream
);
1525 ok_ole_success(hr
, CreateStreamOnHGlobal
);
1527 unmarshal_class
= &CLSID_DfMarshal
;
1528 SET_EXPECT(CustomMarshal_GetUnmarshalClass
);
1529 SET_EXPECT(CustomMarshal_GetMarshalSizeMax
);
1530 SET_EXPECT(CustomMarshal_MarshalInterface
);
1531 hr
= CoMarshalInterface(stream
, &IID_IUnknown
, (IUnknown
*)&CustomMarshal
,
1532 MSHCTX_INPROC
, NULL
, MSHLFLAGS_NORMAL
);
1533 ok_ole_success(hr
, CoMarshalInterface
);
1534 CHECK_CALLED(CustomMarshal_GetUnmarshalClass
);
1535 CHECK_CALLED(CustomMarshal_GetMarshalSizeMax
);
1536 CHECK_CALLED(CustomMarshal_MarshalInterface
);
1538 hr
= IStream_Seek(stream
, ullZero
, STREAM_SEEK_SET
, NULL
);
1539 ok_ole_success(hr
, IStream_Seek
);
1540 size
= FIELD_OFFSET(OBJREF
, u_objref
.u_custom
.pData
);
1541 hr
= IStream_Read(stream
, &objref
, size
, &read
);
1542 ok_ole_success(hr
, IStream_Read
);
1543 ok(read
== size
, "read = %d, expected %d\n", read
, size
);
1544 ok(objref
.signature
== OBJREF_SIGNATURE
, "objref.signature = %x\n",
1546 ok(objref
.flags
== OBJREF_CUSTOM
, "objref.flags = %x\n", objref
.flags
);
1547 ok(IsEqualIID(&objref
.iid
, &IID_IUnknown
), "objref.iid = %s\n",
1548 wine_dbgstr_guid(&objref
.iid
));
1549 ok(IsEqualIID(&objref
.u_objref
.u_custom
.clsid
, &CLSID_DfMarshal
),
1550 "custom.clsid = %s\n", wine_dbgstr_guid(&objref
.u_objref
.u_custom
.clsid
));
1551 ok(!objref
.u_objref
.u_custom
.cbExtension
, "custom.cbExtension = %d\n",
1552 objref
.u_objref
.u_custom
.cbExtension
);
1553 ok(!objref
.u_objref
.u_custom
.size
, "custom.size = %d\n",
1554 objref
.u_objref
.u_custom
.size
);
1556 IStream_Release(stream
);
1558 SET_EXPECT(CustomMarshal_GetMarshalSizeMax
);
1559 hr
= CoGetMarshalSizeMax(&size
, &IID_IUnknown
, (IUnknown
*)&CustomMarshal
,
1560 MSHCTX_INPROC
, NULL
, MSHLFLAGS_NORMAL
);
1561 ok_ole_success(hr
, CoGetMarshalSizeMax
);
1562 CHECK_CALLED(CustomMarshal_GetMarshalSizeMax
);
1563 ok(size
== sizeof(OBJREF
), "size = %d, expected %d\n", size
, (int)sizeof(OBJREF
));
1566 static void test_CoGetStandardMarshal(void)
1568 DUALSTRINGARRAY
*dualstringarr
;
1569 STDOBJREF
*stdobjref
;
1578 hr
= CreateStreamOnHGlobal(NULL
, TRUE
, &stream
);
1579 ok_ole_success(hr
, CreateStreamOnHGlobal
);
1581 hr
= CoGetStandardMarshal(&IID_IUnknown
, &Test_Unknown
,
1582 MSHCTX_INPROC
, NULL
, MSHLFLAGS_NORMAL
, &marshal
);
1583 ok_ole_success(hr
, CoGetStandardMarshal
);
1585 hr
= IMarshal_GetUnmarshalClass(marshal
, &IID_IUnknown
, &Test_Unknown
,
1586 MSHCTX_INPROC
, NULL
, MSHLFLAGS_NORMAL
, &clsid
);
1587 ok_ole_success(hr
, IMarshal_GetUnmarshalClass
);
1588 ok(IsEqualGUID(&clsid
, &CLSID_StdMarshal
), "clsid = %s\n", wine_dbgstr_guid(&clsid
));
1590 hr
= IMarshal_GetMarshalSizeMax(marshal
, &IID_IUnknown
, &Test_Unknown
,
1591 MSHCTX_INPROC
, NULL
, MSHLFLAGS_NORMAL
, &size
);
1592 ok_ole_success(hr
, IMarshal_GetMarshalSizeMax
);
1593 hr
= CoGetMarshalSizeMax(&read
, &IID_IUnknown
, &Test_Unknown
,
1594 MSHCTX_INPROC
, NULL
, MSHLFLAGS_NORMAL
);
1595 ok_ole_success(hr
, CoGetMarshalSizeMax
);
1596 ok(size
== read
, "IMarshal_GetMarshalSizeMax size = %d, expected %d\n", size
, read
);
1598 hr
= IMarshal_MarshalInterface(marshal
, stream
, &IID_IUnknown
,
1599 &Test_Unknown
, MSHCTX_INPROC
, NULL
, MSHLFLAGS_NORMAL
);
1600 ok_ole_success(hr
, IMarshal_MarshalInterface
);
1602 hr
= IStream_Seek(stream
, ullZero
, STREAM_SEEK_SET
, NULL
);
1603 ok_ole_success(hr
, IStream_Seek
);
1604 size
= FIELD_OFFSET(OBJREF
, u_objref
.u_standard
.saResAddr
.aStringArray
);
1605 hr
= IStream_Read(stream
, &objref
, size
, &read
);
1606 ok_ole_success(hr
, IStream_Read
);
1607 ok(read
== size
, "read = %d, expected %d\n", read
, size
);
1608 ok(objref
.signature
== OBJREF_SIGNATURE
, "objref.signature = %x\n",
1610 ok(objref
.flags
== OBJREF_STANDARD
, "objref.flags = %x\n", objref
.flags
);
1611 ok(IsEqualIID(&objref
.iid
, &IID_IUnknown
), "objref.iid = %s\n",
1612 wine_dbgstr_guid(&objref
.iid
));
1613 stdobjref
= &objref
.u_objref
.u_standard
.std
;
1614 ok(stdobjref
->flags
== 0, "stdobjref.flags = %d\n", stdobjref
->flags
);
1615 ok(stdobjref
->cPublicRefs
== 5, "stdobjref.cPublicRefs = %d\n",
1616 stdobjref
->cPublicRefs
);
1617 dualstringarr
= &objref
.u_objref
.u_standard
.saResAddr
;
1618 ok(dualstringarr
->wNumEntries
== 0, "dualstringarr.wNumEntries = %d\n",
1619 dualstringarr
->wNumEntries
);
1620 ok(dualstringarr
->wSecurityOffset
== 0, "dualstringarr.wSecurityOffset = %d\n",
1621 dualstringarr
->wSecurityOffset
);
1623 hr
= IStream_Seek(stream
, ullZero
, STREAM_SEEK_SET
, NULL
);
1624 ok_ole_success(hr
, IStream_Seek
);
1625 hr
= IMarshal_UnmarshalInterface(marshal
, stream
, &IID_IUnknown
, (void**)&unk
);
1626 ok_ole_success(hr
, IMarshal_UnmarshalInterface
);
1627 IUnknown_Release(unk
);
1629 hr
= IStream_Seek(stream
, ullZero
, STREAM_SEEK_SET
, NULL
);
1630 ok_ole_success(hr
, IStream_Seek
);
1631 hr
= IMarshal_MarshalInterface(marshal
, stream
, &IID_IUnknown
,
1632 &Test_Unknown
, MSHCTX_INPROC
, NULL
, MSHLFLAGS_NORMAL
);
1633 ok_ole_success(hr
, IMarshal_MarshalInterface
);
1635 hr
= IStream_Seek(stream
, ullZero
, STREAM_SEEK_SET
, NULL
);
1636 ok_ole_success(hr
, IStream_Seek
);
1637 hr
= IMarshal_ReleaseMarshalData(marshal
, stream
);
1638 ok_ole_success(hr
, IMarshal_ReleaseMarshalData
);
1639 IStream_Release(stream
);
1641 IMarshal_Release(marshal
);
1646 HANDLE marshal_event
;
1647 HANDLE unmarshal_event
;
1650 /* helper for test_no_couninitialize_server */
1651 static DWORD CALLBACK
no_couninitialize_server_proc(LPVOID p
)
1653 struct ncu_params
*ncu_params
= p
;
1656 CoInitializeEx(NULL
, COINIT_MULTITHREADED
);
1658 hr
= CoMarshalInterface(ncu_params
->stream
, &IID_IClassFactory
, (IUnknown
*)&Test_ClassFactory
, MSHCTX_INPROC
, NULL
, MSHLFLAGS_NORMAL
);
1659 ok_ole_success(hr
, CoMarshalInterface
);
1661 SetEvent(ncu_params
->marshal_event
);
1663 ok( !WaitForSingleObject(ncu_params
->unmarshal_event
, 10000), "wait timed out\n" );
1665 /* die without calling CoUninitialize */
1670 /* tests apartment that an apartment with a stub is released without deadlock
1671 * if the owning thread exits */
1672 static void test_no_couninitialize_server(void)
1675 IStream
*pStream
= NULL
;
1676 IUnknown
*pProxy
= NULL
;
1679 struct ncu_params ncu_params
;
1682 external_connections
= 0;
1684 ncu_params
.marshal_event
= CreateEventA(NULL
, TRUE
, FALSE
, NULL
);
1685 ncu_params
.unmarshal_event
= CreateEventA(NULL
, TRUE
, FALSE
, NULL
);
1687 hr
= CreateStreamOnHGlobal(NULL
, TRUE
, &pStream
);
1688 ok_ole_success(hr
, CreateStreamOnHGlobal
);
1689 ncu_params
.stream
= pStream
;
1691 thread
= CreateThread(NULL
, 0, no_couninitialize_server_proc
, &ncu_params
, 0, &tid
);
1693 ok( !WaitForSingleObject(ncu_params
.marshal_event
, 10000), "wait timed out\n" );
1694 ok_more_than_one_lock();
1695 ok_non_zero_external_conn();
1697 IStream_Seek(pStream
, ullZero
, STREAM_SEEK_SET
, NULL
);
1698 hr
= CoUnmarshalInterface(pStream
, &IID_IClassFactory
, (void **)&pProxy
);
1699 ok_ole_success(hr
, CoUnmarshalInterface
);
1700 IStream_Release(pStream
);
1702 ok_more_than_one_lock();
1703 ok_non_zero_external_conn();
1705 SetEvent(ncu_params
.unmarshal_event
);
1706 ok( !WaitForSingleObject(thread
, 10000), "wait timed out\n" );
1710 ok_zero_external_conn();
1711 ok_last_release_closes(FALSE
);
1714 CloseHandle(thread
);
1715 CloseHandle(ncu_params
.marshal_event
);
1716 CloseHandle(ncu_params
.unmarshal_event
);
1718 IUnknown_Release(pProxy
);
1723 /* STA -> STA call during DLL_THREAD_DETACH */
1724 static DWORD CALLBACK
no_couninitialize_client_proc(LPVOID p
)
1726 struct ncu_params
*ncu_params
= p
;
1728 IUnknown
*pProxy
= NULL
;
1730 CoInitializeEx(NULL
, COINIT_APARTMENTTHREADED
);
1732 hr
= CoUnmarshalInterface(ncu_params
->stream
, &IID_IClassFactory
, (void **)&pProxy
);
1733 ok_ole_success(hr
, CoUnmarshalInterface
);
1734 IStream_Release(ncu_params
->stream
);
1736 ok_more_than_one_lock();
1738 /* die without calling CoUninitialize */
1743 /* tests STA -> STA call during DLL_THREAD_DETACH doesn't deadlock */
1744 static void test_no_couninitialize_client(void)
1747 IStream
*pStream
= NULL
;
1752 struct ncu_params ncu_params
;
1755 external_connections
= 0;
1757 hr
= CreateStreamOnHGlobal(NULL
, TRUE
, &pStream
);
1758 ok_ole_success(hr
, CreateStreamOnHGlobal
);
1759 ncu_params
.stream
= pStream
;
1761 /* NOTE: assumes start_host_object uses an STA to host the object, as MTAs
1762 * always deadlock when called from within DllMain */
1763 host_tid
= start_host_object(pStream
, &IID_IClassFactory
, (IUnknown
*)&Test_ClassFactory
, MSHLFLAGS_NORMAL
, &host_thread
);
1764 IStream_Seek(pStream
, ullZero
, STREAM_SEEK_SET
, NULL
);
1766 ok_more_than_one_lock();
1767 ok_non_zero_external_conn();
1769 thread
= CreateThread(NULL
, 0, no_couninitialize_client_proc
, &ncu_params
, 0, &tid
);
1771 ok( !WaitForSingleObject(thread
, 10000), "wait timed out\n" );
1772 CloseHandle(thread
);
1775 ok_zero_external_conn();
1776 ok_last_release_closes(TRUE
);
1778 end_host_object(host_tid
, host_thread
);
1781 static BOOL crash_thread_success
;
1783 static DWORD CALLBACK
crash_couninitialize_proc(void *p
)
1792 hr
= CreateStreamOnHGlobal(NULL
, TRUE
, &stream
);
1793 ok_ole_success(hr
, CreateStreamOnHGlobal
);
1795 hr
= CoMarshalInterface(stream
, &IID_IUnknown
, &TestCrash_Unknown
, MSHCTX_INPROC
, NULL
, MSHLFLAGS_NORMAL
);
1796 ok_ole_success(hr
, CoMarshalInterface
);
1798 IStream_Seek(stream
, ullZero
, STREAM_SEEK_SET
, NULL
);
1800 hr
= CoReleaseMarshalData(stream
);
1801 ok_ole_success(hr
, CoReleaseMarshalData
);
1805 hr
= CoMarshalInterface(stream
, &IID_IUnknown
, &TestCrash_Unknown
, MSHCTX_INPROC
, NULL
, MSHLFLAGS_NORMAL
);
1806 ok_ole_success(hr
, CoMarshalInterface
);
1808 ok_more_than_one_lock();
1810 trace("CoUninitialize >>>\n");
1812 trace("CoUninitialize <<<\n");
1816 IStream_Release(stream
);
1817 crash_thread_success
= TRUE
;
1821 static void test_crash_couninitialize(void)
1826 crash_thread_success
= FALSE
;
1827 thread
= CreateThread(NULL
, 0, crash_couninitialize_proc
, NULL
, 0, &tid
);
1828 ok(!WaitForSingleObject(thread
, 10000), "wait timed out\n");
1829 CloseHandle(thread
);
1830 ok(crash_thread_success
, "Crash thread failed\n");
1833 /* tests success case of a same-thread table-weak marshal, unmarshal, unmarshal */
1834 static void test_tableweak_marshal_and_unmarshal_twice(void)
1837 IStream
*pStream
= NULL
;
1838 IUnknown
*pProxy1
= NULL
;
1839 IUnknown
*pProxy2
= NULL
;
1844 external_connections
= 0;
1846 hr
= CreateStreamOnHGlobal(NULL
, TRUE
, &pStream
);
1847 ok_ole_success(hr
, CreateStreamOnHGlobal
);
1848 tid
= start_host_object(pStream
, &IID_IClassFactory
, (IUnknown
*)&Test_ClassFactory
, MSHLFLAGS_TABLEWEAK
, &thread
);
1850 ok_more_than_one_lock();
1851 ok_zero_external_conn();
1853 IStream_Seek(pStream
, ullZero
, STREAM_SEEK_SET
, NULL
);
1854 hr
= CoUnmarshalInterface(pStream
, &IID_IClassFactory
, (void **)&pProxy1
);
1855 ok_ole_success(hr
, CoUnmarshalInterface
);
1857 ok_more_than_one_lock();
1858 ok_non_zero_external_conn();
1860 IStream_Seek(pStream
, ullZero
, STREAM_SEEK_SET
, NULL
);
1861 hr
= CoUnmarshalInterface(pStream
, &IID_IClassFactory
, (void **)&pProxy2
);
1862 ok_ole_success(hr
, CoUnmarshalInterface
);
1864 ok_more_than_one_lock();
1866 IUnknown_Release(pProxy1
);
1867 ok_non_zero_external_conn();
1868 IUnknown_Release(pProxy2
);
1869 ok_zero_external_conn();
1870 ok_last_release_closes(TRUE
);
1872 /* When IExternalConnection is present COM's lifetime management
1873 * behaviour is altered; the remaining weak ref prevents stub shutdown. */
1874 if (with_external_conn
)
1876 ok_more_than_one_lock();
1877 IStream_Seek(pStream
, ullZero
, STREAM_SEEK_SET
, NULL
);
1878 release_host_object(tid
, 0);
1881 /* Without IExternalConnection this line is shows the difference between weak and strong table marshaling
1882 * weak has cLocks == 0, strong has cLocks > 0. */
1885 IStream_Release(pStream
);
1886 end_host_object(tid
, thread
);
1889 /* tests releasing after unmarshaling one object */
1890 static void test_tableweak_marshal_releasedata1(void)
1893 IStream
*pStream
= NULL
;
1894 IUnknown
*pProxy1
= NULL
;
1895 IUnknown
*pProxy2
= NULL
;
1900 external_connections
= 0;
1902 hr
= CreateStreamOnHGlobal(NULL
, TRUE
, &pStream
);
1903 ok_ole_success(hr
, CreateStreamOnHGlobal
);
1904 tid
= start_host_object(pStream
, &IID_IClassFactory
, (IUnknown
*)&Test_ClassFactory
, MSHLFLAGS_TABLEWEAK
, &thread
);
1906 ok_more_than_one_lock();
1907 ok_zero_external_conn();
1909 IStream_Seek(pStream
, ullZero
, STREAM_SEEK_SET
, NULL
);
1910 hr
= CoUnmarshalInterface(pStream
, &IID_IClassFactory
, (void **)&pProxy1
);
1911 ok_ole_success(hr
, CoUnmarshalInterface
);
1913 ok_more_than_one_lock();
1914 ok_non_zero_external_conn();
1916 /* release the remaining reference on the object by calling
1917 * CoReleaseMarshalData in the hosting thread */
1918 IStream_Seek(pStream
, ullZero
, STREAM_SEEK_SET
, NULL
);
1919 release_host_object(tid
, 0);
1921 ok_more_than_one_lock();
1922 ok_non_zero_external_conn();
1924 IStream_Seek(pStream
, ullZero
, STREAM_SEEK_SET
, NULL
);
1925 hr
= CoUnmarshalInterface(pStream
, &IID_IClassFactory
, (void **)&pProxy2
);
1926 ok_ole_success(hr
, CoUnmarshalInterface
);
1927 IStream_Release(pStream
);
1929 ok_more_than_one_lock();
1930 ok_non_zero_external_conn();
1932 IUnknown_Release(pProxy1
);
1936 ok_non_zero_external_conn();
1937 IUnknown_Release(pProxy2
);
1940 /* this line is shows the difference between weak and strong table marshaling:
1941 * weak has cLocks == 0
1942 * strong has cLocks > 0 */
1944 ok_zero_external_conn();
1945 ok_last_release_closes(TRUE
);
1947 end_host_object(tid
, thread
);
1950 /* tests releasing after unmarshaling one object */
1951 static void test_tableweak_marshal_releasedata2(void)
1954 IStream
*pStream
= NULL
;
1955 IUnknown
*pProxy
= NULL
;
1960 external_connections
= 0;
1962 hr
= CreateStreamOnHGlobal(NULL
, TRUE
, &pStream
);
1963 ok_ole_success(hr
, CreateStreamOnHGlobal
);
1964 tid
= start_host_object(pStream
, &IID_IClassFactory
, (IUnknown
*)&Test_ClassFactory
, MSHLFLAGS_TABLEWEAK
, &thread
);
1966 ok_more_than_one_lock();
1967 ok_zero_external_conn();
1969 /* release the remaining reference on the object by calling
1970 * CoReleaseMarshalData in the hosting thread */
1971 IStream_Seek(pStream
, ullZero
, STREAM_SEEK_SET
, NULL
);
1972 release_host_object(tid
, 0);
1976 IStream_Seek(pStream
, ullZero
, STREAM_SEEK_SET
, NULL
);
1977 hr
= CoUnmarshalInterface(pStream
, &IID_IClassFactory
, (void **)&pProxy
);
1980 ok(hr
== CO_E_OBJNOTREG
,
1981 "CoUnmarshalInterface should have failed with CO_E_OBJNOTREG, but returned 0x%08x instead\n",
1984 IStream_Release(pStream
);
1987 ok_zero_external_conn();
1989 end_host_object(tid
, thread
);
1992 struct duo_marshal_data
1994 MSHLFLAGS marshal_flags1
, marshal_flags2
;
1995 IStream
*pStream1
, *pStream2
;
2000 static DWORD CALLBACK
duo_marshal_thread_proc(void *p
)
2003 struct duo_marshal_data
*data
= p
;
2004 HANDLE hQuitEvent
= data
->hQuitEvent
;
2007 CoInitializeEx(NULL
, COINIT_APARTMENTTHREADED
);
2009 hr
= CoMarshalInterface(data
->pStream1
, &IID_IClassFactory
, (IUnknown
*)&Test_ClassFactory
, MSHCTX_INPROC
, NULL
, data
->marshal_flags1
);
2010 ok_ole_success(hr
, "CoMarshalInterface");
2012 hr
= CoMarshalInterface(data
->pStream2
, &IID_IClassFactory
, (IUnknown
*)&Test_ClassFactory
, MSHCTX_INPROC
, NULL
, data
->marshal_flags2
);
2013 ok_ole_success(hr
, "CoMarshalInterface");
2015 /* force the message queue to be created before signaling parent thread */
2016 PeekMessageA(&msg
, NULL
, WM_USER
, WM_USER
, PM_NOREMOVE
);
2018 SetEvent(data
->hReadyEvent
);
2020 while (WAIT_OBJECT_0
+ 1 == MsgWaitForMultipleObjects(1, &hQuitEvent
, FALSE
, 10000, QS_ALLINPUT
))
2022 while (PeekMessageA(&msg
, NULL
, 0, 0, PM_REMOVE
))
2024 if (msg
.hwnd
== NULL
&& msg
.message
== RELEASEMARSHALDATA
)
2026 CoReleaseMarshalData(msg
.wParam
== 1 ? data
->pStream1
: data
->pStream2
);
2027 SetEvent((HANDLE
)msg
.lParam
);
2030 DispatchMessageA(&msg
);
2033 CloseHandle(hQuitEvent
);
2040 /* tests interaction between table-weak and normal marshalling of an object */
2041 static void test_tableweak_and_normal_marshal_and_unmarshal(void)
2044 IUnknown
*pProxyWeak
= NULL
;
2045 IUnknown
*pProxyNormal
= NULL
;
2048 struct duo_marshal_data data
;
2051 external_connections
= 0;
2053 data
.hReadyEvent
= CreateEventA(NULL
, FALSE
, FALSE
, NULL
);
2054 data
.hQuitEvent
= CreateEventA(NULL
, FALSE
, FALSE
, NULL
);
2055 data
.marshal_flags1
= MSHLFLAGS_TABLEWEAK
;
2056 data
.marshal_flags2
= MSHLFLAGS_NORMAL
;
2057 hr
= CreateStreamOnHGlobal(NULL
, TRUE
, &data
.pStream1
);
2058 ok_ole_success(hr
, CreateStreamOnHGlobal
);
2059 hr
= CreateStreamOnHGlobal(NULL
, TRUE
, &data
.pStream2
);
2060 ok_ole_success(hr
, CreateStreamOnHGlobal
);
2062 thread
= CreateThread(NULL
, 0, duo_marshal_thread_proc
, &data
, 0, &tid
);
2063 ok( !WaitForSingleObject(data
.hReadyEvent
, 10000), "wait timed out\n" );
2064 CloseHandle(data
.hReadyEvent
);
2066 ok_more_than_one_lock();
2067 ok_non_zero_external_conn();
2070 IStream_Seek(data
.pStream1
, ullZero
, STREAM_SEEK_SET
, NULL
);
2071 hr
= CoUnmarshalInterface(data
.pStream1
, &IID_IClassFactory
, (void **)&pProxyWeak
);
2072 ok_ole_success(hr
, CoUnmarshalInterface
);
2074 ok_more_than_one_lock();
2077 IStream_Seek(data
.pStream2
, ullZero
, STREAM_SEEK_SET
, NULL
);
2078 hr
= CoUnmarshalInterface(data
.pStream2
, &IID_IClassFactory
, (void **)&pProxyNormal
);
2079 ok_ole_success(hr
, CoUnmarshalInterface
);
2081 ok_more_than_one_lock();
2083 IUnknown_Release(pProxyNormal
);
2085 ok_more_than_one_lock();
2086 ok_non_zero_external_conn();
2088 IUnknown_Release(pProxyWeak
);
2090 ok_zero_external_conn();
2091 ok_last_release_closes(TRUE
);
2093 /* When IExternalConnection is present COM's lifetime management
2094 * behaviour is altered; the remaining weak ref prevents stub shutdown. */
2095 if (with_external_conn
)
2097 ok_more_than_one_lock();
2098 IStream_Seek(data
.pStream1
, ullZero
, STREAM_SEEK_SET
, NULL
);
2099 release_host_object(tid
, 1);
2103 IStream_Release(data
.pStream1
);
2104 IStream_Release(data
.pStream2
);
2106 SetEvent(data
.hQuitEvent
);
2107 ok( !WaitForSingleObject(thread
, 10000), "wait timed out\n" );
2108 CloseHandle(thread
);
2111 static void test_tableweak_and_normal_marshal_and_releasedata(void)
2116 struct duo_marshal_data data
;
2119 external_connections
= 0;
2121 data
.hReadyEvent
= CreateEventA(NULL
, FALSE
, FALSE
, NULL
);
2122 data
.hQuitEvent
= CreateEventA(NULL
, FALSE
, FALSE
, NULL
);
2123 data
.marshal_flags1
= MSHLFLAGS_TABLEWEAK
;
2124 data
.marshal_flags2
= MSHLFLAGS_NORMAL
;
2125 hr
= CreateStreamOnHGlobal(NULL
, TRUE
, &data
.pStream1
);
2126 ok_ole_success(hr
, CreateStreamOnHGlobal
);
2127 hr
= CreateStreamOnHGlobal(NULL
, TRUE
, &data
.pStream2
);
2128 ok_ole_success(hr
, CreateStreamOnHGlobal
);
2130 thread
= CreateThread(NULL
, 0, duo_marshal_thread_proc
, &data
, 0, &tid
);
2131 ok( !WaitForSingleObject(data
.hReadyEvent
, 10000), "wait timed out\n" );
2132 CloseHandle(data
.hReadyEvent
);
2134 ok_more_than_one_lock();
2135 ok_non_zero_external_conn();
2137 /* release normal - which in the non-external conn case will free the object despite the weak ref. */
2138 IStream_Seek(data
.pStream2
, ullZero
, STREAM_SEEK_SET
, NULL
);
2139 release_host_object(tid
, 2);
2141 ok_zero_external_conn();
2142 ok_last_release_closes(TRUE
);
2144 if (with_external_conn
)
2146 ok_more_than_one_lock();
2147 IStream_Seek(data
.pStream1
, ullZero
, STREAM_SEEK_SET
, NULL
);
2148 release_host_object(tid
, 1);
2153 IStream_Release(data
.pStream1
);
2154 IStream_Release(data
.pStream2
);
2156 SetEvent(data
.hQuitEvent
);
2157 ok( !WaitForSingleObject(thread
, 10000), "wait timed out\n" );
2158 CloseHandle(thread
);
2161 static void test_two_tableweak_marshal_and_releasedata(void)
2166 struct duo_marshal_data data
;
2169 external_connections
= 0;
2171 data
.hReadyEvent
= CreateEventA(NULL
, FALSE
, FALSE
, NULL
);
2172 data
.hQuitEvent
= CreateEventA(NULL
, FALSE
, FALSE
, NULL
);
2173 data
.marshal_flags1
= MSHLFLAGS_TABLEWEAK
;
2174 data
.marshal_flags2
= MSHLFLAGS_TABLEWEAK
;
2175 hr
= CreateStreamOnHGlobal(NULL
, TRUE
, &data
.pStream1
);
2176 ok_ole_success(hr
, CreateStreamOnHGlobal
);
2177 hr
= CreateStreamOnHGlobal(NULL
, TRUE
, &data
.pStream2
);
2178 ok_ole_success(hr
, CreateStreamOnHGlobal
);
2180 thread
= CreateThread(NULL
, 0, duo_marshal_thread_proc
, &data
, 0, &tid
);
2181 ok( !WaitForSingleObject(data
.hReadyEvent
, 10000), "wait timed out\n" );
2182 CloseHandle(data
.hReadyEvent
);
2184 ok_more_than_one_lock();
2185 ok_zero_external_conn();
2187 /* release one weak ref - the remaining weak ref will keep the obj alive */
2188 IStream_Seek(data
.pStream1
, ullZero
, STREAM_SEEK_SET
, NULL
);
2189 release_host_object(tid
, 1);
2191 ok_more_than_one_lock();
2193 IStream_Seek(data
.pStream2
, ullZero
, STREAM_SEEK_SET
, NULL
);
2194 release_host_object(tid
, 2);
2198 IStream_Release(data
.pStream1
);
2199 IStream_Release(data
.pStream2
);
2201 SetEvent(data
.hQuitEvent
);
2202 ok( !WaitForSingleObject(thread
, 10000), "wait timed out\n" );
2203 CloseHandle(thread
);
2206 /* tests success case of a same-thread table-strong marshal, unmarshal, unmarshal */
2207 static void test_tablestrong_marshal_and_unmarshal_twice(void)
2210 IStream
*pStream
= NULL
;
2211 IUnknown
*pProxy1
= NULL
;
2212 IUnknown
*pProxy2
= NULL
;
2217 external_connections
= 0;
2219 hr
= CreateStreamOnHGlobal(NULL
, TRUE
, &pStream
);
2220 ok_ole_success(hr
, CreateStreamOnHGlobal
);
2221 tid
= start_host_object(pStream
, &IID_IClassFactory
, (IUnknown
*)&Test_ClassFactory
, MSHLFLAGS_TABLESTRONG
, &thread
);
2223 ok_more_than_one_lock();
2224 ok_non_zero_external_conn();
2226 IStream_Seek(pStream
, ullZero
, STREAM_SEEK_SET
, NULL
);
2227 hr
= CoUnmarshalInterface(pStream
, &IID_IClassFactory
, (void **)&pProxy1
);
2228 ok_ole_success(hr
, CoUnmarshalInterface
);
2230 ok_more_than_one_lock();
2232 IStream_Seek(pStream
, ullZero
, STREAM_SEEK_SET
, NULL
);
2233 hr
= CoUnmarshalInterface(pStream
, &IID_IClassFactory
, (void **)&pProxy2
);
2234 ok_ole_success(hr
, CoUnmarshalInterface
);
2236 ok_more_than_one_lock();
2238 if (pProxy1
) IUnknown_Release(pProxy1
);
2239 if (pProxy2
) IUnknown_Release(pProxy2
);
2241 /* this line is shows the difference between weak and strong table marshaling:
2242 * weak has cLocks == 0
2243 * strong has cLocks > 0 */
2244 ok_more_than_one_lock();
2246 /* release the remaining reference on the object by calling
2247 * CoReleaseMarshalData in the hosting thread */
2248 IStream_Seek(pStream
, ullZero
, STREAM_SEEK_SET
, NULL
);
2249 release_host_object(tid
, 0);
2250 IStream_Release(pStream
);
2253 ok_zero_external_conn();
2254 ok_last_release_closes(TRUE
);
2256 end_host_object(tid
, thread
);
2259 /* tests CoLockObjectExternal */
2260 static void test_lock_object_external(void)
2263 IStream
*pStream
= NULL
;
2266 external_connections
= 0;
2268 /* test the stub manager creation aspect of CoLockObjectExternal when the
2269 * object hasn't been marshaled yet */
2270 CoLockObjectExternal((IUnknown
*)&Test_ClassFactory
, TRUE
, TRUE
);
2272 ok_more_than_one_lock();
2273 ok_non_zero_external_conn();
2275 CoDisconnectObject((IUnknown
*)&Test_ClassFactory
, 0);
2278 ok_non_zero_external_conn();
2279 external_connections
= 0;
2281 /* test our empty stub manager being handled correctly in
2282 * CoMarshalInterface */
2283 CoLockObjectExternal((IUnknown
*)&Test_ClassFactory
, TRUE
, TRUE
);
2285 hr
= CreateStreamOnHGlobal(NULL
, TRUE
, &pStream
);
2286 ok_ole_success(hr
, CreateStreamOnHGlobal
);
2287 hr
= CoMarshalInterface(pStream
, &IID_IClassFactory
, (IUnknown
*)&Test_ClassFactory
, MSHCTX_INPROC
, NULL
, MSHLFLAGS_NORMAL
);
2288 ok_ole_success(hr
, CoMarshalInterface
);
2290 CoLockObjectExternal((IUnknown
*)&Test_ClassFactory
, TRUE
, TRUE
);
2292 ok_more_than_one_lock();
2293 ok_non_zero_external_conn();
2295 IStream_Seek(pStream
, ullZero
, STREAM_SEEK_SET
, NULL
);
2296 hr
= CoReleaseMarshalData(pStream
);
2297 ok_ole_success(hr
, CoReleaseMarshalData
);
2298 IStream_Seek(pStream
, ullZero
, STREAM_SEEK_SET
, NULL
);
2300 ok_more_than_one_lock();
2301 ok_non_zero_external_conn();
2302 ok_last_release_closes(TRUE
);
2304 CoLockObjectExternal((IUnknown
*)&Test_ClassFactory
, FALSE
, TRUE
);
2306 ok_more_than_one_lock();
2307 ok_non_zero_external_conn();
2308 ok_last_release_closes(TRUE
);
2310 CoLockObjectExternal((IUnknown
*)&Test_ClassFactory
, FALSE
, TRUE
);
2313 ok_zero_external_conn();
2314 ok_last_release_closes(TRUE
);
2316 /* test CoLockObjectExternal releases reference to object with
2317 * fLastUnlockReleases as TRUE and there are only strong references on
2319 CoLockObjectExternal((IUnknown
*)&Test_ClassFactory
, TRUE
, FALSE
);
2321 ok_more_than_one_lock();
2322 ok_non_zero_external_conn();
2324 CoLockObjectExternal((IUnknown
*)&Test_ClassFactory
, FALSE
, FALSE
);
2327 ok_zero_external_conn();
2328 ok_last_release_closes(FALSE
);
2330 /* test CoLockObjectExternal doesn't release the last reference to an
2331 * object with fLastUnlockReleases as TRUE and there is a weak reference
2333 hr
= CoMarshalInterface(pStream
, &IID_IClassFactory
, (IUnknown
*)&Test_ClassFactory
, MSHCTX_INPROC
, NULL
, MSHLFLAGS_TABLEWEAK
);
2334 ok_ole_success(hr
, CoMarshalInterface
);
2336 ok_more_than_one_lock();
2337 ok_zero_external_conn();
2339 CoLockObjectExternal((IUnknown
*)&Test_ClassFactory
, TRUE
, FALSE
);
2341 ok_more_than_one_lock();
2342 ok_non_zero_external_conn();
2344 CoLockObjectExternal((IUnknown
*)&Test_ClassFactory
, FALSE
, FALSE
);
2346 ok_more_than_one_lock();
2347 ok_zero_external_conn();
2348 ok_last_release_closes(FALSE
);
2350 CoDisconnectObject((IUnknown
*)&Test_ClassFactory
, 0);
2354 IStream_Release(pStream
);
2357 /* tests disconnecting stubs */
2358 static void test_disconnect_stub(void)
2361 IStream
*pStream
= NULL
;
2364 external_connections
= 0;
2366 hr
= CreateStreamOnHGlobal(NULL
, TRUE
, &pStream
);
2367 ok_ole_success(hr
, CreateStreamOnHGlobal
);
2368 hr
= CoMarshalInterface(pStream
, &IID_IClassFactory
, (IUnknown
*)&Test_ClassFactory
, MSHCTX_INPROC
, NULL
, MSHLFLAGS_NORMAL
);
2369 ok_ole_success(hr
, CoMarshalInterface
);
2371 ok_non_zero_external_conn();
2373 CoLockObjectExternal((IUnknown
*)&Test_ClassFactory
, TRUE
, TRUE
);
2375 ok_more_than_one_lock();
2376 ok_non_zero_external_conn();
2378 IStream_Seek(pStream
, ullZero
, STREAM_SEEK_SET
, NULL
);
2379 hr
= CoReleaseMarshalData(pStream
);
2380 ok_ole_success(hr
, CoReleaseMarshalData
);
2381 IStream_Release(pStream
);
2383 ok_more_than_one_lock();
2384 ok_non_zero_external_conn();
2386 CoDisconnectObject((IUnknown
*)&Test_ClassFactory
, 0);
2389 ok_non_zero_external_conn();
2391 hr
= CoDisconnectObject(NULL
, 0);
2392 ok( hr
== E_INVALIDARG
, "wrong status %x\n", hr
);
2395 /* tests failure case of a same-thread marshal and unmarshal twice */
2396 static void test_normal_marshal_and_unmarshal_twice(void)
2399 IStream
*pStream
= NULL
;
2400 IUnknown
*pProxy1
= NULL
;
2401 IUnknown
*pProxy2
= NULL
;
2404 external_connections
= 0;
2406 hr
= CreateStreamOnHGlobal(NULL
, TRUE
, &pStream
);
2407 ok_ole_success(hr
, CreateStreamOnHGlobal
);
2408 hr
= CoMarshalInterface(pStream
, &IID_IClassFactory
, (IUnknown
*)&Test_ClassFactory
, MSHCTX_INPROC
, NULL
, MSHLFLAGS_NORMAL
);
2409 ok_ole_success(hr
, CoMarshalInterface
);
2411 ok_more_than_one_lock();
2412 ok_non_zero_external_conn();
2414 IStream_Seek(pStream
, ullZero
, STREAM_SEEK_SET
, NULL
);
2415 hr
= CoUnmarshalInterface(pStream
, &IID_IClassFactory
, (void **)&pProxy1
);
2416 ok_ole_success(hr
, CoUnmarshalInterface
);
2418 ok_more_than_one_lock();
2419 ok_zero_external_conn();
2420 ok_last_release_closes(FALSE
);
2422 IStream_Seek(pStream
, ullZero
, STREAM_SEEK_SET
, NULL
);
2423 hr
= CoUnmarshalInterface(pStream
, &IID_IClassFactory
, (void **)&pProxy2
);
2424 ok(hr
== CO_E_OBJNOTCONNECTED
,
2425 "CoUnmarshalInterface should have failed with error CO_E_OBJNOTCONNECTED for double unmarshal, instead of 0x%08x\n", hr
);
2427 IStream_Release(pStream
);
2429 ok_more_than_one_lock();
2431 IUnknown_Release(pProxy1
);
2436 /* tests success case of marshaling and unmarshaling an HRESULT */
2437 static void test_hresult_marshaling(void)
2440 HRESULT hr_marshaled
= 0;
2441 IStream
*pStream
= NULL
;
2442 static const HRESULT E_DEADBEEF
= 0xdeadbeef;
2444 hr
= CreateStreamOnHGlobal(NULL
, TRUE
, &pStream
);
2445 ok_ole_success(hr
, CreateStreamOnHGlobal
);
2447 hr
= CoMarshalHresult(pStream
, E_DEADBEEF
);
2448 ok_ole_success(hr
, CoMarshalHresult
);
2450 IStream_Seek(pStream
, ullZero
, STREAM_SEEK_SET
, NULL
);
2451 hr
= IStream_Read(pStream
, &hr_marshaled
, sizeof(HRESULT
), NULL
);
2452 ok_ole_success(hr
, IStream_Read
);
2454 ok(hr_marshaled
== E_DEADBEEF
, "Didn't marshal HRESULT as expected: got value 0x%08x instead\n", hr_marshaled
);
2457 IStream_Seek(pStream
, ullZero
, STREAM_SEEK_SET
, NULL
);
2458 hr
= CoUnmarshalHresult(pStream
, &hr_marshaled
);
2459 ok_ole_success(hr
, CoUnmarshalHresult
);
2461 ok(hr_marshaled
== E_DEADBEEF
, "Didn't marshal HRESULT as expected: got value 0x%08x instead\n", hr_marshaled
);
2463 IStream_Release(pStream
);
2467 /* helper for test_proxy_used_in_wrong_thread */
2468 static DWORD CALLBACK
bad_thread_proc(LPVOID p
)
2470 IClassFactory
* cf
= p
;
2472 IUnknown
* proxy
= NULL
;
2474 hr
= IClassFactory_CreateInstance(cf
, NULL
, &IID_IUnknown
, (LPVOID
*)&proxy
);
2475 todo_wine
ok(hr
== CO_E_NOTINITIALIZED
, "Got hr %#x.\n", hr
);
2477 hr
= IClassFactory_QueryInterface(cf
, &IID_IMultiQI
, (LPVOID
*)&proxy
);
2478 todo_wine
ok(hr
== RPC_E_WRONG_THREAD
, "Got hr %#x.\n", hr
);
2480 IUnknown_Release(proxy
);
2482 hr
= IClassFactory_QueryInterface(cf
, &IID_IStream
, (LPVOID
*)&proxy
);
2483 todo_wine
ok(hr
== RPC_E_WRONG_THREAD
, "Got hr %#x.\n", hr
);
2485 IUnknown_Release(proxy
);
2487 CoInitializeEx(NULL
, COINIT_MULTITHREADED
);
2489 hr
= IClassFactory_CreateInstance(cf
, NULL
, &IID_IUnknown
, (LPVOID
*)&proxy
);
2490 if (proxy
) IUnknown_Release(proxy
);
2491 ok(hr
== RPC_E_WRONG_THREAD
,
2492 "COM should have failed with RPC_E_WRONG_THREAD on using proxy from wrong apartment, but instead returned 0x%08x\n",
2495 hr
= IClassFactory_QueryInterface(cf
, &IID_IStream
, (LPVOID
*)&proxy
);
2496 todo_wine
ok(hr
== RPC_E_WRONG_THREAD
, "Got hr %#x.\n", hr
);
2498 /* now be really bad and release the proxy from the wrong apartment */
2499 IClassFactory_Release(cf
);
2506 /* tests failure case of a using a proxy in the wrong apartment */
2507 static void test_proxy_used_in_wrong_thread(void)
2510 IStream
*pStream
= NULL
;
2511 IUnknown
*pProxy
= NULL
;
2518 hr
= CreateStreamOnHGlobal(NULL
, TRUE
, &pStream
);
2519 ok_ole_success(hr
, CreateStreamOnHGlobal
);
2520 tid
= start_host_object(pStream
, &IID_IClassFactory
, (IUnknown
*)&Test_ClassFactory
, MSHLFLAGS_NORMAL
, &host_thread
);
2522 ok_more_than_one_lock();
2524 IStream_Seek(pStream
, ullZero
, STREAM_SEEK_SET
, NULL
);
2525 hr
= CoUnmarshalInterface(pStream
, &IID_IClassFactory
, (void **)&pProxy
);
2526 ok_ole_success(hr
, CoUnmarshalInterface
);
2527 IStream_Release(pStream
);
2529 ok_more_than_one_lock();
2531 /* do a call that will fail, but result in IRemUnknown being used by the proxy */
2532 IUnknown_QueryInterface(pProxy
, &IID_IStream
, (LPVOID
*)&pStream
);
2534 /* create a thread that we can misbehave in */
2535 thread
= CreateThread(NULL
, 0, bad_thread_proc
, pProxy
, 0, &tid2
);
2537 ok( !WaitForSingleObject(thread
, 10000), "wait timed out\n" );
2538 CloseHandle(thread
);
2542 end_host_object(tid
, host_thread
);
2545 static HRESULT WINAPI
MessageFilter_QueryInterface(IMessageFilter
*iface
, REFIID riid
, void ** ppvObj
)
2547 if (ppvObj
== NULL
) return E_POINTER
;
2549 if (IsEqualGUID(riid
, &IID_IUnknown
) ||
2550 IsEqualGUID(riid
, &IID_IClassFactory
))
2553 IMessageFilter_AddRef(iface
);
2557 return E_NOINTERFACE
;
2560 static ULONG WINAPI
MessageFilter_AddRef(IMessageFilter
*iface
)
2562 return 2; /* non-heap object */
2565 static ULONG WINAPI
MessageFilter_Release(IMessageFilter
*iface
)
2567 return 1; /* non-heap object */
2570 static DWORD WINAPI
MessageFilter_HandleInComingCall(
2571 IMessageFilter
*iface
,
2573 HTASK threadIDCaller
,
2575 LPINTERFACEINFO lpInterfaceInfo
)
2577 static int callcount
= 0;
2579 if (winetest_debug
> 1) trace("HandleInComingCall()\n");
2583 ret
= SERVERCALL_REJECTED
;
2586 ret
= SERVERCALL_RETRYLATER
;
2589 ret
= SERVERCALL_ISHANDLED
;
2596 static DWORD WINAPI
MessageFilter_RetryRejectedCall(
2597 IMessageFilter
*iface
,
2598 HTASK threadIDCallee
,
2602 if (winetest_debug
> 1) trace("RetryRejectedCall()\n");
2606 static DWORD WINAPI
MessageFilter_MessagePending(
2607 IMessageFilter
*iface
,
2608 HTASK threadIDCallee
,
2610 DWORD dwPendingType
)
2612 if (winetest_debug
> 1) trace("MessagePending()\n");
2613 return PENDINGMSG_WAITNOPROCESS
;
2616 static const IMessageFilterVtbl MessageFilter_Vtbl
=
2618 MessageFilter_QueryInterface
,
2619 MessageFilter_AddRef
,
2620 MessageFilter_Release
,
2621 MessageFilter_HandleInComingCall
,
2622 MessageFilter_RetryRejectedCall
,
2623 MessageFilter_MessagePending
2626 static IMessageFilter MessageFilter
= { &MessageFilter_Vtbl
};
2628 static void test_message_filter(void)
2631 IClassFactory
*cf
= NULL
;
2633 IUnknown
*proxy
= NULL
;
2634 IMessageFilter
*prev_filter
= NULL
;
2637 struct host_object_data object_data
= { NULL
, &IID_IClassFactory
, (IUnknown
*)&Test_ClassFactory
,
2638 MSHLFLAGS_NORMAL
, &MessageFilter
};
2642 hr
= CreateStreamOnHGlobal(NULL
, TRUE
, &object_data
.stream
);
2643 ok_ole_success(hr
, CreateStreamOnHGlobal
);
2644 tid
= start_host_object2(&object_data
, &thread
);
2646 ok_more_than_one_lock();
2648 IStream_Seek(object_data
.stream
, ullZero
, STREAM_SEEK_SET
, NULL
);
2649 hr
= CoUnmarshalInterface(object_data
.stream
, &IID_IClassFactory
, (void **)&cf
);
2650 ok_ole_success(hr
, CoUnmarshalInterface
);
2651 IStream_Release(object_data
.stream
);
2653 ok_more_than_one_lock();
2655 hr
= IClassFactory_CreateInstance(cf
, NULL
, &IID_IUnknown
, (LPVOID
*)&proxy
);
2656 ok(hr
== RPC_E_CALL_REJECTED
, "Call should have returned RPC_E_CALL_REJECTED, but return 0x%08x instead\n", hr
);
2657 if (proxy
) IUnknown_Release(proxy
);
2660 hr
= CoRegisterMessageFilter(&MessageFilter
, &prev_filter
);
2661 ok_ole_success(hr
, CoRegisterMessageFilter
);
2663 hr
= IClassFactory_CreateInstance(cf
, NULL
, &IID_IUnknown
, (LPVOID
*)&proxy
);
2664 ok_ole_success(hr
, IClassFactory_CreateInstance
);
2666 IUnknown_Release(proxy
);
2668 IClassFactory_Release(cf
);
2672 end_host_object(tid
, thread
);
2674 hr
= CoRegisterMessageFilter(prev_filter
, NULL
);
2675 ok_ole_success(hr
, CoRegisterMessageFilter
);
2678 /* test failure case of trying to unmarshal from bad stream */
2679 static void test_bad_marshal_stream(void)
2682 IStream
*pStream
= NULL
;
2684 hr
= CreateStreamOnHGlobal(NULL
, TRUE
, &pStream
);
2685 ok_ole_success(hr
, CreateStreamOnHGlobal
);
2686 hr
= CoMarshalInterface(pStream
, &IID_IClassFactory
, (IUnknown
*)&Test_ClassFactory
, MSHCTX_INPROC
, NULL
, MSHLFLAGS_NORMAL
);
2687 ok_ole_success(hr
, CoMarshalInterface
);
2689 ok_more_than_one_lock();
2691 /* try to read beyond end of stream */
2692 hr
= CoReleaseMarshalData(pStream
);
2693 ok(hr
== STG_E_READFAULT
, "Should have failed with STG_E_READFAULT, but returned 0x%08x instead\n", hr
);
2695 /* now release for real */
2696 IStream_Seek(pStream
, ullZero
, STREAM_SEEK_SET
, NULL
);
2697 hr
= CoReleaseMarshalData(pStream
);
2698 ok_ole_success(hr
, CoReleaseMarshalData
);
2700 IStream_Release(pStream
);
2703 /* tests that proxies implement certain interfaces */
2704 static void test_proxy_interfaces(void)
2707 IStream
*pStream
= NULL
;
2708 IUnknown
*pProxy
= NULL
;
2709 IUnknown
*pOtherUnknown
= NULL
;
2715 hr
= CreateStreamOnHGlobal(NULL
, TRUE
, &pStream
);
2716 ok_ole_success(hr
, CreateStreamOnHGlobal
);
2717 tid
= start_host_object(pStream
, &IID_IClassFactory
, (IUnknown
*)&Test_ClassFactory
, MSHLFLAGS_NORMAL
, &thread
);
2719 ok_more_than_one_lock();
2721 IStream_Seek(pStream
, ullZero
, STREAM_SEEK_SET
, NULL
);
2722 hr
= CoUnmarshalInterface(pStream
, &IID_IUnknown
, (void **)&pProxy
);
2723 ok_ole_success(hr
, CoUnmarshalInterface
);
2724 IStream_Release(pStream
);
2726 ok_more_than_one_lock();
2728 hr
= IUnknown_QueryInterface(pProxy
, &IID_IUnknown
, (LPVOID
*)&pOtherUnknown
);
2729 ok_ole_success(hr
, IUnknown_QueryInterface IID_IUnknown
);
2730 if (hr
== S_OK
) IUnknown_Release(pOtherUnknown
);
2732 hr
= IUnknown_QueryInterface(pProxy
, &IID_IClientSecurity
, (LPVOID
*)&pOtherUnknown
);
2733 ok_ole_success(hr
, IUnknown_QueryInterface IID_IClientSecurity
);
2734 if (hr
== S_OK
) IUnknown_Release(pOtherUnknown
);
2736 hr
= IUnknown_QueryInterface(pProxy
, &IID_IMultiQI
, (LPVOID
*)&pOtherUnknown
);
2737 ok_ole_success(hr
, IUnknown_QueryInterface IID_IMultiQI
);
2738 if (hr
== S_OK
) IUnknown_Release(pOtherUnknown
);
2740 hr
= IUnknown_QueryInterface(pProxy
, &IID_IMarshal
, (LPVOID
*)&pOtherUnknown
);
2741 ok_ole_success(hr
, IUnknown_QueryInterface IID_IMarshal
);
2742 if (hr
== S_OK
) IUnknown_Release(pOtherUnknown
);
2744 /* IMarshal2 is also supported on NT-based systems, but is pretty much
2745 * useless as it has no more methods over IMarshal that it inherits from. */
2747 IUnknown_Release(pProxy
);
2751 end_host_object(tid
, thread
);
2756 IUnknown IUnknown_iface
;
2760 static inline HeapUnknown
*impl_from_IUnknown(IUnknown
*iface
)
2762 return CONTAINING_RECORD(iface
, HeapUnknown
, IUnknown_iface
);
2765 static HRESULT WINAPI
HeapUnknown_QueryInterface(IUnknown
*iface
, REFIID riid
, void **ppv
)
2767 if (IsEqualIID(riid
, &IID_IUnknown
))
2769 IUnknown_AddRef(iface
);
2774 return E_NOINTERFACE
;
2777 static ULONG WINAPI
HeapUnknown_AddRef(IUnknown
*iface
)
2779 HeapUnknown
*This
= impl_from_IUnknown(iface
);
2780 return InterlockedIncrement((LONG
*)&This
->refs
);
2783 static ULONG WINAPI
HeapUnknown_Release(IUnknown
*iface
)
2785 HeapUnknown
*This
= impl_from_IUnknown(iface
);
2786 ULONG refs
= InterlockedDecrement((LONG
*)&This
->refs
);
2787 if (!refs
) HeapFree(GetProcessHeap(), 0, This
);
2791 static const IUnknownVtbl HeapUnknown_Vtbl
=
2793 HeapUnknown_QueryInterface
,
2798 static void test_proxybuffer(REFIID riid
)
2801 IPSFactoryBuffer
*psfb
;
2802 IRpcProxyBuffer
*proxy
;
2806 HeapUnknown
*pUnkOuter
= HeapAlloc(GetProcessHeap(), 0, sizeof(*pUnkOuter
));
2808 pUnkOuter
->IUnknown_iface
.lpVtbl
= &HeapUnknown_Vtbl
;
2809 pUnkOuter
->refs
= 1;
2811 hr
= CoGetPSClsid(riid
, &clsid
);
2812 ok_ole_success(hr
, CoGetPSClsid
);
2814 hr
= CoGetClassObject(&clsid
, CLSCTX_INPROC_SERVER
, NULL
, &IID_IPSFactoryBuffer
, (LPVOID
*)&psfb
);
2815 ok_ole_success(hr
, CoGetClassObject
);
2817 hr
= IPSFactoryBuffer_CreateProxy(psfb
, &pUnkOuter
->IUnknown_iface
, riid
, &proxy
, &lpvtbl
);
2818 ok_ole_success(hr
, IPSFactoryBuffer_CreateProxy
);
2819 ok(lpvtbl
!= NULL
, "IPSFactoryBuffer_CreateProxy succeeded, but returned a NULL vtable!\n");
2821 /* release our reference to the outer unknown object - the PS factory
2822 * buffer will have AddRef's it in the CreateProxy call */
2823 refs
= IUnknown_Release(&pUnkOuter
->IUnknown_iface
);
2824 ok(refs
== 1, "Ref count of outer unknown should have been 1 instead of %d\n", refs
);
2826 /* Not checking return, unreliable on native. Maybe it leaks references? */
2827 IPSFactoryBuffer_Release(psfb
);
2829 refs
= IUnknown_Release((IUnknown
*)lpvtbl
);
2830 ok(refs
== 0, "Ref-count leak of %d on IRpcProxyBuffer\n", refs
);
2832 refs
= IRpcProxyBuffer_Release(proxy
);
2833 ok(refs
== 0, "Ref-count leak of %d on IRpcProxyBuffer\n", refs
);
2836 static void test_stubbuffer(REFIID riid
)
2839 IPSFactoryBuffer
*psfb
;
2840 IRpcStubBuffer
*stub
;
2846 hr
= CoGetPSClsid(riid
, &clsid
);
2847 ok_ole_success(hr
, CoGetPSClsid
);
2849 hr
= CoGetClassObject(&clsid
, CLSCTX_INPROC_SERVER
, NULL
, &IID_IPSFactoryBuffer
, (LPVOID
*)&psfb
);
2850 ok_ole_success(hr
, CoGetClassObject
);
2852 hr
= IPSFactoryBuffer_CreateStub(psfb
, riid
, (IUnknown
*)&Test_ClassFactory
, &stub
);
2853 ok_ole_success(hr
, IPSFactoryBuffer_CreateStub
);
2855 /* Not checking return, unreliable on native. Maybe it leaks references? */
2856 IPSFactoryBuffer_Release(psfb
);
2858 ok_more_than_one_lock();
2860 IRpcStubBuffer_Disconnect(stub
);
2864 refs
= IRpcStubBuffer_Release(stub
);
2865 ok(refs
== 0, "Ref-count leak of %d on IRpcProxyBuffer\n", refs
);
2868 static HWND hwnd_app
;
2870 static HRESULT WINAPI
TestRE_IClassFactory_CreateInstance(
2871 LPCLASSFACTORY iface
,
2872 LPUNKNOWN pUnkOuter
,
2877 if (IsEqualIID(riid
, &IID_IWineTest
))
2879 BOOL ret
= SendMessageTimeoutA(hwnd_app
, WM_NULL
, 0, 0, SMTO_BLOCK
, 5000, &res
);
2880 ok(ret
, "Timed out sending a message to originating window during RPC call\n");
2886 static const IClassFactoryVtbl TestREClassFactory_Vtbl
=
2888 Test_IClassFactory_QueryInterface
,
2889 Test_IClassFactory_AddRef
,
2890 Test_IClassFactory_Release
,
2891 TestRE_IClassFactory_CreateInstance
,
2892 Test_IClassFactory_LockServer
2895 static IClassFactory TestRE_ClassFactory
= { &TestREClassFactory_Vtbl
};
2897 static LRESULT CALLBACK
window_proc(HWND hwnd
, UINT msg
, WPARAM wparam
, LPARAM lparam
)
2904 IStream
*pStream
= NULL
;
2905 IClassFactory
*proxy
= NULL
;
2912 hr
= CreateStreamOnHGlobal(NULL
, TRUE
, &pStream
);
2913 ok_ole_success(hr
, CreateStreamOnHGlobal
);
2914 tid
= start_host_object(pStream
, &IID_IClassFactory
, (IUnknown
*)&TestRE_ClassFactory
, MSHLFLAGS_NORMAL
, &thread
);
2916 ok_more_than_one_lock();
2918 IStream_Seek(pStream
, ullZero
, STREAM_SEEK_SET
, NULL
);
2919 hr
= CoUnmarshalInterface(pStream
, &IID_IClassFactory
, (void **)&proxy
);
2920 ok_ole_success(hr
, CoReleaseMarshalData
);
2921 IStream_Release(pStream
);
2923 ok_more_than_one_lock();
2925 /* note the use of the magic IID_IWineTest value to tell remote thread
2926 * to try to send a message back to us */
2927 hr
= IClassFactory_CreateInstance(proxy
, NULL
, &IID_IWineTest
, (void **)&object
);
2928 ok(hr
== S_FALSE
, "expected S_FALSE, got %d\n", hr
);
2930 IClassFactory_Release(proxy
);
2934 end_host_object(tid
, thread
);
2936 PostMessageA(hwnd
, WM_QUIT
, 0, 0);
2943 IStream
*pStream
= NULL
;
2944 IClassFactory
*proxy
= NULL
;
2951 hr
= CreateStreamOnHGlobal(NULL
, TRUE
, &pStream
);
2952 ok_ole_success(hr
, CreateStreamOnHGlobal
);
2953 tid
= start_host_object(pStream
, &IID_IClassFactory
, (IUnknown
*)&TestRE_ClassFactory
, MSHLFLAGS_NORMAL
, &thread
);
2955 ok_more_than_one_lock();
2957 IStream_Seek(pStream
, ullZero
, STREAM_SEEK_SET
, NULL
);
2958 hr
= CoUnmarshalInterface(pStream
, &IID_IClassFactory
, (void **)&proxy
);
2959 ok_ole_success(hr
, CoReleaseMarshalData
);
2960 IStream_Release(pStream
);
2962 ok_more_than_one_lock();
2964 /* post quit message before a doing a COM call to show that a pending
2965 * WM_QUIT message doesn't stop the call from succeeding */
2966 PostMessageA(hwnd
, WM_QUIT
, 0, 0);
2967 hr
= IClassFactory_CreateInstance(proxy
, NULL
, &IID_IUnknown
, (void **)&object
);
2968 ok(hr
== S_FALSE
, "IClassFactory_CreateInstance returned 0x%08x, expected S_FALSE\n", hr
);
2970 IClassFactory_Release(proxy
);
2974 end_host_object(tid
, thread
);
2981 IStream
*pStream
= NULL
;
2982 IClassFactory
*proxy
= NULL
;
2987 hr
= CreateStreamOnHGlobal(NULL
, TRUE
, &pStream
);
2988 ok_ole_success(hr
, CreateStreamOnHGlobal
);
2989 tid
= start_host_object(pStream
, &IID_IClassFactory
, (IUnknown
*)&Test_ClassFactory
, MSHLFLAGS_NORMAL
, &thread
);
2991 IStream_Seek(pStream
, ullZero
, STREAM_SEEK_SET
, NULL
);
2992 hr
= CoUnmarshalInterface(pStream
, &IID_IClassFactory
, (void **)&proxy
);
2993 ok_ole_success(hr
, CoReleaseMarshalData
);
2994 IStream_Release(pStream
);
2996 /* shows that COM calls executed during the processing of sent
2997 * messages should fail */
2998 hr
= IClassFactory_CreateInstance(proxy
, NULL
, &IID_IUnknown
, (void **)&object
);
2999 ok(hr
== RPC_E_CANTCALLOUT_ININPUTSYNCCALL
,
3000 "COM call during processing of sent message should return RPC_E_CANTCALLOUT_ININPUTSYNCCALL instead of 0x%08x\n", hr
);
3002 IClassFactory_Release(proxy
);
3004 end_host_object(tid
, thread
);
3011 return DefWindowProcA(hwnd
, msg
, wparam
, lparam
);
3015 static void register_test_window(void)
3019 memset(&wndclass
, 0, sizeof(wndclass
));
3020 wndclass
.lpfnWndProc
= window_proc
;
3021 wndclass
.lpszClassName
= "WineCOMTest";
3022 RegisterClassA(&wndclass
);
3025 static void test_message_reentrancy(void)
3029 hwnd_app
= CreateWindowA("WineCOMTest", NULL
, 0, CW_USEDEFAULT
, CW_USEDEFAULT
, CW_USEDEFAULT
, CW_USEDEFAULT
, NULL
, NULL
, NULL
, 0);
3030 ok(hwnd_app
!= NULL
, "Window creation failed\n");
3032 /* start message re-entrancy test */
3033 PostMessageA(hwnd_app
, WM_USER
, 0, 0);
3035 while (GetMessageA(&msg
, NULL
, 0, 0))
3037 TranslateMessage(&msg
);
3038 DispatchMessageA(&msg
);
3040 DestroyWindow(hwnd_app
);
3043 static HRESULT WINAPI
TestMsg_IClassFactory_CreateInstance(
3044 LPCLASSFACTORY iface
,
3045 LPUNKNOWN pUnkOuter
,
3050 SendMessageA(hwnd_app
, WM_USER
+2, 0, 0);
3054 static IClassFactoryVtbl TestMsgClassFactory_Vtbl
=
3056 Test_IClassFactory_QueryInterface
,
3057 Test_IClassFactory_AddRef
,
3058 Test_IClassFactory_Release
,
3059 TestMsg_IClassFactory_CreateInstance
,
3060 Test_IClassFactory_LockServer
3063 static IClassFactory TestMsg_ClassFactory
= { &TestMsgClassFactory_Vtbl
};
3065 static void test_call_from_message(void)
3070 IClassFactory
*proxy
;
3075 hwnd_app
= CreateWindowA("WineCOMTest", NULL
, 0, CW_USEDEFAULT
, CW_USEDEFAULT
, CW_USEDEFAULT
, CW_USEDEFAULT
, NULL
, NULL
, NULL
, 0);
3076 ok(hwnd_app
!= NULL
, "Window creation failed\n");
3078 hr
= CreateStreamOnHGlobal(NULL
, TRUE
, &pStream
);
3079 ok_ole_success(hr
, CreateStreamOnHGlobal
);
3080 tid
= start_host_object(pStream
, &IID_IClassFactory
, (IUnknown
*)&TestMsg_ClassFactory
, MSHLFLAGS_NORMAL
, &thread
);
3082 ok_more_than_one_lock();
3084 IStream_Seek(pStream
, ullZero
, STREAM_SEEK_SET
, NULL
);
3085 hr
= CoUnmarshalInterface(pStream
, &IID_IClassFactory
, (void **)&proxy
);
3086 ok_ole_success(hr
, CoReleaseMarshalData
);
3087 IStream_Release(pStream
);
3089 ok_more_than_one_lock();
3091 /* start message re-entrancy test */
3092 hr
= IClassFactory_CreateInstance(proxy
, NULL
, &IID_IUnknown
, (void **)&object
);
3093 ok_ole_success(hr
, IClassFactory_CreateInstance
);
3095 IClassFactory_Release(proxy
);
3099 end_host_object(tid
, thread
);
3101 while (GetMessageA(&msg
, NULL
, 0, 0))
3103 TranslateMessage(&msg
);
3104 DispatchMessageA(&msg
);
3106 DestroyWindow(hwnd_app
);
3109 static void test_WM_QUIT_handling(void)
3113 hwnd_app
= CreateWindowA("WineCOMTest", NULL
, 0, CW_USEDEFAULT
, CW_USEDEFAULT
, CW_USEDEFAULT
, CW_USEDEFAULT
, NULL
, NULL
, NULL
, 0);
3114 ok(hwnd_app
!= NULL
, "Window creation failed\n");
3116 /* start WM_QUIT handling test */
3117 PostMessageA(hwnd_app
, WM_USER
+1, 0, 0);
3119 while (GetMessageA(&msg
, NULL
, 0, 0))
3121 TranslateMessage(&msg
);
3122 DispatchMessageA(&msg
);
3126 static SIZE_T
round_global_size(SIZE_T size
)
3128 static SIZE_T global_size_alignment
= -1;
3129 if (global_size_alignment
== -1)
3131 void *p
= GlobalAlloc(GMEM_FIXED
, 1);
3132 global_size_alignment
= GlobalSize(p
);
3136 return ((size
+ global_size_alignment
- 1) & ~(global_size_alignment
- 1));
3139 static void test_freethreadedmarshaldata(IStream
*pStream
, MSHCTX mshctx
, void *ptr
, DWORD mshlflags
)
3146 hr
= GetHGlobalFromStream(pStream
, &hglobal
);
3147 ok_ole_success(hr
, GetHGlobalFromStream
);
3149 size
= GlobalSize(hglobal
);
3151 marshal_data
= GlobalLock(hglobal
);
3153 if (mshctx
== MSHCTX_INPROC
)
3155 DWORD expected_size
= round_global_size(3*sizeof(DWORD
) + sizeof(GUID
));
3156 ok(size
== expected_size
, "expected size %u, got %u\n", expected_size
, size
);
3158 ok(*(DWORD
*)marshal_data
== mshlflags
, "expected 0x%x, but got 0x%x for mshctx\n", mshlflags
, *(DWORD
*)marshal_data
);
3159 marshal_data
+= sizeof(DWORD
);
3160 ok(*(void **)marshal_data
== ptr
, "expected %p, but got %p for mshctx\n", ptr
, *(void **)marshal_data
);
3161 marshal_data
+= sizeof(void *);
3162 if (sizeof(void*) == 4 && size
>= 3*sizeof(DWORD
))
3164 ok(*(DWORD
*)marshal_data
== 0, "expected 0x0, but got 0x%x\n", *(DWORD
*)marshal_data
);
3165 marshal_data
+= sizeof(DWORD
);
3167 if (size
>= 3*sizeof(DWORD
) + sizeof(GUID
) && winetest_debug
> 1)
3169 trace("got guid data: %s\n", wine_dbgstr_guid((GUID
*)marshal_data
));
3174 ok(size
> sizeof(DWORD
), "size should have been > sizeof(DWORD), not %d\n", size
);
3175 ok(*(DWORD
*)marshal_data
== 0x574f454d /* MEOW */,
3176 "marshal data should be filled by standard marshal and start with MEOW signature\n");
3179 GlobalUnlock(hglobal
);
3182 static void test_freethreadedmarshaler(void)
3185 IUnknown
*pFTUnknown
;
3186 IMarshal
*pFTMarshal
;
3189 static const LARGE_INTEGER llZero
;
3193 hr
= CoCreateFreeThreadedMarshaler(NULL
, &pFTUnknown
);
3194 ok_ole_success(hr
, CoCreateFreeThreadedMarshaler
);
3195 hr
= IUnknown_QueryInterface(pFTUnknown
, &IID_IMarshal
, (void **)&pFTMarshal
);
3196 ok_ole_success(hr
, IUnknown_QueryInterface
);
3197 IUnknown_Release(pFTUnknown
);
3199 hr
= CreateStreamOnHGlobal(NULL
, TRUE
, &pStream
);
3200 ok_ole_success(hr
, CreateStreamOnHGlobal
);
3202 /* inproc normal marshaling */
3204 hr
= IMarshal_GetUnmarshalClass(pFTMarshal
, &IID_IClassFactory
,
3205 &Test_ClassFactory
, MSHCTX_INPROC
, NULL
, MSHLFLAGS_NORMAL
, &clsid
);
3206 ok_ole_success(hr
, IMarshal_GetUnmarshalClass
);
3207 ok(IsEqualIID(&clsid
, &CLSID_InProcFreeMarshaler
), "clsid = %s\n",
3208 wine_dbgstr_guid(&clsid
));
3210 hr
= IMarshal_MarshalInterface(pFTMarshal
, pStream
, &IID_IClassFactory
,
3211 &Test_ClassFactory
, MSHCTX_INPROC
, NULL
, MSHLFLAGS_NORMAL
);
3212 ok_ole_success(hr
, IMarshal_MarshalInterface
);
3214 ok_more_than_one_lock();
3216 test_freethreadedmarshaldata(pStream
, MSHCTX_INPROC
, &Test_ClassFactory
, MSHLFLAGS_NORMAL
);
3218 IStream_Seek(pStream
, llZero
, STREAM_SEEK_SET
, NULL
);
3219 hr
= IMarshal_UnmarshalInterface(pFTMarshal
, pStream
, &IID_IUnknown
, (void **)&pProxy
);
3220 ok_ole_success(hr
, IMarshal_UnmarshalInterface
);
3222 IUnknown_Release(pProxy
);
3226 /* inproc table-strong marshaling */
3228 IStream_Seek(pStream
, llZero
, STREAM_SEEK_SET
, NULL
);
3229 hr
= IMarshal_MarshalInterface(pFTMarshal
, pStream
, &IID_IClassFactory
,
3230 (IUnknown
*)&Test_ClassFactory
, MSHCTX_INPROC
, (void *)0xdeadbeef,
3231 MSHLFLAGS_TABLESTRONG
);
3232 ok_ole_success(hr
, IMarshal_MarshalInterface
);
3234 ok_more_than_one_lock();
3236 test_freethreadedmarshaldata(pStream
, MSHCTX_INPROC
, &Test_ClassFactory
, MSHLFLAGS_TABLESTRONG
);
3238 IStream_Seek(pStream
, llZero
, STREAM_SEEK_SET
, NULL
);
3239 hr
= IMarshal_UnmarshalInterface(pFTMarshal
, pStream
, &IID_IUnknown
, (void **)&pProxy
);
3240 ok_ole_success(hr
, IMarshal_UnmarshalInterface
);
3242 IUnknown_Release(pProxy
);
3244 ok_more_than_one_lock();
3246 IStream_Seek(pStream
, llZero
, STREAM_SEEK_SET
, NULL
);
3247 hr
= IMarshal_ReleaseMarshalData(pFTMarshal
, pStream
);
3248 ok_ole_success(hr
, IMarshal_ReleaseMarshalData
);
3252 /* inproc table-weak marshaling */
3254 IStream_Seek(pStream
, llZero
, STREAM_SEEK_SET
, NULL
);
3255 hr
= IMarshal_MarshalInterface(pFTMarshal
, pStream
, &IID_IClassFactory
,
3256 (IUnknown
*)&Test_ClassFactory
, MSHCTX_INPROC
, (void *)0xdeadbeef,
3257 MSHLFLAGS_TABLEWEAK
);
3258 ok_ole_success(hr
, IMarshal_MarshalInterface
);
3262 test_freethreadedmarshaldata(pStream
, MSHCTX_INPROC
, &Test_ClassFactory
, MSHLFLAGS_TABLEWEAK
);
3264 IStream_Seek(pStream
, llZero
, STREAM_SEEK_SET
, NULL
);
3265 hr
= IMarshal_UnmarshalInterface(pFTMarshal
, pStream
, &IID_IUnknown
, (void **)&pProxy
);
3266 ok_ole_success(hr
, IMarshal_UnmarshalInterface
);
3268 ok_more_than_one_lock();
3270 IUnknown_Release(pProxy
);
3274 /* inproc normal marshaling (for extraordinary cases) */
3276 IStream_Seek(pStream
, llZero
, STREAM_SEEK_SET
, NULL
);
3277 hr
= IMarshal_MarshalInterface(pFTMarshal
, pStream
, &IID_IClassFactory
,
3278 &Test_ClassFactory
, MSHCTX_INPROC
, NULL
, MSHLFLAGS_NORMAL
);
3279 ok_ole_success(hr
, IMarshal_MarshalInterface
);
3281 ok_more_than_one_lock();
3283 /* this call shows that DisconnectObject does nothing */
3284 hr
= IMarshal_DisconnectObject(pFTMarshal
, 0);
3285 ok_ole_success(hr
, IMarshal_DisconnectObject
);
3287 ok_more_than_one_lock();
3289 IStream_Seek(pStream
, llZero
, STREAM_SEEK_SET
, NULL
);
3290 hr
= IMarshal_ReleaseMarshalData(pFTMarshal
, pStream
);
3291 ok_ole_success(hr
, IMarshal_ReleaseMarshalData
);
3295 /* doesn't enforce marshaling rules here and allows us to unmarshal the
3296 * interface, even though it was freed above */
3297 IStream_Seek(pStream
, llZero
, STREAM_SEEK_SET
, NULL
);
3298 hr
= IMarshal_UnmarshalInterface(pFTMarshal
, pStream
, &IID_IUnknown
, (void **)&pProxy
);
3299 ok_ole_success(hr
, IMarshal_UnmarshalInterface
);
3303 /* local normal marshaling */
3305 hr
= IMarshal_GetUnmarshalClass(pFTMarshal
, &IID_IClassFactory
,
3306 &Test_ClassFactory
, MSHCTX_LOCAL
, NULL
, MSHLFLAGS_NORMAL
, &clsid
);
3307 ok_ole_success(hr
, IMarshal_GetUnmarshalClass
);
3308 ok(IsEqualGUID(&clsid
, &CLSID_StdMarshal
) || IsEqualGUID(&clsid
, &CLSID_ft_unmarshaler_1809
) /* Win10 1809 */,
3309 "clsid = %s\n", wine_dbgstr_guid(&clsid
));
3311 IStream_Seek(pStream
, llZero
, STREAM_SEEK_SET
, NULL
);
3312 hr
= IMarshal_MarshalInterface(pFTMarshal
, pStream
, &IID_IClassFactory
, &Test_ClassFactory
, MSHCTX_LOCAL
, NULL
, MSHLFLAGS_NORMAL
);
3313 ok_ole_success(hr
, IMarshal_MarshalInterface
);
3315 ok_more_than_one_lock();
3317 test_freethreadedmarshaldata(pStream
, MSHCTX_LOCAL
, &Test_ClassFactory
, MSHLFLAGS_NORMAL
);
3319 IStream_Seek(pStream
, llZero
, STREAM_SEEK_SET
, NULL
);
3320 hr
= CoReleaseMarshalData(pStream
);
3321 ok_ole_success(hr
, CoReleaseMarshalData
);
3325 IStream_Release(pStream
);
3326 IMarshal_Release(pFTMarshal
);
3329 static HRESULT
reg_unreg_wine_test_class(BOOL Register
)
3335 DWORD dwDisposition
;
3338 hr
= StringFromCLSID(&CLSID_WineTest
, &pszClsid
);
3339 ok_ole_success(hr
, "StringFromCLSID");
3340 strcpy(buffer
, "CLSID\\");
3341 WideCharToMultiByte(CP_ACP
, 0, pszClsid
, -1, buffer
+ strlen(buffer
), sizeof(buffer
) - strlen(buffer
), NULL
, NULL
);
3342 CoTaskMemFree(pszClsid
);
3343 strcat(buffer
, "\\InprocHandler32");
3346 error
= RegCreateKeyExA(HKEY_CLASSES_ROOT
, buffer
, 0, NULL
, 0, KEY_SET_VALUE
, NULL
, &hkey
, &dwDisposition
);
3347 if (error
== ERROR_ACCESS_DENIED
)
3349 skip("Not authorized to modify the Classes key\n");
3352 ok(error
== ERROR_SUCCESS
, "RegCreateKeyEx failed with error %d\n", error
);
3353 if (error
!= ERROR_SUCCESS
) hr
= E_FAIL
;
3354 error
= RegSetValueExA(hkey
, NULL
, 0, REG_SZ
, (const unsigned char *)"\"ole32.dll\"", strlen("\"ole32.dll\"") + 1);
3355 ok(error
== ERROR_SUCCESS
, "RegSetValueEx failed with error %d\n", error
);
3356 if (error
!= ERROR_SUCCESS
) hr
= E_FAIL
;
3361 RegDeleteKeyA(HKEY_CLASSES_ROOT
, buffer
);
3362 *strrchr(buffer
, '\\') = '\0';
3363 RegDeleteKeyA(HKEY_CLASSES_ROOT
, buffer
);
3368 static void test_inproc_handler(void)
3374 if (FAILED(reg_unreg_wine_test_class(TRUE
)))
3377 hr
= CoCreateInstance(&CLSID_WineTest
, NULL
, CLSCTX_INPROC_HANDLER
, &IID_IUnknown
, (void **)&pObject
);
3378 ok_ole_success(hr
, "CoCreateInstance");
3382 hr
= IUnknown_QueryInterface(pObject
, &IID_IWineTest
, (void **)&pObject2
);
3383 ok(hr
== E_NOINTERFACE
, "IUnknown_QueryInterface on handler for invalid interface returned 0x%08x instead of E_NOINTERFACE\n", hr
);
3385 /* it's a handler as it supports IOleObject */
3386 hr
= IUnknown_QueryInterface(pObject
, &IID_IOleObject
, (void **)&pObject2
);
3387 ok_ole_success(hr
, "IUnknown_QueryInterface(&IID_IOleObject)");
3388 IUnknown_Release(pObject2
);
3390 IUnknown_Release(pObject
);
3393 reg_unreg_wine_test_class(FALSE
);
3396 static HRESULT WINAPI
Test_SMI_QueryInterface(
3397 IStdMarshalInfo
*iface
,
3401 if (ppvObj
== NULL
) return E_POINTER
;
3403 if (IsEqualGUID(riid
, &IID_IUnknown
) ||
3404 IsEqualGUID(riid
, &IID_IStdMarshalInfo
))
3407 IStdMarshalInfo_AddRef(iface
);
3411 return E_NOINTERFACE
;
3414 static ULONG WINAPI
Test_SMI_AddRef(IStdMarshalInfo
*iface
)
3417 return 2; /* non-heap-based object */
3420 static ULONG WINAPI
Test_SMI_Release(IStdMarshalInfo
*iface
)
3423 return 1; /* non-heap-based object */
3426 static HRESULT WINAPI
Test_SMI_GetClassForHandler(
3427 IStdMarshalInfo
*iface
,
3428 DWORD dwDestContext
,
3429 void *pvDestContext
,
3432 *pClsid
= CLSID_WineTest
;
3436 static const IStdMarshalInfoVtbl Test_SMI_Vtbl
=
3438 Test_SMI_QueryInterface
,
3441 Test_SMI_GetClassForHandler
3444 static IStdMarshalInfo Test_SMI
= {&Test_SMI_Vtbl
};
3446 static void test_handler_marshaling(void)
3449 IStream
*pStream
= NULL
;
3450 IUnknown
*pProxy
= NULL
;
3454 static const LARGE_INTEGER ullZero
;
3456 if (FAILED(reg_unreg_wine_test_class(TRUE
)))
3460 hr
= CreateStreamOnHGlobal(NULL
, TRUE
, &pStream
);
3461 ok_ole_success(hr
, "CreateStreamOnHGlobal");
3462 tid
= start_host_object(pStream
, &IID_IUnknown
, (IUnknown
*)&Test_SMI
, MSHLFLAGS_NORMAL
, &thread
);
3464 ok_more_than_one_lock();
3466 IStream_Seek(pStream
, ullZero
, STREAM_SEEK_SET
, NULL
);
3467 hr
= CoUnmarshalInterface(pStream
, &IID_IUnknown
, (void **)&pProxy
);
3468 ok_ole_success(hr
, "CoUnmarshalInterface");
3469 IStream_Release(pStream
);
3473 ok_more_than_one_lock();
3475 hr
= IUnknown_QueryInterface(pProxy
, &IID_IWineTest
, (void **)&pObject
);
3476 ok(hr
== E_NOINTERFACE
, "IUnknown_QueryInterface with unknown IID should have returned E_NOINTERFACE instead of 0x%08x\n", hr
);
3478 /* it's a handler as it supports IOleObject */
3479 hr
= IUnknown_QueryInterface(pProxy
, &IID_IOleObject
, (void **)&pObject
);
3481 ok_ole_success(hr
, "IUnknown_QueryInterface(&IID_IOleObject)");
3482 if (SUCCEEDED(hr
)) IUnknown_Release(pObject
);
3484 IUnknown_Release(pProxy
);
3489 end_host_object(tid
, thread
);
3490 reg_unreg_wine_test_class(FALSE
);
3492 /* FIXME: test IPersist interface has the same effect as IStdMarshalInfo */
3496 static void test_client_security(void)
3499 IStream
*pStream
= NULL
;
3500 IClassFactory
*pProxy
= NULL
;
3501 IUnknown
*pProxy2
= NULL
;
3502 IUnknown
*pUnknown1
= NULL
;
3503 IUnknown
*pUnknown2
= NULL
;
3504 IClientSecurity
*pCliSec
= NULL
;
3508 static const LARGE_INTEGER ullZero
;
3511 OLECHAR
*pServerPrincName
;
3515 DWORD dwCapabilities
;
3520 hr
= CreateStreamOnHGlobal(NULL
, TRUE
, &pStream
);
3521 ok_ole_success(hr
, "CreateStreamOnHGlobal");
3522 tid
= start_host_object(pStream
, &IID_IClassFactory
, (IUnknown
*)&Test_ClassFactory
, MSHLFLAGS_NORMAL
, &thread
);
3524 IStream_Seek(pStream
, ullZero
, STREAM_SEEK_SET
, NULL
);
3525 hr
= CoUnmarshalInterface(pStream
, &IID_IClassFactory
, (void **)&pProxy
);
3526 ok_ole_success(hr
, "CoUnmarshalInterface");
3527 IStream_Release(pStream
);
3529 hr
= IClassFactory_QueryInterface(pProxy
, &IID_IUnknown
, (LPVOID
*)&pUnknown1
);
3530 ok_ole_success(hr
, "IUnknown_QueryInterface IID_IUnknown");
3532 /* Does not work on Windows 10 19xx+ */
3533 if (SUCCEEDED(IClassFactory_QueryInterface(pProxy
, &IID_IRemUnknown
, (void **)&pProxy2
)))
3535 hr
= IUnknown_QueryInterface(pProxy2
, &IID_IUnknown
, (void **)&pUnknown2
);
3536 ok(hr
== S_OK
, "Unexpected hr %#x.\n", hr
);
3538 ok(pUnknown1
== pUnknown2
, "both proxy's IUnknowns should be the same - %p, %p\n", pUnknown1
, pUnknown2
);
3539 IUnknown_Release(pUnknown2
);
3541 IUnknown_Release(pProxy2
);
3544 hr
= IClassFactory_QueryInterface(pProxy
, &IID_IMarshal
, (LPVOID
*)&pMarshal
);
3545 ok_ole_success(hr
, "IUnknown_QueryInterface IID_IMarshal");
3547 hr
= IClassFactory_QueryInterface(pProxy
, &IID_IClientSecurity
, (LPVOID
*)&pCliSec
);
3548 ok_ole_success(hr
, "IUnknown_QueryInterface IID_IClientSecurity");
3550 hr
= IClientSecurity_QueryBlanket(pCliSec
, (IUnknown
*)pProxy
, NULL
, NULL
, NULL
, NULL
, NULL
, NULL
, NULL
);
3551 todo_wine
ok_ole_success(hr
, "IClientSecurity_QueryBlanket (all NULLs)");
3553 hr
= IClientSecurity_QueryBlanket(pCliSec
, (IUnknown
*)pMarshal
, NULL
, NULL
, NULL
, NULL
, NULL
, NULL
, NULL
);
3554 todo_wine
ok(hr
== E_NOINTERFACE
, "IClientSecurity_QueryBlanket with local interface should have returned E_NOINTERFACE instead of 0x%08x\n", hr
);
3556 hr
= IClientSecurity_QueryBlanket(pCliSec
, (IUnknown
*)pProxy
, &dwAuthnSvc
, &dwAuthzSvc
, &pServerPrincName
, &dwAuthnLevel
, &dwImpLevel
, &pAuthInfo
, &dwCapabilities
);
3557 todo_wine
ok_ole_success(hr
, "IClientSecurity_QueryBlanket");
3559 hr
= IClientSecurity_SetBlanket(pCliSec
, (IUnknown
*)pProxy
, dwAuthnSvc
, dwAuthzSvc
, pServerPrincName
, dwAuthnLevel
, RPC_C_IMP_LEVEL_IMPERSONATE
, pAuthInfo
, dwCapabilities
);
3560 todo_wine
ok_ole_success(hr
, "IClientSecurity_SetBlanket");
3562 hr
= IClassFactory_CreateInstance(pProxy
, NULL
, &IID_IWineTest
, &pv
);
3563 ok(hr
== E_NOINTERFACE
, "COM call should have succeeded instead of returning 0x%08x\n", hr
);
3565 hr
= IClientSecurity_SetBlanket(pCliSec
, (IUnknown
*)pMarshal
, dwAuthnSvc
, dwAuthzSvc
, pServerPrincName
, dwAuthnLevel
, dwImpLevel
, pAuthInfo
, dwCapabilities
);
3566 todo_wine
ok(hr
== E_NOINTERFACE
, "IClientSecurity_SetBlanket with local interface should have returned E_NOINTERFACE instead of 0x%08x\n", hr
);
3568 hr
= IClientSecurity_SetBlanket(pCliSec
, (IUnknown
*)pProxy
, 0xdeadbeef, dwAuthzSvc
, pServerPrincName
, dwAuthnLevel
, dwImpLevel
, pAuthInfo
, dwCapabilities
);
3569 todo_wine
ok(hr
== E_INVALIDARG
, "IClientSecurity_SetBlanke with invalid dwAuthnSvc should have returned E_INVALIDARG instead of 0x%08x\n", hr
);
3571 CoTaskMemFree(pServerPrincName
);
3573 hr
= IClientSecurity_QueryBlanket(pCliSec
, pUnknown1
, &dwAuthnSvc
, &dwAuthzSvc
, &pServerPrincName
, &dwAuthnLevel
, &dwImpLevel
, &pAuthInfo
, &dwCapabilities
);
3574 todo_wine
ok_ole_success(hr
, "IClientSecurity_QueryBlanket(IUnknown)");
3576 CoTaskMemFree(pServerPrincName
);
3578 IClassFactory_Release(pProxy
);
3579 IUnknown_Release(pUnknown1
);
3580 IMarshal_Release(pMarshal
);
3581 IClientSecurity_Release(pCliSec
);
3583 end_host_object(tid
, thread
);
3586 static HANDLE heventShutdown
;
3588 static void LockModuleOOP(void)
3590 InterlockedIncrement(&cLocks
); /* for test purposes only */
3591 CoAddRefServerProcess();
3594 static void UnlockModuleOOP(void)
3596 InterlockedDecrement(&cLocks
); /* for test purposes only */
3597 if (!CoReleaseServerProcess())
3598 SetEvent(heventShutdown
);
3601 static HWND hwnd_app
;
3605 IPersist IPersist_iface
; /* a nice short interface */
3608 static HRESULT WINAPI
local_server_QueryInterface(IPersist
*iface
, REFIID iid
, void **obj
)
3612 if (IsEqualGUID(iid
, &IID_IUnknown
) ||
3613 IsEqualGUID(iid
, &IID_IPersist
))
3618 IPersist_AddRef(iface
);
3621 return E_NOINTERFACE
;
3624 static ULONG WINAPI
local_server_AddRef(IPersist
*iface
)
3629 static ULONG WINAPI
local_server_Release(IPersist
*iface
)
3634 static HRESULT WINAPI
local_server_GetClassID(IPersist
*iface
, CLSID
*clsid
)
3638 *clsid
= IID_IUnknown
;
3640 /* Test calling CoDisconnectObject within a COM call */
3641 hr
= CoDisconnectObject((IUnknown
*)iface
, 0);
3642 ok(hr
== S_OK
, "got %08x\n", hr
);
3644 /* Initialize and uninitialize the apartment to show that we
3645 * remain in the autojoined mta */
3646 hr
= CoInitializeEx( NULL
, COINIT_MULTITHREADED
);
3647 ok( hr
== S_FALSE
, "got %08x\n", hr
);
3653 static const IPersistVtbl local_server_persist_vtbl
=
3655 local_server_QueryInterface
,
3656 local_server_AddRef
,
3657 local_server_Release
,
3658 local_server_GetClassID
3661 struct local_server local_server_class
=
3663 {&local_server_persist_vtbl
}
3666 static HRESULT WINAPI
TestOOP_IClassFactory_QueryInterface(
3667 LPCLASSFACTORY iface
,
3671 if (ppvObj
== NULL
) return E_POINTER
;
3673 if (IsEqualGUID(riid
, &IID_IUnknown
) ||
3674 IsEqualGUID(riid
, &IID_IClassFactory
))
3677 IClassFactory_AddRef(iface
);
3681 return E_NOINTERFACE
;
3684 static ULONG WINAPI
TestOOP_IClassFactory_AddRef(LPCLASSFACTORY iface
)
3686 return 2; /* non-heap-based object */
3689 static ULONG WINAPI
TestOOP_IClassFactory_Release(LPCLASSFACTORY iface
)
3691 return 1; /* non-heap-based object */
3694 static HRESULT WINAPI
TestOOP_IClassFactory_CreateInstance(
3695 LPCLASSFACTORY iface
,
3696 LPUNKNOWN pUnkOuter
,
3700 IPersist
*persist
= &local_server_class
.IPersist_iface
;
3702 IPersist_AddRef( persist
);
3703 hr
= IPersist_QueryInterface( persist
, riid
, ppvObj
);
3704 IPersist_Release( persist
);
3708 static HRESULT WINAPI
TestOOP_IClassFactory_LockServer(
3709 LPCLASSFACTORY iface
,
3719 static const IClassFactoryVtbl TestClassFactoryOOP_Vtbl
=
3721 TestOOP_IClassFactory_QueryInterface
,
3722 TestOOP_IClassFactory_AddRef
,
3723 TestOOP_IClassFactory_Release
,
3724 TestOOP_IClassFactory_CreateInstance
,
3725 TestOOP_IClassFactory_LockServer
3728 static IClassFactory TestOOP_ClassFactory
= { &TestClassFactoryOOP_Vtbl
};
3730 static void test_register_local_server(void)
3738 heventShutdown
= CreateEventA(NULL
, TRUE
, FALSE
, NULL
);
3739 ready_event
= CreateEventA(NULL
, FALSE
, FALSE
, "Wine COM Test Ready Event");
3740 handles
[0] = CreateEventA(NULL
, FALSE
, FALSE
, "Wine COM Test Quit Event");
3741 handles
[1] = CreateEventA(NULL
, FALSE
, FALSE
, "Wine COM Test Repeat Event");
3744 hr
= CoRegisterClassObject(&CLSID_WineOOPTest
, (IUnknown
*)&TestOOP_ClassFactory
,
3745 CLSCTX_LOCAL_SERVER
, REGCLS_SINGLEUSE
, &cookie
);
3746 ok_ole_success(hr
, CoRegisterClassObject
);
3748 SetEvent(ready_event
);
3752 wait
= MsgWaitForMultipleObjects(2, handles
, FALSE
, 30000, QS_ALLINPUT
);
3753 if (wait
== WAIT_OBJECT_0
+2)
3757 if (PeekMessageA(&msg
, NULL
, 0, 0, PM_REMOVE
))
3759 TranslateMessage(&msg
);
3760 DispatchMessageA(&msg
);
3763 else if (wait
== WAIT_OBJECT_0
+1)
3765 hr
= CoRevokeClassObject(cookie
);
3766 ok_ole_success(hr
, CoRevokeClassObject
);
3770 while (wait
== WAIT_OBJECT_0
+2);
3772 ok( wait
== WAIT_OBJECT_0
, "quit event wait timed out\n" );
3773 hr
= CoRevokeClassObject(cookie
);
3774 ok_ole_success(hr
, CoRevokeClassObject
);
3775 CloseHandle(handles
[0]);
3776 CloseHandle(handles
[1]);
3779 static HANDLE
create_target_process(const char *arg
)
3782 char cmdline
[MAX_PATH
];
3784 PROCESS_INFORMATION pi
;
3785 STARTUPINFOA si
= { 0 };
3790 winetest_get_mainargs( &argv
);
3791 sprintf(cmdline
, "\"%s\" %s %s", argv
[0], argv
[1], arg
);
3792 ret
= CreateProcessA(argv
[0], cmdline
, NULL
, NULL
, FALSE
, 0, NULL
, NULL
, &si
, &pi
);
3793 ok(ret
, "CreateProcess failed with error: %u\n", GetLastError());
3794 if (pi
.hThread
) CloseHandle(pi
.hThread
);
3798 /* tests functions commonly used by out of process COM servers */
3799 static void test_local_server(void)
3809 HANDLE repeat_event
;
3812 heventShutdown
= CreateEventA(NULL
, TRUE
, FALSE
, NULL
);
3816 /* Start the object suspended */
3817 hr
= CoRegisterClassObject(&CLSID_WineOOPTest
, (IUnknown
*)&TestOOP_ClassFactory
,
3818 CLSCTX_LOCAL_SERVER
, REGCLS_MULTIPLEUSE
| REGCLS_SUSPENDED
, &cookie
);
3819 ok_ole_success(hr
, CoRegisterClassObject
);
3821 /* ... and CoGetClassObject does not find it and fails when it looks for the
3822 * class in the registry */
3823 hr
= CoGetClassObject(&CLSID_WineOOPTest
, CLSCTX_INPROC_SERVER
,
3824 NULL
, &IID_IClassFactory
, (LPVOID
*)&cf
);
3825 todo_wine
ok(hr
== REGDB_E_CLASSNOTREG
, "Got hr %#x.\n", hr
);
3827 /* Resume the object suspended above ... */
3828 hr
= CoResumeClassObjects();
3829 ok_ole_success(hr
, CoResumeClassObjects
);
3831 /* ... and now it should succeed */
3832 hr
= CoGetClassObject(&CLSID_WineOOPTest
, CLSCTX_INPROC_SERVER
,
3833 NULL
, &IID_IClassFactory
, (LPVOID
*)&cf
);
3834 ok_ole_success(hr
, CoGetClassObject
);
3836 /* Now check the locking is working */
3837 /* NOTE: we are accessing the class directly, not through a proxy */
3841 hr
= IClassFactory_LockServer(cf
, TRUE
);
3842 ok_ole_success(hr
, IClassFactory_LockServer
);
3844 ok_more_than_one_lock();
3846 IClassFactory_LockServer(cf
, FALSE
);
3847 ok_ole_success(hr
, IClassFactory_LockServer
);
3851 IClassFactory_Release(cf
);
3853 /* wait for shutdown signal */
3854 ret
= WaitForSingleObject(heventShutdown
, 0);
3855 ok(ret
!= WAIT_TIMEOUT
, "Server didn't shut down\n");
3857 /* try to connect again after SCM has suspended registered class objects */
3858 hr
= CoGetClassObject(&CLSID_WineOOPTest
, CLSCTX_INPROC_SERVER
| CLSCTX_LOCAL_SERVER
, NULL
,
3859 &IID_IClassFactory
, (LPVOID
*)&cf
);
3860 todo_wine
ok(hr
== CO_E_SERVER_STOPPING
|| hr
== REGDB_E_CLASSNOTREG
/* Win10 1709+ */, "Got hr %#x.\n", hr
);
3862 hr
= CoRevokeClassObject(cookie
);
3863 ok_ole_success(hr
, CoRevokeClassObject
);
3865 CloseHandle(heventShutdown
);
3867 process
= create_target_process("-Embedding");
3868 ok(process
!= NULL
, "couldn't start local server process, error was %d\n", GetLastError());
3870 ready_event
= CreateEventA(NULL
, FALSE
, FALSE
, "Wine COM Test Ready Event");
3871 ok( !WaitForSingleObject(ready_event
, 10000), "wait timed out\n" );
3873 hr
= CoCreateInstance(&CLSID_WineOOPTest
, NULL
, CLSCTX_LOCAL_SERVER
, &IID_IPersist
, (void **)&persist
);
3874 ok_ole_success(hr
, CoCreateInstance
);
3876 IPersist_Release(persist
);
3878 hr
= CoCreateInstance(&CLSID_WineOOPTest
, NULL
, CLSCTX_LOCAL_SERVER
, &IID_IPersist
, (void **)&persist
);
3879 ok(hr
== REGDB_E_CLASSNOTREG
, "Second CoCreateInstance on REGCLS_SINGLEUSE object should have failed\n");
3881 /* Re-register the class and try calling CoDisconnectObject from within a call to that object */
3882 repeat_event
= CreateEventA(NULL
, FALSE
, FALSE
, "Wine COM Test Repeat Event");
3883 SetEvent(repeat_event
);
3884 CloseHandle(repeat_event
);
3886 ok( !WaitForSingleObject(ready_event
, 10000), "wait timed out\n" );
3887 CloseHandle(ready_event
);
3889 hr
= CoCreateInstance(&CLSID_WineOOPTest
, NULL
, CLSCTX_LOCAL_SERVER
, &IID_IPersist
, (void **)&persist
);
3890 ok_ole_success(hr
, CoCreateInstance
);
3892 /* GetClassID will call CoDisconnectObject */
3893 IPersist_GetClassID(persist
, &clsid
);
3894 IPersist_Release(persist
);
3896 quit_event
= CreateEventA(NULL
, FALSE
, FALSE
, "Wine COM Test Quit Event");
3897 SetEvent(quit_event
);
3899 wait_child_process( process
);
3900 CloseHandle(quit_event
);
3901 CloseHandle(process
);
3907 IGlobalInterfaceTable
*git
;
3910 static DWORD CALLBACK
get_global_interface_proc(LPVOID pv
)
3913 struct git_params
*params
= pv
;
3916 hr
= IGlobalInterfaceTable_GetInterfaceFromGlobal(params
->git
, params
->cookie
, &IID_IClassFactory
, (void **)&cf
);
3917 ok(hr
== CO_E_NOTINITIALIZED
, "Got hr %#x.\n", hr
);
3921 hr
= IGlobalInterfaceTable_GetInterfaceFromGlobal(params
->git
, params
->cookie
, &IID_IClassFactory
, (void **)&cf
);
3922 ok_ole_success(hr
, IGlobalInterfaceTable_GetInterfaceFromGlobal
);
3924 IClassFactory_Release(cf
);
3931 static void test_globalinterfacetable(void)
3934 IGlobalInterfaceTable
*git
;
3938 struct git_params params
;
3946 hr
= pDllGetClassObject(&CLSID_StdGlobalInterfaceTable
, &IID_IClassFactory
, (void**)&cf
);
3947 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3949 hr
= IClassFactory_QueryInterface(cf
, &IID_IGlobalInterfaceTable
, (void**)&object
);
3950 ok(hr
== E_NOINTERFACE
, "got 0x%08x\n", hr
);
3952 IClassFactory_Release(cf
);
3954 hr
= CoCreateInstance(&CLSID_StdGlobalInterfaceTable
, NULL
, CLSCTX_INPROC_SERVER
, &IID_IGlobalInterfaceTable
, (void **)&git
);
3955 ok_ole_success(hr
, CoCreateInstance
);
3957 ref
= IGlobalInterfaceTable_AddRef(git
);
3958 ok(ref
== 1, "ref=%d\n", ref
);
3959 ref
= IGlobalInterfaceTable_AddRef(git
);
3960 ok(ref
== 1, "ref=%d\n", ref
);
3962 ref
= IGlobalInterfaceTable_Release(git
);
3963 ok(ref
== 1, "ref=%d\n", ref
);
3964 ref
= IGlobalInterfaceTable_Release(git
);
3965 ok(ref
== 1, "ref=%d\n", ref
);
3967 hr
= IGlobalInterfaceTable_RegisterInterfaceInGlobal(git
, (IUnknown
*)&Test_ClassFactory
, &IID_IClassFactory
, &cookie
);
3968 ok_ole_success(hr
, IGlobalInterfaceTable_RegisterInterfaceInGlobal
);
3970 ok_more_than_one_lock();
3972 params
.cookie
= cookie
;
3974 /* note: params is on stack so we MUST wait for get_global_interface_proc
3975 * to exit before we can return */
3976 thread
= CreateThread(NULL
, 0, get_global_interface_proc
, ¶ms
, 0, &tid
);
3978 ret
= MsgWaitForMultipleObjects(1, &thread
, FALSE
, 10000, QS_ALLINPUT
);
3979 while (ret
== WAIT_OBJECT_0
+ 1)
3982 while (PeekMessageA(&msg
, NULL
, 0, 0, PM_REMOVE
))
3983 DispatchMessageA(&msg
);
3984 ret
= MsgWaitForMultipleObjects(1, &thread
, FALSE
, 10000, QS_ALLINPUT
);
3987 CloseHandle(thread
);
3989 /* test getting interface from global with different iid */
3990 hr
= IGlobalInterfaceTable_GetInterfaceFromGlobal(git
, cookie
, &IID_IUnknown
, (void **)&object
);
3991 ok_ole_success(hr
, IGlobalInterfaceTable_GetInterfaceFromGlobal
);
3992 IUnknown_Release(object
);
3994 /* test getting interface from global with same iid */
3995 hr
= IGlobalInterfaceTable_GetInterfaceFromGlobal(git
, cookie
, &IID_IClassFactory
, (void **)&object
);
3996 ok_ole_success(hr
, IGlobalInterfaceTable_GetInterfaceFromGlobal
);
3997 IUnknown_Release(object
);
3999 hr
= IGlobalInterfaceTable_RevokeInterfaceFromGlobal(git
, cookie
);
4000 ok_ole_success(hr
, IGlobalInterfaceTable_RevokeInterfaceFromGlobal
);
4004 IGlobalInterfaceTable_Release(git
);
4006 hr
= CoGetClassObject(&CLSID_StdGlobalInterfaceTable
, CLSCTX_INPROC_SERVER
, NULL
, &IID_IClassFactory
, (void **)&cf
);
4007 ok(hr
== S_OK
, "Unexpected hr %#x.\n", hr
);
4008 IClassFactory_Release(cf
);
4011 static void test_manualresetevent(void)
4013 ISynchronizeHandle
*sync_handle
;
4014 ISynchronize
*psync1
, *psync2
;
4015 IClassFactory
*factory
;
4021 hr
= pDllGetClassObject(&CLSID_ManualResetEvent
, &IID_IClassFactory
, (void **)&factory
);
4022 ok(hr
== S_OK
, "Unexpected hr %#x.\n", hr
);
4023 IClassFactory_Release(factory
);
4025 hr
= CoGetClassObject(&CLSID_ManualResetEvent
, CLSCTX_INPROC_SERVER
, NULL
, &IID_IClassFactory
, (void **)&factory
);
4026 ok(hr
== S_OK
, "Unexpected hr %#x.\n", hr
);
4027 IClassFactory_Release(factory
);
4029 hr
= CoCreateInstance(&CLSID_ManualResetEvent
, NULL
, CLSCTX_INPROC_SERVER
, &IID_IUnknown
, (void**)&punk
);
4030 ok(hr
== S_OK
, "Got 0x%08x\n", hr
);
4031 ok(!!punk
, "Got NULL.\n");
4032 IUnknown_Release(punk
);
4034 hr
= CoCreateInstance(&CLSID_ManualResetEvent
, NULL
, CLSCTX_INPROC_SERVER
, &IID_ISynchronize
, (void**)&psync1
);
4035 ok(hr
== S_OK
, "Got 0x%08x\n", hr
);
4036 ok(!!psync1
, "Got NULL.\n");
4038 hr
= ISynchronize_Wait(psync1
, 0, 5);
4039 ok(hr
== RPC_S_CALLPENDING
, "Got 0x%08x\n", hr
);
4041 hr
= ISynchronize_Reset(psync1
);
4042 ok(hr
== S_OK
, "Got 0x%08x\n", hr
);
4043 hr
= ISynchronize_Signal(psync1
);
4044 ok(hr
== S_OK
, "Got 0x%08x\n", hr
);
4045 hr
= ISynchronize_Wait(psync1
, 0, 5);
4046 ok(hr
== S_OK
, "Got 0x%08x\n", hr
);
4047 hr
= ISynchronize_Wait(psync1
, 0, 5);
4048 ok(hr
== S_OK
, "Got 0x%08x\n", hr
);
4049 hr
= ISynchronize_Reset(psync1
);
4050 ok(hr
== S_OK
, "Got 0x%08x\n", hr
);
4051 hr
= ISynchronize_Wait(psync1
, 0, 5);
4052 ok(hr
== RPC_S_CALLPENDING
, "Got 0x%08x\n", hr
);
4054 hr
= CoCreateInstance(&CLSID_ManualResetEvent
, NULL
, CLSCTX_INPROC_SERVER
, &IID_ISynchronize
, (void**)&psync2
);
4055 ok(hr
== S_OK
, "Got 0x%08x\n", hr
);
4056 ok(!!psync2
, "Got NULL.\n");
4057 ok(psync1
!= psync2
, "psync1 == psync2.\n");
4059 hr
= ISynchronize_QueryInterface(psync2
, &IID_ISynchronizeHandle
, (void**)&sync_handle
);
4060 ok(hr
== S_OK
, "QueryInterface(IID_ISynchronizeHandle) failed: %08x\n", hr
);
4063 hr
= ISynchronizeHandle_GetHandle(sync_handle
, &handle
);
4064 ok(hr
== S_OK
, "GetHandle failed: %08x\n", hr
);
4065 ok(handle
!= NULL
&& handle
!= INVALID_HANDLE_VALUE
, "handle = %p\n", handle
);
4067 ISynchronizeHandle_Release(sync_handle
);
4069 hr
= ISynchronize_Wait(psync2
, 0, 5);
4070 ok(hr
== RPC_S_CALLPENDING
, "Got 0x%08x\n", hr
);
4072 hr
= ISynchronize_Reset(psync1
);
4073 ok(hr
== S_OK
, "Got 0x%08x\n", hr
);
4074 hr
= ISynchronize_Reset(psync2
);
4075 ok(hr
== S_OK
, "Got 0x%08x\n", hr
);
4076 hr
= ISynchronize_Signal(psync1
);
4077 ok(hr
== S_OK
, "Got 0x%08x\n", hr
);
4078 hr
= ISynchronize_Wait(psync2
, 0, 5);
4079 ok(hr
== RPC_S_CALLPENDING
, "Got 0x%08x\n", hr
);
4081 ref
= ISynchronize_AddRef(psync1
);
4082 ok(ref
== 2, "Got ref: %d\n", ref
);
4083 ref
= ISynchronize_AddRef(psync1
);
4084 ok(ref
== 3, "Got ref: %d\n", ref
);
4085 ref
= ISynchronize_Release(psync1
);
4086 ok(ref
== 2, "Got nonzero ref: %d\n", ref
);
4087 ref
= ISynchronize_Release(psync2
);
4088 ok(!ref
, "Got nonzero ref: %d\n", ref
);
4089 ref
= ISynchronize_Release(psync1
);
4090 ok(ref
== 1, "Got nonzero ref: %d\n", ref
);
4091 ref
= ISynchronize_Release(psync1
);
4092 ok(!ref
, "Got nonzero ref: %d\n", ref
);
4095 static DWORD CALLBACK
implicit_mta_unmarshal_proc(void *param
)
4097 IStream
*stream
= param
;
4102 IStream_Seek(stream
, ullZero
, STREAM_SEEK_SET
, NULL
);
4103 hr
= CoUnmarshalInterface(stream
, &IID_IClassFactory
, (void **)&cf
);
4104 ok_ole_success(hr
, CoUnmarshalInterface
);
4106 hr
= IClassFactory_CreateInstance(cf
, NULL
, &IID_IUnknown
, (void **)&proxy
);
4107 ok_ole_success(hr
, IClassFactory_CreateInstance
);
4109 IUnknown_Release(proxy
);
4111 /* But if we initialize an STA in this apartment, it becomes the wrong one. */
4112 CoInitializeEx(NULL
, COINIT_APARTMENTTHREADED
);
4114 hr
= IClassFactory_CreateInstance(cf
, NULL
, &IID_IUnknown
, (void **)&proxy
);
4115 ok(hr
== RPC_E_WRONG_THREAD
, "got %#x\n", hr
);
4119 ok_more_than_one_lock();
4120 ok_non_zero_external_conn();
4122 IClassFactory_Release(cf
);
4125 ok_zero_external_conn();
4126 ok_last_release_closes(TRUE
);
4130 static DWORD CALLBACK
implicit_mta_use_proc(void *param
)
4132 IClassFactory
*cf
= param
;
4136 hr
= IClassFactory_CreateInstance(cf
, NULL
, &IID_IUnknown
, (void **)&proxy
);
4137 ok_ole_success(hr
, IClassFactory_CreateInstance
);
4139 IUnknown_Release(proxy
);
4141 /* But if we initialize an STA in this apartment, it becomes the wrong one. */
4142 CoInitializeEx(NULL
, COINIT_APARTMENTTHREADED
);
4144 hr
= IClassFactory_CreateInstance(cf
, NULL
, &IID_IUnknown
, (void **)&proxy
);
4145 ok(hr
== RPC_E_WRONG_THREAD
, "got %#x\n", hr
);
4151 struct implicit_mta_marshal_data
4158 static DWORD CALLBACK
implicit_mta_marshal_proc(void *param
)
4160 struct implicit_mta_marshal_data
*data
= param
;
4163 hr
= CoMarshalInterface(data
->stream
, &IID_IClassFactory
,
4164 (IUnknown
*)&Test_ClassFactory
, MSHCTX_INPROC
, NULL
, MSHLFLAGS_NORMAL
);
4165 ok_ole_success(hr
, CoMarshalInterface
);
4167 SetEvent(data
->start
);
4169 ok(!WaitForSingleObject(data
->stop
, 1000), "wait failed\n");
4173 static void test_implicit_mta(void)
4175 struct implicit_mta_marshal_data data
;
4176 HANDLE host_thread
, thread
;
4184 external_connections
= 0;
4186 CoInitializeEx(NULL
, COINIT_MULTITHREADED
);
4188 /* Firstly: we can unmarshal and use an object while in the implicit MTA. */
4189 hr
= CreateStreamOnHGlobal(NULL
, TRUE
, &stream
);
4190 ok_ole_success(hr
, CreateStreamOnHGlobal
);
4191 tid
= start_host_object(stream
, &IID_IClassFactory
, (IUnknown
*)&Test_ClassFactory
, MSHLFLAGS_NORMAL
, &host_thread
);
4193 ok_more_than_one_lock();
4194 ok_non_zero_external_conn();
4196 thread
= CreateThread(NULL
, 0, implicit_mta_unmarshal_proc
, stream
, 0, NULL
);
4197 ok(!WaitForSingleObject(thread
, 1000), "wait failed\n");
4198 CloseHandle(thread
);
4200 IStream_Release(stream
);
4201 end_host_object(tid
, host_thread
);
4203 /* Secondly: we can unmarshal an object into the real MTA and then use it
4204 * from the implicit MTA. */
4205 hr
= CreateStreamOnHGlobal(NULL
, TRUE
, &stream
);
4206 ok_ole_success(hr
, CreateStreamOnHGlobal
);
4207 tid
= start_host_object(stream
, &IID_IClassFactory
, (IUnknown
*)&Test_ClassFactory
, MSHLFLAGS_NORMAL
, &host_thread
);
4209 ok_more_than_one_lock();
4210 ok_non_zero_external_conn();
4212 IStream_Seek(stream
, ullZero
, STREAM_SEEK_SET
, NULL
);
4213 hr
= CoUnmarshalInterface(stream
, &IID_IClassFactory
, (void **)&cf
);
4214 ok_ole_success(hr
, CoUnmarshalInterface
);
4216 thread
= CreateThread(NULL
, 0, implicit_mta_use_proc
, cf
, 0, NULL
);
4217 ok(!WaitForSingleObject(thread
, 1000), "wait failed\n");
4218 CloseHandle(thread
);
4220 IClassFactory_Release(cf
);
4221 IStream_Release(stream
);
4224 ok_non_zero_external_conn();
4225 ok_last_release_closes(TRUE
);
4227 end_host_object(tid
, host_thread
);
4229 /* Thirdly: we can marshal an object from the implicit MTA and then
4230 * unmarshal it into the real one. */
4231 data
.start
= CreateEventA(NULL
, FALSE
, FALSE
, NULL
);
4232 data
.stop
= CreateEventA(NULL
, FALSE
, FALSE
, NULL
);
4234 hr
= CreateStreamOnHGlobal(NULL
, TRUE
, &data
.stream
);
4235 ok_ole_success(hr
, CreateStreamOnHGlobal
);
4237 thread
= CreateThread(NULL
, 0, implicit_mta_marshal_proc
, &data
, 0, NULL
);
4238 ok(!WaitForSingleObject(data
.start
, 1000), "wait failed\n");
4240 IStream_Seek(data
.stream
, ullZero
, STREAM_SEEK_SET
, NULL
);
4241 hr
= CoUnmarshalInterface(data
.stream
, &IID_IClassFactory
, (void **)&cf
);
4242 ok_ole_success(hr
, CoUnmarshalInterface
);
4244 hr
= IClassFactory_CreateInstance(cf
, NULL
, &IID_IUnknown
, (void **)&proxy
);
4245 ok_ole_success(hr
, IClassFactory_CreateInstance
);
4247 IUnknown_Release(proxy
);
4249 SetEvent(data
.stop
);
4250 ok(!WaitForSingleObject(thread
, 1000), "wait failed\n");
4251 CloseHandle(thread
);
4253 IStream_Release(data
.stream
);
4258 static HRESULT WINAPI
TestChannelHook_QueryInterface(IChannelHook
*iface
, REFIID riid
, void **ppv
)
4260 if (IsEqualIID(riid
, &IID_IUnknown
) || IsEqualIID(riid
, &IID_IChannelHook
))
4263 IChannelHook_AddRef(iface
);
4268 return E_NOINTERFACE
;
4271 static ULONG WINAPI
TestChannelHook_AddRef(IChannelHook
*iface
)
4276 static ULONG WINAPI
TestChannelHook_Release(IChannelHook
*iface
)
4282 static GUID causality
;
4284 static void WINAPI
TestChannelHook_ClientGetSize(
4285 IChannelHook
*iface
,
4290 SChannelHookCallInfo
*info
= (SChannelHookCallInfo
*)riid
;
4292 if (winetest_debug
> 1) trace("IChannelHook::ClientGetSize(iid %s)\n", debugstr_guid(riid
));
4294 if (info
->cbSize
== sizeof(*info
))
4296 ok(info
->dwServerPid
== GetCurrentProcessId(), "dwServerPid was 0x%x instead of 0x%x\n", info
->dwServerPid
, GetCurrentProcessId());
4297 ok(info
->iMethod
== method
, "iMethod was %d should be %d\n", info
->iMethod
, method
);
4298 ok(!info
->pObject
, "pObject should be NULL\n");
4300 causality
= info
->uCausality
;
4302 ok(IsEqualGUID(&info
->uCausality
, &causality
), "causality wasn't correct\n");
4305 ok(IsEqualGUID(uExtent
, &EXTENTID_WineTest
), "uExtent wasn't correct\n");
4310 static void WINAPI
TestChannelHook_ClientFillBuffer(
4311 IChannelHook
*iface
,
4317 SChannelHookCallInfo
*info
= (SChannelHookCallInfo
*)riid
;
4319 if (winetest_debug
> 1) trace("IChannelHook::ClientFillBuffer()\n");
4321 if (info
->cbSize
== sizeof(*info
))
4323 ok(info
->dwServerPid
== GetCurrentProcessId(), "dwServerPid was 0x%x instead of 0x%x\n", info
->dwServerPid
, GetCurrentProcessId());
4324 ok(info
->iMethod
== method
, "iMethod was %d should be %d\n", info
->iMethod
, method
);
4325 ok(!info
->pObject
, "pObject should be NULL\n");
4326 ok(IsEqualGUID(&info
->uCausality
, &causality
), "causality wasn't correct\n");
4329 ok(IsEqualGUID(uExtent
, &EXTENTID_WineTest
), "uExtent wasn't correct\n");
4331 *(unsigned char *)pDataBuffer
= 0xcc;
4335 static void WINAPI
TestChannelHook_ClientNotify(
4336 IChannelHook
*iface
,
4344 SChannelHookCallInfo
*info
= (SChannelHookCallInfo
*)riid
;
4346 if (winetest_debug
> 1) trace("IChannelHook::ClientNotify(hr %#x)\n", hrFault
);
4348 if (info
->cbSize
== sizeof(*info
))
4350 ok(info
->dwServerPid
== GetCurrentProcessId(), "dwServerPid was 0x%x instead of 0x%x\n", info
->dwServerPid
, GetCurrentProcessId());
4351 ok(info
->iMethod
== method
, "iMethod was %d should be %d\n", info
->iMethod
, method
);
4353 ok(info
->pObject
!= NULL
, "pObject shouldn't be NULL\n");
4355 ok(IsEqualGUID(&info
->uCausality
, &causality
), "causality wasn't correct\n");
4358 ok(IsEqualGUID(uExtent
, &EXTENTID_WineTest
), "uExtent wasn't correct\n");
4361 static void WINAPI
TestChannelHook_ServerNotify(
4362 IChannelHook
*iface
,
4369 SChannelHookCallInfo
*info
= (SChannelHookCallInfo
*)riid
;
4371 if (winetest_debug
> 1) trace("IChannelHook::ServerNotify()\n");
4373 if (info
->cbSize
== sizeof(*info
))
4375 ok(info
->dwServerPid
== GetCurrentProcessId(), "dwServerPid was 0x%x instead of 0x%x\n", info
->dwServerPid
, GetCurrentProcessId());
4376 ok(info
->iMethod
== method
, "iMethod was %d should be %d\n", info
->iMethod
, method
);
4377 ok(info
->pObject
!= NULL
, "pObject shouldn't be NULL\n");
4378 ok(IsEqualGUID(&info
->uCausality
, &causality
), "causality wasn't correct\n");
4381 ok(cbDataSize
== 1, "cbDataSize should have been 1 instead of %d\n", cbDataSize
);
4382 ok(*(unsigned char *)pDataBuffer
== 0xcc, "pDataBuffer should have contained 0xcc instead of 0x%x\n", *(unsigned char *)pDataBuffer
);
4383 ok(IsEqualGUID(uExtent
, &EXTENTID_WineTest
), "uExtent wasn't correct\n");
4386 static void WINAPI
TestChannelHook_ServerGetSize(
4387 IChannelHook
*iface
,
4393 SChannelHookCallInfo
*info
= (SChannelHookCallInfo
*)riid
;
4395 if (winetest_debug
> 1) trace("IChannelHook::ServerGetSize(iid %s, hr %#x)\n", debugstr_guid(riid
), hrFault
);
4397 if (info
->cbSize
== sizeof(*info
))
4399 ok(info
->dwServerPid
== GetCurrentProcessId(), "dwServerPid was 0x%x instead of 0x%x\n", info
->dwServerPid
, GetCurrentProcessId());
4400 ok(info
->iMethod
== method
, "iMethod was %d should be %d\n", info
->iMethod
, method
);
4401 ok(info
->pObject
!= NULL
, "pObject shouldn't be NULL\n");
4402 ok(IsEqualGUID(&info
->uCausality
, &causality
), "causality wasn't correct\n");
4405 ok(IsEqualGUID(uExtent
, &EXTENTID_WineTest
), "uExtent wasn't correct\n");
4409 static void WINAPI
TestChannelHook_ServerFillBuffer(
4410 IChannelHook
*iface
,
4417 ok(0, "TestChannelHook_ServerFillBuffer shouldn't be called\n");
4420 static const IChannelHookVtbl TestChannelHookVtbl
=
4422 TestChannelHook_QueryInterface
,
4423 TestChannelHook_AddRef
,
4424 TestChannelHook_Release
,
4425 TestChannelHook_ClientGetSize
,
4426 TestChannelHook_ClientFillBuffer
,
4427 TestChannelHook_ClientNotify
,
4428 TestChannelHook_ServerNotify
,
4429 TestChannelHook_ServerGetSize
,
4430 TestChannelHook_ServerFillBuffer
,
4433 static IChannelHook TestChannelHook
= { &TestChannelHookVtbl
};
4435 static void test_channel_hook(void)
4437 IClassFactory
*cf
= NULL
;
4439 IUnknown
*proxy
= NULL
;
4443 struct host_object_data object_data
= { NULL
, &IID_IClassFactory
, (IUnknown
*)&Test_ClassFactory
,
4444 MSHLFLAGS_NORMAL
, &MessageFilter
};
4446 hr
= CoRegisterChannelHook(&EXTENTID_WineTest
, &TestChannelHook
);
4447 ok_ole_success(hr
, CoRegisterChannelHook
);
4449 hr
= CoRegisterMessageFilter(&MessageFilter
, NULL
);
4450 ok_ole_success(hr
, CoRegisterMessageFilter
);
4454 hr
= CreateStreamOnHGlobal(NULL
, TRUE
, &object_data
.stream
);
4455 ok_ole_success(hr
, CreateStreamOnHGlobal
);
4456 tid
= start_host_object2(&object_data
, &thread
);
4458 ok_more_than_one_lock();
4460 IStream_Seek(object_data
.stream
, ullZero
, STREAM_SEEK_SET
, NULL
);
4461 hr
= CoUnmarshalInterface(object_data
.stream
, &IID_IClassFactory
, (void **)&cf
);
4462 ok_ole_success(hr
, CoUnmarshalInterface
);
4463 IStream_Release(object_data
.stream
);
4465 ok_more_than_one_lock();
4468 hr
= IClassFactory_CreateInstance(cf
, NULL
, &IID_IUnknown
, (LPVOID
*)&proxy
);
4469 ok_ole_success(hr
, IClassFactory_CreateInstance
);
4472 IUnknown_Release(proxy
);
4474 IClassFactory_Release(cf
);
4478 end_host_object(tid
, thread
);
4480 hr
= CoRegisterMessageFilter(NULL
, NULL
);
4481 ok_ole_success(hr
, CoRegisterMessageFilter
);
4486 HMODULE hOle32
= GetModuleHandleA("ole32");
4490 pDllGetClassObject
= (void*)GetProcAddress(hOle32
, "DllGetClassObject");
4492 argc
= winetest_get_mainargs( &argv
);
4493 if (argc
> 2 && (!strcmp(argv
[2], "-Embedding")))
4495 CoInitializeEx(NULL
, COINIT_MULTITHREADED
);
4496 test_register_local_server();
4502 register_test_window();
4504 test_cocreateinstance_proxy();
4505 test_implicit_mta();
4507 CoInitializeEx(NULL
, COINIT_APARTMENTTHREADED
);
4509 /* FIXME: test CoCreateInstanceEx */
4511 /* lifecycle management and marshaling tests */
4514 test_no_marshaler();
4515 test_normal_marshal_and_release();
4516 test_normal_marshal_and_unmarshal();
4517 test_marshal_and_unmarshal_invalid();
4518 test_same_apartment_unmarshal_failure();
4519 test_interthread_marshal_and_unmarshal();
4520 test_proxy_marshal_and_unmarshal();
4521 test_proxy_marshal_and_unmarshal2();
4522 test_proxy_marshal_and_unmarshal_weak();
4523 test_proxy_marshal_and_unmarshal_strong();
4524 test_marshal_stub_apartment_shutdown();
4525 test_marshal_proxy_apartment_shutdown();
4526 test_marshal_proxy_mta_apartment_shutdown();
4527 test_no_couninitialize_server();
4528 test_no_couninitialize_client();
4529 test_tableweak_marshal_and_unmarshal_twice();
4530 test_tableweak_marshal_releasedata1();
4531 test_tableweak_marshal_releasedata2();
4532 test_tableweak_and_normal_marshal_and_unmarshal();
4533 test_tableweak_and_normal_marshal_and_releasedata();
4534 test_two_tableweak_marshal_and_releasedata();
4535 test_tablestrong_marshal_and_unmarshal_twice();
4536 test_lock_object_external();
4537 test_disconnect_stub();
4538 test_normal_marshal_and_unmarshal_twice();
4540 with_external_conn
= !with_external_conn
;
4541 } while (with_external_conn
);
4543 test_marshal_channel_buffer();
4544 test_StdMarshal_custom_marshaling();
4545 test_DfMarshal_custom_marshaling();
4546 test_CoGetStandardMarshal();
4547 test_hresult_marshaling();
4548 test_proxy_used_in_wrong_thread();
4549 test_message_filter();
4550 test_bad_marshal_stream();
4551 test_proxy_interfaces();
4552 test_stubbuffer(&IID_IClassFactory
);
4553 test_proxybuffer(&IID_IClassFactory
);
4554 test_message_reentrancy();
4555 test_call_from_message();
4556 test_WM_QUIT_handling();
4557 test_freethreadedmarshaler();
4558 test_inproc_handler();
4559 test_handler_marshaling();
4560 test_client_security();
4562 test_local_server();
4564 test_globalinterfacetable();
4565 test_manualresetevent();
4566 test_crash_couninitialize();
4568 /* must be last test as channel hooks can't be unregistered */
4569 test_channel_hook();