mfplat: Implement GetScanline0AndPitch() for d3d11 buffers.
[wine/zf.git] / dlls / ole32 / tests / marshal.c
blob891df59c54b7304e9bd77c526e89b0db43604d42
1 /*
2 * Marshaling Tests
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
21 #define _WIN32_DCOM
22 #define COBJMACROS
23 #define CONST_VTABLE
25 #include <stdarg.h>
26 #include <stdio.h>
28 #include "windef.h"
29 #include "winbase.h"
30 #include "objbase.h"
31 #include "olectl.h"
32 #include "shlguid.h"
33 #include "shobjidl.h"
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) \
45 do { \
46 ok(expect_ ##func, "unexpected call " #func "\n"); \
47 called_ ## func = TRUE; \
48 }while(0)
50 #define CHECK_EXPECT(func) \
51 do { \
52 CHECK_EXPECT2(func); \
53 expect_ ## func = FALSE; \
54 }while(0)
56 #define CHECK_CALLED(func) \
57 do { \
58 ok(called_ ## func, "expected " #func "\n"); \
59 expect_ ## func = called_ ## func = FALSE; \
60 }while(0)
62 static const GUID CLSID_WineTestPSFactoryBuffer = { 0x22222222, 0x1234, 0x1234, { 0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0 } };
63 static const GUID CLSID_DfMarshal = { 0x0000030b, 0x0000, 0x0000, { 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46 } };
64 static const GUID CLSID_ft_unmarshaler_1809 = {0x00000359, 0x0000, 0x0000, {0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46}};
66 /* functions that are not present on all versions of Windows */
67 static HRESULT (WINAPI *pDllGetClassObject)(REFCLSID,REFIID,LPVOID);
69 /* helper macros to make tests a bit leaner */
70 #define ok_more_than_one_lock() ok(cLocks > 0, "Number of locks should be > 0, but actually is %d\n", cLocks)
71 #define ok_no_locks() ok(cLocks == 0, "Number of locks should be 0, but actually is %d\n", cLocks)
72 #define ok_ole_success(hr, func) ok(hr == S_OK, #func " failed with error 0x%08x\n", hr)
73 #define ok_non_zero_external_conn() do {if (with_external_conn) ok(external_connections, "got no external connections\n");} while(0);
74 #define ok_zero_external_conn() do {if (with_external_conn) ok(!external_connections, "got %d external connections\n", external_connections);} while(0);
75 #define ok_last_release_closes(b) do {if (with_external_conn) ok(last_release_closes == b, "got %d expected %d\n", last_release_closes, b);} while(0);
77 #define OBJREF_SIGNATURE (0x574f454d)
78 #define OBJREF_STANDARD (0x1)
79 #define OBJREF_CUSTOM (0x4)
81 typedef struct tagDUALSTRINGARRAY {
82 unsigned short wNumEntries;
83 unsigned short wSecurityOffset;
84 unsigned short aStringArray[1];
85 } DUALSTRINGARRAY;
87 typedef UINT64 OXID;
88 typedef UINT64 OID;
89 typedef GUID IPID;
91 typedef struct tagSTDOBJREF {
92 ULONG flags;
93 ULONG cPublicRefs;
94 OXID oxid;
95 OID oid;
96 IPID ipid;
97 } STDOBJREF;
99 typedef struct tagOBJREF {
100 ULONG signature;
101 ULONG flags;
102 GUID iid;
103 union {
104 struct OR_STANDARD {
105 STDOBJREF std;
106 DUALSTRINGARRAY saResAddr;
107 } u_standard;
108 struct OR_HANDLER {
109 STDOBJREF std;
110 CLSID clsid;
111 DUALSTRINGARRAY saResAddr;
112 } u_handler;
113 struct OR_CUSTOM {
114 CLSID clsid;
115 ULONG cbExtension;
116 ULONG size;
117 byte *pData;
118 } u_custom;
119 } u_objref;
120 } OBJREF;
122 static const IID IID_IWineTest =
124 0x5201163f,
125 0x8164,
126 0x4fd0,
127 {0xa1, 0xa2, 0x5d, 0x5a, 0x36, 0x54, 0xd3, 0xbd}
128 }; /* 5201163f-8164-4fd0-a1a2-5d5a3654d3bd */
130 static const IID IID_IRemUnknown =
132 0x00000131,
133 0x0000,
134 0x0000,
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 =
143 0x5201163f,
144 0x8164,
145 0x4fd0,
146 {0xa1, 0xa2, 0x5d, 0x5a, 0x36, 0x54, 0xd3, 0xbd}
147 }; /* 5201163f-8164-4fd0-a1a2-5d5a3654d3bd */
149 static void test_cocreateinstance_proxy(void)
151 IUnknown *pProxy;
152 IMultiQI *pMQI;
153 HRESULT hr;
155 CoInitializeEx(NULL, COINIT_MULTITHREADED);
157 hr = CoCreateInstance(&CLSID_ShellDesktop, NULL, CLSCTX_INPROC, &IID_IUnknown, (void **)&pProxy);
158 ok_ole_success(hr, CoCreateInstance);
159 hr = IUnknown_QueryInterface(pProxy, &IID_IMultiQI, (void **)&pMQI);
160 ok(hr == S_OK, "created object is not a proxy, so was created in the wrong apartment\n");
161 if (hr == S_OK)
162 IMultiQI_Release(pMQI);
163 IUnknown_Release(pProxy);
165 CoUninitialize();
168 static const LARGE_INTEGER ullZero;
169 static LONG cLocks;
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");
188 *ppv = NULL;
189 return E_NOINTERFACE;
192 static ULONG WINAPI ExternalConnection_AddRef(IExternalConnection *iface)
194 return 2;
197 static ULONG WINAPI ExternalConnection_Release(IExternalConnection *iface)
199 return 1;
202 static DWORD WINAPI ExternalConnection_AddConnection(IExternalConnection *iface, DWORD extconn, DWORD reserved)
204 if (winetest_debug > 1) trace("add connection\n");
205 return ++external_connections;
209 static DWORD WINAPI ExternalConnection_ReleaseConnection(IExternalConnection *iface, DWORD extconn,
210 DWORD reserved, BOOL fLastReleaseCloses)
212 if (winetest_debug > 1) trace("release connection %d\n", fLastReleaseCloses);
213 last_release_closes = fLastReleaseCloses;
214 return --external_connections;
217 static const IExternalConnectionVtbl ExternalConnectionVtbl = {
218 ExternalConnection_QueryInterface,
219 ExternalConnection_AddRef,
220 ExternalConnection_Release,
221 ExternalConnection_AddConnection,
222 ExternalConnection_ReleaseConnection
225 static IExternalConnection ExternalConnection = { &ExternalConnectionVtbl };
228 static HRESULT WINAPI Test_IUnknown_QueryInterface(
229 LPUNKNOWN iface,
230 REFIID riid,
231 LPVOID *ppvObj)
233 if (ppvObj == NULL) return E_POINTER;
235 if (IsEqualGUID(riid, &IID_IUnknown))
237 *ppvObj = iface;
238 IUnknown_AddRef(iface);
239 return S_OK;
242 *ppvObj = NULL;
243 return E_NOINTERFACE;
246 static ULONG WINAPI Test_IUnknown_AddRef(LPUNKNOWN iface)
248 LockModule();
249 return 2; /* non-heap-based object */
252 static ULONG WINAPI Test_IUnknown_Release(LPUNKNOWN iface)
254 UnlockModule();
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)
269 UnlockModule();
270 if(!cLocks) {
271 trace("crashing...\n");
272 *(int**)0xc = 0;
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,
288 REFIID riid,
289 LPVOID *ppvObj)
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))
298 *ppvObj = iface;
299 IClassFactory_AddRef(iface);
300 return S_OK;
303 if (with_external_conn && IsEqualGUID(riid, &IID_IExternalConnection))
305 *ppvObj = &ExternalConnection;
306 return S_OK;
309 *ppvObj = NULL;
310 return E_NOINTERFACE;
313 static ULONG WINAPI Test_IClassFactory_AddRef(LPCLASSFACTORY iface)
315 LockModule();
316 return 2; /* non-heap-based object */
319 static ULONG WINAPI Test_IClassFactory_Release(LPCLASSFACTORY iface)
321 UnlockModule();
322 return 1; /* non-heap-based object */
325 static HRESULT WINAPI Test_IClassFactory_CreateInstance(
326 LPCLASSFACTORY iface,
327 LPUNKNOWN pUnkOuter,
328 REFIID riid,
329 LPVOID *ppvObj)
331 if (pUnkOuter) return CLASS_E_NOAGGREGATION;
332 return IUnknown_QueryInterface(&Test_Unknown, riid, ppvObj);
335 static HRESULT WINAPI Test_IClassFactory_LockServer(
336 LPCLASSFACTORY iface,
337 BOOL fLock)
339 return S_OK;
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));
362 *ppv = NULL;
363 return E_NOINTERFACE;
366 static ULONG WINAPI OleWindow_AddRef(IOleWindow *iface)
368 return 2;
371 static ULONG WINAPI OleWindow_Release(IOleWindow *iface)
373 return 1;
376 static HRESULT WINAPI OleWindow_GetWindow(IOleWindow *iface, HWND *hwnd)
378 CHECK_EXPECT(GetWindow);
379 *hwnd = (HWND)0xdeadbeef;
380 return S_OK;
383 static const IOleWindowVtbl OleWindowVtbl = {
384 OleWindow_QueryInterface,
385 OleWindow_AddRef,
386 OleWindow_Release,
387 OleWindow_GetWindow,
388 /* not needed */
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))
396 *ppv = iface;
397 else if (IsEqualGUID(riid, &IID_IOleWindow))
398 *ppv = &Test_OleWindow;
399 else
401 *ppv = NULL;
402 return E_NOINTERFACE;
405 IUnknown_AddRef((IUnknown*)*ppv);
406 return S_OK;
409 static ULONG WINAPI OleClientSite_AddRef(IOleClientSite *iface)
411 return 2;
414 static ULONG WINAPI OleClientSite_Release(IOleClientSite *iface)
416 return 1;
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 };
428 typedef struct {
429 IRpcStubBuffer IRpcStubBuffer_iface;
430 LONG ref;
431 IRpcStubBuffer *buffer;
432 } StubBufferWrapper;
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;
445 }else {
446 *ppv = NULL;
447 return E_NOINTERFACE;
450 IUnknown_AddRef((IUnknown*)*ppv);
451 return S_OK;
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);
464 if(!ref) {
465 IRpcStubBuffer_Release(This->buffer);
466 heap_free(This);
468 return ref;
471 static HRESULT WINAPI RpcStubBuffer_Connect(IRpcStubBuffer *iface, IUnknown *pUnkServer)
473 ok(0, "unexpected call\n");
474 return E_NOTIMPL;
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;
487 DWORD dest_context;
488 HRESULT hr;
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");
503 return NULL;
506 static ULONG WINAPI RpcStubBuffer_CountRefs(IRpcStubBuffer *iface)
508 ok(0, "unexpected call\n");
509 return E_NOTIMPL;
512 static HRESULT WINAPI RpcStubBuffer_DebugServerQueryInterface(IRpcStubBuffer *iface, void **ppv)
514 ok(0, "unexpected call\n");
515 return E_NOTIMPL;
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))
541 *ppv = iface;
542 else
544 *ppv = NULL;
545 return E_NOINTERFACE;
547 IUnknown_AddRef((IUnknown*)*ppv);
548 return S_OK;
551 static ULONG WINAPI PSFactoryBuffer_AddRef(IPSFactoryBuffer *iface)
553 return 2;
556 static ULONG WINAPI PSFactoryBuffer_Release(IPSFactoryBuffer *iface)
558 return 1;
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;
572 HRESULT hr;
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;
580 stub->ref = 1;
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;
586 return S_OK;
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
604 IStream *stream;
605 const IID *iid;
606 IUnknown *object;
607 MSHLFLAGS marshal_flags;
608 IMessageFilter *filter;
609 IUnknown *register_object;
610 const CLSID *register_clsid;
611 HANDLE marshal_event;
614 static IPSFactoryBuffer PSFactoryBuffer;
616 static DWORD CALLBACK host_object_proc(LPVOID p)
618 struct host_object_data *data = p;
619 DWORD registration_key;
620 HRESULT hr;
621 MSG msg;
623 CoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
625 if(data->register_object) {
626 hr = CoRegisterClassObject(data->register_clsid, data->register_object,
627 CLSCTX_INPROC_SERVER, REGCLS_MULTIPLEUSE, &registration_key);
628 ok(hr == S_OK, "CoRegisterClassObject failed: %08x\n", hr);
631 if (data->filter)
633 IMessageFilter * prev_filter = NULL;
634 hr = CoRegisterMessageFilter(data->filter, &prev_filter);
635 if (prev_filter) IMessageFilter_Release(prev_filter);
636 ok_ole_success(hr, CoRegisterMessageFilter);
639 hr = CoMarshalInterface(data->stream, data->iid, data->object, MSHCTX_INPROC, NULL, data->marshal_flags);
640 ok_ole_success(hr, CoMarshalInterface);
642 /* force the message queue to be created before signaling parent thread */
643 PeekMessageA(&msg, NULL, WM_USER, WM_USER, PM_NOREMOVE);
645 SetEvent(data->marshal_event);
647 while (GetMessageA(&msg, NULL, 0, 0))
649 if (msg.hwnd == NULL && msg.message == RELEASEMARSHALDATA)
651 CoReleaseMarshalData(data->stream);
652 SetEvent((HANDLE)msg.lParam);
654 else
655 DispatchMessageA(&msg);
658 HeapFree(GetProcessHeap(), 0, data);
660 CoUninitialize();
662 return hr;
665 static DWORD start_host_object2(struct host_object_data *object_data, HANDLE *thread)
667 DWORD tid = 0;
668 struct host_object_data *data;
670 data = HeapAlloc(GetProcessHeap(), 0, sizeof(*data));
671 *data = *object_data;
672 data->marshal_event = CreateEventA(NULL, FALSE, FALSE, NULL);
673 *thread = CreateThread(NULL, 0, host_object_proc, data, 0, &tid);
675 /* wait for marshaling to complete before returning */
676 ok( !WaitForSingleObject(data->marshal_event, 10000), "wait timed out\n" );
677 CloseHandle(data->marshal_event);
679 return tid;
682 static DWORD start_host_object(IStream *stream, REFIID riid, IUnknown *object, MSHLFLAGS marshal_flags, HANDLE *thread)
684 struct host_object_data object_data = { stream, riid, object, marshal_flags };
685 return start_host_object2(&object_data, thread);
688 /* asks thread to release the marshal data because it has to be done by the
689 * same thread that marshaled the interface in the first place. */
690 static void release_host_object(DWORD tid, WPARAM wp)
692 HANDLE event = CreateEventA(NULL, FALSE, FALSE, NULL);
693 PostThreadMessageA(tid, RELEASEMARSHALDATA, wp, (LPARAM)event);
694 ok( !WaitForSingleObject(event, 10000), "wait timed out\n" );
695 CloseHandle(event);
698 static void end_host_object(DWORD tid, HANDLE thread)
700 BOOL ret = PostThreadMessageA(tid, WM_QUIT, 0, 0);
701 ok(ret, "PostThreadMessage failed with error %d\n", GetLastError());
702 /* be careful of races - don't return until hosting thread has terminated */
703 ok( !WaitForSingleObject(thread, 10000), "wait timed out\n" );
704 CloseHandle(thread);
707 /* tests failure case of interface not having a marshaler specified in the
708 * registry */
709 static void test_no_marshaler(void)
711 IStream *pStream;
712 HRESULT hr;
714 hr = CreateStreamOnHGlobal(NULL, TRUE, &pStream);
715 ok_ole_success(hr, CreateStreamOnHGlobal);
716 hr = CoMarshalInterface(pStream, &IID_IWineTest, (IUnknown*)&Test_ClassFactory, MSHCTX_INPROC, NULL, MSHLFLAGS_NORMAL);
717 ok(hr == E_NOINTERFACE, "CoMarshalInterface should have returned E_NOINTERFACE instead of 0x%08x\n", hr);
719 IStream_Release(pStream);
722 /* tests normal marshal and then release without unmarshaling */
723 static void test_normal_marshal_and_release(void)
725 HRESULT hr;
726 IStream *pStream = NULL;
728 cLocks = 0;
729 external_connections = 0;
731 hr = CreateStreamOnHGlobal(NULL, TRUE, &pStream);
732 ok_ole_success(hr, CreateStreamOnHGlobal);
733 hr = CoMarshalInterface(pStream, &IID_IClassFactory, (IUnknown*)&Test_ClassFactory, MSHCTX_INPROC, NULL, MSHLFLAGS_NORMAL);
734 ok_ole_success(hr, CoMarshalInterface);
736 ok_more_than_one_lock();
737 ok_non_zero_external_conn();
739 IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
740 hr = CoReleaseMarshalData(pStream);
741 ok_ole_success(hr, CoReleaseMarshalData);
742 IStream_Release(pStream);
744 ok_no_locks();
745 ok_zero_external_conn();
746 ok_last_release_closes(TRUE);
749 /* tests success case of a same-thread marshal and unmarshal */
750 static void test_normal_marshal_and_unmarshal(void)
752 HRESULT hr;
753 IStream *pStream = NULL;
754 IUnknown *pProxy = NULL;
756 cLocks = 0;
757 external_connections = 0;
759 hr = CreateStreamOnHGlobal(NULL, TRUE, &pStream);
760 ok_ole_success(hr, CreateStreamOnHGlobal);
761 hr = CoMarshalInterface(pStream, &IID_IClassFactory, (IUnknown*)&Test_ClassFactory, MSHCTX_INPROC, NULL, MSHLFLAGS_NORMAL);
762 ok_ole_success(hr, CoMarshalInterface);
764 ok_more_than_one_lock();
765 ok_non_zero_external_conn();
767 IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
768 hr = CoUnmarshalInterface(pStream, &IID_IClassFactory, (void **)&pProxy);
769 ok_ole_success(hr, CoUnmarshalInterface);
770 IStream_Release(pStream);
772 ok_more_than_one_lock();
773 ok_zero_external_conn();
774 ok_last_release_closes(FALSE);
776 IUnknown_Release(pProxy);
778 ok_no_locks();
781 /* tests failure case of unmarshaling a freed object */
782 static void test_marshal_and_unmarshal_invalid(void)
784 HRESULT hr;
785 IStream *pStream = NULL;
786 IClassFactory *pProxy = NULL;
787 DWORD tid;
788 void * dummy;
789 HANDLE thread;
791 cLocks = 0;
792 external_connections = 0;
794 hr = CreateStreamOnHGlobal(NULL, TRUE, &pStream);
795 ok_ole_success(hr, CreateStreamOnHGlobal);
796 tid = start_host_object(pStream, &IID_IClassFactory, (IUnknown*)&Test_ClassFactory, MSHLFLAGS_NORMAL, &thread);
798 ok_more_than_one_lock();
799 ok_non_zero_external_conn();
801 IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
802 hr = CoReleaseMarshalData(pStream);
803 ok_ole_success(hr, CoReleaseMarshalData);
805 ok_no_locks();
806 ok_zero_external_conn();
807 ok_last_release_closes(TRUE);
809 IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
810 hr = CoUnmarshalInterface(pStream, &IID_IClassFactory, (void **)&pProxy);
811 todo_wine { ok_ole_success(hr, CoUnmarshalInterface); }
813 ok_no_locks();
815 if (pProxy)
817 hr = IClassFactory_CreateInstance(pProxy, NULL, &IID_IUnknown, &dummy);
818 ok(hr == RPC_E_DISCONNECTED, "Remote call should have returned RPC_E_DISCONNECTED, instead of 0x%08x\n", hr);
820 IClassFactory_Release(pProxy);
823 IStream_Release(pStream);
825 end_host_object(tid, thread);
828 static void test_same_apartment_unmarshal_failure(void)
830 HRESULT hr;
831 IStream *pStream;
832 IUnknown *pProxy;
833 static const LARGE_INTEGER llZero;
835 cLocks = 0;
836 external_connections = 0;
838 hr = CreateStreamOnHGlobal(NULL, TRUE, &pStream);
839 ok_ole_success(hr, CreateStreamOnHGlobal);
841 hr = CoMarshalInterface(pStream, &IID_IUnknown, (IUnknown *)&Test_ClassFactory, MSHCTX_INPROC, NULL, MSHLFLAGS_NORMAL);
842 ok_ole_success(hr, CoMarshalInterface);
844 ok_more_than_one_lock();
845 ok_non_zero_external_conn();
847 hr = IStream_Seek(pStream, llZero, STREAM_SEEK_SET, NULL);
848 ok_ole_success(hr, IStream_Seek);
850 hr = CoUnmarshalInterface(pStream, &IID_IParseDisplayName, (void **)&pProxy);
851 ok(hr == E_NOINTERFACE, "CoUnmarshalInterface should have returned E_NOINTERFACE instead of 0x%08x\n", hr);
853 ok_no_locks();
854 ok_zero_external_conn();
855 ok_last_release_closes(FALSE);
857 IStream_Release(pStream);
860 /* tests success case of an interthread marshal */
861 static void test_interthread_marshal_and_unmarshal(void)
863 HRESULT hr;
864 IStream *pStream = NULL;
865 IUnknown *pProxy = NULL;
866 DWORD tid;
867 HANDLE thread;
869 cLocks = 0;
870 external_connections = 0;
872 hr = CreateStreamOnHGlobal(NULL, TRUE, &pStream);
873 ok_ole_success(hr, CreateStreamOnHGlobal);
874 tid = start_host_object(pStream, &IID_IClassFactory, (IUnknown*)&Test_ClassFactory, MSHLFLAGS_NORMAL, &thread);
876 ok_more_than_one_lock();
877 ok_non_zero_external_conn();
879 IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
880 hr = CoUnmarshalInterface(pStream, &IID_IClassFactory, (void **)&pProxy);
881 ok_ole_success(hr, CoUnmarshalInterface);
882 IStream_Release(pStream);
884 ok_more_than_one_lock();
885 ok_non_zero_external_conn();
887 IUnknown_Release(pProxy);
889 ok_no_locks();
890 ok_zero_external_conn();
891 ok_last_release_closes(TRUE);
893 end_host_object(tid, thread);
896 /* the number of external references that Wine's proxy manager normally gives
897 * out, so we can test the border case of running out of references */
898 #define NORMALEXTREFS 5
900 /* tests success case of an interthread marshal and then marshaling the proxy */
901 static void test_proxy_marshal_and_unmarshal(void)
903 HRESULT hr;
904 IStream *pStream = NULL;
905 IUnknown *pProxy = NULL;
906 IUnknown *pProxy2 = NULL;
907 DWORD tid;
908 HANDLE thread;
909 int i;
911 cLocks = 0;
912 external_connections = 0;
914 hr = CreateStreamOnHGlobal(NULL, TRUE, &pStream);
915 ok_ole_success(hr, CreateStreamOnHGlobal);
916 tid = start_host_object(pStream, &IID_IClassFactory, (IUnknown*)&Test_ClassFactory, MSHLFLAGS_NORMAL, &thread);
918 ok_more_than_one_lock();
919 ok_non_zero_external_conn();
921 IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
922 hr = CoUnmarshalInterface(pStream, &IID_IClassFactory, (void **)&pProxy);
923 ok_ole_success(hr, CoUnmarshalInterface);
925 ok_more_than_one_lock();
927 IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
928 /* marshal the proxy */
929 hr = CoMarshalInterface(pStream, &IID_IClassFactory, pProxy, MSHCTX_INPROC, NULL, MSHLFLAGS_NORMAL);
930 ok_ole_success(hr, CoMarshalInterface);
932 ok_more_than_one_lock();
934 /* marshal 5 more times to exhaust the normal external references of 5 */
935 for (i = 0; i < NORMALEXTREFS; i++)
937 hr = CoMarshalInterface(pStream, &IID_IClassFactory, pProxy, MSHCTX_INPROC, NULL, MSHLFLAGS_NORMAL);
938 ok_ole_success(hr, CoMarshalInterface);
941 ok_more_than_one_lock();
943 /* release the original proxy to test that we successfully keep the
944 * original object alive */
945 IUnknown_Release(pProxy);
947 IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
948 hr = CoUnmarshalInterface(pStream, &IID_IClassFactory, (void **)&pProxy2);
949 ok_ole_success(hr, CoUnmarshalInterface);
951 ok_more_than_one_lock();
952 ok_non_zero_external_conn();
954 IUnknown_Release(pProxy2);
956 /* unmarshal all of the proxies to check that the object stub still exists */
957 for (i = 0; i < NORMALEXTREFS; i++)
959 hr = CoUnmarshalInterface(pStream, &IID_IClassFactory, (void **)&pProxy2);
960 ok_ole_success(hr, CoUnmarshalInterface);
962 IUnknown_Release(pProxy2);
965 ok_no_locks();
966 ok_zero_external_conn();
967 ok_last_release_closes(TRUE);
969 IStream_Release(pStream);
971 end_host_object(tid, thread);
974 /* tests success case of an interthread marshal and then marshaling the proxy
975 * using an iid that hasn't previously been unmarshaled */
976 static void test_proxy_marshal_and_unmarshal2(void)
978 HRESULT hr;
979 IStream *pStream = NULL;
980 IUnknown *pProxy = NULL;
981 IUnknown *pProxy2 = NULL;
982 DWORD tid;
983 HANDLE thread;
985 cLocks = 0;
986 external_connections = 0;
988 hr = CreateStreamOnHGlobal(NULL, TRUE, &pStream);
989 ok_ole_success(hr, CreateStreamOnHGlobal);
990 tid = start_host_object(pStream, &IID_IUnknown, (IUnknown*)&Test_ClassFactory, MSHLFLAGS_NORMAL, &thread);
992 ok_more_than_one_lock();
993 ok_non_zero_external_conn();
995 IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
996 hr = CoUnmarshalInterface(pStream, &IID_IUnknown, (void **)&pProxy);
997 ok_ole_success(hr, CoUnmarshalInterface);
999 ok_more_than_one_lock();
1001 IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
1002 /* marshal the proxy */
1003 hr = CoMarshalInterface(pStream, &IID_IClassFactory, pProxy, MSHCTX_INPROC, NULL, MSHLFLAGS_NORMAL);
1004 ok_ole_success(hr, CoMarshalInterface);
1006 ok_more_than_one_lock();
1008 IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
1009 /* unmarshal the second proxy to the object */
1010 hr = CoUnmarshalInterface(pStream, &IID_IClassFactory, (void **)&pProxy2);
1011 ok_ole_success(hr, CoUnmarshalInterface);
1012 IStream_Release(pStream);
1014 /* now the proxies should be as follows:
1015 * pProxy -> &Test_ClassFactory
1016 * pProxy2 -> &Test_ClassFactory
1017 * they should NOT be as follows:
1018 * pProxy -> &Test_ClassFactory
1019 * pProxy2 -> pProxy
1020 * the above can only really be tested by looking in +ole traces
1023 ok_more_than_one_lock();
1025 IUnknown_Release(pProxy);
1027 ok_more_than_one_lock();
1028 ok_non_zero_external_conn();
1030 IUnknown_Release(pProxy2);
1032 ok_no_locks();
1033 ok_zero_external_conn();
1034 ok_last_release_closes(TRUE);
1036 end_host_object(tid, thread);
1039 /* tests success case of an interthread marshal and then table-weak-marshaling the proxy */
1040 static void test_proxy_marshal_and_unmarshal_weak(void)
1042 HRESULT hr;
1043 IStream *pStream = NULL;
1044 IUnknown *pProxy = NULL;
1045 IUnknown *pProxy2 = NULL;
1046 DWORD tid;
1047 HANDLE thread;
1049 cLocks = 0;
1050 external_connections = 0;
1052 hr = CreateStreamOnHGlobal(NULL, TRUE, &pStream);
1053 ok_ole_success(hr, CreateStreamOnHGlobal);
1054 tid = start_host_object(pStream, &IID_IClassFactory, (IUnknown*)&Test_ClassFactory, MSHLFLAGS_NORMAL, &thread);
1056 ok_more_than_one_lock();
1057 ok_non_zero_external_conn();
1059 IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
1060 hr = CoUnmarshalInterface(pStream, &IID_IClassFactory, (void **)&pProxy);
1061 ok_ole_success(hr, CoUnmarshalInterface);
1063 ok_more_than_one_lock();
1064 ok_non_zero_external_conn();
1066 IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
1067 /* marshal the proxy */
1068 hr = CoMarshalInterface(pStream, &IID_IClassFactory, pProxy, MSHCTX_INPROC, NULL, MSHLFLAGS_TABLEWEAK);
1069 ok_ole_success(hr, CoMarshalInterface);
1071 ok_more_than_one_lock();
1072 ok_non_zero_external_conn();
1074 /* release the original proxy to test that we successfully keep the
1075 * original object alive */
1076 IUnknown_Release(pProxy);
1078 IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
1079 hr = CoUnmarshalInterface(pStream, &IID_IClassFactory, (void **)&pProxy2);
1080 todo_wine
1081 ok(hr == CO_E_OBJNOTREG, "CoUnmarshalInterface should return CO_E_OBJNOTREG instead of 0x%08x\n", hr);
1083 ok_no_locks();
1084 ok_zero_external_conn();
1085 ok_last_release_closes(TRUE);
1087 IStream_Release(pStream);
1089 end_host_object(tid, thread);
1092 /* tests success case of an interthread marshal and then table-strong-marshaling the proxy */
1093 static void test_proxy_marshal_and_unmarshal_strong(void)
1095 HRESULT hr;
1096 IStream *pStream = NULL;
1097 IUnknown *pProxy = NULL;
1098 IUnknown *pProxy2 = NULL;
1099 DWORD tid;
1100 HANDLE thread;
1102 cLocks = 0;
1103 external_connections = 0;
1105 hr = CreateStreamOnHGlobal(NULL, TRUE, &pStream);
1106 ok_ole_success(hr, CreateStreamOnHGlobal);
1107 tid = start_host_object(pStream, &IID_IClassFactory, (IUnknown*)&Test_ClassFactory, MSHLFLAGS_NORMAL, &thread);
1109 ok_more_than_one_lock();
1110 ok_non_zero_external_conn();
1112 IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
1113 hr = CoUnmarshalInterface(pStream, &IID_IClassFactory, (void **)&pProxy);
1114 ok_ole_success(hr, CoUnmarshalInterface);
1116 ok_more_than_one_lock();
1117 ok_non_zero_external_conn();
1119 IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
1120 /* marshal the proxy */
1121 hr = CoMarshalInterface(pStream, &IID_IClassFactory, pProxy, MSHCTX_INPROC, NULL, MSHLFLAGS_TABLESTRONG);
1122 ok(hr == S_OK, "Got hr %#x.\n", hr);
1124 ok_more_than_one_lock();
1125 ok_non_zero_external_conn();
1127 /* release the original proxy to test that we successfully keep the
1128 * original object alive */
1129 IUnknown_Release(pProxy);
1131 IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
1132 hr = CoUnmarshalInterface(pStream, &IID_IClassFactory, (void **)&pProxy2);
1133 ok_ole_success(hr, CoUnmarshalInterface);
1135 ok_more_than_one_lock();
1136 ok_non_zero_external_conn();
1138 IUnknown_Release(pProxy2);
1140 ok_more_than_one_lock();
1141 ok_non_zero_external_conn();
1143 IStream_Release(pStream);
1145 end_host_object(tid, thread);
1147 ok_no_locks();
1148 todo_wine {
1149 ok_zero_external_conn();
1150 ok_last_release_closes(FALSE);
1154 /* tests that stubs are released when the containing apartment is destroyed */
1155 static void test_marshal_stub_apartment_shutdown(void)
1157 HRESULT hr;
1158 IStream *pStream = NULL;
1159 IUnknown *pProxy = NULL;
1160 DWORD tid;
1161 HANDLE thread;
1163 cLocks = 0;
1164 external_connections = 0;
1166 hr = CreateStreamOnHGlobal(NULL, TRUE, &pStream);
1167 ok_ole_success(hr, CreateStreamOnHGlobal);
1168 tid = start_host_object(pStream, &IID_IClassFactory, (IUnknown*)&Test_ClassFactory, MSHLFLAGS_NORMAL, &thread);
1170 ok_more_than_one_lock();
1171 ok_non_zero_external_conn();
1173 IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
1174 hr = CoUnmarshalInterface(pStream, &IID_IClassFactory, (void **)&pProxy);
1175 ok_ole_success(hr, CoUnmarshalInterface);
1176 IStream_Release(pStream);
1178 ok_more_than_one_lock();
1179 ok_non_zero_external_conn();
1181 end_host_object(tid, thread);
1183 ok_no_locks();
1184 todo_wine {
1185 ok_zero_external_conn();
1186 ok_last_release_closes(FALSE);
1189 IUnknown_Release(pProxy);
1191 ok_no_locks();
1194 /* tests that proxies are released when the containing apartment is destroyed */
1195 static void test_marshal_proxy_apartment_shutdown(void)
1197 HRESULT hr;
1198 IStream *pStream = NULL;
1199 IClassFactory *proxy;
1200 IUnknown *unk;
1201 ULONG ref;
1202 DWORD tid;
1203 HANDLE thread;
1205 cLocks = 0;
1206 external_connections = 0;
1208 hr = CreateStreamOnHGlobal(NULL, TRUE, &pStream);
1209 ok_ole_success(hr, CreateStreamOnHGlobal);
1210 tid = start_host_object(pStream, &IID_IClassFactory, (IUnknown*)&Test_ClassFactory, MSHLFLAGS_NORMAL, &thread);
1212 ok_more_than_one_lock();
1213 ok_non_zero_external_conn();
1215 IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
1216 hr = CoUnmarshalInterface(pStream, &IID_IClassFactory, (void **)&proxy);
1217 ok_ole_success(hr, CoUnmarshalInterface);
1218 IStream_Release(pStream);
1220 ok_more_than_one_lock();
1221 ok_non_zero_external_conn();
1223 CoUninitialize();
1225 ok_no_locks();
1226 ok_zero_external_conn();
1227 ok_last_release_closes(TRUE);
1229 hr = IClassFactory_CreateInstance(proxy, NULL, &IID_IUnknown, (void **)&unk);
1230 ok(hr == CO_E_OBJNOTCONNECTED, "got %#x\n", hr);
1232 ref = IClassFactory_Release(proxy);
1233 ok(!ref, "got %d refs\n", ref);
1235 ok_no_locks();
1237 end_host_object(tid, thread);
1239 CoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
1242 /* tests that proxies are released when the containing mta apartment is destroyed */
1243 static void test_marshal_proxy_mta_apartment_shutdown(void)
1245 HRESULT hr;
1246 IStream *pStream = NULL;
1247 IUnknown *pProxy = NULL;
1248 DWORD tid;
1249 HANDLE thread;
1251 CoUninitialize();
1252 CoInitializeEx(NULL, COINIT_MULTITHREADED);
1254 cLocks = 0;
1255 external_connections = 0;
1257 hr = CreateStreamOnHGlobal(NULL, TRUE, &pStream);
1258 ok_ole_success(hr, CreateStreamOnHGlobal);
1259 tid = start_host_object(pStream, &IID_IClassFactory, (IUnknown*)&Test_ClassFactory, MSHLFLAGS_NORMAL, &thread);
1261 ok_more_than_one_lock();
1262 ok_non_zero_external_conn();
1264 IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
1265 hr = CoUnmarshalInterface(pStream, &IID_IClassFactory, (void **)&pProxy);
1266 ok_ole_success(hr, CoUnmarshalInterface);
1267 IStream_Release(pStream);
1269 ok_more_than_one_lock();
1270 ok_non_zero_external_conn();
1272 CoUninitialize();
1274 ok_no_locks();
1275 ok_zero_external_conn();
1276 ok_last_release_closes(TRUE);
1278 IUnknown_Release(pProxy);
1280 ok_no_locks();
1282 end_host_object(tid, thread);
1284 CoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
1287 static void test_marshal_channel_buffer(void)
1289 DWORD registration_key;
1290 IUnknown *proxy = NULL;
1291 IOleWindow *ole_window;
1292 HWND hwnd;
1293 CLSID clsid;
1294 DWORD tid;
1295 HANDLE thread;
1296 HRESULT hr;
1298 struct host_object_data object_data = { NULL, &IID_IOleClientSite, (IUnknown*)&Test_OleClientSite,
1299 MSHLFLAGS_NORMAL, NULL, (IUnknown*)&PSFactoryBuffer,
1300 &CLSID_WineTestPSFactoryBuffer };
1302 cLocks = 0;
1303 external_connections = 0;
1305 hr = CoGetPSClsid(&IID_IOleWindow, &clsid);
1306 ok_ole_success(hr, "CoGetPSClsid");
1308 hr = CoGetClassObject(&clsid, CLSCTX_INPROC_SERVER, NULL, &IID_IPSFactoryBuffer,
1309 (void **)&ps_factory_buffer);
1310 ok_ole_success(hr, "CoGetClassObject");
1312 hr = CreateStreamOnHGlobal(NULL, TRUE, &object_data.stream);
1313 ok_ole_success(hr, CreateStreamOnHGlobal);
1314 tid = start_host_object2(&object_data, &thread);
1316 IStream_Seek(object_data.stream, ullZero, STREAM_SEEK_SET, NULL);
1317 hr = CoUnmarshalInterface(object_data.stream, &IID_IUnknown, (void **)&proxy);
1318 ok_ole_success(hr, CoUnmarshalInterface);
1319 IStream_Release(object_data.stream);
1321 hr = CoRegisterClassObject(&CLSID_WineTestPSFactoryBuffer, (IUnknown *)&PSFactoryBuffer,
1322 CLSCTX_INPROC_SERVER, REGCLS_MULTIPLEUSE, &registration_key);
1323 ok(hr == S_OK, "CoRegisterClassObject failed: %08x\n", hr);
1325 hr = CoRegisterPSClsid(&IID_IOleWindow, &CLSID_WineTestPSFactoryBuffer);
1326 ok(hr == S_OK, "CoRegisterPSClsid failed: %08x\n", hr);
1328 SET_EXPECT(CreateStub);
1329 SET_EXPECT(CreateProxy);
1330 hr = IUnknown_QueryInterface(proxy, &IID_IOleWindow, (void**)&ole_window);
1331 ok(hr == S_OK, "Could not get IOleWindow iface: %08x\n", hr);
1332 CHECK_CALLED(CreateStub);
1333 CHECK_CALLED(CreateProxy);
1335 SET_EXPECT(Invoke);
1336 SET_EXPECT(GetWindow);
1337 hr = IOleWindow_GetWindow(ole_window, &hwnd);
1338 ok(hr == S_OK, "GetWindow failed: %08x\n", hr);
1339 ok((DWORD)(DWORD_PTR)hwnd == 0xdeadbeef, "hwnd = %p\n", hwnd);
1340 CHECK_CALLED(Invoke);
1341 CHECK_CALLED(GetWindow);
1343 IOleWindow_Release(ole_window);
1345 SET_EXPECT(Disconnect);
1346 IUnknown_Release(proxy);
1347 todo_wine
1348 CHECK_CALLED(Disconnect);
1350 hr = CoRevokeClassObject(registration_key);
1351 ok(hr == S_OK, "CoRevokeClassObject failed: %08x\n", hr);
1353 end_host_object(tid, thread);
1356 static const CLSID *unmarshal_class;
1357 DEFINE_EXPECT(CustomMarshal_GetUnmarshalClass);
1358 DEFINE_EXPECT(CustomMarshal_GetMarshalSizeMax);
1359 DEFINE_EXPECT(CustomMarshal_MarshalInterface);
1361 static HRESULT WINAPI CustomMarshal_QueryInterface(IMarshal *iface, REFIID riid, void **ppv)
1363 if (IsEqualIID(riid, &IID_IUnknown) || IsEqualIID(riid, &IID_IMarshal)) {
1364 *ppv = iface;
1366 else
1368 *ppv = NULL;
1369 return E_NOINTERFACE;
1371 IUnknown_AddRef((IUnknown*)*ppv);
1372 return S_OK;
1375 static ULONG WINAPI CustomMarshal_AddRef(IMarshal *iface)
1377 return 2;
1380 static ULONG WINAPI CustomMarshal_Release(IMarshal *iface)
1382 return 1;
1385 static HRESULT WINAPI CustomMarshal_GetUnmarshalClass(IMarshal *iface, REFIID riid,
1386 void *pv, DWORD dwDestContext, void *pvDestContext, DWORD mshlflags, CLSID *clsid)
1388 CHECK_EXPECT2(CustomMarshal_GetUnmarshalClass);
1389 *clsid = *unmarshal_class;
1390 return S_OK;
1393 static HRESULT WINAPI CustomMarshal_GetMarshalSizeMax(IMarshal *iface, REFIID riid,
1394 void *pv, DWORD dwDestContext, void *pvDestContext, DWORD mshlflags, DWORD *size)
1396 CHECK_EXPECT(CustomMarshal_GetMarshalSizeMax);
1397 ok(size != NULL, "size = NULL\n");
1399 *size = 0;
1400 return S_OK;
1403 static HRESULT WINAPI CustomMarshal_MarshalInterface(IMarshal *iface, IStream *stream,
1404 REFIID riid, void *pv, DWORD dwDestContext, void *pvDestContext, DWORD mshlflags)
1406 IMarshal *std_marshal;
1407 STATSTG stat;
1408 HRESULT hr;
1410 CHECK_EXPECT(CustomMarshal_MarshalInterface);
1412 if(unmarshal_class != &CLSID_StdMarshal)
1413 return S_OK;
1415 hr = IStream_Stat(stream, &stat, STATFLAG_DEFAULT);
1416 ok_ole_success(hr, IStream_Stat);
1417 ok(U(stat.cbSize).LowPart == 0, "stream is not empty (%d)\n", U(stat.cbSize).LowPart);
1418 ok(U(stat.cbSize).HighPart == 0, "stream is not empty (%d)\n", U(stat.cbSize).HighPart);
1420 hr = CoGetStandardMarshal(riid, (IUnknown*)iface,
1421 dwDestContext, NULL, mshlflags, &std_marshal);
1422 ok_ole_success(hr, CoGetStandardMarshal);
1423 hr = IMarshal_MarshalInterface(std_marshal, stream, riid, pv,
1424 dwDestContext, pvDestContext, mshlflags);
1425 ok_ole_success(hr, IMarshal_MarshalInterface);
1426 IMarshal_Release(std_marshal);
1428 return S_OK;
1431 static HRESULT WINAPI CustomMarshal_UnmarshalInterface(IMarshal *iface,
1432 IStream *stream, REFIID riid, void **ppv)
1434 ok(0, "unexpected call\n");
1435 return E_NOTIMPL;
1438 static HRESULT WINAPI CustomMarshal_ReleaseMarshalData(IMarshal *iface, IStream *stream)
1440 ok(0, "unexpected call\n");
1441 return E_NOTIMPL;
1444 static HRESULT WINAPI CustomMarshal_DisconnectObject(IMarshal *iface, DWORD res)
1446 ok(0, "unexpected call\n");
1447 return E_NOTIMPL;
1450 static IMarshalVtbl CustomMarshalVtbl =
1452 CustomMarshal_QueryInterface,
1453 CustomMarshal_AddRef,
1454 CustomMarshal_Release,
1455 CustomMarshal_GetUnmarshalClass,
1456 CustomMarshal_GetMarshalSizeMax,
1457 CustomMarshal_MarshalInterface,
1458 CustomMarshal_UnmarshalInterface,
1459 CustomMarshal_ReleaseMarshalData,
1460 CustomMarshal_DisconnectObject
1463 static IMarshal CustomMarshal = { &CustomMarshalVtbl };
1465 static void test_StdMarshal_custom_marshaling(void)
1467 IStream *stream;
1468 IUnknown *unk;
1469 DWORD size;
1470 HRESULT hr;
1472 hr = CreateStreamOnHGlobal(NULL, TRUE, &stream);
1473 ok_ole_success(hr, CreateStreamOnHGlobal);
1475 unmarshal_class = &CLSID_StdMarshal;
1476 SET_EXPECT(CustomMarshal_GetUnmarshalClass);
1477 SET_EXPECT(CustomMarshal_MarshalInterface);
1478 hr = CoMarshalInterface(stream, &IID_IUnknown, (IUnknown*)&CustomMarshal,
1479 MSHCTX_INPROC, NULL, MSHLFLAGS_NORMAL);
1480 ok_ole_success(hr, CoMarshalInterface);
1481 CHECK_CALLED(CustomMarshal_GetUnmarshalClass);
1482 CHECK_CALLED(CustomMarshal_MarshalInterface);
1484 hr = IStream_Seek(stream, ullZero, STREAM_SEEK_SET, NULL);
1485 ok_ole_success(hr, IStream_Seek);
1486 hr = CoUnmarshalInterface(stream, &IID_IUnknown, (void**)&unk);
1487 ok_ole_success(hr, CoUnmarshalInterface);
1488 ok(unk == (IUnknown*)&CustomMarshal, "unk != &CustomMarshal\n");
1489 IUnknown_Release(unk);
1490 IStream_Release(stream);
1492 hr = CreateStreamOnHGlobal(NULL, TRUE, &stream);
1493 ok_ole_success(hr, CreateStreamOnHGlobal);
1495 SET_EXPECT(CustomMarshal_GetUnmarshalClass);
1496 SET_EXPECT(CustomMarshal_MarshalInterface);
1497 hr = CoMarshalInterface(stream, &IID_IUnknown, (IUnknown*)&CustomMarshal,
1498 MSHCTX_INPROC, NULL, MSHLFLAGS_NORMAL);
1499 ok_ole_success(hr, CoMarshalInterface);
1500 CHECK_CALLED(CustomMarshal_GetUnmarshalClass);
1501 CHECK_CALLED(CustomMarshal_MarshalInterface);
1503 hr = IStream_Seek(stream, ullZero, STREAM_SEEK_SET, NULL);
1504 ok_ole_success(hr, IStream_Seek);
1505 hr = CoReleaseMarshalData(stream);
1506 ok_ole_success(hr, CoReleaseMarshalData);
1507 IStream_Release(stream);
1509 SET_EXPECT(CustomMarshal_GetMarshalSizeMax);
1510 hr = CoGetMarshalSizeMax(&size, &IID_IUnknown, (IUnknown*)&CustomMarshal,
1511 MSHCTX_INPROC, NULL, MSHLFLAGS_NORMAL);
1512 ok_ole_success(hr, CoGetMarshalSizeMax);
1513 CHECK_CALLED(CustomMarshal_GetMarshalSizeMax);
1514 ok(size == sizeof(OBJREF), "size = %d, expected %d\n", size, (int)sizeof(OBJREF));
1517 static void test_DfMarshal_custom_marshaling(void)
1519 DWORD size, read;
1520 IStream *stream;
1521 OBJREF objref;
1522 HRESULT hr;
1524 hr = CreateStreamOnHGlobal(NULL, TRUE, &stream);
1525 ok_ole_success(hr, CreateStreamOnHGlobal);
1527 unmarshal_class = &CLSID_DfMarshal;
1528 SET_EXPECT(CustomMarshal_GetUnmarshalClass);
1529 SET_EXPECT(CustomMarshal_GetMarshalSizeMax);
1530 SET_EXPECT(CustomMarshal_MarshalInterface);
1531 hr = CoMarshalInterface(stream, &IID_IUnknown, (IUnknown*)&CustomMarshal,
1532 MSHCTX_INPROC, NULL, MSHLFLAGS_NORMAL);
1533 ok_ole_success(hr, CoMarshalInterface);
1534 CHECK_CALLED(CustomMarshal_GetUnmarshalClass);
1535 CHECK_CALLED(CustomMarshal_GetMarshalSizeMax);
1536 CHECK_CALLED(CustomMarshal_MarshalInterface);
1538 hr = IStream_Seek(stream, ullZero, STREAM_SEEK_SET, NULL);
1539 ok_ole_success(hr, IStream_Seek);
1540 size = FIELD_OFFSET(OBJREF, u_objref.u_custom.pData);
1541 hr = IStream_Read(stream, &objref, size, &read);
1542 ok_ole_success(hr, IStream_Read);
1543 ok(read == size, "read = %d, expected %d\n", read, size);
1544 ok(objref.signature == OBJREF_SIGNATURE, "objref.signature = %x\n",
1545 objref.signature);
1546 ok(objref.flags == OBJREF_CUSTOM, "objref.flags = %x\n", objref.flags);
1547 ok(IsEqualIID(&objref.iid, &IID_IUnknown), "objref.iid = %s\n",
1548 wine_dbgstr_guid(&objref.iid));
1549 ok(IsEqualIID(&objref.u_objref.u_custom.clsid, &CLSID_DfMarshal),
1550 "custom.clsid = %s\n", wine_dbgstr_guid(&objref.u_objref.u_custom.clsid));
1551 ok(!objref.u_objref.u_custom.cbExtension, "custom.cbExtension = %d\n",
1552 objref.u_objref.u_custom.cbExtension);
1553 ok(!objref.u_objref.u_custom.size, "custom.size = %d\n",
1554 objref.u_objref.u_custom.size);
1556 IStream_Release(stream);
1558 SET_EXPECT(CustomMarshal_GetMarshalSizeMax);
1559 hr = CoGetMarshalSizeMax(&size, &IID_IUnknown, (IUnknown*)&CustomMarshal,
1560 MSHCTX_INPROC, NULL, MSHLFLAGS_NORMAL);
1561 ok_ole_success(hr, CoGetMarshalSizeMax);
1562 CHECK_CALLED(CustomMarshal_GetMarshalSizeMax);
1563 ok(size == sizeof(OBJREF), "size = %d, expected %d\n", size, (int)sizeof(OBJREF));
1566 static void test_CoGetStandardMarshal(void)
1568 DUALSTRINGARRAY *dualstringarr;
1569 STDOBJREF *stdobjref;
1570 OBJREF objref;
1571 IMarshal *marshal;
1572 DWORD size, read;
1573 IStream *stream;
1574 IUnknown *unk;
1575 CLSID clsid;
1576 HRESULT hr;
1578 hr = CreateStreamOnHGlobal(NULL, TRUE, &stream);
1579 ok_ole_success(hr, CreateStreamOnHGlobal);
1581 hr = CoGetStandardMarshal(&IID_IUnknown, &Test_Unknown,
1582 MSHCTX_INPROC, NULL, MSHLFLAGS_NORMAL, &marshal);
1583 ok_ole_success(hr, CoGetStandardMarshal);
1585 hr = IMarshal_GetUnmarshalClass(marshal, &IID_IUnknown, &Test_Unknown,
1586 MSHCTX_INPROC, NULL, MSHLFLAGS_NORMAL, &clsid);
1587 ok_ole_success(hr, IMarshal_GetUnmarshalClass);
1588 ok(IsEqualGUID(&clsid, &CLSID_StdMarshal), "clsid = %s\n", wine_dbgstr_guid(&clsid));
1590 hr = IMarshal_GetMarshalSizeMax(marshal, &IID_IUnknown, &Test_Unknown,
1591 MSHCTX_INPROC, NULL, MSHLFLAGS_NORMAL, &size);
1592 ok_ole_success(hr, IMarshal_GetMarshalSizeMax);
1593 hr = CoGetMarshalSizeMax(&read, &IID_IUnknown, &Test_Unknown,
1594 MSHCTX_INPROC, NULL, MSHLFLAGS_NORMAL);
1595 ok_ole_success(hr, CoGetMarshalSizeMax);
1596 ok(size == read, "IMarshal_GetMarshalSizeMax size = %d, expected %d\n", size, read);
1598 hr = IMarshal_MarshalInterface(marshal, stream, &IID_IUnknown,
1599 &Test_Unknown, MSHCTX_INPROC, NULL, MSHLFLAGS_NORMAL);
1600 ok_ole_success(hr, IMarshal_MarshalInterface);
1602 hr = IStream_Seek(stream, ullZero, STREAM_SEEK_SET, NULL);
1603 ok_ole_success(hr, IStream_Seek);
1604 size = FIELD_OFFSET(OBJREF, u_objref.u_standard.saResAddr.aStringArray);
1605 hr = IStream_Read(stream, &objref, size, &read);
1606 ok_ole_success(hr, IStream_Read);
1607 ok(read == size, "read = %d, expected %d\n", read, size);
1608 ok(objref.signature == OBJREF_SIGNATURE, "objref.signature = %x\n",
1609 objref.signature);
1610 ok(objref.flags == OBJREF_STANDARD, "objref.flags = %x\n", objref.flags);
1611 ok(IsEqualIID(&objref.iid, &IID_IUnknown), "objref.iid = %s\n",
1612 wine_dbgstr_guid(&objref.iid));
1613 stdobjref = &objref.u_objref.u_standard.std;
1614 ok(stdobjref->flags == 0, "stdobjref.flags = %d\n", stdobjref->flags);
1615 ok(stdobjref->cPublicRefs == 5, "stdobjref.cPublicRefs = %d\n",
1616 stdobjref->cPublicRefs);
1617 dualstringarr = &objref.u_objref.u_standard.saResAddr;
1618 ok(dualstringarr->wNumEntries == 0, "dualstringarr.wNumEntries = %d\n",
1619 dualstringarr->wNumEntries);
1620 ok(dualstringarr->wSecurityOffset == 0, "dualstringarr.wSecurityOffset = %d\n",
1621 dualstringarr->wSecurityOffset);
1623 hr = IStream_Seek(stream, ullZero, STREAM_SEEK_SET, NULL);
1624 ok_ole_success(hr, IStream_Seek);
1625 hr = IMarshal_UnmarshalInterface(marshal, stream, &IID_IUnknown, (void**)&unk);
1626 ok_ole_success(hr, IMarshal_UnmarshalInterface);
1627 IUnknown_Release(unk);
1629 hr = IStream_Seek(stream, ullZero, STREAM_SEEK_SET, NULL);
1630 ok_ole_success(hr, IStream_Seek);
1631 hr = IMarshal_MarshalInterface(marshal, stream, &IID_IUnknown,
1632 &Test_Unknown, MSHCTX_INPROC, NULL, MSHLFLAGS_NORMAL);
1633 ok_ole_success(hr, IMarshal_MarshalInterface);
1635 hr = IStream_Seek(stream, ullZero, STREAM_SEEK_SET, NULL);
1636 ok_ole_success(hr, IStream_Seek);
1637 hr = IMarshal_ReleaseMarshalData(marshal, stream);
1638 ok_ole_success(hr, IMarshal_ReleaseMarshalData);
1639 IStream_Release(stream);
1641 IMarshal_Release(marshal);
1643 struct ncu_params
1645 LPSTREAM stream;
1646 HANDLE marshal_event;
1647 HANDLE unmarshal_event;
1650 /* helper for test_no_couninitialize_server */
1651 static DWORD CALLBACK no_couninitialize_server_proc(LPVOID p)
1653 struct ncu_params *ncu_params = p;
1654 HRESULT hr;
1656 CoInitializeEx(NULL, COINIT_MULTITHREADED);
1658 hr = CoMarshalInterface(ncu_params->stream, &IID_IClassFactory, (IUnknown*)&Test_ClassFactory, MSHCTX_INPROC, NULL, MSHLFLAGS_NORMAL);
1659 ok_ole_success(hr, CoMarshalInterface);
1661 SetEvent(ncu_params->marshal_event);
1663 ok( !WaitForSingleObject(ncu_params->unmarshal_event, 10000), "wait timed out\n" );
1665 /* die without calling CoUninitialize */
1667 return 0;
1670 /* tests apartment that an apartment with a stub is released without deadlock
1671 * if the owning thread exits */
1672 static void test_no_couninitialize_server(void)
1674 HRESULT hr;
1675 IStream *pStream = NULL;
1676 IUnknown *pProxy = NULL;
1677 DWORD tid;
1678 HANDLE thread;
1679 struct ncu_params ncu_params;
1681 cLocks = 0;
1682 external_connections = 0;
1684 ncu_params.marshal_event = CreateEventA(NULL, TRUE, FALSE, NULL);
1685 ncu_params.unmarshal_event = CreateEventA(NULL, TRUE, FALSE, NULL);
1687 hr = CreateStreamOnHGlobal(NULL, TRUE, &pStream);
1688 ok_ole_success(hr, CreateStreamOnHGlobal);
1689 ncu_params.stream = pStream;
1691 thread = CreateThread(NULL, 0, no_couninitialize_server_proc, &ncu_params, 0, &tid);
1693 ok( !WaitForSingleObject(ncu_params.marshal_event, 10000), "wait timed out\n" );
1694 ok_more_than_one_lock();
1695 ok_non_zero_external_conn();
1697 IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
1698 hr = CoUnmarshalInterface(pStream, &IID_IClassFactory, (void **)&pProxy);
1699 ok_ole_success(hr, CoUnmarshalInterface);
1700 IStream_Release(pStream);
1702 ok_more_than_one_lock();
1703 ok_non_zero_external_conn();
1705 SetEvent(ncu_params.unmarshal_event);
1706 ok( !WaitForSingleObject(thread, 10000), "wait timed out\n" );
1708 ok_no_locks();
1709 todo_wine {
1710 ok_zero_external_conn();
1711 ok_last_release_closes(FALSE);
1714 CloseHandle(thread);
1715 CloseHandle(ncu_params.marshal_event);
1716 CloseHandle(ncu_params.unmarshal_event);
1718 IUnknown_Release(pProxy);
1720 ok_no_locks();
1723 /* STA -> STA call during DLL_THREAD_DETACH */
1724 static DWORD CALLBACK no_couninitialize_client_proc(LPVOID p)
1726 struct ncu_params *ncu_params = p;
1727 HRESULT hr;
1728 IUnknown *pProxy = NULL;
1730 CoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
1732 hr = CoUnmarshalInterface(ncu_params->stream, &IID_IClassFactory, (void **)&pProxy);
1733 ok_ole_success(hr, CoUnmarshalInterface);
1734 IStream_Release(ncu_params->stream);
1736 ok_more_than_one_lock();
1738 /* die without calling CoUninitialize */
1740 return 0;
1743 /* tests STA -> STA call during DLL_THREAD_DETACH doesn't deadlock */
1744 static void test_no_couninitialize_client(void)
1746 HRESULT hr;
1747 IStream *pStream = NULL;
1748 DWORD tid;
1749 DWORD host_tid;
1750 HANDLE thread;
1751 HANDLE host_thread;
1752 struct ncu_params ncu_params;
1754 cLocks = 0;
1755 external_connections = 0;
1757 hr = CreateStreamOnHGlobal(NULL, TRUE, &pStream);
1758 ok_ole_success(hr, CreateStreamOnHGlobal);
1759 ncu_params.stream = pStream;
1761 /* NOTE: assumes start_host_object uses an STA to host the object, as MTAs
1762 * always deadlock when called from within DllMain */
1763 host_tid = start_host_object(pStream, &IID_IClassFactory, (IUnknown *)&Test_ClassFactory, MSHLFLAGS_NORMAL, &host_thread);
1764 IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
1766 ok_more_than_one_lock();
1767 ok_non_zero_external_conn();
1769 thread = CreateThread(NULL, 0, no_couninitialize_client_proc, &ncu_params, 0, &tid);
1771 ok( !WaitForSingleObject(thread, 10000), "wait timed out\n" );
1772 CloseHandle(thread);
1774 ok_no_locks();
1775 ok_zero_external_conn();
1776 ok_last_release_closes(TRUE);
1778 end_host_object(host_tid, host_thread);
1781 static BOOL crash_thread_success;
1783 static DWORD CALLBACK crash_couninitialize_proc(void *p)
1785 IStream *stream;
1786 HRESULT hr;
1788 cLocks = 0;
1790 CoInitialize(NULL);
1792 hr = CreateStreamOnHGlobal(NULL, TRUE, &stream);
1793 ok_ole_success(hr, CreateStreamOnHGlobal);
1795 hr = CoMarshalInterface(stream, &IID_IUnknown, &TestCrash_Unknown, MSHCTX_INPROC, NULL, MSHLFLAGS_NORMAL);
1796 ok_ole_success(hr, CoMarshalInterface);
1798 IStream_Seek(stream, ullZero, STREAM_SEEK_SET, NULL);
1800 hr = CoReleaseMarshalData(stream);
1801 ok_ole_success(hr, CoReleaseMarshalData);
1803 ok_no_locks();
1805 hr = CoMarshalInterface(stream, &IID_IUnknown, &TestCrash_Unknown, MSHCTX_INPROC, NULL, MSHLFLAGS_NORMAL);
1806 ok_ole_success(hr, CoMarshalInterface);
1808 ok_more_than_one_lock();
1810 trace("CoUninitialize >>>\n");
1811 CoUninitialize();
1812 trace("CoUninitialize <<<\n");
1814 ok_no_locks();
1816 IStream_Release(stream);
1817 crash_thread_success = TRUE;
1818 return 0;
1821 static void test_crash_couninitialize(void)
1823 HANDLE thread;
1824 DWORD tid;
1826 crash_thread_success = FALSE;
1827 thread = CreateThread(NULL, 0, crash_couninitialize_proc, NULL, 0, &tid);
1828 ok(!WaitForSingleObject(thread, 10000), "wait timed out\n");
1829 CloseHandle(thread);
1830 ok(crash_thread_success, "Crash thread failed\n");
1833 /* tests success case of a same-thread table-weak marshal, unmarshal, unmarshal */
1834 static void test_tableweak_marshal_and_unmarshal_twice(void)
1836 HRESULT hr;
1837 IStream *pStream = NULL;
1838 IUnknown *pProxy1 = NULL;
1839 IUnknown *pProxy2 = NULL;
1840 DWORD tid;
1841 HANDLE thread;
1843 cLocks = 0;
1844 external_connections = 0;
1846 hr = CreateStreamOnHGlobal(NULL, TRUE, &pStream);
1847 ok_ole_success(hr, CreateStreamOnHGlobal);
1848 tid = start_host_object(pStream, &IID_IClassFactory, (IUnknown*)&Test_ClassFactory, MSHLFLAGS_TABLEWEAK, &thread);
1850 ok_more_than_one_lock();
1851 ok_zero_external_conn();
1853 IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
1854 hr = CoUnmarshalInterface(pStream, &IID_IClassFactory, (void **)&pProxy1);
1855 ok_ole_success(hr, CoUnmarshalInterface);
1857 ok_more_than_one_lock();
1858 ok_non_zero_external_conn();
1860 IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
1861 hr = CoUnmarshalInterface(pStream, &IID_IClassFactory, (void **)&pProxy2);
1862 ok_ole_success(hr, CoUnmarshalInterface);
1864 ok_more_than_one_lock();
1866 IUnknown_Release(pProxy1);
1867 ok_non_zero_external_conn();
1868 IUnknown_Release(pProxy2);
1869 ok_zero_external_conn();
1870 ok_last_release_closes(TRUE);
1872 /* When IExternalConnection is present COM's lifetime management
1873 * behaviour is altered; the remaining weak ref prevents stub shutdown. */
1874 if (with_external_conn)
1876 ok_more_than_one_lock();
1877 IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
1878 release_host_object(tid, 0);
1881 /* Without IExternalConnection this line is shows the difference between weak and strong table marshaling
1882 * weak has cLocks == 0, strong has cLocks > 0. */
1883 ok_no_locks();
1885 IStream_Release(pStream);
1886 end_host_object(tid, thread);
1889 /* tests releasing after unmarshaling one object */
1890 static void test_tableweak_marshal_releasedata1(void)
1892 HRESULT hr;
1893 IStream *pStream = NULL;
1894 IUnknown *pProxy1 = NULL;
1895 IUnknown *pProxy2 = NULL;
1896 DWORD tid;
1897 HANDLE thread;
1899 cLocks = 0;
1900 external_connections = 0;
1902 hr = CreateStreamOnHGlobal(NULL, TRUE, &pStream);
1903 ok_ole_success(hr, CreateStreamOnHGlobal);
1904 tid = start_host_object(pStream, &IID_IClassFactory, (IUnknown*)&Test_ClassFactory, MSHLFLAGS_TABLEWEAK, &thread);
1906 ok_more_than_one_lock();
1907 ok_zero_external_conn();
1909 IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
1910 hr = CoUnmarshalInterface(pStream, &IID_IClassFactory, (void **)&pProxy1);
1911 ok_ole_success(hr, CoUnmarshalInterface);
1913 ok_more_than_one_lock();
1914 ok_non_zero_external_conn();
1916 /* release the remaining reference on the object by calling
1917 * CoReleaseMarshalData in the hosting thread */
1918 IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
1919 release_host_object(tid, 0);
1921 ok_more_than_one_lock();
1922 ok_non_zero_external_conn();
1924 IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
1925 hr = CoUnmarshalInterface(pStream, &IID_IClassFactory, (void **)&pProxy2);
1926 ok_ole_success(hr, CoUnmarshalInterface);
1927 IStream_Release(pStream);
1929 ok_more_than_one_lock();
1930 ok_non_zero_external_conn();
1932 IUnknown_Release(pProxy1);
1934 if (pProxy2)
1936 ok_non_zero_external_conn();
1937 IUnknown_Release(pProxy2);
1940 /* this line is shows the difference between weak and strong table marshaling:
1941 * weak has cLocks == 0
1942 * strong has cLocks > 0 */
1943 ok_no_locks();
1944 ok_zero_external_conn();
1945 ok_last_release_closes(TRUE);
1947 end_host_object(tid, thread);
1950 /* tests releasing after unmarshaling one object */
1951 static void test_tableweak_marshal_releasedata2(void)
1953 HRESULT hr;
1954 IStream *pStream = NULL;
1955 IUnknown *pProxy = NULL;
1956 DWORD tid;
1957 HANDLE thread;
1959 cLocks = 0;
1960 external_connections = 0;
1962 hr = CreateStreamOnHGlobal(NULL, TRUE, &pStream);
1963 ok_ole_success(hr, CreateStreamOnHGlobal);
1964 tid = start_host_object(pStream, &IID_IClassFactory, (IUnknown*)&Test_ClassFactory, MSHLFLAGS_TABLEWEAK, &thread);
1966 ok_more_than_one_lock();
1967 ok_zero_external_conn();
1969 /* release the remaining reference on the object by calling
1970 * CoReleaseMarshalData in the hosting thread */
1971 IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
1972 release_host_object(tid, 0);
1974 ok_no_locks();
1976 IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
1977 hr = CoUnmarshalInterface(pStream, &IID_IClassFactory, (void **)&pProxy);
1978 todo_wine
1980 ok(hr == CO_E_OBJNOTREG,
1981 "CoUnmarshalInterface should have failed with CO_E_OBJNOTREG, but returned 0x%08x instead\n",
1982 hr);
1984 IStream_Release(pStream);
1986 ok_no_locks();
1987 ok_zero_external_conn();
1989 end_host_object(tid, thread);
1992 struct duo_marshal_data
1994 MSHLFLAGS marshal_flags1, marshal_flags2;
1995 IStream *pStream1, *pStream2;
1996 HANDLE hReadyEvent;
1997 HANDLE hQuitEvent;
2000 static DWORD CALLBACK duo_marshal_thread_proc(void *p)
2002 HRESULT hr;
2003 struct duo_marshal_data *data = p;
2004 HANDLE hQuitEvent = data->hQuitEvent;
2005 MSG msg;
2007 CoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
2009 hr = CoMarshalInterface(data->pStream1, &IID_IClassFactory, (IUnknown*)&Test_ClassFactory, MSHCTX_INPROC, NULL, data->marshal_flags1);
2010 ok_ole_success(hr, "CoMarshalInterface");
2012 hr = CoMarshalInterface(data->pStream2, &IID_IClassFactory, (IUnknown*)&Test_ClassFactory, MSHCTX_INPROC, NULL, data->marshal_flags2);
2013 ok_ole_success(hr, "CoMarshalInterface");
2015 /* force the message queue to be created before signaling parent thread */
2016 PeekMessageA(&msg, NULL, WM_USER, WM_USER, PM_NOREMOVE);
2018 SetEvent(data->hReadyEvent);
2020 while (WAIT_OBJECT_0 + 1 == MsgWaitForMultipleObjects(1, &hQuitEvent, FALSE, 10000, QS_ALLINPUT))
2022 while (PeekMessageA(&msg, NULL, 0, 0, PM_REMOVE))
2024 if (msg.hwnd == NULL && msg.message == RELEASEMARSHALDATA)
2026 CoReleaseMarshalData(msg.wParam == 1 ? data->pStream1 : data->pStream2);
2027 SetEvent((HANDLE)msg.lParam);
2029 else
2030 DispatchMessageA(&msg);
2033 CloseHandle(hQuitEvent);
2035 CoUninitialize();
2037 return 0;
2040 /* tests interaction between table-weak and normal marshalling of an object */
2041 static void test_tableweak_and_normal_marshal_and_unmarshal(void)
2043 HRESULT hr;
2044 IUnknown *pProxyWeak = NULL;
2045 IUnknown *pProxyNormal = NULL;
2046 DWORD tid;
2047 HANDLE thread;
2048 struct duo_marshal_data data;
2050 cLocks = 0;
2051 external_connections = 0;
2053 data.hReadyEvent = CreateEventA(NULL, FALSE, FALSE, NULL);
2054 data.hQuitEvent = CreateEventA(NULL, FALSE, FALSE, NULL);
2055 data.marshal_flags1 = MSHLFLAGS_TABLEWEAK;
2056 data.marshal_flags2 = MSHLFLAGS_NORMAL;
2057 hr = CreateStreamOnHGlobal(NULL, TRUE, &data.pStream1);
2058 ok_ole_success(hr, CreateStreamOnHGlobal);
2059 hr = CreateStreamOnHGlobal(NULL, TRUE, &data.pStream2);
2060 ok_ole_success(hr, CreateStreamOnHGlobal);
2062 thread = CreateThread(NULL, 0, duo_marshal_thread_proc, &data, 0, &tid);
2063 ok( !WaitForSingleObject(data.hReadyEvent, 10000), "wait timed out\n" );
2064 CloseHandle(data.hReadyEvent);
2066 ok_more_than_one_lock();
2067 ok_non_zero_external_conn();
2069 /* weak */
2070 IStream_Seek(data.pStream1, ullZero, STREAM_SEEK_SET, NULL);
2071 hr = CoUnmarshalInterface(data.pStream1, &IID_IClassFactory, (void **)&pProxyWeak);
2072 ok_ole_success(hr, CoUnmarshalInterface);
2074 ok_more_than_one_lock();
2076 /* normal */
2077 IStream_Seek(data.pStream2, ullZero, STREAM_SEEK_SET, NULL);
2078 hr = CoUnmarshalInterface(data.pStream2, &IID_IClassFactory, (void **)&pProxyNormal);
2079 ok_ole_success(hr, CoUnmarshalInterface);
2081 ok_more_than_one_lock();
2083 IUnknown_Release(pProxyNormal);
2085 ok_more_than_one_lock();
2086 ok_non_zero_external_conn();
2088 IUnknown_Release(pProxyWeak);
2090 ok_zero_external_conn();
2091 ok_last_release_closes(TRUE);
2093 /* When IExternalConnection is present COM's lifetime management
2094 * behaviour is altered; the remaining weak ref prevents stub shutdown. */
2095 if (with_external_conn)
2097 ok_more_than_one_lock();
2098 IStream_Seek(data.pStream1, ullZero, STREAM_SEEK_SET, NULL);
2099 release_host_object(tid, 1);
2101 ok_no_locks();
2103 IStream_Release(data.pStream1);
2104 IStream_Release(data.pStream2);
2106 SetEvent(data.hQuitEvent);
2107 ok( !WaitForSingleObject(thread, 10000), "wait timed out\n" );
2108 CloseHandle(thread);
2111 static void test_tableweak_and_normal_marshal_and_releasedata(void)
2113 HRESULT hr;
2114 DWORD tid;
2115 HANDLE thread;
2116 struct duo_marshal_data data;
2118 cLocks = 0;
2119 external_connections = 0;
2121 data.hReadyEvent = CreateEventA(NULL, FALSE, FALSE, NULL);
2122 data.hQuitEvent = CreateEventA(NULL, FALSE, FALSE, NULL);
2123 data.marshal_flags1 = MSHLFLAGS_TABLEWEAK;
2124 data.marshal_flags2 = MSHLFLAGS_NORMAL;
2125 hr = CreateStreamOnHGlobal(NULL, TRUE, &data.pStream1);
2126 ok_ole_success(hr, CreateStreamOnHGlobal);
2127 hr = CreateStreamOnHGlobal(NULL, TRUE, &data.pStream2);
2128 ok_ole_success(hr, CreateStreamOnHGlobal);
2130 thread = CreateThread(NULL, 0, duo_marshal_thread_proc, &data, 0, &tid);
2131 ok( !WaitForSingleObject(data.hReadyEvent, 10000), "wait timed out\n" );
2132 CloseHandle(data.hReadyEvent);
2134 ok_more_than_one_lock();
2135 ok_non_zero_external_conn();
2137 /* release normal - which in the non-external conn case will free the object despite the weak ref. */
2138 IStream_Seek(data.pStream2, ullZero, STREAM_SEEK_SET, NULL);
2139 release_host_object(tid, 2);
2141 ok_zero_external_conn();
2142 ok_last_release_closes(TRUE);
2144 if (with_external_conn)
2146 ok_more_than_one_lock();
2147 IStream_Seek(data.pStream1, ullZero, STREAM_SEEK_SET, NULL);
2148 release_host_object(tid, 1);
2151 ok_no_locks();
2153 IStream_Release(data.pStream1);
2154 IStream_Release(data.pStream2);
2156 SetEvent(data.hQuitEvent);
2157 ok( !WaitForSingleObject(thread, 10000), "wait timed out\n" );
2158 CloseHandle(thread);
2161 static void test_two_tableweak_marshal_and_releasedata(void)
2163 HRESULT hr;
2164 DWORD tid;
2165 HANDLE thread;
2166 struct duo_marshal_data data;
2168 cLocks = 0;
2169 external_connections = 0;
2171 data.hReadyEvent = CreateEventA(NULL, FALSE, FALSE, NULL);
2172 data.hQuitEvent = CreateEventA(NULL, FALSE, FALSE, NULL);
2173 data.marshal_flags1 = MSHLFLAGS_TABLEWEAK;
2174 data.marshal_flags2 = MSHLFLAGS_TABLEWEAK;
2175 hr = CreateStreamOnHGlobal(NULL, TRUE, &data.pStream1);
2176 ok_ole_success(hr, CreateStreamOnHGlobal);
2177 hr = CreateStreamOnHGlobal(NULL, TRUE, &data.pStream2);
2178 ok_ole_success(hr, CreateStreamOnHGlobal);
2180 thread = CreateThread(NULL, 0, duo_marshal_thread_proc, &data, 0, &tid);
2181 ok( !WaitForSingleObject(data.hReadyEvent, 10000), "wait timed out\n" );
2182 CloseHandle(data.hReadyEvent);
2184 ok_more_than_one_lock();
2185 ok_zero_external_conn();
2187 /* release one weak ref - the remaining weak ref will keep the obj alive */
2188 IStream_Seek(data.pStream1, ullZero, STREAM_SEEK_SET, NULL);
2189 release_host_object(tid, 1);
2191 ok_more_than_one_lock();
2193 IStream_Seek(data.pStream2, ullZero, STREAM_SEEK_SET, NULL);
2194 release_host_object(tid, 2);
2196 ok_no_locks();
2198 IStream_Release(data.pStream1);
2199 IStream_Release(data.pStream2);
2201 SetEvent(data.hQuitEvent);
2202 ok( !WaitForSingleObject(thread, 10000), "wait timed out\n" );
2203 CloseHandle(thread);
2206 /* tests success case of a same-thread table-strong marshal, unmarshal, unmarshal */
2207 static void test_tablestrong_marshal_and_unmarshal_twice(void)
2209 HRESULT hr;
2210 IStream *pStream = NULL;
2211 IUnknown *pProxy1 = NULL;
2212 IUnknown *pProxy2 = NULL;
2213 DWORD tid;
2214 HANDLE thread;
2216 cLocks = 0;
2217 external_connections = 0;
2219 hr = CreateStreamOnHGlobal(NULL, TRUE, &pStream);
2220 ok_ole_success(hr, CreateStreamOnHGlobal);
2221 tid = start_host_object(pStream, &IID_IClassFactory, (IUnknown*)&Test_ClassFactory, MSHLFLAGS_TABLESTRONG, &thread);
2223 ok_more_than_one_lock();
2224 ok_non_zero_external_conn();
2226 IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
2227 hr = CoUnmarshalInterface(pStream, &IID_IClassFactory, (void **)&pProxy1);
2228 ok_ole_success(hr, CoUnmarshalInterface);
2230 ok_more_than_one_lock();
2232 IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
2233 hr = CoUnmarshalInterface(pStream, &IID_IClassFactory, (void **)&pProxy2);
2234 ok_ole_success(hr, CoUnmarshalInterface);
2236 ok_more_than_one_lock();
2238 if (pProxy1) IUnknown_Release(pProxy1);
2239 if (pProxy2) IUnknown_Release(pProxy2);
2241 /* this line is shows the difference between weak and strong table marshaling:
2242 * weak has cLocks == 0
2243 * strong has cLocks > 0 */
2244 ok_more_than_one_lock();
2246 /* release the remaining reference on the object by calling
2247 * CoReleaseMarshalData in the hosting thread */
2248 IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
2249 release_host_object(tid, 0);
2250 IStream_Release(pStream);
2252 ok_no_locks();
2253 ok_zero_external_conn();
2254 ok_last_release_closes(TRUE);
2256 end_host_object(tid, thread);
2259 /* tests CoLockObjectExternal */
2260 static void test_lock_object_external(void)
2262 HRESULT hr;
2263 IStream *pStream = NULL;
2265 cLocks = 0;
2266 external_connections = 0;
2268 /* test the stub manager creation aspect of CoLockObjectExternal when the
2269 * object hasn't been marshaled yet */
2270 CoLockObjectExternal((IUnknown*)&Test_ClassFactory, TRUE, TRUE);
2272 ok_more_than_one_lock();
2273 ok_non_zero_external_conn();
2275 CoDisconnectObject((IUnknown*)&Test_ClassFactory, 0);
2277 ok_no_locks();
2278 ok_non_zero_external_conn();
2279 external_connections = 0;
2281 /* test our empty stub manager being handled correctly in
2282 * CoMarshalInterface */
2283 CoLockObjectExternal((IUnknown*)&Test_ClassFactory, TRUE, TRUE);
2285 hr = CreateStreamOnHGlobal(NULL, TRUE, &pStream);
2286 ok_ole_success(hr, CreateStreamOnHGlobal);
2287 hr = CoMarshalInterface(pStream, &IID_IClassFactory, (IUnknown*)&Test_ClassFactory, MSHCTX_INPROC, NULL, MSHLFLAGS_NORMAL);
2288 ok_ole_success(hr, CoMarshalInterface);
2290 CoLockObjectExternal((IUnknown*)&Test_ClassFactory, TRUE, TRUE);
2292 ok_more_than_one_lock();
2293 ok_non_zero_external_conn();
2295 IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
2296 hr = CoReleaseMarshalData(pStream);
2297 ok_ole_success(hr, CoReleaseMarshalData);
2298 IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
2300 ok_more_than_one_lock();
2301 ok_non_zero_external_conn();
2302 ok_last_release_closes(TRUE);
2304 CoLockObjectExternal((IUnknown*)&Test_ClassFactory, FALSE, TRUE);
2306 ok_more_than_one_lock();
2307 ok_non_zero_external_conn();
2308 ok_last_release_closes(TRUE);
2310 CoLockObjectExternal((IUnknown*)&Test_ClassFactory, FALSE, TRUE);
2312 ok_no_locks();
2313 ok_zero_external_conn();
2314 ok_last_release_closes(TRUE);
2316 /* test CoLockObjectExternal releases reference to object with
2317 * fLastUnlockReleases as TRUE and there are only strong references on
2318 * the object */
2319 CoLockObjectExternal((IUnknown*)&Test_ClassFactory, TRUE, FALSE);
2321 ok_more_than_one_lock();
2322 ok_non_zero_external_conn();
2324 CoLockObjectExternal((IUnknown*)&Test_ClassFactory, FALSE, FALSE);
2326 ok_no_locks();
2327 ok_zero_external_conn();
2328 ok_last_release_closes(FALSE);
2330 /* test CoLockObjectExternal doesn't release the last reference to an
2331 * object with fLastUnlockReleases as TRUE and there is a weak reference
2332 * on the object */
2333 hr = CoMarshalInterface(pStream, &IID_IClassFactory, (IUnknown*)&Test_ClassFactory, MSHCTX_INPROC, NULL, MSHLFLAGS_TABLEWEAK);
2334 ok_ole_success(hr, CoMarshalInterface);
2336 ok_more_than_one_lock();
2337 ok_zero_external_conn();
2339 CoLockObjectExternal((IUnknown*)&Test_ClassFactory, TRUE, FALSE);
2341 ok_more_than_one_lock();
2342 ok_non_zero_external_conn();
2344 CoLockObjectExternal((IUnknown*)&Test_ClassFactory, FALSE, FALSE);
2346 ok_more_than_one_lock();
2347 ok_zero_external_conn();
2348 ok_last_release_closes(FALSE);
2350 CoDisconnectObject((IUnknown*)&Test_ClassFactory, 0);
2352 ok_no_locks();
2354 IStream_Release(pStream);
2357 /* tests disconnecting stubs */
2358 static void test_disconnect_stub(void)
2360 HRESULT hr;
2361 IStream *pStream = NULL;
2363 cLocks = 0;
2364 external_connections = 0;
2366 hr = CreateStreamOnHGlobal(NULL, TRUE, &pStream);
2367 ok_ole_success(hr, CreateStreamOnHGlobal);
2368 hr = CoMarshalInterface(pStream, &IID_IClassFactory, (IUnknown*)&Test_ClassFactory, MSHCTX_INPROC, NULL, MSHLFLAGS_NORMAL);
2369 ok_ole_success(hr, CoMarshalInterface);
2371 ok_non_zero_external_conn();
2373 CoLockObjectExternal((IUnknown*)&Test_ClassFactory, TRUE, TRUE);
2375 ok_more_than_one_lock();
2376 ok_non_zero_external_conn();
2378 IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
2379 hr = CoReleaseMarshalData(pStream);
2380 ok_ole_success(hr, CoReleaseMarshalData);
2381 IStream_Release(pStream);
2383 ok_more_than_one_lock();
2384 ok_non_zero_external_conn();
2386 CoDisconnectObject((IUnknown*)&Test_ClassFactory, 0);
2388 ok_no_locks();
2389 ok_non_zero_external_conn();
2391 hr = CoDisconnectObject(NULL, 0);
2392 ok( hr == E_INVALIDARG, "wrong status %x\n", hr );
2395 /* tests failure case of a same-thread marshal and unmarshal twice */
2396 static void test_normal_marshal_and_unmarshal_twice(void)
2398 HRESULT hr;
2399 IStream *pStream = NULL;
2400 IUnknown *pProxy1 = NULL;
2401 IUnknown *pProxy2 = NULL;
2403 cLocks = 0;
2404 external_connections = 0;
2406 hr = CreateStreamOnHGlobal(NULL, TRUE, &pStream);
2407 ok_ole_success(hr, CreateStreamOnHGlobal);
2408 hr = CoMarshalInterface(pStream, &IID_IClassFactory, (IUnknown*)&Test_ClassFactory, MSHCTX_INPROC, NULL, MSHLFLAGS_NORMAL);
2409 ok_ole_success(hr, CoMarshalInterface);
2411 ok_more_than_one_lock();
2412 ok_non_zero_external_conn();
2414 IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
2415 hr = CoUnmarshalInterface(pStream, &IID_IClassFactory, (void **)&pProxy1);
2416 ok_ole_success(hr, CoUnmarshalInterface);
2418 ok_more_than_one_lock();
2419 ok_zero_external_conn();
2420 ok_last_release_closes(FALSE);
2422 IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
2423 hr = CoUnmarshalInterface(pStream, &IID_IClassFactory, (void **)&pProxy2);
2424 ok(hr == CO_E_OBJNOTCONNECTED,
2425 "CoUnmarshalInterface should have failed with error CO_E_OBJNOTCONNECTED for double unmarshal, instead of 0x%08x\n", hr);
2427 IStream_Release(pStream);
2429 ok_more_than_one_lock();
2431 IUnknown_Release(pProxy1);
2433 ok_no_locks();
2436 /* tests success case of marshaling and unmarshaling an HRESULT */
2437 static void test_hresult_marshaling(void)
2439 HRESULT hr;
2440 HRESULT hr_marshaled = 0;
2441 IStream *pStream = NULL;
2442 static const HRESULT E_DEADBEEF = 0xdeadbeef;
2444 hr = CreateStreamOnHGlobal(NULL, TRUE, &pStream);
2445 ok_ole_success(hr, CreateStreamOnHGlobal);
2447 hr = CoMarshalHresult(pStream, E_DEADBEEF);
2448 ok_ole_success(hr, CoMarshalHresult);
2450 IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
2451 hr = IStream_Read(pStream, &hr_marshaled, sizeof(HRESULT), NULL);
2452 ok_ole_success(hr, IStream_Read);
2454 ok(hr_marshaled == E_DEADBEEF, "Didn't marshal HRESULT as expected: got value 0x%08x instead\n", hr_marshaled);
2456 hr_marshaled = 0;
2457 IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
2458 hr = CoUnmarshalHresult(pStream, &hr_marshaled);
2459 ok_ole_success(hr, CoUnmarshalHresult);
2461 ok(hr_marshaled == E_DEADBEEF, "Didn't marshal HRESULT as expected: got value 0x%08x instead\n", hr_marshaled);
2463 IStream_Release(pStream);
2467 /* helper for test_proxy_used_in_wrong_thread */
2468 static DWORD CALLBACK bad_thread_proc(LPVOID p)
2470 IClassFactory * cf = p;
2471 HRESULT hr;
2472 IUnknown * proxy = NULL;
2474 hr = IClassFactory_CreateInstance(cf, NULL, &IID_IUnknown, (LPVOID*)&proxy);
2475 todo_wine ok(hr == CO_E_NOTINITIALIZED, "Got hr %#x.\n", hr);
2477 hr = IClassFactory_QueryInterface(cf, &IID_IMultiQI, (LPVOID *)&proxy);
2478 todo_wine ok(hr == RPC_E_WRONG_THREAD, "Got hr %#x.\n", hr);
2479 if (SUCCEEDED(hr))
2480 IUnknown_Release(proxy);
2482 hr = IClassFactory_QueryInterface(cf, &IID_IStream, (LPVOID *)&proxy);
2483 todo_wine ok(hr == RPC_E_WRONG_THREAD, "Got hr %#x.\n", hr);
2484 if (SUCCEEDED(hr))
2485 IUnknown_Release(proxy);
2487 CoInitializeEx(NULL, COINIT_MULTITHREADED);
2489 hr = IClassFactory_CreateInstance(cf, NULL, &IID_IUnknown, (LPVOID*)&proxy);
2490 if (proxy) IUnknown_Release(proxy);
2491 ok(hr == RPC_E_WRONG_THREAD,
2492 "COM should have failed with RPC_E_WRONG_THREAD on using proxy from wrong apartment, but instead returned 0x%08x\n",
2493 hr);
2495 hr = IClassFactory_QueryInterface(cf, &IID_IStream, (LPVOID *)&proxy);
2496 todo_wine ok(hr == RPC_E_WRONG_THREAD, "Got hr %#x.\n", hr);
2498 /* now be really bad and release the proxy from the wrong apartment */
2499 IClassFactory_Release(cf);
2501 CoUninitialize();
2503 return 0;
2506 /* tests failure case of a using a proxy in the wrong apartment */
2507 static void test_proxy_used_in_wrong_thread(void)
2509 HRESULT hr;
2510 IStream *pStream = NULL;
2511 IUnknown *pProxy = NULL;
2512 DWORD tid, tid2;
2513 HANDLE thread;
2514 HANDLE host_thread;
2516 cLocks = 0;
2518 hr = CreateStreamOnHGlobal(NULL, TRUE, &pStream);
2519 ok_ole_success(hr, CreateStreamOnHGlobal);
2520 tid = start_host_object(pStream, &IID_IClassFactory, (IUnknown*)&Test_ClassFactory, MSHLFLAGS_NORMAL, &host_thread);
2522 ok_more_than_one_lock();
2524 IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
2525 hr = CoUnmarshalInterface(pStream, &IID_IClassFactory, (void **)&pProxy);
2526 ok_ole_success(hr, CoUnmarshalInterface);
2527 IStream_Release(pStream);
2529 ok_more_than_one_lock();
2531 /* do a call that will fail, but result in IRemUnknown being used by the proxy */
2532 IUnknown_QueryInterface(pProxy, &IID_IStream, (LPVOID *)&pStream);
2534 /* create a thread that we can misbehave in */
2535 thread = CreateThread(NULL, 0, bad_thread_proc, pProxy, 0, &tid2);
2537 ok( !WaitForSingleObject(thread, 10000), "wait timed out\n" );
2538 CloseHandle(thread);
2540 ok_no_locks();
2542 end_host_object(tid, host_thread);
2545 static HRESULT WINAPI MessageFilter_QueryInterface(IMessageFilter *iface, REFIID riid, void ** ppvObj)
2547 if (ppvObj == NULL) return E_POINTER;
2549 if (IsEqualGUID(riid, &IID_IUnknown) ||
2550 IsEqualGUID(riid, &IID_IClassFactory))
2552 *ppvObj = iface;
2553 IMessageFilter_AddRef(iface);
2554 return S_OK;
2557 return E_NOINTERFACE;
2560 static ULONG WINAPI MessageFilter_AddRef(IMessageFilter *iface)
2562 return 2; /* non-heap object */
2565 static ULONG WINAPI MessageFilter_Release(IMessageFilter *iface)
2567 return 1; /* non-heap object */
2570 static DWORD WINAPI MessageFilter_HandleInComingCall(
2571 IMessageFilter *iface,
2572 DWORD dwCallType,
2573 HTASK threadIDCaller,
2574 DWORD dwTickCount,
2575 LPINTERFACEINFO lpInterfaceInfo)
2577 static int callcount = 0;
2578 DWORD ret;
2579 if (winetest_debug > 1) trace("HandleInComingCall()\n");
2580 switch (callcount)
2582 case 0:
2583 ret = SERVERCALL_REJECTED;
2584 break;
2585 case 1:
2586 ret = SERVERCALL_RETRYLATER;
2587 break;
2588 default:
2589 ret = SERVERCALL_ISHANDLED;
2590 break;
2592 callcount++;
2593 return ret;
2596 static DWORD WINAPI MessageFilter_RetryRejectedCall(
2597 IMessageFilter *iface,
2598 HTASK threadIDCallee,
2599 DWORD dwTickCount,
2600 DWORD dwRejectType)
2602 if (winetest_debug > 1) trace("RetryRejectedCall()\n");
2603 return 0;
2606 static DWORD WINAPI MessageFilter_MessagePending(
2607 IMessageFilter *iface,
2608 HTASK threadIDCallee,
2609 DWORD dwTickCount,
2610 DWORD dwPendingType)
2612 if (winetest_debug > 1) trace("MessagePending()\n");
2613 return PENDINGMSG_WAITNOPROCESS;
2616 static const IMessageFilterVtbl MessageFilter_Vtbl =
2618 MessageFilter_QueryInterface,
2619 MessageFilter_AddRef,
2620 MessageFilter_Release,
2621 MessageFilter_HandleInComingCall,
2622 MessageFilter_RetryRejectedCall,
2623 MessageFilter_MessagePending
2626 static IMessageFilter MessageFilter = { &MessageFilter_Vtbl };
2628 static void test_message_filter(void)
2630 HRESULT hr;
2631 IClassFactory *cf = NULL;
2632 DWORD tid;
2633 IUnknown *proxy = NULL;
2634 IMessageFilter *prev_filter = NULL;
2635 HANDLE thread;
2637 struct host_object_data object_data = { NULL, &IID_IClassFactory, (IUnknown*)&Test_ClassFactory,
2638 MSHLFLAGS_NORMAL, &MessageFilter };
2640 cLocks = 0;
2642 hr = CreateStreamOnHGlobal(NULL, TRUE, &object_data.stream);
2643 ok_ole_success(hr, CreateStreamOnHGlobal);
2644 tid = start_host_object2(&object_data, &thread);
2646 ok_more_than_one_lock();
2648 IStream_Seek(object_data.stream, ullZero, STREAM_SEEK_SET, NULL);
2649 hr = CoUnmarshalInterface(object_data.stream, &IID_IClassFactory, (void **)&cf);
2650 ok_ole_success(hr, CoUnmarshalInterface);
2651 IStream_Release(object_data.stream);
2653 ok_more_than_one_lock();
2655 hr = IClassFactory_CreateInstance(cf, NULL, &IID_IUnknown, (LPVOID*)&proxy);
2656 ok(hr == RPC_E_CALL_REJECTED, "Call should have returned RPC_E_CALL_REJECTED, but return 0x%08x instead\n", hr);
2657 if (proxy) IUnknown_Release(proxy);
2658 proxy = NULL;
2660 hr = CoRegisterMessageFilter(&MessageFilter, &prev_filter);
2661 ok_ole_success(hr, CoRegisterMessageFilter);
2663 hr = IClassFactory_CreateInstance(cf, NULL, &IID_IUnknown, (LPVOID*)&proxy);
2664 ok_ole_success(hr, IClassFactory_CreateInstance);
2666 IUnknown_Release(proxy);
2668 IClassFactory_Release(cf);
2670 ok_no_locks();
2672 end_host_object(tid, thread);
2674 hr = CoRegisterMessageFilter(prev_filter, NULL);
2675 ok_ole_success(hr, CoRegisterMessageFilter);
2678 /* test failure case of trying to unmarshal from bad stream */
2679 static void test_bad_marshal_stream(void)
2681 HRESULT hr;
2682 IStream *pStream = NULL;
2684 hr = CreateStreamOnHGlobal(NULL, TRUE, &pStream);
2685 ok_ole_success(hr, CreateStreamOnHGlobal);
2686 hr = CoMarshalInterface(pStream, &IID_IClassFactory, (IUnknown*)&Test_ClassFactory, MSHCTX_INPROC, NULL, MSHLFLAGS_NORMAL);
2687 ok_ole_success(hr, CoMarshalInterface);
2689 ok_more_than_one_lock();
2691 /* try to read beyond end of stream */
2692 hr = CoReleaseMarshalData(pStream);
2693 ok(hr == STG_E_READFAULT, "Should have failed with STG_E_READFAULT, but returned 0x%08x instead\n", hr);
2695 /* now release for real */
2696 IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
2697 hr = CoReleaseMarshalData(pStream);
2698 ok_ole_success(hr, CoReleaseMarshalData);
2700 IStream_Release(pStream);
2703 /* tests that proxies implement certain interfaces */
2704 static void test_proxy_interfaces(void)
2706 HRESULT hr;
2707 IStream *pStream = NULL;
2708 IUnknown *pProxy = NULL;
2709 IUnknown *pOtherUnknown = NULL;
2710 DWORD tid;
2711 HANDLE thread;
2713 cLocks = 0;
2715 hr = CreateStreamOnHGlobal(NULL, TRUE, &pStream);
2716 ok_ole_success(hr, CreateStreamOnHGlobal);
2717 tid = start_host_object(pStream, &IID_IClassFactory, (IUnknown*)&Test_ClassFactory, MSHLFLAGS_NORMAL, &thread);
2719 ok_more_than_one_lock();
2721 IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
2722 hr = CoUnmarshalInterface(pStream, &IID_IUnknown, (void **)&pProxy);
2723 ok_ole_success(hr, CoUnmarshalInterface);
2724 IStream_Release(pStream);
2726 ok_more_than_one_lock();
2728 hr = IUnknown_QueryInterface(pProxy, &IID_IUnknown, (LPVOID*)&pOtherUnknown);
2729 ok_ole_success(hr, IUnknown_QueryInterface IID_IUnknown);
2730 if (hr == S_OK) IUnknown_Release(pOtherUnknown);
2732 hr = IUnknown_QueryInterface(pProxy, &IID_IClientSecurity, (LPVOID*)&pOtherUnknown);
2733 ok_ole_success(hr, IUnknown_QueryInterface IID_IClientSecurity);
2734 if (hr == S_OK) IUnknown_Release(pOtherUnknown);
2736 hr = IUnknown_QueryInterface(pProxy, &IID_IMultiQI, (LPVOID*)&pOtherUnknown);
2737 ok_ole_success(hr, IUnknown_QueryInterface IID_IMultiQI);
2738 if (hr == S_OK) IUnknown_Release(pOtherUnknown);
2740 hr = IUnknown_QueryInterface(pProxy, &IID_IMarshal, (LPVOID*)&pOtherUnknown);
2741 ok_ole_success(hr, IUnknown_QueryInterface IID_IMarshal);
2742 if (hr == S_OK) IUnknown_Release(pOtherUnknown);
2744 /* IMarshal2 is also supported on NT-based systems, but is pretty much
2745 * useless as it has no more methods over IMarshal that it inherits from. */
2747 IUnknown_Release(pProxy);
2749 ok_no_locks();
2751 end_host_object(tid, thread);
2754 typedef struct
2756 IUnknown IUnknown_iface;
2757 ULONG refs;
2758 } HeapUnknown;
2760 static inline HeapUnknown *impl_from_IUnknown(IUnknown *iface)
2762 return CONTAINING_RECORD(iface, HeapUnknown, IUnknown_iface);
2765 static HRESULT WINAPI HeapUnknown_QueryInterface(IUnknown *iface, REFIID riid, void **ppv)
2767 if (IsEqualIID(riid, &IID_IUnknown))
2769 IUnknown_AddRef(iface);
2770 *ppv = iface;
2771 return S_OK;
2773 *ppv = NULL;
2774 return E_NOINTERFACE;
2777 static ULONG WINAPI HeapUnknown_AddRef(IUnknown *iface)
2779 HeapUnknown *This = impl_from_IUnknown(iface);
2780 return InterlockedIncrement((LONG*)&This->refs);
2783 static ULONG WINAPI HeapUnknown_Release(IUnknown *iface)
2785 HeapUnknown *This = impl_from_IUnknown(iface);
2786 ULONG refs = InterlockedDecrement((LONG*)&This->refs);
2787 if (!refs) HeapFree(GetProcessHeap(), 0, This);
2788 return refs;
2791 static const IUnknownVtbl HeapUnknown_Vtbl =
2793 HeapUnknown_QueryInterface,
2794 HeapUnknown_AddRef,
2795 HeapUnknown_Release
2798 static void test_proxybuffer(REFIID riid)
2800 HRESULT hr;
2801 IPSFactoryBuffer *psfb;
2802 IRpcProxyBuffer *proxy;
2803 LPVOID lpvtbl;
2804 ULONG refs;
2805 CLSID clsid;
2806 HeapUnknown *pUnkOuter = HeapAlloc(GetProcessHeap(), 0, sizeof(*pUnkOuter));
2808 pUnkOuter->IUnknown_iface.lpVtbl = &HeapUnknown_Vtbl;
2809 pUnkOuter->refs = 1;
2811 hr = CoGetPSClsid(riid, &clsid);
2812 ok_ole_success(hr, CoGetPSClsid);
2814 hr = CoGetClassObject(&clsid, CLSCTX_INPROC_SERVER, NULL, &IID_IPSFactoryBuffer, (LPVOID*)&psfb);
2815 ok_ole_success(hr, CoGetClassObject);
2817 hr = IPSFactoryBuffer_CreateProxy(psfb, &pUnkOuter->IUnknown_iface, riid, &proxy, &lpvtbl);
2818 ok_ole_success(hr, IPSFactoryBuffer_CreateProxy);
2819 ok(lpvtbl != NULL, "IPSFactoryBuffer_CreateProxy succeeded, but returned a NULL vtable!\n");
2821 /* release our reference to the outer unknown object - the PS factory
2822 * buffer will have AddRef's it in the CreateProxy call */
2823 refs = IUnknown_Release(&pUnkOuter->IUnknown_iface);
2824 ok(refs == 1, "Ref count of outer unknown should have been 1 instead of %d\n", refs);
2826 /* Not checking return, unreliable on native. Maybe it leaks references? */
2827 IPSFactoryBuffer_Release(psfb);
2829 refs = IUnknown_Release((IUnknown *)lpvtbl);
2830 ok(refs == 0, "Ref-count leak of %d on IRpcProxyBuffer\n", refs);
2832 refs = IRpcProxyBuffer_Release(proxy);
2833 ok(refs == 0, "Ref-count leak of %d on IRpcProxyBuffer\n", refs);
2836 static void test_stubbuffer(REFIID riid)
2838 HRESULT hr;
2839 IPSFactoryBuffer *psfb;
2840 IRpcStubBuffer *stub;
2841 ULONG refs;
2842 CLSID clsid;
2844 cLocks = 0;
2846 hr = CoGetPSClsid(riid, &clsid);
2847 ok_ole_success(hr, CoGetPSClsid);
2849 hr = CoGetClassObject(&clsid, CLSCTX_INPROC_SERVER, NULL, &IID_IPSFactoryBuffer, (LPVOID*)&psfb);
2850 ok_ole_success(hr, CoGetClassObject);
2852 hr = IPSFactoryBuffer_CreateStub(psfb, riid, (IUnknown*)&Test_ClassFactory, &stub);
2853 ok_ole_success(hr, IPSFactoryBuffer_CreateStub);
2855 /* Not checking return, unreliable on native. Maybe it leaks references? */
2856 IPSFactoryBuffer_Release(psfb);
2858 ok_more_than_one_lock();
2860 IRpcStubBuffer_Disconnect(stub);
2862 ok_no_locks();
2864 refs = IRpcStubBuffer_Release(stub);
2865 ok(refs == 0, "Ref-count leak of %d on IRpcProxyBuffer\n", refs);
2868 static HWND hwnd_app;
2870 static HRESULT WINAPI TestRE_IClassFactory_CreateInstance(
2871 LPCLASSFACTORY iface,
2872 LPUNKNOWN pUnkOuter,
2873 REFIID riid,
2874 LPVOID *ppvObj)
2876 DWORD_PTR res;
2877 if (IsEqualIID(riid, &IID_IWineTest))
2879 BOOL ret = SendMessageTimeoutA(hwnd_app, WM_NULL, 0, 0, SMTO_BLOCK, 5000, &res);
2880 ok(ret, "Timed out sending a message to originating window during RPC call\n");
2882 *ppvObj = NULL;
2883 return S_FALSE;
2886 static const IClassFactoryVtbl TestREClassFactory_Vtbl =
2888 Test_IClassFactory_QueryInterface,
2889 Test_IClassFactory_AddRef,
2890 Test_IClassFactory_Release,
2891 TestRE_IClassFactory_CreateInstance,
2892 Test_IClassFactory_LockServer
2895 static IClassFactory TestRE_ClassFactory = { &TestREClassFactory_Vtbl };
2897 static LRESULT CALLBACK window_proc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam)
2899 switch (msg)
2901 case WM_USER:
2903 HRESULT hr;
2904 IStream *pStream = NULL;
2905 IClassFactory *proxy = NULL;
2906 IUnknown *object;
2907 DWORD tid;
2908 HANDLE thread;
2910 cLocks = 0;
2912 hr = CreateStreamOnHGlobal(NULL, TRUE, &pStream);
2913 ok_ole_success(hr, CreateStreamOnHGlobal);
2914 tid = start_host_object(pStream, &IID_IClassFactory, (IUnknown*)&TestRE_ClassFactory, MSHLFLAGS_NORMAL, &thread);
2916 ok_more_than_one_lock();
2918 IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
2919 hr = CoUnmarshalInterface(pStream, &IID_IClassFactory, (void **)&proxy);
2920 ok_ole_success(hr, CoReleaseMarshalData);
2921 IStream_Release(pStream);
2923 ok_more_than_one_lock();
2925 /* note the use of the magic IID_IWineTest value to tell remote thread
2926 * to try to send a message back to us */
2927 hr = IClassFactory_CreateInstance(proxy, NULL, &IID_IWineTest, (void **)&object);
2928 ok(hr == S_FALSE, "expected S_FALSE, got %d\n", hr);
2930 IClassFactory_Release(proxy);
2932 ok_no_locks();
2934 end_host_object(tid, thread);
2936 PostMessageA(hwnd, WM_QUIT, 0, 0);
2938 return 0;
2940 case WM_USER+1:
2942 HRESULT hr;
2943 IStream *pStream = NULL;
2944 IClassFactory *proxy = NULL;
2945 IUnknown *object;
2946 DWORD tid;
2947 HANDLE thread;
2949 cLocks = 0;
2951 hr = CreateStreamOnHGlobal(NULL, TRUE, &pStream);
2952 ok_ole_success(hr, CreateStreamOnHGlobal);
2953 tid = start_host_object(pStream, &IID_IClassFactory, (IUnknown*)&TestRE_ClassFactory, MSHLFLAGS_NORMAL, &thread);
2955 ok_more_than_one_lock();
2957 IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
2958 hr = CoUnmarshalInterface(pStream, &IID_IClassFactory, (void **)&proxy);
2959 ok_ole_success(hr, CoReleaseMarshalData);
2960 IStream_Release(pStream);
2962 ok_more_than_one_lock();
2964 /* post quit message before a doing a COM call to show that a pending
2965 * WM_QUIT message doesn't stop the call from succeeding */
2966 PostMessageA(hwnd, WM_QUIT, 0, 0);
2967 hr = IClassFactory_CreateInstance(proxy, NULL, &IID_IUnknown, (void **)&object);
2968 ok(hr == S_FALSE, "IClassFactory_CreateInstance returned 0x%08x, expected S_FALSE\n", hr);
2970 IClassFactory_Release(proxy);
2972 ok_no_locks();
2974 end_host_object(tid, thread);
2976 return 0;
2978 case WM_USER+2:
2980 HRESULT hr;
2981 IStream *pStream = NULL;
2982 IClassFactory *proxy = NULL;
2983 IUnknown *object;
2984 DWORD tid;
2985 HANDLE thread;
2987 hr = CreateStreamOnHGlobal(NULL, TRUE, &pStream);
2988 ok_ole_success(hr, CreateStreamOnHGlobal);
2989 tid = start_host_object(pStream, &IID_IClassFactory, (IUnknown*)&Test_ClassFactory, MSHLFLAGS_NORMAL, &thread);
2991 IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
2992 hr = CoUnmarshalInterface(pStream, &IID_IClassFactory, (void **)&proxy);
2993 ok_ole_success(hr, CoReleaseMarshalData);
2994 IStream_Release(pStream);
2996 /* shows that COM calls executed during the processing of sent
2997 * messages should fail */
2998 hr = IClassFactory_CreateInstance(proxy, NULL, &IID_IUnknown, (void **)&object);
2999 ok(hr == RPC_E_CANTCALLOUT_ININPUTSYNCCALL,
3000 "COM call during processing of sent message should return RPC_E_CANTCALLOUT_ININPUTSYNCCALL instead of 0x%08x\n", hr);
3002 IClassFactory_Release(proxy);
3004 end_host_object(tid, thread);
3006 PostQuitMessage(0);
3008 return 0;
3010 default:
3011 return DefWindowProcA(hwnd, msg, wparam, lparam);
3015 static void register_test_window(void)
3017 WNDCLASSA wndclass;
3019 memset(&wndclass, 0, sizeof(wndclass));
3020 wndclass.lpfnWndProc = window_proc;
3021 wndclass.lpszClassName = "WineCOMTest";
3022 RegisterClassA(&wndclass);
3025 static void test_message_reentrancy(void)
3027 MSG msg;
3029 hwnd_app = CreateWindowA("WineCOMTest", NULL, 0, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, NULL, NULL, NULL, 0);
3030 ok(hwnd_app != NULL, "Window creation failed\n");
3032 /* start message re-entrancy test */
3033 PostMessageA(hwnd_app, WM_USER, 0, 0);
3035 while (GetMessageA(&msg, NULL, 0, 0))
3037 TranslateMessage(&msg);
3038 DispatchMessageA(&msg);
3040 DestroyWindow(hwnd_app);
3043 static HRESULT WINAPI TestMsg_IClassFactory_CreateInstance(
3044 LPCLASSFACTORY iface,
3045 LPUNKNOWN pUnkOuter,
3046 REFIID riid,
3047 LPVOID *ppvObj)
3049 *ppvObj = NULL;
3050 SendMessageA(hwnd_app, WM_USER+2, 0, 0);
3051 return S_OK;
3054 static IClassFactoryVtbl TestMsgClassFactory_Vtbl =
3056 Test_IClassFactory_QueryInterface,
3057 Test_IClassFactory_AddRef,
3058 Test_IClassFactory_Release,
3059 TestMsg_IClassFactory_CreateInstance,
3060 Test_IClassFactory_LockServer
3063 static IClassFactory TestMsg_ClassFactory = { &TestMsgClassFactory_Vtbl };
3065 static void test_call_from_message(void)
3067 MSG msg;
3068 IStream *pStream;
3069 HRESULT hr;
3070 IClassFactory *proxy;
3071 DWORD tid;
3072 HANDLE thread;
3073 IUnknown *object;
3075 hwnd_app = CreateWindowA("WineCOMTest", NULL, 0, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, NULL, NULL, NULL, 0);
3076 ok(hwnd_app != NULL, "Window creation failed\n");
3078 hr = CreateStreamOnHGlobal(NULL, TRUE, &pStream);
3079 ok_ole_success(hr, CreateStreamOnHGlobal);
3080 tid = start_host_object(pStream, &IID_IClassFactory, (IUnknown*)&TestMsg_ClassFactory, MSHLFLAGS_NORMAL, &thread);
3082 ok_more_than_one_lock();
3084 IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
3085 hr = CoUnmarshalInterface(pStream, &IID_IClassFactory, (void **)&proxy);
3086 ok_ole_success(hr, CoReleaseMarshalData);
3087 IStream_Release(pStream);
3089 ok_more_than_one_lock();
3091 /* start message re-entrancy test */
3092 hr = IClassFactory_CreateInstance(proxy, NULL, &IID_IUnknown, (void **)&object);
3093 ok_ole_success(hr, IClassFactory_CreateInstance);
3095 IClassFactory_Release(proxy);
3097 ok_no_locks();
3099 end_host_object(tid, thread);
3101 while (GetMessageA(&msg, NULL, 0, 0))
3103 TranslateMessage(&msg);
3104 DispatchMessageA(&msg);
3106 DestroyWindow(hwnd_app);
3109 static void test_WM_QUIT_handling(void)
3111 MSG msg;
3113 hwnd_app = CreateWindowA("WineCOMTest", NULL, 0, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, NULL, NULL, NULL, 0);
3114 ok(hwnd_app != NULL, "Window creation failed\n");
3116 /* start WM_QUIT handling test */
3117 PostMessageA(hwnd_app, WM_USER+1, 0, 0);
3119 while (GetMessageA(&msg, NULL, 0, 0))
3121 TranslateMessage(&msg);
3122 DispatchMessageA(&msg);
3126 static SIZE_T round_global_size(SIZE_T size)
3128 static SIZE_T global_size_alignment = -1;
3129 if (global_size_alignment == -1)
3131 void *p = GlobalAlloc(GMEM_FIXED, 1);
3132 global_size_alignment = GlobalSize(p);
3133 GlobalFree(p);
3136 return ((size + global_size_alignment - 1) & ~(global_size_alignment - 1));
3139 static void test_freethreadedmarshaldata(IStream *pStream, MSHCTX mshctx, void *ptr, DWORD mshlflags)
3141 HGLOBAL hglobal;
3142 DWORD size;
3143 char *marshal_data;
3144 HRESULT hr;
3146 hr = GetHGlobalFromStream(pStream, &hglobal);
3147 ok_ole_success(hr, GetHGlobalFromStream);
3149 size = GlobalSize(hglobal);
3151 marshal_data = GlobalLock(hglobal);
3153 if (mshctx == MSHCTX_INPROC)
3155 DWORD expected_size = round_global_size(3*sizeof(DWORD) + sizeof(GUID));
3156 ok(size == expected_size, "expected size %u, got %u\n", expected_size, size);
3158 ok(*(DWORD *)marshal_data == mshlflags, "expected 0x%x, but got 0x%x for mshctx\n", mshlflags, *(DWORD *)marshal_data);
3159 marshal_data += sizeof(DWORD);
3160 ok(*(void **)marshal_data == ptr, "expected %p, but got %p for mshctx\n", ptr, *(void **)marshal_data);
3161 marshal_data += sizeof(void *);
3162 if (sizeof(void*) == 4 && size >= 3*sizeof(DWORD))
3164 ok(*(DWORD *)marshal_data == 0, "expected 0x0, but got 0x%x\n", *(DWORD *)marshal_data);
3165 marshal_data += sizeof(DWORD);
3167 if (size >= 3*sizeof(DWORD) + sizeof(GUID) && winetest_debug > 1)
3169 trace("got guid data: %s\n", wine_dbgstr_guid((GUID *)marshal_data));
3172 else
3174 ok(size > sizeof(DWORD), "size should have been > sizeof(DWORD), not %d\n", size);
3175 ok(*(DWORD *)marshal_data == 0x574f454d /* MEOW */,
3176 "marshal data should be filled by standard marshal and start with MEOW signature\n");
3179 GlobalUnlock(hglobal);
3182 static void test_freethreadedmarshaler(void)
3184 HRESULT hr;
3185 IUnknown *pFTUnknown;
3186 IMarshal *pFTMarshal;
3187 IStream *pStream;
3188 IUnknown *pProxy;
3189 static const LARGE_INTEGER llZero;
3190 CLSID clsid;
3192 cLocks = 0;
3193 hr = CoCreateFreeThreadedMarshaler(NULL, &pFTUnknown);
3194 ok_ole_success(hr, CoCreateFreeThreadedMarshaler);
3195 hr = IUnknown_QueryInterface(pFTUnknown, &IID_IMarshal, (void **)&pFTMarshal);
3196 ok_ole_success(hr, IUnknown_QueryInterface);
3197 IUnknown_Release(pFTUnknown);
3199 hr = CreateStreamOnHGlobal(NULL, TRUE, &pStream);
3200 ok_ole_success(hr, CreateStreamOnHGlobal);
3202 /* inproc normal marshaling */
3204 hr = IMarshal_GetUnmarshalClass(pFTMarshal, &IID_IClassFactory,
3205 &Test_ClassFactory, MSHCTX_INPROC, NULL, MSHLFLAGS_NORMAL, &clsid);
3206 ok_ole_success(hr, IMarshal_GetUnmarshalClass);
3207 ok(IsEqualIID(&clsid, &CLSID_InProcFreeMarshaler), "clsid = %s\n",
3208 wine_dbgstr_guid(&clsid));
3210 hr = IMarshal_MarshalInterface(pFTMarshal, pStream, &IID_IClassFactory,
3211 &Test_ClassFactory, MSHCTX_INPROC, NULL, MSHLFLAGS_NORMAL);
3212 ok_ole_success(hr, IMarshal_MarshalInterface);
3214 ok_more_than_one_lock();
3216 test_freethreadedmarshaldata(pStream, MSHCTX_INPROC, &Test_ClassFactory, MSHLFLAGS_NORMAL);
3218 IStream_Seek(pStream, llZero, STREAM_SEEK_SET, NULL);
3219 hr = IMarshal_UnmarshalInterface(pFTMarshal, pStream, &IID_IUnknown, (void **)&pProxy);
3220 ok_ole_success(hr, IMarshal_UnmarshalInterface);
3222 IUnknown_Release(pProxy);
3224 ok_no_locks();
3226 /* inproc table-strong marshaling */
3228 IStream_Seek(pStream, llZero, STREAM_SEEK_SET, NULL);
3229 hr = IMarshal_MarshalInterface(pFTMarshal, pStream, &IID_IClassFactory,
3230 (IUnknown*)&Test_ClassFactory, MSHCTX_INPROC, (void *)0xdeadbeef,
3231 MSHLFLAGS_TABLESTRONG);
3232 ok_ole_success(hr, IMarshal_MarshalInterface);
3234 ok_more_than_one_lock();
3236 test_freethreadedmarshaldata(pStream, MSHCTX_INPROC, &Test_ClassFactory, MSHLFLAGS_TABLESTRONG);
3238 IStream_Seek(pStream, llZero, STREAM_SEEK_SET, NULL);
3239 hr = IMarshal_UnmarshalInterface(pFTMarshal, pStream, &IID_IUnknown, (void **)&pProxy);
3240 ok_ole_success(hr, IMarshal_UnmarshalInterface);
3242 IUnknown_Release(pProxy);
3244 ok_more_than_one_lock();
3246 IStream_Seek(pStream, llZero, STREAM_SEEK_SET, NULL);
3247 hr = IMarshal_ReleaseMarshalData(pFTMarshal, pStream);
3248 ok_ole_success(hr, IMarshal_ReleaseMarshalData);
3250 ok_no_locks();
3252 /* inproc table-weak marshaling */
3254 IStream_Seek(pStream, llZero, STREAM_SEEK_SET, NULL);
3255 hr = IMarshal_MarshalInterface(pFTMarshal, pStream, &IID_IClassFactory,
3256 (IUnknown*)&Test_ClassFactory, MSHCTX_INPROC, (void *)0xdeadbeef,
3257 MSHLFLAGS_TABLEWEAK);
3258 ok_ole_success(hr, IMarshal_MarshalInterface);
3260 ok_no_locks();
3262 test_freethreadedmarshaldata(pStream, MSHCTX_INPROC, &Test_ClassFactory, MSHLFLAGS_TABLEWEAK);
3264 IStream_Seek(pStream, llZero, STREAM_SEEK_SET, NULL);
3265 hr = IMarshal_UnmarshalInterface(pFTMarshal, pStream, &IID_IUnknown, (void **)&pProxy);
3266 ok_ole_success(hr, IMarshal_UnmarshalInterface);
3268 ok_more_than_one_lock();
3270 IUnknown_Release(pProxy);
3272 ok_no_locks();
3274 /* inproc normal marshaling (for extraordinary cases) */
3276 IStream_Seek(pStream, llZero, STREAM_SEEK_SET, NULL);
3277 hr = IMarshal_MarshalInterface(pFTMarshal, pStream, &IID_IClassFactory,
3278 &Test_ClassFactory, MSHCTX_INPROC, NULL, MSHLFLAGS_NORMAL);
3279 ok_ole_success(hr, IMarshal_MarshalInterface);
3281 ok_more_than_one_lock();
3283 /* this call shows that DisconnectObject does nothing */
3284 hr = IMarshal_DisconnectObject(pFTMarshal, 0);
3285 ok_ole_success(hr, IMarshal_DisconnectObject);
3287 ok_more_than_one_lock();
3289 IStream_Seek(pStream, llZero, STREAM_SEEK_SET, NULL);
3290 hr = IMarshal_ReleaseMarshalData(pFTMarshal, pStream);
3291 ok_ole_success(hr, IMarshal_ReleaseMarshalData);
3293 ok_no_locks();
3295 /* doesn't enforce marshaling rules here and allows us to unmarshal the
3296 * interface, even though it was freed above */
3297 IStream_Seek(pStream, llZero, STREAM_SEEK_SET, NULL);
3298 hr = IMarshal_UnmarshalInterface(pFTMarshal, pStream, &IID_IUnknown, (void **)&pProxy);
3299 ok_ole_success(hr, IMarshal_UnmarshalInterface);
3301 ok_no_locks();
3303 /* local normal marshaling */
3305 hr = IMarshal_GetUnmarshalClass(pFTMarshal, &IID_IClassFactory,
3306 &Test_ClassFactory, MSHCTX_LOCAL, NULL, MSHLFLAGS_NORMAL, &clsid);
3307 ok_ole_success(hr, IMarshal_GetUnmarshalClass);
3308 ok(IsEqualGUID(&clsid, &CLSID_StdMarshal) || IsEqualGUID(&clsid, &CLSID_ft_unmarshaler_1809) /* Win10 1809 */,
3309 "clsid = %s\n", wine_dbgstr_guid(&clsid));
3311 IStream_Seek(pStream, llZero, STREAM_SEEK_SET, NULL);
3312 hr = IMarshal_MarshalInterface(pFTMarshal, pStream, &IID_IClassFactory, &Test_ClassFactory, MSHCTX_LOCAL, NULL, MSHLFLAGS_NORMAL);
3313 ok_ole_success(hr, IMarshal_MarshalInterface);
3315 ok_more_than_one_lock();
3317 test_freethreadedmarshaldata(pStream, MSHCTX_LOCAL, &Test_ClassFactory, MSHLFLAGS_NORMAL);
3319 IStream_Seek(pStream, llZero, STREAM_SEEK_SET, NULL);
3320 hr = CoReleaseMarshalData(pStream);
3321 ok_ole_success(hr, CoReleaseMarshalData);
3323 ok_no_locks();
3325 IStream_Release(pStream);
3326 IMarshal_Release(pFTMarshal);
3329 static HRESULT reg_unreg_wine_test_class(BOOL Register)
3331 HRESULT hr;
3332 char buffer[256];
3333 LPOLESTR pszClsid;
3334 HKEY hkey;
3335 DWORD dwDisposition;
3336 DWORD error;
3338 hr = StringFromCLSID(&CLSID_WineTest, &pszClsid);
3339 ok_ole_success(hr, "StringFromCLSID");
3340 strcpy(buffer, "CLSID\\");
3341 WideCharToMultiByte(CP_ACP, 0, pszClsid, -1, buffer + strlen(buffer), sizeof(buffer) - strlen(buffer), NULL, NULL);
3342 CoTaskMemFree(pszClsid);
3343 strcat(buffer, "\\InprocHandler32");
3344 if (Register)
3346 error = RegCreateKeyExA(HKEY_CLASSES_ROOT, buffer, 0, NULL, 0, KEY_SET_VALUE, NULL, &hkey, &dwDisposition);
3347 if (error == ERROR_ACCESS_DENIED)
3349 skip("Not authorized to modify the Classes key\n");
3350 return E_FAIL;
3352 ok(error == ERROR_SUCCESS, "RegCreateKeyEx failed with error %d\n", error);
3353 if (error != ERROR_SUCCESS) hr = E_FAIL;
3354 error = RegSetValueExA(hkey, NULL, 0, REG_SZ, (const unsigned char *)"\"ole32.dll\"", strlen("\"ole32.dll\"") + 1);
3355 ok(error == ERROR_SUCCESS, "RegSetValueEx failed with error %d\n", error);
3356 if (error != ERROR_SUCCESS) hr = E_FAIL;
3357 RegCloseKey(hkey);
3359 else
3361 RegDeleteKeyA(HKEY_CLASSES_ROOT, buffer);
3362 *strrchr(buffer, '\\') = '\0';
3363 RegDeleteKeyA(HKEY_CLASSES_ROOT, buffer);
3365 return hr;
3368 static void test_inproc_handler(void)
3370 HRESULT hr;
3371 IUnknown *pObject;
3372 IUnknown *pObject2;
3374 if (FAILED(reg_unreg_wine_test_class(TRUE)))
3375 return;
3377 hr = CoCreateInstance(&CLSID_WineTest, NULL, CLSCTX_INPROC_HANDLER, &IID_IUnknown, (void **)&pObject);
3378 ok_ole_success(hr, "CoCreateInstance");
3380 if (SUCCEEDED(hr))
3382 hr = IUnknown_QueryInterface(pObject, &IID_IWineTest, (void **)&pObject2);
3383 ok(hr == E_NOINTERFACE, "IUnknown_QueryInterface on handler for invalid interface returned 0x%08x instead of E_NOINTERFACE\n", hr);
3385 /* it's a handler as it supports IOleObject */
3386 hr = IUnknown_QueryInterface(pObject, &IID_IOleObject, (void **)&pObject2);
3387 ok_ole_success(hr, "IUnknown_QueryInterface(&IID_IOleObject)");
3388 IUnknown_Release(pObject2);
3390 IUnknown_Release(pObject);
3393 reg_unreg_wine_test_class(FALSE);
3396 static HRESULT WINAPI Test_SMI_QueryInterface(
3397 IStdMarshalInfo *iface,
3398 REFIID riid,
3399 LPVOID *ppvObj)
3401 if (ppvObj == NULL) return E_POINTER;
3403 if (IsEqualGUID(riid, &IID_IUnknown) ||
3404 IsEqualGUID(riid, &IID_IStdMarshalInfo))
3406 *ppvObj = iface;
3407 IStdMarshalInfo_AddRef(iface);
3408 return S_OK;
3411 return E_NOINTERFACE;
3414 static ULONG WINAPI Test_SMI_AddRef(IStdMarshalInfo *iface)
3416 LockModule();
3417 return 2; /* non-heap-based object */
3420 static ULONG WINAPI Test_SMI_Release(IStdMarshalInfo *iface)
3422 UnlockModule();
3423 return 1; /* non-heap-based object */
3426 static HRESULT WINAPI Test_SMI_GetClassForHandler(
3427 IStdMarshalInfo *iface,
3428 DWORD dwDestContext,
3429 void *pvDestContext,
3430 CLSID *pClsid)
3432 *pClsid = CLSID_WineTest;
3433 return S_OK;
3436 static const IStdMarshalInfoVtbl Test_SMI_Vtbl =
3438 Test_SMI_QueryInterface,
3439 Test_SMI_AddRef,
3440 Test_SMI_Release,
3441 Test_SMI_GetClassForHandler
3444 static IStdMarshalInfo Test_SMI = {&Test_SMI_Vtbl};
3446 static void test_handler_marshaling(void)
3448 HRESULT hr;
3449 IStream *pStream = NULL;
3450 IUnknown *pProxy = NULL;
3451 IUnknown *pObject;
3452 DWORD tid;
3453 HANDLE thread;
3454 static const LARGE_INTEGER ullZero;
3456 if (FAILED(reg_unreg_wine_test_class(TRUE)))
3457 return;
3458 cLocks = 0;
3460 hr = CreateStreamOnHGlobal(NULL, TRUE, &pStream);
3461 ok_ole_success(hr, "CreateStreamOnHGlobal");
3462 tid = start_host_object(pStream, &IID_IUnknown, (IUnknown*)&Test_SMI, MSHLFLAGS_NORMAL, &thread);
3464 ok_more_than_one_lock();
3466 IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
3467 hr = CoUnmarshalInterface(pStream, &IID_IUnknown, (void **)&pProxy);
3468 ok_ole_success(hr, "CoUnmarshalInterface");
3469 IStream_Release(pStream);
3471 if(hr == S_OK)
3473 ok_more_than_one_lock();
3475 hr = IUnknown_QueryInterface(pProxy, &IID_IWineTest, (void **)&pObject);
3476 ok(hr == E_NOINTERFACE, "IUnknown_QueryInterface with unknown IID should have returned E_NOINTERFACE instead of 0x%08x\n", hr);
3478 /* it's a handler as it supports IOleObject */
3479 hr = IUnknown_QueryInterface(pProxy, &IID_IOleObject, (void **)&pObject);
3480 todo_wine
3481 ok_ole_success(hr, "IUnknown_QueryInterface(&IID_IOleObject)");
3482 if (SUCCEEDED(hr)) IUnknown_Release(pObject);
3484 IUnknown_Release(pProxy);
3486 ok_no_locks();
3489 end_host_object(tid, thread);
3490 reg_unreg_wine_test_class(FALSE);
3492 /* FIXME: test IPersist interface has the same effect as IStdMarshalInfo */
3496 static void test_client_security(void)
3498 HRESULT hr;
3499 IStream *pStream = NULL;
3500 IClassFactory *pProxy = NULL;
3501 IUnknown *pProxy2 = NULL;
3502 IUnknown *pUnknown1 = NULL;
3503 IUnknown *pUnknown2 = NULL;
3504 IClientSecurity *pCliSec = NULL;
3505 IMarshal *pMarshal;
3506 DWORD tid;
3507 HANDLE thread;
3508 static const LARGE_INTEGER ullZero;
3509 DWORD dwAuthnSvc;
3510 DWORD dwAuthzSvc;
3511 OLECHAR *pServerPrincName;
3512 DWORD dwAuthnLevel;
3513 DWORD dwImpLevel;
3514 void *pAuthInfo;
3515 DWORD dwCapabilities;
3516 void *pv;
3518 cLocks = 0;
3520 hr = CreateStreamOnHGlobal(NULL, TRUE, &pStream);
3521 ok_ole_success(hr, "CreateStreamOnHGlobal");
3522 tid = start_host_object(pStream, &IID_IClassFactory, (IUnknown*)&Test_ClassFactory, MSHLFLAGS_NORMAL, &thread);
3524 IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
3525 hr = CoUnmarshalInterface(pStream, &IID_IClassFactory, (void **)&pProxy);
3526 ok_ole_success(hr, "CoUnmarshalInterface");
3527 IStream_Release(pStream);
3529 hr = IClassFactory_QueryInterface(pProxy, &IID_IUnknown, (LPVOID*)&pUnknown1);
3530 ok_ole_success(hr, "IUnknown_QueryInterface IID_IUnknown");
3532 /* Does not work on Windows 10 19xx+ */
3533 if (SUCCEEDED(IClassFactory_QueryInterface(pProxy, &IID_IRemUnknown, (void **)&pProxy2)))
3535 hr = IUnknown_QueryInterface(pProxy2, &IID_IUnknown, (void **)&pUnknown2);
3536 ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
3538 ok(pUnknown1 == pUnknown2, "both proxy's IUnknowns should be the same - %p, %p\n", pUnknown1, pUnknown2);
3539 IUnknown_Release(pUnknown2);
3541 IUnknown_Release(pProxy2);
3544 hr = IClassFactory_QueryInterface(pProxy, &IID_IMarshal, (LPVOID*)&pMarshal);
3545 ok_ole_success(hr, "IUnknown_QueryInterface IID_IMarshal");
3547 hr = IClassFactory_QueryInterface(pProxy, &IID_IClientSecurity, (LPVOID*)&pCliSec);
3548 ok_ole_success(hr, "IUnknown_QueryInterface IID_IClientSecurity");
3550 hr = IClientSecurity_QueryBlanket(pCliSec, (IUnknown *)pProxy, NULL, NULL, NULL, NULL, NULL, NULL, NULL);
3551 todo_wine ok_ole_success(hr, "IClientSecurity_QueryBlanket (all NULLs)");
3553 hr = IClientSecurity_QueryBlanket(pCliSec, (IUnknown *)pMarshal, NULL, NULL, NULL, NULL, NULL, NULL, NULL);
3554 todo_wine ok(hr == E_NOINTERFACE, "IClientSecurity_QueryBlanket with local interface should have returned E_NOINTERFACE instead of 0x%08x\n", hr);
3556 hr = IClientSecurity_QueryBlanket(pCliSec, (IUnknown *)pProxy, &dwAuthnSvc, &dwAuthzSvc, &pServerPrincName, &dwAuthnLevel, &dwImpLevel, &pAuthInfo, &dwCapabilities);
3557 todo_wine ok_ole_success(hr, "IClientSecurity_QueryBlanket");
3559 hr = IClientSecurity_SetBlanket(pCliSec, (IUnknown *)pProxy, dwAuthnSvc, dwAuthzSvc, pServerPrincName, dwAuthnLevel, RPC_C_IMP_LEVEL_IMPERSONATE, pAuthInfo, dwCapabilities);
3560 todo_wine ok_ole_success(hr, "IClientSecurity_SetBlanket");
3562 hr = IClassFactory_CreateInstance(pProxy, NULL, &IID_IWineTest, &pv);
3563 ok(hr == E_NOINTERFACE, "COM call should have succeeded instead of returning 0x%08x\n", hr);
3565 hr = IClientSecurity_SetBlanket(pCliSec, (IUnknown *)pMarshal, dwAuthnSvc, dwAuthzSvc, pServerPrincName, dwAuthnLevel, dwImpLevel, pAuthInfo, dwCapabilities);
3566 todo_wine ok(hr == E_NOINTERFACE, "IClientSecurity_SetBlanket with local interface should have returned E_NOINTERFACE instead of 0x%08x\n", hr);
3568 hr = IClientSecurity_SetBlanket(pCliSec, (IUnknown *)pProxy, 0xdeadbeef, dwAuthzSvc, pServerPrincName, dwAuthnLevel, dwImpLevel, pAuthInfo, dwCapabilities);
3569 todo_wine ok(hr == E_INVALIDARG, "IClientSecurity_SetBlanke with invalid dwAuthnSvc should have returned E_INVALIDARG instead of 0x%08x\n", hr);
3571 CoTaskMemFree(pServerPrincName);
3573 hr = IClientSecurity_QueryBlanket(pCliSec, pUnknown1, &dwAuthnSvc, &dwAuthzSvc, &pServerPrincName, &dwAuthnLevel, &dwImpLevel, &pAuthInfo, &dwCapabilities);
3574 todo_wine ok_ole_success(hr, "IClientSecurity_QueryBlanket(IUnknown)");
3576 CoTaskMemFree(pServerPrincName);
3578 IClassFactory_Release(pProxy);
3579 IUnknown_Release(pUnknown1);
3580 IMarshal_Release(pMarshal);
3581 IClientSecurity_Release(pCliSec);
3583 end_host_object(tid, thread);
3586 static HANDLE heventShutdown;
3588 static void LockModuleOOP(void)
3590 InterlockedIncrement(&cLocks); /* for test purposes only */
3591 CoAddRefServerProcess();
3594 static void UnlockModuleOOP(void)
3596 InterlockedDecrement(&cLocks); /* for test purposes only */
3597 if (!CoReleaseServerProcess())
3598 SetEvent(heventShutdown);
3601 static HWND hwnd_app;
3603 struct local_server
3605 IPersist IPersist_iface; /* a nice short interface */
3608 static HRESULT WINAPI local_server_QueryInterface(IPersist *iface, REFIID iid, void **obj)
3610 *obj = NULL;
3612 if (IsEqualGUID(iid, &IID_IUnknown) ||
3613 IsEqualGUID(iid, &IID_IPersist))
3614 *obj = iface;
3616 if (*obj)
3618 IPersist_AddRef(iface);
3619 return S_OK;
3621 return E_NOINTERFACE;
3624 static ULONG WINAPI local_server_AddRef(IPersist *iface)
3626 return 2;
3629 static ULONG WINAPI local_server_Release(IPersist *iface)
3631 return 1;
3634 static HRESULT WINAPI local_server_GetClassID(IPersist *iface, CLSID *clsid)
3636 HRESULT hr;
3638 *clsid = IID_IUnknown;
3640 /* Test calling CoDisconnectObject within a COM call */
3641 hr = CoDisconnectObject((IUnknown *)iface, 0);
3642 ok(hr == S_OK, "got %08x\n", hr);
3644 /* Initialize and uninitialize the apartment to show that we
3645 * remain in the autojoined mta */
3646 hr = CoInitializeEx( NULL, COINIT_MULTITHREADED );
3647 ok( hr == S_FALSE, "got %08x\n", hr );
3648 CoUninitialize();
3650 return S_OK;
3653 static const IPersistVtbl local_server_persist_vtbl =
3655 local_server_QueryInterface,
3656 local_server_AddRef,
3657 local_server_Release,
3658 local_server_GetClassID
3661 struct local_server local_server_class =
3663 {&local_server_persist_vtbl}
3666 static HRESULT WINAPI TestOOP_IClassFactory_QueryInterface(
3667 LPCLASSFACTORY iface,
3668 REFIID riid,
3669 LPVOID *ppvObj)
3671 if (ppvObj == NULL) return E_POINTER;
3673 if (IsEqualGUID(riid, &IID_IUnknown) ||
3674 IsEqualGUID(riid, &IID_IClassFactory))
3676 *ppvObj = iface;
3677 IClassFactory_AddRef(iface);
3678 return S_OK;
3681 return E_NOINTERFACE;
3684 static ULONG WINAPI TestOOP_IClassFactory_AddRef(LPCLASSFACTORY iface)
3686 return 2; /* non-heap-based object */
3689 static ULONG WINAPI TestOOP_IClassFactory_Release(LPCLASSFACTORY iface)
3691 return 1; /* non-heap-based object */
3694 static HRESULT WINAPI TestOOP_IClassFactory_CreateInstance(
3695 LPCLASSFACTORY iface,
3696 LPUNKNOWN pUnkOuter,
3697 REFIID riid,
3698 LPVOID *ppvObj)
3700 IPersist *persist = &local_server_class.IPersist_iface;
3701 HRESULT hr;
3702 IPersist_AddRef( persist );
3703 hr = IPersist_QueryInterface( persist, riid, ppvObj );
3704 IPersist_Release( persist );
3705 return hr;
3708 static HRESULT WINAPI TestOOP_IClassFactory_LockServer(
3709 LPCLASSFACTORY iface,
3710 BOOL fLock)
3712 if (fLock)
3713 LockModuleOOP();
3714 else
3715 UnlockModuleOOP();
3716 return S_OK;
3719 static const IClassFactoryVtbl TestClassFactoryOOP_Vtbl =
3721 TestOOP_IClassFactory_QueryInterface,
3722 TestOOP_IClassFactory_AddRef,
3723 TestOOP_IClassFactory_Release,
3724 TestOOP_IClassFactory_CreateInstance,
3725 TestOOP_IClassFactory_LockServer
3728 static IClassFactory TestOOP_ClassFactory = { &TestClassFactoryOOP_Vtbl };
3730 static void test_register_local_server(void)
3732 DWORD cookie;
3733 HRESULT hr;
3734 HANDLE ready_event;
3735 DWORD wait;
3736 HANDLE handles[2];
3738 heventShutdown = CreateEventA(NULL, TRUE, FALSE, NULL);
3739 ready_event = CreateEventA(NULL, FALSE, FALSE, "Wine COM Test Ready Event");
3740 handles[0] = CreateEventA(NULL, FALSE, FALSE, "Wine COM Test Quit Event");
3741 handles[1] = CreateEventA(NULL, FALSE, FALSE, "Wine COM Test Repeat Event");
3743 again:
3744 hr = CoRegisterClassObject(&CLSID_WineOOPTest, (IUnknown *)&TestOOP_ClassFactory,
3745 CLSCTX_LOCAL_SERVER, REGCLS_SINGLEUSE, &cookie);
3746 ok_ole_success(hr, CoRegisterClassObject);
3748 SetEvent(ready_event);
3752 wait = MsgWaitForMultipleObjects(2, handles, FALSE, 30000, QS_ALLINPUT);
3753 if (wait == WAIT_OBJECT_0+2)
3755 MSG msg;
3757 if (PeekMessageA(&msg, NULL, 0, 0, PM_REMOVE))
3759 TranslateMessage(&msg);
3760 DispatchMessageA(&msg);
3763 else if (wait == WAIT_OBJECT_0+1)
3765 hr = CoRevokeClassObject(cookie);
3766 ok_ole_success(hr, CoRevokeClassObject);
3767 goto again;
3770 while (wait == WAIT_OBJECT_0+2);
3772 ok( wait == WAIT_OBJECT_0, "quit event wait timed out\n" );
3773 hr = CoRevokeClassObject(cookie);
3774 ok_ole_success(hr, CoRevokeClassObject);
3775 CloseHandle(handles[0]);
3776 CloseHandle(handles[1]);
3779 static HANDLE create_target_process(const char *arg)
3781 char **argv;
3782 char cmdline[MAX_PATH];
3783 BOOL ret;
3784 PROCESS_INFORMATION pi;
3785 STARTUPINFOA si = { 0 };
3786 si.cb = sizeof(si);
3788 pi.hThread = NULL;
3789 pi.hProcess = NULL;
3790 winetest_get_mainargs( &argv );
3791 sprintf(cmdline, "\"%s\" %s %s", argv[0], argv[1], arg);
3792 ret = CreateProcessA(argv[0], cmdline, NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi);
3793 ok(ret, "CreateProcess failed with error: %u\n", GetLastError());
3794 if (pi.hThread) CloseHandle(pi.hThread);
3795 return pi.hProcess;
3798 /* tests functions commonly used by out of process COM servers */
3799 static void test_local_server(void)
3801 DWORD cookie;
3802 HRESULT hr;
3803 IClassFactory * cf;
3804 IPersist *persist;
3805 DWORD ret;
3806 HANDLE process;
3807 HANDLE quit_event;
3808 HANDLE ready_event;
3809 HANDLE repeat_event;
3810 CLSID clsid;
3812 heventShutdown = CreateEventA(NULL, TRUE, FALSE, NULL);
3814 cLocks = 0;
3816 /* Start the object suspended */
3817 hr = CoRegisterClassObject(&CLSID_WineOOPTest, (IUnknown *)&TestOOP_ClassFactory,
3818 CLSCTX_LOCAL_SERVER, REGCLS_MULTIPLEUSE | REGCLS_SUSPENDED, &cookie);
3819 ok_ole_success(hr, CoRegisterClassObject);
3821 /* ... and CoGetClassObject does not find it and fails when it looks for the
3822 * class in the registry */
3823 hr = CoGetClassObject(&CLSID_WineOOPTest, CLSCTX_INPROC_SERVER,
3824 NULL, &IID_IClassFactory, (LPVOID*)&cf);
3825 todo_wine ok(hr == REGDB_E_CLASSNOTREG, "Got hr %#x.\n", hr);
3827 /* Resume the object suspended above ... */
3828 hr = CoResumeClassObjects();
3829 ok_ole_success(hr, CoResumeClassObjects);
3831 /* ... and now it should succeed */
3832 hr = CoGetClassObject(&CLSID_WineOOPTest, CLSCTX_INPROC_SERVER,
3833 NULL, &IID_IClassFactory, (LPVOID*)&cf);
3834 ok_ole_success(hr, CoGetClassObject);
3836 /* Now check the locking is working */
3837 /* NOTE: we are accessing the class directly, not through a proxy */
3839 ok_no_locks();
3841 hr = IClassFactory_LockServer(cf, TRUE);
3842 ok_ole_success(hr, IClassFactory_LockServer);
3844 ok_more_than_one_lock();
3846 IClassFactory_LockServer(cf, FALSE);
3847 ok_ole_success(hr, IClassFactory_LockServer);
3849 ok_no_locks();
3851 IClassFactory_Release(cf);
3853 /* wait for shutdown signal */
3854 ret = WaitForSingleObject(heventShutdown, 0);
3855 ok(ret != WAIT_TIMEOUT, "Server didn't shut down\n");
3857 /* try to connect again after SCM has suspended registered class objects */
3858 hr = CoGetClassObject(&CLSID_WineOOPTest, CLSCTX_INPROC_SERVER | CLSCTX_LOCAL_SERVER, NULL,
3859 &IID_IClassFactory, (LPVOID*)&cf);
3860 todo_wine ok(hr == CO_E_SERVER_STOPPING || hr == REGDB_E_CLASSNOTREG /* Win10 1709+ */, "Got hr %#x.\n", hr);
3862 hr = CoRevokeClassObject(cookie);
3863 ok_ole_success(hr, CoRevokeClassObject);
3865 CloseHandle(heventShutdown);
3867 process = create_target_process("-Embedding");
3868 ok(process != NULL, "couldn't start local server process, error was %d\n", GetLastError());
3870 ready_event = CreateEventA(NULL, FALSE, FALSE, "Wine COM Test Ready Event");
3871 ok( !WaitForSingleObject(ready_event, 10000), "wait timed out\n" );
3873 hr = CoCreateInstance(&CLSID_WineOOPTest, NULL, CLSCTX_LOCAL_SERVER, &IID_IPersist, (void **)&persist);
3874 ok_ole_success(hr, CoCreateInstance);
3876 IPersist_Release(persist);
3878 hr = CoCreateInstance(&CLSID_WineOOPTest, NULL, CLSCTX_LOCAL_SERVER, &IID_IPersist, (void **)&persist);
3879 ok(hr == REGDB_E_CLASSNOTREG, "Second CoCreateInstance on REGCLS_SINGLEUSE object should have failed\n");
3881 /* Re-register the class and try calling CoDisconnectObject from within a call to that object */
3882 repeat_event = CreateEventA(NULL, FALSE, FALSE, "Wine COM Test Repeat Event");
3883 SetEvent(repeat_event);
3884 CloseHandle(repeat_event);
3886 ok( !WaitForSingleObject(ready_event, 10000), "wait timed out\n" );
3887 CloseHandle(ready_event);
3889 hr = CoCreateInstance(&CLSID_WineOOPTest, NULL, CLSCTX_LOCAL_SERVER, &IID_IPersist, (void **)&persist);
3890 ok_ole_success(hr, CoCreateInstance);
3892 /* GetClassID will call CoDisconnectObject */
3893 IPersist_GetClassID(persist, &clsid);
3894 IPersist_Release(persist);
3896 quit_event = CreateEventA(NULL, FALSE, FALSE, "Wine COM Test Quit Event");
3897 SetEvent(quit_event);
3899 wait_child_process( process );
3900 CloseHandle(quit_event);
3901 CloseHandle(process);
3904 struct git_params
3906 DWORD cookie;
3907 IGlobalInterfaceTable *git;
3910 static DWORD CALLBACK get_global_interface_proc(LPVOID pv)
3912 HRESULT hr;
3913 struct git_params *params = pv;
3914 IClassFactory *cf;
3916 hr = IGlobalInterfaceTable_GetInterfaceFromGlobal(params->git, params->cookie, &IID_IClassFactory, (void **)&cf);
3917 ok(hr == CO_E_NOTINITIALIZED, "Got hr %#x.\n", hr);
3919 CoInitialize(NULL);
3921 hr = IGlobalInterfaceTable_GetInterfaceFromGlobal(params->git, params->cookie, &IID_IClassFactory, (void **)&cf);
3922 ok_ole_success(hr, IGlobalInterfaceTable_GetInterfaceFromGlobal);
3924 IClassFactory_Release(cf);
3926 CoUninitialize();
3928 return hr;
3931 static void test_globalinterfacetable(void)
3933 HRESULT hr;
3934 IGlobalInterfaceTable *git;
3935 DWORD cookie;
3936 HANDLE thread;
3937 DWORD tid;
3938 struct git_params params;
3939 DWORD ret;
3940 IUnknown *object;
3941 IClassFactory *cf;
3942 ULONG ref;
3944 cLocks = 0;
3946 hr = pDllGetClassObject(&CLSID_StdGlobalInterfaceTable, &IID_IClassFactory, (void**)&cf);
3947 ok(hr == S_OK, "got 0x%08x\n", hr);
3949 hr = IClassFactory_QueryInterface(cf, &IID_IGlobalInterfaceTable, (void**)&object);
3950 ok(hr == E_NOINTERFACE, "got 0x%08x\n", hr);
3952 IClassFactory_Release(cf);
3954 hr = CoCreateInstance(&CLSID_StdGlobalInterfaceTable, NULL, CLSCTX_INPROC_SERVER, &IID_IGlobalInterfaceTable, (void **)&git);
3955 ok_ole_success(hr, CoCreateInstance);
3957 ref = IGlobalInterfaceTable_AddRef(git);
3958 ok(ref == 1, "ref=%d\n", ref);
3959 ref = IGlobalInterfaceTable_AddRef(git);
3960 ok(ref == 1, "ref=%d\n", ref);
3962 ref = IGlobalInterfaceTable_Release(git);
3963 ok(ref == 1, "ref=%d\n", ref);
3964 ref = IGlobalInterfaceTable_Release(git);
3965 ok(ref == 1, "ref=%d\n", ref);
3967 hr = IGlobalInterfaceTable_RegisterInterfaceInGlobal(git, (IUnknown *)&Test_ClassFactory, &IID_IClassFactory, &cookie);
3968 ok_ole_success(hr, IGlobalInterfaceTable_RegisterInterfaceInGlobal);
3970 ok_more_than_one_lock();
3972 params.cookie = cookie;
3973 params.git = git;
3974 /* note: params is on stack so we MUST wait for get_global_interface_proc
3975 * to exit before we can return */
3976 thread = CreateThread(NULL, 0, get_global_interface_proc, &params, 0, &tid);
3978 ret = MsgWaitForMultipleObjects(1, &thread, FALSE, 10000, QS_ALLINPUT);
3979 while (ret == WAIT_OBJECT_0 + 1)
3981 MSG msg;
3982 while (PeekMessageA(&msg, NULL, 0, 0, PM_REMOVE))
3983 DispatchMessageA(&msg);
3984 ret = MsgWaitForMultipleObjects(1, &thread, FALSE, 10000, QS_ALLINPUT);
3987 CloseHandle(thread);
3989 /* test getting interface from global with different iid */
3990 hr = IGlobalInterfaceTable_GetInterfaceFromGlobal(git, cookie, &IID_IUnknown, (void **)&object);
3991 ok_ole_success(hr, IGlobalInterfaceTable_GetInterfaceFromGlobal);
3992 IUnknown_Release(object);
3994 /* test getting interface from global with same iid */
3995 hr = IGlobalInterfaceTable_GetInterfaceFromGlobal(git, cookie, &IID_IClassFactory, (void **)&object);
3996 ok_ole_success(hr, IGlobalInterfaceTable_GetInterfaceFromGlobal);
3997 IUnknown_Release(object);
3999 hr = IGlobalInterfaceTable_RevokeInterfaceFromGlobal(git, cookie);
4000 ok_ole_success(hr, IGlobalInterfaceTable_RevokeInterfaceFromGlobal);
4002 ok_no_locks();
4004 IGlobalInterfaceTable_Release(git);
4006 hr = CoGetClassObject(&CLSID_StdGlobalInterfaceTable, CLSCTX_INPROC_SERVER, NULL, &IID_IClassFactory, (void **)&cf);
4007 ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
4008 IClassFactory_Release(cf);
4011 static void test_manualresetevent(void)
4013 ISynchronizeHandle *sync_handle;
4014 ISynchronize *psync1, *psync2;
4015 IClassFactory *factory;
4016 IUnknown *punk;
4017 HANDLE handle;
4018 LONG ref;
4019 HRESULT hr;
4021 hr = pDllGetClassObject(&CLSID_ManualResetEvent, &IID_IClassFactory, (void **)&factory);
4022 ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
4023 IClassFactory_Release(factory);
4025 hr = CoGetClassObject(&CLSID_ManualResetEvent, CLSCTX_INPROC_SERVER, NULL, &IID_IClassFactory, (void **)&factory);
4026 ok(hr == S_OK, "Unexpected hr %#x.\n", hr);
4027 IClassFactory_Release(factory);
4029 hr = CoCreateInstance(&CLSID_ManualResetEvent, NULL, CLSCTX_INPROC_SERVER, &IID_IUnknown, (void**)&punk);
4030 ok(hr == S_OK, "Got 0x%08x\n", hr);
4031 ok(!!punk, "Got NULL.\n");
4032 IUnknown_Release(punk);
4034 hr = CoCreateInstance(&CLSID_ManualResetEvent, NULL, CLSCTX_INPROC_SERVER, &IID_ISynchronize, (void**)&psync1);
4035 ok(hr == S_OK, "Got 0x%08x\n", hr);
4036 ok(!!psync1, "Got NULL.\n");
4038 hr = ISynchronize_Wait(psync1, 0, 5);
4039 ok(hr == RPC_S_CALLPENDING, "Got 0x%08x\n", hr);
4041 hr = ISynchronize_Reset(psync1);
4042 ok(hr == S_OK, "Got 0x%08x\n", hr);
4043 hr = ISynchronize_Signal(psync1);
4044 ok(hr == S_OK, "Got 0x%08x\n", hr);
4045 hr = ISynchronize_Wait(psync1, 0, 5);
4046 ok(hr == S_OK, "Got 0x%08x\n", hr);
4047 hr = ISynchronize_Wait(psync1, 0, 5);
4048 ok(hr == S_OK, "Got 0x%08x\n", hr);
4049 hr = ISynchronize_Reset(psync1);
4050 ok(hr == S_OK, "Got 0x%08x\n", hr);
4051 hr = ISynchronize_Wait(psync1, 0, 5);
4052 ok(hr == RPC_S_CALLPENDING, "Got 0x%08x\n", hr);
4054 hr = CoCreateInstance(&CLSID_ManualResetEvent, NULL, CLSCTX_INPROC_SERVER, &IID_ISynchronize, (void**)&psync2);
4055 ok(hr == S_OK, "Got 0x%08x\n", hr);
4056 ok(!!psync2, "Got NULL.\n");
4057 ok(psync1 != psync2, "psync1 == psync2.\n");
4059 hr = ISynchronize_QueryInterface(psync2, &IID_ISynchronizeHandle, (void**)&sync_handle);
4060 ok(hr == S_OK, "QueryInterface(IID_ISynchronizeHandle) failed: %08x\n", hr);
4062 handle = NULL;
4063 hr = ISynchronizeHandle_GetHandle(sync_handle, &handle);
4064 ok(hr == S_OK, "GetHandle failed: %08x\n", hr);
4065 ok(handle != NULL && handle != INVALID_HANDLE_VALUE, "handle = %p\n", handle);
4067 ISynchronizeHandle_Release(sync_handle);
4069 hr = ISynchronize_Wait(psync2, 0, 5);
4070 ok(hr == RPC_S_CALLPENDING, "Got 0x%08x\n", hr);
4072 hr = ISynchronize_Reset(psync1);
4073 ok(hr == S_OK, "Got 0x%08x\n", hr);
4074 hr = ISynchronize_Reset(psync2);
4075 ok(hr == S_OK, "Got 0x%08x\n", hr);
4076 hr = ISynchronize_Signal(psync1);
4077 ok(hr == S_OK, "Got 0x%08x\n", hr);
4078 hr = ISynchronize_Wait(psync2, 0, 5);
4079 ok(hr == RPC_S_CALLPENDING, "Got 0x%08x\n", hr);
4081 ref = ISynchronize_AddRef(psync1);
4082 ok(ref == 2, "Got ref: %d\n", ref);
4083 ref = ISynchronize_AddRef(psync1);
4084 ok(ref == 3, "Got ref: %d\n", ref);
4085 ref = ISynchronize_Release(psync1);
4086 ok(ref == 2, "Got nonzero ref: %d\n", ref);
4087 ref = ISynchronize_Release(psync2);
4088 ok(!ref, "Got nonzero ref: %d\n", ref);
4089 ref = ISynchronize_Release(psync1);
4090 ok(ref == 1, "Got nonzero ref: %d\n", ref);
4091 ref = ISynchronize_Release(psync1);
4092 ok(!ref, "Got nonzero ref: %d\n", ref);
4095 static DWORD CALLBACK implicit_mta_unmarshal_proc(void *param)
4097 IStream *stream = param;
4098 IClassFactory *cf;
4099 IUnknown *proxy;
4100 HRESULT hr;
4102 IStream_Seek(stream, ullZero, STREAM_SEEK_SET, NULL);
4103 hr = CoUnmarshalInterface(stream, &IID_IClassFactory, (void **)&cf);
4104 ok_ole_success(hr, CoUnmarshalInterface);
4106 hr = IClassFactory_CreateInstance(cf, NULL, &IID_IUnknown, (void **)&proxy);
4107 ok_ole_success(hr, IClassFactory_CreateInstance);
4109 IUnknown_Release(proxy);
4111 /* But if we initialize an STA in this apartment, it becomes the wrong one. */
4112 CoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
4114 hr = IClassFactory_CreateInstance(cf, NULL, &IID_IUnknown, (void **)&proxy);
4115 ok(hr == RPC_E_WRONG_THREAD, "got %#x\n", hr);
4117 CoUninitialize();
4119 ok_more_than_one_lock();
4120 ok_non_zero_external_conn();
4122 IClassFactory_Release(cf);
4124 ok_no_locks();
4125 ok_zero_external_conn();
4126 ok_last_release_closes(TRUE);
4127 return 0;
4130 static DWORD CALLBACK implicit_mta_use_proc(void *param)
4132 IClassFactory *cf = param;
4133 IUnknown *proxy;
4134 HRESULT hr;
4136 hr = IClassFactory_CreateInstance(cf, NULL, &IID_IUnknown, (void **)&proxy);
4137 ok_ole_success(hr, IClassFactory_CreateInstance);
4139 IUnknown_Release(proxy);
4141 /* But if we initialize an STA in this apartment, it becomes the wrong one. */
4142 CoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
4144 hr = IClassFactory_CreateInstance(cf, NULL, &IID_IUnknown, (void **)&proxy);
4145 ok(hr == RPC_E_WRONG_THREAD, "got %#x\n", hr);
4147 CoUninitialize();
4148 return 0;
4151 struct implicit_mta_marshal_data
4153 IStream *stream;
4154 HANDLE start;
4155 HANDLE stop;
4158 static DWORD CALLBACK implicit_mta_marshal_proc(void *param)
4160 struct implicit_mta_marshal_data *data = param;
4161 HRESULT hr;
4163 hr = CoMarshalInterface(data->stream, &IID_IClassFactory,
4164 (IUnknown *)&Test_ClassFactory, MSHCTX_INPROC, NULL, MSHLFLAGS_NORMAL);
4165 ok_ole_success(hr, CoMarshalInterface);
4167 SetEvent(data->start);
4169 ok(!WaitForSingleObject(data->stop, 1000), "wait failed\n");
4170 return 0;
4173 static void test_implicit_mta(void)
4175 struct implicit_mta_marshal_data data;
4176 HANDLE host_thread, thread;
4177 IClassFactory *cf;
4178 IUnknown *proxy;
4179 IStream *stream;
4180 HRESULT hr;
4181 DWORD tid;
4183 cLocks = 0;
4184 external_connections = 0;
4186 CoInitializeEx(NULL, COINIT_MULTITHREADED);
4188 /* Firstly: we can unmarshal and use an object while in the implicit MTA. */
4189 hr = CreateStreamOnHGlobal(NULL, TRUE, &stream);
4190 ok_ole_success(hr, CreateStreamOnHGlobal);
4191 tid = start_host_object(stream, &IID_IClassFactory, (IUnknown *)&Test_ClassFactory, MSHLFLAGS_NORMAL, &host_thread);
4193 ok_more_than_one_lock();
4194 ok_non_zero_external_conn();
4196 thread = CreateThread(NULL, 0, implicit_mta_unmarshal_proc, stream, 0, NULL);
4197 ok(!WaitForSingleObject(thread, 1000), "wait failed\n");
4198 CloseHandle(thread);
4200 IStream_Release(stream);
4201 end_host_object(tid, host_thread);
4203 /* Secondly: we can unmarshal an object into the real MTA and then use it
4204 * from the implicit MTA. */
4205 hr = CreateStreamOnHGlobal(NULL, TRUE, &stream);
4206 ok_ole_success(hr, CreateStreamOnHGlobal);
4207 tid = start_host_object(stream, &IID_IClassFactory, (IUnknown *)&Test_ClassFactory, MSHLFLAGS_NORMAL, &host_thread);
4209 ok_more_than_one_lock();
4210 ok_non_zero_external_conn();
4212 IStream_Seek(stream, ullZero, STREAM_SEEK_SET, NULL);
4213 hr = CoUnmarshalInterface(stream, &IID_IClassFactory, (void **)&cf);
4214 ok_ole_success(hr, CoUnmarshalInterface);
4216 thread = CreateThread(NULL, 0, implicit_mta_use_proc, cf, 0, NULL);
4217 ok(!WaitForSingleObject(thread, 1000), "wait failed\n");
4218 CloseHandle(thread);
4220 IClassFactory_Release(cf);
4221 IStream_Release(stream);
4223 ok_no_locks();
4224 ok_non_zero_external_conn();
4225 ok_last_release_closes(TRUE);
4227 end_host_object(tid, host_thread);
4229 /* Thirdly: we can marshal an object from the implicit MTA and then
4230 * unmarshal it into the real one. */
4231 data.start = CreateEventA(NULL, FALSE, FALSE, NULL);
4232 data.stop = CreateEventA(NULL, FALSE, FALSE, NULL);
4234 hr = CreateStreamOnHGlobal(NULL, TRUE, &data.stream);
4235 ok_ole_success(hr, CreateStreamOnHGlobal);
4237 thread = CreateThread(NULL, 0, implicit_mta_marshal_proc, &data, 0, NULL);
4238 ok(!WaitForSingleObject(data.start, 1000), "wait failed\n");
4240 IStream_Seek(data.stream, ullZero, STREAM_SEEK_SET, NULL);
4241 hr = CoUnmarshalInterface(data.stream, &IID_IClassFactory, (void **)&cf);
4242 ok_ole_success(hr, CoUnmarshalInterface);
4244 hr = IClassFactory_CreateInstance(cf, NULL, &IID_IUnknown, (void **)&proxy);
4245 ok_ole_success(hr, IClassFactory_CreateInstance);
4247 IUnknown_Release(proxy);
4249 SetEvent(data.stop);
4250 ok(!WaitForSingleObject(thread, 1000), "wait failed\n");
4251 CloseHandle(thread);
4253 IStream_Release(data.stream);
4255 CoUninitialize();
4258 static HRESULT WINAPI TestChannelHook_QueryInterface(IChannelHook *iface, REFIID riid, void **ppv)
4260 if (IsEqualIID(riid, &IID_IUnknown) || IsEqualIID(riid, &IID_IChannelHook))
4262 *ppv = iface;
4263 IChannelHook_AddRef(iface);
4264 return S_OK;
4267 *ppv = NULL;
4268 return E_NOINTERFACE;
4271 static ULONG WINAPI TestChannelHook_AddRef(IChannelHook *iface)
4273 return 2;
4276 static ULONG WINAPI TestChannelHook_Release(IChannelHook *iface)
4278 return 1;
4281 static int method;
4282 static GUID causality;
4284 static void WINAPI TestChannelHook_ClientGetSize(
4285 IChannelHook *iface,
4286 REFGUID uExtent,
4287 REFIID riid,
4288 ULONG *pDataSize )
4290 SChannelHookCallInfo *info = (SChannelHookCallInfo *)riid;
4292 if (winetest_debug > 1) trace("IChannelHook::ClientGetSize(iid %s)\n", debugstr_guid(riid));
4294 if (info->cbSize == sizeof(*info))
4296 ok(info->dwServerPid == GetCurrentProcessId(), "dwServerPid was 0x%x instead of 0x%x\n", info->dwServerPid, GetCurrentProcessId());
4297 ok(info->iMethod == method, "iMethod was %d should be %d\n", info->iMethod, method);
4298 ok(!info->pObject, "pObject should be NULL\n");
4299 if (method == 3)
4300 causality = info->uCausality;
4301 else
4302 ok(IsEqualGUID(&info->uCausality, &causality), "causality wasn't correct\n");
4305 ok(IsEqualGUID(uExtent, &EXTENTID_WineTest), "uExtent wasn't correct\n");
4307 *pDataSize = 1;
4310 static void WINAPI TestChannelHook_ClientFillBuffer(
4311 IChannelHook *iface,
4312 REFGUID uExtent,
4313 REFIID riid,
4314 ULONG *pDataSize,
4315 void *pDataBuffer )
4317 SChannelHookCallInfo *info = (SChannelHookCallInfo *)riid;
4319 if (winetest_debug > 1) trace("IChannelHook::ClientFillBuffer()\n");
4321 if (info->cbSize == sizeof(*info))
4323 ok(info->dwServerPid == GetCurrentProcessId(), "dwServerPid was 0x%x instead of 0x%x\n", info->dwServerPid, GetCurrentProcessId());
4324 ok(info->iMethod == method, "iMethod was %d should be %d\n", info->iMethod, method);
4325 ok(!info->pObject, "pObject should be NULL\n");
4326 ok(IsEqualGUID(&info->uCausality, &causality), "causality wasn't correct\n");
4329 ok(IsEqualGUID(uExtent, &EXTENTID_WineTest), "uExtent wasn't correct\n");
4331 *(unsigned char *)pDataBuffer = 0xcc;
4332 *pDataSize = 1;
4335 static void WINAPI TestChannelHook_ClientNotify(
4336 IChannelHook *iface,
4337 REFGUID uExtent,
4338 REFIID riid,
4339 ULONG cbDataSize,
4340 void *pDataBuffer,
4341 DWORD lDataRep,
4342 HRESULT hrFault )
4344 SChannelHookCallInfo *info = (SChannelHookCallInfo *)riid;
4346 if (winetest_debug > 1) trace("IChannelHook::ClientNotify(hr %#x)\n", hrFault);
4348 if (info->cbSize == sizeof(*info))
4350 ok(info->dwServerPid == GetCurrentProcessId(), "dwServerPid was 0x%x instead of 0x%x\n", info->dwServerPid, GetCurrentProcessId());
4351 ok(info->iMethod == method, "iMethod was %d should be %d\n", info->iMethod, method);
4352 todo_wine {
4353 ok(info->pObject != NULL, "pObject shouldn't be NULL\n");
4355 ok(IsEqualGUID(&info->uCausality, &causality), "causality wasn't correct\n");
4358 ok(IsEqualGUID(uExtent, &EXTENTID_WineTest), "uExtent wasn't correct\n");
4361 static void WINAPI TestChannelHook_ServerNotify(
4362 IChannelHook *iface,
4363 REFGUID uExtent,
4364 REFIID riid,
4365 ULONG cbDataSize,
4366 void *pDataBuffer,
4367 DWORD lDataRep )
4369 SChannelHookCallInfo *info = (SChannelHookCallInfo *)riid;
4371 if (winetest_debug > 1) trace("IChannelHook::ServerNotify()\n");
4373 if (info->cbSize == sizeof(*info))
4375 ok(info->dwServerPid == GetCurrentProcessId(), "dwServerPid was 0x%x instead of 0x%x\n", info->dwServerPid, GetCurrentProcessId());
4376 ok(info->iMethod == method, "iMethod was %d should be %d\n", info->iMethod, method);
4377 ok(info->pObject != NULL, "pObject shouldn't be NULL\n");
4378 ok(IsEqualGUID(&info->uCausality, &causality), "causality wasn't correct\n");
4381 ok(cbDataSize == 1, "cbDataSize should have been 1 instead of %d\n", cbDataSize);
4382 ok(*(unsigned char *)pDataBuffer == 0xcc, "pDataBuffer should have contained 0xcc instead of 0x%x\n", *(unsigned char *)pDataBuffer);
4383 ok(IsEqualGUID(uExtent, &EXTENTID_WineTest), "uExtent wasn't correct\n");
4386 static void WINAPI TestChannelHook_ServerGetSize(
4387 IChannelHook *iface,
4388 REFGUID uExtent,
4389 REFIID riid,
4390 HRESULT hrFault,
4391 ULONG *pDataSize )
4393 SChannelHookCallInfo *info = (SChannelHookCallInfo *)riid;
4395 if (winetest_debug > 1) trace("IChannelHook::ServerGetSize(iid %s, hr %#x)\n", debugstr_guid(riid), hrFault);
4397 if (info->cbSize == sizeof(*info))
4399 ok(info->dwServerPid == GetCurrentProcessId(), "dwServerPid was 0x%x instead of 0x%x\n", info->dwServerPid, GetCurrentProcessId());
4400 ok(info->iMethod == method, "iMethod was %d should be %d\n", info->iMethod, method);
4401 ok(info->pObject != NULL, "pObject shouldn't be NULL\n");
4402 ok(IsEqualGUID(&info->uCausality, &causality), "causality wasn't correct\n");
4405 ok(IsEqualGUID(uExtent, &EXTENTID_WineTest), "uExtent wasn't correct\n");
4406 *pDataSize = 0;
4409 static void WINAPI TestChannelHook_ServerFillBuffer(
4410 IChannelHook *iface,
4411 REFGUID uExtent,
4412 REFIID riid,
4413 ULONG *pDataSize,
4414 void *pDataBuffer,
4415 HRESULT hrFault )
4417 ok(0, "TestChannelHook_ServerFillBuffer shouldn't be called\n");
4420 static const IChannelHookVtbl TestChannelHookVtbl =
4422 TestChannelHook_QueryInterface,
4423 TestChannelHook_AddRef,
4424 TestChannelHook_Release,
4425 TestChannelHook_ClientGetSize,
4426 TestChannelHook_ClientFillBuffer,
4427 TestChannelHook_ClientNotify,
4428 TestChannelHook_ServerNotify,
4429 TestChannelHook_ServerGetSize,
4430 TestChannelHook_ServerFillBuffer,
4433 static IChannelHook TestChannelHook = { &TestChannelHookVtbl };
4435 static void test_channel_hook(void)
4437 IClassFactory *cf = NULL;
4438 DWORD tid;
4439 IUnknown *proxy = NULL;
4440 HANDLE thread;
4441 HRESULT hr;
4443 struct host_object_data object_data = { NULL, &IID_IClassFactory, (IUnknown*)&Test_ClassFactory,
4444 MSHLFLAGS_NORMAL, &MessageFilter };
4446 hr = CoRegisterChannelHook(&EXTENTID_WineTest, &TestChannelHook);
4447 ok_ole_success(hr, CoRegisterChannelHook);
4449 hr = CoRegisterMessageFilter(&MessageFilter, NULL);
4450 ok_ole_success(hr, CoRegisterMessageFilter);
4452 cLocks = 0;
4454 hr = CreateStreamOnHGlobal(NULL, TRUE, &object_data.stream);
4455 ok_ole_success(hr, CreateStreamOnHGlobal);
4456 tid = start_host_object2(&object_data, &thread);
4458 ok_more_than_one_lock();
4460 IStream_Seek(object_data.stream, ullZero, STREAM_SEEK_SET, NULL);
4461 hr = CoUnmarshalInterface(object_data.stream, &IID_IClassFactory, (void **)&cf);
4462 ok_ole_success(hr, CoUnmarshalInterface);
4463 IStream_Release(object_data.stream);
4465 ok_more_than_one_lock();
4467 method = 3;
4468 hr = IClassFactory_CreateInstance(cf, NULL, &IID_IUnknown, (LPVOID*)&proxy);
4469 ok_ole_success(hr, IClassFactory_CreateInstance);
4471 method = 5;
4472 IUnknown_Release(proxy);
4474 IClassFactory_Release(cf);
4476 ok_no_locks();
4478 end_host_object(tid, thread);
4480 hr = CoRegisterMessageFilter(NULL, NULL);
4481 ok_ole_success(hr, CoRegisterMessageFilter);
4484 START_TEST(marshal)
4486 HMODULE hOle32 = GetModuleHandleA("ole32");
4487 int argc;
4488 char **argv;
4490 pDllGetClassObject = (void*)GetProcAddress(hOle32, "DllGetClassObject");
4492 argc = winetest_get_mainargs( &argv );
4493 if (argc > 2 && (!strcmp(argv[2], "-Embedding")))
4495 CoInitializeEx(NULL, COINIT_MULTITHREADED);
4496 test_register_local_server();
4497 CoUninitialize();
4499 return;
4502 register_test_window();
4504 test_cocreateinstance_proxy();
4505 test_implicit_mta();
4507 CoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
4509 /* FIXME: test CoCreateInstanceEx */
4511 /* lifecycle management and marshaling tests */
4514 test_no_marshaler();
4515 test_normal_marshal_and_release();
4516 test_normal_marshal_and_unmarshal();
4517 test_marshal_and_unmarshal_invalid();
4518 test_same_apartment_unmarshal_failure();
4519 test_interthread_marshal_and_unmarshal();
4520 test_proxy_marshal_and_unmarshal();
4521 test_proxy_marshal_and_unmarshal2();
4522 test_proxy_marshal_and_unmarshal_weak();
4523 test_proxy_marshal_and_unmarshal_strong();
4524 test_marshal_stub_apartment_shutdown();
4525 test_marshal_proxy_apartment_shutdown();
4526 test_marshal_proxy_mta_apartment_shutdown();
4527 test_no_couninitialize_server();
4528 test_no_couninitialize_client();
4529 test_tableweak_marshal_and_unmarshal_twice();
4530 test_tableweak_marshal_releasedata1();
4531 test_tableweak_marshal_releasedata2();
4532 test_tableweak_and_normal_marshal_and_unmarshal();
4533 test_tableweak_and_normal_marshal_and_releasedata();
4534 test_two_tableweak_marshal_and_releasedata();
4535 test_tablestrong_marshal_and_unmarshal_twice();
4536 test_lock_object_external();
4537 test_disconnect_stub();
4538 test_normal_marshal_and_unmarshal_twice();
4540 with_external_conn = !with_external_conn;
4541 } while (with_external_conn);
4543 test_marshal_channel_buffer();
4544 test_StdMarshal_custom_marshaling();
4545 test_DfMarshal_custom_marshaling();
4546 test_CoGetStandardMarshal();
4547 test_hresult_marshaling();
4548 test_proxy_used_in_wrong_thread();
4549 test_message_filter();
4550 test_bad_marshal_stream();
4551 test_proxy_interfaces();
4552 test_stubbuffer(&IID_IClassFactory);
4553 test_proxybuffer(&IID_IClassFactory);
4554 test_message_reentrancy();
4555 test_call_from_message();
4556 test_WM_QUIT_handling();
4557 test_freethreadedmarshaler();
4558 test_inproc_handler();
4559 test_handler_marshaling();
4560 test_client_security();
4562 test_local_server();
4564 test_globalinterfacetable();
4565 test_manualresetevent();
4566 test_crash_couninitialize();
4568 /* must be last test as channel hooks can't be unregistered */
4569 test_channel_hook();
4571 CoUninitialize();