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 void test_CoGetPSClsid()
44 static const CLSID IID_IWineTest
= {
48 {0xa1, 0xa2, 0x5d, 0x5a, 0x36, 0x54, 0xd3, 0xbd}
49 }; /* 5201163f-8164-4fd0-a1a2-5d5a3654d3bd */
51 hr
= CoGetPSClsid(&IID_IClassFactory
, &clsid
);
52 ok_ole_success(hr
, CoGetPSClsid
);
54 hr
= CoGetPSClsid(&IID_IWineTest
, &clsid
);
55 ok(hr
== REGDB_E_IIDNOTREG
,
56 "CoGetPSClsid for random IID returned 0x%08lx instead of REGDB_E_IIDNOTREG\n",
60 static const LARGE_INTEGER ullZero
;
63 static void LockModule()
65 InterlockedIncrement(&cLocks
);
68 static void UnlockModule()
70 InterlockedDecrement(&cLocks
);
74 static HRESULT WINAPI
Test_IUnknown_QueryInterface(
79 if (ppvObj
== NULL
) return E_POINTER
;
81 if (IsEqualGUID(riid
, &IID_IUnknown
))
83 *ppvObj
= (LPVOID
)iface
;
84 IUnknown_AddRef(iface
);
92 static ULONG WINAPI
Test_IUnknown_AddRef(LPUNKNOWN iface
)
95 return 2; /* non-heap-based object */
98 static ULONG WINAPI
Test_IUnknown_Release(LPUNKNOWN iface
)
101 return 1; /* non-heap-based object */
104 static const IUnknownVtbl TestUnknown_Vtbl
=
106 Test_IUnknown_QueryInterface
,
107 Test_IUnknown_AddRef
,
108 Test_IUnknown_Release
,
111 static IUnknown Test_Unknown
= { &TestUnknown_Vtbl
};
114 static HRESULT WINAPI
Test_IClassFactory_QueryInterface(
115 LPCLASSFACTORY iface
,
119 if (ppvObj
== NULL
) return E_POINTER
;
121 if (IsEqualGUID(riid
, &IID_IUnknown
) ||
122 IsEqualGUID(riid
, &IID_IClassFactory
))
124 *ppvObj
= (LPVOID
)iface
;
125 IClassFactory_AddRef(iface
);
130 return E_NOINTERFACE
;
133 static ULONG WINAPI
Test_IClassFactory_AddRef(LPCLASSFACTORY iface
)
136 return 2; /* non-heap-based object */
139 static ULONG WINAPI
Test_IClassFactory_Release(LPCLASSFACTORY iface
)
142 return 1; /* non-heap-based object */
145 static HRESULT WINAPI
Test_IClassFactory_CreateInstance(
146 LPCLASSFACTORY iface
,
151 if (pUnkOuter
) return CLASS_E_NOAGGREGATION
;
152 return IUnknown_QueryInterface((IUnknown
*)&Test_Unknown
, riid
, ppvObj
);
155 static HRESULT WINAPI
Test_IClassFactory_LockServer(
156 LPCLASSFACTORY iface
,
162 static const IClassFactoryVtbl TestClassFactory_Vtbl
=
164 Test_IClassFactory_QueryInterface
,
165 Test_IClassFactory_AddRef
,
166 Test_IClassFactory_Release
,
167 Test_IClassFactory_CreateInstance
,
168 Test_IClassFactory_LockServer
171 static IClassFactory Test_ClassFactory
= { &TestClassFactory_Vtbl
};
173 #define RELEASEMARSHALDATA WM_USER
175 struct host_object_data
180 MSHLFLAGS marshal_flags
;
181 HANDLE marshal_event
;
182 IMessageFilter
*filter
;
185 static DWORD CALLBACK
host_object_proc(LPVOID p
)
187 struct host_object_data
*data
= (struct host_object_data
*)p
;
191 pCoInitializeEx(NULL
, COINIT_APARTMENTTHREADED
);
195 IMessageFilter
* prev_filter
= NULL
;
196 hr
= CoRegisterMessageFilter(data
->filter
, &prev_filter
);
197 if (prev_filter
) IMessageFilter_Release(prev_filter
);
198 ok_ole_success(hr
, CoRegisterMessageFilter
);
201 hr
= CoMarshalInterface(data
->stream
, &data
->iid
, data
->object
, MSHCTX_INPROC
, NULL
, data
->marshal_flags
);
202 ok_ole_success(hr
, CoMarshalInterface
);
204 /* force the message queue to be created before signaling parent thread */
205 PeekMessage(&msg
, NULL
, WM_USER
, WM_USER
, PM_NOREMOVE
);
207 SetEvent(data
->marshal_event
);
209 while (GetMessage(&msg
, NULL
, 0, 0))
211 if (msg
.hwnd
== NULL
&& msg
.message
== RELEASEMARSHALDATA
)
213 trace("releasing marshal data\n");
214 CoReleaseMarshalData(data
->stream
);
215 SetEvent((HANDLE
)msg
.lParam
);
218 DispatchMessage(&msg
);
221 HeapFree(GetProcessHeap(), 0, data
);
228 static DWORD
start_host_object2(IStream
*stream
, REFIID riid
, IUnknown
*object
, MSHLFLAGS marshal_flags
, IMessageFilter
*filter
, HANDLE
*thread
)
231 HANDLE marshal_event
= CreateEvent(NULL
, FALSE
, FALSE
, NULL
);
232 struct host_object_data
*data
= HeapAlloc(GetProcessHeap(), 0, sizeof(*data
));
234 data
->stream
= stream
;
236 data
->object
= object
;
237 data
->marshal_flags
= marshal_flags
;
238 data
->marshal_event
= marshal_event
;
239 data
->filter
= filter
;
241 *thread
= CreateThread(NULL
, 0, host_object_proc
, data
, 0, &tid
);
243 /* wait for marshaling to complete before returning */
244 WaitForSingleObject(marshal_event
, INFINITE
);
245 CloseHandle(marshal_event
);
250 static DWORD
start_host_object(IStream
*stream
, REFIID riid
, IUnknown
*object
, MSHLFLAGS marshal_flags
, HANDLE
*thread
)
252 return start_host_object2(stream
, riid
, object
, marshal_flags
, NULL
, thread
);
255 /* asks thread to release the marshal data because it has to be done by the
256 * same thread that marshaled the interface in the first place. */
257 static void release_host_object(DWORD tid
)
259 HANDLE event
= CreateEvent(NULL
, FALSE
, FALSE
, NULL
);
260 PostThreadMessage(tid
, RELEASEMARSHALDATA
, 0, (LPARAM
)event
);
261 WaitForSingleObject(event
, INFINITE
);
265 static void end_host_object(DWORD tid
, HANDLE thread
)
267 BOOL ret
= PostThreadMessage(tid
, WM_QUIT
, 0, 0);
268 ok(ret
, "PostThreadMessage failed with error %ld\n", GetLastError());
269 /* be careful of races - don't return until hosting thread has terminated */
270 WaitForSingleObject(thread
, INFINITE
);
274 /* tests failure case of interface not having a marshaler specified in the
276 static void test_no_marshaler()
280 static const CLSID IID_IWineTest
= {
284 {0xa1, 0xa2, 0x5d, 0x5a, 0x36, 0x54, 0xd3, 0xbd}
285 }; /* 5201163f-8164-4fd0-a1a2-5d5a3654d3bd */
287 hr
= CreateStreamOnHGlobal(NULL
, TRUE
, &pStream
);
288 ok_ole_success(hr
, CreateStreamOnHGlobal
);
289 hr
= CoMarshalInterface(pStream
, &IID_IWineTest
, (IUnknown
*)&Test_ClassFactory
, MSHCTX_INPROC
, NULL
, MSHLFLAGS_NORMAL
);
290 ok(hr
== E_NOINTERFACE
, "CoMarshalInterface should have returned E_NOINTERFACE instead of 0x%08lx\n", hr
);
292 IStream_Release(pStream
);
295 /* tests normal marshal and then release without unmarshaling */
296 static void test_normal_marshal_and_release()
299 IStream
*pStream
= NULL
;
303 hr
= CreateStreamOnHGlobal(NULL
, TRUE
, &pStream
);
304 ok_ole_success(hr
, CreateStreamOnHGlobal
);
305 hr
= CoMarshalInterface(pStream
, &IID_IClassFactory
, (IUnknown
*)&Test_ClassFactory
, MSHCTX_INPROC
, NULL
, MSHLFLAGS_NORMAL
);
306 ok_ole_success(hr
, CoMarshalInterface
);
308 ok_more_than_one_lock();
310 IStream_Seek(pStream
, ullZero
, STREAM_SEEK_SET
, NULL
);
311 hr
= CoReleaseMarshalData(pStream
);
312 ok_ole_success(hr
, CoReleaseMarshalData
);
313 IStream_Release(pStream
);
318 /* tests success case of a same-thread marshal and unmarshal */
319 static void test_normal_marshal_and_unmarshal()
322 IStream
*pStream
= NULL
;
323 IUnknown
*pProxy
= NULL
;
327 hr
= CreateStreamOnHGlobal(NULL
, TRUE
, &pStream
);
328 ok_ole_success(hr
, CreateStreamOnHGlobal
);
329 hr
= CoMarshalInterface(pStream
, &IID_IClassFactory
, (IUnknown
*)&Test_ClassFactory
, MSHCTX_INPROC
, NULL
, MSHLFLAGS_NORMAL
);
330 ok_ole_success(hr
, CoMarshalInterface
);
332 ok_more_than_one_lock();
334 IStream_Seek(pStream
, ullZero
, STREAM_SEEK_SET
, NULL
);
335 hr
= CoUnmarshalInterface(pStream
, &IID_IClassFactory
, (void **)&pProxy
);
336 ok_ole_success(hr
, CoUnmarshalInterface
);
337 IStream_Release(pStream
);
339 ok_more_than_one_lock();
341 IUnknown_Release(pProxy
);
346 /* tests failure case of unmarshaling a freed object */
347 static void test_marshal_and_unmarshal_invalid()
350 IStream
*pStream
= NULL
;
351 IClassFactory
*pProxy
= NULL
;
358 hr
= CreateStreamOnHGlobal(NULL
, TRUE
, &pStream
);
359 ok_ole_success(hr
, CreateStreamOnHGlobal
);
360 tid
= start_host_object(pStream
, &IID_IClassFactory
, (IUnknown
*)&Test_ClassFactory
, MSHLFLAGS_NORMAL
, &thread
);
362 ok_more_than_one_lock();
364 IStream_Seek(pStream
, ullZero
, STREAM_SEEK_SET
, NULL
);
365 hr
= CoReleaseMarshalData(pStream
);
366 ok_ole_success(hr
, CoReleaseMarshalData
);
370 IStream_Seek(pStream
, ullZero
, STREAM_SEEK_SET
, NULL
);
371 hr
= CoUnmarshalInterface(pStream
, &IID_IClassFactory
, (void **)&pProxy
);
372 todo_wine
{ ok_ole_success(hr
, CoUnmarshalInterface
); }
378 hr
= IClassFactory_CreateInstance(pProxy
, NULL
, &IID_IUnknown
, &dummy
);
379 ok(hr
== RPC_E_DISCONNECTED
, "Remote call should have returned RPC_E_DISCONNECTED, instead of 0x%08lx\n", hr
);
381 IClassFactory_Release(pProxy
);
384 IStream_Release(pStream
);
386 end_host_object(tid
, thread
);
389 /* tests success case of an interthread marshal */
390 static void test_interthread_marshal_and_unmarshal()
393 IStream
*pStream
= NULL
;
394 IUnknown
*pProxy
= NULL
;
400 hr
= CreateStreamOnHGlobal(NULL
, TRUE
, &pStream
);
401 ok_ole_success(hr
, CreateStreamOnHGlobal
);
402 tid
= start_host_object(pStream
, &IID_IClassFactory
, (IUnknown
*)&Test_ClassFactory
, MSHLFLAGS_NORMAL
, &thread
);
404 ok_more_than_one_lock();
406 IStream_Seek(pStream
, ullZero
, STREAM_SEEK_SET
, NULL
);
407 hr
= CoUnmarshalInterface(pStream
, &IID_IClassFactory
, (void **)&pProxy
);
408 ok_ole_success(hr
, CoUnmarshalInterface
);
409 IStream_Release(pStream
);
411 ok_more_than_one_lock();
413 IUnknown_Release(pProxy
);
417 end_host_object(tid
, thread
);
420 /* tests that stubs are released when the containing apartment is destroyed */
421 static void test_marshal_stub_apartment_shutdown()
424 IStream
*pStream
= NULL
;
425 IUnknown
*pProxy
= NULL
;
431 hr
= CreateStreamOnHGlobal(NULL
, TRUE
, &pStream
);
432 ok_ole_success(hr
, CreateStreamOnHGlobal
);
433 tid
= start_host_object(pStream
, &IID_IClassFactory
, (IUnknown
*)&Test_ClassFactory
, MSHLFLAGS_NORMAL
, &thread
);
435 ok_more_than_one_lock();
437 IStream_Seek(pStream
, ullZero
, STREAM_SEEK_SET
, NULL
);
438 hr
= CoUnmarshalInterface(pStream
, &IID_IClassFactory
, (void **)&pProxy
);
439 ok_ole_success(hr
, CoUnmarshalInterface
);
440 IStream_Release(pStream
);
442 ok_more_than_one_lock();
444 end_host_object(tid
, thread
);
448 IUnknown_Release(pProxy
);
453 /* tests that proxies are released when the containing apartment is destroyed */
454 static void test_marshal_proxy_apartment_shutdown()
457 IStream
*pStream
= NULL
;
458 IUnknown
*pProxy
= NULL
;
464 hr
= CreateStreamOnHGlobal(NULL
, TRUE
, &pStream
);
465 ok_ole_success(hr
, CreateStreamOnHGlobal
);
466 tid
= start_host_object(pStream
, &IID_IClassFactory
, (IUnknown
*)&Test_ClassFactory
, MSHLFLAGS_NORMAL
, &thread
);
468 ok_more_than_one_lock();
470 IStream_Seek(pStream
, ullZero
, STREAM_SEEK_SET
, NULL
);
471 hr
= CoUnmarshalInterface(pStream
, &IID_IClassFactory
, (void **)&pProxy
);
472 ok_ole_success(hr
, CoUnmarshalInterface
);
473 IStream_Release(pStream
);
475 ok_more_than_one_lock();
481 IUnknown_Release(pProxy
);
485 end_host_object(tid
, thread
);
487 pCoInitializeEx(NULL
, COINIT_APARTMENTTHREADED
);
490 /* tests that proxies are released when the containing mta apartment is destroyed */
491 static void test_marshal_proxy_mta_apartment_shutdown()
494 IStream
*pStream
= NULL
;
495 IUnknown
*pProxy
= NULL
;
500 pCoInitializeEx(NULL
, COINIT_MULTITHREADED
);
504 hr
= CreateStreamOnHGlobal(NULL
, TRUE
, &pStream
);
505 ok_ole_success(hr
, CreateStreamOnHGlobal
);
506 tid
= start_host_object(pStream
, &IID_IClassFactory
, (IUnknown
*)&Test_ClassFactory
, MSHLFLAGS_NORMAL
, &thread
);
508 ok_more_than_one_lock();
510 IStream_Seek(pStream
, ullZero
, STREAM_SEEK_SET
, NULL
);
511 hr
= CoUnmarshalInterface(pStream
, &IID_IClassFactory
, (void **)&pProxy
);
512 ok_ole_success(hr
, CoUnmarshalInterface
);
513 IStream_Release(pStream
);
515 ok_more_than_one_lock();
521 IUnknown_Release(pProxy
);
525 end_host_object(tid
, thread
);
527 pCoInitializeEx(NULL
, COINIT_APARTMENTTHREADED
);
533 HANDLE marshal_event
;
534 HANDLE unmarshal_event
;
537 /* helper for test_proxy_used_in_wrong_thread */
538 static DWORD CALLBACK
no_couninitialize_proc(LPVOID p
)
540 struct ncu_params
*ncu_params
= (struct ncu_params
*)p
;
543 pCoInitializeEx(NULL
, COINIT_MULTITHREADED
);
545 hr
= CoMarshalInterface(ncu_params
->stream
, &IID_IClassFactory
, (IUnknown
*)&Test_ClassFactory
, MSHCTX_INPROC
, NULL
, MSHLFLAGS_NORMAL
);
546 ok_ole_success(hr
, CoMarshalInterface
);
548 SetEvent(ncu_params
->marshal_event
);
550 WaitForSingleObject(ncu_params
->unmarshal_event
, INFINITE
);
552 /* die without calling CoUninitialize */
557 /* tests apartment that an apartment is released if the owning thread exits */
558 static void test_no_couninitialize()
561 IStream
*pStream
= NULL
;
562 IUnknown
*pProxy
= NULL
;
565 struct ncu_params ncu_params
;
569 ncu_params
.marshal_event
= CreateEvent(NULL
, TRUE
, FALSE
, NULL
);
570 ncu_params
.unmarshal_event
= CreateEvent(NULL
, TRUE
, FALSE
, NULL
);
572 hr
= CreateStreamOnHGlobal(NULL
, TRUE
, &pStream
);
573 ok_ole_success(hr
, CreateStreamOnHGlobal
);
574 ncu_params
.stream
= pStream
;
576 thread
= CreateThread(NULL
, 0, no_couninitialize_proc
, &ncu_params
, 0, &tid
);
578 WaitForSingleObject(ncu_params
.marshal_event
, INFINITE
);
579 ok_more_than_one_lock();
581 IStream_Seek(pStream
, ullZero
, STREAM_SEEK_SET
, NULL
);
582 hr
= CoUnmarshalInterface(pStream
, &IID_IClassFactory
, (void **)&pProxy
);
583 ok_ole_success(hr
, CoUnmarshalInterface
);
584 IStream_Release(pStream
);
586 ok_more_than_one_lock();
588 SetEvent(ncu_params
.unmarshal_event
);
589 WaitForSingleObject(thread
, INFINITE
);
594 CloseHandle(ncu_params
.marshal_event
);
595 CloseHandle(ncu_params
.unmarshal_event
);
597 IUnknown_Release(pProxy
);
602 /* tests success case of a same-thread table-weak marshal, unmarshal, unmarshal */
603 static void test_tableweak_marshal_and_unmarshal_twice()
606 IStream
*pStream
= NULL
;
607 IUnknown
*pProxy1
= NULL
;
608 IUnknown
*pProxy2
= NULL
;
614 hr
= CreateStreamOnHGlobal(NULL
, TRUE
, &pStream
);
615 ok_ole_success(hr
, CreateStreamOnHGlobal
);
616 tid
= start_host_object(pStream
, &IID_IClassFactory
, (IUnknown
*)&Test_ClassFactory
, MSHLFLAGS_TABLEWEAK
, &thread
);
618 ok_more_than_one_lock();
620 IStream_Seek(pStream
, ullZero
, STREAM_SEEK_SET
, NULL
);
621 hr
= CoUnmarshalInterface(pStream
, &IID_IClassFactory
, (void **)&pProxy1
);
622 ok_ole_success(hr
, CoUnmarshalInterface
);
624 ok_more_than_one_lock();
626 IStream_Seek(pStream
, ullZero
, STREAM_SEEK_SET
, NULL
);
627 hr
= CoUnmarshalInterface(pStream
, &IID_IClassFactory
, (void **)&pProxy2
);
628 ok_ole_success(hr
, CoUnmarshalInterface
);
630 ok_more_than_one_lock();
632 IUnknown_Release(pProxy1
);
633 IUnknown_Release(pProxy2
);
635 /* this line is shows the difference between weak and strong table marshaling:
636 * weak has cLocks == 0
637 * strong has cLocks > 0 */
640 end_host_object(tid
, thread
);
643 /* tests releasing after unmarshaling one object */
644 static void test_tableweak_marshal_releasedata1()
647 IStream
*pStream
= NULL
;
648 IUnknown
*pProxy1
= NULL
;
649 IUnknown
*pProxy2
= NULL
;
655 hr
= CreateStreamOnHGlobal(NULL
, TRUE
, &pStream
);
656 ok_ole_success(hr
, CreateStreamOnHGlobal
);
657 tid
= start_host_object(pStream
, &IID_IClassFactory
, (IUnknown
*)&Test_ClassFactory
, MSHLFLAGS_TABLEWEAK
, &thread
);
659 ok_more_than_one_lock();
661 IStream_Seek(pStream
, ullZero
, STREAM_SEEK_SET
, NULL
);
662 hr
= CoUnmarshalInterface(pStream
, &IID_IClassFactory
, (void **)&pProxy1
);
663 ok_ole_success(hr
, CoUnmarshalInterface
);
665 ok_more_than_one_lock();
667 /* release the remaining reference on the object by calling
668 * CoReleaseMarshalData in the hosting thread */
669 IStream_Seek(pStream
, ullZero
, STREAM_SEEK_SET
, NULL
);
670 release_host_object(tid
);
672 ok_more_than_one_lock();
674 IStream_Seek(pStream
, ullZero
, STREAM_SEEK_SET
, NULL
);
675 hr
= CoUnmarshalInterface(pStream
, &IID_IClassFactory
, (void **)&pProxy2
);
676 ok_ole_success(hr
, CoUnmarshalInterface
);
677 IStream_Release(pStream
);
679 ok_more_than_one_lock();
681 IUnknown_Release(pProxy1
);
683 IUnknown_Release(pProxy2
);
685 /* this line is shows the difference between weak and strong table marshaling:
686 * weak has cLocks == 0
687 * strong has cLocks > 0 */
690 end_host_object(tid
, thread
);
693 /* tests releasing after unmarshaling one object */
694 static void test_tableweak_marshal_releasedata2()
697 IStream
*pStream
= NULL
;
698 IUnknown
*pProxy
= NULL
;
704 hr
= CreateStreamOnHGlobal(NULL
, TRUE
, &pStream
);
705 ok_ole_success(hr
, CreateStreamOnHGlobal
);
706 tid
= start_host_object(pStream
, &IID_IClassFactory
, (IUnknown
*)&Test_ClassFactory
, MSHLFLAGS_TABLEWEAK
, &thread
);
708 ok_more_than_one_lock();
710 /* release the remaining reference on the object by calling
711 * CoReleaseMarshalData in the hosting thread */
712 IStream_Seek(pStream
, ullZero
, STREAM_SEEK_SET
, NULL
);
713 release_host_object(tid
);
717 IStream_Seek(pStream
, ullZero
, STREAM_SEEK_SET
, NULL
);
718 hr
= CoUnmarshalInterface(pStream
, &IID_IClassFactory
, (void **)&pProxy
);
721 ok(hr
== CO_E_OBJNOTREG
,
722 "CoUnmarshalInterface should have failed with CO_E_OBJNOTREG, but returned 0x%08lx instead\n",
725 IStream_Release(pStream
);
729 end_host_object(tid
, thread
);
732 /* tests success case of a same-thread table-strong marshal, unmarshal, unmarshal */
733 static void test_tablestrong_marshal_and_unmarshal_twice()
736 IStream
*pStream
= NULL
;
737 IUnknown
*pProxy1
= NULL
;
738 IUnknown
*pProxy2
= NULL
;
744 hr
= CreateStreamOnHGlobal(NULL
, TRUE
, &pStream
);
745 ok_ole_success(hr
, CreateStreamOnHGlobal
);
746 tid
= start_host_object(pStream
, &IID_IClassFactory
, (IUnknown
*)&Test_ClassFactory
, MSHLFLAGS_TABLESTRONG
, &thread
);
748 ok_more_than_one_lock();
750 IStream_Seek(pStream
, ullZero
, STREAM_SEEK_SET
, NULL
);
751 hr
= CoUnmarshalInterface(pStream
, &IID_IClassFactory
, (void **)&pProxy1
);
752 ok_ole_success(hr
, CoUnmarshalInterface
);
754 ok_more_than_one_lock();
756 IStream_Seek(pStream
, ullZero
, STREAM_SEEK_SET
, NULL
);
757 hr
= CoUnmarshalInterface(pStream
, &IID_IClassFactory
, (void **)&pProxy2
);
758 ok_ole_success(hr
, CoUnmarshalInterface
);
760 ok_more_than_one_lock();
762 if (pProxy1
) IUnknown_Release(pProxy1
);
763 if (pProxy2
) IUnknown_Release(pProxy2
);
765 /* this line is shows the difference between weak and strong table marshaling:
766 * weak has cLocks == 0
767 * strong has cLocks > 0 */
768 ok_more_than_one_lock();
770 /* release the remaining reference on the object by calling
771 * CoReleaseMarshalData in the hosting thread */
772 IStream_Seek(pStream
, ullZero
, STREAM_SEEK_SET
, NULL
);
773 release_host_object(tid
);
774 IStream_Release(pStream
);
778 end_host_object(tid
, thread
);
781 /* tests CoLockObjectExternal */
782 static void test_lock_object_external()
785 IStream
*pStream
= NULL
;
789 hr
= CreateStreamOnHGlobal(NULL
, TRUE
, &pStream
);
790 ok_ole_success(hr
, CreateStreamOnHGlobal
);
791 hr
= CoMarshalInterface(pStream
, &IID_IClassFactory
, (IUnknown
*)&Test_ClassFactory
, MSHCTX_INPROC
, NULL
, MSHLFLAGS_NORMAL
);
792 ok_ole_success(hr
, CoMarshalInterface
);
794 CoLockObjectExternal((IUnknown
*)&Test_ClassFactory
, TRUE
, TRUE
);
796 ok_more_than_one_lock();
798 IStream_Seek(pStream
, ullZero
, STREAM_SEEK_SET
, NULL
);
799 hr
= CoReleaseMarshalData(pStream
);
800 ok_ole_success(hr
, CoReleaseMarshalData
);
801 IStream_Release(pStream
);
803 ok_more_than_one_lock();
805 CoLockObjectExternal((IUnknown
*)&Test_ClassFactory
, FALSE
, TRUE
);
810 /* tests disconnecting stubs */
811 static void test_disconnect_stub()
814 IStream
*pStream
= NULL
;
818 hr
= CreateStreamOnHGlobal(NULL
, TRUE
, &pStream
);
819 ok_ole_success(hr
, CreateStreamOnHGlobal
);
820 hr
= CoMarshalInterface(pStream
, &IID_IClassFactory
, (IUnknown
*)&Test_ClassFactory
, MSHCTX_INPROC
, NULL
, MSHLFLAGS_NORMAL
);
821 ok_ole_success(hr
, CoMarshalInterface
);
823 CoLockObjectExternal((IUnknown
*)&Test_ClassFactory
, TRUE
, TRUE
);
825 ok_more_than_one_lock();
827 IStream_Seek(pStream
, ullZero
, STREAM_SEEK_SET
, NULL
);
828 hr
= CoReleaseMarshalData(pStream
);
829 ok_ole_success(hr
, CoReleaseMarshalData
);
830 IStream_Release(pStream
);
832 ok_more_than_one_lock();
834 CoDisconnectObject((IUnknown
*)&Test_ClassFactory
, 0);
839 /* tests failure case of a same-thread marshal and unmarshal twice */
840 static void test_normal_marshal_and_unmarshal_twice()
843 IStream
*pStream
= NULL
;
844 IUnknown
*pProxy1
= NULL
;
845 IUnknown
*pProxy2
= NULL
;
849 hr
= CreateStreamOnHGlobal(NULL
, TRUE
, &pStream
);
850 ok_ole_success(hr
, CreateStreamOnHGlobal
);
851 hr
= CoMarshalInterface(pStream
, &IID_IClassFactory
, (IUnknown
*)&Test_ClassFactory
, MSHCTX_INPROC
, NULL
, MSHLFLAGS_NORMAL
);
852 ok_ole_success(hr
, CoMarshalInterface
);
854 ok_more_than_one_lock();
856 IStream_Seek(pStream
, ullZero
, STREAM_SEEK_SET
, NULL
);
857 hr
= CoUnmarshalInterface(pStream
, &IID_IClassFactory
, (void **)&pProxy1
);
858 ok_ole_success(hr
, CoUnmarshalInterface
);
860 ok_more_than_one_lock();
862 IStream_Seek(pStream
, ullZero
, STREAM_SEEK_SET
, NULL
);
863 hr
= CoUnmarshalInterface(pStream
, &IID_IClassFactory
, (void **)&pProxy2
);
864 ok(hr
== CO_E_OBJNOTCONNECTED
,
865 "CoUnmarshalInterface should have failed with error CO_E_OBJNOTCONNECTED for double unmarshal, instead of 0x%08lx\n", hr
);
867 IStream_Release(pStream
);
869 ok_more_than_one_lock();
871 IUnknown_Release(pProxy1
);
876 /* tests success case of marshaling and unmarshaling an HRESULT */
877 static void test_hresult_marshaling()
880 HRESULT hr_marshaled
= 0;
881 IStream
*pStream
= NULL
;
882 static const HRESULT E_DEADBEEF
= 0xdeadbeef;
884 hr
= CreateStreamOnHGlobal(NULL
, TRUE
, &pStream
);
885 ok_ole_success(hr
, CreateStreamOnHGlobal
);
887 hr
= CoMarshalHresult(pStream
, E_DEADBEEF
);
888 ok_ole_success(hr
, CoMarshalHresult
);
890 IStream_Seek(pStream
, ullZero
, STREAM_SEEK_SET
, NULL
);
891 hr
= IStream_Read(pStream
, &hr_marshaled
, sizeof(HRESULT
), NULL
);
892 ok_ole_success(hr
, IStream_Read
);
894 ok(hr_marshaled
== E_DEADBEEF
, "Didn't marshal HRESULT as expected: got value 0x%08lx instead\n", hr_marshaled
);
897 IStream_Seek(pStream
, ullZero
, STREAM_SEEK_SET
, NULL
);
898 hr
= CoUnmarshalHresult(pStream
, &hr_marshaled
);
899 ok_ole_success(hr
, CoUnmarshalHresult
);
901 ok(hr_marshaled
== E_DEADBEEF
, "Didn't marshal HRESULT as expected: got value 0x%08lx instead\n", hr_marshaled
);
903 IStream_Release(pStream
);
907 /* helper for test_proxy_used_in_wrong_thread */
908 static DWORD CALLBACK
bad_thread_proc(LPVOID p
)
910 IClassFactory
* cf
= (IClassFactory
*)p
;
912 IUnknown
* proxy
= NULL
;
914 pCoInitializeEx(NULL
, COINIT_MULTITHREADED
);
916 hr
= IClassFactory_CreateInstance(cf
, NULL
, &IID_IUnknown
, (LPVOID
*)&proxy
);
917 if (proxy
) IUnknown_Release(proxy
);
919 ok(hr
== RPC_E_WRONG_THREAD
,
920 "COM should have failed with RPC_E_WRONG_THREAD on using proxy from wrong apartment, but instead returned 0x%08lx\n",
929 /* tests failure case of a using a proxy in the wrong apartment */
930 static void test_proxy_used_in_wrong_thread()
933 IStream
*pStream
= NULL
;
934 IUnknown
*pProxy
= NULL
;
941 hr
= CreateStreamOnHGlobal(NULL
, TRUE
, &pStream
);
942 ok_ole_success(hr
, CreateStreamOnHGlobal
);
943 tid
= start_host_object(pStream
, &IID_IClassFactory
, (IUnknown
*)&Test_ClassFactory
, MSHLFLAGS_NORMAL
, &host_thread
);
945 ok_more_than_one_lock();
947 IStream_Seek(pStream
, ullZero
, STREAM_SEEK_SET
, NULL
);
948 hr
= CoUnmarshalInterface(pStream
, &IID_IClassFactory
, (void **)&pProxy
);
949 ok_ole_success(hr
, CoUnmarshalInterface
);
950 IStream_Release(pStream
);
952 ok_more_than_one_lock();
954 /* create a thread that we can misbehave in */
955 thread
= CreateThread(NULL
, 0, bad_thread_proc
, (LPVOID
)pProxy
, 0, &tid2
);
957 WaitForSingleObject(thread
, INFINITE
);
960 IUnknown_Release(pProxy
);
964 end_host_object(tid
, host_thread
);
967 static HRESULT WINAPI
MessageFilter_QueryInterface(IMessageFilter
*iface
, REFIID riid
, void ** ppvObj
)
969 if (ppvObj
== NULL
) return E_POINTER
;
971 if (IsEqualGUID(riid
, &IID_IUnknown
) ||
972 IsEqualGUID(riid
, &IID_IClassFactory
))
974 *ppvObj
= (LPVOID
)iface
;
975 IClassFactory_AddRef(iface
);
979 return E_NOINTERFACE
;
982 static ULONG WINAPI
MessageFilter_AddRef(IMessageFilter
*iface
)
984 return 2; /* non-heap object */
987 static ULONG WINAPI
MessageFilter_Release(IMessageFilter
*iface
)
989 return 1; /* non-heap object */
992 static DWORD WINAPI
MessageFilter_HandleInComingCall(
993 IMessageFilter
*iface
,
995 HTASK threadIDCaller
,
997 LPINTERFACEINFO lpInterfaceInfo
)
999 static int callcount
= 0;
1001 trace("HandleInComingCall\n");
1005 ret
= SERVERCALL_REJECTED
;
1008 ret
= SERVERCALL_RETRYLATER
;
1011 ret
= SERVERCALL_ISHANDLED
;
1018 static DWORD WINAPI
MessageFilter_RetryRejectedCall(
1019 IMessageFilter
*iface
,
1020 HTASK threadIDCallee
,
1024 trace("RetryRejectedCall\n");
1028 static DWORD WINAPI
MessageFilter_MessagePending(
1029 IMessageFilter
*iface
,
1030 HTASK threadIDCallee
,
1032 DWORD dwPendingType
)
1034 trace("MessagePending\n");
1035 return PENDINGMSG_WAITNOPROCESS
;
1038 static const IMessageFilterVtbl MessageFilter_Vtbl
=
1040 MessageFilter_QueryInterface
,
1041 MessageFilter_AddRef
,
1042 MessageFilter_Release
,
1043 MessageFilter_HandleInComingCall
,
1044 MessageFilter_RetryRejectedCall
,
1045 MessageFilter_MessagePending
1048 static IMessageFilter MessageFilter
= { &MessageFilter_Vtbl
};
1050 static void test_message_filter()
1053 IStream
*pStream
= NULL
;
1054 IClassFactory
*cf
= NULL
;
1056 IUnknown
*proxy
= NULL
;
1057 IMessageFilter
*prev_filter
= NULL
;
1062 hr
= CreateStreamOnHGlobal(NULL
, TRUE
, &pStream
);
1063 ok_ole_success(hr
, CreateStreamOnHGlobal
);
1064 tid
= start_host_object2(pStream
, &IID_IClassFactory
, (IUnknown
*)&Test_ClassFactory
, MSHLFLAGS_NORMAL
, &MessageFilter
, &thread
);
1066 ok_more_than_one_lock();
1068 IStream_Seek(pStream
, ullZero
, STREAM_SEEK_SET
, NULL
);
1069 hr
= CoUnmarshalInterface(pStream
, &IID_IClassFactory
, (void **)&cf
);
1070 ok_ole_success(hr
, CoUnmarshalInterface
);
1071 IStream_Release(pStream
);
1073 ok_more_than_one_lock();
1075 hr
= IClassFactory_CreateInstance(cf
, NULL
, &IID_IUnknown
, (LPVOID
*)&proxy
);
1076 todo_wine
{ ok(hr
== RPC_E_CALL_REJECTED
, "Call should have returned RPC_E_CALL_REJECTED, but return 0x%08lx instead\n", hr
); }
1077 if (proxy
) IUnknown_Release(proxy
);
1080 hr
= CoRegisterMessageFilter(&MessageFilter
, &prev_filter
);
1081 ok_ole_success(hr
, CoRegisterMessageFilter
);
1082 if (prev_filter
) IMessageFilter_Release(prev_filter
);
1084 hr
= IClassFactory_CreateInstance(cf
, NULL
, &IID_IUnknown
, (LPVOID
*)&proxy
);
1085 ok_ole_success(hr
, IClassFactory_CreateInstance
);
1087 IUnknown_Release(proxy
);
1089 IClassFactory_Release(cf
);
1093 end_host_object(tid
, thread
);
1096 /* test failure case of trying to unmarshal from bad stream */
1097 static void test_bad_marshal_stream()
1100 IStream
*pStream
= NULL
;
1102 hr
= CreateStreamOnHGlobal(NULL
, TRUE
, &pStream
);
1103 ok_ole_success(hr
, CreateStreamOnHGlobal
);
1104 hr
= CoMarshalInterface(pStream
, &IID_IClassFactory
, (IUnknown
*)&Test_ClassFactory
, MSHCTX_INPROC
, NULL
, MSHLFLAGS_NORMAL
);
1105 ok_ole_success(hr
, CoMarshalInterface
);
1107 ok_more_than_one_lock();
1109 /* try to read beyond end of stream */
1110 hr
= CoReleaseMarshalData(pStream
);
1111 ok(hr
== STG_E_READFAULT
, "Should have failed with STG_E_READFAULT, but returned 0x%08lx instead\n", hr
);
1113 /* now release for real */
1114 IStream_Seek(pStream
, ullZero
, STREAM_SEEK_SET
, NULL
);
1115 hr
= CoReleaseMarshalData(pStream
);
1116 ok_ole_success(hr
, CoReleaseMarshalData
);
1118 IStream_Release(pStream
);
1121 /* tests that proxies implement certain interfaces */
1122 static void test_proxy_interfaces()
1125 IStream
*pStream
= NULL
;
1126 IUnknown
*pProxy
= NULL
;
1127 IUnknown
*pOtherUnknown
= NULL
;
1133 hr
= CreateStreamOnHGlobal(NULL
, TRUE
, &pStream
);
1134 ok_ole_success(hr
, CreateStreamOnHGlobal
);
1135 tid
= start_host_object(pStream
, &IID_IClassFactory
, (IUnknown
*)&Test_ClassFactory
, MSHLFLAGS_NORMAL
, &thread
);
1137 ok_more_than_one_lock();
1139 IStream_Seek(pStream
, ullZero
, STREAM_SEEK_SET
, NULL
);
1140 hr
= CoUnmarshalInterface(pStream
, &IID_IUnknown
, (void **)&pProxy
);
1141 ok_ole_success(hr
, CoUnmarshalInterface
);
1142 IStream_Release(pStream
);
1144 ok_more_than_one_lock();
1146 hr
= IUnknown_QueryInterface(pProxy
, &IID_IUnknown
, (LPVOID
*)&pOtherUnknown
);
1147 ok_ole_success(hr
, IUnknown_QueryInterface IID_IUnknown
);
1148 if (hr
== S_OK
) IUnknown_Release(pOtherUnknown
);
1150 hr
= IUnknown_QueryInterface(pProxy
, &IID_IClientSecurity
, (LPVOID
*)&pOtherUnknown
);
1151 todo_wine
{ ok_ole_success(hr
, IUnknown_QueryInterface IID_IClientSecurity
); }
1152 if (hr
== S_OK
) IUnknown_Release(pOtherUnknown
);
1154 hr
= IUnknown_QueryInterface(pProxy
, &IID_IMultiQI
, (LPVOID
*)&pOtherUnknown
);
1155 ok_ole_success(hr
, IUnknown_QueryInterface IID_IMultiQI
);
1156 if (hr
== S_OK
) IUnknown_Release(pOtherUnknown
);
1158 hr
= IUnknown_QueryInterface(pProxy
, &IID_IMarshal
, (LPVOID
*)&pOtherUnknown
);
1159 todo_wine
{ ok_ole_success(hr
, IUnknown_QueryInterface IID_IMarshal
); }
1160 if (hr
== S_OK
) IUnknown_Release(pOtherUnknown
);
1162 /* IMarshal2 is also supported on NT-based systems, but is pretty much
1163 * useless as it has no more methods over IMarshal that it inherits from. */
1165 IUnknown_Release(pProxy
);
1169 end_host_object(tid
, thread
);
1172 static void test_stubbuffer(REFIID riid
)
1175 IPSFactoryBuffer
*psfb
;
1176 IRpcStubBuffer
*stub
;
1182 hr
= CoGetPSClsid(riid
, &clsid
);
1183 ok_ole_success(hr
, CoGetPSClsid
);
1185 hr
= CoGetClassObject(&clsid
, CLSCTX_INPROC_SERVER
, NULL
, &IID_IPSFactoryBuffer
, (LPVOID
*)&psfb
);
1186 ok_ole_success(hr
, CoGetClassObject
);
1188 hr
= IPSFactoryBuffer_CreateStub(psfb
, riid
, (IUnknown
*)&Test_ClassFactory
, &stub
);
1189 ok_ole_success(hr
, IPSFactoryBuffer_CreateStub
);
1191 refs
= IPSFactoryBuffer_Release(psfb
);
1192 #if 0 /* not reliable on native. maybe it leaks references */
1193 ok(refs
== 0, "Ref-count leak of %ld on IPSFactoryBuffer\n", refs
);
1196 ok_more_than_one_lock();
1198 IRpcStubBuffer_Disconnect(stub
);
1202 refs
= IRpcStubBuffer_Release(stub
);
1203 ok(refs
== 0, "Ref-count leak of %ld on IRpcProxyBuffer\n", refs
);
1206 static HWND hwnd_app
;
1208 static HRESULT WINAPI
TestRE_IClassFactory_CreateInstance(
1209 LPCLASSFACTORY iface
,
1210 LPUNKNOWN pUnkOuter
,
1215 BOOL ret
= SendMessageTimeout(hwnd_app
, WM_NULL
, 0, 0, SMTO_BLOCK
, 5000, &res
);
1216 ok(ret
, "Timed out sending a message to originating window during RPC call\n");
1220 static const IClassFactoryVtbl TestREClassFactory_Vtbl
=
1222 Test_IClassFactory_QueryInterface
,
1223 Test_IClassFactory_AddRef
,
1224 Test_IClassFactory_Release
,
1225 TestRE_IClassFactory_CreateInstance
,
1226 Test_IClassFactory_LockServer
1229 IClassFactory TestRE_ClassFactory
= { &TestREClassFactory_Vtbl
};
1231 static LRESULT CALLBACK
window_proc(HWND hwnd
, UINT msg
, WPARAM wparam
, LPARAM lparam
)
1238 IStream
*pStream
= NULL
;
1239 IClassFactory
*proxy
= NULL
;
1246 hr
= CreateStreamOnHGlobal(NULL
, TRUE
, &pStream
);
1247 ok_ole_success(hr
, CreateStreamOnHGlobal
);
1248 tid
= start_host_object(pStream
, &IID_IClassFactory
, (IUnknown
*)&TestRE_ClassFactory
, MSHLFLAGS_NORMAL
, &thread
);
1250 ok_more_than_one_lock();
1252 IStream_Seek(pStream
, ullZero
, STREAM_SEEK_SET
, NULL
);
1253 hr
= CoUnmarshalInterface(pStream
, &IID_IClassFactory
, (void **)&proxy
);
1254 ok_ole_success(hr
, CoReleaseMarshalData
);
1255 IStream_Release(pStream
);
1257 ok_more_than_one_lock();
1259 hr
= IClassFactory_CreateInstance(proxy
, NULL
, &IID_IUnknown
, (void **)&object
);
1261 IClassFactory_Release(proxy
);
1265 end_host_object(tid
, thread
);
1267 PostMessage(hwnd
, WM_QUIT
, 0, 0);
1272 return DefWindowProc(hwnd
, msg
, wparam
, lparam
);
1276 static void test_message_reentrancy()
1281 memset(&wndclass
, 0, sizeof(wndclass
));
1282 wndclass
.lpfnWndProc
= window_proc
;
1283 wndclass
.lpszClassName
= "WineCOMTest";
1284 RegisterClass(&wndclass
);
1286 hwnd_app
= CreateWindow("WineCOMTest", NULL
, 0, CW_USEDEFAULT
, CW_USEDEFAULT
, CW_USEDEFAULT
, CW_USEDEFAULT
, NULL
, NULL
, NULL
, 0);
1287 ok(hwnd_app
!= NULL
, "Window creation failed\n");
1289 PostMessage(hwnd_app
, WM_USER
, 0, 0);
1291 while (GetMessage(&msg
, NULL
, 0, 0))
1293 TranslateMessage(&msg
);
1294 DispatchMessage(&msg
);
1298 /* doesn't pass with Win9x COM DLLs (even though Essential COM says it should) */
1301 static HANDLE heventShutdown
;
1303 static void LockModuleOOP()
1305 InterlockedIncrement(&cLocks
); /* for test purposes only */
1306 CoAddRefServerProcess();
1309 static void UnlockModuleOOP()
1311 InterlockedDecrement(&cLocks
); /* for test purposes only */
1312 if (!CoReleaseServerProcess())
1313 SetEvent(heventShutdown
);
1316 static HWND hwnd_app
;
1318 static HRESULT WINAPI
TestRE_IClassFactory_CreateInstance(
1319 LPCLASSFACTORY iface
,
1320 LPUNKNOWN pUnkOuter
,
1325 BOOL ret
= SendMessageTimeout(hwnd_app
, WM_NULL
, 0, 0, SMTO_BLOCK
, 500, &res
);
1326 todo_wine
{ ok(ret
, "Timed out sending a message to originating window during RPC call\n"); }
1330 static const IClassFactoryVtbl TestREClassFactory_Vtbl
=
1332 Test_IClassFactory_QueryInterface
,
1333 Test_IClassFactory_AddRef
,
1334 Test_IClassFactory_Release
,
1335 TestRE_IClassFactory_CreateInstance
,
1336 Test_IClassFactory_LockServer
1339 IClassFactory TestRE_ClassFactory
= { &TestREClassFactory_Vtbl
};
1341 static LRESULT CALLBACK
window_proc(HWND hwnd
, UINT msg
, WPARAM wparam
, LPARAM lparam
)
1348 IStream
*pStream
= NULL
;
1349 IClassFactory
*proxy
= NULL
;
1356 hr
= CreateStreamOnHGlobal(NULL
, TRUE
, &pStream
);
1357 ok_ole_success(hr
, CreateStreamOnHGlobal
);
1358 tid
= start_host_object(pStream
, &IID_IClassFactory
, (IUnknown
*)&TestRE_ClassFactory
, MSHLFLAGS_NORMAL
, &thread
);
1360 ok_more_than_one_lock();
1362 IStream_Seek(pStream
, ullZero
, STREAM_SEEK_SET
, NULL
);
1363 hr
= CoUnmarshalInterface(pStream
, &IID_IClassFactory
, (void **)&proxy
);
1364 ok_ole_success(hr
, CoReleaseMarshalData
);
1365 IStream_Release(pStream
);
1367 ok_more_than_one_lock();
1369 hr
= IClassFactory_CreateInstance(proxy
, NULL
, &IID_IUnknown
, (void **)&object
);
1371 IClassFactory_Release(proxy
);
1375 end_host_object(tid
, thread
);
1377 PostMessage(hwnd
, WM_QUIT
, 0, 0);
1382 return DefWindowProc(hwnd
, msg
, wparam
, lparam
);
1386 static void test_message_reentrancy()
1391 memset(&wndclass
, 0, sizeof(wndclass
));
1392 wndclass
.lpfnWndProc
= window_proc
;
1393 wndclass
.lpszClassName
= "WineCOMTest";
1394 RegisterClass(&wndclass
);
1396 hwnd_app
= CreateWindow("WineCOMTest", NULL
, 0, CW_USEDEFAULT
, CW_USEDEFAULT
, CW_USEDEFAULT
, CW_USEDEFAULT
, NULL
, NULL
, NULL
, 0);
1397 ok(hwnd_app
!= NULL
, "Window creation failed\n");
1399 PostMessage(hwnd_app
, WM_USER
, 0, 0);
1401 while (GetMessage(&msg
, NULL
, 0, 0))
1403 TranslateMessage(&msg
);
1404 DispatchMessage(&msg
);
1408 static HRESULT WINAPI
TestOOP_IClassFactory_QueryInterface(
1409 LPCLASSFACTORY iface
,
1413 if (ppvObj
== NULL
) return E_POINTER
;
1415 if (IsEqualGUID(riid
, &IID_IUnknown
) ||
1416 IsEqualGUID(riid
, &IID_IClassFactory
))
1418 *ppvObj
= (LPVOID
)iface
;
1419 IClassFactory_AddRef(iface
);
1423 return E_NOINTERFACE
;
1426 static ULONG WINAPI
TestOOP_IClassFactory_AddRef(LPCLASSFACTORY iface
)
1428 return 2; /* non-heap-based object */
1431 static ULONG WINAPI
TestOOP_IClassFactory_Release(LPCLASSFACTORY iface
)
1433 return 1; /* non-heap-based object */
1436 static HRESULT WINAPI
TestOOP_IClassFactory_CreateInstance(
1437 LPCLASSFACTORY iface
,
1438 LPUNKNOWN pUnkOuter
,
1442 return CLASS_E_CLASSNOTAVAILABLE
;
1445 static HRESULT WINAPI
TestOOP_IClassFactory_LockServer(
1446 LPCLASSFACTORY iface
,
1456 static const IClassFactoryVtbl TestClassFactoryOOP_Vtbl
=
1458 TestOOP_IClassFactory_QueryInterface
,
1459 TestOOP_IClassFactory_AddRef
,
1460 TestOOP_IClassFactory_Release
,
1461 TestOOP_IClassFactory_CreateInstance
,
1462 TestOOP_IClassFactory_LockServer
1465 static IClassFactory TestOOP_ClassFactory
= { &TestClassFactoryOOP_Vtbl
};
1467 /* tests functions commonly used by out of process COM servers */
1468 static void test_out_of_process_com()
1470 static const CLSID CLSID_WineOOPTest
= {
1474 {0xa1, 0xa2, 0x5d, 0x5a, 0x36, 0x54, 0xd3, 0xbd}
1475 }; /* 5201163f-8164-4fd0-a1a2-5d5a3654d3bd */
1481 heventShutdown
= CreateEvent(NULL
, TRUE
, FALSE
, NULL
);
1485 /* Start the object suspended */
1486 hr
= CoRegisterClassObject(&CLSID_WineOOPTest
, (IUnknown
*)&TestOOP_ClassFactory
,
1487 CLSCTX_LOCAL_SERVER
, REGCLS_MULTIPLEUSE
| REGCLS_SUSPENDED
, &cookie
);
1488 ok_ole_success(hr
, CoRegisterClassObject
);
1490 /* ... and CoGetClassObject does not find it and fails when it looks for the
1491 * class in the registry */
1492 hr
= CoGetClassObject(&CLSID_WineOOPTest
, CLSCTX_INPROC_SERVER
,
1493 NULL
, &IID_IClassFactory
, (LPVOID
*)&cf
);
1495 ok(hr
== REGDB_E_CLASSNOTREG
,
1496 "CoGetClassObject should have returned REGDB_E_CLASSNOTREG instead of 0x%08lx\n", hr
);
1499 /* Resume the object suspended above ... */
1500 hr
= CoResumeClassObjects();
1501 ok_ole_success(hr
, CoResumeClassObjects
);
1503 /* ... and now it should succeed */
1504 hr
= CoGetClassObject(&CLSID_WineOOPTest
, CLSCTX_INPROC_SERVER
,
1505 NULL
, &IID_IClassFactory
, (LPVOID
*)&cf
);
1506 ok_ole_success(hr
, CoGetClassObject
);
1508 /* Now check the locking is working */
1509 /* NOTE: we are accessing the class directly, not through a proxy */
1513 hr
= IClassFactory_LockServer(cf
, TRUE
);
1514 trace("IClassFactory_LockServer returned 0x%08lx\n", hr
);
1516 ok_more_than_one_lock();
1518 IClassFactory_LockServer(cf
, FALSE
);
1522 IClassFactory_Release(cf
);
1524 /* wait for shutdown signal */
1525 ret
= WaitForSingleObject(heventShutdown
, 5000);
1526 todo_wine
{ ok(ret
!= WAIT_TIMEOUT
, "Server didn't shut down or machine is under very heavy load\n"); }
1528 /* try to connect again after SCM has suspended registered class objects */
1529 hr
= CoGetClassObject(&CLSID_WineOOPTest
, CLSCTX_INPROC_SERVER
| CLSCTX_LOCAL_SERVER
, NULL
,
1530 &IID_IClassFactory
, (LPVOID
*)&cf
);
1532 ok(hr
== CO_E_SERVER_STOPPING
,
1533 "CoGetClassObject should have returned CO_E_SERVER_STOPPING instead of 0x%08lx\n", hr
);
1536 hr
= CoRevokeClassObject(cookie
);
1537 ok_ole_success(hr
, CoRevokeClassObject
);
1539 CloseHandle(heventShutdown
);
1543 static void test_ROT()
1545 static const WCHAR wszFileName
[] = {'B','E','2','0','E','2','F','5','-',
1546 '1','9','0','3','-','4','A','A','E','-','B','1','A','F','-',
1547 '2','0','4','6','E','5','8','6','C','9','2','5',0};
1549 IMoniker
*pMoniker
= NULL
;
1550 IRunningObjectTable
*pROT
= NULL
;
1555 hr
= CreateFileMoniker(wszFileName
, &pMoniker
);
1556 ok_ole_success(hr
, CreateClassMoniker
);
1557 hr
= GetRunningObjectTable(0, &pROT
);
1558 ok_ole_success(hr
, GetRunningObjectTable
);
1559 hr
= IRunningObjectTable_Register(pROT
, 0, (IUnknown
*)&Test_ClassFactory
, pMoniker
, &dwCookie
);
1560 ok_ole_success(hr
, IRunningObjectTable_Register
);
1562 ok_more_than_one_lock();
1564 hr
= IRunningObjectTable_Revoke(pROT
, dwCookie
);
1565 ok_ole_success(hr
, IRunningObjectTable_Revoke
);
1572 HMODULE hOle32
= GetModuleHandle("ole32");
1573 if (!(pCoInitializeEx
= (void*)GetProcAddress(hOle32
, "CoInitializeEx"))) goto no_test
;
1575 pCoInitializeEx(NULL
, COINIT_APARTMENTTHREADED
);
1577 /* FIXME: test CoCreateInstanceEx */
1579 /* helper function tests */
1580 test_CoGetPSClsid();
1582 /* lifecycle management and marshaling tests */
1583 test_no_marshaler();
1584 test_normal_marshal_and_release();
1585 test_normal_marshal_and_unmarshal();
1586 test_marshal_and_unmarshal_invalid();
1587 test_interthread_marshal_and_unmarshal();
1588 test_marshal_stub_apartment_shutdown();
1589 test_marshal_proxy_apartment_shutdown();
1590 test_marshal_proxy_mta_apartment_shutdown();
1591 test_no_couninitialize();
1592 test_tableweak_marshal_and_unmarshal_twice();
1593 test_tableweak_marshal_releasedata1();
1594 test_tableweak_marshal_releasedata2();
1595 test_tablestrong_marshal_and_unmarshal_twice();
1596 test_lock_object_external();
1597 test_disconnect_stub();
1598 test_normal_marshal_and_unmarshal_twice();
1599 test_hresult_marshaling();
1600 test_proxy_used_in_wrong_thread();
1601 test_message_filter();
1602 test_bad_marshal_stream();
1603 test_proxy_interfaces();
1604 test_stubbuffer(&IID_IClassFactory
);
1605 test_message_reentrancy();
1607 /* test_out_of_process_com(); */
1610 /* FIXME: test GIT */
1616 trace("You need DCOM95 installed to run this test\n");