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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
30 #include "wine/test.h"
32 /* functions that are not present on all versions of Windows */
33 HRESULT (WINAPI * pCoInitializeEx)(LPVOID lpReserved, DWORD dwCoInit);
35 /* helper macros to make tests a bit leaner */
36 #define ok_more_than_one_lock() ok(cLocks > 0, "Number of locks should be > 0, but actually is %ld\n", cLocks)
37 #define ok_no_locks() ok(cLocks == 0, "Number of locks should be 0, but actually is %ld\n", cLocks)
38 #define ok_ole_success(hr, func) ok(hr == S_OK, #func " failed with error 0x%08lx\n", hr)
40 static const LARGE_INTEGER ullZero;
43 static void LockModule()
45 InterlockedIncrement(&cLocks);
48 static void UnlockModule()
50 InterlockedDecrement(&cLocks);
54 static HRESULT WINAPI Test_IUnknown_QueryInterface(
59 if (ppvObj == NULL) return E_POINTER;
61 if (IsEqualGUID(riid, &IID_IUnknown))
63 *ppvObj = (LPVOID)iface;
64 IUnknown_AddRef(iface);
72 static ULONG WINAPI Test_IUnknown_AddRef(LPUNKNOWN iface)
75 return 2; /* non-heap-based object */
78 static ULONG WINAPI Test_IUnknown_Release(LPUNKNOWN iface)
81 return 1; /* non-heap-based object */
84 static IUnknownVtbl TestUnknown_Vtbl =
86 Test_IUnknown_QueryInterface,
88 Test_IUnknown_Release,
91 static IUnknown Test_Unknown = { &TestUnknown_Vtbl };
94 static HRESULT WINAPI Test_IClassFactory_QueryInterface(
99 if (ppvObj == NULL) return E_POINTER;
101 if (IsEqualGUID(riid, &IID_IUnknown) ||
102 IsEqualGUID(riid, &IID_IClassFactory))
104 *ppvObj = (LPVOID)iface;
105 IClassFactory_AddRef(iface);
110 return E_NOINTERFACE;
113 static ULONG WINAPI Test_IClassFactory_AddRef(LPCLASSFACTORY iface)
116 return 2; /* non-heap-based object */
119 static ULONG WINAPI Test_IClassFactory_Release(LPCLASSFACTORY iface)
122 return 1; /* non-heap-based object */
125 static HRESULT WINAPI Test_IClassFactory_CreateInstance(
126 LPCLASSFACTORY iface,
131 if (pUnkOuter) return CLASS_E_NOAGGREGATION;
132 return IUnknown_QueryInterface((IUnknown*)&Test_Unknown, riid, ppvObj);
135 static HRESULT WINAPI Test_IClassFactory_LockServer(
136 LPCLASSFACTORY iface,
142 static IClassFactoryVtbl TestClassFactory_Vtbl =
144 Test_IClassFactory_QueryInterface,
145 Test_IClassFactory_AddRef,
146 Test_IClassFactory_Release,
147 Test_IClassFactory_CreateInstance,
148 Test_IClassFactory_LockServer
151 static IClassFactory Test_ClassFactory = { &TestClassFactory_Vtbl };
153 #define RELEASEMARSHALDATA WM_USER
155 struct host_object_data
160 MSHLFLAGS marshal_flags;
161 HANDLE marshal_event;
162 IMessageFilter *filter;
165 static DWORD CALLBACK host_object_proc(LPVOID p)
167 struct host_object_data *data = (struct host_object_data *)p;
171 CoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
175 IMessageFilter * prev_filter = NULL;
176 hr = CoRegisterMessageFilter(data->filter, &prev_filter);
177 if (prev_filter) IMessageFilter_Release(prev_filter);
178 ok_ole_success(hr, CoRegisterMessageFilter);
181 hr = CoMarshalInterface(data->stream, &data->iid, data->object, MSHCTX_INPROC, NULL, data->marshal_flags);
182 ok_ole_success(hr, CoMarshalInterface);
184 /* force the message queue to be created before signaling parent thread */
185 PeekMessage(&msg, NULL, WM_USER, WM_USER, PM_NOREMOVE);
187 SetEvent(data->marshal_event);
189 while (GetMessage(&msg, NULL, 0, 0))
191 if (msg.hwnd == NULL && msg.message == RELEASEMARSHALDATA)
193 trace("releasing marshal data\n");
194 CoReleaseMarshalData(data->stream);
195 SetEvent((HANDLE)msg.lParam);
198 DispatchMessage(&msg);
201 HeapFree(GetProcessHeap(), 0, data);
208 static DWORD start_host_object2(IStream *stream, REFIID riid, IUnknown *object, MSHLFLAGS marshal_flags, IMessageFilter *filter, HANDLE *thread)
211 HANDLE marshal_event = CreateEvent(NULL, FALSE, FALSE, NULL);
212 struct host_object_data *data = (struct host_object_data *)HeapAlloc(GetProcessHeap(), 0, sizeof(*data));
214 data->stream = stream;
216 data->object = object;
217 data->marshal_flags = marshal_flags;
218 data->marshal_event = marshal_event;
219 data->filter = filter;
221 *thread = CreateThread(NULL, 0, host_object_proc, data, 0, &tid);
223 /* wait for marshaling to complete before returning */
224 WaitForSingleObject(marshal_event, INFINITE);
225 CloseHandle(marshal_event);
230 static DWORD start_host_object(IStream *stream, REFIID riid, IUnknown *object, MSHLFLAGS marshal_flags, HANDLE *thread)
232 return start_host_object2(stream, riid, object, marshal_flags, NULL, thread);
235 /* asks thread to release the marshal data because it has to be done by the
236 * same thread that marshaled the interface in the first place. */
237 static void release_host_object(DWORD tid)
239 HANDLE event = CreateEvent(NULL, FALSE, FALSE, NULL);
240 PostThreadMessage(tid, RELEASEMARSHALDATA, 0, (LPARAM)event);
241 WaitForSingleObject(event, INFINITE);
245 static void end_host_object(DWORD tid, HANDLE thread)
247 BOOL ret = PostThreadMessage(tid, WM_QUIT, 0, 0);
248 ok(ret, "PostThreadMessage failed with error %ld\n", GetLastError());
249 /* be careful of races - don't return until hosting thread has terminated */
250 WaitForSingleObject(thread, INFINITE);
254 /* tests normal marshal and then release without unmarshaling */
255 static void test_normal_marshal_and_release()
258 IStream *pStream = NULL;
262 hr = CreateStreamOnHGlobal(NULL, TRUE, &pStream);
263 ok_ole_success(hr, CreateStreamOnHGlobal);
264 hr = CoMarshalInterface(pStream, &IID_IClassFactory, (IUnknown*)&Test_ClassFactory, MSHCTX_INPROC, NULL, MSHLFLAGS_NORMAL);
265 ok_ole_success(hr, CoMarshalInterface);
267 ok_more_than_one_lock();
269 IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
270 hr = CoReleaseMarshalData(pStream);
271 ok_ole_success(hr, CoReleaseMarshalData);
272 IStream_Release(pStream);
277 /* tests success case of a same-thread marshal and unmarshal */
278 static void test_normal_marshal_and_unmarshal()
281 IStream *pStream = NULL;
282 IUnknown *pProxy = NULL;
286 hr = CreateStreamOnHGlobal(NULL, TRUE, &pStream);
287 ok_ole_success(hr, CreateStreamOnHGlobal);
288 hr = CoMarshalInterface(pStream, &IID_IClassFactory, (IUnknown*)&Test_ClassFactory, MSHCTX_INPROC, NULL, MSHLFLAGS_NORMAL);
289 ok_ole_success(hr, CoMarshalInterface);
291 ok_more_than_one_lock();
293 IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
294 hr = CoUnmarshalInterface(pStream, &IID_IClassFactory, (void **)&pProxy);
295 ok_ole_success(hr, CoUnmarshalInterface);
296 IStream_Release(pStream);
298 ok_more_than_one_lock();
300 IUnknown_Release(pProxy);
305 /* tests success case of an interthread marshal */
306 static void test_interthread_marshal_and_unmarshal()
309 IStream *pStream = NULL;
310 IUnknown *pProxy = NULL;
316 hr = CreateStreamOnHGlobal(NULL, TRUE, &pStream);
317 ok_ole_success(hr, CreateStreamOnHGlobal);
318 tid = start_host_object(pStream, &IID_IClassFactory, (IUnknown*)&Test_ClassFactory, MSHLFLAGS_NORMAL, &thread);
320 ok_more_than_one_lock();
322 IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
323 hr = CoUnmarshalInterface(pStream, &IID_IClassFactory, (void **)&pProxy);
324 ok_ole_success(hr, CoUnmarshalInterface);
325 IStream_Release(pStream);
327 ok_more_than_one_lock();
329 IUnknown_Release(pProxy);
333 end_host_object(tid, thread);
336 /* tests that stubs are released when the containing apartment is destroyed */
337 static void test_marshal_stub_apartment_shutdown()
340 IStream *pStream = NULL;
341 IUnknown *pProxy = NULL;
347 hr = CreateStreamOnHGlobal(NULL, TRUE, &pStream);
348 ok_ole_success(hr, CreateStreamOnHGlobal);
349 tid = start_host_object(pStream, &IID_IClassFactory, (IUnknown*)&Test_ClassFactory, MSHLFLAGS_NORMAL, &thread);
351 ok_more_than_one_lock();
353 IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
354 hr = CoUnmarshalInterface(pStream, &IID_IClassFactory, (void **)&pProxy);
355 ok_ole_success(hr, CoReleaseMarshalData);
356 IStream_Release(pStream);
358 ok_more_than_one_lock();
360 end_host_object(tid, thread);
364 IUnknown_Release(pProxy);
369 /* tests that proxies are released when the containing apartment is destroyed */
370 static void test_marshal_proxy_apartment_shutdown()
373 IStream *pStream = NULL;
374 IUnknown *pProxy = NULL;
380 hr = CreateStreamOnHGlobal(NULL, TRUE, &pStream);
381 ok_ole_success(hr, CreateStreamOnHGlobal);
382 tid = start_host_object(pStream, &IID_IClassFactory, (IUnknown*)&Test_ClassFactory, MSHLFLAGS_NORMAL, &thread);
384 ok_more_than_one_lock();
386 IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
387 hr = CoUnmarshalInterface(pStream, &IID_IClassFactory, (void **)&pProxy);
388 ok_ole_success(hr, CoReleaseMarshalData);
389 IStream_Release(pStream);
391 ok_more_than_one_lock();
397 IUnknown_Release(pProxy);
401 end_host_object(tid, thread);
403 CoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
406 /* tests success case of a same-thread table-weak marshal, unmarshal, unmarshal */
407 static void test_tableweak_marshal_and_unmarshal_twice()
410 IStream *pStream = NULL;
411 IUnknown *pProxy1 = NULL;
412 IUnknown *pProxy2 = NULL;
418 hr = CreateStreamOnHGlobal(NULL, TRUE, &pStream);
419 ok_ole_success(hr, CreateStreamOnHGlobal);
420 tid = start_host_object(pStream, &IID_IClassFactory, (IUnknown*)&Test_ClassFactory, MSHLFLAGS_TABLEWEAK, &thread);
422 ok_more_than_one_lock();
424 IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
425 hr = CoUnmarshalInterface(pStream, &IID_IClassFactory, (void **)&pProxy1);
426 ok_ole_success(hr, CoReleaseMarshalData);
428 ok_more_than_one_lock();
430 IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
431 hr = CoUnmarshalInterface(pStream, &IID_IClassFactory, (void **)&pProxy2);
432 ok_ole_success(hr, CoUnmarshalInterface);
434 ok_more_than_one_lock();
436 IUnknown_Release(pProxy1);
437 IUnknown_Release(pProxy2);
439 /* this line is shows the difference between weak and strong table marshaling:
440 * weak has cLocks == 0
441 * strong has cLocks > 0 */
444 end_host_object(tid, thread);
447 /* tests success case of a same-thread table-strong marshal, unmarshal, unmarshal */
448 static void test_tablestrong_marshal_and_unmarshal_twice()
451 IStream *pStream = NULL;
452 IUnknown *pProxy1 = NULL;
453 IUnknown *pProxy2 = NULL;
459 hr = CreateStreamOnHGlobal(NULL, TRUE, &pStream);
460 ok_ole_success(hr, CreateStreamOnHGlobal);
461 tid = start_host_object(pStream, &IID_IClassFactory, (IUnknown*)&Test_ClassFactory, MSHLFLAGS_TABLESTRONG, &thread);
463 ok_more_than_one_lock();
465 IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
466 hr = CoUnmarshalInterface(pStream, &IID_IClassFactory, (void **)&pProxy1);
467 ok_ole_success(hr, CoReleaseMarshalData);
469 ok_more_than_one_lock();
471 IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
472 hr = CoUnmarshalInterface(pStream, &IID_IClassFactory, (void **)&pProxy2);
473 ok_ole_success(hr, CoUnmarshalInterface);
475 ok_more_than_one_lock();
477 if (pProxy1) IUnknown_Release(pProxy1);
478 if (pProxy2) IUnknown_Release(pProxy2);
480 /* this line is shows the difference between weak and strong table marshaling:
481 * weak has cLocks == 0
482 * strong has cLocks > 0 */
483 ok_more_than_one_lock();
485 /* release the remaining reference on the object by calling
486 * CoReleaseMarshalData in the hosting thread */
487 IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
488 release_host_object(tid);
489 IStream_Release(pStream);
493 end_host_object(tid, thread);
496 /* tests CoLockObjectExternal */
497 static void test_lock_object_external()
500 IStream *pStream = NULL;
504 hr = CreateStreamOnHGlobal(NULL, TRUE, &pStream);
505 ok_ole_success(hr, CreateStreamOnHGlobal);
506 hr = CoMarshalInterface(pStream, &IID_IClassFactory, (IUnknown*)&Test_ClassFactory, MSHCTX_INPROC, NULL, MSHLFLAGS_NORMAL);
507 ok_ole_success(hr, CoMarshalInterface);
509 CoLockObjectExternal((IUnknown*)&Test_ClassFactory, TRUE, TRUE);
511 ok_more_than_one_lock();
513 IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
514 hr = CoReleaseMarshalData(pStream);
515 ok_ole_success(hr, CoReleaseMarshalData);
516 IStream_Release(pStream);
518 ok_more_than_one_lock();
520 CoLockObjectExternal((IUnknown*)&Test_ClassFactory, FALSE, TRUE);
525 /* tests disconnecting stubs */
526 static void test_disconnect_stub()
529 IStream *pStream = NULL;
533 hr = CreateStreamOnHGlobal(NULL, TRUE, &pStream);
534 ok_ole_success(hr, CreateStreamOnHGlobal);
535 hr = CoMarshalInterface(pStream, &IID_IClassFactory, (IUnknown*)&Test_ClassFactory, MSHCTX_INPROC, NULL, MSHLFLAGS_NORMAL);
536 ok_ole_success(hr, CoMarshalInterface);
538 CoLockObjectExternal((IUnknown*)&Test_ClassFactory, TRUE, TRUE);
540 ok_more_than_one_lock();
542 IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
543 hr = CoReleaseMarshalData(pStream);
544 ok_ole_success(hr, CoReleaseMarshalData);
545 IStream_Release(pStream);
547 ok_more_than_one_lock();
549 CoDisconnectObject((IUnknown*)&Test_ClassFactory, 0);
551 todo_wine { ok_no_locks(); }
554 /* tests failure case of a same-thread marshal and unmarshal twice */
555 static void test_normal_marshal_and_unmarshal_twice()
558 IStream *pStream = NULL;
559 IUnknown *pProxy1 = NULL;
560 IUnknown *pProxy2 = NULL;
564 hr = CreateStreamOnHGlobal(NULL, TRUE, &pStream);
565 ok_ole_success(hr, CreateStreamOnHGlobal);
566 hr = CoMarshalInterface(pStream, &IID_IClassFactory, (IUnknown*)&Test_ClassFactory, MSHCTX_INPROC, NULL, MSHLFLAGS_NORMAL);
567 ok_ole_success(hr, CoMarshalInterface);
569 ok_more_than_one_lock();
571 IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
572 hr = CoUnmarshalInterface(pStream, &IID_IClassFactory, (void **)&pProxy1);
573 ok_ole_success(hr, CoUnmarshalInterface);
575 ok_more_than_one_lock();
577 IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
578 hr = CoUnmarshalInterface(pStream, &IID_IClassFactory, (void **)&pProxy2);
579 ok(hr == CO_E_OBJNOTCONNECTED,
580 "CoUnmarshalInterface should have failed with error CO_E_OBJNOTCONNECTED for double unmarshal, instead of 0x%08lx\n", hr);
582 IStream_Release(pStream);
584 ok_more_than_one_lock();
586 IUnknown_Release(pProxy1);
591 /* tests success case of marshaling and unmarshaling an HRESULT */
592 static void test_hresult_marshaling()
595 HRESULT hr_marshaled = 0;
596 IStream *pStream = NULL;
597 static const HRESULT E_DEADBEEF = 0xdeadbeef;
599 hr = CreateStreamOnHGlobal(NULL, TRUE, &pStream);
600 ok_ole_success(hr, CreateStreamOnHGlobal);
602 hr = CoMarshalHresult(pStream, E_DEADBEEF);
603 ok_ole_success(hr, CoMarshalHresult);
605 IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
606 hr = IStream_Read(pStream, &hr_marshaled, sizeof(HRESULT), NULL);
607 ok_ole_success(hr, IStream_Read);
609 ok(hr_marshaled == E_DEADBEEF, "Didn't marshal HRESULT as expected: got value 0x%08lx instead\n", hr_marshaled);
612 IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
613 hr = CoUnmarshalHresult(pStream, &hr_marshaled);
614 ok_ole_success(hr, CoUnmarshalHresult);
616 ok(hr_marshaled == E_DEADBEEF, "Didn't marshal HRESULT as expected: got value 0x%08lx instead\n", hr_marshaled);
618 IStream_Release(pStream);
622 /* helper for test_proxy_used_in_wrong_thread */
623 static DWORD CALLBACK bad_thread_proc(LPVOID p)
625 IClassFactory * cf = (IClassFactory *)p;
627 IUnknown * proxy = NULL;
629 CoInitializeEx(NULL, COINIT_MULTITHREADED);
631 hr = IClassFactory_CreateInstance(cf, NULL, &IID_IUnknown, (LPVOID*)&proxy);
632 if (proxy) IUnknown_Release(proxy);
634 ok(hr == RPC_E_WRONG_THREAD,
635 "COM should have failed with RPC_E_WRONG_THREAD on using proxy from wrong apartment, but instead returned 0x%08lx\n",
644 /* tests failure case of a using a proxy in the wrong apartment */
645 static void test_proxy_used_in_wrong_thread()
648 IStream *pStream = NULL;
649 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, &host_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, CoReleaseMarshalData);
665 IStream_Release(pStream);
667 ok_more_than_one_lock();
669 /* create a thread that we can misbehave in */
670 thread = CreateThread(NULL, 0, bad_thread_proc, (LPVOID)pProxy, 0, &tid2);
672 WaitForSingleObject(thread, INFINITE);
675 IUnknown_Release(pProxy);
679 end_host_object(tid, host_thread);
682 static HRESULT WINAPI MessageFilter_QueryInterface(IMessageFilter *iface, REFIID riid, void ** ppvObj)
684 if (ppvObj == NULL) return E_POINTER;
686 if (IsEqualGUID(riid, &IID_IUnknown) ||
687 IsEqualGUID(riid, &IID_IClassFactory))
689 *ppvObj = (LPVOID)iface;
690 IClassFactory_AddRef(iface);
694 return E_NOINTERFACE;
697 static ULONG WINAPI MessageFilter_AddRef(IMessageFilter *iface)
699 return 2; /* non-heap object */
702 static ULONG WINAPI MessageFilter_Release(IMessageFilter *iface)
704 return 1; /* non-heap object */
707 static DWORD WINAPI MessageFilter_HandleInComingCall(
708 IMessageFilter *iface,
710 HTASK threadIDCaller,
712 LPINTERFACEINFO lpInterfaceInfo)
714 static int callcount = 0;
716 trace("HandleInComingCall\n");
720 ret = SERVERCALL_REJECTED;
723 ret = SERVERCALL_RETRYLATER;
726 ret = SERVERCALL_ISHANDLED;
733 static DWORD WINAPI MessageFilter_RetryRejectedCall(
734 IMessageFilter *iface,
735 HTASK threadIDCallee,
739 trace("RetryRejectedCall\n");
743 static DWORD WINAPI MessageFilter_MessagePending(
744 IMessageFilter *iface,
745 HTASK threadIDCallee,
749 trace("MessagePending\n");
750 return PENDINGMSG_WAITNOPROCESS;
753 static IMessageFilterVtbl MessageFilter_Vtbl =
755 MessageFilter_QueryInterface,
756 MessageFilter_AddRef,
757 MessageFilter_Release,
758 MessageFilter_HandleInComingCall,
759 MessageFilter_RetryRejectedCall,
760 MessageFilter_MessagePending
763 static IMessageFilter MessageFilter = { &MessageFilter_Vtbl };
765 static void test_message_filter()
768 IStream *pStream = NULL;
769 IClassFactory *cf = NULL;
771 IUnknown *proxy = NULL;
772 IMessageFilter *prev_filter = NULL;
777 hr = CreateStreamOnHGlobal(NULL, TRUE, &pStream);
778 ok_ole_success(hr, CreateStreamOnHGlobal);
779 tid = start_host_object2(pStream, &IID_IClassFactory, (IUnknown*)&Test_ClassFactory, MSHLFLAGS_NORMAL, &MessageFilter, &thread);
781 ok_more_than_one_lock();
783 IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
784 hr = CoUnmarshalInterface(pStream, &IID_IClassFactory, (void **)&cf);
785 ok_ole_success(hr, CoUnmarshalInterface);
786 IStream_Release(pStream);
788 ok_more_than_one_lock();
790 hr = IClassFactory_CreateInstance(cf, NULL, &IID_IUnknown, (LPVOID*)&proxy);
791 todo_wine { ok(hr == RPC_E_CALL_REJECTED, "Call should have returned RPC_E_CALL_REJECTED, but return 0x%08lx instead\n", hr); }
792 if (proxy) IUnknown_Release(proxy);
795 hr = CoRegisterMessageFilter(&MessageFilter, &prev_filter);
796 ok_ole_success(hr, CoRegisterMessageFilter);
797 if (prev_filter) IMessageFilter_Release(prev_filter);
799 hr = IClassFactory_CreateInstance(cf, NULL, &IID_IUnknown, (LPVOID*)&proxy);
800 ok_ole_success(hr, IClassFactory_CreateInstance);
802 IUnknown_Release(proxy);
804 IClassFactory_Release(cf);
806 /* FIXME: this is a regression caused by the fact that I faked the
807 * IUnknown unmarshaling too much and didn't give it its own ifstub. */
808 todo_wine { ok_no_locks(); }
810 end_host_object(tid, thread);
813 /* test failure case of trying to unmarshal from bad stream */
814 static void test_bad_marshal_stream()
817 IStream *pStream = NULL;
819 hr = CreateStreamOnHGlobal(NULL, TRUE, &pStream);
820 ok_ole_success(hr, CreateStreamOnHGlobal);
821 hr = CoMarshalInterface(pStream, &IID_IClassFactory, (IUnknown*)&Test_ClassFactory, MSHCTX_INPROC, NULL, MSHLFLAGS_NORMAL);
822 ok_ole_success(hr, CoMarshalInterface);
824 ok_more_than_one_lock();
826 /* try to read beyond end of stream */
827 hr = CoReleaseMarshalData(pStream);
828 ok(hr == STG_E_READFAULT, "Should have failed with STG_E_READFAULT, but returned 0x%08lx instead\n", hr);
830 /* now release for real */
831 IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
832 hr = CoReleaseMarshalData(pStream);
833 ok_ole_success(hr, CoReleaseMarshalData);
835 IStream_Release(pStream);
838 /* tests that proxies implement certain interfaces */
839 static void test_proxy_interfaces()
842 IStream *pStream = NULL;
843 IUnknown *pProxy = NULL;
844 IUnknown *pOtherUnknown = NULL;
847 static const IID IID_IMarshal2 =
852 { 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46 }
857 hr = CreateStreamOnHGlobal(NULL, TRUE, &pStream);
858 ok_ole_success(hr, CreateStreamOnHGlobal);
859 tid = start_host_object(pStream, &IID_IClassFactory, (IUnknown*)&Test_ClassFactory, MSHLFLAGS_NORMAL, &thread);
861 ok_more_than_one_lock();
863 IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
864 hr = CoUnmarshalInterface(pStream, &IID_IClassFactory, (void **)&pProxy);
865 ok_ole_success(hr, CoReleaseMarshalData);
866 IStream_Release(pStream);
868 ok_more_than_one_lock();
870 hr = IUnknown_QueryInterface(pProxy, &IID_IUnknown, (LPVOID*)&pOtherUnknown);
871 ok_ole_success(hr, IUnknown_QueryInterface IID_IUnknown);
872 if (hr == S_OK) IUnknown_Release(pOtherUnknown);
874 hr = IUnknown_QueryInterface(pProxy, &IID_IClientSecurity, (LPVOID*)&pOtherUnknown);
875 todo_wine { ok_ole_success(hr, IUnknown_QueryInterface IID_IClientSecurity); }
876 if (hr == S_OK) IUnknown_Release(pOtherUnknown);
878 hr = IUnknown_QueryInterface(pProxy, &IID_IMultiQI, (LPVOID*)&pOtherUnknown);
879 ok_ole_success(hr, IUnknown_QueryInterface IID_IMultiQI);
880 if (hr == S_OK) IUnknown_Release(pOtherUnknown);
882 hr = IUnknown_QueryInterface(pProxy, &IID_IMarshal, (LPVOID*)&pOtherUnknown);
883 todo_wine { ok_ole_success(hr, IUnknown_QueryInterface IID_IMarshal); }
884 if (hr == S_OK) IUnknown_Release(pOtherUnknown);
886 hr = IUnknown_QueryInterface(pProxy, &IID_IMarshal2, (LPVOID*)&pOtherUnknown);
887 todo_wine { ok_ole_success(hr, IUnknown_QueryInterface IID_IMarshal2); }
888 if (hr == S_OK) IUnknown_Release(pOtherUnknown);
890 IUnknown_Release(pProxy);
894 end_host_object(tid, thread);
898 /* doesn't pass with Win9x COM DLLs (even though Essential COM says it should) */
901 static HANDLE heventShutdown;
903 static void LockModuleOOP()
905 InterlockedIncrement(&cLocks); /* for test purposes only */
906 CoAddRefServerProcess();
909 static void UnlockModuleOOP()
911 InterlockedDecrement(&cLocks); /* for test purposes only */
912 if (!CoReleaseServerProcess())
913 SetEvent(heventShutdown);
917 static HRESULT WINAPI TestOOP_IClassFactory_QueryInterface(
918 LPCLASSFACTORY iface,
922 if (ppvObj == NULL) return E_POINTER;
924 if (IsEqualGUID(riid, &IID_IUnknown) ||
925 IsEqualGUID(riid, &IID_IClassFactory))
927 *ppvObj = (LPVOID)iface;
928 IClassFactory_AddRef(iface);
932 return E_NOINTERFACE;
935 static ULONG WINAPI TestOOP_IClassFactory_AddRef(LPCLASSFACTORY iface)
937 return 2; /* non-heap-based object */
940 static ULONG WINAPI TestOOP_IClassFactory_Release(LPCLASSFACTORY iface)
942 return 1; /* non-heap-based object */
945 static HRESULT WINAPI TestOOP_IClassFactory_CreateInstance(
946 LPCLASSFACTORY iface,
951 return CLASS_E_CLASSNOTAVAILABLE;
954 static HRESULT WINAPI TestOOP_IClassFactory_LockServer(
955 LPCLASSFACTORY iface,
965 static IClassFactoryVtbl TestClassFactoryOOP_Vtbl =
967 TestOOP_IClassFactory_QueryInterface,
968 TestOOP_IClassFactory_AddRef,
969 TestOOP_IClassFactory_Release,
970 TestOOP_IClassFactory_CreateInstance,
971 TestOOP_IClassFactory_LockServer
974 static IClassFactory TestOOP_ClassFactory = { &TestClassFactoryOOP_Vtbl };
976 /* tests functions commonly used by out of process COM servers */
977 static void test_out_of_process_com()
979 static const CLSID CLSID_WineOOPTest = {
983 {0xa1, 0xa2, 0x5d, 0x5a, 0x36, 0x54, 0xd3, 0xbd}
984 }; /* 5201163f-8164-4fd0-a1a2-5d5a3654d3bd */
990 heventShutdown = CreateEvent(NULL, TRUE, FALSE, NULL);
994 /* Start the object suspended */
995 hr = CoRegisterClassObject(&CLSID_WineOOPTest, (IUnknown *)&TestOOP_ClassFactory,
996 CLSCTX_LOCAL_SERVER, REGCLS_MULTIPLEUSE | REGCLS_SUSPENDED, &cookie);
997 ok_ole_success(hr, CoRegisterClassObject);
999 /* ... and CoGetClassObject does not find it and fails when it looks for the
1000 * class in the registry */
1001 hr = CoGetClassObject(&CLSID_WineOOPTest, CLSCTX_INPROC_SERVER,
1002 NULL, &IID_IClassFactory, (LPVOID*)&cf);
1004 ok(hr == REGDB_E_CLASSNOTREG,
1005 "CoGetClassObject should have returned REGDB_E_CLASSNOTREG instead of 0x%08lx\n", hr);
1008 /* Resume the object suspended above ... */
1009 hr = CoResumeClassObjects();
1010 ok_ole_success(hr, CoResumeClassObjects);
1012 /* ... and now it should succeed */
1013 hr = CoGetClassObject(&CLSID_WineOOPTest, CLSCTX_INPROC_SERVER,
1014 NULL, &IID_IClassFactory, (LPVOID*)&cf);
1015 ok_ole_success(hr, CoGetClassObject);
1017 /* Now check the locking is working */
1018 /* NOTE: we are accessing the class directly, not through a proxy */
1022 hr = IClassFactory_LockServer(cf, TRUE);
1023 trace("IClassFactory_LockServer returned 0x%08lx\n", hr);
1025 ok_more_than_one_lock();
1027 IClassFactory_LockServer(cf, FALSE);
1031 IClassFactory_Release(cf);
1033 /* wait for shutdown signal */
1034 ret = WaitForSingleObject(heventShutdown, 5000);
1035 todo_wine { ok(ret != WAIT_TIMEOUT, "Server didn't shut down or machine is under very heavy load\n"); }
1037 /* try to connect again after SCM has suspended registered class objects */
1038 hr = CoGetClassObject(&CLSID_WineOOPTest, CLSCTX_INPROC_SERVER | CLSCTX_LOCAL_SERVER, NULL,
1039 &IID_IClassFactory, (LPVOID*)&cf);
1041 ok(hr == CO_E_SERVER_STOPPING,
1042 "CoGetClassObject should have returned CO_E_SERVER_STOPPING instead of 0x%08lx\n", hr);
1045 hr = CoRevokeClassObject(cookie);
1046 ok_ole_success(hr, CoRevokeClassObject);
1048 CloseHandle(heventShutdown);
1054 HMODULE hOle32 = GetModuleHandle("ole32");
1055 if (!(pCoInitializeEx = (void*)GetProcAddress(hOle32, "CoInitializeEx"))) goto no_test;
1057 pCoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
1059 /* FIXME: test CoCreateInstanceEx */
1061 /* lifecycle management and marshaling tests */
1062 test_normal_marshal_and_release();
1063 test_normal_marshal_and_unmarshal();
1064 test_interthread_marshal_and_unmarshal();
1065 test_marshal_stub_apartment_shutdown();
1066 test_marshal_proxy_apartment_shutdown();
1067 test_tableweak_marshal_and_unmarshal_twice();
1068 test_tablestrong_marshal_and_unmarshal_twice();
1069 test_lock_object_external();
1070 test_disconnect_stub();
1071 test_normal_marshal_and_unmarshal_twice();
1072 test_hresult_marshaling();
1073 test_proxy_used_in_wrong_thread();
1074 test_message_filter();
1075 test_bad_marshal_stream();
1076 test_proxy_interfaces();
1077 /* FIXME: test custom marshaling */
1078 /* FIXME: test GIT */
1079 /* FIXME: test COM re-entrancy */
1081 /* test_out_of_process_com(); */
1086 trace("You need DCOM95 installed to run this test\n");