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
33 #include "wine/test.h"
35 /* functions that are not present on all versions of Windows */
36 HRESULT (WINAPI * pCoInitializeEx)(LPVOID lpReserved, DWORD dwCoInit);
38 /* helper macros to make tests a bit leaner */
39 #define ok_more_than_one_lock() ok(cLocks > 0, "Number of locks should be > 0, but actually is %d\n", cLocks)
40 #define ok_no_locks() ok(cLocks == 0, "Number of locks should be 0, but actually is %d\n", cLocks)
41 #define ok_ole_success(hr, func) ok(hr == S_OK, #func " failed with error 0x%08x\n", hr)
43 static const IID IID_IWineTest =
48 {0xa1, 0xa2, 0x5d, 0x5a, 0x36, 0x54, 0xd3, 0xbd}
49 }; /* 5201163f-8164-4fd0-a1a2-5d5a3654d3bd */
51 static const IID IID_IRemUnknown =
56 {0xc0,0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46}
59 #define EXTENTID_WineTest IID_IWineTest
60 #define CLSID_WineTest IID_IWineTest
62 static const CLSID CLSID_WineOOPTest =
67 {0xa1, 0xa2, 0x5d, 0x5a, 0x36, 0x54, 0xd3, 0xbd}
68 }; /* 5201163f-8164-4fd0-a1a2-5d5a3654d3bd */
70 static void test_cocreateinstance_proxy(void)
76 pCoInitializeEx(NULL, COINIT_MULTITHREADED);
78 hr = CoCreateInstance(&CLSID_ShellDesktop, NULL, CLSCTX_INPROC, &IID_IUnknown, (void **)&pProxy);
79 ok_ole_success(hr, CoCreateInstance);
80 hr = IUnknown_QueryInterface(pProxy, &IID_IMultiQI, (void **)&pMQI);
81 ok(hr == S_OK, "created object is not a proxy, so was created in the wrong apartment\n");
83 IMultiQI_Release(pMQI);
84 IUnknown_Release(pProxy);
89 static const LARGE_INTEGER ullZero;
92 static void LockModule(void)
94 InterlockedIncrement(&cLocks);
97 static void UnlockModule(void)
99 InterlockedDecrement(&cLocks);
103 static HRESULT WINAPI Test_IUnknown_QueryInterface(
108 if (ppvObj == NULL) return E_POINTER;
110 if (IsEqualGUID(riid, &IID_IUnknown))
112 *ppvObj = (LPVOID)iface;
113 IUnknown_AddRef(iface);
118 return E_NOINTERFACE;
121 static ULONG WINAPI Test_IUnknown_AddRef(LPUNKNOWN iface)
124 return 2; /* non-heap-based object */
127 static ULONG WINAPI Test_IUnknown_Release(LPUNKNOWN iface)
130 return 1; /* non-heap-based object */
133 static const IUnknownVtbl TestUnknown_Vtbl =
135 Test_IUnknown_QueryInterface,
136 Test_IUnknown_AddRef,
137 Test_IUnknown_Release,
140 static IUnknown Test_Unknown = { &TestUnknown_Vtbl };
143 static HRESULT WINAPI Test_IClassFactory_QueryInterface(
144 LPCLASSFACTORY iface,
148 if (ppvObj == NULL) return E_POINTER;
150 if (IsEqualGUID(riid, &IID_IUnknown) ||
151 IsEqualGUID(riid, &IID_IClassFactory) ||
152 /* the only other interface Wine is currently able to marshal (for testing two proxies) */
153 IsEqualGUID(riid, &IID_IRemUnknown))
155 *ppvObj = (LPVOID)iface;
156 IClassFactory_AddRef(iface);
161 return E_NOINTERFACE;
164 static ULONG WINAPI Test_IClassFactory_AddRef(LPCLASSFACTORY iface)
167 return 2; /* non-heap-based object */
170 static ULONG WINAPI Test_IClassFactory_Release(LPCLASSFACTORY iface)
173 return 1; /* non-heap-based object */
176 static HRESULT WINAPI Test_IClassFactory_CreateInstance(
177 LPCLASSFACTORY iface,
182 if (pUnkOuter) return CLASS_E_NOAGGREGATION;
183 return IUnknown_QueryInterface((IUnknown*)&Test_Unknown, riid, ppvObj);
186 static HRESULT WINAPI Test_IClassFactory_LockServer(
187 LPCLASSFACTORY iface,
193 static const IClassFactoryVtbl TestClassFactory_Vtbl =
195 Test_IClassFactory_QueryInterface,
196 Test_IClassFactory_AddRef,
197 Test_IClassFactory_Release,
198 Test_IClassFactory_CreateInstance,
199 Test_IClassFactory_LockServer
202 static IClassFactory Test_ClassFactory = { &TestClassFactory_Vtbl };
204 #define RELEASEMARSHALDATA WM_USER
206 struct host_object_data
211 MSHLFLAGS marshal_flags;
212 HANDLE marshal_event;
213 IMessageFilter *filter;
216 static DWORD CALLBACK host_object_proc(LPVOID p)
218 struct host_object_data *data = (struct host_object_data *)p;
222 pCoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
226 IMessageFilter * prev_filter = NULL;
227 hr = CoRegisterMessageFilter(data->filter, &prev_filter);
228 if (prev_filter) IMessageFilter_Release(prev_filter);
229 ok_ole_success(hr, CoRegisterMessageFilter);
232 hr = CoMarshalInterface(data->stream, &data->iid, data->object, MSHCTX_INPROC, NULL, data->marshal_flags);
233 ok_ole_success(hr, CoMarshalInterface);
235 /* force the message queue to be created before signaling parent thread */
236 PeekMessage(&msg, NULL, WM_USER, WM_USER, PM_NOREMOVE);
238 SetEvent(data->marshal_event);
240 while (GetMessage(&msg, NULL, 0, 0))
242 if (msg.hwnd == NULL && msg.message == RELEASEMARSHALDATA)
244 trace("releasing marshal data\n");
245 CoReleaseMarshalData(data->stream);
246 SetEvent((HANDLE)msg.lParam);
249 DispatchMessage(&msg);
252 HeapFree(GetProcessHeap(), 0, data);
259 static DWORD start_host_object2(IStream *stream, REFIID riid, IUnknown *object, MSHLFLAGS marshal_flags, IMessageFilter *filter, HANDLE *thread)
262 HANDLE marshal_event = CreateEvent(NULL, FALSE, FALSE, NULL);
263 struct host_object_data *data = HeapAlloc(GetProcessHeap(), 0, sizeof(*data));
265 data->stream = stream;
267 data->object = object;
268 data->marshal_flags = marshal_flags;
269 data->marshal_event = marshal_event;
270 data->filter = filter;
272 *thread = CreateThread(NULL, 0, host_object_proc, data, 0, &tid);
274 /* wait for marshaling to complete before returning */
275 WaitForSingleObject(marshal_event, INFINITE);
276 CloseHandle(marshal_event);
281 static DWORD start_host_object(IStream *stream, REFIID riid, IUnknown *object, MSHLFLAGS marshal_flags, HANDLE *thread)
283 return start_host_object2(stream, riid, object, marshal_flags, NULL, thread);
286 /* asks thread to release the marshal data because it has to be done by the
287 * same thread that marshaled the interface in the first place. */
288 static void release_host_object(DWORD tid)
290 HANDLE event = CreateEvent(NULL, FALSE, FALSE, NULL);
291 PostThreadMessage(tid, RELEASEMARSHALDATA, 0, (LPARAM)event);
292 WaitForSingleObject(event, INFINITE);
296 static void end_host_object(DWORD tid, HANDLE thread)
298 BOOL ret = PostThreadMessage(tid, WM_QUIT, 0, 0);
299 ok(ret, "PostThreadMessage failed with error %d\n", GetLastError());
300 /* be careful of races - don't return until hosting thread has terminated */
301 WaitForSingleObject(thread, INFINITE);
305 /* tests failure case of interface not having a marshaler specified in the
307 static void test_no_marshaler(void)
312 hr = CreateStreamOnHGlobal(NULL, TRUE, &pStream);
313 ok_ole_success(hr, CreateStreamOnHGlobal);
314 hr = CoMarshalInterface(pStream, &IID_IWineTest, (IUnknown*)&Test_ClassFactory, MSHCTX_INPROC, NULL, MSHLFLAGS_NORMAL);
315 ok(hr == E_NOINTERFACE, "CoMarshalInterface should have returned E_NOINTERFACE instead of 0x%08x\n", hr);
317 IStream_Release(pStream);
320 /* tests normal marshal and then release without unmarshaling */
321 static void test_normal_marshal_and_release(void)
324 IStream *pStream = NULL;
328 hr = CreateStreamOnHGlobal(NULL, TRUE, &pStream);
329 ok_ole_success(hr, CreateStreamOnHGlobal);
330 hr = CoMarshalInterface(pStream, &IID_IClassFactory, (IUnknown*)&Test_ClassFactory, MSHCTX_INPROC, NULL, MSHLFLAGS_NORMAL);
331 ok_ole_success(hr, CoMarshalInterface);
333 ok_more_than_one_lock();
335 IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
336 hr = CoReleaseMarshalData(pStream);
337 ok_ole_success(hr, CoReleaseMarshalData);
338 IStream_Release(pStream);
343 /* tests success case of a same-thread marshal and unmarshal */
344 static void test_normal_marshal_and_unmarshal(void)
347 IStream *pStream = NULL;
348 IUnknown *pProxy = NULL;
352 hr = CreateStreamOnHGlobal(NULL, TRUE, &pStream);
353 ok_ole_success(hr, CreateStreamOnHGlobal);
354 hr = CoMarshalInterface(pStream, &IID_IClassFactory, (IUnknown*)&Test_ClassFactory, MSHCTX_INPROC, NULL, MSHLFLAGS_NORMAL);
355 ok_ole_success(hr, CoMarshalInterface);
357 ok_more_than_one_lock();
359 IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
360 hr = CoUnmarshalInterface(pStream, &IID_IClassFactory, (void **)&pProxy);
361 ok_ole_success(hr, CoUnmarshalInterface);
362 IStream_Release(pStream);
364 ok_more_than_one_lock();
366 IUnknown_Release(pProxy);
371 /* tests failure case of unmarshaling a freed object */
372 static void test_marshal_and_unmarshal_invalid(void)
375 IStream *pStream = NULL;
376 IClassFactory *pProxy = NULL;
383 hr = CreateStreamOnHGlobal(NULL, TRUE, &pStream);
384 ok_ole_success(hr, CreateStreamOnHGlobal);
385 tid = start_host_object(pStream, &IID_IClassFactory, (IUnknown*)&Test_ClassFactory, MSHLFLAGS_NORMAL, &thread);
387 ok_more_than_one_lock();
389 IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
390 hr = CoReleaseMarshalData(pStream);
391 ok_ole_success(hr, CoReleaseMarshalData);
395 IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
396 hr = CoUnmarshalInterface(pStream, &IID_IClassFactory, (void **)&pProxy);
397 todo_wine { ok_ole_success(hr, CoUnmarshalInterface); }
403 hr = IClassFactory_CreateInstance(pProxy, NULL, &IID_IUnknown, &dummy);
404 ok(hr == RPC_E_DISCONNECTED, "Remote call should have returned RPC_E_DISCONNECTED, instead of 0x%08x\n", hr);
406 IClassFactory_Release(pProxy);
409 IStream_Release(pStream);
411 end_host_object(tid, thread);
414 static void test_same_apartment_unmarshal_failure(void)
419 static const LARGE_INTEGER llZero;
423 hr = CreateStreamOnHGlobal(NULL, TRUE, &pStream);
424 ok_ole_success(hr, CreateStreamOnHGlobal);
426 hr = CoMarshalInterface(pStream, &IID_IUnknown, (IUnknown *)&Test_ClassFactory, MSHCTX_INPROC, NULL, MSHLFLAGS_NORMAL);
427 ok_ole_success(hr, CoMarshalInterface);
429 ok_more_than_one_lock();
431 hr = IStream_Seek(pStream, llZero, STREAM_SEEK_SET, NULL);
432 ok_ole_success(hr, IStream_Seek);
434 hr = CoUnmarshalInterface(pStream, &IID_IParseDisplayName, (void **)&pProxy);
435 ok(hr == E_NOINTERFACE, "CoUnmarshalInterface should have returned E_NOINTERFACE instead of 0x%08x\n", hr);
440 /* tests success case of an interthread marshal */
441 static void test_interthread_marshal_and_unmarshal(void)
444 IStream *pStream = NULL;
445 IUnknown *pProxy = NULL;
451 hr = CreateStreamOnHGlobal(NULL, TRUE, &pStream);
452 ok_ole_success(hr, CreateStreamOnHGlobal);
453 tid = start_host_object(pStream, &IID_IClassFactory, (IUnknown*)&Test_ClassFactory, MSHLFLAGS_NORMAL, &thread);
455 ok_more_than_one_lock();
457 IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
458 hr = CoUnmarshalInterface(pStream, &IID_IClassFactory, (void **)&pProxy);
459 ok_ole_success(hr, CoUnmarshalInterface);
460 IStream_Release(pStream);
462 ok_more_than_one_lock();
464 IUnknown_Release(pProxy);
468 end_host_object(tid, thread);
471 /* the number of external references that Wine's proxy manager normally gives
472 * out, so we can test the border case of running out of references */
473 #define NORMALEXTREFS 5
475 /* tests success case of an interthread marshal and then marshaling the proxy */
476 static void test_proxy_marshal_and_unmarshal(void)
479 IStream *pStream = NULL;
480 IUnknown *pProxy = NULL;
481 IUnknown *pProxy2 = NULL;
488 hr = CreateStreamOnHGlobal(NULL, TRUE, &pStream);
489 ok_ole_success(hr, CreateStreamOnHGlobal);
490 tid = start_host_object(pStream, &IID_IClassFactory, (IUnknown*)&Test_ClassFactory, MSHLFLAGS_NORMAL, &thread);
492 ok_more_than_one_lock();
494 IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
495 hr = CoUnmarshalInterface(pStream, &IID_IClassFactory, (void **)&pProxy);
496 ok_ole_success(hr, CoUnmarshalInterface);
498 ok_more_than_one_lock();
500 IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
501 /* marshal the proxy */
502 hr = CoMarshalInterface(pStream, &IID_IClassFactory, pProxy, MSHCTX_INPROC, NULL, MSHLFLAGS_NORMAL);
503 ok_ole_success(hr, CoMarshalInterface);
505 ok_more_than_one_lock();
507 /* marshal 5 more times to exhaust the normal external references of 5 */
508 for (i = 0; i < NORMALEXTREFS; i++)
510 hr = CoMarshalInterface(pStream, &IID_IClassFactory, pProxy, MSHCTX_INPROC, NULL, MSHLFLAGS_NORMAL);
511 ok_ole_success(hr, CoMarshalInterface);
514 ok_more_than_one_lock();
516 /* release the original proxy to test that we successfully keep the
517 * original object alive */
518 IUnknown_Release(pProxy);
520 IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
521 hr = CoUnmarshalInterface(pStream, &IID_IClassFactory, (void **)&pProxy2);
522 ok_ole_success(hr, CoUnmarshalInterface);
524 ok_more_than_one_lock();
526 /* now the proxies should be as follows:
527 * pProxy2 -> &Test_ClassFactory
528 * they should NOT be as follows:
529 * pProxy -> &Test_ClassFactory
531 * the above can only really be tested by looking in +ole traces
534 IUnknown_Release(pProxy2);
536 /* unmarshal all of the proxies to check that the object stub still exists */
537 for (i = 0; i < NORMALEXTREFS; i++)
539 hr = CoUnmarshalInterface(pStream, &IID_IClassFactory, (void **)&pProxy2);
540 ok_ole_success(hr, CoUnmarshalInterface);
542 IUnknown_Release(pProxy2);
547 IStream_Release(pStream);
549 end_host_object(tid, thread);
552 /* tests success case of an interthread marshal and then marshaling the proxy
553 * using an iid that hasn't previously been unmarshaled */
554 static void test_proxy_marshal_and_unmarshal2(void)
557 IStream *pStream = NULL;
558 IUnknown *pProxy = NULL;
559 IUnknown *pProxy2 = NULL;
565 hr = CreateStreamOnHGlobal(NULL, TRUE, &pStream);
566 ok_ole_success(hr, CreateStreamOnHGlobal);
567 tid = start_host_object(pStream, &IID_IUnknown, (IUnknown*)&Test_ClassFactory, MSHLFLAGS_NORMAL, &thread);
569 ok_more_than_one_lock();
571 IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
572 hr = CoUnmarshalInterface(pStream, &IID_IUnknown, (void **)&pProxy);
573 ok_ole_success(hr, CoUnmarshalInterface);
575 ok_more_than_one_lock();
577 IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
578 /* marshal the proxy */
579 hr = CoMarshalInterface(pStream, &IID_IClassFactory, pProxy, MSHCTX_INPROC, NULL, MSHLFLAGS_NORMAL);
580 ok_ole_success(hr, CoMarshalInterface);
582 ok_more_than_one_lock();
584 IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
585 /* unmarshal the second proxy to the object */
586 hr = CoUnmarshalInterface(pStream, &IID_IClassFactory, (void **)&pProxy2);
587 ok_ole_success(hr, CoUnmarshalInterface);
588 IStream_Release(pStream);
590 /* now the proxies should be as follows:
591 * pProxy -> &Test_ClassFactory
592 * pProxy2 -> &Test_ClassFactory
593 * they should NOT be as follows:
594 * pProxy -> &Test_ClassFactory
596 * the above can only really be tested by looking in +ole traces
599 ok_more_than_one_lock();
601 IUnknown_Release(pProxy);
603 ok_more_than_one_lock();
605 IUnknown_Release(pProxy2);
609 end_host_object(tid, thread);
612 /* tests that stubs are released when the containing apartment is destroyed */
613 static void test_marshal_stub_apartment_shutdown(void)
616 IStream *pStream = NULL;
617 IUnknown *pProxy = NULL;
623 hr = CreateStreamOnHGlobal(NULL, TRUE, &pStream);
624 ok_ole_success(hr, CreateStreamOnHGlobal);
625 tid = start_host_object(pStream, &IID_IClassFactory, (IUnknown*)&Test_ClassFactory, MSHLFLAGS_NORMAL, &thread);
627 ok_more_than_one_lock();
629 IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
630 hr = CoUnmarshalInterface(pStream, &IID_IClassFactory, (void **)&pProxy);
631 ok_ole_success(hr, CoUnmarshalInterface);
632 IStream_Release(pStream);
634 ok_more_than_one_lock();
636 end_host_object(tid, thread);
640 IUnknown_Release(pProxy);
645 /* tests that proxies are released when the containing apartment is destroyed */
646 static void test_marshal_proxy_apartment_shutdown(void)
649 IStream *pStream = NULL;
650 IUnknown *pProxy = NULL;
656 hr = CreateStreamOnHGlobal(NULL, TRUE, &pStream);
657 ok_ole_success(hr, CreateStreamOnHGlobal);
658 tid = start_host_object(pStream, &IID_IClassFactory, (IUnknown*)&Test_ClassFactory, MSHLFLAGS_NORMAL, &thread);
660 ok_more_than_one_lock();
662 IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
663 hr = CoUnmarshalInterface(pStream, &IID_IClassFactory, (void **)&pProxy);
664 ok_ole_success(hr, CoUnmarshalInterface);
665 IStream_Release(pStream);
667 ok_more_than_one_lock();
673 IUnknown_Release(pProxy);
677 end_host_object(tid, thread);
679 pCoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
682 /* tests that proxies are released when the containing mta apartment is destroyed */
683 static void test_marshal_proxy_mta_apartment_shutdown(void)
686 IStream *pStream = NULL;
687 IUnknown *pProxy = NULL;
692 pCoInitializeEx(NULL, COINIT_MULTITHREADED);
696 hr = CreateStreamOnHGlobal(NULL, TRUE, &pStream);
697 ok_ole_success(hr, CreateStreamOnHGlobal);
698 tid = start_host_object(pStream, &IID_IClassFactory, (IUnknown*)&Test_ClassFactory, MSHLFLAGS_NORMAL, &thread);
700 ok_more_than_one_lock();
702 IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
703 hr = CoUnmarshalInterface(pStream, &IID_IClassFactory, (void **)&pProxy);
704 ok_ole_success(hr, CoUnmarshalInterface);
705 IStream_Release(pStream);
707 ok_more_than_one_lock();
713 IUnknown_Release(pProxy);
717 end_host_object(tid, thread);
719 pCoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
725 HANDLE marshal_event;
726 HANDLE unmarshal_event;
729 /* helper for test_no_couninitialize_server */
730 static DWORD CALLBACK no_couninitialize_server_proc(LPVOID p)
732 struct ncu_params *ncu_params = (struct ncu_params *)p;
735 pCoInitializeEx(NULL, COINIT_MULTITHREADED);
737 hr = CoMarshalInterface(ncu_params->stream, &IID_IClassFactory, (IUnknown*)&Test_ClassFactory, MSHCTX_INPROC, NULL, MSHLFLAGS_NORMAL);
738 ok_ole_success(hr, CoMarshalInterface);
740 SetEvent(ncu_params->marshal_event);
742 WaitForSingleObject(ncu_params->unmarshal_event, INFINITE);
744 /* die without calling CoUninitialize */
749 /* tests apartment that an apartment with a stub is released without deadlock
750 * if the owning thread exits */
751 static void test_no_couninitialize_server(void)
754 IStream *pStream = NULL;
755 IUnknown *pProxy = NULL;
758 struct ncu_params ncu_params;
762 ncu_params.marshal_event = CreateEvent(NULL, TRUE, FALSE, NULL);
763 ncu_params.unmarshal_event = CreateEvent(NULL, TRUE, FALSE, NULL);
765 hr = CreateStreamOnHGlobal(NULL, TRUE, &pStream);
766 ok_ole_success(hr, CreateStreamOnHGlobal);
767 ncu_params.stream = pStream;
769 thread = CreateThread(NULL, 0, no_couninitialize_server_proc, &ncu_params, 0, &tid);
771 WaitForSingleObject(ncu_params.marshal_event, INFINITE);
772 ok_more_than_one_lock();
774 IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
775 hr = CoUnmarshalInterface(pStream, &IID_IClassFactory, (void **)&pProxy);
776 ok_ole_success(hr, CoUnmarshalInterface);
777 IStream_Release(pStream);
779 ok_more_than_one_lock();
781 SetEvent(ncu_params.unmarshal_event);
782 WaitForSingleObject(thread, INFINITE);
787 CloseHandle(ncu_params.marshal_event);
788 CloseHandle(ncu_params.unmarshal_event);
790 IUnknown_Release(pProxy);
795 /* STA -> STA call during DLL_THREAD_DETACH */
796 static DWORD CALLBACK no_couninitialize_client_proc(LPVOID p)
798 struct ncu_params *ncu_params = (struct ncu_params *)p;
800 IUnknown *pProxy = NULL;
802 pCoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
804 hr = CoUnmarshalInterface(ncu_params->stream, &IID_IClassFactory, (void **)&pProxy);
805 ok_ole_success(hr, CoUnmarshalInterface);
806 IStream_Release(ncu_params->stream);
808 ok_more_than_one_lock();
810 /* die without calling CoUninitialize */
815 /* tests STA -> STA call during DLL_THREAD_DETACH doesn't deadlock */
816 static void test_no_couninitialize_client(void)
819 IStream *pStream = NULL;
824 struct ncu_params ncu_params;
828 hr = CreateStreamOnHGlobal(NULL, TRUE, &pStream);
829 ok_ole_success(hr, CreateStreamOnHGlobal);
830 ncu_params.stream = pStream;
832 /* NOTE: assumes start_host_object uses an STA to host the object, as MTAs
833 * always deadlock when called from within DllMain */
834 host_tid = start_host_object(pStream, &IID_IClassFactory, (IUnknown *)&Test_ClassFactory, MSHLFLAGS_NORMAL, &host_thread);
835 IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
837 ok_more_than_one_lock();
839 thread = CreateThread(NULL, 0, no_couninitialize_client_proc, &ncu_params, 0, &tid);
841 WaitForSingleObject(thread, INFINITE);
846 end_host_object(host_tid, host_thread);
849 /* tests success case of a same-thread table-weak marshal, unmarshal, unmarshal */
850 static void test_tableweak_marshal_and_unmarshal_twice(void)
853 IStream *pStream = NULL;
854 IUnknown *pProxy1 = NULL;
855 IUnknown *pProxy2 = NULL;
861 hr = CreateStreamOnHGlobal(NULL, TRUE, &pStream);
862 ok_ole_success(hr, CreateStreamOnHGlobal);
863 tid = start_host_object(pStream, &IID_IClassFactory, (IUnknown*)&Test_ClassFactory, MSHLFLAGS_TABLEWEAK, &thread);
865 ok_more_than_one_lock();
867 IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
868 hr = CoUnmarshalInterface(pStream, &IID_IClassFactory, (void **)&pProxy1);
869 ok_ole_success(hr, CoUnmarshalInterface);
871 ok_more_than_one_lock();
873 IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
874 hr = CoUnmarshalInterface(pStream, &IID_IClassFactory, (void **)&pProxy2);
875 IStream_Release(pStream);
876 ok_ole_success(hr, CoUnmarshalInterface);
878 ok_more_than_one_lock();
880 IUnknown_Release(pProxy1);
881 IUnknown_Release(pProxy2);
883 /* this line is shows the difference between weak and strong table marshaling:
884 * weak has cLocks == 0
885 * strong has cLocks > 0 */
888 end_host_object(tid, thread);
891 /* tests releasing after unmarshaling one object */
892 static void test_tableweak_marshal_releasedata1(void)
895 IStream *pStream = NULL;
896 IUnknown *pProxy1 = NULL;
897 IUnknown *pProxy2 = NULL;
903 hr = CreateStreamOnHGlobal(NULL, TRUE, &pStream);
904 ok_ole_success(hr, CreateStreamOnHGlobal);
905 tid = start_host_object(pStream, &IID_IClassFactory, (IUnknown*)&Test_ClassFactory, MSHLFLAGS_TABLEWEAK, &thread);
907 ok_more_than_one_lock();
909 IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
910 hr = CoUnmarshalInterface(pStream, &IID_IClassFactory, (void **)&pProxy1);
911 ok_ole_success(hr, CoUnmarshalInterface);
913 ok_more_than_one_lock();
915 /* release the remaining reference on the object by calling
916 * CoReleaseMarshalData in the hosting thread */
917 IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
918 release_host_object(tid);
920 ok_more_than_one_lock();
922 IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
923 hr = CoUnmarshalInterface(pStream, &IID_IClassFactory, (void **)&pProxy2);
924 ok_ole_success(hr, CoUnmarshalInterface);
925 IStream_Release(pStream);
927 ok_more_than_one_lock();
929 IUnknown_Release(pProxy1);
931 IUnknown_Release(pProxy2);
933 /* this line is shows the difference between weak and strong table marshaling:
934 * weak has cLocks == 0
935 * strong has cLocks > 0 */
938 end_host_object(tid, thread);
941 /* tests releasing after unmarshaling one object */
942 static void test_tableweak_marshal_releasedata2(void)
945 IStream *pStream = NULL;
946 IUnknown *pProxy = NULL;
952 hr = CreateStreamOnHGlobal(NULL, TRUE, &pStream);
953 ok_ole_success(hr, CreateStreamOnHGlobal);
954 tid = start_host_object(pStream, &IID_IClassFactory, (IUnknown*)&Test_ClassFactory, MSHLFLAGS_TABLEWEAK, &thread);
956 ok_more_than_one_lock();
958 /* release the remaining reference on the object by calling
959 * CoReleaseMarshalData in the hosting thread */
960 IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
961 release_host_object(tid);
965 IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
966 hr = CoUnmarshalInterface(pStream, &IID_IClassFactory, (void **)&pProxy);
969 ok(hr == CO_E_OBJNOTREG,
970 "CoUnmarshalInterface should have failed with CO_E_OBJNOTREG, but returned 0x%08x instead\n",
973 IStream_Release(pStream);
977 end_host_object(tid, thread);
980 /* tests success case of a same-thread table-strong marshal, unmarshal, unmarshal */
981 static void test_tablestrong_marshal_and_unmarshal_twice(void)
984 IStream *pStream = NULL;
985 IUnknown *pProxy1 = NULL;
986 IUnknown *pProxy2 = NULL;
992 hr = CreateStreamOnHGlobal(NULL, TRUE, &pStream);
993 ok_ole_success(hr, CreateStreamOnHGlobal);
994 tid = start_host_object(pStream, &IID_IClassFactory, (IUnknown*)&Test_ClassFactory, MSHLFLAGS_TABLESTRONG, &thread);
996 ok_more_than_one_lock();
998 IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
999 hr = CoUnmarshalInterface(pStream, &IID_IClassFactory, (void **)&pProxy1);
1000 ok_ole_success(hr, CoUnmarshalInterface);
1002 ok_more_than_one_lock();
1004 IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
1005 hr = CoUnmarshalInterface(pStream, &IID_IClassFactory, (void **)&pProxy2);
1006 ok_ole_success(hr, CoUnmarshalInterface);
1008 ok_more_than_one_lock();
1010 if (pProxy1) IUnknown_Release(pProxy1);
1011 if (pProxy2) IUnknown_Release(pProxy2);
1013 /* this line is shows the difference between weak and strong table marshaling:
1014 * weak has cLocks == 0
1015 * strong has cLocks > 0 */
1016 ok_more_than_one_lock();
1018 /* release the remaining reference on the object by calling
1019 * CoReleaseMarshalData in the hosting thread */
1020 IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
1021 release_host_object(tid);
1022 IStream_Release(pStream);
1026 end_host_object(tid, thread);
1029 /* tests CoLockObjectExternal */
1030 static void test_lock_object_external(void)
1033 IStream *pStream = NULL;
1037 /* test the stub manager creation aspect of CoLockObjectExternal when the
1038 * object hasn't been marshaled yet */
1039 CoLockObjectExternal((IUnknown*)&Test_ClassFactory, TRUE, TRUE);
1041 ok_more_than_one_lock();
1043 CoDisconnectObject((IUnknown*)&Test_ClassFactory, 0);
1047 /* test our empty stub manager being handled correctly in
1048 * CoMarshalInterface */
1049 CoLockObjectExternal((IUnknown*)&Test_ClassFactory, TRUE, TRUE);
1051 hr = CreateStreamOnHGlobal(NULL, TRUE, &pStream);
1052 ok_ole_success(hr, CreateStreamOnHGlobal);
1053 hr = CoMarshalInterface(pStream, &IID_IClassFactory, (IUnknown*)&Test_ClassFactory, MSHCTX_INPROC, NULL, MSHLFLAGS_NORMAL);
1054 ok_ole_success(hr, CoMarshalInterface);
1056 CoLockObjectExternal((IUnknown*)&Test_ClassFactory, TRUE, TRUE);
1058 ok_more_than_one_lock();
1060 IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
1061 hr = CoReleaseMarshalData(pStream);
1062 ok_ole_success(hr, CoReleaseMarshalData);
1063 IStream_Release(pStream);
1065 ok_more_than_one_lock();
1067 CoLockObjectExternal((IUnknown*)&Test_ClassFactory, FALSE, TRUE);
1069 ok_more_than_one_lock();
1071 CoLockObjectExternal((IUnknown*)&Test_ClassFactory, FALSE, TRUE);
1076 /* tests disconnecting stubs */
1077 static void test_disconnect_stub(void)
1080 IStream *pStream = NULL;
1084 hr = CreateStreamOnHGlobal(NULL, TRUE, &pStream);
1085 ok_ole_success(hr, CreateStreamOnHGlobal);
1086 hr = CoMarshalInterface(pStream, &IID_IClassFactory, (IUnknown*)&Test_ClassFactory, MSHCTX_INPROC, NULL, MSHLFLAGS_NORMAL);
1087 ok_ole_success(hr, CoMarshalInterface);
1089 CoLockObjectExternal((IUnknown*)&Test_ClassFactory, TRUE, TRUE);
1091 ok_more_than_one_lock();
1093 IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
1094 hr = CoReleaseMarshalData(pStream);
1095 ok_ole_success(hr, CoReleaseMarshalData);
1096 IStream_Release(pStream);
1098 ok_more_than_one_lock();
1100 CoDisconnectObject((IUnknown*)&Test_ClassFactory, 0);
1105 /* tests failure case of a same-thread marshal and unmarshal twice */
1106 static void test_normal_marshal_and_unmarshal_twice(void)
1109 IStream *pStream = NULL;
1110 IUnknown *pProxy1 = NULL;
1111 IUnknown *pProxy2 = NULL;
1115 hr = CreateStreamOnHGlobal(NULL, TRUE, &pStream);
1116 ok_ole_success(hr, CreateStreamOnHGlobal);
1117 hr = CoMarshalInterface(pStream, &IID_IClassFactory, (IUnknown*)&Test_ClassFactory, MSHCTX_INPROC, NULL, MSHLFLAGS_NORMAL);
1118 ok_ole_success(hr, CoMarshalInterface);
1120 ok_more_than_one_lock();
1122 IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
1123 hr = CoUnmarshalInterface(pStream, &IID_IClassFactory, (void **)&pProxy1);
1124 ok_ole_success(hr, CoUnmarshalInterface);
1126 ok_more_than_one_lock();
1128 IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
1129 hr = CoUnmarshalInterface(pStream, &IID_IClassFactory, (void **)&pProxy2);
1130 ok(hr == CO_E_OBJNOTCONNECTED,
1131 "CoUnmarshalInterface should have failed with error CO_E_OBJNOTCONNECTED for double unmarshal, instead of 0x%08x\n", hr);
1133 IStream_Release(pStream);
1135 ok_more_than_one_lock();
1137 IUnknown_Release(pProxy1);
1142 /* tests success case of marshaling and unmarshaling an HRESULT */
1143 static void test_hresult_marshaling(void)
1146 HRESULT hr_marshaled = 0;
1147 IStream *pStream = NULL;
1148 static const HRESULT E_DEADBEEF = 0xdeadbeef;
1150 hr = CreateStreamOnHGlobal(NULL, TRUE, &pStream);
1151 ok_ole_success(hr, CreateStreamOnHGlobal);
1153 hr = CoMarshalHresult(pStream, E_DEADBEEF);
1154 ok_ole_success(hr, CoMarshalHresult);
1156 IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
1157 hr = IStream_Read(pStream, &hr_marshaled, sizeof(HRESULT), NULL);
1158 ok_ole_success(hr, IStream_Read);
1160 ok(hr_marshaled == E_DEADBEEF, "Didn't marshal HRESULT as expected: got value 0x%08x instead\n", hr_marshaled);
1163 IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
1164 hr = CoUnmarshalHresult(pStream, &hr_marshaled);
1165 ok_ole_success(hr, CoUnmarshalHresult);
1167 ok(hr_marshaled == E_DEADBEEF, "Didn't marshal HRESULT as expected: got value 0x%08x instead\n", hr_marshaled);
1169 IStream_Release(pStream);
1173 /* helper for test_proxy_used_in_wrong_thread */
1174 static DWORD CALLBACK bad_thread_proc(LPVOID p)
1176 IClassFactory * cf = (IClassFactory *)p;
1178 IUnknown * proxy = NULL;
1180 pCoInitializeEx(NULL, COINIT_MULTITHREADED);
1182 hr = IClassFactory_CreateInstance(cf, NULL, &IID_IUnknown, (LPVOID*)&proxy);
1183 if (proxy) IUnknown_Release(proxy);
1184 ok(hr == RPC_E_WRONG_THREAD,
1185 "COM should have failed with RPC_E_WRONG_THREAD on using proxy from wrong apartment, but instead returned 0x%08x\n",
1193 /* tests failure case of a using a proxy in the wrong apartment */
1194 static void test_proxy_used_in_wrong_thread(void)
1197 IStream *pStream = NULL;
1198 IUnknown *pProxy = NULL;
1205 hr = CreateStreamOnHGlobal(NULL, TRUE, &pStream);
1206 ok_ole_success(hr, CreateStreamOnHGlobal);
1207 tid = start_host_object(pStream, &IID_IClassFactory, (IUnknown*)&Test_ClassFactory, MSHLFLAGS_NORMAL, &host_thread);
1209 ok_more_than_one_lock();
1211 IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
1212 hr = CoUnmarshalInterface(pStream, &IID_IClassFactory, (void **)&pProxy);
1213 ok_ole_success(hr, CoUnmarshalInterface);
1214 IStream_Release(pStream);
1216 ok_more_than_one_lock();
1218 /* create a thread that we can misbehave in */
1219 thread = CreateThread(NULL, 0, bad_thread_proc, (LPVOID)pProxy, 0, &tid2);
1221 WaitForSingleObject(thread, INFINITE);
1222 CloseHandle(thread);
1224 IUnknown_Release(pProxy);
1228 end_host_object(tid, host_thread);
1231 static HRESULT WINAPI MessageFilter_QueryInterface(IMessageFilter *iface, REFIID riid, void ** ppvObj)
1233 if (ppvObj == NULL) return E_POINTER;
1235 if (IsEqualGUID(riid, &IID_IUnknown) ||
1236 IsEqualGUID(riid, &IID_IClassFactory))
1238 *ppvObj = (LPVOID)iface;
1239 IClassFactory_AddRef(iface);
1243 return E_NOINTERFACE;
1246 static ULONG WINAPI MessageFilter_AddRef(IMessageFilter *iface)
1248 return 2; /* non-heap object */
1251 static ULONG WINAPI MessageFilter_Release(IMessageFilter *iface)
1253 return 1; /* non-heap object */
1256 static DWORD WINAPI MessageFilter_HandleInComingCall(
1257 IMessageFilter *iface,
1259 HTASK threadIDCaller,
1261 LPINTERFACEINFO lpInterfaceInfo)
1263 static int callcount = 0;
1265 trace("HandleInComingCall\n");
1269 ret = SERVERCALL_REJECTED;
1272 ret = SERVERCALL_RETRYLATER;
1275 ret = SERVERCALL_ISHANDLED;
1282 static DWORD WINAPI MessageFilter_RetryRejectedCall(
1283 IMessageFilter *iface,
1284 HTASK threadIDCallee,
1288 trace("RetryRejectedCall\n");
1292 static DWORD WINAPI MessageFilter_MessagePending(
1293 IMessageFilter *iface,
1294 HTASK threadIDCallee,
1296 DWORD dwPendingType)
1298 trace("MessagePending\n");
1299 return PENDINGMSG_WAITNOPROCESS;
1302 static const IMessageFilterVtbl MessageFilter_Vtbl =
1304 MessageFilter_QueryInterface,
1305 MessageFilter_AddRef,
1306 MessageFilter_Release,
1307 MessageFilter_HandleInComingCall,
1308 MessageFilter_RetryRejectedCall,
1309 MessageFilter_MessagePending
1312 static IMessageFilter MessageFilter = { &MessageFilter_Vtbl };
1314 static void test_message_filter(void)
1317 IStream *pStream = NULL;
1318 IClassFactory *cf = NULL;
1320 IUnknown *proxy = NULL;
1321 IMessageFilter *prev_filter = NULL;
1326 hr = CreateStreamOnHGlobal(NULL, TRUE, &pStream);
1327 ok_ole_success(hr, CreateStreamOnHGlobal);
1328 tid = start_host_object2(pStream, &IID_IClassFactory, (IUnknown*)&Test_ClassFactory, MSHLFLAGS_NORMAL, &MessageFilter, &thread);
1330 ok_more_than_one_lock();
1332 IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
1333 hr = CoUnmarshalInterface(pStream, &IID_IClassFactory, (void **)&cf);
1334 ok_ole_success(hr, CoUnmarshalInterface);
1335 IStream_Release(pStream);
1337 ok_more_than_one_lock();
1339 hr = IClassFactory_CreateInstance(cf, NULL, &IID_IUnknown, (LPVOID*)&proxy);
1340 ok(hr == RPC_E_CALL_REJECTED, "Call should have returned RPC_E_CALL_REJECTED, but return 0x%08x instead\n", hr);
1341 if (proxy) IUnknown_Release(proxy);
1344 hr = CoRegisterMessageFilter(&MessageFilter, &prev_filter);
1345 ok_ole_success(hr, CoRegisterMessageFilter);
1347 hr = IClassFactory_CreateInstance(cf, NULL, &IID_IUnknown, (LPVOID*)&proxy);
1348 ok_ole_success(hr, IClassFactory_CreateInstance);
1350 IUnknown_Release(proxy);
1352 IClassFactory_Release(cf);
1356 end_host_object(tid, thread);
1358 hr = CoRegisterMessageFilter(prev_filter, NULL);
1359 ok_ole_success(hr, CoRegisterMessageFilter);
1362 /* test failure case of trying to unmarshal from bad stream */
1363 static void test_bad_marshal_stream(void)
1366 IStream *pStream = NULL;
1368 hr = CreateStreamOnHGlobal(NULL, TRUE, &pStream);
1369 ok_ole_success(hr, CreateStreamOnHGlobal);
1370 hr = CoMarshalInterface(pStream, &IID_IClassFactory, (IUnknown*)&Test_ClassFactory, MSHCTX_INPROC, NULL, MSHLFLAGS_NORMAL);
1371 ok_ole_success(hr, CoMarshalInterface);
1373 ok_more_than_one_lock();
1375 /* try to read beyond end of stream */
1376 hr = CoReleaseMarshalData(pStream);
1377 ok(hr == STG_E_READFAULT, "Should have failed with STG_E_READFAULT, but returned 0x%08x instead\n", hr);
1379 /* now release for real */
1380 IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
1381 hr = CoReleaseMarshalData(pStream);
1382 ok_ole_success(hr, CoReleaseMarshalData);
1384 IStream_Release(pStream);
1387 /* tests that proxies implement certain interfaces */
1388 static void test_proxy_interfaces(void)
1391 IStream *pStream = NULL;
1392 IUnknown *pProxy = NULL;
1393 IUnknown *pOtherUnknown = NULL;
1399 hr = CreateStreamOnHGlobal(NULL, TRUE, &pStream);
1400 ok_ole_success(hr, CreateStreamOnHGlobal);
1401 tid = start_host_object(pStream, &IID_IClassFactory, (IUnknown*)&Test_ClassFactory, MSHLFLAGS_NORMAL, &thread);
1403 ok_more_than_one_lock();
1405 IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
1406 hr = CoUnmarshalInterface(pStream, &IID_IUnknown, (void **)&pProxy);
1407 ok_ole_success(hr, CoUnmarshalInterface);
1408 IStream_Release(pStream);
1410 ok_more_than_one_lock();
1412 hr = IUnknown_QueryInterface(pProxy, &IID_IUnknown, (LPVOID*)&pOtherUnknown);
1413 ok_ole_success(hr, IUnknown_QueryInterface IID_IUnknown);
1414 if (hr == S_OK) IUnknown_Release(pOtherUnknown);
1416 hr = IUnknown_QueryInterface(pProxy, &IID_IClientSecurity, (LPVOID*)&pOtherUnknown);
1417 ok_ole_success(hr, IUnknown_QueryInterface IID_IClientSecurity);
1418 if (hr == S_OK) IUnknown_Release(pOtherUnknown);
1420 hr = IUnknown_QueryInterface(pProxy, &IID_IMultiQI, (LPVOID*)&pOtherUnknown);
1421 ok_ole_success(hr, IUnknown_QueryInterface IID_IMultiQI);
1422 if (hr == S_OK) IUnknown_Release(pOtherUnknown);
1424 hr = IUnknown_QueryInterface(pProxy, &IID_IMarshal, (LPVOID*)&pOtherUnknown);
1425 ok_ole_success(hr, IUnknown_QueryInterface IID_IMarshal);
1426 if (hr == S_OK) IUnknown_Release(pOtherUnknown);
1428 /* IMarshal2 is also supported on NT-based systems, but is pretty much
1429 * useless as it has no more methods over IMarshal that it inherits from. */
1431 IUnknown_Release(pProxy);
1435 end_host_object(tid, thread);
1440 const IUnknownVtbl *lpVtbl;
1444 static HRESULT WINAPI HeapUnknown_QueryInterface(IUnknown *iface, REFIID riid, void **ppv)
1446 if (IsEqualIID(riid, &IID_IUnknown))
1448 IUnknown_AddRef(iface);
1449 *ppv = (LPVOID)iface;
1453 return E_NOINTERFACE;
1456 static ULONG WINAPI HeapUnknown_AddRef(IUnknown *iface)
1458 HeapUnknown *This = (HeapUnknown *)iface;
1459 return InterlockedIncrement((LONG*)&This->refs);
1462 static ULONG WINAPI HeapUnknown_Release(IUnknown *iface)
1464 HeapUnknown *This = (HeapUnknown *)iface;
1465 ULONG refs = InterlockedDecrement((LONG*)&This->refs);
1466 if (!refs) HeapFree(GetProcessHeap(), 0, This);
1470 static const IUnknownVtbl HeapUnknown_Vtbl =
1472 HeapUnknown_QueryInterface,
1477 static void test_proxybuffer(REFIID riid)
1480 IPSFactoryBuffer *psfb;
1481 IRpcProxyBuffer *proxy;
1485 HeapUnknown *pUnkOuter = (HeapUnknown *)HeapAlloc(GetProcessHeap(), 0, sizeof(*pUnkOuter));
1487 pUnkOuter->lpVtbl = &HeapUnknown_Vtbl;
1488 pUnkOuter->refs = 1;
1490 hr = CoGetPSClsid(riid, &clsid);
1491 ok_ole_success(hr, CoGetPSClsid);
1493 hr = CoGetClassObject(&clsid, CLSCTX_INPROC_SERVER, NULL, &IID_IPSFactoryBuffer, (LPVOID*)&psfb);
1494 ok_ole_success(hr, CoGetClassObject);
1496 hr = IPSFactoryBuffer_CreateProxy(psfb, (IUnknown*)pUnkOuter, riid, &proxy, &lpvtbl);
1497 ok_ole_success(hr, IPSFactoryBuffer_CreateProxy);
1498 ok(lpvtbl != NULL, "IPSFactoryBuffer_CreateProxy succeeded, but returned a NULL vtable!\n");
1500 /* release our reference to the outer unknown object - the PS factory
1501 * buffer will have AddRef's it in the CreateProxy call */
1502 refs = IUnknown_Release((IUnknown *)pUnkOuter);
1503 ok(refs == 1, "Ref count of outer unknown should have been 1 instead of %d\n", refs);
1505 refs = IPSFactoryBuffer_Release(psfb);
1508 /* not reliable on native. maybe it leaks references! */
1509 ok(refs == 0, "Ref-count leak of %d on IPSFactoryBuffer\n", refs);
1512 refs = IUnknown_Release((IUnknown *)lpvtbl);
1513 ok(refs == 0, "Ref-count leak of %d on IRpcProxyBuffer\n", refs);
1515 refs = IRpcProxyBuffer_Release(proxy);
1516 ok(refs == 0, "Ref-count leak of %d on IRpcProxyBuffer\n", refs);
1519 static void test_stubbuffer(REFIID riid)
1522 IPSFactoryBuffer *psfb;
1523 IRpcStubBuffer *stub;
1529 hr = CoGetPSClsid(riid, &clsid);
1530 ok_ole_success(hr, CoGetPSClsid);
1532 hr = CoGetClassObject(&clsid, CLSCTX_INPROC_SERVER, NULL, &IID_IPSFactoryBuffer, (LPVOID*)&psfb);
1533 ok_ole_success(hr, CoGetClassObject);
1535 hr = IPSFactoryBuffer_CreateStub(psfb, riid, (IUnknown*)&Test_ClassFactory, &stub);
1536 ok_ole_success(hr, IPSFactoryBuffer_CreateStub);
1538 refs = IPSFactoryBuffer_Release(psfb);
1541 /* not reliable on native. maybe it leaks references */
1542 ok(refs == 0, "Ref-count leak of %d on IPSFactoryBuffer\n", refs);
1545 ok_more_than_one_lock();
1547 IRpcStubBuffer_Disconnect(stub);
1551 refs = IRpcStubBuffer_Release(stub);
1552 ok(refs == 0, "Ref-count leak of %d on IRpcProxyBuffer\n", refs);
1555 static HWND hwnd_app;
1557 static HRESULT WINAPI TestRE_IClassFactory_CreateInstance(
1558 LPCLASSFACTORY iface,
1559 LPUNKNOWN pUnkOuter,
1564 if (IsEqualIID(riid, &IID_IWineTest))
1566 BOOL ret = SendMessageTimeout(hwnd_app, WM_NULL, 0, 0, SMTO_BLOCK, 5000, &res);
1567 ok(ret, "Timed out sending a message to originating window during RPC call\n");
1572 static const IClassFactoryVtbl TestREClassFactory_Vtbl =
1574 Test_IClassFactory_QueryInterface,
1575 Test_IClassFactory_AddRef,
1576 Test_IClassFactory_Release,
1577 TestRE_IClassFactory_CreateInstance,
1578 Test_IClassFactory_LockServer
1581 IClassFactory TestRE_ClassFactory = { &TestREClassFactory_Vtbl };
1583 static LRESULT CALLBACK window_proc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam)
1590 IStream *pStream = NULL;
1591 IClassFactory *proxy = NULL;
1598 hr = CreateStreamOnHGlobal(NULL, TRUE, &pStream);
1599 ok_ole_success(hr, CreateStreamOnHGlobal);
1600 tid = start_host_object(pStream, &IID_IClassFactory, (IUnknown*)&TestRE_ClassFactory, MSHLFLAGS_NORMAL, &thread);
1602 ok_more_than_one_lock();
1604 IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
1605 hr = CoUnmarshalInterface(pStream, &IID_IClassFactory, (void **)&proxy);
1606 ok_ole_success(hr, CoReleaseMarshalData);
1607 IStream_Release(pStream);
1609 ok_more_than_one_lock();
1611 /* note the use of the magic IID_IWineTest value to tell remote thread
1612 * to try to send a message back to us */
1613 hr = IClassFactory_CreateInstance(proxy, NULL, &IID_IWineTest, (void **)&object);
1615 IClassFactory_Release(proxy);
1619 end_host_object(tid, thread);
1621 PostMessage(hwnd, WM_QUIT, 0, 0);
1628 IStream *pStream = NULL;
1629 IClassFactory *proxy = NULL;
1636 hr = CreateStreamOnHGlobal(NULL, TRUE, &pStream);
1637 ok_ole_success(hr, CreateStreamOnHGlobal);
1638 tid = start_host_object(pStream, &IID_IClassFactory, (IUnknown*)&TestRE_ClassFactory, MSHLFLAGS_NORMAL, &thread);
1640 ok_more_than_one_lock();
1642 IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
1643 hr = CoUnmarshalInterface(pStream, &IID_IClassFactory, (void **)&proxy);
1644 ok_ole_success(hr, CoReleaseMarshalData);
1645 IStream_Release(pStream);
1647 ok_more_than_one_lock();
1649 /* post quit message before a doing a COM call to show that a pending
1650 * WM_QUIT message doesn't stop the call from succeeding */
1651 PostMessage(hwnd, WM_QUIT, 0, 0);
1652 hr = IClassFactory_CreateInstance(proxy, NULL, &IID_IUnknown, (void **)&object);
1654 IClassFactory_Release(proxy);
1658 end_host_object(tid, thread);
1665 IStream *pStream = NULL;
1666 IClassFactory *proxy = NULL;
1671 hr = CreateStreamOnHGlobal(NULL, TRUE, &pStream);
1672 ok_ole_success(hr, CreateStreamOnHGlobal);
1673 tid = start_host_object(pStream, &IID_IClassFactory, (IUnknown*)&Test_ClassFactory, MSHLFLAGS_NORMAL, &thread);
1675 IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
1676 hr = CoUnmarshalInterface(pStream, &IID_IClassFactory, (void **)&proxy);
1677 ok_ole_success(hr, CoReleaseMarshalData);
1678 IStream_Release(pStream);
1680 /* shows that COM calls executed during the processing of sent
1681 * messages should fail */
1682 hr = IClassFactory_CreateInstance(proxy, NULL, &IID_IUnknown, (void **)&object);
1683 ok(hr == RPC_E_CANTCALLOUT_ININPUTSYNCCALL,
1684 "COM call during processing of sent message should return RPC_E_CANTCALLOUT_ININPUTSYNCCALL instead of 0x%08x\n", hr);
1686 IClassFactory_Release(proxy);
1688 end_host_object(tid, thread);
1695 return DefWindowProc(hwnd, msg, wparam, lparam);
1699 static void test_message_reentrancy(void)
1704 memset(&wndclass, 0, sizeof(wndclass));
1705 wndclass.lpfnWndProc = window_proc;
1706 wndclass.lpszClassName = "WineCOMTest";
1707 RegisterClass(&wndclass);
1709 hwnd_app = CreateWindow("WineCOMTest", NULL, 0, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, NULL, NULL, NULL, 0);
1710 ok(hwnd_app != NULL, "Window creation failed\n");
1712 /* start message re-entrancy test */
1713 PostMessage(hwnd_app, WM_USER, 0, 0);
1715 while (GetMessage(&msg, NULL, 0, 0))
1717 TranslateMessage(&msg);
1718 DispatchMessage(&msg);
1722 static HRESULT WINAPI TestMsg_IClassFactory_CreateInstance(
1723 LPCLASSFACTORY iface,
1724 LPUNKNOWN pUnkOuter,
1729 SendMessage(hwnd_app, WM_USER+2, 0, 0);
1733 static IClassFactoryVtbl TestMsgClassFactory_Vtbl =
1735 Test_IClassFactory_QueryInterface,
1736 Test_IClassFactory_AddRef,
1737 Test_IClassFactory_Release,
1738 TestMsg_IClassFactory_CreateInstance,
1739 Test_IClassFactory_LockServer
1742 IClassFactory TestMsg_ClassFactory = { &TestMsgClassFactory_Vtbl };
1744 static void test_call_from_message(void)
1749 IClassFactory *proxy;
1754 hwnd_app = CreateWindow("WineCOMTest", NULL, 0, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, NULL, NULL, NULL, 0);
1755 ok(hwnd_app != NULL, "Window creation failed\n");
1757 hr = CreateStreamOnHGlobal(NULL, TRUE, &pStream);
1758 ok_ole_success(hr, CreateStreamOnHGlobal);
1759 tid = start_host_object(pStream, &IID_IClassFactory, (IUnknown*)&TestMsg_ClassFactory, MSHLFLAGS_NORMAL, &thread);
1761 ok_more_than_one_lock();
1763 IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
1764 hr = CoUnmarshalInterface(pStream, &IID_IClassFactory, (void **)&proxy);
1765 ok_ole_success(hr, CoReleaseMarshalData);
1766 IStream_Release(pStream);
1768 ok_more_than_one_lock();
1770 /* start message re-entrancy test */
1771 hr = IClassFactory_CreateInstance(proxy, NULL, &IID_IUnknown, (void **)&object);
1772 ok_ole_success(hr, IClassFactory_CreateInstance);
1774 IClassFactory_Release(proxy);
1778 end_host_object(tid, thread);
1780 while (GetMessage(&msg, NULL, 0, 0))
1782 TranslateMessage(&msg);
1783 DispatchMessage(&msg);
1787 static void test_WM_QUIT_handling(void)
1791 hwnd_app = CreateWindow("WineCOMTest", NULL, 0, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, NULL, NULL, NULL, 0);
1792 ok(hwnd_app != NULL, "Window creation failed\n");
1794 /* start WM_QUIT handling test */
1795 PostMessage(hwnd_app, WM_USER+1, 0, 0);
1797 while (GetMessage(&msg, NULL, 0, 0))
1799 TranslateMessage(&msg);
1800 DispatchMessage(&msg);
1804 static void test_freethreadedmarshaldata(IStream *pStream, MSHCTX mshctx, void *ptr, DWORD mshlflags)
1811 hr = GetHGlobalFromStream(pStream, &hglobal);
1812 ok_ole_success(hr, GetHGlobalFromStream);
1814 size = GlobalSize(hglobal);
1816 marshal_data = (char *)GlobalLock(hglobal);
1818 if (mshctx == MSHCTX_INPROC)
1820 DWORD expected_size = sizeof(DWORD) + sizeof(void *) + sizeof(DWORD) + sizeof(GUID);
1821 ok(size == expected_size, "size should have been %d instead of %d\n", expected_size, size);
1823 ok(*(DWORD *)marshal_data == mshlflags, "expected 0x%x, but got 0x%x for mshctx\n", mshlflags, *(DWORD *)marshal_data);
1824 marshal_data += sizeof(DWORD);
1825 ok(*(void **)marshal_data == ptr, "expected %p, but got %p for mshctx\n", ptr, *(void **)marshal_data);
1826 marshal_data += sizeof(void *);
1827 ok(*(DWORD *)marshal_data == 0, "expected 0x0, but got 0x%x\n", *(DWORD *)marshal_data);
1828 marshal_data += sizeof(DWORD);
1829 trace("got guid data: {%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x}\n",
1830 ((GUID *)marshal_data)->Data1, ((GUID *)marshal_data)->Data2, ((GUID *)marshal_data)->Data3,
1831 ((GUID *)marshal_data)->Data4[0], ((GUID *)marshal_data)->Data4[1], ((GUID *)marshal_data)->Data4[2], ((GUID *)marshal_data)->Data4[3],
1832 ((GUID *)marshal_data)->Data4[4], ((GUID *)marshal_data)->Data4[5], ((GUID *)marshal_data)->Data4[6], ((GUID *)marshal_data)->Data4[7]);
1836 ok(size > sizeof(DWORD), "size should have been > sizeof(DWORD), not %d\n", size);
1837 ok(*(DWORD *)marshal_data == 0x574f454d /* MEOW */,
1838 "marshal data should be filled by standard marshal and start with MEOW signature\n");
1841 GlobalUnlock(hglobal);
1844 static void test_freethreadedmarshaler(void)
1847 IUnknown *pFTUnknown;
1848 IMarshal *pFTMarshal;
1851 static const LARGE_INTEGER llZero;
1854 hr = CoCreateFreeThreadedMarshaler(NULL, &pFTUnknown);
1855 ok_ole_success(hr, CoCreateFreeThreadedMarshaler);
1856 hr = IUnknown_QueryInterface(pFTUnknown, &IID_IMarshal, (void **)&pFTMarshal);
1857 ok_ole_success(hr, IUnknown_QueryInterface);
1858 IUnknown_Release(pFTUnknown);
1860 hr = CreateStreamOnHGlobal(NULL, TRUE, &pStream);
1861 ok_ole_success(hr, CreateStreamOnHGlobal);
1863 /* inproc normal marshaling */
1865 hr = IMarshal_MarshalInterface(pFTMarshal, pStream, &IID_IClassFactory,
1866 (IUnknown*)&Test_ClassFactory, MSHCTX_INPROC, NULL, MSHLFLAGS_NORMAL);
1867 ok_ole_success(hr, IMarshal_MarshalInterface);
1869 ok_more_than_one_lock();
1871 test_freethreadedmarshaldata(pStream, MSHCTX_INPROC, &Test_ClassFactory, MSHLFLAGS_NORMAL);
1873 IStream_Seek(pStream, llZero, STREAM_SEEK_SET, NULL);
1874 hr = IMarshal_UnmarshalInterface(pFTMarshal, pStream, &IID_IUnknown, (void **)&pProxy);
1875 ok_ole_success(hr, IMarshal_UnmarshalInterface);
1877 IUnknown_Release(pProxy);
1881 /* native doesn't allow us to unmarshal or release the stream data,
1882 * presumably because it wants us to call CoMarshalInterface instead */
1885 /* local normal marshaling */
1887 IStream_Seek(pStream, llZero, STREAM_SEEK_SET, NULL);
1888 hr = IMarshal_MarshalInterface(pFTMarshal, pStream, &IID_IClassFactory, (IUnknown*)&Test_ClassFactory, MSHCTX_LOCAL, NULL, MSHLFLAGS_NORMAL);
1889 ok_ole_success(hr, IMarshal_MarshalInterface);
1891 ok_more_than_one_lock();
1893 test_freethreadedmarshaldata(pStream, MSHCTX_LOCAL, &Test_ClassFactory, MSHLFLAGS_NORMAL);
1895 IStream_Seek(pStream, llZero, STREAM_SEEK_SET, NULL);
1896 hr = IMarshal_ReleaseMarshalData(pFTMarshal, pStream);
1897 ok_ole_success(hr, IMarshal_ReleaseMarshalData);
1902 /* inproc table-strong marshaling */
1904 IStream_Seek(pStream, llZero, STREAM_SEEK_SET, NULL);
1905 hr = IMarshal_MarshalInterface(pFTMarshal, pStream, &IID_IClassFactory,
1906 (IUnknown*)&Test_ClassFactory, MSHCTX_INPROC, (void *)0xdeadbeef,
1907 MSHLFLAGS_TABLESTRONG);
1908 ok_ole_success(hr, IMarshal_MarshalInterface);
1910 ok_more_than_one_lock();
1912 test_freethreadedmarshaldata(pStream, MSHCTX_INPROC, &Test_ClassFactory, MSHLFLAGS_TABLESTRONG);
1914 IStream_Seek(pStream, llZero, STREAM_SEEK_SET, NULL);
1915 hr = IMarshal_UnmarshalInterface(pFTMarshal, pStream, &IID_IUnknown, (void **)&pProxy);
1916 ok_ole_success(hr, IMarshal_UnmarshalInterface);
1918 IUnknown_Release(pProxy);
1920 ok_more_than_one_lock();
1922 IStream_Seek(pStream, llZero, STREAM_SEEK_SET, NULL);
1923 hr = IMarshal_ReleaseMarshalData(pFTMarshal, pStream);
1924 ok_ole_success(hr, IMarshal_ReleaseMarshalData);
1928 /* inproc table-weak marshaling */
1930 IStream_Seek(pStream, llZero, STREAM_SEEK_SET, NULL);
1931 hr = IMarshal_MarshalInterface(pFTMarshal, pStream, &IID_IClassFactory,
1932 (IUnknown*)&Test_ClassFactory, MSHCTX_INPROC, (void *)0xdeadbeef,
1933 MSHLFLAGS_TABLEWEAK);
1934 ok_ole_success(hr, IMarshal_MarshalInterface);
1938 test_freethreadedmarshaldata(pStream, MSHCTX_INPROC, &Test_ClassFactory, MSHLFLAGS_TABLEWEAK);
1940 IStream_Seek(pStream, llZero, STREAM_SEEK_SET, NULL);
1941 hr = IMarshal_UnmarshalInterface(pFTMarshal, pStream, &IID_IUnknown, (void **)&pProxy);
1942 ok_ole_success(hr, IMarshal_UnmarshalInterface);
1944 ok_more_than_one_lock();
1946 IUnknown_Release(pProxy);
1950 /* inproc normal marshaling (for extraordinary cases) */
1952 IStream_Seek(pStream, llZero, STREAM_SEEK_SET, NULL);
1953 hr = IMarshal_MarshalInterface(pFTMarshal, pStream, &IID_IClassFactory,
1954 (IUnknown*)&Test_ClassFactory, MSHCTX_INPROC, NULL, MSHLFLAGS_NORMAL);
1955 ok_ole_success(hr, IMarshal_MarshalInterface);
1957 ok_more_than_one_lock();
1959 /* this call shows that DisconnectObject does nothing */
1960 hr = IMarshal_DisconnectObject(pFTMarshal, 0);
1961 ok_ole_success(hr, IMarshal_DisconnectObject);
1963 ok_more_than_one_lock();
1965 IStream_Seek(pStream, llZero, STREAM_SEEK_SET, NULL);
1966 hr = IMarshal_ReleaseMarshalData(pFTMarshal, pStream);
1967 ok_ole_success(hr, IMarshal_ReleaseMarshalData);
1971 /* doesn't enforce marshaling rules here and allows us to unmarshal the
1972 * interface, even though it was freed above */
1973 IStream_Seek(pStream, llZero, STREAM_SEEK_SET, NULL);
1974 hr = IMarshal_UnmarshalInterface(pFTMarshal, pStream, &IID_IUnknown, (void **)&pProxy);
1975 ok_ole_success(hr, IMarshal_UnmarshalInterface);
1979 IStream_Release(pStream);
1980 IMarshal_Release(pFTMarshal);
1983 static void test_inproc_handler(void)
1991 DWORD dwDisposition;
1994 hr = StringFromCLSID(&CLSID_WineTest, &pszClsid);
1995 ok_ole_success(hr, "StringFromCLSID");
1996 strcpy(buffer, "CLSID\\");
1997 WideCharToMultiByte(CP_ACP, 0, pszClsid, -1, buffer + strlen(buffer), sizeof(buffer) - strlen(buffer), NULL, NULL);
1998 CoTaskMemFree(pszClsid);
1999 strcat(buffer, "\\InprocHandler32");
2000 error = RegCreateKeyEx(HKEY_CLASSES_ROOT, buffer, 0, NULL, 0, KEY_SET_VALUE, NULL, &hkey, &dwDisposition);
2001 ok(error == ERROR_SUCCESS, "RegCreateKeyEx failed with error %d\n", error);
2002 error = RegSetValueEx(hkey, NULL, 0, REG_SZ, (const unsigned char *)"ole32.dll", strlen("ole32.dll") + 1);
2003 ok(error == ERROR_SUCCESS, "RegSetValueEx failed with error %d\n", error);
2006 hr = CoCreateInstance(&CLSID_WineTest, NULL, CLSCTX_INPROC_HANDLER, &IID_IUnknown, (void **)&pObject);
2008 ok_ole_success(hr, "CoCreateInstance");
2012 hr = IUnknown_QueryInterface(pObject, &IID_IWineTest, (void **)&pObject2);
2013 ok(hr == E_NOINTERFACE, "IUnknown_QueryInterface on handler for invalid interface returned 0x%08x instead of E_NOINTERFACE\n", hr);
2015 /* it's a handler as it supports IOleObject */
2016 hr = IUnknown_QueryInterface(pObject, &IID_IOleObject, (void **)&pObject2);
2017 ok_ole_success(hr, "IUnknown_QueryInterface(&IID_IOleObject)");
2018 IUnknown_Release(pObject2);
2020 IUnknown_Release(pObject);
2023 RegDeleteKey(HKEY_CLASSES_ROOT, buffer);
2024 *strrchr(buffer, '\\') = '\0';
2025 RegDeleteKey(HKEY_CLASSES_ROOT, buffer);
2028 static HRESULT WINAPI Test_SMI_QueryInterface(
2029 IStdMarshalInfo *iface,
2033 if (ppvObj == NULL) return E_POINTER;
2035 if (IsEqualGUID(riid, &IID_IUnknown) ||
2036 IsEqualGUID(riid, &IID_IStdMarshalInfo))
2038 *ppvObj = (LPVOID)iface;
2039 IClassFactory_AddRef(iface);
2043 return E_NOINTERFACE;
2046 static ULONG WINAPI Test_SMI_AddRef(IStdMarshalInfo *iface)
2049 return 2; /* non-heap-based object */
2052 static ULONG WINAPI Test_SMI_Release(IStdMarshalInfo *iface)
2055 return 1; /* non-heap-based object */
2058 static HRESULT WINAPI Test_SMI_GetClassForHandler(
2059 IStdMarshalInfo *iface,
2060 DWORD dwDestContext,
2061 void *pvDestContext,
2064 *pClsid = CLSID_WineTest;
2068 static const IStdMarshalInfoVtbl Test_SMI_Vtbl =
2070 Test_SMI_QueryInterface,
2073 Test_SMI_GetClassForHandler
2076 static IStdMarshalInfo Test_SMI = {&Test_SMI_Vtbl};
2078 static void test_handler_marshaling(void)
2081 IStream *pStream = NULL;
2082 IUnknown *pProxy = NULL;
2086 static const LARGE_INTEGER ullZero;
2090 hr = CreateStreamOnHGlobal(NULL, TRUE, &pStream);
2091 ok_ole_success(hr, "CreateStreamOnHGlobal");
2092 tid = start_host_object(pStream, &IID_IUnknown, (IUnknown*)&Test_SMI, MSHLFLAGS_NORMAL, &thread);
2094 ok_more_than_one_lock();
2096 IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
2097 hr = CoUnmarshalInterface(pStream, &IID_IUnknown, (void **)&pProxy);
2098 ok_ole_success(hr, "CoUnmarshalInterface");
2099 IStream_Release(pStream);
2101 ok_more_than_one_lock();
2103 hr = IUnknown_QueryInterface(pProxy, &IID_IWineTest, (void **)&pObject);
2104 ok(hr == E_NOINTERFACE, "IUnknown_QueryInterface with unknown IID should have returned E_NOINTERFACE instead of 0x%08x\n", hr);
2106 /* it's a handler as it supports IOleObject */
2107 hr = IUnknown_QueryInterface(pProxy, &IID_IOleObject, (void **)&pObject);
2109 ok_ole_success(hr, "IUnknown_QueryInterface(&IID_IOleObject)");
2110 if (SUCCEEDED(hr)) IUnknown_Release(pObject);
2112 IUnknown_Release(pProxy);
2116 end_host_object(tid, thread);
2118 /* FIXME: test IPersist interface has the same effect as IStdMarshalInfo */
2122 static void test_client_security(void)
2125 IStream *pStream = NULL;
2126 IClassFactory *pProxy = NULL;
2127 IUnknown *pProxy2 = NULL;
2128 IUnknown *pUnknown1 = NULL;
2129 IUnknown *pUnknown2 = NULL;
2130 IClientSecurity *pCliSec = NULL;
2134 static const LARGE_INTEGER ullZero;
2137 OLECHAR *pServerPrincName;
2141 DWORD dwCapabilities;
2146 hr = CreateStreamOnHGlobal(NULL, TRUE, &pStream);
2147 ok_ole_success(hr, "CreateStreamOnHGlobal");
2148 tid = start_host_object(pStream, &IID_IClassFactory, (IUnknown*)&Test_ClassFactory, MSHLFLAGS_NORMAL, &thread);
2150 IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
2151 hr = CoUnmarshalInterface(pStream, &IID_IClassFactory, (void **)&pProxy);
2152 ok_ole_success(hr, "CoUnmarshalInterface");
2153 IStream_Release(pStream);
2155 hr = IUnknown_QueryInterface(pProxy, &IID_IUnknown, (LPVOID*)&pUnknown1);
2156 ok_ole_success(hr, "IUnknown_QueryInterface IID_IUnknown");
2158 hr = IUnknown_QueryInterface(pProxy, &IID_IRemUnknown, (LPVOID*)&pProxy2);
2159 ok_ole_success(hr, "IUnknown_QueryInterface IID_IStream");
2161 hr = IUnknown_QueryInterface(pProxy2, &IID_IUnknown, (LPVOID*)&pUnknown2);
2162 ok_ole_success(hr, "IUnknown_QueryInterface IID_IUnknown");
2164 ok(pUnknown1 == pUnknown2, "both proxy's IUnknowns should be the same - %p, %p\n", pUnknown1, pUnknown2);
2166 hr = IUnknown_QueryInterface(pProxy, &IID_IMarshal, (LPVOID*)&pMarshal);
2167 ok_ole_success(hr, "IUnknown_QueryInterface IID_IMarshal");
2169 hr = IUnknown_QueryInterface(pProxy, &IID_IClientSecurity, (LPVOID*)&pCliSec);
2170 ok_ole_success(hr, "IUnknown_QueryInterface IID_IClientSecurity");
2172 hr = IClientSecurity_QueryBlanket(pCliSec, (IUnknown *)pProxy, NULL, NULL, NULL, NULL, NULL, NULL, NULL);
2173 todo_wine ok_ole_success(hr, "IClientSecurity_QueryBlanket (all NULLs)");
2175 hr = IClientSecurity_QueryBlanket(pCliSec, (IUnknown *)pMarshal, NULL, NULL, NULL, NULL, NULL, NULL, NULL);
2176 todo_wine ok(hr == E_NOINTERFACE, "IClientSecurity_QueryBlanket with local interface should have returned E_NOINTERFACE instead of 0x%08x\n", hr);
2178 hr = IClientSecurity_QueryBlanket(pCliSec, (IUnknown *)pProxy, &dwAuthnSvc, &dwAuthzSvc, &pServerPrincName, &dwAuthnLevel, &dwImpLevel, &pAuthInfo, &dwCapabilities);
2179 todo_wine ok_ole_success(hr, "IClientSecurity_QueryBlanket");
2181 hr = IClientSecurity_SetBlanket(pCliSec, (IUnknown *)pProxy, dwAuthnSvc, dwAuthzSvc, pServerPrincName, dwAuthnLevel, RPC_C_IMP_LEVEL_IMPERSONATE, pAuthInfo, dwCapabilities);
2182 todo_wine ok_ole_success(hr, "IClientSecurity_SetBlanket");
2184 hr = IClassFactory_CreateInstance(pProxy, NULL, &IID_IWineTest, &pv);
2185 ok(hr == E_NOINTERFACE, "COM call should have succeeded instead of returning 0x%08x\n", hr);
2187 hr = IClientSecurity_SetBlanket(pCliSec, (IUnknown *)pMarshal, dwAuthnSvc, dwAuthzSvc, pServerPrincName, dwAuthnLevel, dwImpLevel, pAuthInfo, dwCapabilities);
2188 todo_wine ok(hr == E_NOINTERFACE, "IClientSecurity_SetBlanket with local interface should have returned E_NOINTERFACE instead of 0x%08x\n", hr);
2190 hr = IClientSecurity_SetBlanket(pCliSec, (IUnknown *)pProxy, 0xdeadbeef, dwAuthzSvc, pServerPrincName, dwAuthnLevel, dwImpLevel, pAuthInfo, dwCapabilities);
2191 todo_wine ok(hr == E_INVALIDARG, "IClientSecurity_SetBlanke with invalid dwAuthnSvc should have returned E_INVALIDARG instead of 0x%08x\n", hr);
2193 CoTaskMemFree(pServerPrincName);
2195 hr = IClientSecurity_QueryBlanket(pCliSec, (IUnknown *)pUnknown1, &dwAuthnSvc, &dwAuthzSvc, &pServerPrincName, &dwAuthnLevel, &dwImpLevel, &pAuthInfo, &dwCapabilities);
2196 todo_wine ok_ole_success(hr, "IClientSecurity_QueryBlanket(IUnknown)");
2198 CoTaskMemFree(pServerPrincName);
2200 IClassFactory_Release(pProxy);
2201 IUnknown_Release(pProxy2);
2202 IUnknown_Release(pUnknown1);
2203 IUnknown_Release(pUnknown2);
2204 IMarshal_Release(pMarshal);
2205 IClientSecurity_Release(pCliSec);
2207 end_host_object(tid, thread);
2210 static HANDLE heventShutdown;
2212 static void LockModuleOOP(void)
2214 InterlockedIncrement(&cLocks); /* for test purposes only */
2215 CoAddRefServerProcess();
2218 static void UnlockModuleOOP(void)
2220 InterlockedDecrement(&cLocks); /* for test purposes only */
2221 if (!CoReleaseServerProcess())
2222 SetEvent(heventShutdown);
2225 static HWND hwnd_app;
2227 static HRESULT WINAPI TestOOP_IClassFactory_QueryInterface(
2228 LPCLASSFACTORY iface,
2232 if (ppvObj == NULL) return E_POINTER;
2234 if (IsEqualGUID(riid, &IID_IUnknown) ||
2235 IsEqualGUID(riid, &IID_IClassFactory))
2237 *ppvObj = (LPVOID)iface;
2238 IClassFactory_AddRef(iface);
2242 return E_NOINTERFACE;
2245 static ULONG WINAPI TestOOP_IClassFactory_AddRef(LPCLASSFACTORY iface)
2247 return 2; /* non-heap-based object */
2250 static ULONG WINAPI TestOOP_IClassFactory_Release(LPCLASSFACTORY iface)
2252 return 1; /* non-heap-based object */
2255 static HRESULT WINAPI TestOOP_IClassFactory_CreateInstance(
2256 LPCLASSFACTORY iface,
2257 LPUNKNOWN pUnkOuter,
2261 if (IsEqualIID(riid, &IID_IClassFactory) || IsEqualIID(riid, &IID_IUnknown))
2266 return CLASS_E_CLASSNOTAVAILABLE;
2269 static HRESULT WINAPI TestOOP_IClassFactory_LockServer(
2270 LPCLASSFACTORY iface,
2280 static const IClassFactoryVtbl TestClassFactoryOOP_Vtbl =
2282 TestOOP_IClassFactory_QueryInterface,
2283 TestOOP_IClassFactory_AddRef,
2284 TestOOP_IClassFactory_Release,
2285 TestOOP_IClassFactory_CreateInstance,
2286 TestOOP_IClassFactory_LockServer
2289 static IClassFactory TestOOP_ClassFactory = { &TestClassFactoryOOP_Vtbl };
2291 static void test_register_local_server(void)
2299 heventShutdown = CreateEvent(NULL, TRUE, FALSE, NULL);
2301 hr = CoRegisterClassObject(&CLSID_WineOOPTest, (IUnknown *)&TestOOP_ClassFactory,
2302 CLSCTX_LOCAL_SERVER, REGCLS_SINGLEUSE, &cookie);
2303 ok_ole_success(hr, CoRegisterClassObject);
2305 ready_event = CreateEvent(NULL, FALSE, FALSE, "Wine COM Test Ready Event");
2306 SetEvent(ready_event);
2308 quit_event = CreateEvent(NULL, FALSE, FALSE, "Wine COM Test Quit Event");
2312 wait = MsgWaitForMultipleObjects(1, &quit_event, FALSE, INFINITE, QS_ALLINPUT);
2313 if (wait == WAIT_OBJECT_0+1)
2316 BOOL ret = PeekMessage(&msg, NULL, 0, 0, PM_REMOVE);
2319 trace("Message 0x%x\n", msg.message);
2320 TranslateMessage(&msg);
2321 DispatchMessage(&msg);
2325 while (wait == WAIT_OBJECT_0+1);
2327 hr = CoRevokeClassObject(cookie);
2328 ok_ole_success(hr, CoRevokeClassObject);
2331 static HANDLE create_target_process(const char *arg)
2334 char cmdline[MAX_PATH];
2335 PROCESS_INFORMATION pi;
2336 STARTUPINFO si = { 0 };
2339 winetest_get_mainargs( &argv );
2340 sprintf(cmdline, "%s %s %s", argv[0], argv[1], arg);
2341 ok(CreateProcess(argv[0], cmdline, NULL, NULL, FALSE, 0, NULL, NULL,
2342 &si, &pi) != 0, "error: %u\n", GetLastError());
2343 ok(CloseHandle(pi.hThread) != 0, "error %u\n", GetLastError());
2347 /* tests functions commonly used by out of process COM servers */
2348 static void test_local_server(void)
2358 heventShutdown = CreateEvent(NULL, TRUE, FALSE, NULL);
2362 /* Start the object suspended */
2363 hr = CoRegisterClassObject(&CLSID_WineOOPTest, (IUnknown *)&TestOOP_ClassFactory,
2364 CLSCTX_LOCAL_SERVER, REGCLS_MULTIPLEUSE | REGCLS_SUSPENDED, &cookie);
2365 ok_ole_success(hr, CoRegisterClassObject);
2367 /* ... and CoGetClassObject does not find it and fails when it looks for the
2368 * class in the registry */
2369 hr = CoGetClassObject(&CLSID_WineOOPTest, CLSCTX_INPROC_SERVER,
2370 NULL, &IID_IClassFactory, (LPVOID*)&cf);
2371 ok(hr == REGDB_E_CLASSNOTREG || /* NT */
2372 hr == S_OK /* Win9x */,
2373 "CoGetClassObject should have returned REGDB_E_CLASSNOTREG instead of 0x%08x\n", hr);
2375 /* Resume the object suspended above ... */
2376 hr = CoResumeClassObjects();
2377 ok_ole_success(hr, CoResumeClassObjects);
2379 /* ... and now it should succeed */
2380 hr = CoGetClassObject(&CLSID_WineOOPTest, CLSCTX_INPROC_SERVER,
2381 NULL, &IID_IClassFactory, (LPVOID*)&cf);
2382 ok_ole_success(hr, CoGetClassObject);
2384 /* Now check the locking is working */
2385 /* NOTE: we are accessing the class directly, not through a proxy */
2389 hr = IClassFactory_LockServer(cf, TRUE);
2390 ok_ole_success(hr, IClassFactory_LockServer);
2392 ok_more_than_one_lock();
2394 IClassFactory_LockServer(cf, FALSE);
2395 ok_ole_success(hr, IClassFactory_LockServer);
2399 IClassFactory_Release(cf);
2401 /* wait for shutdown signal */
2402 ret = WaitForSingleObject(heventShutdown, 0);
2403 ok(ret != WAIT_TIMEOUT, "Server didn't shut down\n");
2405 /* try to connect again after SCM has suspended registered class objects */
2406 hr = CoGetClassObject(&CLSID_WineOOPTest, CLSCTX_INPROC_SERVER | CLSCTX_LOCAL_SERVER, NULL,
2407 &IID_IClassFactory, (LPVOID*)&cf);
2408 ok(hr == CO_E_SERVER_STOPPING || /* NT */
2409 hr == S_OK /* Win9x */,
2410 "CoGetClassObject should have returned CO_E_SERVER_STOPPING instead of 0x%08x\n", hr);
2412 hr = CoRevokeClassObject(cookie);
2413 ok_ole_success(hr, CoRevokeClassObject);
2415 CloseHandle(heventShutdown);
2417 process = create_target_process("-Embedding");
2418 ok(process != NULL, "couldn't start local server process, error was %d\n", GetLastError());
2420 ready_event = CreateEvent(NULL, FALSE, FALSE, "Wine COM Test Ready Event");
2421 WaitForSingleObject(ready_event, 1000);
2422 CloseHandle(ready_event);
2424 hr = CoCreateInstance(&CLSID_WineOOPTest, NULL, CLSCTX_LOCAL_SERVER, &IID_IClassFactory, (void **)&cf);
2425 ok_ole_success(hr, CoCreateInstance);
2427 IClassFactory_Release(cf);
2429 hr = CoCreateInstance(&CLSID_WineOOPTest, NULL, CLSCTX_LOCAL_SERVER, &IID_IClassFactory, (void **)&cf);
2430 ok(hr == REGDB_E_CLASSNOTREG, "Second CoCreateInstance on REGCLS_SINGLEUSE object should have failed\n");
2432 quit_event = CreateEvent(NULL, FALSE, FALSE, "Wine COM Test Quit Event");
2433 SetEvent(quit_event);
2435 WaitForSingleObject(process, INFINITE);
2436 CloseHandle(quit_event);
2437 CloseHandle(process);
2443 IGlobalInterfaceTable *git;
2446 static DWORD CALLBACK get_global_interface_proc(LPVOID pv)
2449 struct git_params *params = (struct git_params *)pv;
2452 hr = IGlobalInterfaceTable_GetInterfaceFromGlobal(params->git, params->cookie, &IID_IClassFactory, (void **)&cf);
2453 ok(hr == CO_E_NOTINITIALIZED,
2454 "IGlobalInterfaceTable_GetInterfaceFromGlobal should have failed with error CO_E_NOTINITIALIZED instead of 0x%08x\n",
2458 hr = IGlobalInterfaceTable_GetInterfaceFromGlobal(params->git, params->cookie, &IID_IClassFactory, (void **)&cf);
2459 ok_ole_success(hr, IGlobalInterfaceTable_GetInterfaceFromGlobal);
2461 IGlobalInterfaceTable_Release(params->git);
2468 static void test_globalinterfacetable(void)
2471 IGlobalInterfaceTable *git;
2475 struct git_params params;
2478 hr = CoCreateInstance(&CLSID_StdGlobalInterfaceTable, NULL, CLSCTX_INPROC_SERVER, &IID_IGlobalInterfaceTable, (void **)&git);
2479 ok_ole_success(hr, CoCreateInstance);
2481 hr = IGlobalInterfaceTable_RegisterInterfaceInGlobal(git, (IUnknown *)&Test_ClassFactory, &IID_IClassFactory, &cookie);
2482 ok_ole_success(hr, IGlobalInterfaceTable_RegisterInterfaceInGlobal);
2484 params.cookie = cookie;
2486 /* note: params is on stack so we MUST wait for get_global_interface_proc
2487 * to exit before we can return */
2488 thread = CreateThread(NULL, 0, get_global_interface_proc, ¶ms, 0, &tid);
2490 ret = MsgWaitForMultipleObjects(1, &thread, FALSE, INFINITE, QS_ALLINPUT);
2491 while (ret == WAIT_OBJECT_0 + 1)
2494 while (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
2495 DispatchMessage(&msg);
2496 ret = MsgWaitForMultipleObjects(1, &thread, FALSE, INFINITE, QS_ALLINPUT);
2499 CloseHandle(thread);
2502 static const char *debugstr_iid(REFIID riid)
2504 static char name[256];
2508 LONG name_size = sizeof(name);
2509 StringFromGUID2(riid, bufferW, sizeof(bufferW)/sizeof(bufferW[0]));
2510 WideCharToMultiByte(CP_ACP, 0, bufferW, sizeof(bufferW)/sizeof(bufferW[0]), buffer, sizeof(buffer), NULL, NULL);
2511 if (RegOpenKeyEx(HKEY_CLASSES_ROOT, "Interface", 0, KEY_QUERY_VALUE, &hkeyInterface) != ERROR_SUCCESS)
2513 memcpy(name, buffer, sizeof(buffer));
2516 if (RegQueryValue(hkeyInterface, buffer, name, &name_size) != ERROR_SUCCESS)
2518 memcpy(name, buffer, sizeof(buffer));
2521 RegCloseKey(hkeyInterface);
2526 static HRESULT WINAPI TestChannelHook_QueryInterface(IChannelHook *iface, REFIID riid, void **ppv)
2528 if (IsEqualIID(riid, &IID_IUnknown) || IsEqualIID(riid, &IID_IChannelHook))
2531 IUnknown_AddRef(iface);
2536 return E_NOINTERFACE;
2539 static ULONG WINAPI TestChannelHook_AddRef(IChannelHook *iface)
2544 static ULONG WINAPI TestChannelHook_Release(IChannelHook *iface)
2549 static void WINAPI TestChannelHook_ClientGetSize(
2550 IChannelHook *iface,
2555 SChannelHookCallInfo *info = (SChannelHookCallInfo *)riid;
2556 trace("TestChannelHook_ClientGetBuffer\n");
2557 trace("\t%s method %d\n", debugstr_iid(riid), info->iMethod);
2558 trace("\tcid: %s\n", debugstr_iid(&info->uCausality));
2559 ok(info->cbSize == sizeof(*info), "info->cbSize was %d instead of %d\n", info->cbSize, (int)sizeof(*info));
2560 ok(info->dwServerPid == GetCurrentProcessId(), "info->dwServerPid was 0x%x instead of 0x%x\n", info->dwServerPid, GetCurrentProcessId());
2561 ok(!info->pObject, "info->pObject should be NULL\n");
2562 ok(IsEqualGUID(uExtent, &EXTENTID_WineTest), "uExtent wasn't correct\n");
2567 static void WINAPI TestChannelHook_ClientFillBuffer(
2568 IChannelHook *iface,
2574 SChannelHookCallInfo *info = (SChannelHookCallInfo *)riid;
2575 trace("TestChannelHook_ClientFillBuffer\n");
2576 ok(info->cbSize == sizeof(*info), "info->cbSize was %d instead of %d\n", info->cbSize, (int)sizeof(*info));
2577 ok(info->dwServerPid == GetCurrentProcessId(), "info->dwServerPid was 0x%x instead of 0x%x\n", info->dwServerPid, GetCurrentProcessId());
2578 ok(!info->pObject, "info->pObject should be NULL\n");
2579 ok(IsEqualGUID(uExtent, &EXTENTID_WineTest), "uExtent wasn't correct\n");
2581 *(unsigned char *)pDataBuffer = 0xcc;
2585 static void WINAPI TestChannelHook_ClientNotify(
2586 IChannelHook *iface,
2594 SChannelHookCallInfo *info = (SChannelHookCallInfo *)riid;
2595 trace("TestChannelHook_ClientNotify hrFault = 0x%08x\n", hrFault);
2596 ok(info->cbSize == sizeof(*info), "info->cbSize was %d instead of %d\n", info->cbSize, (int)sizeof(*info));
2597 ok(info->dwServerPid == GetCurrentProcessId(), "info->dwServerPid was 0x%x instead of 0x%x\n", info->dwServerPid, GetCurrentProcessId());
2599 ok(info->pObject != NULL, "info->pObject shouldn't be NULL\n");
2601 ok(IsEqualGUID(uExtent, &EXTENTID_WineTest), "uExtent wasn't correct\n");
2604 static void WINAPI TestChannelHook_ServerNotify(
2605 IChannelHook *iface,
2612 SChannelHookCallInfo *info = (SChannelHookCallInfo *)riid;
2613 trace("TestChannelHook_ServerNotify\n");
2614 ok(info->cbSize == sizeof(*info), "info->cbSize was %d instead of %d\n", info->cbSize, (int)sizeof(*info));
2615 ok(info->dwServerPid == GetCurrentProcessId(), "info->dwServerPid was 0x%x instead of 0x%x\n", info->dwServerPid, GetCurrentProcessId());
2616 ok(info->pObject != NULL, "info->pObject shouldn't be NULL\n");
2617 ok(cbDataSize == 1, "cbDataSize should have been 1 instead of %d\n", cbDataSize);
2618 ok(*(unsigned char *)pDataBuffer == 0xcc, "pDataBuffer should have contained 0xcc instead of 0x%x\n", *(unsigned char *)pDataBuffer);
2619 ok(IsEqualGUID(uExtent, &EXTENTID_WineTest), "uExtent wasn't correct\n");
2622 static void WINAPI TestChannelHook_ServerGetSize(
2623 IChannelHook *iface,
2629 SChannelHookCallInfo *info = (SChannelHookCallInfo *)riid;
2630 trace("TestChannelHook_ServerGetSize\n");
2631 trace("\t%s method %d\n", debugstr_iid(riid), info->iMethod);
2632 ok(info->cbSize == sizeof(*info), "info->cbSize was %d instead of %d\n", info->cbSize, (int)sizeof(*info));
2633 ok(info->dwServerPid == GetCurrentProcessId(), "info->dwServerPid was 0x%x instead of 0x%x\n", info->dwServerPid, GetCurrentProcessId());
2634 ok(info->pObject != NULL, "info->pObject shouldn't be NULL\n");
2635 ok(IsEqualGUID(uExtent, &EXTENTID_WineTest), "uExtent wasn't correct\n");
2636 if (hrFault != S_OK)
2637 trace("\thrFault = 0x%08x\n", hrFault);
2642 static void WINAPI TestChannelHook_ServerFillBuffer(
2643 IChannelHook *iface,
2650 trace("TestChannelHook_ServerFillBuffer\n");
2651 ok(0, "TestChannelHook_ServerFillBuffer shouldn't be called\n");
2654 static const IChannelHookVtbl TestChannelHookVtbl =
2656 TestChannelHook_QueryInterface,
2657 TestChannelHook_AddRef,
2658 TestChannelHook_Release,
2659 TestChannelHook_ClientGetSize,
2660 TestChannelHook_ClientFillBuffer,
2661 TestChannelHook_ClientNotify,
2662 TestChannelHook_ServerNotify,
2663 TestChannelHook_ServerGetSize,
2664 TestChannelHook_ServerFillBuffer,
2667 static IChannelHook TestChannelHook = { &TestChannelHookVtbl };
2669 static void test_channel_hook(void)
2671 IStream *pStream = NULL;
2672 IClassFactory *cf = NULL;
2674 IUnknown *proxy = NULL;
2678 hr = CoRegisterChannelHook(&EXTENTID_WineTest, &TestChannelHook);
2679 ok_ole_success(hr, CoRegisterChannelHook);
2681 hr = CoRegisterMessageFilter(&MessageFilter, NULL);
2682 ok_ole_success(hr, CoRegisterMessageFilter);
2686 hr = CreateStreamOnHGlobal(NULL, TRUE, &pStream);
2687 ok_ole_success(hr, CreateStreamOnHGlobal);
2688 tid = start_host_object2(pStream, &IID_IClassFactory, (IUnknown*)&Test_ClassFactory, MSHLFLAGS_NORMAL, &MessageFilter, &thread);
2690 ok_more_than_one_lock();
2692 IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
2693 hr = CoUnmarshalInterface(pStream, &IID_IClassFactory, (void **)&cf);
2694 ok_ole_success(hr, CoUnmarshalInterface);
2695 IStream_Release(pStream);
2697 ok_more_than_one_lock();
2699 hr = IClassFactory_CreateInstance(cf, NULL, &IID_IUnknown, (LPVOID*)&proxy);
2700 ok_ole_success(hr, IClassFactory_CreateInstance);
2701 IUnknown_Release(proxy);
2703 IClassFactory_Release(cf);
2707 end_host_object(tid, thread);
2709 hr = CoRegisterMessageFilter(NULL, NULL);
2710 ok_ole_success(hr, CoRegisterMessageFilter);
2716 HMODULE hOle32 = GetModuleHandle("ole32");
2720 if (!(pCoInitializeEx = (void*)GetProcAddress(hOle32, "CoInitializeEx"))) goto no_test;
2722 argc = winetest_get_mainargs( &argv );
2723 if (argc > 2 && (!strcmp(argv[2], "-Embedding")))
2725 pCoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
2726 test_register_local_server();
2732 /* register a window class used in several tests */
2733 memset(&wndclass, 0, sizeof(wndclass));
2734 wndclass.lpfnWndProc = window_proc;
2735 wndclass.lpszClassName = "WineCOMTest";
2736 RegisterClass(&wndclass);
2738 test_cocreateinstance_proxy();
2740 pCoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
2742 /* FIXME: test CoCreateInstanceEx */
2744 /* lifecycle management and marshaling tests */
2745 test_no_marshaler();
2746 test_normal_marshal_and_release();
2747 test_normal_marshal_and_unmarshal();
2748 test_marshal_and_unmarshal_invalid();
2749 test_same_apartment_unmarshal_failure();
2750 test_interthread_marshal_and_unmarshal();
2751 test_proxy_marshal_and_unmarshal();
2752 test_proxy_marshal_and_unmarshal2();
2753 test_marshal_stub_apartment_shutdown();
2754 test_marshal_proxy_apartment_shutdown();
2755 test_marshal_proxy_mta_apartment_shutdown();
2756 test_no_couninitialize_server();
2757 test_no_couninitialize_client();
2758 test_tableweak_marshal_and_unmarshal_twice();
2759 test_tableweak_marshal_releasedata1();
2760 test_tableweak_marshal_releasedata2();
2761 test_tablestrong_marshal_and_unmarshal_twice();
2762 test_lock_object_external();
2763 test_disconnect_stub();
2764 test_normal_marshal_and_unmarshal_twice();
2765 test_hresult_marshaling();
2766 test_proxy_used_in_wrong_thread();
2767 test_message_filter();
2768 test_bad_marshal_stream();
2769 test_proxy_interfaces();
2770 test_stubbuffer(&IID_IClassFactory);
2771 test_proxybuffer(&IID_IClassFactory);
2772 test_message_reentrancy();
2773 test_call_from_message();
2774 test_WM_QUIT_handling();
2775 test_freethreadedmarshaler();
2776 test_inproc_handler();
2777 test_handler_marshaling();
2778 test_client_security();
2780 test_local_server();
2782 test_globalinterfacetable();
2784 /* must be last test as channel hooks can't be unregistered */
2785 test_channel_hook();
2791 trace("You need DCOM95 installed to run this test\n");