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(void)
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(void)
65 InterlockedIncrement(&cLocks
);
68 static void UnlockModule(void)
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(void)
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(void)
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(void)
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(void)
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(void)
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(void)
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(void)
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(void)
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_no_couninitialize_server */
538 static DWORD CALLBACK
no_couninitialize_server_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 with a stub is released without deadlock
558 * if the owning thread exits */
559 static void test_no_couninitialize_server()
562 IStream
*pStream
= NULL
;
563 IUnknown
*pProxy
= NULL
;
566 struct ncu_params ncu_params
;
570 ncu_params
.marshal_event
= CreateEvent(NULL
, TRUE
, FALSE
, NULL
);
571 ncu_params
.unmarshal_event
= CreateEvent(NULL
, TRUE
, FALSE
, NULL
);
573 hr
= CreateStreamOnHGlobal(NULL
, TRUE
, &pStream
);
574 ok_ole_success(hr
, CreateStreamOnHGlobal
);
575 ncu_params
.stream
= pStream
;
577 thread
= CreateThread(NULL
, 0, no_couninitialize_server_proc
, &ncu_params
, 0, &tid
);
579 WaitForSingleObject(ncu_params
.marshal_event
, INFINITE
);
580 ok_more_than_one_lock();
582 IStream_Seek(pStream
, ullZero
, STREAM_SEEK_SET
, NULL
);
583 hr
= CoUnmarshalInterface(pStream
, &IID_IClassFactory
, (void **)&pProxy
);
584 ok_ole_success(hr
, CoUnmarshalInterface
);
585 IStream_Release(pStream
);
587 ok_more_than_one_lock();
589 SetEvent(ncu_params
.unmarshal_event
);
590 WaitForSingleObject(thread
, INFINITE
);
595 CloseHandle(ncu_params
.marshal_event
);
596 CloseHandle(ncu_params
.unmarshal_event
);
598 IUnknown_Release(pProxy
);
603 /* STA -> STA call during DLL_THREAD_DETACH */
604 static DWORD CALLBACK
no_couninitialize_client_proc(LPVOID p
)
606 struct ncu_params
*ncu_params
= (struct ncu_params
*)p
;
608 IUnknown
*pProxy
= NULL
;
610 pCoInitializeEx(NULL
, COINIT_APARTMENTTHREADED
);
612 hr
= CoUnmarshalInterface(ncu_params
->stream
, &IID_IClassFactory
, (void **)&pProxy
);
613 ok_ole_success(hr
, CoUnmarshalInterface
);
615 ok_more_than_one_lock();
617 /* die without calling CoUninitialize */
622 /* tests STA -> STA call during DLL_THREAD_DETACH doesn't deadlock */
623 static void test_no_couninitialize_client()
626 IStream
*pStream
= NULL
;
631 struct ncu_params ncu_params
;
635 hr
= CreateStreamOnHGlobal(NULL
, TRUE
, &pStream
);
636 ok_ole_success(hr
, CreateStreamOnHGlobal
);
637 ncu_params
.stream
= pStream
;
639 /* NOTE: assumes start_host_object uses an STA to host the object, as MTAs
640 * always deadlock when called from within DllMain */
641 host_tid
= start_host_object(pStream
, &IID_IClassFactory
, (IUnknown
*)&Test_ClassFactory
, MSHLFLAGS_NORMAL
, &host_thread
);
642 IStream_Seek(pStream
, ullZero
, STREAM_SEEK_SET
, NULL
);
644 ok_more_than_one_lock();
646 thread
= CreateThread(NULL
, 0, no_couninitialize_client_proc
, &ncu_params
, 0, &tid
);
648 WaitForSingleObject(thread
, INFINITE
);
653 end_host_object(host_tid
, host_thread
);
656 /* tests success case of a same-thread table-weak marshal, unmarshal, unmarshal */
657 static void test_tableweak_marshal_and_unmarshal_twice(void)
660 IStream
*pStream
= NULL
;
661 IUnknown
*pProxy1
= NULL
;
662 IUnknown
*pProxy2
= NULL
;
668 hr
= CreateStreamOnHGlobal(NULL
, TRUE
, &pStream
);
669 ok_ole_success(hr
, CreateStreamOnHGlobal
);
670 tid
= start_host_object(pStream
, &IID_IClassFactory
, (IUnknown
*)&Test_ClassFactory
, MSHLFLAGS_TABLEWEAK
, &thread
);
672 ok_more_than_one_lock();
674 IStream_Seek(pStream
, ullZero
, STREAM_SEEK_SET
, NULL
);
675 hr
= CoUnmarshalInterface(pStream
, &IID_IClassFactory
, (void **)&pProxy1
);
676 ok_ole_success(hr
, CoUnmarshalInterface
);
678 ok_more_than_one_lock();
680 IStream_Seek(pStream
, ullZero
, STREAM_SEEK_SET
, NULL
);
681 hr
= CoUnmarshalInterface(pStream
, &IID_IClassFactory
, (void **)&pProxy2
);
682 ok_ole_success(hr
, CoUnmarshalInterface
);
684 ok_more_than_one_lock();
686 IUnknown_Release(pProxy1
);
687 IUnknown_Release(pProxy2
);
689 /* this line is shows the difference between weak and strong table marshaling:
690 * weak has cLocks == 0
691 * strong has cLocks > 0 */
694 end_host_object(tid
, thread
);
697 /* tests releasing after unmarshaling one object */
698 static void test_tableweak_marshal_releasedata1(void)
701 IStream
*pStream
= NULL
;
702 IUnknown
*pProxy1
= NULL
;
703 IUnknown
*pProxy2
= NULL
;
709 hr
= CreateStreamOnHGlobal(NULL
, TRUE
, &pStream
);
710 ok_ole_success(hr
, CreateStreamOnHGlobal
);
711 tid
= start_host_object(pStream
, &IID_IClassFactory
, (IUnknown
*)&Test_ClassFactory
, MSHLFLAGS_TABLEWEAK
, &thread
);
713 ok_more_than_one_lock();
715 IStream_Seek(pStream
, ullZero
, STREAM_SEEK_SET
, NULL
);
716 hr
= CoUnmarshalInterface(pStream
, &IID_IClassFactory
, (void **)&pProxy1
);
717 ok_ole_success(hr
, CoUnmarshalInterface
);
719 ok_more_than_one_lock();
721 /* release the remaining reference on the object by calling
722 * CoReleaseMarshalData in the hosting thread */
723 IStream_Seek(pStream
, ullZero
, STREAM_SEEK_SET
, NULL
);
724 release_host_object(tid
);
726 ok_more_than_one_lock();
728 IStream_Seek(pStream
, ullZero
, STREAM_SEEK_SET
, NULL
);
729 hr
= CoUnmarshalInterface(pStream
, &IID_IClassFactory
, (void **)&pProxy2
);
730 ok_ole_success(hr
, CoUnmarshalInterface
);
731 IStream_Release(pStream
);
733 ok_more_than_one_lock();
735 IUnknown_Release(pProxy1
);
737 IUnknown_Release(pProxy2
);
739 /* this line is shows the difference between weak and strong table marshaling:
740 * weak has cLocks == 0
741 * strong has cLocks > 0 */
744 end_host_object(tid
, thread
);
747 /* tests releasing after unmarshaling one object */
748 static void test_tableweak_marshal_releasedata2(void)
751 IStream
*pStream
= NULL
;
752 IUnknown
*pProxy
= NULL
;
758 hr
= CreateStreamOnHGlobal(NULL
, TRUE
, &pStream
);
759 ok_ole_success(hr
, CreateStreamOnHGlobal
);
760 tid
= start_host_object(pStream
, &IID_IClassFactory
, (IUnknown
*)&Test_ClassFactory
, MSHLFLAGS_TABLEWEAK
, &thread
);
762 ok_more_than_one_lock();
764 /* release the remaining reference on the object by calling
765 * CoReleaseMarshalData in the hosting thread */
766 IStream_Seek(pStream
, ullZero
, STREAM_SEEK_SET
, NULL
);
767 release_host_object(tid
);
771 IStream_Seek(pStream
, ullZero
, STREAM_SEEK_SET
, NULL
);
772 hr
= CoUnmarshalInterface(pStream
, &IID_IClassFactory
, (void **)&pProxy
);
775 ok(hr
== CO_E_OBJNOTREG
,
776 "CoUnmarshalInterface should have failed with CO_E_OBJNOTREG, but returned 0x%08lx instead\n",
779 IStream_Release(pStream
);
783 end_host_object(tid
, thread
);
786 /* tests success case of a same-thread table-strong marshal, unmarshal, unmarshal */
787 static void test_tablestrong_marshal_and_unmarshal_twice(void)
790 IStream
*pStream
= NULL
;
791 IUnknown
*pProxy1
= NULL
;
792 IUnknown
*pProxy2
= NULL
;
798 hr
= CreateStreamOnHGlobal(NULL
, TRUE
, &pStream
);
799 ok_ole_success(hr
, CreateStreamOnHGlobal
);
800 tid
= start_host_object(pStream
, &IID_IClassFactory
, (IUnknown
*)&Test_ClassFactory
, MSHLFLAGS_TABLESTRONG
, &thread
);
802 ok_more_than_one_lock();
804 IStream_Seek(pStream
, ullZero
, STREAM_SEEK_SET
, NULL
);
805 hr
= CoUnmarshalInterface(pStream
, &IID_IClassFactory
, (void **)&pProxy1
);
806 ok_ole_success(hr
, CoUnmarshalInterface
);
808 ok_more_than_one_lock();
810 IStream_Seek(pStream
, ullZero
, STREAM_SEEK_SET
, NULL
);
811 hr
= CoUnmarshalInterface(pStream
, &IID_IClassFactory
, (void **)&pProxy2
);
812 ok_ole_success(hr
, CoUnmarshalInterface
);
814 ok_more_than_one_lock();
816 if (pProxy1
) IUnknown_Release(pProxy1
);
817 if (pProxy2
) IUnknown_Release(pProxy2
);
819 /* this line is shows the difference between weak and strong table marshaling:
820 * weak has cLocks == 0
821 * strong has cLocks > 0 */
822 ok_more_than_one_lock();
824 /* release the remaining reference on the object by calling
825 * CoReleaseMarshalData in the hosting thread */
826 IStream_Seek(pStream
, ullZero
, STREAM_SEEK_SET
, NULL
);
827 release_host_object(tid
);
828 IStream_Release(pStream
);
832 end_host_object(tid
, thread
);
835 /* tests CoLockObjectExternal */
836 static void test_lock_object_external(void)
839 IStream
*pStream
= NULL
;
843 hr
= CreateStreamOnHGlobal(NULL
, TRUE
, &pStream
);
844 ok_ole_success(hr
, CreateStreamOnHGlobal
);
845 hr
= CoMarshalInterface(pStream
, &IID_IClassFactory
, (IUnknown
*)&Test_ClassFactory
, MSHCTX_INPROC
, NULL
, MSHLFLAGS_NORMAL
);
846 ok_ole_success(hr
, CoMarshalInterface
);
848 CoLockObjectExternal((IUnknown
*)&Test_ClassFactory
, TRUE
, TRUE
);
850 ok_more_than_one_lock();
852 IStream_Seek(pStream
, ullZero
, STREAM_SEEK_SET
, NULL
);
853 hr
= CoReleaseMarshalData(pStream
);
854 ok_ole_success(hr
, CoReleaseMarshalData
);
855 IStream_Release(pStream
);
857 ok_more_than_one_lock();
859 CoLockObjectExternal((IUnknown
*)&Test_ClassFactory
, FALSE
, TRUE
);
864 /* tests disconnecting stubs */
865 static void test_disconnect_stub(void)
868 IStream
*pStream
= NULL
;
872 hr
= CreateStreamOnHGlobal(NULL
, TRUE
, &pStream
);
873 ok_ole_success(hr
, CreateStreamOnHGlobal
);
874 hr
= CoMarshalInterface(pStream
, &IID_IClassFactory
, (IUnknown
*)&Test_ClassFactory
, MSHCTX_INPROC
, NULL
, MSHLFLAGS_NORMAL
);
875 ok_ole_success(hr
, CoMarshalInterface
);
877 CoLockObjectExternal((IUnknown
*)&Test_ClassFactory
, TRUE
, TRUE
);
879 ok_more_than_one_lock();
881 IStream_Seek(pStream
, ullZero
, STREAM_SEEK_SET
, NULL
);
882 hr
= CoReleaseMarshalData(pStream
);
883 ok_ole_success(hr
, CoReleaseMarshalData
);
884 IStream_Release(pStream
);
886 ok_more_than_one_lock();
888 CoDisconnectObject((IUnknown
*)&Test_ClassFactory
, 0);
893 /* tests failure case of a same-thread marshal and unmarshal twice */
894 static void test_normal_marshal_and_unmarshal_twice(void)
897 IStream
*pStream
= NULL
;
898 IUnknown
*pProxy1
= NULL
;
899 IUnknown
*pProxy2
= NULL
;
903 hr
= CreateStreamOnHGlobal(NULL
, TRUE
, &pStream
);
904 ok_ole_success(hr
, CreateStreamOnHGlobal
);
905 hr
= CoMarshalInterface(pStream
, &IID_IClassFactory
, (IUnknown
*)&Test_ClassFactory
, MSHCTX_INPROC
, NULL
, MSHLFLAGS_NORMAL
);
906 ok_ole_success(hr
, CoMarshalInterface
);
908 ok_more_than_one_lock();
910 IStream_Seek(pStream
, ullZero
, STREAM_SEEK_SET
, NULL
);
911 hr
= CoUnmarshalInterface(pStream
, &IID_IClassFactory
, (void **)&pProxy1
);
912 ok_ole_success(hr
, CoUnmarshalInterface
);
914 ok_more_than_one_lock();
916 IStream_Seek(pStream
, ullZero
, STREAM_SEEK_SET
, NULL
);
917 hr
= CoUnmarshalInterface(pStream
, &IID_IClassFactory
, (void **)&pProxy2
);
918 ok(hr
== CO_E_OBJNOTCONNECTED
,
919 "CoUnmarshalInterface should have failed with error CO_E_OBJNOTCONNECTED for double unmarshal, instead of 0x%08lx\n", hr
);
921 IStream_Release(pStream
);
923 ok_more_than_one_lock();
925 IUnknown_Release(pProxy1
);
930 /* tests success case of marshaling and unmarshaling an HRESULT */
931 static void test_hresult_marshaling(void)
934 HRESULT hr_marshaled
= 0;
935 IStream
*pStream
= NULL
;
936 static const HRESULT E_DEADBEEF
= 0xdeadbeef;
938 hr
= CreateStreamOnHGlobal(NULL
, TRUE
, &pStream
);
939 ok_ole_success(hr
, CreateStreamOnHGlobal
);
941 hr
= CoMarshalHresult(pStream
, E_DEADBEEF
);
942 ok_ole_success(hr
, CoMarshalHresult
);
944 IStream_Seek(pStream
, ullZero
, STREAM_SEEK_SET
, NULL
);
945 hr
= IStream_Read(pStream
, &hr_marshaled
, sizeof(HRESULT
), NULL
);
946 ok_ole_success(hr
, IStream_Read
);
948 ok(hr_marshaled
== E_DEADBEEF
, "Didn't marshal HRESULT as expected: got value 0x%08lx instead\n", hr_marshaled
);
951 IStream_Seek(pStream
, ullZero
, STREAM_SEEK_SET
, NULL
);
952 hr
= CoUnmarshalHresult(pStream
, &hr_marshaled
);
953 ok_ole_success(hr
, CoUnmarshalHresult
);
955 ok(hr_marshaled
== E_DEADBEEF
, "Didn't marshal HRESULT as expected: got value 0x%08lx instead\n", hr_marshaled
);
957 IStream_Release(pStream
);
961 /* helper for test_proxy_used_in_wrong_thread */
962 static DWORD CALLBACK
bad_thread_proc(LPVOID p
)
964 IClassFactory
* cf
= (IClassFactory
*)p
;
966 IUnknown
* proxy
= NULL
;
968 pCoInitializeEx(NULL
, COINIT_MULTITHREADED
);
970 hr
= IClassFactory_CreateInstance(cf
, NULL
, &IID_IUnknown
, (LPVOID
*)&proxy
);
971 if (proxy
) IUnknown_Release(proxy
);
973 ok(hr
== RPC_E_WRONG_THREAD
,
974 "COM should have failed with RPC_E_WRONG_THREAD on using proxy from wrong apartment, but instead returned 0x%08lx\n",
983 /* tests failure case of a using a proxy in the wrong apartment */
984 static void test_proxy_used_in_wrong_thread(void)
987 IStream
*pStream
= NULL
;
988 IUnknown
*pProxy
= NULL
;
995 hr
= CreateStreamOnHGlobal(NULL
, TRUE
, &pStream
);
996 ok_ole_success(hr
, CreateStreamOnHGlobal
);
997 tid
= start_host_object(pStream
, &IID_IClassFactory
, (IUnknown
*)&Test_ClassFactory
, MSHLFLAGS_NORMAL
, &host_thread
);
999 ok_more_than_one_lock();
1001 IStream_Seek(pStream
, ullZero
, STREAM_SEEK_SET
, NULL
);
1002 hr
= CoUnmarshalInterface(pStream
, &IID_IClassFactory
, (void **)&pProxy
);
1003 ok_ole_success(hr
, CoUnmarshalInterface
);
1004 IStream_Release(pStream
);
1006 ok_more_than_one_lock();
1008 /* create a thread that we can misbehave in */
1009 thread
= CreateThread(NULL
, 0, bad_thread_proc
, (LPVOID
)pProxy
, 0, &tid2
);
1011 WaitForSingleObject(thread
, INFINITE
);
1012 CloseHandle(thread
);
1014 IUnknown_Release(pProxy
);
1018 end_host_object(tid
, host_thread
);
1021 static HRESULT WINAPI
MessageFilter_QueryInterface(IMessageFilter
*iface
, REFIID riid
, void ** ppvObj
)
1023 if (ppvObj
== NULL
) return E_POINTER
;
1025 if (IsEqualGUID(riid
, &IID_IUnknown
) ||
1026 IsEqualGUID(riid
, &IID_IClassFactory
))
1028 *ppvObj
= (LPVOID
)iface
;
1029 IClassFactory_AddRef(iface
);
1033 return E_NOINTERFACE
;
1036 static ULONG WINAPI
MessageFilter_AddRef(IMessageFilter
*iface
)
1038 return 2; /* non-heap object */
1041 static ULONG WINAPI
MessageFilter_Release(IMessageFilter
*iface
)
1043 return 1; /* non-heap object */
1046 static DWORD WINAPI
MessageFilter_HandleInComingCall(
1047 IMessageFilter
*iface
,
1049 HTASK threadIDCaller
,
1051 LPINTERFACEINFO lpInterfaceInfo
)
1053 static int callcount
= 0;
1055 trace("HandleInComingCall\n");
1059 ret
= SERVERCALL_REJECTED
;
1062 ret
= SERVERCALL_RETRYLATER
;
1065 ret
= SERVERCALL_ISHANDLED
;
1072 static DWORD WINAPI
MessageFilter_RetryRejectedCall(
1073 IMessageFilter
*iface
,
1074 HTASK threadIDCallee
,
1078 trace("RetryRejectedCall\n");
1082 static DWORD WINAPI
MessageFilter_MessagePending(
1083 IMessageFilter
*iface
,
1084 HTASK threadIDCallee
,
1086 DWORD dwPendingType
)
1088 trace("MessagePending\n");
1089 return PENDINGMSG_WAITNOPROCESS
;
1092 static const IMessageFilterVtbl MessageFilter_Vtbl
=
1094 MessageFilter_QueryInterface
,
1095 MessageFilter_AddRef
,
1096 MessageFilter_Release
,
1097 MessageFilter_HandleInComingCall
,
1098 MessageFilter_RetryRejectedCall
,
1099 MessageFilter_MessagePending
1102 static IMessageFilter MessageFilter
= { &MessageFilter_Vtbl
};
1104 static void test_message_filter(void)
1107 IStream
*pStream
= NULL
;
1108 IClassFactory
*cf
= NULL
;
1110 IUnknown
*proxy
= NULL
;
1111 IMessageFilter
*prev_filter
= NULL
;
1116 hr
= CreateStreamOnHGlobal(NULL
, TRUE
, &pStream
);
1117 ok_ole_success(hr
, CreateStreamOnHGlobal
);
1118 tid
= start_host_object2(pStream
, &IID_IClassFactory
, (IUnknown
*)&Test_ClassFactory
, MSHLFLAGS_NORMAL
, &MessageFilter
, &thread
);
1120 ok_more_than_one_lock();
1122 IStream_Seek(pStream
, ullZero
, STREAM_SEEK_SET
, NULL
);
1123 hr
= CoUnmarshalInterface(pStream
, &IID_IClassFactory
, (void **)&cf
);
1124 ok_ole_success(hr
, CoUnmarshalInterface
);
1125 IStream_Release(pStream
);
1127 ok_more_than_one_lock();
1129 hr
= IClassFactory_CreateInstance(cf
, NULL
, &IID_IUnknown
, (LPVOID
*)&proxy
);
1130 todo_wine
{ ok(hr
== RPC_E_CALL_REJECTED
, "Call should have returned RPC_E_CALL_REJECTED, but return 0x%08lx instead\n", hr
); }
1131 if (proxy
) IUnknown_Release(proxy
);
1134 hr
= CoRegisterMessageFilter(&MessageFilter
, &prev_filter
);
1135 ok_ole_success(hr
, CoRegisterMessageFilter
);
1136 if (prev_filter
) IMessageFilter_Release(prev_filter
);
1138 hr
= IClassFactory_CreateInstance(cf
, NULL
, &IID_IUnknown
, (LPVOID
*)&proxy
);
1139 ok_ole_success(hr
, IClassFactory_CreateInstance
);
1141 IUnknown_Release(proxy
);
1143 IClassFactory_Release(cf
);
1147 end_host_object(tid
, thread
);
1150 /* test failure case of trying to unmarshal from bad stream */
1151 static void test_bad_marshal_stream(void)
1154 IStream
*pStream
= NULL
;
1156 hr
= CreateStreamOnHGlobal(NULL
, TRUE
, &pStream
);
1157 ok_ole_success(hr
, CreateStreamOnHGlobal
);
1158 hr
= CoMarshalInterface(pStream
, &IID_IClassFactory
, (IUnknown
*)&Test_ClassFactory
, MSHCTX_INPROC
, NULL
, MSHLFLAGS_NORMAL
);
1159 ok_ole_success(hr
, CoMarshalInterface
);
1161 ok_more_than_one_lock();
1163 /* try to read beyond end of stream */
1164 hr
= CoReleaseMarshalData(pStream
);
1165 ok(hr
== STG_E_READFAULT
, "Should have failed with STG_E_READFAULT, but returned 0x%08lx instead\n", hr
);
1167 /* now release for real */
1168 IStream_Seek(pStream
, ullZero
, STREAM_SEEK_SET
, NULL
);
1169 hr
= CoReleaseMarshalData(pStream
);
1170 ok_ole_success(hr
, CoReleaseMarshalData
);
1172 IStream_Release(pStream
);
1175 /* tests that proxies implement certain interfaces */
1176 static void test_proxy_interfaces(void)
1179 IStream
*pStream
= NULL
;
1180 IUnknown
*pProxy
= NULL
;
1181 IUnknown
*pOtherUnknown
= NULL
;
1187 hr
= CreateStreamOnHGlobal(NULL
, TRUE
, &pStream
);
1188 ok_ole_success(hr
, CreateStreamOnHGlobal
);
1189 tid
= start_host_object(pStream
, &IID_IClassFactory
, (IUnknown
*)&Test_ClassFactory
, MSHLFLAGS_NORMAL
, &thread
);
1191 ok_more_than_one_lock();
1193 IStream_Seek(pStream
, ullZero
, STREAM_SEEK_SET
, NULL
);
1194 hr
= CoUnmarshalInterface(pStream
, &IID_IUnknown
, (void **)&pProxy
);
1195 ok_ole_success(hr
, CoUnmarshalInterface
);
1196 IStream_Release(pStream
);
1198 ok_more_than_one_lock();
1200 hr
= IUnknown_QueryInterface(pProxy
, &IID_IUnknown
, (LPVOID
*)&pOtherUnknown
);
1201 ok_ole_success(hr
, IUnknown_QueryInterface IID_IUnknown
);
1202 if (hr
== S_OK
) IUnknown_Release(pOtherUnknown
);
1204 hr
= IUnknown_QueryInterface(pProxy
, &IID_IClientSecurity
, (LPVOID
*)&pOtherUnknown
);
1205 todo_wine
{ ok_ole_success(hr
, IUnknown_QueryInterface IID_IClientSecurity
); }
1206 if (hr
== S_OK
) IUnknown_Release(pOtherUnknown
);
1208 hr
= IUnknown_QueryInterface(pProxy
, &IID_IMultiQI
, (LPVOID
*)&pOtherUnknown
);
1209 ok_ole_success(hr
, IUnknown_QueryInterface IID_IMultiQI
);
1210 if (hr
== S_OK
) IUnknown_Release(pOtherUnknown
);
1212 hr
= IUnknown_QueryInterface(pProxy
, &IID_IMarshal
, (LPVOID
*)&pOtherUnknown
);
1213 todo_wine
{ ok_ole_success(hr
, IUnknown_QueryInterface IID_IMarshal
); }
1214 if (hr
== S_OK
) IUnknown_Release(pOtherUnknown
);
1216 /* IMarshal2 is also supported on NT-based systems, but is pretty much
1217 * useless as it has no more methods over IMarshal that it inherits from. */
1219 IUnknown_Release(pProxy
);
1223 end_host_object(tid
, thread
);
1226 static void test_stubbuffer(REFIID riid
)
1229 IPSFactoryBuffer
*psfb
;
1230 IRpcStubBuffer
*stub
;
1236 hr
= CoGetPSClsid(riid
, &clsid
);
1237 ok_ole_success(hr
, CoGetPSClsid
);
1239 hr
= CoGetClassObject(&clsid
, CLSCTX_INPROC_SERVER
, NULL
, &IID_IPSFactoryBuffer
, (LPVOID
*)&psfb
);
1240 ok_ole_success(hr
, CoGetClassObject
);
1242 hr
= IPSFactoryBuffer_CreateStub(psfb
, riid
, (IUnknown
*)&Test_ClassFactory
, &stub
);
1243 ok_ole_success(hr
, IPSFactoryBuffer_CreateStub
);
1245 refs
= IPSFactoryBuffer_Release(psfb
);
1246 #if 0 /* not reliable on native. maybe it leaks references */
1247 ok(refs
== 0, "Ref-count leak of %ld on IPSFactoryBuffer\n", refs
);
1250 ok_more_than_one_lock();
1252 IRpcStubBuffer_Disconnect(stub
);
1256 refs
= IRpcStubBuffer_Release(stub
);
1257 ok(refs
== 0, "Ref-count leak of %ld on IRpcProxyBuffer\n", refs
);
1260 static HWND hwnd_app
;
1262 static HRESULT WINAPI
TestRE_IClassFactory_CreateInstance(
1263 LPCLASSFACTORY iface
,
1264 LPUNKNOWN pUnkOuter
,
1269 BOOL ret
= SendMessageTimeout(hwnd_app
, WM_NULL
, 0, 0, SMTO_BLOCK
, 5000, &res
);
1270 ok(ret
, "Timed out sending a message to originating window during RPC call\n");
1274 static const IClassFactoryVtbl TestREClassFactory_Vtbl
=
1276 Test_IClassFactory_QueryInterface
,
1277 Test_IClassFactory_AddRef
,
1278 Test_IClassFactory_Release
,
1279 TestRE_IClassFactory_CreateInstance
,
1280 Test_IClassFactory_LockServer
1283 IClassFactory TestRE_ClassFactory
= { &TestREClassFactory_Vtbl
};
1285 static LRESULT CALLBACK
window_proc(HWND hwnd
, UINT msg
, WPARAM wparam
, LPARAM lparam
)
1292 IStream
*pStream
= NULL
;
1293 IClassFactory
*proxy
= NULL
;
1300 hr
= CreateStreamOnHGlobal(NULL
, TRUE
, &pStream
);
1301 ok_ole_success(hr
, CreateStreamOnHGlobal
);
1302 tid
= start_host_object(pStream
, &IID_IClassFactory
, (IUnknown
*)&TestRE_ClassFactory
, MSHLFLAGS_NORMAL
, &thread
);
1304 ok_more_than_one_lock();
1306 IStream_Seek(pStream
, ullZero
, STREAM_SEEK_SET
, NULL
);
1307 hr
= CoUnmarshalInterface(pStream
, &IID_IClassFactory
, (void **)&proxy
);
1308 ok_ole_success(hr
, CoReleaseMarshalData
);
1309 IStream_Release(pStream
);
1311 ok_more_than_one_lock();
1313 hr
= IClassFactory_CreateInstance(proxy
, NULL
, &IID_IUnknown
, (void **)&object
);
1315 IClassFactory_Release(proxy
);
1319 end_host_object(tid
, thread
);
1321 PostMessage(hwnd
, WM_QUIT
, 0, 0);
1326 return DefWindowProc(hwnd
, msg
, wparam
, lparam
);
1330 static void test_message_reentrancy(void)
1335 memset(&wndclass
, 0, sizeof(wndclass
));
1336 wndclass
.lpfnWndProc
= window_proc
;
1337 wndclass
.lpszClassName
= "WineCOMTest";
1338 RegisterClass(&wndclass
);
1340 hwnd_app
= CreateWindow("WineCOMTest", NULL
, 0, CW_USEDEFAULT
, CW_USEDEFAULT
, CW_USEDEFAULT
, CW_USEDEFAULT
, NULL
, NULL
, NULL
, 0);
1341 ok(hwnd_app
!= NULL
, "Window creation failed\n");
1343 PostMessage(hwnd_app
, WM_USER
, 0, 0);
1345 while (GetMessage(&msg
, NULL
, 0, 0))
1347 TranslateMessage(&msg
);
1348 DispatchMessage(&msg
);
1352 /* doesn't pass with Win9x COM DLLs (even though Essential COM says it should) */
1355 static HANDLE heventShutdown
;
1357 static void LockModuleOOP()
1359 InterlockedIncrement(&cLocks
); /* for test purposes only */
1360 CoAddRefServerProcess();
1363 static void UnlockModuleOOP()
1365 InterlockedDecrement(&cLocks
); /* for test purposes only */
1366 if (!CoReleaseServerProcess())
1367 SetEvent(heventShutdown
);
1370 static HWND hwnd_app
;
1372 static HRESULT WINAPI
TestRE_IClassFactory_CreateInstance(
1373 LPCLASSFACTORY iface
,
1374 LPUNKNOWN pUnkOuter
,
1379 BOOL ret
= SendMessageTimeout(hwnd_app
, WM_NULL
, 0, 0, SMTO_BLOCK
, 500, &res
);
1380 todo_wine
{ ok(ret
, "Timed out sending a message to originating window during RPC call\n"); }
1384 static const IClassFactoryVtbl TestREClassFactory_Vtbl
=
1386 Test_IClassFactory_QueryInterface
,
1387 Test_IClassFactory_AddRef
,
1388 Test_IClassFactory_Release
,
1389 TestRE_IClassFactory_CreateInstance
,
1390 Test_IClassFactory_LockServer
1393 IClassFactory TestRE_ClassFactory
= { &TestREClassFactory_Vtbl
};
1395 static LRESULT CALLBACK
window_proc(HWND hwnd
, UINT msg
, WPARAM wparam
, LPARAM lparam
)
1402 IStream
*pStream
= NULL
;
1403 IClassFactory
*proxy
= NULL
;
1410 hr
= CreateStreamOnHGlobal(NULL
, TRUE
, &pStream
);
1411 ok_ole_success(hr
, CreateStreamOnHGlobal
);
1412 tid
= start_host_object(pStream
, &IID_IClassFactory
, (IUnknown
*)&TestRE_ClassFactory
, MSHLFLAGS_NORMAL
, &thread
);
1414 ok_more_than_one_lock();
1416 IStream_Seek(pStream
, ullZero
, STREAM_SEEK_SET
, NULL
);
1417 hr
= CoUnmarshalInterface(pStream
, &IID_IClassFactory
, (void **)&proxy
);
1418 ok_ole_success(hr
, CoReleaseMarshalData
);
1419 IStream_Release(pStream
);
1421 ok_more_than_one_lock();
1423 hr
= IClassFactory_CreateInstance(proxy
, NULL
, &IID_IUnknown
, (void **)&object
);
1425 IClassFactory_Release(proxy
);
1429 end_host_object(tid
, thread
);
1431 PostMessage(hwnd
, WM_QUIT
, 0, 0);
1436 return DefWindowProc(hwnd
, msg
, wparam
, lparam
);
1440 static void test_message_reentrancy()
1445 memset(&wndclass
, 0, sizeof(wndclass
));
1446 wndclass
.lpfnWndProc
= window_proc
;
1447 wndclass
.lpszClassName
= "WineCOMTest";
1448 RegisterClass(&wndclass
);
1450 hwnd_app
= CreateWindow("WineCOMTest", NULL
, 0, CW_USEDEFAULT
, CW_USEDEFAULT
, CW_USEDEFAULT
, CW_USEDEFAULT
, NULL
, NULL
, NULL
, 0);
1451 ok(hwnd_app
!= NULL
, "Window creation failed\n");
1453 PostMessage(hwnd_app
, WM_USER
, 0, 0);
1455 while (GetMessage(&msg
, NULL
, 0, 0))
1457 TranslateMessage(&msg
);
1458 DispatchMessage(&msg
);
1462 static HRESULT WINAPI
TestOOP_IClassFactory_QueryInterface(
1463 LPCLASSFACTORY iface
,
1467 if (ppvObj
== NULL
) return E_POINTER
;
1469 if (IsEqualGUID(riid
, &IID_IUnknown
) ||
1470 IsEqualGUID(riid
, &IID_IClassFactory
))
1472 *ppvObj
= (LPVOID
)iface
;
1473 IClassFactory_AddRef(iface
);
1477 return E_NOINTERFACE
;
1480 static ULONG WINAPI
TestOOP_IClassFactory_AddRef(LPCLASSFACTORY iface
)
1482 return 2; /* non-heap-based object */
1485 static ULONG WINAPI
TestOOP_IClassFactory_Release(LPCLASSFACTORY iface
)
1487 return 1; /* non-heap-based object */
1490 static HRESULT WINAPI
TestOOP_IClassFactory_CreateInstance(
1491 LPCLASSFACTORY iface
,
1492 LPUNKNOWN pUnkOuter
,
1496 return CLASS_E_CLASSNOTAVAILABLE
;
1499 static HRESULT WINAPI
TestOOP_IClassFactory_LockServer(
1500 LPCLASSFACTORY iface
,
1510 static const IClassFactoryVtbl TestClassFactoryOOP_Vtbl
=
1512 TestOOP_IClassFactory_QueryInterface
,
1513 TestOOP_IClassFactory_AddRef
,
1514 TestOOP_IClassFactory_Release
,
1515 TestOOP_IClassFactory_CreateInstance
,
1516 TestOOP_IClassFactory_LockServer
1519 static IClassFactory TestOOP_ClassFactory
= { &TestClassFactoryOOP_Vtbl
};
1521 /* tests functions commonly used by out of process COM servers */
1522 static void test_out_of_process_com()
1524 static const CLSID CLSID_WineOOPTest
= {
1528 {0xa1, 0xa2, 0x5d, 0x5a, 0x36, 0x54, 0xd3, 0xbd}
1529 }; /* 5201163f-8164-4fd0-a1a2-5d5a3654d3bd */
1535 heventShutdown
= CreateEvent(NULL
, TRUE
, FALSE
, NULL
);
1539 /* Start the object suspended */
1540 hr
= CoRegisterClassObject(&CLSID_WineOOPTest
, (IUnknown
*)&TestOOP_ClassFactory
,
1541 CLSCTX_LOCAL_SERVER
, REGCLS_MULTIPLEUSE
| REGCLS_SUSPENDED
, &cookie
);
1542 ok_ole_success(hr
, CoRegisterClassObject
);
1544 /* ... and CoGetClassObject does not find it and fails when it looks for the
1545 * class in the registry */
1546 hr
= CoGetClassObject(&CLSID_WineOOPTest
, CLSCTX_INPROC_SERVER
,
1547 NULL
, &IID_IClassFactory
, (LPVOID
*)&cf
);
1549 ok(hr
== REGDB_E_CLASSNOTREG
,
1550 "CoGetClassObject should have returned REGDB_E_CLASSNOTREG instead of 0x%08lx\n", hr
);
1553 /* Resume the object suspended above ... */
1554 hr
= CoResumeClassObjects();
1555 ok_ole_success(hr
, CoResumeClassObjects
);
1557 /* ... and now it should succeed */
1558 hr
= CoGetClassObject(&CLSID_WineOOPTest
, CLSCTX_INPROC_SERVER
,
1559 NULL
, &IID_IClassFactory
, (LPVOID
*)&cf
);
1560 ok_ole_success(hr
, CoGetClassObject
);
1562 /* Now check the locking is working */
1563 /* NOTE: we are accessing the class directly, not through a proxy */
1567 hr
= IClassFactory_LockServer(cf
, TRUE
);
1568 trace("IClassFactory_LockServer returned 0x%08lx\n", hr
);
1570 ok_more_than_one_lock();
1572 IClassFactory_LockServer(cf
, FALSE
);
1576 IClassFactory_Release(cf
);
1578 /* wait for shutdown signal */
1579 ret
= WaitForSingleObject(heventShutdown
, 5000);
1580 todo_wine
{ ok(ret
!= WAIT_TIMEOUT
, "Server didn't shut down or machine is under very heavy load\n"); }
1582 /* try to connect again after SCM has suspended registered class objects */
1583 hr
= CoGetClassObject(&CLSID_WineOOPTest
, CLSCTX_INPROC_SERVER
| CLSCTX_LOCAL_SERVER
, NULL
,
1584 &IID_IClassFactory
, (LPVOID
*)&cf
);
1586 ok(hr
== CO_E_SERVER_STOPPING
,
1587 "CoGetClassObject should have returned CO_E_SERVER_STOPPING instead of 0x%08lx\n", hr
);
1590 hr
= CoRevokeClassObject(cookie
);
1591 ok_ole_success(hr
, CoRevokeClassObject
);
1593 CloseHandle(heventShutdown
);
1597 static void test_ROT(void)
1599 static const WCHAR wszFileName
[] = {'B','E','2','0','E','2','F','5','-',
1600 '1','9','0','3','-','4','A','A','E','-','B','1','A','F','-',
1601 '2','0','4','6','E','5','8','6','C','9','2','5',0};
1603 IMoniker
*pMoniker
= NULL
;
1604 IRunningObjectTable
*pROT
= NULL
;
1609 hr
= CreateFileMoniker(wszFileName
, &pMoniker
);
1610 ok_ole_success(hr
, CreateClassMoniker
);
1611 hr
= GetRunningObjectTable(0, &pROT
);
1612 ok_ole_success(hr
, GetRunningObjectTable
);
1613 hr
= IRunningObjectTable_Register(pROT
, 0, (IUnknown
*)&Test_ClassFactory
, pMoniker
, &dwCookie
);
1614 ok_ole_success(hr
, IRunningObjectTable_Register
);
1616 ok_more_than_one_lock();
1618 hr
= IRunningObjectTable_Revoke(pROT
, dwCookie
);
1619 ok_ole_success(hr
, IRunningObjectTable_Revoke
);
1626 HMODULE hOle32
= GetModuleHandle("ole32");
1627 if (!(pCoInitializeEx
= (void*)GetProcAddress(hOle32
, "CoInitializeEx"))) goto no_test
;
1629 pCoInitializeEx(NULL
, COINIT_APARTMENTTHREADED
);
1631 /* FIXME: test CoCreateInstanceEx */
1633 /* helper function tests */
1634 test_CoGetPSClsid();
1636 /* lifecycle management and marshaling tests */
1637 test_no_marshaler();
1638 test_normal_marshal_and_release();
1639 test_normal_marshal_and_unmarshal();
1640 test_marshal_and_unmarshal_invalid();
1641 test_interthread_marshal_and_unmarshal();
1642 test_marshal_stub_apartment_shutdown();
1643 test_marshal_proxy_apartment_shutdown();
1644 test_marshal_proxy_mta_apartment_shutdown();
1645 test_no_couninitialize_server();
1646 test_no_couninitialize_client();
1647 test_tableweak_marshal_and_unmarshal_twice();
1648 test_tableweak_marshal_releasedata1();
1649 test_tableweak_marshal_releasedata2();
1650 test_tablestrong_marshal_and_unmarshal_twice();
1651 test_lock_object_external();
1652 test_disconnect_stub();
1653 test_normal_marshal_and_unmarshal_twice();
1654 test_hresult_marshaling();
1655 test_proxy_used_in_wrong_thread();
1656 test_message_filter();
1657 test_bad_marshal_stream();
1658 test_proxy_interfaces();
1659 test_stubbuffer(&IID_IClassFactory
);
1660 test_message_reentrancy();
1662 /* test_out_of_process_com(); */
1665 /* FIXME: test GIT */
1671 trace("You need DCOM95 installed to run this test\n");