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