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 } };
65 /* functions that are not present on all versions of Windows */
66 static HRESULT (WINAPI
* pCoInitializeEx
)(LPVOID lpReserved
, DWORD dwCoInit
);
67 static HRESULT (WINAPI
*pDllGetClassObject
)(REFCLSID
,REFIID
,LPVOID
);
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 pCoInitializeEx(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 trace("add connection\n");
205 return ++external_connections
;
209 static DWORD WINAPI
ExternalConnection_ReleaseConnection(IExternalConnection
*iface
, DWORD extconn
,
210 DWORD reserved
, BOOL fLastReleaseCloses
)
212 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((IUnknown
*)&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 #ifndef __REACTOS__ /* FIXME: Inspect */
615 static IPSFactoryBuffer PSFactoryBuffer
;
618 static DWORD CALLBACK
host_object_proc(LPVOID p
)
620 struct host_object_data
*data
= p
;
621 DWORD registration_key
;
625 pCoInitializeEx(NULL
, COINIT_APARTMENTTHREADED
);
627 if(data
->register_object
) {
628 hr
= CoRegisterClassObject(data
->register_clsid
, data
->register_object
,
629 CLSCTX_INPROC_SERVER
, REGCLS_MULTIPLEUSE
, ®istration_key
);
630 ok(hr
== S_OK
, "CoRegisterClassObject failed: %08x\n", hr
);
635 IMessageFilter
* prev_filter
= NULL
;
636 hr
= CoRegisterMessageFilter(data
->filter
, &prev_filter
);
637 if (prev_filter
) IMessageFilter_Release(prev_filter
);
638 ok_ole_success(hr
, CoRegisterMessageFilter
);
641 hr
= CoMarshalInterface(data
->stream
, data
->iid
, data
->object
, MSHCTX_INPROC
, NULL
, data
->marshal_flags
);
642 ok_ole_success(hr
, CoMarshalInterface
);
644 /* force the message queue to be created before signaling parent thread */
645 PeekMessageA(&msg
, NULL
, WM_USER
, WM_USER
, PM_NOREMOVE
);
647 SetEvent(data
->marshal_event
);
649 while (GetMessageA(&msg
, NULL
, 0, 0))
651 if (msg
.hwnd
== NULL
&& msg
.message
== RELEASEMARSHALDATA
)
653 CoReleaseMarshalData(data
->stream
);
654 SetEvent((HANDLE
)msg
.lParam
);
657 DispatchMessageA(&msg
);
660 HeapFree(GetProcessHeap(), 0, data
);
667 static DWORD
start_host_object2(struct host_object_data
*object_data
, HANDLE
*thread
)
670 struct host_object_data
*data
;
672 data
= HeapAlloc(GetProcessHeap(), 0, sizeof(*data
));
673 *data
= *object_data
;
674 data
->marshal_event
= CreateEventA(NULL
, FALSE
, FALSE
, NULL
);
675 *thread
= CreateThread(NULL
, 0, host_object_proc
, data
, 0, &tid
);
677 /* wait for marshaling to complete before returning */
678 ok( !WaitForSingleObject(data
->marshal_event
, 10000), "wait timed out\n" );
679 CloseHandle(data
->marshal_event
);
684 static DWORD
start_host_object(IStream
*stream
, REFIID riid
, IUnknown
*object
, MSHLFLAGS marshal_flags
, HANDLE
*thread
)
686 struct host_object_data object_data
= { stream
, riid
, object
, marshal_flags
};
687 return start_host_object2(&object_data
, thread
);
690 /* asks thread to release the marshal data because it has to be done by the
691 * same thread that marshaled the interface in the first place. */
692 static void release_host_object(DWORD tid
, WPARAM wp
)
694 HANDLE event
= CreateEventA(NULL
, FALSE
, FALSE
, NULL
);
695 PostThreadMessageA(tid
, RELEASEMARSHALDATA
, wp
, (LPARAM
)event
);
696 ok( !WaitForSingleObject(event
, 10000), "wait timed out\n" );
700 static void end_host_object(DWORD tid
, HANDLE thread
)
702 BOOL ret
= PostThreadMessageA(tid
, WM_QUIT
, 0, 0);
703 ok(ret
, "PostThreadMessage failed with error %d\n", GetLastError());
704 /* be careful of races - don't return until hosting thread has terminated */
705 ok( !WaitForSingleObject(thread
, 10000), "wait timed out\n" );
709 /* tests failure case of interface not having a marshaler specified in the
711 static void test_no_marshaler(void)
716 hr
= CreateStreamOnHGlobal(NULL
, TRUE
, &pStream
);
717 ok_ole_success(hr
, CreateStreamOnHGlobal
);
718 hr
= CoMarshalInterface(pStream
, &IID_IWineTest
, (IUnknown
*)&Test_ClassFactory
, MSHCTX_INPROC
, NULL
, MSHLFLAGS_NORMAL
);
719 ok(hr
== E_NOINTERFACE
, "CoMarshalInterface should have returned E_NOINTERFACE instead of 0x%08x\n", hr
);
721 IStream_Release(pStream
);
724 /* tests normal marshal and then release without unmarshaling */
725 static void test_normal_marshal_and_release(void)
728 IStream
*pStream
= NULL
;
731 external_connections
= 0;
733 hr
= CreateStreamOnHGlobal(NULL
, TRUE
, &pStream
);
734 ok_ole_success(hr
, CreateStreamOnHGlobal
);
735 hr
= CoMarshalInterface(pStream
, &IID_IClassFactory
, (IUnknown
*)&Test_ClassFactory
, MSHCTX_INPROC
, NULL
, MSHLFLAGS_NORMAL
);
736 ok_ole_success(hr
, CoMarshalInterface
);
738 ok_more_than_one_lock();
739 ok_non_zero_external_conn();
741 IStream_Seek(pStream
, ullZero
, STREAM_SEEK_SET
, NULL
);
742 hr
= CoReleaseMarshalData(pStream
);
743 ok_ole_success(hr
, CoReleaseMarshalData
);
744 IStream_Release(pStream
);
747 ok_zero_external_conn();
748 ok_last_release_closes(TRUE
);
751 /* tests success case of a same-thread marshal and unmarshal */
752 static void test_normal_marshal_and_unmarshal(void)
755 IStream
*pStream
= NULL
;
756 IUnknown
*pProxy
= NULL
;
759 external_connections
= 0;
761 hr
= CreateStreamOnHGlobal(NULL
, TRUE
, &pStream
);
762 ok_ole_success(hr
, CreateStreamOnHGlobal
);
763 hr
= CoMarshalInterface(pStream
, &IID_IClassFactory
, (IUnknown
*)&Test_ClassFactory
, MSHCTX_INPROC
, NULL
, MSHLFLAGS_NORMAL
);
764 ok_ole_success(hr
, CoMarshalInterface
);
766 ok_more_than_one_lock();
767 ok_non_zero_external_conn();
769 IStream_Seek(pStream
, ullZero
, STREAM_SEEK_SET
, NULL
);
770 hr
= CoUnmarshalInterface(pStream
, &IID_IClassFactory
, (void **)&pProxy
);
771 ok_ole_success(hr
, CoUnmarshalInterface
);
772 IStream_Release(pStream
);
774 ok_more_than_one_lock();
775 ok_zero_external_conn();
776 ok_last_release_closes(FALSE
);
778 IUnknown_Release(pProxy
);
783 /* tests failure case of unmarshaling a freed object */
784 static void test_marshal_and_unmarshal_invalid(void)
787 IStream
*pStream
= NULL
;
788 IClassFactory
*pProxy
= NULL
;
794 external_connections
= 0;
796 hr
= CreateStreamOnHGlobal(NULL
, TRUE
, &pStream
);
797 ok_ole_success(hr
, CreateStreamOnHGlobal
);
798 tid
= start_host_object(pStream
, &IID_IClassFactory
, (IUnknown
*)&Test_ClassFactory
, MSHLFLAGS_NORMAL
, &thread
);
800 ok_more_than_one_lock();
801 ok_non_zero_external_conn();
803 IStream_Seek(pStream
, ullZero
, STREAM_SEEK_SET
, NULL
);
804 hr
= CoReleaseMarshalData(pStream
);
805 ok_ole_success(hr
, CoReleaseMarshalData
);
808 ok_zero_external_conn();
809 ok_last_release_closes(TRUE
);
811 IStream_Seek(pStream
, ullZero
, STREAM_SEEK_SET
, NULL
);
812 hr
= CoUnmarshalInterface(pStream
, &IID_IClassFactory
, (void **)&pProxy
);
813 todo_wine
{ ok_ole_success(hr
, CoUnmarshalInterface
); }
819 hr
= IClassFactory_CreateInstance(pProxy
, NULL
, &IID_IUnknown
, &dummy
);
820 ok(hr
== RPC_E_DISCONNECTED
, "Remote call should have returned RPC_E_DISCONNECTED, instead of 0x%08x\n", hr
);
822 IClassFactory_Release(pProxy
);
825 IStream_Release(pStream
);
827 end_host_object(tid
, thread
);
830 static void test_same_apartment_unmarshal_failure(void)
835 static const LARGE_INTEGER llZero
;
838 external_connections
= 0;
840 hr
= CreateStreamOnHGlobal(NULL
, TRUE
, &pStream
);
841 ok_ole_success(hr
, CreateStreamOnHGlobal
);
843 hr
= CoMarshalInterface(pStream
, &IID_IUnknown
, (IUnknown
*)&Test_ClassFactory
, MSHCTX_INPROC
, NULL
, MSHLFLAGS_NORMAL
);
844 ok_ole_success(hr
, CoMarshalInterface
);
846 ok_more_than_one_lock();
847 ok_non_zero_external_conn();
849 hr
= IStream_Seek(pStream
, llZero
, STREAM_SEEK_SET
, NULL
);
850 ok_ole_success(hr
, IStream_Seek
);
852 hr
= CoUnmarshalInterface(pStream
, &IID_IParseDisplayName
, (void **)&pProxy
);
853 ok(hr
== E_NOINTERFACE
, "CoUnmarshalInterface should have returned E_NOINTERFACE instead of 0x%08x\n", hr
);
856 ok_zero_external_conn();
857 ok_last_release_closes(FALSE
);
859 IStream_Release(pStream
);
862 /* tests success case of an interthread marshal */
863 static void test_interthread_marshal_and_unmarshal(void)
866 IStream
*pStream
= NULL
;
867 IUnknown
*pProxy
= NULL
;
872 external_connections
= 0;
874 hr
= CreateStreamOnHGlobal(NULL
, TRUE
, &pStream
);
875 ok_ole_success(hr
, CreateStreamOnHGlobal
);
876 tid
= start_host_object(pStream
, &IID_IClassFactory
, (IUnknown
*)&Test_ClassFactory
, MSHLFLAGS_NORMAL
, &thread
);
878 ok_more_than_one_lock();
879 ok_non_zero_external_conn();
881 IStream_Seek(pStream
, ullZero
, STREAM_SEEK_SET
, NULL
);
882 hr
= CoUnmarshalInterface(pStream
, &IID_IClassFactory
, (void **)&pProxy
);
883 ok_ole_success(hr
, CoUnmarshalInterface
);
884 IStream_Release(pStream
);
886 ok_more_than_one_lock();
887 ok_non_zero_external_conn();
889 IUnknown_Release(pProxy
);
892 ok_zero_external_conn();
893 ok_last_release_closes(TRUE
);
895 end_host_object(tid
, thread
);
898 /* the number of external references that Wine's proxy manager normally gives
899 * out, so we can test the border case of running out of references */
900 #define NORMALEXTREFS 5
902 /* tests success case of an interthread marshal and then marshaling the proxy */
903 static void test_proxy_marshal_and_unmarshal(void)
906 IStream
*pStream
= NULL
;
907 IUnknown
*pProxy
= NULL
;
908 IUnknown
*pProxy2
= NULL
;
914 external_connections
= 0;
916 hr
= CreateStreamOnHGlobal(NULL
, TRUE
, &pStream
);
917 ok_ole_success(hr
, CreateStreamOnHGlobal
);
918 tid
= start_host_object(pStream
, &IID_IClassFactory
, (IUnknown
*)&Test_ClassFactory
, MSHLFLAGS_NORMAL
, &thread
);
920 ok_more_than_one_lock();
921 ok_non_zero_external_conn();
923 IStream_Seek(pStream
, ullZero
, STREAM_SEEK_SET
, NULL
);
924 hr
= CoUnmarshalInterface(pStream
, &IID_IClassFactory
, (void **)&pProxy
);
925 ok_ole_success(hr
, CoUnmarshalInterface
);
927 ok_more_than_one_lock();
929 IStream_Seek(pStream
, ullZero
, STREAM_SEEK_SET
, NULL
);
930 /* marshal the proxy */
931 hr
= CoMarshalInterface(pStream
, &IID_IClassFactory
, pProxy
, MSHCTX_INPROC
, NULL
, MSHLFLAGS_NORMAL
);
932 ok_ole_success(hr
, CoMarshalInterface
);
934 ok_more_than_one_lock();
936 /* marshal 5 more times to exhaust the normal external references of 5 */
937 for (i
= 0; i
< NORMALEXTREFS
; i
++)
939 hr
= CoMarshalInterface(pStream
, &IID_IClassFactory
, pProxy
, MSHCTX_INPROC
, NULL
, MSHLFLAGS_NORMAL
);
940 ok_ole_success(hr
, CoMarshalInterface
);
943 ok_more_than_one_lock();
945 /* release the original proxy to test that we successfully keep the
946 * original object alive */
947 IUnknown_Release(pProxy
);
949 IStream_Seek(pStream
, ullZero
, STREAM_SEEK_SET
, NULL
);
950 hr
= CoUnmarshalInterface(pStream
, &IID_IClassFactory
, (void **)&pProxy2
);
951 ok_ole_success(hr
, CoUnmarshalInterface
);
953 ok_more_than_one_lock();
954 ok_non_zero_external_conn();
956 IUnknown_Release(pProxy2
);
958 /* unmarshal all of the proxies to check that the object stub still exists */
959 for (i
= 0; i
< NORMALEXTREFS
; i
++)
961 hr
= CoUnmarshalInterface(pStream
, &IID_IClassFactory
, (void **)&pProxy2
);
962 ok_ole_success(hr
, CoUnmarshalInterface
);
964 IUnknown_Release(pProxy2
);
968 ok_zero_external_conn();
969 ok_last_release_closes(TRUE
);
971 IStream_Release(pStream
);
973 end_host_object(tid
, thread
);
976 /* tests success case of an interthread marshal and then marshaling the proxy
977 * using an iid that hasn't previously been unmarshaled */
978 static void test_proxy_marshal_and_unmarshal2(void)
981 IStream
*pStream
= NULL
;
982 IUnknown
*pProxy
= NULL
;
983 IUnknown
*pProxy2
= NULL
;
988 external_connections
= 0;
990 hr
= CreateStreamOnHGlobal(NULL
, TRUE
, &pStream
);
991 ok_ole_success(hr
, CreateStreamOnHGlobal
);
992 tid
= start_host_object(pStream
, &IID_IUnknown
, (IUnknown
*)&Test_ClassFactory
, MSHLFLAGS_NORMAL
, &thread
);
994 ok_more_than_one_lock();
995 ok_non_zero_external_conn();
997 IStream_Seek(pStream
, ullZero
, STREAM_SEEK_SET
, NULL
);
998 hr
= CoUnmarshalInterface(pStream
, &IID_IUnknown
, (void **)&pProxy
);
999 ok_ole_success(hr
, CoUnmarshalInterface
);
1001 ok_more_than_one_lock();
1003 IStream_Seek(pStream
, ullZero
, STREAM_SEEK_SET
, NULL
);
1004 /* marshal the proxy */
1005 hr
= CoMarshalInterface(pStream
, &IID_IClassFactory
, pProxy
, MSHCTX_INPROC
, NULL
, MSHLFLAGS_NORMAL
);
1006 ok_ole_success(hr
, CoMarshalInterface
);
1008 ok_more_than_one_lock();
1010 IStream_Seek(pStream
, ullZero
, STREAM_SEEK_SET
, NULL
);
1011 /* unmarshal the second proxy to the object */
1012 hr
= CoUnmarshalInterface(pStream
, &IID_IClassFactory
, (void **)&pProxy2
);
1013 ok_ole_success(hr
, CoUnmarshalInterface
);
1014 IStream_Release(pStream
);
1016 /* now the proxies should be as follows:
1017 * pProxy -> &Test_ClassFactory
1018 * pProxy2 -> &Test_ClassFactory
1019 * they should NOT be as follows:
1020 * pProxy -> &Test_ClassFactory
1022 * the above can only really be tested by looking in +ole traces
1025 ok_more_than_one_lock();
1027 IUnknown_Release(pProxy
);
1029 ok_more_than_one_lock();
1030 ok_non_zero_external_conn();
1032 IUnknown_Release(pProxy2
);
1035 ok_zero_external_conn();
1036 ok_last_release_closes(TRUE
);
1038 end_host_object(tid
, thread
);
1041 /* tests success case of an interthread marshal and then table-weak-marshaling the proxy */
1042 static void test_proxy_marshal_and_unmarshal_weak(void)
1045 IStream
*pStream
= NULL
;
1046 IUnknown
*pProxy
= NULL
;
1047 IUnknown
*pProxy2
= NULL
;
1052 external_connections
= 0;
1054 hr
= CreateStreamOnHGlobal(NULL
, TRUE
, &pStream
);
1055 ok_ole_success(hr
, CreateStreamOnHGlobal
);
1056 tid
= start_host_object(pStream
, &IID_IClassFactory
, (IUnknown
*)&Test_ClassFactory
, MSHLFLAGS_NORMAL
, &thread
);
1058 ok_more_than_one_lock();
1059 ok_non_zero_external_conn();
1061 IStream_Seek(pStream
, ullZero
, STREAM_SEEK_SET
, NULL
);
1062 hr
= CoUnmarshalInterface(pStream
, &IID_IClassFactory
, (void **)&pProxy
);
1063 ok_ole_success(hr
, CoUnmarshalInterface
);
1065 ok_more_than_one_lock();
1066 ok_non_zero_external_conn();
1068 IStream_Seek(pStream
, ullZero
, STREAM_SEEK_SET
, NULL
);
1069 /* marshal the proxy */
1070 hr
= CoMarshalInterface(pStream
, &IID_IClassFactory
, pProxy
, MSHCTX_INPROC
, NULL
, MSHLFLAGS_TABLEWEAK
);
1071 ok_ole_success(hr
, CoMarshalInterface
);
1073 ok_more_than_one_lock();
1074 ok_non_zero_external_conn();
1076 /* release the original proxy to test that we successfully keep the
1077 * original object alive */
1078 IUnknown_Release(pProxy
);
1080 IStream_Seek(pStream
, ullZero
, STREAM_SEEK_SET
, NULL
);
1081 hr
= CoUnmarshalInterface(pStream
, &IID_IClassFactory
, (void **)&pProxy2
);
1083 ok(hr
== CO_E_OBJNOTREG
, "CoUnmarshalInterface should return CO_E_OBJNOTREG instead of 0x%08x\n", hr
);
1086 ok_zero_external_conn();
1087 ok_last_release_closes(TRUE
);
1089 IStream_Release(pStream
);
1091 end_host_object(tid
, thread
);
1094 /* tests success case of an interthread marshal and then table-strong-marshaling the proxy */
1095 static void test_proxy_marshal_and_unmarshal_strong(void)
1098 IStream
*pStream
= NULL
;
1099 IUnknown
*pProxy
= NULL
;
1100 IUnknown
*pProxy2
= NULL
;
1105 external_connections
= 0;
1107 hr
= CreateStreamOnHGlobal(NULL
, TRUE
, &pStream
);
1108 ok_ole_success(hr
, CreateStreamOnHGlobal
);
1109 tid
= start_host_object(pStream
, &IID_IClassFactory
, (IUnknown
*)&Test_ClassFactory
, MSHLFLAGS_NORMAL
, &thread
);
1111 ok_more_than_one_lock();
1112 ok_non_zero_external_conn();
1114 IStream_Seek(pStream
, ullZero
, STREAM_SEEK_SET
, NULL
);
1115 hr
= CoUnmarshalInterface(pStream
, &IID_IClassFactory
, (void **)&pProxy
);
1116 ok_ole_success(hr
, CoUnmarshalInterface
);
1118 ok_more_than_one_lock();
1119 ok_non_zero_external_conn();
1121 IStream_Seek(pStream
, ullZero
, STREAM_SEEK_SET
, NULL
);
1122 /* marshal the proxy */
1123 hr
= CoMarshalInterface(pStream
, &IID_IClassFactory
, pProxy
, MSHCTX_INPROC
, NULL
, MSHLFLAGS_TABLESTRONG
);
1124 ok(hr
== S_OK
/* WinNT */ || hr
== E_INVALIDARG
/* Win9x */,
1125 "CoMarshalInterface should have return S_OK or E_INVALIDARG instead of 0x%08x\n", hr
);
1128 IUnknown_Release(pProxy
);
1132 ok_more_than_one_lock();
1133 ok_non_zero_external_conn();
1135 /* release the original proxy to test that we successfully keep the
1136 * original object alive */
1137 IUnknown_Release(pProxy
);
1139 IStream_Seek(pStream
, ullZero
, STREAM_SEEK_SET
, NULL
);
1140 hr
= CoUnmarshalInterface(pStream
, &IID_IClassFactory
, (void **)&pProxy2
);
1141 ok_ole_success(hr
, CoUnmarshalInterface
);
1143 ok_more_than_one_lock();
1144 ok_non_zero_external_conn();
1146 IUnknown_Release(pProxy2
);
1148 ok_more_than_one_lock();
1149 ok_non_zero_external_conn();
1152 IStream_Release(pStream
);
1154 end_host_object(tid
, thread
);
1158 ok_zero_external_conn();
1159 ok_last_release_closes(FALSE
);
1163 /* tests that stubs are released when the containing apartment is destroyed */
1164 static void test_marshal_stub_apartment_shutdown(void)
1167 IStream
*pStream
= NULL
;
1168 IUnknown
*pProxy
= NULL
;
1173 external_connections
= 0;
1175 hr
= CreateStreamOnHGlobal(NULL
, TRUE
, &pStream
);
1176 ok_ole_success(hr
, CreateStreamOnHGlobal
);
1177 tid
= start_host_object(pStream
, &IID_IClassFactory
, (IUnknown
*)&Test_ClassFactory
, MSHLFLAGS_NORMAL
, &thread
);
1179 ok_more_than_one_lock();
1180 ok_non_zero_external_conn();
1182 IStream_Seek(pStream
, ullZero
, STREAM_SEEK_SET
, NULL
);
1183 hr
= CoUnmarshalInterface(pStream
, &IID_IClassFactory
, (void **)&pProxy
);
1184 ok_ole_success(hr
, CoUnmarshalInterface
);
1185 IStream_Release(pStream
);
1187 ok_more_than_one_lock();
1188 ok_non_zero_external_conn();
1190 end_host_object(tid
, thread
);
1194 ok_zero_external_conn();
1195 ok_last_release_closes(FALSE
);
1198 IUnknown_Release(pProxy
);
1203 /* tests that proxies are released when the containing apartment is destroyed */
1204 static void test_marshal_proxy_apartment_shutdown(void)
1207 IStream
*pStream
= NULL
;
1208 IUnknown
*pProxy
= NULL
;
1213 external_connections
= 0;
1215 hr
= CreateStreamOnHGlobal(NULL
, TRUE
, &pStream
);
1216 ok_ole_success(hr
, CreateStreamOnHGlobal
);
1217 tid
= start_host_object(pStream
, &IID_IClassFactory
, (IUnknown
*)&Test_ClassFactory
, MSHLFLAGS_NORMAL
, &thread
);
1219 ok_more_than_one_lock();
1220 ok_non_zero_external_conn();
1222 IStream_Seek(pStream
, ullZero
, STREAM_SEEK_SET
, NULL
);
1223 hr
= CoUnmarshalInterface(pStream
, &IID_IClassFactory
, (void **)&pProxy
);
1224 ok_ole_success(hr
, CoUnmarshalInterface
);
1225 IStream_Release(pStream
);
1227 ok_more_than_one_lock();
1228 ok_non_zero_external_conn();
1233 ok_zero_external_conn();
1234 ok_last_release_closes(TRUE
);
1236 IUnknown_Release(pProxy
);
1240 end_host_object(tid
, thread
);
1242 pCoInitializeEx(NULL
, COINIT_APARTMENTTHREADED
);
1245 /* tests that proxies are released when the containing mta apartment is destroyed */
1246 static void test_marshal_proxy_mta_apartment_shutdown(void)
1249 IStream
*pStream
= NULL
;
1250 IUnknown
*pProxy
= NULL
;
1255 pCoInitializeEx(NULL
, COINIT_MULTITHREADED
);
1258 external_connections
= 0;
1260 hr
= CreateStreamOnHGlobal(NULL
, TRUE
, &pStream
);
1261 ok_ole_success(hr
, CreateStreamOnHGlobal
);
1262 tid
= start_host_object(pStream
, &IID_IClassFactory
, (IUnknown
*)&Test_ClassFactory
, MSHLFLAGS_NORMAL
, &thread
);
1264 ok_more_than_one_lock();
1265 ok_non_zero_external_conn();
1267 IStream_Seek(pStream
, ullZero
, STREAM_SEEK_SET
, NULL
);
1268 hr
= CoUnmarshalInterface(pStream
, &IID_IClassFactory
, (void **)&pProxy
);
1269 ok_ole_success(hr
, CoUnmarshalInterface
);
1270 IStream_Release(pStream
);
1272 ok_more_than_one_lock();
1273 ok_non_zero_external_conn();
1278 ok_zero_external_conn();
1279 ok_last_release_closes(TRUE
);
1281 IUnknown_Release(pProxy
);
1285 end_host_object(tid
, thread
);
1287 pCoInitializeEx(NULL
, COINIT_APARTMENTTHREADED
);
1290 static void test_marshal_channel_buffer(void)
1292 DWORD registration_key
;
1293 IUnknown
*proxy
= NULL
;
1294 IOleWindow
*ole_window
;
1301 struct host_object_data object_data
= { NULL
, &IID_IOleClientSite
, (IUnknown
*)&Test_OleClientSite
,
1302 MSHLFLAGS_NORMAL
, NULL
, (IUnknown
*)&PSFactoryBuffer
,
1303 &CLSID_WineTestPSFactoryBuffer
};
1306 external_connections
= 0;
1308 hr
= CoGetPSClsid(&IID_IOleWindow
, &clsid
);
1309 ok_ole_success(hr
, "CoGetPSClsid");
1311 hr
= CoGetClassObject(&clsid
, CLSCTX_INPROC_SERVER
, NULL
, &IID_IPSFactoryBuffer
,
1312 (void **)&ps_factory_buffer
);
1313 ok_ole_success(hr
, "CoGetClassObject");
1315 hr
= CreateStreamOnHGlobal(NULL
, TRUE
, &object_data
.stream
);
1316 ok_ole_success(hr
, CreateStreamOnHGlobal
);
1317 tid
= start_host_object2(&object_data
, &thread
);
1319 IStream_Seek(object_data
.stream
, ullZero
, STREAM_SEEK_SET
, NULL
);
1320 hr
= CoUnmarshalInterface(object_data
.stream
, &IID_IUnknown
, (void **)&proxy
);
1321 ok_ole_success(hr
, CoUnmarshalInterface
);
1322 IStream_Release(object_data
.stream
);
1324 hr
= CoRegisterClassObject(&CLSID_WineTestPSFactoryBuffer
, (IUnknown
*)&PSFactoryBuffer
,
1325 CLSCTX_INPROC_SERVER
, REGCLS_MULTIPLEUSE
, ®istration_key
);
1326 ok(hr
== S_OK
, "CoRegisterClassObject failed: %08x\n", hr
);
1328 hr
= CoRegisterPSClsid(&IID_IOleWindow
, &CLSID_WineTestPSFactoryBuffer
);
1329 ok(hr
== S_OK
, "CoRegisterPSClsid failed: %08x\n", hr
);
1331 SET_EXPECT(CreateStub
);
1332 SET_EXPECT(CreateProxy
);
1333 hr
= IUnknown_QueryInterface(proxy
, &IID_IOleWindow
, (void**)&ole_window
);
1334 ok(hr
== S_OK
, "Could not get IOleWindow iface: %08x\n", hr
);
1335 CHECK_CALLED(CreateStub
);
1336 CHECK_CALLED(CreateProxy
);
1339 SET_EXPECT(GetWindow
);
1340 hr
= IOleWindow_GetWindow(ole_window
, &hwnd
);
1341 ok(hr
== S_OK
, "GetWindow failed: %08x\n", hr
);
1342 ok((DWORD
)(DWORD_PTR
)hwnd
== 0xdeadbeef, "hwnd = %p\n", hwnd
);
1343 CHECK_CALLED(Invoke
);
1344 CHECK_CALLED(GetWindow
);
1346 IOleWindow_Release(ole_window
);
1348 SET_EXPECT(Disconnect
);
1349 IUnknown_Release(proxy
);
1351 CHECK_CALLED(Disconnect
);
1353 hr
= CoRevokeClassObject(registration_key
);
1354 ok(hr
== S_OK
, "CoRevokeClassObject failed: %08x\n", hr
);
1356 end_host_object(tid
, thread
);
1359 static const CLSID
*unmarshal_class
;
1360 DEFINE_EXPECT(CustomMarshal_GetUnmarshalClass
);
1361 DEFINE_EXPECT(CustomMarshal_GetMarshalSizeMax
);
1362 DEFINE_EXPECT(CustomMarshal_MarshalInterface
);
1364 static HRESULT WINAPI
CustomMarshal_QueryInterface(IMarshal
*iface
, REFIID riid
, void **ppv
)
1366 if (IsEqualIID(riid
, &IID_IUnknown
) || IsEqualIID(riid
, &IID_IMarshal
)) {
1372 return E_NOINTERFACE
;
1374 IUnknown_AddRef((IUnknown
*)*ppv
);
1378 static ULONG WINAPI
CustomMarshal_AddRef(IMarshal
*iface
)
1383 static ULONG WINAPI
CustomMarshal_Release(IMarshal
*iface
)
1388 static HRESULT WINAPI
CustomMarshal_GetUnmarshalClass(IMarshal
*iface
, REFIID riid
,
1389 void *pv
, DWORD dwDestContext
, void *pvDestContext
, DWORD mshlflags
, CLSID
*clsid
)
1391 CHECK_EXPECT(CustomMarshal_GetUnmarshalClass
);
1392 *clsid
= *unmarshal_class
;
1396 static HRESULT WINAPI
CustomMarshal_GetMarshalSizeMax(IMarshal
*iface
, REFIID riid
,
1397 void *pv
, DWORD dwDestContext
, void *pvDestContext
, DWORD mshlflags
, DWORD
*size
)
1399 CHECK_EXPECT(CustomMarshal_GetMarshalSizeMax
);
1400 ok(size
!= NULL
, "size = NULL\n");
1406 static HRESULT WINAPI
CustomMarshal_MarshalInterface(IMarshal
*iface
, IStream
*stream
,
1407 REFIID riid
, void *pv
, DWORD dwDestContext
, void *pvDestContext
, DWORD mshlflags
)
1409 IMarshal
*std_marshal
;
1413 CHECK_EXPECT(CustomMarshal_MarshalInterface
);
1415 if(unmarshal_class
!= &CLSID_StdMarshal
)
1418 hr
= IStream_Stat(stream
, &stat
, STATFLAG_DEFAULT
);
1419 ok_ole_success(hr
, IStream_Stat
);
1420 ok(U(stat
.cbSize
).LowPart
== 0, "stream is not empty (%d)\n", U(stat
.cbSize
).LowPart
);
1421 ok(U(stat
.cbSize
).HighPart
== 0, "stream is not empty (%d)\n", U(stat
.cbSize
).HighPart
);
1423 hr
= CoGetStandardMarshal(riid
, (IUnknown
*)iface
,
1424 dwDestContext
, NULL
, mshlflags
, &std_marshal
);
1425 ok_ole_success(hr
, CoGetStandardMarshal
);
1426 hr
= IMarshal_MarshalInterface(std_marshal
, stream
, riid
, pv
,
1427 dwDestContext
, pvDestContext
, mshlflags
);
1428 ok_ole_success(hr
, IMarshal_MarshalInterface
);
1429 IMarshal_Release(std_marshal
);
1434 static HRESULT WINAPI
CustomMarshal_UnmarshalInterface(IMarshal
*iface
,
1435 IStream
*stream
, REFIID riid
, void **ppv
)
1437 ok(0, "unexpected call\n");
1441 static HRESULT WINAPI
CustomMarshal_ReleaseMarshalData(IMarshal
*iface
, IStream
*stream
)
1443 ok(0, "unexpected call\n");
1447 static HRESULT WINAPI
CustomMarshal_DisconnectObject(IMarshal
*iface
, DWORD res
)
1449 ok(0, "unexpected call\n");
1453 static IMarshalVtbl CustomMarshalVtbl
=
1455 CustomMarshal_QueryInterface
,
1456 CustomMarshal_AddRef
,
1457 CustomMarshal_Release
,
1458 CustomMarshal_GetUnmarshalClass
,
1459 CustomMarshal_GetMarshalSizeMax
,
1460 CustomMarshal_MarshalInterface
,
1461 CustomMarshal_UnmarshalInterface
,
1462 CustomMarshal_ReleaseMarshalData
,
1463 CustomMarshal_DisconnectObject
1466 static IMarshal CustomMarshal
= { &CustomMarshalVtbl
};
1468 static void test_StdMarshal_custom_marshaling(void)
1475 hr
= CreateStreamOnHGlobal(NULL
, TRUE
, &stream
);
1476 ok_ole_success(hr
, CreateStreamOnHGlobal
);
1478 unmarshal_class
= &CLSID_StdMarshal
;
1479 SET_EXPECT(CustomMarshal_GetUnmarshalClass
);
1480 SET_EXPECT(CustomMarshal_MarshalInterface
);
1481 hr
= CoMarshalInterface(stream
, &IID_IUnknown
, (IUnknown
*)&CustomMarshal
,
1482 MSHCTX_INPROC
, NULL
, MSHLFLAGS_NORMAL
);
1483 ok_ole_success(hr
, CoMarshalInterface
);
1484 CHECK_CALLED(CustomMarshal_GetUnmarshalClass
);
1485 CHECK_CALLED(CustomMarshal_MarshalInterface
);
1487 hr
= IStream_Seek(stream
, ullZero
, STREAM_SEEK_SET
, NULL
);
1488 ok_ole_success(hr
, IStream_Seek
);
1489 hr
= CoUnmarshalInterface(stream
, &IID_IUnknown
, (void**)&unk
);
1490 ok_ole_success(hr
, CoUnmarshalInterface
);
1491 ok(unk
== (IUnknown
*)&CustomMarshal
, "unk != &CustomMarshal\n");
1492 IUnknown_Release(unk
);
1493 IStream_Release(stream
);
1495 hr
= CreateStreamOnHGlobal(NULL
, TRUE
, &stream
);
1496 ok_ole_success(hr
, CreateStreamOnHGlobal
);
1498 SET_EXPECT(CustomMarshal_GetUnmarshalClass
);
1499 SET_EXPECT(CustomMarshal_MarshalInterface
);
1500 hr
= CoMarshalInterface(stream
, &IID_IUnknown
, (IUnknown
*)&CustomMarshal
,
1501 MSHCTX_INPROC
, NULL
, MSHLFLAGS_NORMAL
);
1502 ok_ole_success(hr
, CoMarshalInterface
);
1503 CHECK_CALLED(CustomMarshal_GetUnmarshalClass
);
1504 CHECK_CALLED(CustomMarshal_MarshalInterface
);
1506 hr
= IStream_Seek(stream
, ullZero
, STREAM_SEEK_SET
, NULL
);
1507 ok_ole_success(hr
, IStream_Seek
);
1508 hr
= CoReleaseMarshalData(stream
);
1509 ok_ole_success(hr
, CoReleaseMarshalData
);
1510 IStream_Release(stream
);
1512 SET_EXPECT(CustomMarshal_GetMarshalSizeMax
);
1513 hr
= CoGetMarshalSizeMax(&size
, &IID_IUnknown
, (IUnknown
*)&CustomMarshal
,
1514 MSHCTX_INPROC
, NULL
, MSHLFLAGS_NORMAL
);
1515 ok_ole_success(hr
, CoGetMarshalSizeMax
);
1516 CHECK_CALLED(CustomMarshal_GetMarshalSizeMax
);
1517 ok(size
== sizeof(OBJREF
), "size = %d, expected %d\n", size
, (int)sizeof(OBJREF
));
1520 static void test_DfMarshal_custom_marshaling(void)
1527 hr
= CreateStreamOnHGlobal(NULL
, TRUE
, &stream
);
1528 ok_ole_success(hr
, CreateStreamOnHGlobal
);
1530 unmarshal_class
= &CLSID_DfMarshal
;
1531 SET_EXPECT(CustomMarshal_GetUnmarshalClass
);
1532 SET_EXPECT(CustomMarshal_GetMarshalSizeMax
);
1533 SET_EXPECT(CustomMarshal_MarshalInterface
);
1534 hr
= CoMarshalInterface(stream
, &IID_IUnknown
, (IUnknown
*)&CustomMarshal
,
1535 MSHCTX_INPROC
, NULL
, MSHLFLAGS_NORMAL
);
1536 ok_ole_success(hr
, CoMarshalInterface
);
1537 CHECK_CALLED(CustomMarshal_GetUnmarshalClass
);
1538 CHECK_CALLED(CustomMarshal_GetMarshalSizeMax
);
1539 CHECK_CALLED(CustomMarshal_MarshalInterface
);
1541 hr
= IStream_Seek(stream
, ullZero
, STREAM_SEEK_SET
, NULL
);
1542 ok_ole_success(hr
, IStream_Seek
);
1543 size
= FIELD_OFFSET(OBJREF
, u_objref
.u_custom
.pData
);
1544 hr
= IStream_Read(stream
, &objref
, size
, &read
);
1545 ok_ole_success(hr
, IStream_Read
);
1546 ok(read
== size
, "read = %d, expected %d\n", read
, size
);
1547 ok(objref
.signature
== OBJREF_SIGNATURE
, "objref.signature = %x\n",
1549 ok(objref
.flags
== OBJREF_CUSTOM
, "objref.flags = %x\n", objref
.flags
);
1550 ok(IsEqualIID(&objref
.iid
, &IID_IUnknown
), "objref.iid = %s\n",
1551 wine_dbgstr_guid(&objref
.iid
));
1552 ok(IsEqualIID(&objref
.u_objref
.u_custom
.clsid
, &CLSID_DfMarshal
),
1553 "custom.clsid = %s\n", wine_dbgstr_guid(&objref
.u_objref
.u_custom
.clsid
));
1554 ok(!objref
.u_objref
.u_custom
.cbExtension
, "custom.cbExtension = %d\n",
1555 objref
.u_objref
.u_custom
.cbExtension
);
1556 ok(!objref
.u_objref
.u_custom
.size
, "custom.size = %d\n",
1557 objref
.u_objref
.u_custom
.size
);
1559 IStream_Release(stream
);
1561 SET_EXPECT(CustomMarshal_GetMarshalSizeMax
);
1562 hr
= CoGetMarshalSizeMax(&size
, &IID_IUnknown
, (IUnknown
*)&CustomMarshal
,
1563 MSHCTX_INPROC
, NULL
, MSHLFLAGS_NORMAL
);
1564 ok_ole_success(hr
, CoGetMarshalSizeMax
);
1565 CHECK_CALLED(CustomMarshal_GetMarshalSizeMax
);
1566 ok(size
== sizeof(OBJREF
), "size = %d, expected %d\n", size
, (int)sizeof(OBJREF
));
1569 static void test_CoGetStandardMarshal(void)
1571 DUALSTRINGARRAY
*dualstringarr
;
1572 STDOBJREF
*stdobjref
;
1581 hr
= CreateStreamOnHGlobal(NULL
, TRUE
, &stream
);
1582 ok_ole_success(hr
, CreateStreamOnHGlobal
);
1584 hr
= CoGetStandardMarshal(&IID_IUnknown
, &Test_Unknown
,
1585 MSHCTX_INPROC
, NULL
, MSHLFLAGS_NORMAL
, &marshal
);
1586 ok_ole_success(hr
, CoGetStandardMarshal
);
1588 hr
= IMarshal_GetUnmarshalClass(marshal
, &IID_IUnknown
, &Test_Unknown
,
1589 MSHCTX_INPROC
, NULL
, MSHLFLAGS_NORMAL
, &clsid
);
1590 ok_ole_success(hr
, IMarshal_GetUnmarshalClass
);
1591 ok(IsEqualGUID(&clsid
, &CLSID_StdMarshal
), "clsid = %s\n", wine_dbgstr_guid(&clsid
));
1593 hr
= IMarshal_GetMarshalSizeMax(marshal
, &IID_IUnknown
, &Test_Unknown
,
1594 MSHCTX_INPROC
, NULL
, MSHLFLAGS_NORMAL
, &size
);
1595 ok_ole_success(hr
, IMarshal_GetMarshalSizeMax
);
1596 hr
= CoGetMarshalSizeMax(&read
, &IID_IUnknown
, &Test_Unknown
,
1597 MSHCTX_INPROC
, NULL
, MSHLFLAGS_NORMAL
);
1598 ok_ole_success(hr
, CoGetMarshalSizeMax
);
1599 ok(size
== read
, "IMarshal_GetMarshalSizeMax size = %d, expected %d\n", size
, read
);
1601 hr
= IMarshal_MarshalInterface(marshal
, stream
, &IID_IUnknown
,
1602 &Test_Unknown
, MSHCTX_INPROC
, NULL
, MSHLFLAGS_NORMAL
);
1603 ok_ole_success(hr
, IMarshal_MarshalInterface
);
1605 hr
= IStream_Seek(stream
, ullZero
, STREAM_SEEK_SET
, NULL
);
1606 ok_ole_success(hr
, IStream_Seek
);
1607 size
= FIELD_OFFSET(OBJREF
, u_objref
.u_standard
.saResAddr
.aStringArray
);
1608 hr
= IStream_Read(stream
, &objref
, size
, &read
);
1609 ok_ole_success(hr
, IStream_Read
);
1610 ok(read
== size
, "read = %d, expected %d\n", read
, size
);
1611 ok(objref
.signature
== OBJREF_SIGNATURE
, "objref.signature = %x\n",
1613 ok(objref
.flags
== OBJREF_STANDARD
, "objref.flags = %x\n", objref
.flags
);
1614 ok(IsEqualIID(&objref
.iid
, &IID_IUnknown
), "objref.iid = %s\n",
1615 wine_dbgstr_guid(&objref
.iid
));
1616 stdobjref
= &objref
.u_objref
.u_standard
.std
;
1617 ok(stdobjref
->flags
== 0, "stdobjref.flags = %d\n", stdobjref
->flags
);
1618 ok(stdobjref
->cPublicRefs
== 5, "stdobjref.cPublicRefs = %d\n",
1619 stdobjref
->cPublicRefs
);
1620 dualstringarr
= &objref
.u_objref
.u_standard
.saResAddr
;
1621 ok(dualstringarr
->wNumEntries
== 0, "dualstringarr.wNumEntries = %d\n",
1622 dualstringarr
->wNumEntries
);
1623 ok(dualstringarr
->wSecurityOffset
== 0, "dualstringarr.wSecurityOffset = %d\n",
1624 dualstringarr
->wSecurityOffset
);
1626 hr
= IStream_Seek(stream
, ullZero
, STREAM_SEEK_SET
, NULL
);
1627 ok_ole_success(hr
, IStream_Seek
);
1628 hr
= IMarshal_UnmarshalInterface(marshal
, stream
, &IID_IUnknown
, (void**)&unk
);
1629 ok_ole_success(hr
, IMarshal_UnmarshalInterface
);
1630 IUnknown_Release(unk
);
1632 hr
= IStream_Seek(stream
, ullZero
, STREAM_SEEK_SET
, NULL
);
1633 ok_ole_success(hr
, IStream_Seek
);
1634 hr
= IMarshal_MarshalInterface(marshal
, stream
, &IID_IUnknown
,
1635 &Test_Unknown
, MSHCTX_INPROC
, NULL
, MSHLFLAGS_NORMAL
);
1636 ok_ole_success(hr
, IMarshal_MarshalInterface
);
1638 hr
= IStream_Seek(stream
, ullZero
, STREAM_SEEK_SET
, NULL
);
1639 ok_ole_success(hr
, IStream_Seek
);
1640 hr
= IMarshal_ReleaseMarshalData(marshal
, stream
);
1641 ok_ole_success(hr
, IMarshal_ReleaseMarshalData
);
1642 IStream_Release(stream
);
1644 IMarshal_Release(marshal
);
1649 HANDLE marshal_event
;
1650 HANDLE unmarshal_event
;
1653 /* helper for test_no_couninitialize_server */
1654 static DWORD CALLBACK
no_couninitialize_server_proc(LPVOID p
)
1656 struct ncu_params
*ncu_params
= p
;
1659 pCoInitializeEx(NULL
, COINIT_MULTITHREADED
);
1661 hr
= CoMarshalInterface(ncu_params
->stream
, &IID_IClassFactory
, (IUnknown
*)&Test_ClassFactory
, MSHCTX_INPROC
, NULL
, MSHLFLAGS_NORMAL
);
1662 ok_ole_success(hr
, CoMarshalInterface
);
1664 SetEvent(ncu_params
->marshal_event
);
1666 ok( !WaitForSingleObject(ncu_params
->unmarshal_event
, 10000), "wait timed out\n" );
1668 /* die without calling CoUninitialize */
1673 /* tests apartment that an apartment with a stub is released without deadlock
1674 * if the owning thread exits */
1675 static void test_no_couninitialize_server(void)
1678 IStream
*pStream
= NULL
;
1679 IUnknown
*pProxy
= NULL
;
1682 struct ncu_params ncu_params
;
1685 external_connections
= 0;
1687 ncu_params
.marshal_event
= CreateEventA(NULL
, TRUE
, FALSE
, NULL
);
1688 ncu_params
.unmarshal_event
= CreateEventA(NULL
, TRUE
, FALSE
, NULL
);
1690 hr
= CreateStreamOnHGlobal(NULL
, TRUE
, &pStream
);
1691 ok_ole_success(hr
, CreateStreamOnHGlobal
);
1692 ncu_params
.stream
= pStream
;
1694 thread
= CreateThread(NULL
, 0, no_couninitialize_server_proc
, &ncu_params
, 0, &tid
);
1696 ok( !WaitForSingleObject(ncu_params
.marshal_event
, 10000), "wait timed out\n" );
1697 ok_more_than_one_lock();
1698 ok_non_zero_external_conn();
1700 IStream_Seek(pStream
, ullZero
, STREAM_SEEK_SET
, NULL
);
1701 hr
= CoUnmarshalInterface(pStream
, &IID_IClassFactory
, (void **)&pProxy
);
1702 ok_ole_success(hr
, CoUnmarshalInterface
);
1703 IStream_Release(pStream
);
1705 ok_more_than_one_lock();
1706 ok_non_zero_external_conn();
1708 SetEvent(ncu_params
.unmarshal_event
);
1709 ok( !WaitForSingleObject(thread
, 10000), "wait timed out\n" );
1713 ok_zero_external_conn();
1714 ok_last_release_closes(FALSE
);
1717 CloseHandle(thread
);
1718 CloseHandle(ncu_params
.marshal_event
);
1719 CloseHandle(ncu_params
.unmarshal_event
);
1721 IUnknown_Release(pProxy
);
1726 /* STA -> STA call during DLL_THREAD_DETACH */
1727 static DWORD CALLBACK
no_couninitialize_client_proc(LPVOID p
)
1729 struct ncu_params
*ncu_params
= p
;
1731 IUnknown
*pProxy
= NULL
;
1733 pCoInitializeEx(NULL
, COINIT_APARTMENTTHREADED
);
1735 hr
= CoUnmarshalInterface(ncu_params
->stream
, &IID_IClassFactory
, (void **)&pProxy
);
1736 ok_ole_success(hr
, CoUnmarshalInterface
);
1737 IStream_Release(ncu_params
->stream
);
1739 ok_more_than_one_lock();
1741 /* die without calling CoUninitialize */
1746 /* tests STA -> STA call during DLL_THREAD_DETACH doesn't deadlock */
1747 static void test_no_couninitialize_client(void)
1750 IStream
*pStream
= NULL
;
1755 struct ncu_params ncu_params
;
1758 external_connections
= 0;
1760 hr
= CreateStreamOnHGlobal(NULL
, TRUE
, &pStream
);
1761 ok_ole_success(hr
, CreateStreamOnHGlobal
);
1762 ncu_params
.stream
= pStream
;
1764 /* NOTE: assumes start_host_object uses an STA to host the object, as MTAs
1765 * always deadlock when called from within DllMain */
1766 host_tid
= start_host_object(pStream
, &IID_IClassFactory
, (IUnknown
*)&Test_ClassFactory
, MSHLFLAGS_NORMAL
, &host_thread
);
1767 IStream_Seek(pStream
, ullZero
, STREAM_SEEK_SET
, NULL
);
1769 ok_more_than_one_lock();
1770 ok_non_zero_external_conn();
1772 thread
= CreateThread(NULL
, 0, no_couninitialize_client_proc
, &ncu_params
, 0, &tid
);
1774 ok( !WaitForSingleObject(thread
, 10000), "wait timed out\n" );
1775 CloseHandle(thread
);
1778 ok_zero_external_conn();
1779 ok_last_release_closes(TRUE
);
1781 end_host_object(host_tid
, host_thread
);
1784 static BOOL crash_thread_success
;
1786 static DWORD CALLBACK
crash_couninitialize_proc(void *p
)
1795 hr
= CreateStreamOnHGlobal(NULL
, TRUE
, &stream
);
1796 ok_ole_success(hr
, CreateStreamOnHGlobal
);
1798 hr
= CoMarshalInterface(stream
, &IID_IUnknown
, &TestCrash_Unknown
, MSHCTX_INPROC
, NULL
, MSHLFLAGS_NORMAL
);
1799 ok_ole_success(hr
, CoMarshalInterface
);
1801 IStream_Seek(stream
, ullZero
, STREAM_SEEK_SET
, NULL
);
1803 hr
= CoReleaseMarshalData(stream
);
1804 ok_ole_success(hr
, CoReleaseMarshalData
);
1808 hr
= CoMarshalInterface(stream
, &IID_IUnknown
, &TestCrash_Unknown
, MSHCTX_INPROC
, NULL
, MSHLFLAGS_NORMAL
);
1809 ok_ole_success(hr
, CoMarshalInterface
);
1811 ok_more_than_one_lock();
1813 trace("CoUninitialize >>>\n");
1815 trace("CoUninitialize <<<\n");
1819 IStream_Release(stream
);
1820 crash_thread_success
= TRUE
;
1824 static void test_crash_couninitialize(void)
1829 if(!GetProcAddress(GetModuleHandleA("kernel32.dll"), "CreateActCtxW")) {
1830 win_skip("Skipping crash tests on win2k.\n");
1834 crash_thread_success
= FALSE
;
1835 thread
= CreateThread(NULL
, 0, crash_couninitialize_proc
, NULL
, 0, &tid
);
1836 ok(!WaitForSingleObject(thread
, 10000), "wait timed out\n");
1837 CloseHandle(thread
);
1838 ok(crash_thread_success
, "Crash thread failed\n");
1841 /* tests success case of a same-thread table-weak marshal, unmarshal, unmarshal */
1842 static void test_tableweak_marshal_and_unmarshal_twice(void)
1845 IStream
*pStream
= NULL
;
1846 IUnknown
*pProxy1
= NULL
;
1847 IUnknown
*pProxy2
= NULL
;
1852 external_connections
= 0;
1854 hr
= CreateStreamOnHGlobal(NULL
, TRUE
, &pStream
);
1855 ok_ole_success(hr
, CreateStreamOnHGlobal
);
1856 tid
= start_host_object(pStream
, &IID_IClassFactory
, (IUnknown
*)&Test_ClassFactory
, MSHLFLAGS_TABLEWEAK
, &thread
);
1858 ok_more_than_one_lock();
1859 ok_zero_external_conn();
1861 IStream_Seek(pStream
, ullZero
, STREAM_SEEK_SET
, NULL
);
1862 hr
= CoUnmarshalInterface(pStream
, &IID_IClassFactory
, (void **)&pProxy1
);
1863 ok_ole_success(hr
, CoUnmarshalInterface
);
1865 ok_more_than_one_lock();
1866 ok_non_zero_external_conn();
1868 IStream_Seek(pStream
, ullZero
, STREAM_SEEK_SET
, NULL
);
1869 hr
= CoUnmarshalInterface(pStream
, &IID_IClassFactory
, (void **)&pProxy2
);
1870 ok_ole_success(hr
, CoUnmarshalInterface
);
1872 ok_more_than_one_lock();
1874 IUnknown_Release(pProxy1
);
1875 ok_non_zero_external_conn();
1876 IUnknown_Release(pProxy2
);
1877 ok_zero_external_conn();
1878 ok_last_release_closes(TRUE
);
1880 /* When IExternalConnection is present COM's lifetime management
1881 * behaviour is altered; the remaining weak ref prevents stub shutdown. */
1882 if (with_external_conn
)
1884 ok_more_than_one_lock();
1885 IStream_Seek(pStream
, ullZero
, STREAM_SEEK_SET
, NULL
);
1886 release_host_object(tid
, 0);
1889 /* Without IExternalConnection this line is shows the difference between weak and strong table marshaling
1890 * weak has cLocks == 0, strong has cLocks > 0. */
1893 IStream_Release(pStream
);
1894 end_host_object(tid
, thread
);
1897 /* tests releasing after unmarshaling one object */
1898 static void test_tableweak_marshal_releasedata1(void)
1901 IStream
*pStream
= NULL
;
1902 IUnknown
*pProxy1
= NULL
;
1903 IUnknown
*pProxy2
= NULL
;
1908 external_connections
= 0;
1910 hr
= CreateStreamOnHGlobal(NULL
, TRUE
, &pStream
);
1911 ok_ole_success(hr
, CreateStreamOnHGlobal
);
1912 tid
= start_host_object(pStream
, &IID_IClassFactory
, (IUnknown
*)&Test_ClassFactory
, MSHLFLAGS_TABLEWEAK
, &thread
);
1914 ok_more_than_one_lock();
1915 ok_zero_external_conn();
1917 IStream_Seek(pStream
, ullZero
, STREAM_SEEK_SET
, NULL
);
1918 hr
= CoUnmarshalInterface(pStream
, &IID_IClassFactory
, (void **)&pProxy1
);
1919 ok_ole_success(hr
, CoUnmarshalInterface
);
1921 ok_more_than_one_lock();
1922 ok_non_zero_external_conn();
1924 /* release the remaining reference on the object by calling
1925 * CoReleaseMarshalData in the hosting thread */
1926 IStream_Seek(pStream
, ullZero
, STREAM_SEEK_SET
, NULL
);
1927 release_host_object(tid
, 0);
1929 ok_more_than_one_lock();
1930 ok_non_zero_external_conn();
1932 IStream_Seek(pStream
, ullZero
, STREAM_SEEK_SET
, NULL
);
1933 hr
= CoUnmarshalInterface(pStream
, &IID_IClassFactory
, (void **)&pProxy2
);
1934 ok_ole_success(hr
, CoUnmarshalInterface
);
1935 IStream_Release(pStream
);
1937 ok_more_than_one_lock();
1938 ok_non_zero_external_conn();
1940 IUnknown_Release(pProxy1
);
1944 ok_non_zero_external_conn();
1945 IUnknown_Release(pProxy2
);
1948 /* this line is shows the difference between weak and strong table marshaling:
1949 * weak has cLocks == 0
1950 * strong has cLocks > 0 */
1952 ok_zero_external_conn();
1953 ok_last_release_closes(TRUE
);
1955 end_host_object(tid
, thread
);
1958 /* tests releasing after unmarshaling one object */
1959 static void test_tableweak_marshal_releasedata2(void)
1962 IStream
*pStream
= NULL
;
1963 IUnknown
*pProxy
= NULL
;
1968 external_connections
= 0;
1970 hr
= CreateStreamOnHGlobal(NULL
, TRUE
, &pStream
);
1971 ok_ole_success(hr
, CreateStreamOnHGlobal
);
1972 tid
= start_host_object(pStream
, &IID_IClassFactory
, (IUnknown
*)&Test_ClassFactory
, MSHLFLAGS_TABLEWEAK
, &thread
);
1974 ok_more_than_one_lock();
1975 ok_zero_external_conn();
1977 /* release the remaining reference on the object by calling
1978 * CoReleaseMarshalData in the hosting thread */
1979 IStream_Seek(pStream
, ullZero
, STREAM_SEEK_SET
, NULL
);
1980 release_host_object(tid
, 0);
1984 IStream_Seek(pStream
, ullZero
, STREAM_SEEK_SET
, NULL
);
1985 hr
= CoUnmarshalInterface(pStream
, &IID_IClassFactory
, (void **)&pProxy
);
1988 ok(hr
== CO_E_OBJNOTREG
,
1989 "CoUnmarshalInterface should have failed with CO_E_OBJNOTREG, but returned 0x%08x instead\n",
1992 IStream_Release(pStream
);
1995 ok_zero_external_conn();
1997 end_host_object(tid
, thread
);
2000 struct duo_marshal_data
2002 MSHLFLAGS marshal_flags1
, marshal_flags2
;
2003 IStream
*pStream1
, *pStream2
;
2008 static DWORD CALLBACK
duo_marshal_thread_proc(void *p
)
2011 struct duo_marshal_data
*data
= p
;
2012 HANDLE hQuitEvent
= data
->hQuitEvent
;
2015 pCoInitializeEx(NULL
, COINIT_APARTMENTTHREADED
);
2017 hr
= CoMarshalInterface(data
->pStream1
, &IID_IClassFactory
, (IUnknown
*)&Test_ClassFactory
, MSHCTX_INPROC
, NULL
, data
->marshal_flags1
);
2018 ok_ole_success(hr
, "CoMarshalInterface");
2020 hr
= CoMarshalInterface(data
->pStream2
, &IID_IClassFactory
, (IUnknown
*)&Test_ClassFactory
, MSHCTX_INPROC
, NULL
, data
->marshal_flags2
);
2021 ok_ole_success(hr
, "CoMarshalInterface");
2023 /* force the message queue to be created before signaling parent thread */
2024 PeekMessageA(&msg
, NULL
, WM_USER
, WM_USER
, PM_NOREMOVE
);
2026 SetEvent(data
->hReadyEvent
);
2028 while (WAIT_OBJECT_0
+ 1 == MsgWaitForMultipleObjects(1, &hQuitEvent
, FALSE
, 10000, QS_ALLINPUT
))
2030 while (PeekMessageA(&msg
, NULL
, 0, 0, PM_REMOVE
))
2032 if (msg
.hwnd
== NULL
&& msg
.message
== RELEASEMARSHALDATA
)
2034 CoReleaseMarshalData(msg
.wParam
== 1 ? data
->pStream1
: data
->pStream2
);
2035 SetEvent((HANDLE
)msg
.lParam
);
2038 DispatchMessageA(&msg
);
2041 CloseHandle(hQuitEvent
);
2048 /* tests interaction between table-weak and normal marshalling of an object */
2049 static void test_tableweak_and_normal_marshal_and_unmarshal(void)
2052 IUnknown
*pProxyWeak
= NULL
;
2053 IUnknown
*pProxyNormal
= NULL
;
2056 struct duo_marshal_data data
;
2059 external_connections
= 0;
2061 data
.hReadyEvent
= CreateEventA(NULL
, FALSE
, FALSE
, NULL
);
2062 data
.hQuitEvent
= CreateEventA(NULL
, FALSE
, FALSE
, NULL
);
2063 data
.marshal_flags1
= MSHLFLAGS_TABLEWEAK
;
2064 data
.marshal_flags2
= MSHLFLAGS_NORMAL
;
2065 hr
= CreateStreamOnHGlobal(NULL
, TRUE
, &data
.pStream1
);
2066 ok_ole_success(hr
, CreateStreamOnHGlobal
);
2067 hr
= CreateStreamOnHGlobal(NULL
, TRUE
, &data
.pStream2
);
2068 ok_ole_success(hr
, CreateStreamOnHGlobal
);
2070 thread
= CreateThread(NULL
, 0, duo_marshal_thread_proc
, &data
, 0, &tid
);
2071 ok( !WaitForSingleObject(data
.hReadyEvent
, 10000), "wait timed out\n" );
2072 CloseHandle(data
.hReadyEvent
);
2074 ok_more_than_one_lock();
2075 ok_non_zero_external_conn();
2078 IStream_Seek(data
.pStream1
, ullZero
, STREAM_SEEK_SET
, NULL
);
2079 hr
= CoUnmarshalInterface(data
.pStream1
, &IID_IClassFactory
, (void **)&pProxyWeak
);
2080 ok_ole_success(hr
, CoUnmarshalInterface
);
2082 ok_more_than_one_lock();
2085 IStream_Seek(data
.pStream2
, ullZero
, STREAM_SEEK_SET
, NULL
);
2086 hr
= CoUnmarshalInterface(data
.pStream2
, &IID_IClassFactory
, (void **)&pProxyNormal
);
2087 ok_ole_success(hr
, CoUnmarshalInterface
);
2089 ok_more_than_one_lock();
2091 IUnknown_Release(pProxyNormal
);
2093 ok_more_than_one_lock();
2094 ok_non_zero_external_conn();
2096 IUnknown_Release(pProxyWeak
);
2098 ok_zero_external_conn();
2099 ok_last_release_closes(TRUE
);
2101 /* When IExternalConnection is present COM's lifetime management
2102 * behaviour is altered; the remaining weak ref prevents stub shutdown. */
2103 if (with_external_conn
)
2105 ok_more_than_one_lock();
2106 IStream_Seek(data
.pStream1
, ullZero
, STREAM_SEEK_SET
, NULL
);
2107 release_host_object(tid
, 1);
2111 IStream_Release(data
.pStream1
);
2112 IStream_Release(data
.pStream2
);
2114 SetEvent(data
.hQuitEvent
);
2115 ok( !WaitForSingleObject(thread
, 10000), "wait timed out\n" );
2116 CloseHandle(thread
);
2119 static void test_tableweak_and_normal_marshal_and_releasedata(void)
2124 struct duo_marshal_data data
;
2127 external_connections
= 0;
2129 data
.hReadyEvent
= CreateEventA(NULL
, FALSE
, FALSE
, NULL
);
2130 data
.hQuitEvent
= CreateEventA(NULL
, FALSE
, FALSE
, NULL
);
2131 data
.marshal_flags1
= MSHLFLAGS_TABLEWEAK
;
2132 data
.marshal_flags2
= MSHLFLAGS_NORMAL
;
2133 hr
= CreateStreamOnHGlobal(NULL
, TRUE
, &data
.pStream1
);
2134 ok_ole_success(hr
, CreateStreamOnHGlobal
);
2135 hr
= CreateStreamOnHGlobal(NULL
, TRUE
, &data
.pStream2
);
2136 ok_ole_success(hr
, CreateStreamOnHGlobal
);
2138 thread
= CreateThread(NULL
, 0, duo_marshal_thread_proc
, &data
, 0, &tid
);
2139 ok( !WaitForSingleObject(data
.hReadyEvent
, 10000), "wait timed out\n" );
2140 CloseHandle(data
.hReadyEvent
);
2142 ok_more_than_one_lock();
2143 ok_non_zero_external_conn();
2145 /* release normal - which in the non-external conn case will free the object despite the weak ref. */
2146 IStream_Seek(data
.pStream2
, ullZero
, STREAM_SEEK_SET
, NULL
);
2147 release_host_object(tid
, 2);
2149 ok_zero_external_conn();
2150 ok_last_release_closes(TRUE
);
2152 if (with_external_conn
)
2154 ok_more_than_one_lock();
2155 IStream_Seek(data
.pStream1
, ullZero
, STREAM_SEEK_SET
, NULL
);
2156 release_host_object(tid
, 1);
2161 IStream_Release(data
.pStream1
);
2162 IStream_Release(data
.pStream2
);
2164 SetEvent(data
.hQuitEvent
);
2165 ok( !WaitForSingleObject(thread
, 10000), "wait timed out\n" );
2166 CloseHandle(thread
);
2169 static void test_two_tableweak_marshal_and_releasedata(void)
2174 struct duo_marshal_data data
;
2177 external_connections
= 0;
2179 data
.hReadyEvent
= CreateEventA(NULL
, FALSE
, FALSE
, NULL
);
2180 data
.hQuitEvent
= CreateEventA(NULL
, FALSE
, FALSE
, NULL
);
2181 data
.marshal_flags1
= MSHLFLAGS_TABLEWEAK
;
2182 data
.marshal_flags2
= MSHLFLAGS_TABLEWEAK
;
2183 hr
= CreateStreamOnHGlobal(NULL
, TRUE
, &data
.pStream1
);
2184 ok_ole_success(hr
, CreateStreamOnHGlobal
);
2185 hr
= CreateStreamOnHGlobal(NULL
, TRUE
, &data
.pStream2
);
2186 ok_ole_success(hr
, CreateStreamOnHGlobal
);
2188 thread
= CreateThread(NULL
, 0, duo_marshal_thread_proc
, &data
, 0, &tid
);
2189 ok( !WaitForSingleObject(data
.hReadyEvent
, 10000), "wait timed out\n" );
2190 CloseHandle(data
.hReadyEvent
);
2192 ok_more_than_one_lock();
2193 ok_zero_external_conn();
2195 /* release one weak ref - the remaining weak ref will keep the obj alive */
2196 IStream_Seek(data
.pStream1
, ullZero
, STREAM_SEEK_SET
, NULL
);
2197 release_host_object(tid
, 1);
2199 ok_more_than_one_lock();
2201 IStream_Seek(data
.pStream2
, ullZero
, STREAM_SEEK_SET
, NULL
);
2202 release_host_object(tid
, 2);
2206 IStream_Release(data
.pStream1
);
2207 IStream_Release(data
.pStream2
);
2209 SetEvent(data
.hQuitEvent
);
2210 ok( !WaitForSingleObject(thread
, 10000), "wait timed out\n" );
2211 CloseHandle(thread
);
2214 /* tests success case of a same-thread table-strong marshal, unmarshal, unmarshal */
2215 static void test_tablestrong_marshal_and_unmarshal_twice(void)
2218 IStream
*pStream
= NULL
;
2219 IUnknown
*pProxy1
= NULL
;
2220 IUnknown
*pProxy2
= NULL
;
2225 external_connections
= 0;
2227 hr
= CreateStreamOnHGlobal(NULL
, TRUE
, &pStream
);
2228 ok_ole_success(hr
, CreateStreamOnHGlobal
);
2229 tid
= start_host_object(pStream
, &IID_IClassFactory
, (IUnknown
*)&Test_ClassFactory
, MSHLFLAGS_TABLESTRONG
, &thread
);
2231 ok_more_than_one_lock();
2232 ok_non_zero_external_conn();
2234 IStream_Seek(pStream
, ullZero
, STREAM_SEEK_SET
, NULL
);
2235 hr
= CoUnmarshalInterface(pStream
, &IID_IClassFactory
, (void **)&pProxy1
);
2236 ok_ole_success(hr
, CoUnmarshalInterface
);
2238 ok_more_than_one_lock();
2240 IStream_Seek(pStream
, ullZero
, STREAM_SEEK_SET
, NULL
);
2241 hr
= CoUnmarshalInterface(pStream
, &IID_IClassFactory
, (void **)&pProxy2
);
2242 ok_ole_success(hr
, CoUnmarshalInterface
);
2244 ok_more_than_one_lock();
2246 if (pProxy1
) IUnknown_Release(pProxy1
);
2247 if (pProxy2
) IUnknown_Release(pProxy2
);
2249 /* this line is shows the difference between weak and strong table marshaling:
2250 * weak has cLocks == 0
2251 * strong has cLocks > 0 */
2252 ok_more_than_one_lock();
2254 /* release the remaining reference on the object by calling
2255 * CoReleaseMarshalData in the hosting thread */
2256 IStream_Seek(pStream
, ullZero
, STREAM_SEEK_SET
, NULL
);
2257 release_host_object(tid
, 0);
2258 IStream_Release(pStream
);
2261 ok_zero_external_conn();
2262 ok_last_release_closes(TRUE
);
2264 end_host_object(tid
, thread
);
2267 /* tests CoLockObjectExternal */
2268 static void test_lock_object_external(void)
2271 IStream
*pStream
= NULL
;
2274 external_connections
= 0;
2276 /* test the stub manager creation aspect of CoLockObjectExternal when the
2277 * object hasn't been marshaled yet */
2278 CoLockObjectExternal((IUnknown
*)&Test_ClassFactory
, TRUE
, TRUE
);
2280 ok_more_than_one_lock();
2281 ok_non_zero_external_conn();
2283 CoDisconnectObject((IUnknown
*)&Test_ClassFactory
, 0);
2286 ok_non_zero_external_conn();
2287 external_connections
= 0;
2289 /* test our empty stub manager being handled correctly in
2290 * CoMarshalInterface */
2291 CoLockObjectExternal((IUnknown
*)&Test_ClassFactory
, TRUE
, TRUE
);
2293 hr
= CreateStreamOnHGlobal(NULL
, TRUE
, &pStream
);
2294 ok_ole_success(hr
, CreateStreamOnHGlobal
);
2295 hr
= CoMarshalInterface(pStream
, &IID_IClassFactory
, (IUnknown
*)&Test_ClassFactory
, MSHCTX_INPROC
, NULL
, MSHLFLAGS_NORMAL
);
2296 ok_ole_success(hr
, CoMarshalInterface
);
2298 CoLockObjectExternal((IUnknown
*)&Test_ClassFactory
, TRUE
, TRUE
);
2300 ok_more_than_one_lock();
2301 ok_non_zero_external_conn();
2303 IStream_Seek(pStream
, ullZero
, STREAM_SEEK_SET
, NULL
);
2304 hr
= CoReleaseMarshalData(pStream
);
2305 ok_ole_success(hr
, CoReleaseMarshalData
);
2306 IStream_Seek(pStream
, ullZero
, STREAM_SEEK_SET
, NULL
);
2308 ok_more_than_one_lock();
2309 ok_non_zero_external_conn();
2310 ok_last_release_closes(TRUE
);
2312 CoLockObjectExternal((IUnknown
*)&Test_ClassFactory
, FALSE
, TRUE
);
2314 ok_more_than_one_lock();
2315 ok_non_zero_external_conn();
2316 ok_last_release_closes(TRUE
);
2318 CoLockObjectExternal((IUnknown
*)&Test_ClassFactory
, FALSE
, TRUE
);
2321 ok_zero_external_conn();
2322 ok_last_release_closes(TRUE
);
2324 /* test CoLockObjectExternal releases reference to object with
2325 * fLastUnlockReleases as TRUE and there are only strong references on
2327 CoLockObjectExternal((IUnknown
*)&Test_ClassFactory
, TRUE
, FALSE
);
2329 ok_more_than_one_lock();
2330 ok_non_zero_external_conn();
2332 CoLockObjectExternal((IUnknown
*)&Test_ClassFactory
, FALSE
, FALSE
);
2335 ok_zero_external_conn();
2336 ok_last_release_closes(FALSE
);
2338 /* test CoLockObjectExternal doesn't release the last reference to an
2339 * object with fLastUnlockReleases as TRUE and there is a weak reference
2341 hr
= CoMarshalInterface(pStream
, &IID_IClassFactory
, (IUnknown
*)&Test_ClassFactory
, MSHCTX_INPROC
, NULL
, MSHLFLAGS_TABLEWEAK
);
2342 ok_ole_success(hr
, CoMarshalInterface
);
2344 ok_more_than_one_lock();
2345 ok_zero_external_conn();
2347 CoLockObjectExternal((IUnknown
*)&Test_ClassFactory
, TRUE
, FALSE
);
2349 ok_more_than_one_lock();
2350 ok_non_zero_external_conn();
2352 CoLockObjectExternal((IUnknown
*)&Test_ClassFactory
, FALSE
, FALSE
);
2354 ok_more_than_one_lock();
2355 ok_zero_external_conn();
2356 ok_last_release_closes(FALSE
);
2358 CoDisconnectObject((IUnknown
*)&Test_ClassFactory
, 0);
2362 IStream_Release(pStream
);
2365 /* tests disconnecting stubs */
2366 static void test_disconnect_stub(void)
2369 IStream
*pStream
= NULL
;
2372 external_connections
= 0;
2374 hr
= CreateStreamOnHGlobal(NULL
, TRUE
, &pStream
);
2375 ok_ole_success(hr
, CreateStreamOnHGlobal
);
2376 hr
= CoMarshalInterface(pStream
, &IID_IClassFactory
, (IUnknown
*)&Test_ClassFactory
, MSHCTX_INPROC
, NULL
, MSHLFLAGS_NORMAL
);
2377 ok_ole_success(hr
, CoMarshalInterface
);
2379 ok_non_zero_external_conn();
2381 CoLockObjectExternal((IUnknown
*)&Test_ClassFactory
, TRUE
, TRUE
);
2383 ok_more_than_one_lock();
2384 ok_non_zero_external_conn();
2386 IStream_Seek(pStream
, ullZero
, STREAM_SEEK_SET
, NULL
);
2387 hr
= CoReleaseMarshalData(pStream
);
2388 ok_ole_success(hr
, CoReleaseMarshalData
);
2389 IStream_Release(pStream
);
2391 ok_more_than_one_lock();
2392 ok_non_zero_external_conn();
2394 CoDisconnectObject((IUnknown
*)&Test_ClassFactory
, 0);
2397 ok_non_zero_external_conn();
2399 hr
= CoDisconnectObject(NULL
, 0);
2400 ok( hr
== E_INVALIDARG
, "wrong status %x\n", hr
);
2403 /* tests failure case of a same-thread marshal and unmarshal twice */
2404 static void test_normal_marshal_and_unmarshal_twice(void)
2407 IStream
*pStream
= NULL
;
2408 IUnknown
*pProxy1
= NULL
;
2409 IUnknown
*pProxy2
= NULL
;
2412 external_connections
= 0;
2414 hr
= CreateStreamOnHGlobal(NULL
, TRUE
, &pStream
);
2415 ok_ole_success(hr
, CreateStreamOnHGlobal
);
2416 hr
= CoMarshalInterface(pStream
, &IID_IClassFactory
, (IUnknown
*)&Test_ClassFactory
, MSHCTX_INPROC
, NULL
, MSHLFLAGS_NORMAL
);
2417 ok_ole_success(hr
, CoMarshalInterface
);
2419 ok_more_than_one_lock();
2420 ok_non_zero_external_conn();
2422 IStream_Seek(pStream
, ullZero
, STREAM_SEEK_SET
, NULL
);
2423 hr
= CoUnmarshalInterface(pStream
, &IID_IClassFactory
, (void **)&pProxy1
);
2424 ok_ole_success(hr
, CoUnmarshalInterface
);
2426 ok_more_than_one_lock();
2427 ok_zero_external_conn();
2428 ok_last_release_closes(FALSE
);
2430 IStream_Seek(pStream
, ullZero
, STREAM_SEEK_SET
, NULL
);
2431 hr
= CoUnmarshalInterface(pStream
, &IID_IClassFactory
, (void **)&pProxy2
);
2432 ok(hr
== CO_E_OBJNOTCONNECTED
,
2433 "CoUnmarshalInterface should have failed with error CO_E_OBJNOTCONNECTED for double unmarshal, instead of 0x%08x\n", hr
);
2435 IStream_Release(pStream
);
2437 ok_more_than_one_lock();
2439 IUnknown_Release(pProxy1
);
2444 /* tests success case of marshaling and unmarshaling an HRESULT */
2445 static void test_hresult_marshaling(void)
2448 HRESULT hr_marshaled
= 0;
2449 IStream
*pStream
= NULL
;
2450 static const HRESULT E_DEADBEEF
= 0xdeadbeef;
2452 hr
= CreateStreamOnHGlobal(NULL
, TRUE
, &pStream
);
2453 ok_ole_success(hr
, CreateStreamOnHGlobal
);
2455 hr
= CoMarshalHresult(pStream
, E_DEADBEEF
);
2456 ok_ole_success(hr
, CoMarshalHresult
);
2458 IStream_Seek(pStream
, ullZero
, STREAM_SEEK_SET
, NULL
);
2459 hr
= IStream_Read(pStream
, &hr_marshaled
, sizeof(HRESULT
), NULL
);
2460 ok_ole_success(hr
, IStream_Read
);
2462 ok(hr_marshaled
== E_DEADBEEF
, "Didn't marshal HRESULT as expected: got value 0x%08x instead\n", hr_marshaled
);
2465 IStream_Seek(pStream
, ullZero
, STREAM_SEEK_SET
, NULL
);
2466 hr
= CoUnmarshalHresult(pStream
, &hr_marshaled
);
2467 ok_ole_success(hr
, CoUnmarshalHresult
);
2469 ok(hr_marshaled
== E_DEADBEEF
, "Didn't marshal HRESULT as expected: got value 0x%08x instead\n", hr_marshaled
);
2471 IStream_Release(pStream
);
2475 /* helper for test_proxy_used_in_wrong_thread */
2476 static DWORD CALLBACK
bad_thread_proc(LPVOID p
)
2478 IClassFactory
* cf
= p
;
2480 IUnknown
* proxy
= NULL
;
2482 hr
= IClassFactory_CreateInstance(cf
, NULL
, &IID_IUnknown
, (LPVOID
*)&proxy
);
2484 ok(hr
== CO_E_NOTINITIALIZED
,
2485 "COM should have failed with CO_E_NOTINITIALIZED on using proxy without apartment, but instead returned 0x%08x\n",
2488 hr
= IClassFactory_QueryInterface(cf
, &IID_IMultiQI
, (LPVOID
*)&proxy
);
2489 /* Win9x returns S_OK, whilst NT returns RPC_E_WRONG_THREAD */
2490 trace("call to proxy's QueryInterface for local interface without apartment returned 0x%08x\n", hr
);
2492 IUnknown_Release(proxy
);
2494 hr
= IClassFactory_QueryInterface(cf
, &IID_IStream
, (LPVOID
*)&proxy
);
2495 /* Win9x returns E_NOINTERFACE, whilst NT returns RPC_E_WRONG_THREAD */
2496 trace("call to proxy's QueryInterface without apartment returned 0x%08x\n", hr
);
2498 IUnknown_Release(proxy
);
2500 pCoInitializeEx(NULL
, COINIT_MULTITHREADED
);
2502 hr
= IClassFactory_CreateInstance(cf
, NULL
, &IID_IUnknown
, (LPVOID
*)&proxy
);
2503 if (proxy
) IUnknown_Release(proxy
);
2504 ok(hr
== RPC_E_WRONG_THREAD
,
2505 "COM should have failed with RPC_E_WRONG_THREAD on using proxy from wrong apartment, but instead returned 0x%08x\n",
2508 hr
= IClassFactory_QueryInterface(cf
, &IID_IStream
, (LPVOID
*)&proxy
);
2509 /* Win9x returns E_NOINTERFACE, whilst NT returns RPC_E_WRONG_THREAD */
2510 trace("call to proxy's QueryInterface from wrong apartment returned 0x%08x\n", hr
);
2512 /* now be really bad and release the proxy from the wrong apartment */
2513 IClassFactory_Release(cf
);
2520 /* tests failure case of a using a proxy in the wrong apartment */
2521 static void test_proxy_used_in_wrong_thread(void)
2524 IStream
*pStream
= NULL
;
2525 IUnknown
*pProxy
= NULL
;
2532 hr
= CreateStreamOnHGlobal(NULL
, TRUE
, &pStream
);
2533 ok_ole_success(hr
, CreateStreamOnHGlobal
);
2534 tid
= start_host_object(pStream
, &IID_IClassFactory
, (IUnknown
*)&Test_ClassFactory
, MSHLFLAGS_NORMAL
, &host_thread
);
2536 ok_more_than_one_lock();
2538 IStream_Seek(pStream
, ullZero
, STREAM_SEEK_SET
, NULL
);
2539 hr
= CoUnmarshalInterface(pStream
, &IID_IClassFactory
, (void **)&pProxy
);
2540 ok_ole_success(hr
, CoUnmarshalInterface
);
2541 IStream_Release(pStream
);
2543 ok_more_than_one_lock();
2545 /* do a call that will fail, but result in IRemUnknown being used by the proxy */
2546 IUnknown_QueryInterface(pProxy
, &IID_IStream
, (LPVOID
*)&pStream
);
2548 /* create a thread that we can misbehave in */
2549 thread
= CreateThread(NULL
, 0, bad_thread_proc
, pProxy
, 0, &tid2
);
2551 ok( !WaitForSingleObject(thread
, 10000), "wait timed out\n" );
2552 CloseHandle(thread
);
2554 /* do release statement on Win9x that we should have done above */
2555 if (!GetProcAddress(GetModuleHandleA("ole32"), "CoRegisterSurrogateEx"))
2556 IUnknown_Release(pProxy
);
2560 end_host_object(tid
, host_thread
);
2563 static HRESULT WINAPI
MessageFilter_QueryInterface(IMessageFilter
*iface
, REFIID riid
, void ** ppvObj
)
2565 if (ppvObj
== NULL
) return E_POINTER
;
2567 if (IsEqualGUID(riid
, &IID_IUnknown
) ||
2568 IsEqualGUID(riid
, &IID_IClassFactory
))
2571 IMessageFilter_AddRef(iface
);
2575 return E_NOINTERFACE
;
2578 static ULONG WINAPI
MessageFilter_AddRef(IMessageFilter
*iface
)
2580 return 2; /* non-heap object */
2583 static ULONG WINAPI
MessageFilter_Release(IMessageFilter
*iface
)
2585 return 1; /* non-heap object */
2588 static DWORD WINAPI
MessageFilter_HandleInComingCall(
2589 IMessageFilter
*iface
,
2591 HTASK threadIDCaller
,
2593 LPINTERFACEINFO lpInterfaceInfo
)
2595 static int callcount
= 0;
2597 trace("HandleInComingCall\n");
2601 ret
= SERVERCALL_REJECTED
;
2604 ret
= SERVERCALL_RETRYLATER
;
2607 ret
= SERVERCALL_ISHANDLED
;
2614 static DWORD WINAPI
MessageFilter_RetryRejectedCall(
2615 IMessageFilter
*iface
,
2616 HTASK threadIDCallee
,
2620 trace("RetryRejectedCall\n");
2624 static DWORD WINAPI
MessageFilter_MessagePending(
2625 IMessageFilter
*iface
,
2626 HTASK threadIDCallee
,
2628 DWORD dwPendingType
)
2630 trace("MessagePending\n");
2631 return PENDINGMSG_WAITNOPROCESS
;
2634 static const IMessageFilterVtbl MessageFilter_Vtbl
=
2636 MessageFilter_QueryInterface
,
2637 MessageFilter_AddRef
,
2638 MessageFilter_Release
,
2639 MessageFilter_HandleInComingCall
,
2640 MessageFilter_RetryRejectedCall
,
2641 MessageFilter_MessagePending
2644 static IMessageFilter MessageFilter
= { &MessageFilter_Vtbl
};
2646 static void test_message_filter(void)
2649 IClassFactory
*cf
= NULL
;
2651 IUnknown
*proxy
= NULL
;
2652 IMessageFilter
*prev_filter
= NULL
;
2655 struct host_object_data object_data
= { NULL
, &IID_IClassFactory
, (IUnknown
*)&Test_ClassFactory
,
2656 MSHLFLAGS_NORMAL
, &MessageFilter
};
2660 hr
= CreateStreamOnHGlobal(NULL
, TRUE
, &object_data
.stream
);
2661 ok_ole_success(hr
, CreateStreamOnHGlobal
);
2662 tid
= start_host_object2(&object_data
, &thread
);
2664 ok_more_than_one_lock();
2666 IStream_Seek(object_data
.stream
, ullZero
, STREAM_SEEK_SET
, NULL
);
2667 hr
= CoUnmarshalInterface(object_data
.stream
, &IID_IClassFactory
, (void **)&cf
);
2668 ok_ole_success(hr
, CoUnmarshalInterface
);
2669 IStream_Release(object_data
.stream
);
2671 ok_more_than_one_lock();
2673 hr
= IClassFactory_CreateInstance(cf
, NULL
, &IID_IUnknown
, (LPVOID
*)&proxy
);
2674 ok(hr
== RPC_E_CALL_REJECTED
, "Call should have returned RPC_E_CALL_REJECTED, but return 0x%08x instead\n", hr
);
2675 if (proxy
) IUnknown_Release(proxy
);
2678 hr
= CoRegisterMessageFilter(&MessageFilter
, &prev_filter
);
2679 ok_ole_success(hr
, CoRegisterMessageFilter
);
2681 hr
= IClassFactory_CreateInstance(cf
, NULL
, &IID_IUnknown
, (LPVOID
*)&proxy
);
2682 ok_ole_success(hr
, IClassFactory_CreateInstance
);
2684 IUnknown_Release(proxy
);
2686 IClassFactory_Release(cf
);
2690 end_host_object(tid
, thread
);
2692 hr
= CoRegisterMessageFilter(prev_filter
, NULL
);
2693 ok_ole_success(hr
, CoRegisterMessageFilter
);
2696 /* test failure case of trying to unmarshal from bad stream */
2697 static void test_bad_marshal_stream(void)
2700 IStream
*pStream
= NULL
;
2702 hr
= CreateStreamOnHGlobal(NULL
, TRUE
, &pStream
);
2703 ok_ole_success(hr
, CreateStreamOnHGlobal
);
2704 hr
= CoMarshalInterface(pStream
, &IID_IClassFactory
, (IUnknown
*)&Test_ClassFactory
, MSHCTX_INPROC
, NULL
, MSHLFLAGS_NORMAL
);
2705 ok_ole_success(hr
, CoMarshalInterface
);
2707 ok_more_than_one_lock();
2709 /* try to read beyond end of stream */
2710 hr
= CoReleaseMarshalData(pStream
);
2711 ok(hr
== STG_E_READFAULT
, "Should have failed with STG_E_READFAULT, but returned 0x%08x instead\n", hr
);
2713 /* now release for real */
2714 IStream_Seek(pStream
, ullZero
, STREAM_SEEK_SET
, NULL
);
2715 hr
= CoReleaseMarshalData(pStream
);
2716 ok_ole_success(hr
, CoReleaseMarshalData
);
2718 IStream_Release(pStream
);
2721 /* tests that proxies implement certain interfaces */
2722 static void test_proxy_interfaces(void)
2725 IStream
*pStream
= NULL
;
2726 IUnknown
*pProxy
= NULL
;
2727 IUnknown
*pOtherUnknown
= NULL
;
2733 hr
= CreateStreamOnHGlobal(NULL
, TRUE
, &pStream
);
2734 ok_ole_success(hr
, CreateStreamOnHGlobal
);
2735 tid
= start_host_object(pStream
, &IID_IClassFactory
, (IUnknown
*)&Test_ClassFactory
, MSHLFLAGS_NORMAL
, &thread
);
2737 ok_more_than_one_lock();
2739 IStream_Seek(pStream
, ullZero
, STREAM_SEEK_SET
, NULL
);
2740 hr
= CoUnmarshalInterface(pStream
, &IID_IUnknown
, (void **)&pProxy
);
2741 ok_ole_success(hr
, CoUnmarshalInterface
);
2742 IStream_Release(pStream
);
2744 ok_more_than_one_lock();
2746 hr
= IUnknown_QueryInterface(pProxy
, &IID_IUnknown
, (LPVOID
*)&pOtherUnknown
);
2747 ok_ole_success(hr
, IUnknown_QueryInterface IID_IUnknown
);
2748 if (hr
== S_OK
) IUnknown_Release(pOtherUnknown
);
2750 hr
= IUnknown_QueryInterface(pProxy
, &IID_IClientSecurity
, (LPVOID
*)&pOtherUnknown
);
2751 ok_ole_success(hr
, IUnknown_QueryInterface IID_IClientSecurity
);
2752 if (hr
== S_OK
) IUnknown_Release(pOtherUnknown
);
2754 hr
= IUnknown_QueryInterface(pProxy
, &IID_IMultiQI
, (LPVOID
*)&pOtherUnknown
);
2755 ok_ole_success(hr
, IUnknown_QueryInterface IID_IMultiQI
);
2756 if (hr
== S_OK
) IUnknown_Release(pOtherUnknown
);
2758 hr
= IUnknown_QueryInterface(pProxy
, &IID_IMarshal
, (LPVOID
*)&pOtherUnknown
);
2759 ok_ole_success(hr
, IUnknown_QueryInterface IID_IMarshal
);
2760 if (hr
== S_OK
) IUnknown_Release(pOtherUnknown
);
2762 /* IMarshal2 is also supported on NT-based systems, but is pretty much
2763 * useless as it has no more methods over IMarshal that it inherits from. */
2765 IUnknown_Release(pProxy
);
2769 end_host_object(tid
, thread
);
2774 IUnknown IUnknown_iface
;
2778 static inline HeapUnknown
*impl_from_IUnknown(IUnknown
*iface
)
2780 return CONTAINING_RECORD(iface
, HeapUnknown
, IUnknown_iface
);
2783 static HRESULT WINAPI
HeapUnknown_QueryInterface(IUnknown
*iface
, REFIID riid
, void **ppv
)
2785 if (IsEqualIID(riid
, &IID_IUnknown
))
2787 IUnknown_AddRef(iface
);
2792 return E_NOINTERFACE
;
2795 static ULONG WINAPI
HeapUnknown_AddRef(IUnknown
*iface
)
2797 HeapUnknown
*This
= impl_from_IUnknown(iface
);
2798 return InterlockedIncrement((LONG
*)&This
->refs
);
2801 static ULONG WINAPI
HeapUnknown_Release(IUnknown
*iface
)
2803 HeapUnknown
*This
= impl_from_IUnknown(iface
);
2804 ULONG refs
= InterlockedDecrement((LONG
*)&This
->refs
);
2805 if (!refs
) HeapFree(GetProcessHeap(), 0, This
);
2809 static const IUnknownVtbl HeapUnknown_Vtbl
=
2811 HeapUnknown_QueryInterface
,
2816 static void test_proxybuffer(REFIID riid
)
2819 IPSFactoryBuffer
*psfb
;
2820 IRpcProxyBuffer
*proxy
;
2824 HeapUnknown
*pUnkOuter
= HeapAlloc(GetProcessHeap(), 0, sizeof(*pUnkOuter
));
2826 pUnkOuter
->IUnknown_iface
.lpVtbl
= &HeapUnknown_Vtbl
;
2827 pUnkOuter
->refs
= 1;
2829 hr
= CoGetPSClsid(riid
, &clsid
);
2830 ok_ole_success(hr
, CoGetPSClsid
);
2832 hr
= CoGetClassObject(&clsid
, CLSCTX_INPROC_SERVER
, NULL
, &IID_IPSFactoryBuffer
, (LPVOID
*)&psfb
);
2833 ok_ole_success(hr
, CoGetClassObject
);
2835 hr
= IPSFactoryBuffer_CreateProxy(psfb
, &pUnkOuter
->IUnknown_iface
, riid
, &proxy
, &lpvtbl
);
2836 ok_ole_success(hr
, IPSFactoryBuffer_CreateProxy
);
2837 ok(lpvtbl
!= NULL
, "IPSFactoryBuffer_CreateProxy succeeded, but returned a NULL vtable!\n");
2839 /* release our reference to the outer unknown object - the PS factory
2840 * buffer will have AddRef's it in the CreateProxy call */
2841 refs
= IUnknown_Release(&pUnkOuter
->IUnknown_iface
);
2842 ok(refs
== 1, "Ref count of outer unknown should have been 1 instead of %d\n", refs
);
2844 /* Not checking return, unreliable on native. Maybe it leaks references? */
2845 IPSFactoryBuffer_Release(psfb
);
2847 refs
= IUnknown_Release((IUnknown
*)lpvtbl
);
2848 ok(refs
== 0, "Ref-count leak of %d on IRpcProxyBuffer\n", refs
);
2850 refs
= IRpcProxyBuffer_Release(proxy
);
2851 ok(refs
== 0, "Ref-count leak of %d on IRpcProxyBuffer\n", refs
);
2854 static void test_stubbuffer(REFIID riid
)
2857 IPSFactoryBuffer
*psfb
;
2858 IRpcStubBuffer
*stub
;
2864 hr
= CoGetPSClsid(riid
, &clsid
);
2865 ok_ole_success(hr
, CoGetPSClsid
);
2867 hr
= CoGetClassObject(&clsid
, CLSCTX_INPROC_SERVER
, NULL
, &IID_IPSFactoryBuffer
, (LPVOID
*)&psfb
);
2868 ok_ole_success(hr
, CoGetClassObject
);
2870 hr
= IPSFactoryBuffer_CreateStub(psfb
, riid
, (IUnknown
*)&Test_ClassFactory
, &stub
);
2871 ok_ole_success(hr
, IPSFactoryBuffer_CreateStub
);
2873 /* Not checking return, unreliable on native. Maybe it leaks references? */
2874 IPSFactoryBuffer_Release(psfb
);
2876 ok_more_than_one_lock();
2878 IRpcStubBuffer_Disconnect(stub
);
2882 refs
= IRpcStubBuffer_Release(stub
);
2883 ok(refs
== 0, "Ref-count leak of %d on IRpcProxyBuffer\n", refs
);
2886 static HWND hwnd_app
;
2888 static HRESULT WINAPI
TestRE_IClassFactory_CreateInstance(
2889 LPCLASSFACTORY iface
,
2890 LPUNKNOWN pUnkOuter
,
2895 if (IsEqualIID(riid
, &IID_IWineTest
))
2897 BOOL ret
= SendMessageTimeoutA(hwnd_app
, WM_NULL
, 0, 0, SMTO_BLOCK
, 5000, &res
);
2898 ok(ret
, "Timed out sending a message to originating window during RPC call\n");
2904 static const IClassFactoryVtbl TestREClassFactory_Vtbl
=
2906 Test_IClassFactory_QueryInterface
,
2907 Test_IClassFactory_AddRef
,
2908 Test_IClassFactory_Release
,
2909 TestRE_IClassFactory_CreateInstance
,
2910 Test_IClassFactory_LockServer
2913 static IClassFactory TestRE_ClassFactory
= { &TestREClassFactory_Vtbl
};
2915 static LRESULT CALLBACK
window_proc(HWND hwnd
, UINT msg
, WPARAM wparam
, LPARAM lparam
)
2922 IStream
*pStream
= NULL
;
2923 IClassFactory
*proxy
= NULL
;
2930 hr
= CreateStreamOnHGlobal(NULL
, TRUE
, &pStream
);
2931 ok_ole_success(hr
, CreateStreamOnHGlobal
);
2932 tid
= start_host_object(pStream
, &IID_IClassFactory
, (IUnknown
*)&TestRE_ClassFactory
, MSHLFLAGS_NORMAL
, &thread
);
2934 ok_more_than_one_lock();
2936 IStream_Seek(pStream
, ullZero
, STREAM_SEEK_SET
, NULL
);
2937 hr
= CoUnmarshalInterface(pStream
, &IID_IClassFactory
, (void **)&proxy
);
2938 ok_ole_success(hr
, CoReleaseMarshalData
);
2939 IStream_Release(pStream
);
2941 ok_more_than_one_lock();
2943 /* note the use of the magic IID_IWineTest value to tell remote thread
2944 * to try to send a message back to us */
2945 hr
= IClassFactory_CreateInstance(proxy
, NULL
, &IID_IWineTest
, (void **)&object
);
2946 ok(hr
== S_FALSE
, "expected S_FALSE, got %d\n", hr
);
2948 IClassFactory_Release(proxy
);
2952 end_host_object(tid
, thread
);
2954 PostMessageA(hwnd
, WM_QUIT
, 0, 0);
2961 IStream
*pStream
= NULL
;
2962 IClassFactory
*proxy
= NULL
;
2969 hr
= CreateStreamOnHGlobal(NULL
, TRUE
, &pStream
);
2970 ok_ole_success(hr
, CreateStreamOnHGlobal
);
2971 tid
= start_host_object(pStream
, &IID_IClassFactory
, (IUnknown
*)&TestRE_ClassFactory
, MSHLFLAGS_NORMAL
, &thread
);
2973 ok_more_than_one_lock();
2975 IStream_Seek(pStream
, ullZero
, STREAM_SEEK_SET
, NULL
);
2976 hr
= CoUnmarshalInterface(pStream
, &IID_IClassFactory
, (void **)&proxy
);
2977 ok_ole_success(hr
, CoReleaseMarshalData
);
2978 IStream_Release(pStream
);
2980 ok_more_than_one_lock();
2982 /* post quit message before a doing a COM call to show that a pending
2983 * WM_QUIT message doesn't stop the call from succeeding */
2984 PostMessageA(hwnd
, WM_QUIT
, 0, 0);
2985 hr
= IClassFactory_CreateInstance(proxy
, NULL
, &IID_IUnknown
, (void **)&object
);
2986 ok(hr
== S_FALSE
, "IClassFactory_CreateInstance returned 0x%08x, expected S_FALSE\n", hr
);
2988 IClassFactory_Release(proxy
);
2992 end_host_object(tid
, thread
);
2999 IStream
*pStream
= NULL
;
3000 IClassFactory
*proxy
= NULL
;
3005 hr
= CreateStreamOnHGlobal(NULL
, TRUE
, &pStream
);
3006 ok_ole_success(hr
, CreateStreamOnHGlobal
);
3007 tid
= start_host_object(pStream
, &IID_IClassFactory
, (IUnknown
*)&Test_ClassFactory
, MSHLFLAGS_NORMAL
, &thread
);
3009 IStream_Seek(pStream
, ullZero
, STREAM_SEEK_SET
, NULL
);
3010 hr
= CoUnmarshalInterface(pStream
, &IID_IClassFactory
, (void **)&proxy
);
3011 ok_ole_success(hr
, CoReleaseMarshalData
);
3012 IStream_Release(pStream
);
3014 /* shows that COM calls executed during the processing of sent
3015 * messages should fail */
3016 hr
= IClassFactory_CreateInstance(proxy
, NULL
, &IID_IUnknown
, (void **)&object
);
3017 ok(hr
== RPC_E_CANTCALLOUT_ININPUTSYNCCALL
,
3018 "COM call during processing of sent message should return RPC_E_CANTCALLOUT_ININPUTSYNCCALL instead of 0x%08x\n", hr
);
3020 IClassFactory_Release(proxy
);
3022 end_host_object(tid
, thread
);
3029 return DefWindowProcA(hwnd
, msg
, wparam
, lparam
);
3033 static void register_test_window(void)
3037 memset(&wndclass
, 0, sizeof(wndclass
));
3038 wndclass
.lpfnWndProc
= window_proc
;
3039 wndclass
.lpszClassName
= "WineCOMTest";
3040 RegisterClassA(&wndclass
);
3043 static void test_message_reentrancy(void)
3047 hwnd_app
= CreateWindowA("WineCOMTest", NULL
, 0, CW_USEDEFAULT
, CW_USEDEFAULT
, CW_USEDEFAULT
, CW_USEDEFAULT
, NULL
, NULL
, NULL
, 0);
3048 ok(hwnd_app
!= NULL
, "Window creation failed\n");
3050 /* start message re-entrancy test */
3051 PostMessageA(hwnd_app
, WM_USER
, 0, 0);
3053 while (GetMessageA(&msg
, NULL
, 0, 0))
3055 TranslateMessage(&msg
);
3056 DispatchMessageA(&msg
);
3058 DestroyWindow(hwnd_app
);
3061 static HRESULT WINAPI
TestMsg_IClassFactory_CreateInstance(
3062 LPCLASSFACTORY iface
,
3063 LPUNKNOWN pUnkOuter
,
3068 SendMessageA(hwnd_app
, WM_USER
+2, 0, 0);
3072 static IClassFactoryVtbl TestMsgClassFactory_Vtbl
=
3074 Test_IClassFactory_QueryInterface
,
3075 Test_IClassFactory_AddRef
,
3076 Test_IClassFactory_Release
,
3077 TestMsg_IClassFactory_CreateInstance
,
3078 Test_IClassFactory_LockServer
3081 static IClassFactory TestMsg_ClassFactory
= { &TestMsgClassFactory_Vtbl
};
3083 static void test_call_from_message(void)
3088 IClassFactory
*proxy
;
3093 hwnd_app
= CreateWindowA("WineCOMTest", NULL
, 0, CW_USEDEFAULT
, CW_USEDEFAULT
, CW_USEDEFAULT
, CW_USEDEFAULT
, NULL
, NULL
, NULL
, 0);
3094 ok(hwnd_app
!= NULL
, "Window creation failed\n");
3096 hr
= CreateStreamOnHGlobal(NULL
, TRUE
, &pStream
);
3097 ok_ole_success(hr
, CreateStreamOnHGlobal
);
3098 tid
= start_host_object(pStream
, &IID_IClassFactory
, (IUnknown
*)&TestMsg_ClassFactory
, MSHLFLAGS_NORMAL
, &thread
);
3100 ok_more_than_one_lock();
3102 IStream_Seek(pStream
, ullZero
, STREAM_SEEK_SET
, NULL
);
3103 hr
= CoUnmarshalInterface(pStream
, &IID_IClassFactory
, (void **)&proxy
);
3104 ok_ole_success(hr
, CoReleaseMarshalData
);
3105 IStream_Release(pStream
);
3107 ok_more_than_one_lock();
3109 /* start message re-entrancy test */
3110 hr
= IClassFactory_CreateInstance(proxy
, NULL
, &IID_IUnknown
, (void **)&object
);
3111 ok_ole_success(hr
, IClassFactory_CreateInstance
);
3113 IClassFactory_Release(proxy
);
3117 end_host_object(tid
, thread
);
3119 while (GetMessageA(&msg
, NULL
, 0, 0))
3121 TranslateMessage(&msg
);
3122 DispatchMessageA(&msg
);
3124 DestroyWindow(hwnd_app
);
3127 static void test_WM_QUIT_handling(void)
3131 hwnd_app
= CreateWindowA("WineCOMTest", NULL
, 0, CW_USEDEFAULT
, CW_USEDEFAULT
, CW_USEDEFAULT
, CW_USEDEFAULT
, NULL
, NULL
, NULL
, 0);
3132 ok(hwnd_app
!= NULL
, "Window creation failed\n");
3134 /* start WM_QUIT handling test */
3135 PostMessageA(hwnd_app
, WM_USER
+1, 0, 0);
3137 while (GetMessageA(&msg
, NULL
, 0, 0))
3139 TranslateMessage(&msg
);
3140 DispatchMessageA(&msg
);
3144 static SIZE_T
round_global_size(SIZE_T size
)
3146 static SIZE_T global_size_alignment
= -1;
3147 if (global_size_alignment
== -1)
3149 void *p
= GlobalAlloc(GMEM_FIXED
, 1);
3150 global_size_alignment
= GlobalSize(p
);
3154 return ((size
+ global_size_alignment
- 1) & ~(global_size_alignment
- 1));
3157 static void test_freethreadedmarshaldata(IStream
*pStream
, MSHCTX mshctx
, void *ptr
, DWORD mshlflags
)
3164 hr
= GetHGlobalFromStream(pStream
, &hglobal
);
3165 ok_ole_success(hr
, GetHGlobalFromStream
);
3167 size
= GlobalSize(hglobal
);
3169 marshal_data
= GlobalLock(hglobal
);
3171 if (mshctx
== MSHCTX_INPROC
)
3173 DWORD expected_size
= round_global_size(3*sizeof(DWORD
) + sizeof(GUID
));
3174 ok(size
== expected_size
||
3175 broken(size
== (2*sizeof(DWORD
))) /* Win9x & NT4 */,
3176 "size should have been %d instead of %d\n", expected_size
, size
);
3178 ok(*(DWORD
*)marshal_data
== mshlflags
, "expected 0x%x, but got 0x%x for mshctx\n", mshlflags
, *(DWORD
*)marshal_data
);
3179 marshal_data
+= sizeof(DWORD
);
3180 ok(*(void **)marshal_data
== ptr
, "expected %p, but got %p for mshctx\n", ptr
, *(void **)marshal_data
);
3181 marshal_data
+= sizeof(void *);
3182 if (sizeof(void*) == 4 && size
>= 3*sizeof(DWORD
))
3184 ok(*(DWORD
*)marshal_data
== 0, "expected 0x0, but got 0x%x\n", *(DWORD
*)marshal_data
);
3185 marshal_data
+= sizeof(DWORD
);
3187 if (size
>= 3*sizeof(DWORD
) + sizeof(GUID
))
3189 trace("got guid data: %s\n", wine_dbgstr_guid((GUID
*)marshal_data
));
3194 ok(size
> sizeof(DWORD
), "size should have been > sizeof(DWORD), not %d\n", size
);
3195 ok(*(DWORD
*)marshal_data
== 0x574f454d /* MEOW */,
3196 "marshal data should be filled by standard marshal and start with MEOW signature\n");
3199 GlobalUnlock(hglobal
);
3202 static void test_freethreadedmarshaler(void)
3205 IUnknown
*pFTUnknown
;
3206 IMarshal
*pFTMarshal
;
3209 static const LARGE_INTEGER llZero
;
3213 hr
= CoCreateFreeThreadedMarshaler(NULL
, &pFTUnknown
);
3214 ok_ole_success(hr
, CoCreateFreeThreadedMarshaler
);
3215 hr
= IUnknown_QueryInterface(pFTUnknown
, &IID_IMarshal
, (void **)&pFTMarshal
);
3216 ok_ole_success(hr
, IUnknown_QueryInterface
);
3217 IUnknown_Release(pFTUnknown
);
3219 hr
= CreateStreamOnHGlobal(NULL
, TRUE
, &pStream
);
3220 ok_ole_success(hr
, CreateStreamOnHGlobal
);
3222 /* inproc normal marshaling */
3224 hr
= IMarshal_GetUnmarshalClass(pFTMarshal
, &IID_IClassFactory
,
3225 &Test_ClassFactory
, MSHCTX_INPROC
, NULL
, MSHLFLAGS_NORMAL
, &clsid
);
3226 ok_ole_success(hr
, IMarshal_GetUnmarshalClass
);
3227 ok(IsEqualIID(&clsid
, &CLSID_InProcFreeMarshaler
), "clsid = %s\n",
3228 wine_dbgstr_guid(&clsid
));
3230 hr
= IMarshal_MarshalInterface(pFTMarshal
, pStream
, &IID_IClassFactory
,
3231 &Test_ClassFactory
, MSHCTX_INPROC
, NULL
, MSHLFLAGS_NORMAL
);
3232 ok_ole_success(hr
, IMarshal_MarshalInterface
);
3234 ok_more_than_one_lock();
3236 test_freethreadedmarshaldata(pStream
, MSHCTX_INPROC
, &Test_ClassFactory
, MSHLFLAGS_NORMAL
);
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
);
3246 /* inproc table-strong marshaling */
3248 IStream_Seek(pStream
, llZero
, STREAM_SEEK_SET
, NULL
);
3249 hr
= IMarshal_MarshalInterface(pFTMarshal
, pStream
, &IID_IClassFactory
,
3250 (IUnknown
*)&Test_ClassFactory
, MSHCTX_INPROC
, (void *)0xdeadbeef,
3251 MSHLFLAGS_TABLESTRONG
);
3252 ok_ole_success(hr
, IMarshal_MarshalInterface
);
3254 ok_more_than_one_lock();
3256 test_freethreadedmarshaldata(pStream
, MSHCTX_INPROC
, &Test_ClassFactory
, MSHLFLAGS_TABLESTRONG
);
3258 IStream_Seek(pStream
, llZero
, STREAM_SEEK_SET
, NULL
);
3259 hr
= IMarshal_UnmarshalInterface(pFTMarshal
, pStream
, &IID_IUnknown
, (void **)&pProxy
);
3260 ok_ole_success(hr
, IMarshal_UnmarshalInterface
);
3262 IUnknown_Release(pProxy
);
3264 ok_more_than_one_lock();
3266 IStream_Seek(pStream
, llZero
, STREAM_SEEK_SET
, NULL
);
3267 hr
= IMarshal_ReleaseMarshalData(pFTMarshal
, pStream
);
3268 ok_ole_success(hr
, IMarshal_ReleaseMarshalData
);
3272 /* inproc table-weak marshaling */
3274 IStream_Seek(pStream
, llZero
, STREAM_SEEK_SET
, NULL
);
3275 hr
= IMarshal_MarshalInterface(pFTMarshal
, pStream
, &IID_IClassFactory
,
3276 (IUnknown
*)&Test_ClassFactory
, MSHCTX_INPROC
, (void *)0xdeadbeef,
3277 MSHLFLAGS_TABLEWEAK
);
3278 ok_ole_success(hr
, IMarshal_MarshalInterface
);
3282 test_freethreadedmarshaldata(pStream
, MSHCTX_INPROC
, &Test_ClassFactory
, MSHLFLAGS_TABLEWEAK
);
3284 IStream_Seek(pStream
, llZero
, STREAM_SEEK_SET
, NULL
);
3285 hr
= IMarshal_UnmarshalInterface(pFTMarshal
, pStream
, &IID_IUnknown
, (void **)&pProxy
);
3286 ok_ole_success(hr
, IMarshal_UnmarshalInterface
);
3288 ok_more_than_one_lock();
3290 IUnknown_Release(pProxy
);
3294 /* inproc normal marshaling (for extraordinary cases) */
3296 IStream_Seek(pStream
, llZero
, STREAM_SEEK_SET
, NULL
);
3297 hr
= IMarshal_MarshalInterface(pFTMarshal
, pStream
, &IID_IClassFactory
,
3298 &Test_ClassFactory
, MSHCTX_INPROC
, NULL
, MSHLFLAGS_NORMAL
);
3299 ok_ole_success(hr
, IMarshal_MarshalInterface
);
3301 ok_more_than_one_lock();
3303 /* this call shows that DisconnectObject does nothing */
3304 hr
= IMarshal_DisconnectObject(pFTMarshal
, 0);
3305 ok_ole_success(hr
, IMarshal_DisconnectObject
);
3307 ok_more_than_one_lock();
3309 IStream_Seek(pStream
, llZero
, STREAM_SEEK_SET
, NULL
);
3310 hr
= IMarshal_ReleaseMarshalData(pFTMarshal
, pStream
);
3311 ok_ole_success(hr
, IMarshal_ReleaseMarshalData
);
3315 /* doesn't enforce marshaling rules here and allows us to unmarshal the
3316 * interface, even though it was freed above */
3317 IStream_Seek(pStream
, llZero
, STREAM_SEEK_SET
, NULL
);
3318 hr
= IMarshal_UnmarshalInterface(pFTMarshal
, pStream
, &IID_IUnknown
, (void **)&pProxy
);
3319 ok_ole_success(hr
, IMarshal_UnmarshalInterface
);
3323 /* local normal marshaling */
3325 hr
= IMarshal_GetUnmarshalClass(pFTMarshal
, &IID_IClassFactory
,
3326 &Test_ClassFactory
, MSHCTX_LOCAL
, NULL
, MSHLFLAGS_NORMAL
, &clsid
);
3327 ok_ole_success(hr
, IMarshal_GetUnmarshalClass
);
3328 ok(IsEqualIID(&clsid
, &CLSID_StdMarshal
), "clsid = %s\n",
3329 wine_dbgstr_guid(&clsid
));
3331 IStream_Seek(pStream
, llZero
, STREAM_SEEK_SET
, NULL
);
3332 hr
= IMarshal_MarshalInterface(pFTMarshal
, pStream
, &IID_IClassFactory
, &Test_ClassFactory
, MSHCTX_LOCAL
, NULL
, MSHLFLAGS_NORMAL
);
3333 ok_ole_success(hr
, IMarshal_MarshalInterface
);
3335 ok_more_than_one_lock();
3337 test_freethreadedmarshaldata(pStream
, MSHCTX_LOCAL
, &Test_ClassFactory
, MSHLFLAGS_NORMAL
);
3339 IStream_Seek(pStream
, llZero
, STREAM_SEEK_SET
, NULL
);
3340 hr
= CoReleaseMarshalData(pStream
);
3341 ok_ole_success(hr
, CoReleaseMarshalData
);
3345 IStream_Release(pStream
);
3346 IMarshal_Release(pFTMarshal
);
3349 static HRESULT
reg_unreg_wine_test_class(BOOL Register
)
3355 DWORD dwDisposition
;
3358 hr
= StringFromCLSID(&CLSID_WineTest
, &pszClsid
);
3359 ok_ole_success(hr
, "StringFromCLSID");
3360 strcpy(buffer
, "CLSID\\");
3361 WideCharToMultiByte(CP_ACP
, 0, pszClsid
, -1, buffer
+ strlen(buffer
), sizeof(buffer
) - strlen(buffer
), NULL
, NULL
);
3362 CoTaskMemFree(pszClsid
);
3363 strcat(buffer
, "\\InprocHandler32");
3366 error
= RegCreateKeyExA(HKEY_CLASSES_ROOT
, buffer
, 0, NULL
, 0, KEY_SET_VALUE
, NULL
, &hkey
, &dwDisposition
);
3367 if (error
== ERROR_ACCESS_DENIED
)
3369 skip("Not authorized to modify the Classes key\n");
3372 ok(error
== ERROR_SUCCESS
, "RegCreateKeyEx failed with error %d\n", error
);
3373 if (error
!= ERROR_SUCCESS
) hr
= E_FAIL
;
3374 error
= RegSetValueExA(hkey
, NULL
, 0, REG_SZ
, (const unsigned char *)"\"ole32.dll\"", strlen("\"ole32.dll\"") + 1);
3375 ok(error
== ERROR_SUCCESS
, "RegSetValueEx failed with error %d\n", error
);
3376 if (error
!= ERROR_SUCCESS
) hr
= E_FAIL
;
3381 RegDeleteKeyA(HKEY_CLASSES_ROOT
, buffer
);
3382 *strrchr(buffer
, '\\') = '\0';
3383 RegDeleteKeyA(HKEY_CLASSES_ROOT
, buffer
);
3388 static void test_inproc_handler(void)
3394 if (FAILED(reg_unreg_wine_test_class(TRUE
)))
3397 hr
= CoCreateInstance(&CLSID_WineTest
, NULL
, CLSCTX_INPROC_HANDLER
, &IID_IUnknown
, (void **)&pObject
);
3398 ok_ole_success(hr
, "CoCreateInstance");
3402 hr
= IUnknown_QueryInterface(pObject
, &IID_IWineTest
, (void **)&pObject2
);
3403 ok(hr
== E_NOINTERFACE
, "IUnknown_QueryInterface on handler for invalid interface returned 0x%08x instead of E_NOINTERFACE\n", hr
);
3405 /* it's a handler as it supports IOleObject */
3406 hr
= IUnknown_QueryInterface(pObject
, &IID_IOleObject
, (void **)&pObject2
);
3407 ok_ole_success(hr
, "IUnknown_QueryInterface(&IID_IOleObject)");
3408 IUnknown_Release(pObject2
);
3410 IUnknown_Release(pObject
);
3413 reg_unreg_wine_test_class(FALSE
);
3416 static HRESULT WINAPI
Test_SMI_QueryInterface(
3417 IStdMarshalInfo
*iface
,
3421 if (ppvObj
== NULL
) return E_POINTER
;
3423 if (IsEqualGUID(riid
, &IID_IUnknown
) ||
3424 IsEqualGUID(riid
, &IID_IStdMarshalInfo
))
3427 IStdMarshalInfo_AddRef(iface
);
3431 return E_NOINTERFACE
;
3434 static ULONG WINAPI
Test_SMI_AddRef(IStdMarshalInfo
*iface
)
3437 return 2; /* non-heap-based object */
3440 static ULONG WINAPI
Test_SMI_Release(IStdMarshalInfo
*iface
)
3443 return 1; /* non-heap-based object */
3446 static HRESULT WINAPI
Test_SMI_GetClassForHandler(
3447 IStdMarshalInfo
*iface
,
3448 DWORD dwDestContext
,
3449 void *pvDestContext
,
3452 *pClsid
= CLSID_WineTest
;
3456 static const IStdMarshalInfoVtbl Test_SMI_Vtbl
=
3458 Test_SMI_QueryInterface
,
3461 Test_SMI_GetClassForHandler
3464 static IStdMarshalInfo Test_SMI
= {&Test_SMI_Vtbl
};
3466 static void test_handler_marshaling(void)
3469 IStream
*pStream
= NULL
;
3470 IUnknown
*pProxy
= NULL
;
3474 static const LARGE_INTEGER ullZero
;
3476 if (FAILED(reg_unreg_wine_test_class(TRUE
)))
3480 hr
= CreateStreamOnHGlobal(NULL
, TRUE
, &pStream
);
3481 ok_ole_success(hr
, "CreateStreamOnHGlobal");
3482 tid
= start_host_object(pStream
, &IID_IUnknown
, (IUnknown
*)&Test_SMI
, MSHLFLAGS_NORMAL
, &thread
);
3484 ok_more_than_one_lock();
3486 IStream_Seek(pStream
, ullZero
, STREAM_SEEK_SET
, NULL
);
3487 hr
= CoUnmarshalInterface(pStream
, &IID_IUnknown
, (void **)&pProxy
);
3488 ok_ole_success(hr
, "CoUnmarshalInterface");
3489 IStream_Release(pStream
);
3493 ok_more_than_one_lock();
3495 hr
= IUnknown_QueryInterface(pProxy
, &IID_IWineTest
, (void **)&pObject
);
3496 ok(hr
== E_NOINTERFACE
, "IUnknown_QueryInterface with unknown IID should have returned E_NOINTERFACE instead of 0x%08x\n", hr
);
3498 /* it's a handler as it supports IOleObject */
3499 hr
= IUnknown_QueryInterface(pProxy
, &IID_IOleObject
, (void **)&pObject
);
3501 ok_ole_success(hr
, "IUnknown_QueryInterface(&IID_IOleObject)");
3502 if (SUCCEEDED(hr
)) IUnknown_Release(pObject
);
3504 IUnknown_Release(pProxy
);
3509 end_host_object(tid
, thread
);
3510 reg_unreg_wine_test_class(FALSE
);
3512 /* FIXME: test IPersist interface has the same effect as IStdMarshalInfo */
3516 static void test_client_security(void)
3519 IStream
*pStream
= NULL
;
3520 IClassFactory
*pProxy
= NULL
;
3521 IUnknown
*pProxy2
= NULL
;
3522 IUnknown
*pUnknown1
= NULL
;
3523 IUnknown
*pUnknown2
= NULL
;
3524 IClientSecurity
*pCliSec
= NULL
;
3528 static const LARGE_INTEGER ullZero
;
3531 OLECHAR
*pServerPrincName
;
3535 DWORD dwCapabilities
;
3540 hr
= CreateStreamOnHGlobal(NULL
, TRUE
, &pStream
);
3541 ok_ole_success(hr
, "CreateStreamOnHGlobal");
3542 tid
= start_host_object(pStream
, &IID_IClassFactory
, (IUnknown
*)&Test_ClassFactory
, MSHLFLAGS_NORMAL
, &thread
);
3544 IStream_Seek(pStream
, ullZero
, STREAM_SEEK_SET
, NULL
);
3545 hr
= CoUnmarshalInterface(pStream
, &IID_IClassFactory
, (void **)&pProxy
);
3546 ok_ole_success(hr
, "CoUnmarshalInterface");
3547 IStream_Release(pStream
);
3549 hr
= IClassFactory_QueryInterface(pProxy
, &IID_IUnknown
, (LPVOID
*)&pUnknown1
);
3550 ok_ole_success(hr
, "IUnknown_QueryInterface IID_IUnknown");
3552 hr
= IClassFactory_QueryInterface(pProxy
, &IID_IRemUnknown
, (LPVOID
*)&pProxy2
);
3553 ok_ole_success(hr
, "IUnknown_QueryInterface IID_IStream");
3555 hr
= IUnknown_QueryInterface(pProxy2
, &IID_IUnknown
, (LPVOID
*)&pUnknown2
);
3556 ok_ole_success(hr
, "IUnknown_QueryInterface IID_IUnknown");
3558 ok(pUnknown1
== pUnknown2
, "both proxy's IUnknowns should be the same - %p, %p\n", pUnknown1
, pUnknown2
);
3560 hr
= IClassFactory_QueryInterface(pProxy
, &IID_IMarshal
, (LPVOID
*)&pMarshal
);
3561 ok_ole_success(hr
, "IUnknown_QueryInterface IID_IMarshal");
3563 hr
= IClassFactory_QueryInterface(pProxy
, &IID_IClientSecurity
, (LPVOID
*)&pCliSec
);
3564 ok_ole_success(hr
, "IUnknown_QueryInterface IID_IClientSecurity");
3566 hr
= IClientSecurity_QueryBlanket(pCliSec
, (IUnknown
*)pProxy
, NULL
, NULL
, NULL
, NULL
, NULL
, NULL
, NULL
);
3567 todo_wine
ok_ole_success(hr
, "IClientSecurity_QueryBlanket (all NULLs)");
3569 hr
= IClientSecurity_QueryBlanket(pCliSec
, (IUnknown
*)pMarshal
, NULL
, NULL
, NULL
, NULL
, NULL
, NULL
, NULL
);
3570 todo_wine
ok(hr
== E_NOINTERFACE
, "IClientSecurity_QueryBlanket with local interface should have returned E_NOINTERFACE instead of 0x%08x\n", hr
);
3572 hr
= IClientSecurity_QueryBlanket(pCliSec
, (IUnknown
*)pProxy
, &dwAuthnSvc
, &dwAuthzSvc
, &pServerPrincName
, &dwAuthnLevel
, &dwImpLevel
, &pAuthInfo
, &dwCapabilities
);
3573 todo_wine
ok_ole_success(hr
, "IClientSecurity_QueryBlanket");
3575 hr
= IClientSecurity_SetBlanket(pCliSec
, (IUnknown
*)pProxy
, dwAuthnSvc
, dwAuthzSvc
, pServerPrincName
, dwAuthnLevel
, RPC_C_IMP_LEVEL_IMPERSONATE
, pAuthInfo
, dwCapabilities
);
3576 todo_wine
ok_ole_success(hr
, "IClientSecurity_SetBlanket");
3578 hr
= IClassFactory_CreateInstance(pProxy
, NULL
, &IID_IWineTest
, &pv
);
3579 ok(hr
== E_NOINTERFACE
, "COM call should have succeeded instead of returning 0x%08x\n", hr
);
3581 hr
= IClientSecurity_SetBlanket(pCliSec
, (IUnknown
*)pMarshal
, dwAuthnSvc
, dwAuthzSvc
, pServerPrincName
, dwAuthnLevel
, dwImpLevel
, pAuthInfo
, dwCapabilities
);
3582 todo_wine
ok(hr
== E_NOINTERFACE
, "IClientSecurity_SetBlanket with local interface should have returned E_NOINTERFACE instead of 0x%08x\n", hr
);
3584 hr
= IClientSecurity_SetBlanket(pCliSec
, (IUnknown
*)pProxy
, 0xdeadbeef, dwAuthzSvc
, pServerPrincName
, dwAuthnLevel
, dwImpLevel
, pAuthInfo
, dwCapabilities
);
3585 todo_wine
ok(hr
== E_INVALIDARG
, "IClientSecurity_SetBlanke with invalid dwAuthnSvc should have returned E_INVALIDARG instead of 0x%08x\n", hr
);
3587 CoTaskMemFree(pServerPrincName
);
3589 hr
= IClientSecurity_QueryBlanket(pCliSec
, pUnknown1
, &dwAuthnSvc
, &dwAuthzSvc
, &pServerPrincName
, &dwAuthnLevel
, &dwImpLevel
, &pAuthInfo
, &dwCapabilities
);
3590 todo_wine
ok_ole_success(hr
, "IClientSecurity_QueryBlanket(IUnknown)");
3592 CoTaskMemFree(pServerPrincName
);
3594 IClassFactory_Release(pProxy
);
3595 IUnknown_Release(pProxy2
);
3596 IUnknown_Release(pUnknown1
);
3597 IUnknown_Release(pUnknown2
);
3598 IMarshal_Release(pMarshal
);
3599 IClientSecurity_Release(pCliSec
);
3601 end_host_object(tid
, thread
);
3604 static HANDLE heventShutdown
;
3606 static void LockModuleOOP(void)
3608 InterlockedIncrement(&cLocks
); /* for test purposes only */
3609 CoAddRefServerProcess();
3612 static void UnlockModuleOOP(void)
3614 InterlockedDecrement(&cLocks
); /* for test purposes only */
3615 if (!CoReleaseServerProcess())
3616 SetEvent(heventShutdown
);
3619 static HWND hwnd_app
;
3623 IPersist IPersist_iface
; /* a nice short interface */
3626 static HRESULT WINAPI
local_server_QueryInterface(IPersist
*iface
, REFIID iid
, void **obj
)
3630 if (IsEqualGUID(iid
, &IID_IUnknown
) ||
3631 IsEqualGUID(iid
, &IID_IPersist
))
3636 IPersist_AddRef(iface
);
3639 return E_NOINTERFACE
;
3642 static ULONG WINAPI
local_server_AddRef(IPersist
*iface
)
3647 static ULONG WINAPI
local_server_Release(IPersist
*iface
)
3652 static HRESULT WINAPI
local_server_GetClassID(IPersist
*iface
, CLSID
*clsid
)
3656 *clsid
= IID_IUnknown
;
3658 /* Test calling CoDisconnectObject within a COM call */
3659 hr
= CoDisconnectObject((IUnknown
*)iface
, 0);
3660 ok(hr
== S_OK
, "got %08x\n", hr
);
3662 /* Initialize and uninitialize the apartment to show that we
3663 * remain in the autojoined mta */
3664 hr
= pCoInitializeEx( NULL
, COINIT_MULTITHREADED
);
3665 ok( hr
== S_FALSE
, "got %08x\n", hr
);
3671 static const IPersistVtbl local_server_persist_vtbl
=
3673 local_server_QueryInterface
,
3674 local_server_AddRef
,
3675 local_server_Release
,
3676 local_server_GetClassID
3679 struct local_server local_server_class
=
3681 {&local_server_persist_vtbl
}
3684 static HRESULT WINAPI
TestOOP_IClassFactory_QueryInterface(
3685 LPCLASSFACTORY iface
,
3689 if (ppvObj
== NULL
) return E_POINTER
;
3691 if (IsEqualGUID(riid
, &IID_IUnknown
) ||
3692 IsEqualGUID(riid
, &IID_IClassFactory
))
3695 IClassFactory_AddRef(iface
);
3699 return E_NOINTERFACE
;
3702 static ULONG WINAPI
TestOOP_IClassFactory_AddRef(LPCLASSFACTORY iface
)
3704 return 2; /* non-heap-based object */
3707 static ULONG WINAPI
TestOOP_IClassFactory_Release(LPCLASSFACTORY iface
)
3709 return 1; /* non-heap-based object */
3712 static HRESULT WINAPI
TestOOP_IClassFactory_CreateInstance(
3713 LPCLASSFACTORY iface
,
3714 LPUNKNOWN pUnkOuter
,
3718 IPersist
*persist
= &local_server_class
.IPersist_iface
;
3720 IPersist_AddRef( persist
);
3721 hr
= IPersist_QueryInterface( persist
, riid
, ppvObj
);
3722 IPersist_Release( persist
);
3726 static HRESULT WINAPI
TestOOP_IClassFactory_LockServer(
3727 LPCLASSFACTORY iface
,
3737 static const IClassFactoryVtbl TestClassFactoryOOP_Vtbl
=
3739 TestOOP_IClassFactory_QueryInterface
,
3740 TestOOP_IClassFactory_AddRef
,
3741 TestOOP_IClassFactory_Release
,
3742 TestOOP_IClassFactory_CreateInstance
,
3743 TestOOP_IClassFactory_LockServer
3746 static IClassFactory TestOOP_ClassFactory
= { &TestClassFactoryOOP_Vtbl
};
3748 static void test_register_local_server(void)
3756 heventShutdown
= CreateEventA(NULL
, TRUE
, FALSE
, NULL
);
3757 ready_event
= CreateEventA(NULL
, FALSE
, FALSE
, "Wine COM Test Ready Event");
3758 handles
[0] = CreateEventA(NULL
, FALSE
, FALSE
, "Wine COM Test Quit Event");
3759 handles
[1] = CreateEventA(NULL
, FALSE
, FALSE
, "Wine COM Test Repeat Event");
3762 hr
= CoRegisterClassObject(&CLSID_WineOOPTest
, (IUnknown
*)&TestOOP_ClassFactory
,
3763 CLSCTX_LOCAL_SERVER
, REGCLS_SINGLEUSE
, &cookie
);
3764 ok_ole_success(hr
, CoRegisterClassObject
);
3766 SetEvent(ready_event
);
3770 wait
= MsgWaitForMultipleObjects(2, handles
, FALSE
, 30000, QS_ALLINPUT
);
3771 if (wait
== WAIT_OBJECT_0
+2)
3775 if (PeekMessageA(&msg
, NULL
, 0, 0, PM_REMOVE
))
3777 trace("Message 0x%x\n", msg
.message
);
3778 TranslateMessage(&msg
);
3779 DispatchMessageA(&msg
);
3782 else if (wait
== WAIT_OBJECT_0
+1)
3784 hr
= CoRevokeClassObject(cookie
);
3785 ok_ole_success(hr
, CoRevokeClassObject
);
3789 while (wait
== WAIT_OBJECT_0
+2);
3791 ok( wait
== WAIT_OBJECT_0
, "quit event wait timed out\n" );
3792 hr
= CoRevokeClassObject(cookie
);
3793 ok_ole_success(hr
, CoRevokeClassObject
);
3794 CloseHandle(handles
[0]);
3795 CloseHandle(handles
[1]);
3798 static HANDLE
create_target_process(const char *arg
)
3801 char cmdline
[MAX_PATH
];
3803 PROCESS_INFORMATION pi
;
3804 STARTUPINFOA si
= { 0 };
3809 winetest_get_mainargs( &argv
);
3810 sprintf(cmdline
, "\"%s\" %s %s", argv
[0], argv
[1], arg
);
3811 ret
= CreateProcessA(argv
[0], cmdline
, NULL
, NULL
, FALSE
, 0, NULL
, NULL
, &si
, &pi
);
3812 ok(ret
, "CreateProcess failed with error: %u\n", GetLastError());
3813 if (pi
.hThread
) CloseHandle(pi
.hThread
);
3817 /* tests functions commonly used by out of process COM servers */
3818 static void test_local_server(void)
3828 HANDLE repeat_event
;
3831 heventShutdown
= CreateEventA(NULL
, TRUE
, FALSE
, NULL
);
3835 /* Start the object suspended */
3836 hr
= CoRegisterClassObject(&CLSID_WineOOPTest
, (IUnknown
*)&TestOOP_ClassFactory
,
3837 CLSCTX_LOCAL_SERVER
, REGCLS_MULTIPLEUSE
| REGCLS_SUSPENDED
, &cookie
);
3838 ok_ole_success(hr
, CoRegisterClassObject
);
3840 /* ... and CoGetClassObject does not find it and fails when it looks for the
3841 * class in the registry */
3842 hr
= CoGetClassObject(&CLSID_WineOOPTest
, CLSCTX_INPROC_SERVER
,
3843 NULL
, &IID_IClassFactory
, (LPVOID
*)&cf
);
3844 ok(hr
== REGDB_E_CLASSNOTREG
|| /* NT */
3845 hr
== S_OK
/* Win9x */,
3846 "CoGetClassObject should have returned REGDB_E_CLASSNOTREG instead of 0x%08x\n", hr
);
3848 /* Resume the object suspended above ... */
3849 hr
= CoResumeClassObjects();
3850 ok_ole_success(hr
, CoResumeClassObjects
);
3852 /* ... and now it should succeed */
3853 hr
= CoGetClassObject(&CLSID_WineOOPTest
, CLSCTX_INPROC_SERVER
,
3854 NULL
, &IID_IClassFactory
, (LPVOID
*)&cf
);
3855 ok_ole_success(hr
, CoGetClassObject
);
3857 /* Now check the locking is working */
3858 /* NOTE: we are accessing the class directly, not through a proxy */
3862 hr
= IClassFactory_LockServer(cf
, TRUE
);
3863 ok_ole_success(hr
, IClassFactory_LockServer
);
3865 ok_more_than_one_lock();
3867 IClassFactory_LockServer(cf
, FALSE
);
3868 ok_ole_success(hr
, IClassFactory_LockServer
);
3872 IClassFactory_Release(cf
);
3874 /* wait for shutdown signal */
3875 ret
= WaitForSingleObject(heventShutdown
, 0);
3876 ok(ret
!= WAIT_TIMEOUT
, "Server didn't shut down\n");
3878 /* try to connect again after SCM has suspended registered class objects */
3879 hr
= CoGetClassObject(&CLSID_WineOOPTest
, CLSCTX_INPROC_SERVER
| CLSCTX_LOCAL_SERVER
, NULL
,
3880 &IID_IClassFactory
, (LPVOID
*)&cf
);
3881 ok(hr
== CO_E_SERVER_STOPPING
|| /* NT */
3882 hr
== REGDB_E_CLASSNOTREG
|| /* win2k */
3883 hr
== S_OK
/* Win9x */,
3884 "CoGetClassObject should have returned CO_E_SERVER_STOPPING or REGDB_E_CLASSNOTREG instead of 0x%08x\n", hr
);
3886 hr
= CoRevokeClassObject(cookie
);
3887 ok_ole_success(hr
, CoRevokeClassObject
);
3889 CloseHandle(heventShutdown
);
3891 process
= create_target_process("-Embedding");
3892 ok(process
!= NULL
, "couldn't start local server process, error was %d\n", GetLastError());
3894 ready_event
= CreateEventA(NULL
, FALSE
, FALSE
, "Wine COM Test Ready Event");
3895 ok( !WaitForSingleObject(ready_event
, 10000), "wait timed out\n" );
3897 hr
= CoCreateInstance(&CLSID_WineOOPTest
, NULL
, CLSCTX_LOCAL_SERVER
, &IID_IPersist
, (void **)&persist
);
3898 ok_ole_success(hr
, CoCreateInstance
);
3900 IPersist_Release(persist
);
3902 hr
= CoCreateInstance(&CLSID_WineOOPTest
, NULL
, CLSCTX_LOCAL_SERVER
, &IID_IPersist
, (void **)&persist
);
3903 ok(hr
== REGDB_E_CLASSNOTREG
, "Second CoCreateInstance on REGCLS_SINGLEUSE object should have failed\n");
3905 /* Re-register the class and try calling CoDisconnectObject from within a call to that object */
3906 repeat_event
= CreateEventA(NULL
, FALSE
, FALSE
, "Wine COM Test Repeat Event");
3907 SetEvent(repeat_event
);
3908 CloseHandle(repeat_event
);
3910 ok( !WaitForSingleObject(ready_event
, 10000), "wait timed out\n" );
3911 CloseHandle(ready_event
);
3913 hr
= CoCreateInstance(&CLSID_WineOOPTest
, NULL
, CLSCTX_LOCAL_SERVER
, &IID_IPersist
, (void **)&persist
);
3914 ok_ole_success(hr
, CoCreateInstance
);
3916 /* GetClassID will call CoDisconnectObject */
3917 IPersist_GetClassID(persist
, &clsid
);
3918 IPersist_Release(persist
);
3920 quit_event
= CreateEventA(NULL
, FALSE
, FALSE
, "Wine COM Test Quit Event");
3921 SetEvent(quit_event
);
3923 winetest_wait_child_process( process
);
3924 CloseHandle(quit_event
);
3925 CloseHandle(process
);
3931 IGlobalInterfaceTable
*git
;
3934 static DWORD CALLBACK
get_global_interface_proc(LPVOID pv
)
3937 struct git_params
*params
= pv
;
3940 hr
= IGlobalInterfaceTable_GetInterfaceFromGlobal(params
->git
, params
->cookie
, &IID_IClassFactory
, (void **)&cf
);
3941 ok(hr
== CO_E_NOTINITIALIZED
||
3942 broken(hr
== E_UNEXPECTED
) /* win2k */ ||
3943 broken(hr
== S_OK
) /* NT 4 */,
3944 "IGlobalInterfaceTable_GetInterfaceFromGlobal should have failed with error CO_E_NOTINITIALIZED or E_UNEXPECTED instead of 0x%08x\n",
3947 IClassFactory_Release(cf
);
3951 hr
= IGlobalInterfaceTable_GetInterfaceFromGlobal(params
->git
, params
->cookie
, &IID_IClassFactory
, (void **)&cf
);
3952 ok_ole_success(hr
, IGlobalInterfaceTable_GetInterfaceFromGlobal
);
3954 IClassFactory_Release(cf
);
3961 static void test_globalinterfacetable(void)
3964 IGlobalInterfaceTable
*git
;
3968 struct git_params params
;
3974 trace("test_globalinterfacetable\n");
3977 hr
= pDllGetClassObject(&CLSID_StdGlobalInterfaceTable
, &IID_IClassFactory
, (void**)&cf
);
3978 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3980 hr
= IClassFactory_QueryInterface(cf
, &IID_IGlobalInterfaceTable
, (void**)&object
);
3981 ok(hr
== E_NOINTERFACE
, "got 0x%08x\n", hr
);
3983 IClassFactory_Release(cf
);
3985 hr
= CoCreateInstance(&CLSID_StdGlobalInterfaceTable
, NULL
, CLSCTX_INPROC_SERVER
, &IID_IGlobalInterfaceTable
, (void **)&git
);
3986 ok_ole_success(hr
, CoCreateInstance
);
3988 ref
= IGlobalInterfaceTable_AddRef(git
);
3989 ok(ref
== 1, "ref=%d\n", ref
);
3990 ref
= IGlobalInterfaceTable_AddRef(git
);
3991 ok(ref
== 1, "ref=%d\n", ref
);
3993 ref
= IGlobalInterfaceTable_Release(git
);
3994 ok(ref
== 1, "ref=%d\n", ref
);
3995 ref
= IGlobalInterfaceTable_Release(git
);
3996 ok(ref
== 1, "ref=%d\n", ref
);
3998 hr
= IGlobalInterfaceTable_RegisterInterfaceInGlobal(git
, (IUnknown
*)&Test_ClassFactory
, &IID_IClassFactory
, &cookie
);
3999 ok_ole_success(hr
, IGlobalInterfaceTable_RegisterInterfaceInGlobal
);
4001 ok_more_than_one_lock();
4003 params
.cookie
= cookie
;
4005 /* note: params is on stack so we MUST wait for get_global_interface_proc
4006 * to exit before we can return */
4007 thread
= CreateThread(NULL
, 0, get_global_interface_proc
, ¶ms
, 0, &tid
);
4009 ret
= MsgWaitForMultipleObjects(1, &thread
, FALSE
, 10000, QS_ALLINPUT
);
4010 while (ret
== WAIT_OBJECT_0
+ 1)
4013 while (PeekMessageA(&msg
, NULL
, 0, 0, PM_REMOVE
))
4014 DispatchMessageA(&msg
);
4015 ret
= MsgWaitForMultipleObjects(1, &thread
, FALSE
, 10000, QS_ALLINPUT
);
4018 CloseHandle(thread
);
4020 /* test getting interface from global with different iid */
4021 hr
= IGlobalInterfaceTable_GetInterfaceFromGlobal(git
, cookie
, &IID_IUnknown
, (void **)&object
);
4022 ok_ole_success(hr
, IGlobalInterfaceTable_GetInterfaceFromGlobal
);
4023 IUnknown_Release(object
);
4025 /* test getting interface from global with same iid */
4026 hr
= IGlobalInterfaceTable_GetInterfaceFromGlobal(git
, cookie
, &IID_IClassFactory
, (void **)&object
);
4027 ok_ole_success(hr
, IGlobalInterfaceTable_GetInterfaceFromGlobal
);
4028 IUnknown_Release(object
);
4030 hr
= IGlobalInterfaceTable_RevokeInterfaceFromGlobal(git
, cookie
);
4031 ok_ole_success(hr
, IGlobalInterfaceTable_RevokeInterfaceFromGlobal
);
4035 IGlobalInterfaceTable_Release(git
);
4038 static void test_manualresetevent(void)
4040 ISynchronizeHandle
*sync_handle
;
4041 ISynchronize
*psync1
, *psync2
;
4047 hr
= CoCreateInstance(&CLSID_ManualResetEvent
, NULL
, CLSCTX_INPROC_SERVER
, &IID_IUnknown
, (void**)&punk
);
4048 ok(hr
== S_OK
, "Got 0x%08x\n", hr
);
4049 ok(!!punk
, "Got NULL.\n");
4050 IUnknown_Release(punk
);
4052 hr
= CoCreateInstance(&CLSID_ManualResetEvent
, NULL
, CLSCTX_INPROC_SERVER
, &IID_ISynchronize
, (void**)&psync1
);
4053 ok(hr
== S_OK
, "Got 0x%08x\n", hr
);
4054 ok(!!psync1
, "Got NULL.\n");
4056 hr
= ISynchronize_Wait(psync1
, 0, 5);
4057 ok(hr
== RPC_S_CALLPENDING
, "Got 0x%08x\n", hr
);
4059 hr
= ISynchronize_Reset(psync1
);
4060 ok(hr
== S_OK
, "Got 0x%08x\n", hr
);
4061 hr
= ISynchronize_Signal(psync1
);
4062 ok(hr
== S_OK
, "Got 0x%08x\n", hr
);
4063 hr
= ISynchronize_Wait(psync1
, 0, 5);
4064 ok(hr
== S_OK
, "Got 0x%08x\n", hr
);
4065 hr
= ISynchronize_Wait(psync1
, 0, 5);
4066 ok(hr
== S_OK
, "Got 0x%08x\n", hr
);
4067 hr
= ISynchronize_Reset(psync1
);
4068 ok(hr
== S_OK
, "Got 0x%08x\n", hr
);
4069 hr
= ISynchronize_Wait(psync1
, 0, 5);
4070 ok(hr
== RPC_S_CALLPENDING
, "Got 0x%08x\n", hr
);
4072 hr
= CoCreateInstance(&CLSID_ManualResetEvent
, NULL
, CLSCTX_INPROC_SERVER
, &IID_ISynchronize
, (void**)&psync2
);
4073 ok(hr
== S_OK
, "Got 0x%08x\n", hr
);
4074 ok(!!psync2
, "Got NULL.\n");
4075 ok(psync1
!= psync2
, "psync1 == psync2.\n");
4077 hr
= ISynchronize_QueryInterface(psync2
, &IID_ISynchronizeHandle
, (void**)&sync_handle
);
4078 ok(hr
== S_OK
, "QueryInterface(IID_ISynchronizeHandle) failed: %08x\n", hr
);
4081 hr
= ISynchronizeHandle_GetHandle(sync_handle
, &handle
);
4082 ok(hr
== S_OK
, "GetHandle failed: %08x\n", hr
);
4083 ok(handle
!= NULL
&& handle
!= INVALID_HANDLE_VALUE
, "handle = %p\n", handle
);
4085 ISynchronizeHandle_Release(sync_handle
);
4087 hr
= ISynchronize_Wait(psync2
, 0, 5);
4088 ok(hr
== RPC_S_CALLPENDING
, "Got 0x%08x\n", hr
);
4090 hr
= ISynchronize_Reset(psync1
);
4091 ok(hr
== S_OK
, "Got 0x%08x\n", hr
);
4092 hr
= ISynchronize_Reset(psync2
);
4093 ok(hr
== S_OK
, "Got 0x%08x\n", hr
);
4094 hr
= ISynchronize_Signal(psync1
);
4095 ok(hr
== S_OK
, "Got 0x%08x\n", hr
);
4096 hr
= ISynchronize_Wait(psync2
, 0, 5);
4097 ok(hr
== RPC_S_CALLPENDING
, "Got 0x%08x\n", hr
);
4099 ref
= ISynchronize_AddRef(psync1
);
4100 ok(ref
== 2, "Got ref: %d\n", ref
);
4101 ref
= ISynchronize_AddRef(psync1
);
4102 ok(ref
== 3, "Got ref: %d\n", ref
);
4103 ref
= ISynchronize_Release(psync1
);
4104 ok(ref
== 2, "Got nonzero ref: %d\n", ref
);
4105 ref
= ISynchronize_Release(psync2
);
4106 ok(!ref
, "Got nonzero ref: %d\n", ref
);
4107 ref
= ISynchronize_Release(psync1
);
4108 ok(ref
== 1, "Got nonzero ref: %d\n", ref
);
4109 ref
= ISynchronize_Release(psync1
);
4110 ok(!ref
, "Got nonzero ref: %d\n", ref
);
4113 static DWORD CALLBACK
implicit_mta_unmarshal_proc(void *param
)
4115 IStream
*stream
= param
;
4120 IStream_Seek(stream
, ullZero
, STREAM_SEEK_SET
, NULL
);
4121 hr
= CoUnmarshalInterface(stream
, &IID_IClassFactory
, (void **)&cf
);
4122 ok_ole_success(hr
, CoUnmarshalInterface
);
4124 hr
= IClassFactory_CreateInstance(cf
, NULL
, &IID_IUnknown
, (void **)&proxy
);
4125 ok_ole_success(hr
, IClassFactory_CreateInstance
);
4127 IUnknown_Release(proxy
);
4129 /* But if we initialize an STA in this apartment, it becomes the wrong one. */
4130 CoInitializeEx(NULL
, COINIT_APARTMENTTHREADED
);
4132 hr
= IClassFactory_CreateInstance(cf
, NULL
, &IID_IUnknown
, (void **)&proxy
);
4133 ok(hr
== RPC_E_WRONG_THREAD
, "got %#x\n", hr
);
4137 ok_more_than_one_lock();
4138 ok_non_zero_external_conn();
4140 IClassFactory_Release(cf
);
4143 ok_zero_external_conn();
4144 ok_last_release_closes(TRUE
);
4148 static DWORD CALLBACK
implicit_mta_use_proc(void *param
)
4150 IClassFactory
*cf
= param
;
4154 hr
= IClassFactory_CreateInstance(cf
, NULL
, &IID_IUnknown
, (void **)&proxy
);
4155 ok_ole_success(hr
, IClassFactory_CreateInstance
);
4157 IUnknown_Release(proxy
);
4159 /* But if we initialize an STA in this apartment, it becomes the wrong one. */
4160 CoInitializeEx(NULL
, COINIT_APARTMENTTHREADED
);
4162 hr
= IClassFactory_CreateInstance(cf
, NULL
, &IID_IUnknown
, (void **)&proxy
);
4163 ok(hr
== RPC_E_WRONG_THREAD
, "got %#x\n", hr
);
4169 struct implicit_mta_marshal_data
4176 static DWORD CALLBACK
implicit_mta_marshal_proc(void *param
)
4178 struct implicit_mta_marshal_data
*data
= param
;
4181 hr
= CoMarshalInterface(data
->stream
, &IID_IClassFactory
,
4182 (IUnknown
*)&Test_ClassFactory
, MSHCTX_INPROC
, NULL
, MSHLFLAGS_NORMAL
);
4183 ok_ole_success(hr
, CoMarshalInterface
);
4185 SetEvent(data
->start
);
4187 ok(!WaitForSingleObject(data
->stop
, 1000), "wait failed\n");
4191 static void test_implicit_mta(void)
4193 struct implicit_mta_marshal_data data
;
4194 HANDLE host_thread
, thread
;
4202 external_connections
= 0;
4204 CoInitializeEx(NULL
, COINIT_MULTITHREADED
);
4206 /* Firstly: we can unmarshal and use an object while in the implicit MTA. */
4207 hr
= CreateStreamOnHGlobal(NULL
, TRUE
, &stream
);
4208 ok_ole_success(hr
, CreateStreamOnHGlobal
);
4209 tid
= start_host_object(stream
, &IID_IClassFactory
, (IUnknown
*)&Test_ClassFactory
, MSHLFLAGS_NORMAL
, &host_thread
);
4211 ok_more_than_one_lock();
4212 ok_non_zero_external_conn();
4214 thread
= CreateThread(NULL
, 0, implicit_mta_unmarshal_proc
, stream
, 0, NULL
);
4215 ok(!WaitForSingleObject(thread
, 1000), "wait failed\n");
4216 CloseHandle(thread
);
4218 IStream_Release(stream
);
4219 end_host_object(tid
, host_thread
);
4221 /* Secondly: we can unmarshal an object into the real MTA and then use it
4222 * from the implicit MTA. */
4223 hr
= CreateStreamOnHGlobal(NULL
, TRUE
, &stream
);
4224 ok_ole_success(hr
, CreateStreamOnHGlobal
);
4225 tid
= start_host_object(stream
, &IID_IClassFactory
, (IUnknown
*)&Test_ClassFactory
, MSHLFLAGS_NORMAL
, &host_thread
);
4227 ok_more_than_one_lock();
4228 ok_non_zero_external_conn();
4230 IStream_Seek(stream
, ullZero
, STREAM_SEEK_SET
, NULL
);
4231 hr
= CoUnmarshalInterface(stream
, &IID_IClassFactory
, (void **)&cf
);
4232 ok_ole_success(hr
, CoUnmarshalInterface
);
4234 thread
= CreateThread(NULL
, 0, implicit_mta_use_proc
, cf
, 0, NULL
);
4235 ok(!WaitForSingleObject(thread
, 1000), "wait failed\n");
4236 CloseHandle(thread
);
4238 IClassFactory_Release(cf
);
4239 IStream_Release(stream
);
4242 ok_non_zero_external_conn();
4243 ok_last_release_closes(TRUE
);
4245 end_host_object(tid
, host_thread
);
4247 /* Thirdly: we can marshal an object from the implicit MTA and then
4248 * unmarshal it into the real one. */
4249 data
.start
= CreateEventA(NULL
, FALSE
, FALSE
, NULL
);
4250 data
.stop
= CreateEventA(NULL
, FALSE
, FALSE
, NULL
);
4252 hr
= CreateStreamOnHGlobal(NULL
, TRUE
, &data
.stream
);
4253 ok_ole_success(hr
, CreateStreamOnHGlobal
);
4255 thread
= CreateThread(NULL
, 0, implicit_mta_marshal_proc
, &data
, 0, NULL
);
4256 ok(!WaitForSingleObject(data
.start
, 1000), "wait failed\n");
4258 IStream_Seek(data
.stream
, ullZero
, STREAM_SEEK_SET
, NULL
);
4259 hr
= CoUnmarshalInterface(data
.stream
, &IID_IClassFactory
, (void **)&cf
);
4260 ok_ole_success(hr
, CoUnmarshalInterface
);
4262 hr
= IClassFactory_CreateInstance(cf
, NULL
, &IID_IUnknown
, (void **)&proxy
);
4263 ok_ole_success(hr
, IClassFactory_CreateInstance
);
4265 IUnknown_Release(proxy
);
4267 SetEvent(data
.stop
);
4268 ok(!WaitForSingleObject(thread
, 1000), "wait failed\n");
4269 CloseHandle(thread
);
4271 IStream_Release(data
.stream
);
4276 static const char *debugstr_iid(REFIID riid
)
4278 static char name
[256];
4282 LONG name_size
= sizeof(name
);
4283 StringFromGUID2(riid
, bufferW
, ARRAY_SIZE(bufferW
));
4284 WideCharToMultiByte(CP_ACP
, 0, bufferW
, ARRAY_SIZE(bufferW
), buffer
, sizeof(buffer
), NULL
, NULL
);
4285 if (RegOpenKeyExA(HKEY_CLASSES_ROOT
, "Interface", 0, KEY_QUERY_VALUE
, &hkeyInterface
) != ERROR_SUCCESS
)
4287 memcpy(name
, buffer
, sizeof(buffer
));
4290 if (RegQueryValueA(hkeyInterface
, buffer
, name
, &name_size
) != ERROR_SUCCESS
)
4292 memcpy(name
, buffer
, sizeof(buffer
));
4295 RegCloseKey(hkeyInterface
);
4300 static HRESULT WINAPI
TestChannelHook_QueryInterface(IChannelHook
*iface
, REFIID riid
, void **ppv
)
4302 if (IsEqualIID(riid
, &IID_IUnknown
) || IsEqualIID(riid
, &IID_IChannelHook
))
4305 IChannelHook_AddRef(iface
);
4310 return E_NOINTERFACE
;
4313 static ULONG WINAPI
TestChannelHook_AddRef(IChannelHook
*iface
)
4318 static ULONG WINAPI
TestChannelHook_Release(IChannelHook
*iface
)
4323 static BOOL new_hook_struct
;
4324 static int method
, server_tid
;
4325 static GUID causality
;
4327 struct new_hook_info
4336 static void WINAPI
TestChannelHook_ClientGetSize(
4337 IChannelHook
*iface
,
4342 SChannelHookCallInfo
*info
= (SChannelHookCallInfo
*)riid
;
4343 trace("TestChannelHook_ClientGetSize\n");
4344 trace("\t%s\n", debugstr_iid(riid
));
4345 if (info
->cbSize
!= sizeof(*info
))
4346 new_hook_struct
= TRUE
;
4348 if (!new_hook_struct
)
4350 ok(info
->cbSize
== sizeof(*info
), "cbSize was %d instead of %d\n", info
->cbSize
, (int)sizeof(*info
));
4351 ok(info
->dwServerPid
== GetCurrentProcessId(), "dwServerPid was 0x%x instead of 0x%x\n", info
->dwServerPid
, GetCurrentProcessId());
4352 ok(info
->iMethod
== method
, "iMethod was %d should be %d\n", info
->iMethod
, method
);
4353 ok(!info
->pObject
, "pObject should be NULL\n");
4355 causality
= info
->uCausality
;
4357 ok(IsEqualGUID(&info
->uCausality
, &causality
), "causality wasn't correct\n");
4361 struct new_hook_info
*new_info
= (struct new_hook_info
*)riid
;
4362 ok(new_info
->server_pid
== GetCurrentProcessId(), "server pid was 0x%x instead of 0x%x\n", new_info
->server_pid
,
4363 GetCurrentProcessId());
4364 ok(new_info
->server_tid
== server_tid
, "server tid was 0x%x instead of 0x%x\n", new_info
->server_tid
,
4366 ok(new_info
->method
== method
, "method was %d instead of %d\n", new_info
->method
, method
);
4368 causality
= new_info
->causality
;
4370 ok(IsEqualGUID(&new_info
->causality
, &causality
), "causality wasn't correct\n");
4373 ok(IsEqualGUID(uExtent
, &EXTENTID_WineTest
), "uExtent wasn't correct\n");
4378 static void WINAPI
TestChannelHook_ClientFillBuffer(
4379 IChannelHook
*iface
,
4385 SChannelHookCallInfo
*info
= (SChannelHookCallInfo
*)riid
;
4386 trace("TestChannelHook_ClientFillBuffer\n");
4388 if (!new_hook_struct
)
4390 ok(info
->cbSize
== sizeof(*info
), "cbSize was %d instead of %d\n", info
->cbSize
, (int)sizeof(*info
));
4391 ok(info
->dwServerPid
== GetCurrentProcessId(), "dwServerPid was 0x%x instead of 0x%x\n", info
->dwServerPid
, GetCurrentProcessId());
4392 ok(info
->iMethod
== method
, "iMethod was %d should be %d\n", info
->iMethod
, method
);
4393 ok(!info
->pObject
, "pObject should be NULL\n");
4394 ok(IsEqualGUID(&info
->uCausality
, &causality
), "causality wasn't correct\n");
4398 struct new_hook_info
*new_info
= (struct new_hook_info
*)riid
;
4399 ok(new_info
->server_pid
== GetCurrentProcessId(), "server pid was 0x%x instead of 0x%x\n", new_info
->server_pid
,
4400 GetCurrentProcessId());
4401 ok(new_info
->server_tid
== server_tid
, "server tid was 0x%x instead of 0x%x\n", new_info
->server_tid
,
4403 ok(new_info
->method
== method
, "method was %d instead of %d\n", new_info
->method
, method
);
4404 ok(IsEqualGUID(&new_info
->causality
, &causality
), "causality wasn't correct\n");
4407 ok(IsEqualGUID(uExtent
, &EXTENTID_WineTest
), "uExtent wasn't correct\n");
4409 *(unsigned char *)pDataBuffer
= 0xcc;
4413 static void WINAPI
TestChannelHook_ClientNotify(
4414 IChannelHook
*iface
,
4422 SChannelHookCallInfo
*info
= (SChannelHookCallInfo
*)riid
;
4423 trace("TestChannelHook_ClientNotify hrFault = 0x%08x\n", hrFault
);
4425 if (!new_hook_struct
)
4427 ok(info
->cbSize
== sizeof(*info
), "cbSize was %d instead of %d\n", info
->cbSize
, (int)sizeof(*info
));
4428 ok(info
->dwServerPid
== GetCurrentProcessId(), "dwServerPid was 0x%x instead of 0x%x\n", info
->dwServerPid
, GetCurrentProcessId());
4429 ok(info
->iMethod
== method
, "iMethod was %d should be %d\n", info
->iMethod
, method
);
4431 ok(info
->pObject
!= NULL
, "pObject shouldn't be NULL\n");
4433 ok(IsEqualGUID(&info
->uCausality
, &causality
), "causality wasn't correct\n");
4437 struct new_hook_info
*new_info
= (struct new_hook_info
*)riid
;
4438 ok(new_info
->server_pid
== GetCurrentProcessId(), "server pid was 0x%x instead of 0x%x\n", new_info
->server_pid
,
4439 GetCurrentProcessId());
4440 ok(new_info
->server_tid
== server_tid
, "server tid was 0x%x instead of 0x%x\n", new_info
->server_tid
,
4442 ok(new_info
->method
== method
, "method was %d instead of %d\n", new_info
->method
, method
);
4443 ok(IsEqualGUID(&new_info
->causality
, &causality
), "causality wasn't correct\n");
4446 ok(IsEqualGUID(uExtent
, &EXTENTID_WineTest
), "uExtent wasn't correct\n");
4449 static void WINAPI
TestChannelHook_ServerNotify(
4450 IChannelHook
*iface
,
4457 SChannelHookCallInfo
*info
= (SChannelHookCallInfo
*)riid
;
4458 trace("TestChannelHook_ServerNotify\n");
4460 if (!new_hook_struct
)
4462 ok(info
->cbSize
== sizeof(*info
), "cbSize was %d instead of %d\n", info
->cbSize
, (int)sizeof(*info
));
4463 ok(info
->dwServerPid
== GetCurrentProcessId(), "dwServerPid was 0x%x instead of 0x%x\n", info
->dwServerPid
, GetCurrentProcessId());
4464 ok(info
->iMethod
== method
, "iMethod was %d should be %d\n", info
->iMethod
, method
);
4465 ok(info
->pObject
!= NULL
, "pObject shouldn't be NULL\n");
4466 ok(IsEqualGUID(&info
->uCausality
, &causality
), "causality wasn't correct\n");
4470 struct new_hook_info
*new_info
= (struct new_hook_info
*)riid
;
4471 ok(new_info
->server_pid
== GetCurrentProcessId(), "server pid was 0x%x instead of 0x%x\n", new_info
->server_pid
,
4472 GetCurrentProcessId());
4473 ok(new_info
->server_tid
== server_tid
, "server tid was 0x%x instead of 0x%x\n", new_info
->server_tid
,
4475 ok(new_info
->method
== method
, "method was %d instead of %d\n", new_info
->method
, method
);
4476 ok(IsEqualGUID(&new_info
->causality
, &causality
), "causality wasn't correct\n");
4479 ok(cbDataSize
== 1, "cbDataSize should have been 1 instead of %d\n", cbDataSize
);
4480 ok(*(unsigned char *)pDataBuffer
== 0xcc, "pDataBuffer should have contained 0xcc instead of 0x%x\n", *(unsigned char *)pDataBuffer
);
4481 ok(IsEqualGUID(uExtent
, &EXTENTID_WineTest
), "uExtent wasn't correct\n");
4484 static void WINAPI
TestChannelHook_ServerGetSize(
4485 IChannelHook
*iface
,
4491 SChannelHookCallInfo
*info
= (SChannelHookCallInfo
*)riid
;
4492 trace("TestChannelHook_ServerGetSize\n");
4493 trace("\t%s\n", debugstr_iid(riid
));
4494 if (!new_hook_struct
)
4496 ok(info
->cbSize
== sizeof(*info
), "cbSize was %d instead of %d\n", info
->cbSize
, (int)sizeof(*info
));
4497 ok(info
->dwServerPid
== GetCurrentProcessId(), "dwServerPid was 0x%x instead of 0x%x\n", info
->dwServerPid
, GetCurrentProcessId());
4498 ok(info
->iMethod
== method
, "iMethod was %d should be %d\n", info
->iMethod
, method
);
4499 ok(info
->pObject
!= NULL
, "pObject shouldn't be NULL\n");
4500 ok(IsEqualGUID(&info
->uCausality
, &causality
), "causality wasn't correct\n");
4504 struct new_hook_info
*new_info
= (struct new_hook_info
*)riid
;
4505 ok(new_info
->server_pid
== GetCurrentProcessId(), "server pid was 0x%x instead of 0x%x\n", new_info
->server_pid
,
4506 GetCurrentProcessId());
4507 ok(new_info
->server_tid
== server_tid
, "server tid was 0x%x instead of 0x%x\n", new_info
->server_tid
,
4509 ok(new_info
->method
== method
, "method was %d instead of %d\n", new_info
->method
, method
);
4510 ok(IsEqualGUID(&new_info
->causality
, &causality
), "causality wasn't correct\n");
4513 ok(IsEqualGUID(uExtent
, &EXTENTID_WineTest
), "uExtent wasn't correct\n");
4514 if (hrFault
!= S_OK
)
4515 trace("\thrFault = 0x%08x\n", hrFault
);
4520 static void WINAPI
TestChannelHook_ServerFillBuffer(
4521 IChannelHook
*iface
,
4528 trace("TestChannelHook_ServerFillBuffer\n");
4529 ok(0, "TestChannelHook_ServerFillBuffer shouldn't be called\n");
4532 static const IChannelHookVtbl TestChannelHookVtbl
=
4534 TestChannelHook_QueryInterface
,
4535 TestChannelHook_AddRef
,
4536 TestChannelHook_Release
,
4537 TestChannelHook_ClientGetSize
,
4538 TestChannelHook_ClientFillBuffer
,
4539 TestChannelHook_ClientNotify
,
4540 TestChannelHook_ServerNotify
,
4541 TestChannelHook_ServerGetSize
,
4542 TestChannelHook_ServerFillBuffer
,
4545 static IChannelHook TestChannelHook
= { &TestChannelHookVtbl
};
4547 static void test_channel_hook(void)
4549 IClassFactory
*cf
= NULL
;
4551 IUnknown
*proxy
= NULL
;
4555 struct host_object_data object_data
= { NULL
, &IID_IClassFactory
, (IUnknown
*)&Test_ClassFactory
,
4556 MSHLFLAGS_NORMAL
, &MessageFilter
};
4558 hr
= CoRegisterChannelHook(&EXTENTID_WineTest
, &TestChannelHook
);
4559 ok_ole_success(hr
, CoRegisterChannelHook
);
4561 hr
= CoRegisterMessageFilter(&MessageFilter
, NULL
);
4562 ok_ole_success(hr
, CoRegisterMessageFilter
);
4566 hr
= CreateStreamOnHGlobal(NULL
, TRUE
, &object_data
.stream
);
4567 ok_ole_success(hr
, CreateStreamOnHGlobal
);
4568 tid
= start_host_object2(&object_data
, &thread
);
4571 ok_more_than_one_lock();
4573 IStream_Seek(object_data
.stream
, ullZero
, STREAM_SEEK_SET
, NULL
);
4574 hr
= CoUnmarshalInterface(object_data
.stream
, &IID_IClassFactory
, (void **)&cf
);
4575 ok_ole_success(hr
, CoUnmarshalInterface
);
4576 IStream_Release(object_data
.stream
);
4578 ok_more_than_one_lock();
4581 hr
= IClassFactory_CreateInstance(cf
, NULL
, &IID_IUnknown
, (LPVOID
*)&proxy
);
4582 ok_ole_success(hr
, IClassFactory_CreateInstance
);
4585 IUnknown_Release(proxy
);
4587 IClassFactory_Release(cf
);
4591 end_host_object(tid
, thread
);
4593 hr
= CoRegisterMessageFilter(NULL
, NULL
);
4594 ok_ole_success(hr
, CoRegisterMessageFilter
);
4599 HMODULE hOle32
= GetModuleHandleA("ole32");
4603 if (!GetProcAddress(hOle32
, "CoRegisterSurrogateEx")) {
4604 win_skip("skipping test on win9x\n");
4608 pCoInitializeEx
= (void*)GetProcAddress(hOle32
, "CoInitializeEx");
4609 pDllGetClassObject
= (void*)GetProcAddress(hOle32
, "DllGetClassObject");
4611 argc
= winetest_get_mainargs( &argv
);
4612 if (argc
> 2 && (!strcmp(argv
[2], "-Embedding")))
4614 pCoInitializeEx(NULL
, COINIT_MULTITHREADED
);
4615 test_register_local_server();
4621 register_test_window();
4623 test_cocreateinstance_proxy();
4624 test_implicit_mta();
4626 pCoInitializeEx(NULL
, COINIT_APARTMENTTHREADED
);
4628 /* FIXME: test CoCreateInstanceEx */
4630 /* lifecycle management and marshaling tests */
4633 test_no_marshaler();
4634 test_normal_marshal_and_release();
4635 test_normal_marshal_and_unmarshal();
4636 test_marshal_and_unmarshal_invalid();
4637 test_same_apartment_unmarshal_failure();
4638 test_interthread_marshal_and_unmarshal();
4639 test_proxy_marshal_and_unmarshal();
4640 test_proxy_marshal_and_unmarshal2();
4641 test_proxy_marshal_and_unmarshal_weak();
4642 test_proxy_marshal_and_unmarshal_strong();
4643 test_marshal_stub_apartment_shutdown();
4644 test_marshal_proxy_apartment_shutdown();
4645 test_marshal_proxy_mta_apartment_shutdown();
4646 test_no_couninitialize_server();
4647 test_no_couninitialize_client();
4648 test_tableweak_marshal_and_unmarshal_twice();
4649 test_tableweak_marshal_releasedata1();
4650 test_tableweak_marshal_releasedata2();
4651 test_tableweak_and_normal_marshal_and_unmarshal();
4652 test_tableweak_and_normal_marshal_and_releasedata();
4653 test_two_tableweak_marshal_and_releasedata();
4654 test_tablestrong_marshal_and_unmarshal_twice();
4655 test_lock_object_external();
4656 test_disconnect_stub();
4657 test_normal_marshal_and_unmarshal_twice();
4659 with_external_conn
= !with_external_conn
;
4660 } while (with_external_conn
);
4662 test_marshal_channel_buffer();
4663 test_StdMarshal_custom_marshaling();
4664 test_DfMarshal_custom_marshaling();
4665 test_CoGetStandardMarshal();
4666 test_hresult_marshaling();
4667 test_proxy_used_in_wrong_thread();
4668 test_message_filter();
4669 test_bad_marshal_stream();
4670 test_proxy_interfaces();
4671 test_stubbuffer(&IID_IClassFactory
);
4672 test_proxybuffer(&IID_IClassFactory
);
4673 test_message_reentrancy();
4674 test_call_from_message();
4675 test_WM_QUIT_handling();
4676 test_freethreadedmarshaler();
4677 test_inproc_handler();
4678 test_handler_marshaling();
4679 test_client_security();
4681 test_local_server();
4683 test_globalinterfacetable();
4684 test_manualresetevent();
4685 test_crash_couninitialize();
4687 /* must be last test as channel hooks can't be unregistered */
4688 test_channel_hook();