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_IClassFactory_QueryInterface(
59 if (ppvObj == NULL) return E_POINTER;
61 if (IsEqualGUID(riid, &IID_IUnknown) ||
62 IsEqualGUID(riid, &IID_IClassFactory))
64 *ppvObj = (LPVOID)iface;
65 IClassFactory_AddRef(iface);
72 static ULONG WINAPI Test_IClassFactory_AddRef(LPCLASSFACTORY iface)
75 return 2; /* non-heap-based object */
78 static ULONG WINAPI Test_IClassFactory_Release(LPCLASSFACTORY iface)
81 return 1; /* non-heap-based object */
84 static HRESULT WINAPI Test_IClassFactory_CreateInstance(
90 return CLASS_E_CLASSNOTAVAILABLE;
93 static HRESULT WINAPI Test_IClassFactory_LockServer(
100 static IClassFactoryVtbl TestClassFactory_Vtbl =
102 Test_IClassFactory_QueryInterface,
103 Test_IClassFactory_AddRef,
104 Test_IClassFactory_Release,
105 Test_IClassFactory_CreateInstance,
106 Test_IClassFactory_LockServer
109 static IClassFactory Test_ClassFactory = { &TestClassFactory_Vtbl };
111 #define RELEASEMARSHALDATA WM_USER
113 struct host_object_data
118 MSHLFLAGS marshal_flags;
119 HANDLE marshal_event;
120 IMessageFilter *filter;
123 static DWORD CALLBACK host_object_proc(LPVOID p)
125 struct host_object_data *data = (struct host_object_data *)p;
129 CoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
133 IMessageFilter * prev_filter = NULL;
134 hr = CoRegisterMessageFilter(data->filter, &prev_filter);
135 if (prev_filter) IMessageFilter_Release(prev_filter);
136 ok_ole_success(hr, CoRegisterMessageFilter);
139 hr = CoMarshalInterface(data->stream, &data->iid, data->object, MSHCTX_INPROC, NULL, data->marshal_flags);
140 ok_ole_success(hr, CoMarshalInterface);
142 SetEvent(data->marshal_event);
144 while (GetMessage(&msg, NULL, 0, 0))
146 if (msg.hwnd == NULL && msg.message == RELEASEMARSHALDATA)
148 trace("releasing marshal data\n");
149 CoReleaseMarshalData(data->stream);
150 SetEvent((HANDLE)msg.lParam);
153 DispatchMessage(&msg);
156 HeapFree(GetProcessHeap(), 0, data);
163 static DWORD start_host_object2(IStream *stream, REFIID riid, IUnknown *object, MSHLFLAGS marshal_flags, IMessageFilter *filter, HANDLE *thread)
166 HANDLE marshal_event = CreateEvent(NULL, FALSE, FALSE, NULL);
167 struct host_object_data *data = (struct host_object_data *)HeapAlloc(GetProcessHeap(), 0, sizeof(*data));
169 data->stream = stream;
171 data->object = object;
172 data->marshal_flags = marshal_flags;
173 data->marshal_event = marshal_event;
174 data->filter = filter;
176 *thread = CreateThread(NULL, 0, host_object_proc, data, 0, &tid);
178 /* wait for marshaling to complete before returning */
179 WaitForSingleObject(marshal_event, INFINITE);
180 CloseHandle(marshal_event);
185 static DWORD start_host_object(IStream *stream, REFIID riid, IUnknown *object, MSHLFLAGS marshal_flags, HANDLE *thread)
187 return start_host_object2(stream, riid, object, marshal_flags, NULL, thread);
190 /* asks thread to release the marshal data because it has to be done by the
191 * same thread that marshaled the interface in the first place. */
192 static void release_host_object(DWORD tid)
194 HANDLE event = CreateEvent(NULL, FALSE, FALSE, NULL);
195 PostThreadMessage(tid, RELEASEMARSHALDATA, 0, (LPARAM)event);
196 WaitForSingleObject(event, INFINITE);
200 static void end_host_object(DWORD tid, HANDLE thread)
202 PostThreadMessage(tid, WM_QUIT, 0, 0);
203 /* be careful of races - don't return until hosting thread has terminated */
204 WaitForSingleObject(thread, INFINITE);
208 /* tests normal marshal and then release without unmarshaling */
209 static void test_normal_marshal_and_release()
212 IStream *pStream = NULL;
216 hr = CreateStreamOnHGlobal(NULL, TRUE, &pStream);
217 ok_ole_success(hr, CreateStreamOnHGlobal);
218 hr = CoMarshalInterface(pStream, &IID_IClassFactory, (IUnknown*)&Test_ClassFactory, MSHCTX_INPROC, NULL, MSHLFLAGS_NORMAL);
219 ok_ole_success(hr, CoMarshalInterface);
221 ok_more_than_one_lock();
223 IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
224 hr = CoReleaseMarshalData(pStream);
225 ok_ole_success(hr, CoReleaseMarshalData);
226 IStream_Release(pStream);
231 /* tests success case of a same-thread marshal and unmarshal */
232 static void test_normal_marshal_and_unmarshal()
235 IStream *pStream = NULL;
236 IUnknown *pProxy = NULL;
240 hr = CreateStreamOnHGlobal(NULL, TRUE, &pStream);
241 ok_ole_success(hr, CreateStreamOnHGlobal);
242 hr = CoMarshalInterface(pStream, &IID_IClassFactory, (IUnknown*)&Test_ClassFactory, MSHCTX_INPROC, NULL, MSHLFLAGS_NORMAL);
243 ok_ole_success(hr, CoMarshalInterface);
245 ok_more_than_one_lock();
247 IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
248 hr = CoUnmarshalInterface(pStream, &IID_IClassFactory, (void **)&pProxy);
249 ok_ole_success(hr, CoUnmarshalInterface);
250 IStream_Release(pStream);
252 ok_more_than_one_lock();
254 IUnknown_Release(pProxy);
259 /* tests success case of an interthread marshal */
260 static void test_interthread_marshal_and_unmarshal()
263 IStream *pStream = NULL;
264 IUnknown *pProxy = NULL;
270 hr = CreateStreamOnHGlobal(NULL, TRUE, &pStream);
271 ok_ole_success(hr, CreateStreamOnHGlobal);
272 tid = start_host_object(pStream, &IID_IClassFactory, (IUnknown*)&Test_ClassFactory, MSHLFLAGS_NORMAL, &thread);
274 ok_more_than_one_lock();
276 IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
277 hr = CoUnmarshalInterface(pStream, &IID_IClassFactory, (void **)&pProxy);
278 ok_ole_success(hr, CoReleaseMarshalData);
279 IStream_Release(pStream);
281 ok_more_than_one_lock();
283 IUnknown_Release(pProxy);
287 end_host_object(tid, thread);
290 /* tests that stubs are released when the containing apartment is destroyed */
291 static void test_marshal_stub_apartment_shutdown()
294 IStream *pStream = NULL;
295 IUnknown *pProxy = NULL;
301 hr = CreateStreamOnHGlobal(NULL, TRUE, &pStream);
302 ok_ole_success(hr, CreateStreamOnHGlobal);
303 tid = start_host_object(pStream, &IID_IClassFactory, (IUnknown*)&Test_ClassFactory, MSHLFLAGS_NORMAL, &thread);
305 ok_more_than_one_lock();
307 IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
308 hr = CoUnmarshalInterface(pStream, &IID_IClassFactory, (void **)&pProxy);
309 ok_ole_success(hr, CoReleaseMarshalData);
310 IStream_Release(pStream);
312 ok_more_than_one_lock();
314 end_host_object(tid, thread);
316 todo_wine { ok_no_locks(); }
318 IUnknown_Release(pProxy);
323 /* tests that proxies are released when the containing apartment is destroyed */
324 static void test_marshal_proxy_apartment_shutdown()
327 IStream *pStream = NULL;
328 IUnknown *pProxy = NULL;
334 hr = CreateStreamOnHGlobal(NULL, TRUE, &pStream);
335 ok_ole_success(hr, CreateStreamOnHGlobal);
336 tid = start_host_object(pStream, &IID_IClassFactory, (IUnknown*)&Test_ClassFactory, MSHLFLAGS_NORMAL, &thread);
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, CoReleaseMarshalData);
343 IStream_Release(pStream);
345 ok_more_than_one_lock();
349 /* FIXME: this could be a bit racy - I don't know if there are any
350 * guarantees that the stub will get its disconnection message
352 todo_wine { ok_no_locks(); }
354 IUnknown_Release(pProxy);
358 end_host_object(tid, thread);
360 CoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
363 /* tests success case of a same-thread table-weak marshal, unmarshal, unmarshal */
364 static void test_tableweak_marshal_and_unmarshal_twice()
367 IStream *pStream = NULL;
368 IUnknown *pProxy1 = NULL;
369 IUnknown *pProxy2 = NULL;
375 hr = CreateStreamOnHGlobal(NULL, TRUE, &pStream);
376 ok_ole_success(hr, CreateStreamOnHGlobal);
377 tid = start_host_object(pStream, &IID_IClassFactory, (IUnknown*)&Test_ClassFactory, MSHLFLAGS_TABLEWEAK, &thread);
379 ok_more_than_one_lock();
381 IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
382 hr = CoUnmarshalInterface(pStream, &IID_IClassFactory, (void **)&pProxy1);
383 ok_ole_success(hr, CoReleaseMarshalData);
385 ok_more_than_one_lock();
387 IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
388 hr = CoUnmarshalInterface(pStream, &IID_IClassFactory, (void **)&pProxy2);
389 ok_ole_success(hr, CoUnmarshalInterface);
391 ok_more_than_one_lock();
393 IUnknown_Release(pProxy1);
394 IUnknown_Release(pProxy2);
396 /* this line is shows the difference between weak and strong table marshaling:
397 * weak has cLocks == 0
398 * strong has cLocks > 0 */
399 todo_wine { ok_no_locks(); }
401 end_host_object(tid, thread);
404 /* tests success case of a same-thread table-strong marshal, unmarshal, unmarshal */
405 static void test_tablestrong_marshal_and_unmarshal_twice()
408 IStream *pStream = NULL;
409 IUnknown *pProxy1 = NULL;
410 IUnknown *pProxy2 = NULL;
416 hr = CreateStreamOnHGlobal(NULL, TRUE, &pStream);
417 ok_ole_success(hr, CreateStreamOnHGlobal);
418 tid = start_host_object(pStream, &IID_IClassFactory, (IUnknown*)&Test_ClassFactory, MSHLFLAGS_TABLESTRONG, &thread);
420 ok_more_than_one_lock();
422 IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
423 hr = CoUnmarshalInterface(pStream, &IID_IClassFactory, (void **)&pProxy1);
424 ok_ole_success(hr, CoReleaseMarshalData);
426 ok_more_than_one_lock();
428 IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
429 hr = CoUnmarshalInterface(pStream, &IID_IClassFactory, (void **)&pProxy2);
430 ok_ole_success(hr, CoUnmarshalInterface);
432 ok_more_than_one_lock();
434 if (pProxy1) IUnknown_Release(pProxy1);
435 if (pProxy2) IUnknown_Release(pProxy2);
437 /* this line is shows the difference between weak and strong table marshaling:
438 * weak has cLocks == 0
439 * strong has cLocks > 0 */
440 ok_more_than_one_lock();
442 /* release the remaining reference on the object by calling
443 * CoReleaseMarshalData in the hosting thread */
444 IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
445 release_host_object(tid);
446 IStream_Release(pStream);
448 todo_wine { ok_no_locks(); }
450 end_host_object(tid, thread);
453 /* tests CoLockObjectExternal */
454 static void test_lock_object_external()
457 IStream *pStream = NULL;
461 hr = CreateStreamOnHGlobal(NULL, TRUE, &pStream);
462 ok_ole_success(hr, CreateStreamOnHGlobal);
463 hr = CoMarshalInterface(pStream, &IID_IClassFactory, (IUnknown*)&Test_ClassFactory, MSHCTX_INPROC, NULL, MSHLFLAGS_NORMAL);
464 ok_ole_success(hr, CoMarshalInterface);
466 CoLockObjectExternal((IUnknown*)&Test_ClassFactory, TRUE, TRUE);
468 ok_more_than_one_lock();
470 IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
471 hr = CoReleaseMarshalData(pStream);
472 ok_ole_success(hr, CoReleaseMarshalData);
473 IStream_Release(pStream);
475 ok_more_than_one_lock();
477 CoLockObjectExternal((IUnknown*)&Test_ClassFactory, FALSE, TRUE);
482 /* tests disconnecting stubs */
483 static void test_disconnect_stub()
486 IStream *pStream = NULL;
490 hr = CreateStreamOnHGlobal(NULL, TRUE, &pStream);
491 ok_ole_success(hr, CreateStreamOnHGlobal);
492 hr = CoMarshalInterface(pStream, &IID_IClassFactory, (IUnknown*)&Test_ClassFactory, MSHCTX_INPROC, NULL, MSHLFLAGS_NORMAL);
493 ok_ole_success(hr, CoMarshalInterface);
495 CoLockObjectExternal((IUnknown*)&Test_ClassFactory, TRUE, TRUE);
497 ok_more_than_one_lock();
499 IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
500 hr = CoReleaseMarshalData(pStream);
501 ok_ole_success(hr, CoReleaseMarshalData);
502 IStream_Release(pStream);
504 ok_more_than_one_lock();
506 CoDisconnectObject((IUnknown*)&Test_ClassFactory, 0);
508 todo_wine { ok_no_locks(); }
511 /* tests failure case of a same-thread marshal and unmarshal twice */
512 static void test_normal_marshal_and_unmarshal_twice()
515 IStream *pStream = NULL;
516 IUnknown *pProxy1 = NULL;
517 IUnknown *pProxy2 = NULL;
521 hr = CreateStreamOnHGlobal(NULL, TRUE, &pStream);
522 ok_ole_success(hr, CreateStreamOnHGlobal);
523 hr = CoMarshalInterface(pStream, &IID_IClassFactory, (IUnknown*)&Test_ClassFactory, MSHCTX_INPROC, NULL, MSHLFLAGS_NORMAL);
524 ok_ole_success(hr, CoMarshalInterface);
526 ok_more_than_one_lock();
528 IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
529 hr = CoUnmarshalInterface(pStream, &IID_IClassFactory, (void **)&pProxy1);
530 ok_ole_success(hr, CoUnmarshalInterface);
532 ok_more_than_one_lock();
534 IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
535 hr = CoUnmarshalInterface(pStream, &IID_IClassFactory, (void **)&pProxy2);
537 ok(hr == CO_E_OBJNOTCONNECTED,
538 "CoUnmarshalInterface should have failed with error CO_E_OBJNOTCONNECTED for double unmarshal, instead of 0x%08lx\n", hr);
541 IStream_Release(pStream);
543 ok_more_than_one_lock();
545 IUnknown_Release(pProxy1);
550 /* tests success case of marshaling and unmarshaling an HRESULT */
551 static void test_hresult_marshaling()
554 HRESULT hr_marshaled = 0;
555 IStream *pStream = NULL;
556 static const HRESULT E_DEADBEEF = 0xdeadbeef;
558 hr = CreateStreamOnHGlobal(NULL, TRUE, &pStream);
559 ok_ole_success(hr, CreateStreamOnHGlobal);
561 hr = CoMarshalHresult(pStream, E_DEADBEEF);
562 ok_ole_success(hr, CoMarshalHresult);
564 IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
565 hr = IStream_Read(pStream, &hr_marshaled, sizeof(HRESULT), NULL);
566 ok_ole_success(hr, IStream_Read);
568 ok(hr_marshaled == E_DEADBEEF, "Didn't marshal HRESULT as expected: got value 0x%08lx instead\n", hr_marshaled);
571 IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
572 hr = CoUnmarshalHresult(pStream, &hr_marshaled);
573 ok_ole_success(hr, CoUnmarshalHresult);
575 ok(hr_marshaled == E_DEADBEEF, "Didn't marshal HRESULT as expected: got value 0x%08lx instead\n", hr_marshaled);
577 IStream_Release(pStream);
581 /* helper for test_proxy_used_in_wrong_thread */
582 static DWORD CALLBACK bad_thread_proc(LPVOID p)
584 IClassFactory * cf = (IClassFactory *)p;
588 CoInitializeEx(NULL, COINIT_MULTITHREADED);
590 hr = IClassFactory_CreateInstance(cf, NULL, &IID_IUnknown, (LPVOID*)&dummy);
593 ok(hr == RPC_E_WRONG_THREAD,
594 "COM should have failed with RPC_E_WRONG_THREAD on using proxy from wrong apartment, but instead returned 0x%08lx\n",
603 /* tests failure case of a using a proxy in the wrong apartment */
604 static void test_proxy_used_in_wrong_thread()
607 IStream *pStream = NULL;
608 IUnknown *pProxy = NULL;
615 hr = CreateStreamOnHGlobal(NULL, TRUE, &pStream);
616 ok_ole_success(hr, CreateStreamOnHGlobal);
617 tid = start_host_object(pStream, &IID_IClassFactory, (IUnknown*)&Test_ClassFactory, MSHLFLAGS_NORMAL, &host_thread);
619 ok_more_than_one_lock();
621 IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
622 hr = CoUnmarshalInterface(pStream, &IID_IClassFactory, (void **)&pProxy);
623 ok_ole_success(hr, CoReleaseMarshalData);
624 IStream_Release(pStream);
626 ok_more_than_one_lock();
628 /* create a thread that we can misbehave in */
629 thread = CreateThread(NULL, 0, bad_thread_proc, (LPVOID)pProxy, 0, &tid2);
631 WaitForSingleObject(thread, INFINITE);
634 IUnknown_Release(pProxy);
638 end_host_object(tid, host_thread);
641 static HRESULT WINAPI MessageFilter_QueryInterface(IMessageFilter *iface, REFIID riid, void ** ppvObj)
643 if (ppvObj == NULL) return E_POINTER;
645 if (IsEqualGUID(riid, &IID_IUnknown) ||
646 IsEqualGUID(riid, &IID_IClassFactory))
648 *ppvObj = (LPVOID)iface;
649 IClassFactory_AddRef(iface);
653 return E_NOINTERFACE;
656 static ULONG WINAPI MessageFilter_AddRef(IMessageFilter *iface)
658 return 2; /* non-heap object */
661 static ULONG WINAPI MessageFilter_Release(IMessageFilter *iface)
663 return 1; /* non-heap object */
666 static DWORD WINAPI MessageFilter_HandleInComingCall(
667 IMessageFilter *iface,
669 HTASK threadIDCaller,
671 LPINTERFACEINFO lpInterfaceInfo)
673 static int callcount = 0;
675 trace("HandleInComingCall\n");
679 ret = SERVERCALL_REJECTED;
682 ret = SERVERCALL_RETRYLATER;
685 ret = SERVERCALL_ISHANDLED;
692 static DWORD WINAPI MessageFilter_RetryRejectedCall(
693 IMessageFilter *iface,
694 HTASK threadIDCallee,
698 trace("RetryRejectedCall\n");
702 static DWORD WINAPI MessageFilter_MessagePending(
703 IMessageFilter *iface,
704 HTASK threadIDCallee,
708 trace("MessagePending\n");
709 return PENDINGMSG_WAITNOPROCESS;
712 static IMessageFilterVtbl MessageFilter_Vtbl =
714 MessageFilter_QueryInterface,
715 MessageFilter_AddRef,
716 MessageFilter_Release,
717 MessageFilter_HandleInComingCall,
718 MessageFilter_RetryRejectedCall,
719 MessageFilter_MessagePending
722 static IMessageFilter MessageFilter = { &MessageFilter_Vtbl };
724 static void test_message_filter()
727 IStream *pStream = NULL;
728 IClassFactory *cf = NULL;
731 IMessageFilter *prev_filter = NULL;
736 hr = CreateStreamOnHGlobal(NULL, TRUE, &pStream);
737 ok_ole_success(hr, CreateStreamOnHGlobal);
738 tid = start_host_object2(pStream, &IID_IClassFactory, (IUnknown*)&Test_ClassFactory, MSHLFLAGS_NORMAL, &MessageFilter, &thread);
740 ok_more_than_one_lock();
742 IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
743 hr = CoUnmarshalInterface(pStream, &IID_IClassFactory, (void **)&cf);
744 ok_ole_success(hr, CoReleaseMarshalData);
745 IStream_Release(pStream);
747 ok_more_than_one_lock();
749 hr = IClassFactory_CreateInstance(cf, NULL, &IID_IUnknown, (LPVOID*)&dummy);
750 todo_wine { ok(hr == RPC_E_CALL_REJECTED, "Call should have returned RPC_E_CALL_REJECTED, but return 0x%08lx instead\n", hr); }
752 hr = CoRegisterMessageFilter(&MessageFilter, &prev_filter);
753 ok_ole_success(hr, CoRegisterMessageFilter);
754 if (prev_filter) IMessageFilter_Release(prev_filter);
756 hr = IClassFactory_CreateInstance(cf, NULL, &IID_IUnknown, (LPVOID*)&dummy);
757 ok(hr == CLASS_E_CLASSNOTAVAILABLE, "Call didn't wasn't accepted. hr = 0x%08lx\n", hr);
759 IClassFactory_Release(cf);
763 end_host_object(tid, thread);
767 /* doesn't pass with Win9x COM DLLs (even though Essential COM says it should) */
770 static HANDLE heventShutdown;
772 static void LockModuleOOP()
774 InterlockedIncrement(&cLocks); /* for test purposes only */
775 CoAddRefServerProcess();
778 static void UnlockModuleOOP()
780 InterlockedDecrement(&cLocks); /* for test purposes only */
781 if (!CoReleaseServerProcess())
782 SetEvent(heventShutdown);
786 static HRESULT WINAPI TestOOP_IClassFactory_QueryInterface(
787 LPCLASSFACTORY iface,
791 if (ppvObj == NULL) return E_POINTER;
793 if (IsEqualGUID(riid, &IID_IUnknown) ||
794 IsEqualGUID(riid, &IID_IClassFactory))
796 *ppvObj = (LPVOID)iface;
797 IClassFactory_AddRef(iface);
801 return E_NOINTERFACE;
804 static ULONG WINAPI TestOOP_IClassFactory_AddRef(LPCLASSFACTORY iface)
806 return 2; /* non-heap-based object */
809 static ULONG WINAPI TestOOP_IClassFactory_Release(LPCLASSFACTORY iface)
811 return 1; /* non-heap-based object */
814 static HRESULT WINAPI TestOOP_IClassFactory_CreateInstance(
815 LPCLASSFACTORY iface,
820 return CLASS_E_CLASSNOTAVAILABLE;
823 static HRESULT WINAPI TestOOP_IClassFactory_LockServer(
824 LPCLASSFACTORY iface,
834 static IClassFactoryVtbl TestClassFactoryOOP_Vtbl =
836 TestOOP_IClassFactory_QueryInterface,
837 TestOOP_IClassFactory_AddRef,
838 TestOOP_IClassFactory_Release,
839 TestOOP_IClassFactory_CreateInstance,
840 TestOOP_IClassFactory_LockServer
843 static IClassFactory TestOOP_ClassFactory = { &TestClassFactoryOOP_Vtbl };
845 /* tests functions commonly used by out of process COM servers */
846 static void test_out_of_process_com()
848 static const CLSID CLSID_WineOOPTest = {
852 {0xa1, 0xa2, 0x5d, 0x5a, 0x36, 0x54, 0xd3, 0xbd}
853 }; /* 5201163f-8164-4fd0-a1a2-5d5a3654d3bd */
859 heventShutdown = CreateEvent(NULL, TRUE, FALSE, NULL);
863 /* Start the object suspended */
864 hr = CoRegisterClassObject(&CLSID_WineOOPTest, (IUnknown *)&TestOOP_ClassFactory,
865 CLSCTX_LOCAL_SERVER, REGCLS_MULTIPLEUSE | REGCLS_SUSPENDED, &cookie);
866 ok_ole_success(hr, CoRegisterClassObject);
868 /* ... and CoGetClassObject does not find it and fails when it looks for the
869 * class in the registry */
870 hr = CoGetClassObject(&CLSID_WineOOPTest, CLSCTX_INPROC_SERVER,
871 NULL, &IID_IClassFactory, (LPVOID*)&cf);
873 ok(hr == REGDB_E_CLASSNOTREG,
874 "CoGetClassObject should have returned REGDB_E_CLASSNOTREG instead of 0x%08lx\n", hr);
877 /* Resume the object suspended above ... */
878 hr = CoResumeClassObjects();
879 ok_ole_success(hr, CoResumeClassObjects);
881 /* ... and now it should succeed */
882 hr = CoGetClassObject(&CLSID_WineOOPTest, CLSCTX_INPROC_SERVER,
883 NULL, &IID_IClassFactory, (LPVOID*)&cf);
884 ok_ole_success(hr, CoGetClassObject);
886 /* Now check the locking is working */
887 /* NOTE: we are accessing the class directly, not through a proxy */
891 hr = IClassFactory_LockServer(cf, TRUE);
892 trace("IClassFactory_LockServer returned 0x%08lx\n", hr);
894 ok_more_than_one_lock();
896 IClassFactory_LockServer(cf, FALSE);
900 IClassFactory_Release(cf);
902 /* wait for shutdown signal */
903 ret = WaitForSingleObject(heventShutdown, 5000);
904 todo_wine { ok(ret != WAIT_TIMEOUT, "Server didn't shut down or machine is under very heavy load\n"); }
906 /* try to connect again after SCM has suspended registered class objects */
907 hr = CoGetClassObject(&CLSID_WineOOPTest, CLSCTX_INPROC_SERVER | CLSCTX_LOCAL_SERVER, NULL,
908 &IID_IClassFactory, (LPVOID*)&cf);
910 ok(hr == CO_E_SERVER_STOPPING,
911 "CoGetClassObject should have returned CO_E_SERVER_STOPPING instead of 0x%08lx\n", hr);
914 hr = CoRevokeClassObject(cookie);
915 ok_ole_success(hr, CoRevokeClassObject);
917 CloseHandle(heventShutdown);
923 HMODULE hOle32 = GetModuleHandle("ole32");
924 if (!(pCoInitializeEx = (void*)GetProcAddress(hOle32, "CoInitializeEx"))) goto no_test;
926 pCoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
928 /* FIXME: test CoCreateInstanceEx */
930 /* lifecycle management and marshaling tests */
931 test_normal_marshal_and_release();
932 test_normal_marshal_and_unmarshal();
933 test_interthread_marshal_and_unmarshal();
934 test_marshal_stub_apartment_shutdown();
935 test_marshal_proxy_apartment_shutdown();
936 test_tableweak_marshal_and_unmarshal_twice();
937 test_tablestrong_marshal_and_unmarshal_twice();
938 test_lock_object_external();
939 test_disconnect_stub();
940 test_normal_marshal_and_unmarshal_twice();
941 test_hresult_marshaling();
942 test_proxy_used_in_wrong_thread();
943 test_message_filter();
944 /* FIXME: test custom marshaling */
945 /* FIXME: test GIT */
946 /* FIXME: test COM re-entrancy */
948 /* test_out_of_process_com(); */
953 trace("You need DCOM95 installed to run this test\n");