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
32 #include "wine/test.h"
34 /* functions that are not present on all versions of Windows */
35 HRESULT (WINAPI * pCoInitializeEx)(LPVOID lpReserved, DWORD dwCoInit);
37 /* helper macros to make tests a bit leaner */
38 #define ok_more_than_one_lock() ok(cLocks > 0, "Number of locks should be > 0, but actually is %d\n", cLocks)
39 #define ok_no_locks() ok(cLocks == 0, "Number of locks should be 0, but actually is %d\n", cLocks)
40 #define ok_ole_success(hr, func) ok(hr == S_OK, #func " failed with error 0x%08x\n", hr)
42 static const IID IID_IWineTest =
47 {0xa1, 0xa2, 0x5d, 0x5a, 0x36, 0x54, 0xd3, 0xbd}
48 }; /* 5201163f-8164-4fd0-a1a2-5d5a3654d3bd */
50 #define EXTENTID_WineTest IID_IWineTest
52 static void test_cocreateinstance_proxy(void)
58 pCoInitializeEx(NULL, COINIT_MULTITHREADED);
60 hr = CoCreateInstance(&CLSID_ShellDesktop, NULL, CLSCTX_INPROC, &IID_IUnknown, (void **)&pProxy);
61 ok_ole_success(hr, CoCreateInstance);
62 hr = IUnknown_QueryInterface(pProxy, &IID_IMultiQI, (void **)&pMQI);
64 ok(hr == S_OK, "created object is not a proxy, so was created in the wrong apartment\n");
66 IMultiQI_Release(pMQI);
67 IUnknown_Release(pProxy);
72 static const LARGE_INTEGER ullZero;
75 static void LockModule(void)
77 InterlockedIncrement(&cLocks);
80 static void UnlockModule(void)
82 InterlockedDecrement(&cLocks);
86 static HRESULT WINAPI Test_IUnknown_QueryInterface(
91 if (ppvObj == NULL) return E_POINTER;
93 if (IsEqualGUID(riid, &IID_IUnknown))
95 *ppvObj = (LPVOID)iface;
96 IUnknown_AddRef(iface);
101 return E_NOINTERFACE;
104 static ULONG WINAPI Test_IUnknown_AddRef(LPUNKNOWN iface)
107 return 2; /* non-heap-based object */
110 static ULONG WINAPI Test_IUnknown_Release(LPUNKNOWN iface)
113 return 1; /* non-heap-based object */
116 static const IUnknownVtbl TestUnknown_Vtbl =
118 Test_IUnknown_QueryInterface,
119 Test_IUnknown_AddRef,
120 Test_IUnknown_Release,
123 static IUnknown Test_Unknown = { &TestUnknown_Vtbl };
126 static HRESULT WINAPI Test_IClassFactory_QueryInterface(
127 LPCLASSFACTORY iface,
131 if (ppvObj == NULL) return E_POINTER;
133 if (IsEqualGUID(riid, &IID_IUnknown) ||
134 IsEqualGUID(riid, &IID_IClassFactory))
136 *ppvObj = (LPVOID)iface;
137 IClassFactory_AddRef(iface);
142 return E_NOINTERFACE;
145 static ULONG WINAPI Test_IClassFactory_AddRef(LPCLASSFACTORY iface)
148 return 2; /* non-heap-based object */
151 static ULONG WINAPI Test_IClassFactory_Release(LPCLASSFACTORY iface)
154 return 1; /* non-heap-based object */
157 static HRESULT WINAPI Test_IClassFactory_CreateInstance(
158 LPCLASSFACTORY iface,
163 if (pUnkOuter) return CLASS_E_NOAGGREGATION;
164 return IUnknown_QueryInterface((IUnknown*)&Test_Unknown, riid, ppvObj);
167 static HRESULT WINAPI Test_IClassFactory_LockServer(
168 LPCLASSFACTORY iface,
174 static const IClassFactoryVtbl TestClassFactory_Vtbl =
176 Test_IClassFactory_QueryInterface,
177 Test_IClassFactory_AddRef,
178 Test_IClassFactory_Release,
179 Test_IClassFactory_CreateInstance,
180 Test_IClassFactory_LockServer
183 static IClassFactory Test_ClassFactory = { &TestClassFactory_Vtbl };
185 #define RELEASEMARSHALDATA WM_USER
187 struct host_object_data
192 MSHLFLAGS marshal_flags;
193 HANDLE marshal_event;
194 IMessageFilter *filter;
197 static DWORD CALLBACK host_object_proc(LPVOID p)
199 struct host_object_data *data = (struct host_object_data *)p;
203 pCoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
207 IMessageFilter * prev_filter = NULL;
208 hr = CoRegisterMessageFilter(data->filter, &prev_filter);
209 if (prev_filter) IMessageFilter_Release(prev_filter);
210 ok_ole_success(hr, CoRegisterMessageFilter);
213 hr = CoMarshalInterface(data->stream, &data->iid, data->object, MSHCTX_INPROC, NULL, data->marshal_flags);
214 ok_ole_success(hr, CoMarshalInterface);
216 /* force the message queue to be created before signaling parent thread */
217 PeekMessage(&msg, NULL, WM_USER, WM_USER, PM_NOREMOVE);
219 SetEvent(data->marshal_event);
221 while (GetMessage(&msg, NULL, 0, 0))
223 if (msg.hwnd == NULL && msg.message == RELEASEMARSHALDATA)
225 trace("releasing marshal data\n");
226 CoReleaseMarshalData(data->stream);
227 SetEvent((HANDLE)msg.lParam);
230 DispatchMessage(&msg);
233 HeapFree(GetProcessHeap(), 0, data);
240 static DWORD start_host_object2(IStream *stream, REFIID riid, IUnknown *object, MSHLFLAGS marshal_flags, IMessageFilter *filter, HANDLE *thread)
243 HANDLE marshal_event = CreateEvent(NULL, FALSE, FALSE, NULL);
244 struct host_object_data *data = HeapAlloc(GetProcessHeap(), 0, sizeof(*data));
246 data->stream = stream;
248 data->object = object;
249 data->marshal_flags = marshal_flags;
250 data->marshal_event = marshal_event;
251 data->filter = filter;
253 *thread = CreateThread(NULL, 0, host_object_proc, data, 0, &tid);
255 /* wait for marshaling to complete before returning */
256 WaitForSingleObject(marshal_event, INFINITE);
257 CloseHandle(marshal_event);
262 static DWORD start_host_object(IStream *stream, REFIID riid, IUnknown *object, MSHLFLAGS marshal_flags, HANDLE *thread)
264 return start_host_object2(stream, riid, object, marshal_flags, NULL, thread);
267 /* asks thread to release the marshal data because it has to be done by the
268 * same thread that marshaled the interface in the first place. */
269 static void release_host_object(DWORD tid)
271 HANDLE event = CreateEvent(NULL, FALSE, FALSE, NULL);
272 PostThreadMessage(tid, RELEASEMARSHALDATA, 0, (LPARAM)event);
273 WaitForSingleObject(event, INFINITE);
277 static void end_host_object(DWORD tid, HANDLE thread)
279 BOOL ret = PostThreadMessage(tid, WM_QUIT, 0, 0);
280 ok(ret, "PostThreadMessage failed with error %d\n", GetLastError());
281 /* be careful of races - don't return until hosting thread has terminated */
282 WaitForSingleObject(thread, INFINITE);
286 /* tests failure case of interface not having a marshaler specified in the
288 static void test_no_marshaler(void)
293 hr = CreateStreamOnHGlobal(NULL, TRUE, &pStream);
294 ok_ole_success(hr, CreateStreamOnHGlobal);
295 hr = CoMarshalInterface(pStream, &IID_IWineTest, (IUnknown*)&Test_ClassFactory, MSHCTX_INPROC, NULL, MSHLFLAGS_NORMAL);
296 ok(hr == E_NOINTERFACE, "CoMarshalInterface should have returned E_NOINTERFACE instead of 0x%08x\n", hr);
298 IStream_Release(pStream);
301 /* tests normal marshal and then release without unmarshaling */
302 static void test_normal_marshal_and_release(void)
305 IStream *pStream = NULL;
309 hr = CreateStreamOnHGlobal(NULL, TRUE, &pStream);
310 ok_ole_success(hr, CreateStreamOnHGlobal);
311 hr = CoMarshalInterface(pStream, &IID_IClassFactory, (IUnknown*)&Test_ClassFactory, MSHCTX_INPROC, NULL, MSHLFLAGS_NORMAL);
312 ok_ole_success(hr, CoMarshalInterface);
314 ok_more_than_one_lock();
316 IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
317 hr = CoReleaseMarshalData(pStream);
318 ok_ole_success(hr, CoReleaseMarshalData);
319 IStream_Release(pStream);
324 /* tests success case of a same-thread marshal and unmarshal */
325 static void test_normal_marshal_and_unmarshal(void)
328 IStream *pStream = NULL;
329 IUnknown *pProxy = NULL;
333 hr = CreateStreamOnHGlobal(NULL, TRUE, &pStream);
334 ok_ole_success(hr, CreateStreamOnHGlobal);
335 hr = CoMarshalInterface(pStream, &IID_IClassFactory, (IUnknown*)&Test_ClassFactory, MSHCTX_INPROC, NULL, MSHLFLAGS_NORMAL);
336 ok_ole_success(hr, CoMarshalInterface);
338 ok_more_than_one_lock();
340 IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
341 hr = CoUnmarshalInterface(pStream, &IID_IClassFactory, (void **)&pProxy);
342 ok_ole_success(hr, CoUnmarshalInterface);
343 IStream_Release(pStream);
345 ok_more_than_one_lock();
347 IUnknown_Release(pProxy);
352 /* tests failure case of unmarshaling a freed object */
353 static void test_marshal_and_unmarshal_invalid(void)
356 IStream *pStream = NULL;
357 IClassFactory *pProxy = NULL;
364 hr = CreateStreamOnHGlobal(NULL, TRUE, &pStream);
365 ok_ole_success(hr, CreateStreamOnHGlobal);
366 tid = start_host_object(pStream, &IID_IClassFactory, (IUnknown*)&Test_ClassFactory, MSHLFLAGS_NORMAL, &thread);
368 ok_more_than_one_lock();
370 IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
371 hr = CoReleaseMarshalData(pStream);
372 ok_ole_success(hr, CoReleaseMarshalData);
376 IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
377 hr = CoUnmarshalInterface(pStream, &IID_IClassFactory, (void **)&pProxy);
378 todo_wine { ok_ole_success(hr, CoUnmarshalInterface); }
384 hr = IClassFactory_CreateInstance(pProxy, NULL, &IID_IUnknown, &dummy);
385 ok(hr == RPC_E_DISCONNECTED, "Remote call should have returned RPC_E_DISCONNECTED, instead of 0x%08x\n", hr);
387 IClassFactory_Release(pProxy);
390 IStream_Release(pStream);
392 end_host_object(tid, thread);
395 /* tests success case of an interthread marshal */
396 static void test_interthread_marshal_and_unmarshal(void)
399 IStream *pStream = NULL;
400 IUnknown *pProxy = NULL;
406 hr = CreateStreamOnHGlobal(NULL, TRUE, &pStream);
407 ok_ole_success(hr, CreateStreamOnHGlobal);
408 tid = start_host_object(pStream, &IID_IClassFactory, (IUnknown*)&Test_ClassFactory, MSHLFLAGS_NORMAL, &thread);
410 ok_more_than_one_lock();
412 IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
413 hr = CoUnmarshalInterface(pStream, &IID_IClassFactory, (void **)&pProxy);
414 ok_ole_success(hr, CoUnmarshalInterface);
415 IStream_Release(pStream);
417 ok_more_than_one_lock();
419 IUnknown_Release(pProxy);
423 end_host_object(tid, thread);
426 /* the number of external references that Wine's proxy manager normally gives
427 * out, so we can test the border case of running out of references */
428 #define NORMALEXTREFS 5
430 /* tests success case of an interthread marshal and then marshaling the proxy */
431 static void test_proxy_marshal_and_unmarshal(void)
434 IStream *pStream = NULL;
435 IUnknown *pProxy = NULL;
436 IUnknown *pProxy2 = NULL;
443 hr = CreateStreamOnHGlobal(NULL, TRUE, &pStream);
444 ok_ole_success(hr, CreateStreamOnHGlobal);
445 tid = start_host_object(pStream, &IID_IClassFactory, (IUnknown*)&Test_ClassFactory, MSHLFLAGS_NORMAL, &thread);
447 ok_more_than_one_lock();
449 IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
450 hr = CoUnmarshalInterface(pStream, &IID_IClassFactory, (void **)&pProxy);
451 ok_ole_success(hr, CoUnmarshalInterface);
453 ok_more_than_one_lock();
455 IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
456 /* marshal the proxy */
457 hr = CoMarshalInterface(pStream, &IID_IClassFactory, pProxy, MSHCTX_INPROC, NULL, MSHLFLAGS_NORMAL);
458 ok_ole_success(hr, CoMarshalInterface);
460 ok_more_than_one_lock();
462 /* marshal 5 more times to exhaust the normal external references of 5 */
463 for (i = 0; i < NORMALEXTREFS; i++)
465 hr = CoMarshalInterface(pStream, &IID_IClassFactory, pProxy, MSHCTX_INPROC, NULL, MSHLFLAGS_NORMAL);
466 ok_ole_success(hr, CoMarshalInterface);
469 ok_more_than_one_lock();
471 /* release the original proxy to test that we successfully keep the
472 * original object alive */
473 IUnknown_Release(pProxy);
475 IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
476 hr = CoUnmarshalInterface(pStream, &IID_IClassFactory, (void **)&pProxy2);
477 ok_ole_success(hr, CoUnmarshalInterface);
479 ok_more_than_one_lock();
481 /* now the proxies should be as follows:
482 * pProxy2 -> &Test_ClassFactory
483 * they should NOT be as follows:
484 * pProxy -> &Test_ClassFactory
486 * the above can only really be tested by looking in +ole traces
489 IUnknown_Release(pProxy2);
491 /* unmarshal all of the proxies to check that the object stub still exists */
492 for (i = 0; i < NORMALEXTREFS; i++)
494 hr = CoUnmarshalInterface(pStream, &IID_IClassFactory, (void **)&pProxy2);
495 ok_ole_success(hr, CoUnmarshalInterface);
497 IUnknown_Release(pProxy2);
502 IStream_Release(pStream);
504 end_host_object(tid, thread);
507 /* tests success case of an interthread marshal and then marshaling the proxy
508 * using an iid that hasn't previously been unmarshaled */
509 static void test_proxy_marshal_and_unmarshal2(void)
512 IStream *pStream = NULL;
513 IUnknown *pProxy = NULL;
514 IUnknown *pProxy2 = NULL;
520 hr = CreateStreamOnHGlobal(NULL, TRUE, &pStream);
521 ok_ole_success(hr, CreateStreamOnHGlobal);
522 tid = start_host_object(pStream, &IID_IUnknown, (IUnknown*)&Test_ClassFactory, MSHLFLAGS_NORMAL, &thread);
524 ok_more_than_one_lock();
526 IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
527 hr = CoUnmarshalInterface(pStream, &IID_IUnknown, (void **)&pProxy);
528 ok_ole_success(hr, CoUnmarshalInterface);
530 ok_more_than_one_lock();
532 IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
533 /* marshal the proxy */
534 hr = CoMarshalInterface(pStream, &IID_IClassFactory, pProxy, MSHCTX_INPROC, NULL, MSHLFLAGS_NORMAL);
535 ok_ole_success(hr, CoMarshalInterface);
537 ok_more_than_one_lock();
539 IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
540 /* unmarshal the second proxy to the object */
541 hr = CoUnmarshalInterface(pStream, &IID_IClassFactory, (void **)&pProxy2);
542 ok_ole_success(hr, CoUnmarshalInterface);
543 IStream_Release(pStream);
545 /* now the proxies should be as follows:
546 * pProxy -> &Test_ClassFactory
547 * pProxy2 -> &Test_ClassFactory
548 * they should NOT be as follows:
549 * pProxy -> &Test_ClassFactory
551 * the above can only really be tested by looking in +ole traces
554 ok_more_than_one_lock();
556 IUnknown_Release(pProxy);
558 ok_more_than_one_lock();
560 IUnknown_Release(pProxy2);
564 end_host_object(tid, thread);
567 /* tests that stubs are released when the containing apartment is destroyed */
568 static void test_marshal_stub_apartment_shutdown(void)
571 IStream *pStream = NULL;
572 IUnknown *pProxy = NULL;
578 hr = CreateStreamOnHGlobal(NULL, TRUE, &pStream);
579 ok_ole_success(hr, CreateStreamOnHGlobal);
580 tid = start_host_object(pStream, &IID_IClassFactory, (IUnknown*)&Test_ClassFactory, MSHLFLAGS_NORMAL, &thread);
582 ok_more_than_one_lock();
584 IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
585 hr = CoUnmarshalInterface(pStream, &IID_IClassFactory, (void **)&pProxy);
586 ok_ole_success(hr, CoUnmarshalInterface);
587 IStream_Release(pStream);
589 ok_more_than_one_lock();
591 end_host_object(tid, thread);
595 IUnknown_Release(pProxy);
600 /* tests that proxies are released when the containing apartment is destroyed */
601 static void test_marshal_proxy_apartment_shutdown(void)
604 IStream *pStream = NULL;
605 IUnknown *pProxy = NULL;
611 hr = CreateStreamOnHGlobal(NULL, TRUE, &pStream);
612 ok_ole_success(hr, CreateStreamOnHGlobal);
613 tid = start_host_object(pStream, &IID_IClassFactory, (IUnknown*)&Test_ClassFactory, MSHLFLAGS_NORMAL, &thread);
615 ok_more_than_one_lock();
617 IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
618 hr = CoUnmarshalInterface(pStream, &IID_IClassFactory, (void **)&pProxy);
619 ok_ole_success(hr, CoUnmarshalInterface);
620 IStream_Release(pStream);
622 ok_more_than_one_lock();
628 IUnknown_Release(pProxy);
632 end_host_object(tid, thread);
634 pCoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
637 /* tests that proxies are released when the containing mta apartment is destroyed */
638 static void test_marshal_proxy_mta_apartment_shutdown(void)
641 IStream *pStream = NULL;
642 IUnknown *pProxy = NULL;
647 pCoInitializeEx(NULL, COINIT_MULTITHREADED);
651 hr = CreateStreamOnHGlobal(NULL, TRUE, &pStream);
652 ok_ole_success(hr, CreateStreamOnHGlobal);
653 tid = start_host_object(pStream, &IID_IClassFactory, (IUnknown*)&Test_ClassFactory, MSHLFLAGS_NORMAL, &thread);
655 ok_more_than_one_lock();
657 IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
658 hr = CoUnmarshalInterface(pStream, &IID_IClassFactory, (void **)&pProxy);
659 ok_ole_success(hr, CoUnmarshalInterface);
660 IStream_Release(pStream);
662 ok_more_than_one_lock();
668 IUnknown_Release(pProxy);
672 end_host_object(tid, thread);
674 pCoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
680 HANDLE marshal_event;
681 HANDLE unmarshal_event;
684 /* helper for test_no_couninitialize_server */
685 static DWORD CALLBACK no_couninitialize_server_proc(LPVOID p)
687 struct ncu_params *ncu_params = (struct ncu_params *)p;
690 pCoInitializeEx(NULL, COINIT_MULTITHREADED);
692 hr = CoMarshalInterface(ncu_params->stream, &IID_IClassFactory, (IUnknown*)&Test_ClassFactory, MSHCTX_INPROC, NULL, MSHLFLAGS_NORMAL);
693 ok_ole_success(hr, CoMarshalInterface);
695 SetEvent(ncu_params->marshal_event);
697 WaitForSingleObject(ncu_params->unmarshal_event, INFINITE);
699 /* die without calling CoUninitialize */
704 /* tests apartment that an apartment with a stub is released without deadlock
705 * if the owning thread exits */
706 static void test_no_couninitialize_server(void)
709 IStream *pStream = NULL;
710 IUnknown *pProxy = NULL;
713 struct ncu_params ncu_params;
717 ncu_params.marshal_event = CreateEvent(NULL, TRUE, FALSE, NULL);
718 ncu_params.unmarshal_event = CreateEvent(NULL, TRUE, FALSE, NULL);
720 hr = CreateStreamOnHGlobal(NULL, TRUE, &pStream);
721 ok_ole_success(hr, CreateStreamOnHGlobal);
722 ncu_params.stream = pStream;
724 thread = CreateThread(NULL, 0, no_couninitialize_server_proc, &ncu_params, 0, &tid);
726 WaitForSingleObject(ncu_params.marshal_event, INFINITE);
727 ok_more_than_one_lock();
729 IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
730 hr = CoUnmarshalInterface(pStream, &IID_IClassFactory, (void **)&pProxy);
731 ok_ole_success(hr, CoUnmarshalInterface);
732 IStream_Release(pStream);
734 ok_more_than_one_lock();
736 SetEvent(ncu_params.unmarshal_event);
737 WaitForSingleObject(thread, INFINITE);
742 CloseHandle(ncu_params.marshal_event);
743 CloseHandle(ncu_params.unmarshal_event);
745 IUnknown_Release(pProxy);
750 /* STA -> STA call during DLL_THREAD_DETACH */
751 static DWORD CALLBACK no_couninitialize_client_proc(LPVOID p)
753 struct ncu_params *ncu_params = (struct ncu_params *)p;
755 IUnknown *pProxy = NULL;
757 pCoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
759 hr = CoUnmarshalInterface(ncu_params->stream, &IID_IClassFactory, (void **)&pProxy);
760 ok_ole_success(hr, CoUnmarshalInterface);
761 IStream_Release(ncu_params->stream);
763 ok_more_than_one_lock();
765 /* die without calling CoUninitialize */
770 /* tests STA -> STA call during DLL_THREAD_DETACH doesn't deadlock */
771 static void test_no_couninitialize_client(void)
774 IStream *pStream = NULL;
779 struct ncu_params ncu_params;
783 hr = CreateStreamOnHGlobal(NULL, TRUE, &pStream);
784 ok_ole_success(hr, CreateStreamOnHGlobal);
785 ncu_params.stream = pStream;
787 /* NOTE: assumes start_host_object uses an STA to host the object, as MTAs
788 * always deadlock when called from within DllMain */
789 host_tid = start_host_object(pStream, &IID_IClassFactory, (IUnknown *)&Test_ClassFactory, MSHLFLAGS_NORMAL, &host_thread);
790 IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
792 ok_more_than_one_lock();
794 thread = CreateThread(NULL, 0, no_couninitialize_client_proc, &ncu_params, 0, &tid);
796 WaitForSingleObject(thread, INFINITE);
801 end_host_object(host_tid, host_thread);
804 /* tests success case of a same-thread table-weak marshal, unmarshal, unmarshal */
805 static void test_tableweak_marshal_and_unmarshal_twice(void)
808 IStream *pStream = NULL;
809 IUnknown *pProxy1 = NULL;
810 IUnknown *pProxy2 = NULL;
816 hr = CreateStreamOnHGlobal(NULL, TRUE, &pStream);
817 ok_ole_success(hr, CreateStreamOnHGlobal);
818 tid = start_host_object(pStream, &IID_IClassFactory, (IUnknown*)&Test_ClassFactory, MSHLFLAGS_TABLEWEAK, &thread);
820 ok_more_than_one_lock();
822 IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
823 hr = CoUnmarshalInterface(pStream, &IID_IClassFactory, (void **)&pProxy1);
824 ok_ole_success(hr, CoUnmarshalInterface);
826 ok_more_than_one_lock();
828 IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
829 hr = CoUnmarshalInterface(pStream, &IID_IClassFactory, (void **)&pProxy2);
830 IStream_Release(pStream);
831 ok_ole_success(hr, CoUnmarshalInterface);
833 ok_more_than_one_lock();
835 IUnknown_Release(pProxy1);
836 IUnknown_Release(pProxy2);
838 /* this line is shows the difference between weak and strong table marshaling:
839 * weak has cLocks == 0
840 * strong has cLocks > 0 */
843 end_host_object(tid, thread);
846 /* tests releasing after unmarshaling one object */
847 static void test_tableweak_marshal_releasedata1(void)
850 IStream *pStream = NULL;
851 IUnknown *pProxy1 = NULL;
852 IUnknown *pProxy2 = NULL;
858 hr = CreateStreamOnHGlobal(NULL, TRUE, &pStream);
859 ok_ole_success(hr, CreateStreamOnHGlobal);
860 tid = start_host_object(pStream, &IID_IClassFactory, (IUnknown*)&Test_ClassFactory, MSHLFLAGS_TABLEWEAK, &thread);
862 ok_more_than_one_lock();
864 IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
865 hr = CoUnmarshalInterface(pStream, &IID_IClassFactory, (void **)&pProxy1);
866 ok_ole_success(hr, CoUnmarshalInterface);
868 ok_more_than_one_lock();
870 /* release the remaining reference on the object by calling
871 * CoReleaseMarshalData in the hosting thread */
872 IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
873 release_host_object(tid);
875 ok_more_than_one_lock();
877 IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
878 hr = CoUnmarshalInterface(pStream, &IID_IClassFactory, (void **)&pProxy2);
879 ok_ole_success(hr, CoUnmarshalInterface);
880 IStream_Release(pStream);
882 ok_more_than_one_lock();
884 IUnknown_Release(pProxy1);
886 IUnknown_Release(pProxy2);
888 /* this line is shows the difference between weak and strong table marshaling:
889 * weak has cLocks == 0
890 * strong has cLocks > 0 */
893 end_host_object(tid, thread);
896 /* tests releasing after unmarshaling one object */
897 static void test_tableweak_marshal_releasedata2(void)
900 IStream *pStream = NULL;
901 IUnknown *pProxy = NULL;
907 hr = CreateStreamOnHGlobal(NULL, TRUE, &pStream);
908 ok_ole_success(hr, CreateStreamOnHGlobal);
909 tid = start_host_object(pStream, &IID_IClassFactory, (IUnknown*)&Test_ClassFactory, MSHLFLAGS_TABLEWEAK, &thread);
911 ok_more_than_one_lock();
913 /* release the remaining reference on the object by calling
914 * CoReleaseMarshalData in the hosting thread */
915 IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
916 release_host_object(tid);
920 IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
921 hr = CoUnmarshalInterface(pStream, &IID_IClassFactory, (void **)&pProxy);
924 ok(hr == CO_E_OBJNOTREG,
925 "CoUnmarshalInterface should have failed with CO_E_OBJNOTREG, but returned 0x%08x instead\n",
928 IStream_Release(pStream);
932 end_host_object(tid, thread);
935 /* tests success case of a same-thread table-strong marshal, unmarshal, unmarshal */
936 static void test_tablestrong_marshal_and_unmarshal_twice(void)
939 IStream *pStream = NULL;
940 IUnknown *pProxy1 = NULL;
941 IUnknown *pProxy2 = NULL;
947 hr = CreateStreamOnHGlobal(NULL, TRUE, &pStream);
948 ok_ole_success(hr, CreateStreamOnHGlobal);
949 tid = start_host_object(pStream, &IID_IClassFactory, (IUnknown*)&Test_ClassFactory, MSHLFLAGS_TABLESTRONG, &thread);
951 ok_more_than_one_lock();
953 IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
954 hr = CoUnmarshalInterface(pStream, &IID_IClassFactory, (void **)&pProxy1);
955 ok_ole_success(hr, CoUnmarshalInterface);
957 ok_more_than_one_lock();
959 IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
960 hr = CoUnmarshalInterface(pStream, &IID_IClassFactory, (void **)&pProxy2);
961 ok_ole_success(hr, CoUnmarshalInterface);
963 ok_more_than_one_lock();
965 if (pProxy1) IUnknown_Release(pProxy1);
966 if (pProxy2) IUnknown_Release(pProxy2);
968 /* this line is shows the difference between weak and strong table marshaling:
969 * weak has cLocks == 0
970 * strong has cLocks > 0 */
971 ok_more_than_one_lock();
973 /* release the remaining reference on the object by calling
974 * CoReleaseMarshalData in the hosting thread */
975 IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
976 release_host_object(tid);
977 IStream_Release(pStream);
981 end_host_object(tid, thread);
984 /* tests CoLockObjectExternal */
985 static void test_lock_object_external(void)
988 IStream *pStream = NULL;
992 /* test the stub manager creation aspect of CoLockObjectExternal when the
993 * object hasn't been marshaled yet */
994 CoLockObjectExternal((IUnknown*)&Test_ClassFactory, TRUE, TRUE);
996 ok_more_than_one_lock();
998 CoDisconnectObject((IUnknown*)&Test_ClassFactory, 0);
1002 /* test our empty stub manager being handled correctly in
1003 * CoMarshalInterface */
1004 CoLockObjectExternal((IUnknown*)&Test_ClassFactory, TRUE, TRUE);
1006 hr = CreateStreamOnHGlobal(NULL, TRUE, &pStream);
1007 ok_ole_success(hr, CreateStreamOnHGlobal);
1008 hr = CoMarshalInterface(pStream, &IID_IClassFactory, (IUnknown*)&Test_ClassFactory, MSHCTX_INPROC, NULL, MSHLFLAGS_NORMAL);
1009 ok_ole_success(hr, CoMarshalInterface);
1011 CoLockObjectExternal((IUnknown*)&Test_ClassFactory, TRUE, TRUE);
1013 ok_more_than_one_lock();
1015 IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
1016 hr = CoReleaseMarshalData(pStream);
1017 ok_ole_success(hr, CoReleaseMarshalData);
1018 IStream_Release(pStream);
1020 ok_more_than_one_lock();
1022 CoLockObjectExternal((IUnknown*)&Test_ClassFactory, FALSE, TRUE);
1024 ok_more_than_one_lock();
1026 CoLockObjectExternal((IUnknown*)&Test_ClassFactory, FALSE, TRUE);
1031 /* tests disconnecting stubs */
1032 static void test_disconnect_stub(void)
1035 IStream *pStream = NULL;
1039 hr = CreateStreamOnHGlobal(NULL, TRUE, &pStream);
1040 ok_ole_success(hr, CreateStreamOnHGlobal);
1041 hr = CoMarshalInterface(pStream, &IID_IClassFactory, (IUnknown*)&Test_ClassFactory, MSHCTX_INPROC, NULL, MSHLFLAGS_NORMAL);
1042 ok_ole_success(hr, CoMarshalInterface);
1044 CoLockObjectExternal((IUnknown*)&Test_ClassFactory, TRUE, TRUE);
1046 ok_more_than_one_lock();
1048 IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
1049 hr = CoReleaseMarshalData(pStream);
1050 ok_ole_success(hr, CoReleaseMarshalData);
1051 IStream_Release(pStream);
1053 ok_more_than_one_lock();
1055 CoDisconnectObject((IUnknown*)&Test_ClassFactory, 0);
1060 /* tests failure case of a same-thread marshal and unmarshal twice */
1061 static void test_normal_marshal_and_unmarshal_twice(void)
1064 IStream *pStream = NULL;
1065 IUnknown *pProxy1 = NULL;
1066 IUnknown *pProxy2 = NULL;
1070 hr = CreateStreamOnHGlobal(NULL, TRUE, &pStream);
1071 ok_ole_success(hr, CreateStreamOnHGlobal);
1072 hr = CoMarshalInterface(pStream, &IID_IClassFactory, (IUnknown*)&Test_ClassFactory, MSHCTX_INPROC, NULL, MSHLFLAGS_NORMAL);
1073 ok_ole_success(hr, CoMarshalInterface);
1075 ok_more_than_one_lock();
1077 IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
1078 hr = CoUnmarshalInterface(pStream, &IID_IClassFactory, (void **)&pProxy1);
1079 ok_ole_success(hr, CoUnmarshalInterface);
1081 ok_more_than_one_lock();
1083 IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
1084 hr = CoUnmarshalInterface(pStream, &IID_IClassFactory, (void **)&pProxy2);
1085 ok(hr == CO_E_OBJNOTCONNECTED,
1086 "CoUnmarshalInterface should have failed with error CO_E_OBJNOTCONNECTED for double unmarshal, instead of 0x%08x\n", hr);
1088 IStream_Release(pStream);
1090 ok_more_than_one_lock();
1092 IUnknown_Release(pProxy1);
1097 /* tests success case of marshaling and unmarshaling an HRESULT */
1098 static void test_hresult_marshaling(void)
1101 HRESULT hr_marshaled = 0;
1102 IStream *pStream = NULL;
1103 static const HRESULT E_DEADBEEF = 0xdeadbeef;
1105 hr = CreateStreamOnHGlobal(NULL, TRUE, &pStream);
1106 ok_ole_success(hr, CreateStreamOnHGlobal);
1108 hr = CoMarshalHresult(pStream, E_DEADBEEF);
1109 ok_ole_success(hr, CoMarshalHresult);
1111 IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
1112 hr = IStream_Read(pStream, &hr_marshaled, sizeof(HRESULT), NULL);
1113 ok_ole_success(hr, IStream_Read);
1115 ok(hr_marshaled == E_DEADBEEF, "Didn't marshal HRESULT as expected: got value 0x%08x instead\n", hr_marshaled);
1118 IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
1119 hr = CoUnmarshalHresult(pStream, &hr_marshaled);
1120 ok_ole_success(hr, CoUnmarshalHresult);
1122 ok(hr_marshaled == E_DEADBEEF, "Didn't marshal HRESULT as expected: got value 0x%08x instead\n", hr_marshaled);
1124 IStream_Release(pStream);
1128 /* helper for test_proxy_used_in_wrong_thread */
1129 static DWORD CALLBACK bad_thread_proc(LPVOID p)
1131 IClassFactory * cf = (IClassFactory *)p;
1133 IUnknown * proxy = NULL;
1135 pCoInitializeEx(NULL, COINIT_MULTITHREADED);
1137 hr = IClassFactory_CreateInstance(cf, NULL, &IID_IUnknown, (LPVOID*)&proxy);
1138 if (proxy) IUnknown_Release(proxy);
1139 ok(hr == RPC_E_WRONG_THREAD,
1140 "COM should have failed with RPC_E_WRONG_THREAD on using proxy from wrong apartment, but instead returned 0x%08x\n",
1148 /* tests failure case of a using a proxy in the wrong apartment */
1149 static void test_proxy_used_in_wrong_thread(void)
1152 IStream *pStream = NULL;
1153 IUnknown *pProxy = NULL;
1160 hr = CreateStreamOnHGlobal(NULL, TRUE, &pStream);
1161 ok_ole_success(hr, CreateStreamOnHGlobal);
1162 tid = start_host_object(pStream, &IID_IClassFactory, (IUnknown*)&Test_ClassFactory, MSHLFLAGS_NORMAL, &host_thread);
1164 ok_more_than_one_lock();
1166 IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
1167 hr = CoUnmarshalInterface(pStream, &IID_IClassFactory, (void **)&pProxy);
1168 ok_ole_success(hr, CoUnmarshalInterface);
1169 IStream_Release(pStream);
1171 ok_more_than_one_lock();
1173 /* create a thread that we can misbehave in */
1174 thread = CreateThread(NULL, 0, bad_thread_proc, (LPVOID)pProxy, 0, &tid2);
1176 WaitForSingleObject(thread, INFINITE);
1177 CloseHandle(thread);
1179 IUnknown_Release(pProxy);
1183 end_host_object(tid, host_thread);
1186 static HRESULT WINAPI MessageFilter_QueryInterface(IMessageFilter *iface, REFIID riid, void ** ppvObj)
1188 if (ppvObj == NULL) return E_POINTER;
1190 if (IsEqualGUID(riid, &IID_IUnknown) ||
1191 IsEqualGUID(riid, &IID_IClassFactory))
1193 *ppvObj = (LPVOID)iface;
1194 IClassFactory_AddRef(iface);
1198 return E_NOINTERFACE;
1201 static ULONG WINAPI MessageFilter_AddRef(IMessageFilter *iface)
1203 return 2; /* non-heap object */
1206 static ULONG WINAPI MessageFilter_Release(IMessageFilter *iface)
1208 return 1; /* non-heap object */
1211 static DWORD WINAPI MessageFilter_HandleInComingCall(
1212 IMessageFilter *iface,
1214 HTASK threadIDCaller,
1216 LPINTERFACEINFO lpInterfaceInfo)
1218 static int callcount = 0;
1220 trace("HandleInComingCall\n");
1224 ret = SERVERCALL_REJECTED;
1227 ret = SERVERCALL_RETRYLATER;
1230 ret = SERVERCALL_ISHANDLED;
1237 static DWORD WINAPI MessageFilter_RetryRejectedCall(
1238 IMessageFilter *iface,
1239 HTASK threadIDCallee,
1243 trace("RetryRejectedCall\n");
1247 static DWORD WINAPI MessageFilter_MessagePending(
1248 IMessageFilter *iface,
1249 HTASK threadIDCallee,
1251 DWORD dwPendingType)
1253 trace("MessagePending\n");
1254 return PENDINGMSG_WAITNOPROCESS;
1257 static const IMessageFilterVtbl MessageFilter_Vtbl =
1259 MessageFilter_QueryInterface,
1260 MessageFilter_AddRef,
1261 MessageFilter_Release,
1262 MessageFilter_HandleInComingCall,
1263 MessageFilter_RetryRejectedCall,
1264 MessageFilter_MessagePending
1267 static IMessageFilter MessageFilter = { &MessageFilter_Vtbl };
1269 static void test_message_filter(void)
1272 IStream *pStream = NULL;
1273 IClassFactory *cf = NULL;
1275 IUnknown *proxy = NULL;
1276 IMessageFilter *prev_filter = NULL;
1281 hr = CreateStreamOnHGlobal(NULL, TRUE, &pStream);
1282 ok_ole_success(hr, CreateStreamOnHGlobal);
1283 tid = start_host_object2(pStream, &IID_IClassFactory, (IUnknown*)&Test_ClassFactory, MSHLFLAGS_NORMAL, &MessageFilter, &thread);
1285 ok_more_than_one_lock();
1287 IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
1288 hr = CoUnmarshalInterface(pStream, &IID_IClassFactory, (void **)&cf);
1289 ok_ole_success(hr, CoUnmarshalInterface);
1290 IStream_Release(pStream);
1292 ok_more_than_one_lock();
1294 hr = IClassFactory_CreateInstance(cf, NULL, &IID_IUnknown, (LPVOID*)&proxy);
1295 ok(hr == RPC_E_CALL_REJECTED, "Call should have returned RPC_E_CALL_REJECTED, but return 0x%08x instead\n", hr);
1296 if (proxy) IUnknown_Release(proxy);
1299 hr = CoRegisterMessageFilter(&MessageFilter, &prev_filter);
1300 ok_ole_success(hr, CoRegisterMessageFilter);
1302 hr = IClassFactory_CreateInstance(cf, NULL, &IID_IUnknown, (LPVOID*)&proxy);
1303 ok_ole_success(hr, IClassFactory_CreateInstance);
1305 IUnknown_Release(proxy);
1307 IClassFactory_Release(cf);
1311 end_host_object(tid, thread);
1313 hr = CoRegisterMessageFilter(prev_filter, NULL);
1314 ok_ole_success(hr, CoRegisterMessageFilter);
1317 /* test failure case of trying to unmarshal from bad stream */
1318 static void test_bad_marshal_stream(void)
1321 IStream *pStream = NULL;
1323 hr = CreateStreamOnHGlobal(NULL, TRUE, &pStream);
1324 ok_ole_success(hr, CreateStreamOnHGlobal);
1325 hr = CoMarshalInterface(pStream, &IID_IClassFactory, (IUnknown*)&Test_ClassFactory, MSHCTX_INPROC, NULL, MSHLFLAGS_NORMAL);
1326 ok_ole_success(hr, CoMarshalInterface);
1328 ok_more_than_one_lock();
1330 /* try to read beyond end of stream */
1331 hr = CoReleaseMarshalData(pStream);
1332 ok(hr == STG_E_READFAULT, "Should have failed with STG_E_READFAULT, but returned 0x%08x instead\n", hr);
1334 /* now release for real */
1335 IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
1336 hr = CoReleaseMarshalData(pStream);
1337 ok_ole_success(hr, CoReleaseMarshalData);
1339 IStream_Release(pStream);
1342 /* tests that proxies implement certain interfaces */
1343 static void test_proxy_interfaces(void)
1346 IStream *pStream = NULL;
1347 IUnknown *pProxy = NULL;
1348 IUnknown *pOtherUnknown = NULL;
1354 hr = CreateStreamOnHGlobal(NULL, TRUE, &pStream);
1355 ok_ole_success(hr, CreateStreamOnHGlobal);
1356 tid = start_host_object(pStream, &IID_IClassFactory, (IUnknown*)&Test_ClassFactory, MSHLFLAGS_NORMAL, &thread);
1358 ok_more_than_one_lock();
1360 IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
1361 hr = CoUnmarshalInterface(pStream, &IID_IUnknown, (void **)&pProxy);
1362 ok_ole_success(hr, CoUnmarshalInterface);
1363 IStream_Release(pStream);
1365 ok_more_than_one_lock();
1367 hr = IUnknown_QueryInterface(pProxy, &IID_IUnknown, (LPVOID*)&pOtherUnknown);
1368 ok_ole_success(hr, IUnknown_QueryInterface IID_IUnknown);
1369 if (hr == S_OK) IUnknown_Release(pOtherUnknown);
1371 hr = IUnknown_QueryInterface(pProxy, &IID_IClientSecurity, (LPVOID*)&pOtherUnknown);
1372 todo_wine { ok_ole_success(hr, IUnknown_QueryInterface IID_IClientSecurity); }
1373 if (hr == S_OK) IUnknown_Release(pOtherUnknown);
1375 hr = IUnknown_QueryInterface(pProxy, &IID_IMultiQI, (LPVOID*)&pOtherUnknown);
1376 ok_ole_success(hr, IUnknown_QueryInterface IID_IMultiQI);
1377 if (hr == S_OK) IUnknown_Release(pOtherUnknown);
1379 hr = IUnknown_QueryInterface(pProxy, &IID_IMarshal, (LPVOID*)&pOtherUnknown);
1380 ok_ole_success(hr, IUnknown_QueryInterface IID_IMarshal);
1381 if (hr == S_OK) IUnknown_Release(pOtherUnknown);
1383 /* IMarshal2 is also supported on NT-based systems, but is pretty much
1384 * useless as it has no more methods over IMarshal that it inherits from. */
1386 IUnknown_Release(pProxy);
1390 end_host_object(tid, thread);
1395 const IUnknownVtbl *lpVtbl;
1399 static HRESULT WINAPI HeapUnknown_QueryInterface(IUnknown *iface, REFIID riid, void **ppv)
1401 if (IsEqualIID(riid, &IID_IUnknown))
1403 IUnknown_AddRef(iface);
1404 *ppv = (LPVOID)iface;
1408 return E_NOINTERFACE;
1411 static ULONG WINAPI HeapUnknown_AddRef(IUnknown *iface)
1413 HeapUnknown *This = (HeapUnknown *)iface;
1414 trace("HeapUnknown_AddRef(%p)\n", iface);
1415 return InterlockedIncrement((LONG*)&This->refs);
1418 static ULONG WINAPI HeapUnknown_Release(IUnknown *iface)
1420 HeapUnknown *This = (HeapUnknown *)iface;
1421 ULONG refs = InterlockedDecrement((LONG*)&This->refs);
1422 trace("HeapUnknown_Release(%p)\n", iface);
1423 if (!refs) HeapFree(GetProcessHeap(), 0, This);
1427 static const IUnknownVtbl HeapUnknown_Vtbl =
1429 HeapUnknown_QueryInterface,
1434 static void test_proxybuffer(REFIID riid)
1437 IPSFactoryBuffer *psfb;
1438 IRpcProxyBuffer *proxy;
1442 HeapUnknown *pUnkOuter = (HeapUnknown *)HeapAlloc(GetProcessHeap(), 0, sizeof(*pUnkOuter));
1444 pUnkOuter->lpVtbl = &HeapUnknown_Vtbl;
1445 pUnkOuter->refs = 1;
1447 hr = CoGetPSClsid(riid, &clsid);
1448 ok_ole_success(hr, CoGetPSClsid);
1450 hr = CoGetClassObject(&clsid, CLSCTX_INPROC_SERVER, NULL, &IID_IPSFactoryBuffer, (LPVOID*)&psfb);
1451 ok_ole_success(hr, CoGetClassObject);
1453 hr = IPSFactoryBuffer_CreateProxy(psfb, (IUnknown*)pUnkOuter, riid, &proxy, &lpvtbl);
1454 ok_ole_success(hr, IPSFactoryBuffer_CreateProxy);
1455 ok(lpvtbl != NULL, "IPSFactoryBuffer_CreateProxy succeeded, but returned a NULL vtable!\n");
1457 /* release our reference to the outer unknown object - the PS factory
1458 * buffer will have AddRef's it in the CreateProxy call */
1459 refs = IUnknown_Release((IUnknown *)pUnkOuter);
1460 ok(refs == 1, "Ref count of outer unknown should have been 1 instead of %d\n", refs);
1462 refs = IPSFactoryBuffer_Release(psfb);
1465 /* not reliable on native. maybe it leaks references! */
1466 ok(refs == 0, "Ref-count leak of %d on IPSFactoryBuffer\n", refs);
1469 refs = IUnknown_Release((IUnknown *)lpvtbl);
1470 ok(refs == 0, "Ref-count leak of %d on IRpcProxyBuffer\n", refs);
1472 refs = IRpcProxyBuffer_Release(proxy);
1473 ok(refs == 0, "Ref-count leak of %d on IRpcProxyBuffer\n", refs);
1476 static void test_stubbuffer(REFIID riid)
1479 IPSFactoryBuffer *psfb;
1480 IRpcStubBuffer *stub;
1486 hr = CoGetPSClsid(riid, &clsid);
1487 ok_ole_success(hr, CoGetPSClsid);
1489 hr = CoGetClassObject(&clsid, CLSCTX_INPROC_SERVER, NULL, &IID_IPSFactoryBuffer, (LPVOID*)&psfb);
1490 ok_ole_success(hr, CoGetClassObject);
1492 hr = IPSFactoryBuffer_CreateStub(psfb, riid, (IUnknown*)&Test_ClassFactory, &stub);
1493 ok_ole_success(hr, IPSFactoryBuffer_CreateStub);
1495 refs = IPSFactoryBuffer_Release(psfb);
1498 /* not reliable on native. maybe it leaks references */
1499 ok(refs == 0, "Ref-count leak of %d on IPSFactoryBuffer\n", refs);
1502 ok_more_than_one_lock();
1504 IRpcStubBuffer_Disconnect(stub);
1508 refs = IRpcStubBuffer_Release(stub);
1509 ok(refs == 0, "Ref-count leak of %d on IRpcProxyBuffer\n", refs);
1512 static HWND hwnd_app;
1514 static HRESULT WINAPI TestRE_IClassFactory_CreateInstance(
1515 LPCLASSFACTORY iface,
1516 LPUNKNOWN pUnkOuter,
1521 if (IsEqualIID(riid, &IID_IWineTest))
1523 BOOL ret = SendMessageTimeout(hwnd_app, WM_NULL, 0, 0, SMTO_BLOCK, 5000, &res);
1524 ok(ret, "Timed out sending a message to originating window during RPC call\n");
1529 static const IClassFactoryVtbl TestREClassFactory_Vtbl =
1531 Test_IClassFactory_QueryInterface,
1532 Test_IClassFactory_AddRef,
1533 Test_IClassFactory_Release,
1534 TestRE_IClassFactory_CreateInstance,
1535 Test_IClassFactory_LockServer
1538 IClassFactory TestRE_ClassFactory = { &TestREClassFactory_Vtbl };
1540 static LRESULT CALLBACK window_proc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam)
1547 IStream *pStream = NULL;
1548 IClassFactory *proxy = NULL;
1555 hr = CreateStreamOnHGlobal(NULL, TRUE, &pStream);
1556 ok_ole_success(hr, CreateStreamOnHGlobal);
1557 tid = start_host_object(pStream, &IID_IClassFactory, (IUnknown*)&TestRE_ClassFactory, MSHLFLAGS_NORMAL, &thread);
1559 ok_more_than_one_lock();
1561 IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
1562 hr = CoUnmarshalInterface(pStream, &IID_IClassFactory, (void **)&proxy);
1563 ok_ole_success(hr, CoReleaseMarshalData);
1564 IStream_Release(pStream);
1566 ok_more_than_one_lock();
1568 /* note the use of the magic IID_IWineTest value to tell remote thread
1569 * to try to send a message back to us */
1570 hr = IClassFactory_CreateInstance(proxy, NULL, &IID_IWineTest, (void **)&object);
1572 IClassFactory_Release(proxy);
1576 end_host_object(tid, thread);
1578 PostMessage(hwnd, WM_QUIT, 0, 0);
1585 IStream *pStream = NULL;
1586 IClassFactory *proxy = NULL;
1593 hr = CreateStreamOnHGlobal(NULL, TRUE, &pStream);
1594 ok_ole_success(hr, CreateStreamOnHGlobal);
1595 tid = start_host_object(pStream, &IID_IClassFactory, (IUnknown*)&TestRE_ClassFactory, MSHLFLAGS_NORMAL, &thread);
1597 ok_more_than_one_lock();
1599 IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
1600 hr = CoUnmarshalInterface(pStream, &IID_IClassFactory, (void **)&proxy);
1601 ok_ole_success(hr, CoReleaseMarshalData);
1602 IStream_Release(pStream);
1604 ok_more_than_one_lock();
1606 /* post quit message before a doing a COM call to show that a pending
1607 * WM_QUIT message doesn't stop the call from succeeding */
1608 PostMessage(hwnd, WM_QUIT, 0, 0);
1609 hr = IClassFactory_CreateInstance(proxy, NULL, &IID_IUnknown, (void **)&object);
1611 IClassFactory_Release(proxy);
1615 end_host_object(tid, thread);
1622 IStream *pStream = NULL;
1623 IClassFactory *proxy = NULL;
1628 hr = CreateStreamOnHGlobal(NULL, TRUE, &pStream);
1629 ok_ole_success(hr, CreateStreamOnHGlobal);
1630 tid = start_host_object(pStream, &IID_IClassFactory, (IUnknown*)&Test_ClassFactory, MSHLFLAGS_NORMAL, &thread);
1632 IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
1633 hr = CoUnmarshalInterface(pStream, &IID_IClassFactory, (void **)&proxy);
1634 ok_ole_success(hr, CoReleaseMarshalData);
1635 IStream_Release(pStream);
1637 /* shows that COM calls executed during the processing of sent
1638 * messages should fail */
1639 hr = IClassFactory_CreateInstance(proxy, NULL, &IID_IUnknown, (void **)&object);
1640 ok(hr == RPC_E_CANTCALLOUT_ININPUTSYNCCALL,
1641 "COM call during processing of sent message should return RPC_E_CANTCALLOUT_ININPUTSYNCCALL instead of 0x%08x\n", hr);
1643 IClassFactory_Release(proxy);
1645 end_host_object(tid, thread);
1652 return DefWindowProc(hwnd, msg, wparam, lparam);
1656 static void test_message_reentrancy(void)
1661 memset(&wndclass, 0, sizeof(wndclass));
1662 wndclass.lpfnWndProc = window_proc;
1663 wndclass.lpszClassName = "WineCOMTest";
1664 RegisterClass(&wndclass);
1666 hwnd_app = CreateWindow("WineCOMTest", NULL, 0, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, NULL, NULL, NULL, 0);
1667 ok(hwnd_app != NULL, "Window creation failed\n");
1669 /* start message re-entrancy test */
1670 PostMessage(hwnd_app, WM_USER, 0, 0);
1672 while (GetMessage(&msg, NULL, 0, 0))
1674 TranslateMessage(&msg);
1675 DispatchMessage(&msg);
1679 static HRESULT WINAPI TestMsg_IClassFactory_CreateInstance(
1680 LPCLASSFACTORY iface,
1681 LPUNKNOWN pUnkOuter,
1686 SendMessage(hwnd_app, WM_USER+2, 0, 0);
1690 static IClassFactoryVtbl TestMsgClassFactory_Vtbl =
1692 Test_IClassFactory_QueryInterface,
1693 Test_IClassFactory_AddRef,
1694 Test_IClassFactory_Release,
1695 TestMsg_IClassFactory_CreateInstance,
1696 Test_IClassFactory_LockServer
1699 IClassFactory TestMsg_ClassFactory = { &TestMsgClassFactory_Vtbl };
1701 static void test_call_from_message(void)
1706 IClassFactory *proxy;
1711 hwnd_app = CreateWindow("WineCOMTest", NULL, 0, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, NULL, NULL, NULL, 0);
1712 ok(hwnd_app != NULL, "Window creation failed\n");
1714 hr = CreateStreamOnHGlobal(NULL, TRUE, &pStream);
1715 ok_ole_success(hr, CreateStreamOnHGlobal);
1716 tid = start_host_object(pStream, &IID_IClassFactory, (IUnknown*)&TestMsg_ClassFactory, MSHLFLAGS_NORMAL, &thread);
1718 ok_more_than_one_lock();
1720 IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
1721 hr = CoUnmarshalInterface(pStream, &IID_IClassFactory, (void **)&proxy);
1722 ok_ole_success(hr, CoReleaseMarshalData);
1723 IStream_Release(pStream);
1725 ok_more_than_one_lock();
1727 /* start message re-entrancy test */
1728 hr = IClassFactory_CreateInstance(proxy, NULL, &IID_IUnknown, (void **)&object);
1729 ok_ole_success(hr, IClassFactory_CreateInstance);
1731 IClassFactory_Release(proxy);
1735 end_host_object(tid, thread);
1737 while (GetMessage(&msg, NULL, 0, 0))
1739 TranslateMessage(&msg);
1740 DispatchMessage(&msg);
1744 static void test_WM_QUIT_handling(void)
1748 hwnd_app = CreateWindow("WineCOMTest", NULL, 0, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, NULL, NULL, NULL, 0);
1749 ok(hwnd_app != NULL, "Window creation failed\n");
1751 /* start WM_QUIT handling test */
1752 PostMessage(hwnd_app, WM_USER+1, 0, 0);
1754 while (GetMessage(&msg, NULL, 0, 0))
1756 TranslateMessage(&msg);
1757 DispatchMessage(&msg);
1761 static void test_freethreadedmarshaldata(IStream *pStream, MSHCTX mshctx, void *ptr, DWORD mshlflags)
1768 hr = GetHGlobalFromStream(pStream, &hglobal);
1769 ok_ole_success(hr, GetHGlobalFromStream);
1771 size = GlobalSize(hglobal);
1773 marshal_data = (char *)GlobalLock(hglobal);
1775 if (mshctx == MSHCTX_INPROC)
1777 DWORD expected_size = sizeof(DWORD) + sizeof(void *) + sizeof(DWORD) + sizeof(GUID);
1778 ok(size == expected_size, "size should have been %d instead of %d\n", expected_size, size);
1780 ok(*(DWORD *)marshal_data == mshlflags, "expected 0x%x, but got 0x%x for mshctx\n", mshlflags, *(DWORD *)marshal_data);
1781 marshal_data += sizeof(DWORD);
1782 ok(*(void **)marshal_data == ptr, "expected %p, but got %p for mshctx\n", ptr, *(void **)marshal_data);
1783 marshal_data += sizeof(void *);
1784 ok(*(DWORD *)marshal_data == 0, "expected 0x0, but got 0x%x\n", *(DWORD *)marshal_data);
1785 marshal_data += sizeof(DWORD);
1786 trace("got guid data: {%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x}\n",
1787 ((GUID *)marshal_data)->Data1, ((GUID *)marshal_data)->Data2, ((GUID *)marshal_data)->Data3,
1788 ((GUID *)marshal_data)->Data4[0], ((GUID *)marshal_data)->Data4[1], ((GUID *)marshal_data)->Data4[2], ((GUID *)marshal_data)->Data4[3],
1789 ((GUID *)marshal_data)->Data4[4], ((GUID *)marshal_data)->Data4[5], ((GUID *)marshal_data)->Data4[6], ((GUID *)marshal_data)->Data4[7]);
1793 ok(size > sizeof(DWORD), "size should have been > sizeof(DWORD), not %d\n", size);
1794 ok(*(DWORD *)marshal_data == 0x574f454d /* MEOW */,
1795 "marshal data should be filled by standard marshal and start with MEOW signature\n");
1798 GlobalUnlock(hglobal);
1801 static void test_freethreadedmarshaler(void)
1804 IUnknown *pFTUnknown;
1805 IMarshal *pFTMarshal;
1808 static const LARGE_INTEGER llZero;
1811 hr = CoCreateFreeThreadedMarshaler(NULL, &pFTUnknown);
1812 ok_ole_success(hr, CoCreateFreeThreadedMarshaler);
1813 hr = IUnknown_QueryInterface(pFTUnknown, &IID_IMarshal, (void **)&pFTMarshal);
1814 ok_ole_success(hr, IUnknown_QueryInterface);
1815 IUnknown_Release(pFTUnknown);
1817 hr = CreateStreamOnHGlobal(NULL, TRUE, &pStream);
1818 ok_ole_success(hr, CreateStreamOnHGlobal);
1820 /* inproc normal marshaling */
1822 hr = IMarshal_MarshalInterface(pFTMarshal, pStream, &IID_IClassFactory,
1823 (IUnknown*)&Test_ClassFactory, MSHCTX_INPROC, NULL, MSHLFLAGS_NORMAL);
1824 ok_ole_success(hr, IMarshal_MarshalInterface);
1826 ok_more_than_one_lock();
1828 test_freethreadedmarshaldata(pStream, MSHCTX_INPROC, &Test_ClassFactory, MSHLFLAGS_NORMAL);
1830 IStream_Seek(pStream, llZero, STREAM_SEEK_SET, NULL);
1831 hr = IMarshal_UnmarshalInterface(pFTMarshal, pStream, &IID_IUnknown, (void **)&pProxy);
1832 ok_ole_success(hr, IMarshal_UnmarshalInterface);
1834 IUnknown_Release(pProxy);
1838 /* native doesn't allow us to unmarshal or release the stream data,
1839 * presumably because it wants us to call CoMarshalInterface instead */
1842 /* local normal marshaling */
1844 IStream_Seek(pStream, llZero, STREAM_SEEK_SET, NULL);
1845 hr = IMarshal_MarshalInterface(pFTMarshal, pStream, &IID_IClassFactory, (IUnknown*)&Test_ClassFactory, MSHCTX_LOCAL, NULL, MSHLFLAGS_NORMAL);
1846 ok_ole_success(hr, IMarshal_MarshalInterface);
1848 ok_more_than_one_lock();
1850 test_freethreadedmarshaldata(pStream, MSHCTX_LOCAL, &Test_ClassFactory, MSHLFLAGS_NORMAL);
1852 IStream_Seek(pStream, llZero, STREAM_SEEK_SET, NULL);
1853 hr = IMarshal_ReleaseMarshalData(pFTMarshal, pStream);
1854 ok_ole_success(hr, IMarshal_ReleaseMarshalData);
1859 /* inproc table-strong marshaling */
1861 IStream_Seek(pStream, llZero, STREAM_SEEK_SET, NULL);
1862 hr = IMarshal_MarshalInterface(pFTMarshal, pStream, &IID_IClassFactory,
1863 (IUnknown*)&Test_ClassFactory, MSHCTX_INPROC, (void *)0xdeadbeef,
1864 MSHLFLAGS_TABLESTRONG);
1865 ok_ole_success(hr, IMarshal_MarshalInterface);
1867 ok_more_than_one_lock();
1869 test_freethreadedmarshaldata(pStream, MSHCTX_INPROC, &Test_ClassFactory, MSHLFLAGS_TABLESTRONG);
1871 IStream_Seek(pStream, llZero, STREAM_SEEK_SET, NULL);
1872 hr = IMarshal_UnmarshalInterface(pFTMarshal, pStream, &IID_IUnknown, (void **)&pProxy);
1873 ok_ole_success(hr, IMarshal_UnmarshalInterface);
1875 IUnknown_Release(pProxy);
1877 ok_more_than_one_lock();
1879 IStream_Seek(pStream, llZero, STREAM_SEEK_SET, NULL);
1880 hr = IMarshal_ReleaseMarshalData(pFTMarshal, pStream);
1881 ok_ole_success(hr, IMarshal_ReleaseMarshalData);
1885 /* inproc table-weak marshaling */
1887 IStream_Seek(pStream, llZero, STREAM_SEEK_SET, NULL);
1888 hr = IMarshal_MarshalInterface(pFTMarshal, pStream, &IID_IClassFactory,
1889 (IUnknown*)&Test_ClassFactory, MSHCTX_INPROC, (void *)0xdeadbeef,
1890 MSHLFLAGS_TABLEWEAK);
1891 ok_ole_success(hr, IMarshal_MarshalInterface);
1895 test_freethreadedmarshaldata(pStream, MSHCTX_INPROC, &Test_ClassFactory, MSHLFLAGS_TABLEWEAK);
1897 IStream_Seek(pStream, llZero, STREAM_SEEK_SET, NULL);
1898 hr = IMarshal_UnmarshalInterface(pFTMarshal, pStream, &IID_IUnknown, (void **)&pProxy);
1899 ok_ole_success(hr, IMarshal_UnmarshalInterface);
1901 ok_more_than_one_lock();
1903 IUnknown_Release(pProxy);
1907 /* inproc normal marshaling (for extraordinary cases) */
1909 IStream_Seek(pStream, llZero, STREAM_SEEK_SET, NULL);
1910 hr = IMarshal_MarshalInterface(pFTMarshal, pStream, &IID_IClassFactory,
1911 (IUnknown*)&Test_ClassFactory, MSHCTX_INPROC, NULL, MSHLFLAGS_NORMAL);
1912 ok_ole_success(hr, IMarshal_MarshalInterface);
1914 ok_more_than_one_lock();
1916 /* this call shows that DisconnectObject does nothing */
1917 hr = IMarshal_DisconnectObject(pFTMarshal, 0);
1918 ok_ole_success(hr, IMarshal_DisconnectObject);
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 /* doesn't enforce marshaling rules here and allows us to unmarshal the
1929 * interface, even though it was freed above */
1930 IStream_Seek(pStream, llZero, STREAM_SEEK_SET, NULL);
1931 hr = IMarshal_UnmarshalInterface(pFTMarshal, pStream, &IID_IUnknown, (void **)&pProxy);
1932 ok_ole_success(hr, IMarshal_UnmarshalInterface);
1936 IStream_Release(pStream);
1937 IMarshal_Release(pFTMarshal);
1940 static HANDLE heventShutdown;
1942 static void LockModuleOOP(void)
1944 InterlockedIncrement(&cLocks); /* for test purposes only */
1945 CoAddRefServerProcess();
1948 static void UnlockModuleOOP(void)
1950 InterlockedDecrement(&cLocks); /* for test purposes only */
1951 if (!CoReleaseServerProcess())
1952 SetEvent(heventShutdown);
1955 static HWND hwnd_app;
1957 static HRESULT WINAPI TestOOP_IClassFactory_QueryInterface(
1958 LPCLASSFACTORY iface,
1962 if (ppvObj == NULL) return E_POINTER;
1964 if (IsEqualGUID(riid, &IID_IUnknown) ||
1965 IsEqualGUID(riid, &IID_IClassFactory))
1967 *ppvObj = (LPVOID)iface;
1968 IClassFactory_AddRef(iface);
1972 return E_NOINTERFACE;
1975 static ULONG WINAPI TestOOP_IClassFactory_AddRef(LPCLASSFACTORY iface)
1977 return 2; /* non-heap-based object */
1980 static ULONG WINAPI TestOOP_IClassFactory_Release(LPCLASSFACTORY iface)
1982 return 1; /* non-heap-based object */
1985 static HRESULT WINAPI TestOOP_IClassFactory_CreateInstance(
1986 LPCLASSFACTORY iface,
1987 LPUNKNOWN pUnkOuter,
1991 return CLASS_E_CLASSNOTAVAILABLE;
1994 static HRESULT WINAPI TestOOP_IClassFactory_LockServer(
1995 LPCLASSFACTORY iface,
2005 static const IClassFactoryVtbl TestClassFactoryOOP_Vtbl =
2007 TestOOP_IClassFactory_QueryInterface,
2008 TestOOP_IClassFactory_AddRef,
2009 TestOOP_IClassFactory_Release,
2010 TestOOP_IClassFactory_CreateInstance,
2011 TestOOP_IClassFactory_LockServer
2014 static IClassFactory TestOOP_ClassFactory = { &TestClassFactoryOOP_Vtbl };
2016 /* tests functions commonly used by out of process COM servers */
2017 static void test_out_of_process_com(void)
2019 static const CLSID CLSID_WineOOPTest = {
2023 {0xa1, 0xa2, 0x5d, 0x5a, 0x36, 0x54, 0xd3, 0xbd}
2024 }; /* 5201163f-8164-4fd0-a1a2-5d5a3654d3bd */
2030 heventShutdown = CreateEvent(NULL, TRUE, FALSE, NULL);
2034 /* Start the object suspended */
2035 hr = CoRegisterClassObject(&CLSID_WineOOPTest, (IUnknown *)&TestOOP_ClassFactory,
2036 CLSCTX_LOCAL_SERVER, REGCLS_MULTIPLEUSE | REGCLS_SUSPENDED, &cookie);
2037 ok_ole_success(hr, CoRegisterClassObject);
2039 /* ... and CoGetClassObject does not find it and fails when it looks for the
2040 * class in the registry */
2041 hr = CoGetClassObject(&CLSID_WineOOPTest, CLSCTX_INPROC_SERVER,
2042 NULL, &IID_IClassFactory, (LPVOID*)&cf);
2044 ok(hr == REGDB_E_CLASSNOTREG,
2045 "CoGetClassObject should have returned REGDB_E_CLASSNOTREG instead of 0x%08x\n", hr);
2048 /* Resume the object suspended above ... */
2049 hr = CoResumeClassObjects();
2050 ok_ole_success(hr, CoResumeClassObjects);
2052 /* ... and now it should succeed */
2053 hr = CoGetClassObject(&CLSID_WineOOPTest, CLSCTX_INPROC_SERVER,
2054 NULL, &IID_IClassFactory, (LPVOID*)&cf);
2055 ok_ole_success(hr, CoGetClassObject);
2057 /* Now check the locking is working */
2058 /* NOTE: we are accessing the class directly, not through a proxy */
2062 hr = IClassFactory_LockServer(cf, TRUE);
2063 trace("IClassFactory_LockServer returned 0x%08x\n", hr);
2065 ok_more_than_one_lock();
2067 IClassFactory_LockServer(cf, FALSE);
2071 IClassFactory_Release(cf);
2073 /* wait for shutdown signal */
2074 ret = WaitForSingleObject(heventShutdown, 5000);
2075 todo_wine { ok(ret != WAIT_TIMEOUT, "Server didn't shut down or machine is under very heavy load\n"); }
2077 /* try to connect again after SCM has suspended registered class objects */
2078 hr = CoGetClassObject(&CLSID_WineOOPTest, CLSCTX_INPROC_SERVER | CLSCTX_LOCAL_SERVER, NULL,
2079 &IID_IClassFactory, (LPVOID*)&cf);
2081 ok(hr == CO_E_SERVER_STOPPING,
2082 "CoGetClassObject should have returned CO_E_SERVER_STOPPING instead of 0x%08x\n", hr);
2085 hr = CoRevokeClassObject(cookie);
2086 ok_ole_success(hr, CoRevokeClassObject);
2088 CloseHandle(heventShutdown);
2091 static void test_ROT(void)
2093 static const WCHAR wszFileName[] = {'B','E','2','0','E','2','F','5','-',
2094 '1','9','0','3','-','4','A','A','E','-','B','1','A','F','-',
2095 '2','0','4','6','E','5','8','6','C','9','2','5',0};
2097 IMoniker *pMoniker = NULL;
2098 IRunningObjectTable *pROT = NULL;
2103 hr = CreateFileMoniker(wszFileName, &pMoniker);
2104 ok_ole_success(hr, CreateClassMoniker);
2105 hr = GetRunningObjectTable(0, &pROT);
2106 ok_ole_success(hr, GetRunningObjectTable);
2107 hr = IRunningObjectTable_Register(pROT, 0, (IUnknown*)&Test_ClassFactory, pMoniker, &dwCookie);
2108 ok_ole_success(hr, IRunningObjectTable_Register);
2109 IMoniker_Release(pMoniker);
2111 ok_more_than_one_lock();
2113 hr = IRunningObjectTable_Revoke(pROT, dwCookie);
2114 ok_ole_success(hr, IRunningObjectTable_Revoke);
2122 IGlobalInterfaceTable *git;
2125 static DWORD CALLBACK get_global_interface_proc(LPVOID pv)
2128 struct git_params *params = (struct git_params *)pv;
2131 hr = IGlobalInterfaceTable_GetInterfaceFromGlobal(params->git, params->cookie, &IID_IClassFactory, (void **)&cf);
2132 ok(hr == CO_E_NOTINITIALIZED,
2133 "IGlobalInterfaceTable_GetInterfaceFromGlobal should have failed with error CO_E_NOTINITIALIZED instead of 0x%08x\n",
2137 hr = IGlobalInterfaceTable_GetInterfaceFromGlobal(params->git, params->cookie, &IID_IClassFactory, (void **)&cf);
2138 ok_ole_success(hr, IGlobalInterfaceTable_GetInterfaceFromGlobal);
2140 IGlobalInterfaceTable_Release(params->git);
2147 static void test_globalinterfacetable(void)
2150 IGlobalInterfaceTable *git;
2154 struct git_params params;
2157 hr = CoCreateInstance(&CLSID_StdGlobalInterfaceTable, NULL, CLSCTX_INPROC_SERVER, &IID_IGlobalInterfaceTable, (void **)&git);
2158 ok_ole_success(hr, CoCreateInstance);
2160 hr = IGlobalInterfaceTable_RegisterInterfaceInGlobal(git, (IUnknown *)&Test_ClassFactory, &IID_IClassFactory, &cookie);
2161 ok_ole_success(hr, IGlobalInterfaceTable_RegisterInterfaceInGlobal);
2163 params.cookie = cookie;
2165 /* note: params is on stack so we MUST wait for get_global_interface_proc
2166 * to exit before we can return */
2167 thread = CreateThread(NULL, 0, get_global_interface_proc, ¶ms, 0, &tid);
2169 ret = MsgWaitForMultipleObjects(1, &thread, FALSE, INFINITE, QS_ALLINPUT);
2170 while (ret == WAIT_OBJECT_0 + 1)
2173 while (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
2174 DispatchMessage(&msg);
2175 ret = MsgWaitForMultipleObjects(1, &thread, FALSE, INFINITE, QS_ALLINPUT);
2178 CloseHandle(thread);
2181 static void test_CoGetInterfaceAndReleaseStream(void)
2186 hr = CoGetInterfaceAndReleaseStream(NULL, &IID_IUnknown, (void**)&pUnk);
2187 ok(hr == E_INVALIDARG, "hr %08x\n", hr);
2190 static const char *debugstr_iid(REFIID riid)
2192 static char name[256];
2196 LONG name_size = sizeof(name);
2197 StringFromGUID2(riid, bufferW, sizeof(bufferW)/sizeof(bufferW[0]));
2198 WideCharToMultiByte(CP_ACP, 0, bufferW, sizeof(bufferW)/sizeof(bufferW[0]), buffer, sizeof(buffer), NULL, NULL);
2199 if (RegOpenKeyEx(HKEY_CLASSES_ROOT, "Interface", 0, KEY_QUERY_VALUE, &hkeyInterface) != ERROR_SUCCESS)
2201 memcpy(name, buffer, sizeof(buffer));
2204 if (RegQueryValue(hkeyInterface, buffer, name, &name_size) != ERROR_SUCCESS)
2206 memcpy(name, buffer, sizeof(buffer));
2209 RegCloseKey(hkeyInterface);
2214 static HRESULT WINAPI TestChannelHook_QueryInterface(IChannelHook *iface, REFIID riid, void **ppv)
2216 if (IsEqualIID(riid, &IID_IUnknown) || IsEqualIID(riid, &IID_IChannelHook))
2219 IUnknown_AddRef(iface);
2224 return E_NOINTERFACE;
2227 static ULONG WINAPI TestChannelHook_AddRef(IChannelHook *iface)
2232 static ULONG WINAPI TestChannelHook_Release(IChannelHook *iface)
2237 static void WINAPI TestChannelHook_ClientGetSize(
2238 IChannelHook *iface,
2243 SChannelHookCallInfo *info = (SChannelHookCallInfo *)riid;
2244 trace("TestChannelHook_ClientGetBuffer\n");
2245 trace("\t%s method %d\n", debugstr_iid(riid), info->iMethod);
2246 trace("\tcid: %s\n", debugstr_iid(&info->uCausality));
2247 ok(info->cbSize == sizeof(*info), "info->cbSize was %d instead of %d\n", info->cbSize, (int)sizeof(*info));
2249 ok(info->dwServerPid == GetCurrentProcessId(), "info->dwServerPid was 0x%x instead of 0x%x\n", info->dwServerPid, GetCurrentProcessId());
2251 ok(!info->pObject, "info->pObject should be NULL\n");
2252 ok(IsEqualGUID(uExtent, &EXTENTID_WineTest), "uExtent wasn't correct\n");
2257 static void WINAPI TestChannelHook_ClientFillBuffer(
2258 IChannelHook *iface,
2264 SChannelHookCallInfo *info = (SChannelHookCallInfo *)riid;
2265 trace("TestChannelHook_ClientFillBuffer\n");
2266 ok(info->cbSize == sizeof(*info), "info->cbSize was %d instead of %d\n", info->cbSize, (int)sizeof(*info));
2268 ok(info->dwServerPid == GetCurrentProcessId(), "info->dwServerPid was 0x%x instead of 0x%x\n", info->dwServerPid, GetCurrentProcessId());
2270 ok(!info->pObject, "info->pObject should be NULL\n");
2271 ok(IsEqualGUID(uExtent, &EXTENTID_WineTest), "uExtent wasn't correct\n");
2273 *(unsigned char *)pDataBuffer = 0xcc;
2277 static void WINAPI TestChannelHook_ClientNotify(
2278 IChannelHook *iface,
2286 SChannelHookCallInfo *info = (SChannelHookCallInfo *)riid;
2287 trace("TestChannelHook_ClientNotify hrFault = 0x%08x\n", hrFault);
2288 ok(info->cbSize == sizeof(*info), "info->cbSize was %d instead of %d\n", info->cbSize, (int)sizeof(*info));
2290 ok(info->dwServerPid == GetCurrentProcessId(), "info->dwServerPid was 0x%x instead of 0x%x\n", info->dwServerPid, GetCurrentProcessId());
2291 ok(info->pObject != NULL, "info->pObject shouldn't be NULL\n");
2293 ok(IsEqualGUID(uExtent, &EXTENTID_WineTest), "uExtent wasn't correct\n");
2296 static void WINAPI TestChannelHook_ServerNotify(
2297 IChannelHook *iface,
2304 SChannelHookCallInfo *info = (SChannelHookCallInfo *)riid;
2305 trace("TestChannelHook_ServerNotify\n");
2306 ok(info->cbSize == sizeof(*info), "info->cbSize was %d instead of %d\n", info->cbSize, (int)sizeof(*info));
2307 ok(info->dwServerPid == GetCurrentProcessId(), "info->dwServerPid was 0x%x instead of 0x%x\n", info->dwServerPid, GetCurrentProcessId());
2308 ok(info->pObject != NULL, "info->pObject shouldn't be NULL\n");
2309 ok(cbDataSize == 1, "cbDataSize should have been 1 instead of %d\n", cbDataSize);
2310 ok(*(unsigned char *)pDataBuffer == 0xcc, "pDataBuffer should have contained 0xcc instead of 0x%x\n", *(unsigned char *)pDataBuffer);
2311 ok(IsEqualGUID(uExtent, &EXTENTID_WineTest), "uExtent wasn't correct\n");
2314 static void WINAPI TestChannelHook_ServerGetSize(
2315 IChannelHook *iface,
2321 SChannelHookCallInfo *info = (SChannelHookCallInfo *)riid;
2322 trace("TestChannelHook_ServerGetSize\n");
2323 trace("\t%s method %d\n", debugstr_iid(riid), info->iMethod);
2324 ok(info->cbSize == sizeof(*info), "info->cbSize was %d instead of %d\n", info->cbSize, (int)sizeof(*info));
2325 ok(info->dwServerPid == GetCurrentProcessId(), "info->dwServerPid was 0x%x instead of 0x%x\n", info->dwServerPid, GetCurrentProcessId());
2326 ok(info->pObject != NULL, "info->pObject shouldn't be NULL\n");
2327 ok(IsEqualGUID(uExtent, &EXTENTID_WineTest), "uExtent wasn't correct\n");
2328 if (hrFault != S_OK)
2329 trace("\thrFault = 0x%08x\n", hrFault);
2334 static void WINAPI TestChannelHook_ServerFillBuffer(
2335 IChannelHook *iface,
2342 trace("TestChannelHook_ServerFillBuffer\n");
2343 ok(0, "TestChannelHook_ServerFillBuffer shouldn't be called\n");
2346 static const IChannelHookVtbl TestChannelHookVtbl =
2348 TestChannelHook_QueryInterface,
2349 TestChannelHook_AddRef,
2350 TestChannelHook_Release,
2351 TestChannelHook_ClientGetSize,
2352 TestChannelHook_ClientFillBuffer,
2353 TestChannelHook_ClientNotify,
2354 TestChannelHook_ServerNotify,
2355 TestChannelHook_ServerGetSize,
2356 TestChannelHook_ServerFillBuffer,
2359 static IChannelHook TestChannelHook = { &TestChannelHookVtbl };
2361 static void test_channel_hook(void)
2363 IStream *pStream = NULL;
2364 IClassFactory *cf = NULL;
2366 IUnknown *proxy = NULL;
2370 hr = CoRegisterChannelHook(&EXTENTID_WineTest, &TestChannelHook);
2371 ok_ole_success(hr, CoRegisterChannelHook);
2373 hr = CoRegisterMessageFilter(&MessageFilter, NULL);
2374 ok_ole_success(hr, CoRegisterMessageFilter);
2378 hr = CreateStreamOnHGlobal(NULL, TRUE, &pStream);
2379 ok_ole_success(hr, CreateStreamOnHGlobal);
2380 tid = start_host_object2(pStream, &IID_IClassFactory, (IUnknown*)&Test_ClassFactory, MSHLFLAGS_NORMAL, &MessageFilter, &thread);
2382 ok_more_than_one_lock();
2384 IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
2385 hr = CoUnmarshalInterface(pStream, &IID_IClassFactory, (void **)&cf);
2386 ok_ole_success(hr, CoUnmarshalInterface);
2387 IStream_Release(pStream);
2389 ok_more_than_one_lock();
2391 hr = IClassFactory_CreateInstance(cf, NULL, &IID_IUnknown, (LPVOID*)&proxy);
2392 ok_ole_success(hr, IClassFactory_CreateInstance);
2393 IUnknown_Release(proxy);
2395 IClassFactory_Release(cf);
2399 end_host_object(tid, thread);
2401 hr = CoRegisterMessageFilter(NULL, NULL);
2402 ok_ole_success(hr, CoRegisterMessageFilter);
2408 HMODULE hOle32 = GetModuleHandle("ole32");
2409 if (!(pCoInitializeEx = (void*)GetProcAddress(hOle32, "CoInitializeEx"))) goto no_test;
2411 /* register a window class used in several tests */
2412 memset(&wndclass, 0, sizeof(wndclass));
2413 wndclass.lpfnWndProc = window_proc;
2414 wndclass.lpszClassName = "WineCOMTest";
2415 RegisterClass(&wndclass);
2417 test_cocreateinstance_proxy();
2419 pCoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
2421 /* FIXME: test CoCreateInstanceEx */
2423 /* lifecycle management and marshaling tests */
2424 test_no_marshaler();
2425 test_normal_marshal_and_release();
2426 test_normal_marshal_and_unmarshal();
2427 test_marshal_and_unmarshal_invalid();
2428 test_interthread_marshal_and_unmarshal();
2429 test_proxy_marshal_and_unmarshal();
2430 test_proxy_marshal_and_unmarshal2();
2431 test_marshal_stub_apartment_shutdown();
2432 test_marshal_proxy_apartment_shutdown();
2433 test_marshal_proxy_mta_apartment_shutdown();
2434 test_no_couninitialize_server();
2435 test_no_couninitialize_client();
2436 test_tableweak_marshal_and_unmarshal_twice();
2437 test_tableweak_marshal_releasedata1();
2438 test_tableweak_marshal_releasedata2();
2439 test_tablestrong_marshal_and_unmarshal_twice();
2440 test_lock_object_external();
2441 test_disconnect_stub();
2442 test_normal_marshal_and_unmarshal_twice();
2443 test_hresult_marshaling();
2444 test_proxy_used_in_wrong_thread();
2445 test_message_filter();
2446 test_bad_marshal_stream();
2447 test_proxy_interfaces();
2448 test_stubbuffer(&IID_IClassFactory);
2449 test_proxybuffer(&IID_IClassFactory);
2450 test_message_reentrancy();
2451 test_call_from_message();
2452 test_WM_QUIT_handling();
2453 test_freethreadedmarshaler();
2455 /* doesn't pass with Win9x COM DLLs (even though Essential COM says it should) */
2456 if (0) test_out_of_process_com();
2459 test_globalinterfacetable();
2461 test_CoGetInterfaceAndReleaseStream();
2463 /* must be last test as channel hooks can't be unregistered */
2464 test_channel_hook();
2470 trace("You need DCOM95 installed to run this test\n");