4 * Copyright 2004 Robert Shearman
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
32 #include "wine/test.h"
34 /* functions that are not present on all versions of Windows */
35 HRESULT (WINAPI
* pCoInitializeEx
)(LPVOID lpReserved
, DWORD dwCoInit
);
37 /* helper macros to make tests a bit leaner */
38 #define ok_more_than_one_lock() ok(cLocks > 0, "Number of locks should be > 0, but actually is %d\n", cLocks)
39 #define ok_no_locks() ok(cLocks == 0, "Number of locks should be 0, but actually is %d\n", cLocks)
40 #define ok_ole_success(hr, func) ok(hr == S_OK, #func " failed with error 0x%08x\n", hr)
42 static const IID IID_IWineTest
=
47 {0xa1, 0xa2, 0x5d, 0x5a, 0x36, 0x54, 0xd3, 0xbd}
48 }; /* 5201163f-8164-4fd0-a1a2-5d5a3654d3bd */
50 #define EXTENTID_WineTest IID_IWineTest
52 static void test_cocreateinstance_proxy(void)
58 pCoInitializeEx(NULL
, COINIT_MULTITHREADED
);
60 hr
= CoCreateInstance(&CLSID_ShellDesktop
, NULL
, CLSCTX_INPROC
, &IID_IUnknown
, (void **)&pProxy
);
61 ok_ole_success(hr
, CoCreateInstance
);
62 hr
= IUnknown_QueryInterface(pProxy
, &IID_IMultiQI
, (void **)&pMQI
);
64 ok(hr
== S_OK
, "created object is not a proxy, so was created in the wrong apartment\n");
66 IMultiQI_Release(pMQI
);
67 IUnknown_Release(pProxy
);
72 static const LARGE_INTEGER ullZero
;
75 static void LockModule(void)
77 InterlockedIncrement(&cLocks
);
80 static void UnlockModule(void)
82 InterlockedDecrement(&cLocks
);
86 static HRESULT WINAPI
Test_IUnknown_QueryInterface(
91 if (ppvObj
== NULL
) return E_POINTER
;
93 if (IsEqualGUID(riid
, &IID_IUnknown
))
95 *ppvObj
= (LPVOID
)iface
;
96 IUnknown_AddRef(iface
);
101 return E_NOINTERFACE
;
104 static ULONG WINAPI
Test_IUnknown_AddRef(LPUNKNOWN iface
)
107 return 2; /* non-heap-based object */
110 static ULONG WINAPI
Test_IUnknown_Release(LPUNKNOWN iface
)
113 return 1; /* non-heap-based object */
116 static const IUnknownVtbl TestUnknown_Vtbl
=
118 Test_IUnknown_QueryInterface
,
119 Test_IUnknown_AddRef
,
120 Test_IUnknown_Release
,
123 static IUnknown Test_Unknown
= { &TestUnknown_Vtbl
};
126 static HRESULT WINAPI
Test_IClassFactory_QueryInterface(
127 LPCLASSFACTORY iface
,
131 if (ppvObj
== NULL
) return E_POINTER
;
133 if (IsEqualGUID(riid
, &IID_IUnknown
) ||
134 IsEqualGUID(riid
, &IID_IClassFactory
))
136 *ppvObj
= (LPVOID
)iface
;
137 IClassFactory_AddRef(iface
);
142 return E_NOINTERFACE
;
145 static ULONG WINAPI
Test_IClassFactory_AddRef(LPCLASSFACTORY iface
)
148 return 2; /* non-heap-based object */
151 static ULONG WINAPI
Test_IClassFactory_Release(LPCLASSFACTORY iface
)
154 return 1; /* non-heap-based object */
157 static HRESULT WINAPI
Test_IClassFactory_CreateInstance(
158 LPCLASSFACTORY iface
,
163 if (pUnkOuter
) return CLASS_E_NOAGGREGATION
;
164 return IUnknown_QueryInterface((IUnknown
*)&Test_Unknown
, riid
, ppvObj
);
167 static HRESULT WINAPI
Test_IClassFactory_LockServer(
168 LPCLASSFACTORY iface
,
174 static const IClassFactoryVtbl TestClassFactory_Vtbl
=
176 Test_IClassFactory_QueryInterface
,
177 Test_IClassFactory_AddRef
,
178 Test_IClassFactory_Release
,
179 Test_IClassFactory_CreateInstance
,
180 Test_IClassFactory_LockServer
183 static IClassFactory Test_ClassFactory
= { &TestClassFactory_Vtbl
};
185 #define RELEASEMARSHALDATA WM_USER
187 struct host_object_data
192 MSHLFLAGS marshal_flags
;
193 HANDLE marshal_event
;
194 IMessageFilter
*filter
;
197 static DWORD CALLBACK
host_object_proc(LPVOID p
)
199 struct host_object_data
*data
= (struct host_object_data
*)p
;
203 pCoInitializeEx(NULL
, COINIT_APARTMENTTHREADED
);
207 IMessageFilter
* prev_filter
= NULL
;
208 hr
= CoRegisterMessageFilter(data
->filter
, &prev_filter
);
209 if (prev_filter
) IMessageFilter_Release(prev_filter
);
210 ok_ole_success(hr
, CoRegisterMessageFilter
);
213 hr
= CoMarshalInterface(data
->stream
, &data
->iid
, data
->object
, MSHCTX_INPROC
, NULL
, data
->marshal_flags
);
214 ok_ole_success(hr
, CoMarshalInterface
);
216 /* force the message queue to be created before signaling parent thread */
217 PeekMessage(&msg
, NULL
, WM_USER
, WM_USER
, PM_NOREMOVE
);
219 SetEvent(data
->marshal_event
);
221 while (GetMessage(&msg
, NULL
, 0, 0))
223 if (msg
.hwnd
== NULL
&& msg
.message
== RELEASEMARSHALDATA
)
225 trace("releasing marshal data\n");
226 CoReleaseMarshalData(data
->stream
);
227 SetEvent((HANDLE
)msg
.lParam
);
230 DispatchMessage(&msg
);
233 HeapFree(GetProcessHeap(), 0, data
);
240 static DWORD
start_host_object2(IStream
*stream
, REFIID riid
, IUnknown
*object
, MSHLFLAGS marshal_flags
, IMessageFilter
*filter
, HANDLE
*thread
)
243 HANDLE marshal_event
= CreateEvent(NULL
, FALSE
, FALSE
, NULL
);
244 struct host_object_data
*data
= HeapAlloc(GetProcessHeap(), 0, sizeof(*data
));
246 data
->stream
= stream
;
248 data
->object
= object
;
249 data
->marshal_flags
= marshal_flags
;
250 data
->marshal_event
= marshal_event
;
251 data
->filter
= filter
;
253 *thread
= CreateThread(NULL
, 0, host_object_proc
, data
, 0, &tid
);
255 /* wait for marshaling to complete before returning */
256 WaitForSingleObject(marshal_event
, INFINITE
);
257 CloseHandle(marshal_event
);
262 static DWORD
start_host_object(IStream
*stream
, REFIID riid
, IUnknown
*object
, MSHLFLAGS marshal_flags
, HANDLE
*thread
)
264 return start_host_object2(stream
, riid
, object
, marshal_flags
, NULL
, thread
);
267 /* asks thread to release the marshal data because it has to be done by the
268 * same thread that marshaled the interface in the first place. */
269 static void release_host_object(DWORD tid
)
271 HANDLE event
= CreateEvent(NULL
, FALSE
, FALSE
, NULL
);
272 PostThreadMessage(tid
, RELEASEMARSHALDATA
, 0, (LPARAM
)event
);
273 WaitForSingleObject(event
, INFINITE
);
277 static void end_host_object(DWORD tid
, HANDLE thread
)
279 BOOL ret
= PostThreadMessage(tid
, WM_QUIT
, 0, 0);
280 ok(ret
, "PostThreadMessage failed with error %d\n", GetLastError());
281 /* be careful of races - don't return until hosting thread has terminated */
282 WaitForSingleObject(thread
, INFINITE
);
286 /* tests failure case of interface not having a marshaler specified in the
288 static void test_no_marshaler(void)
293 hr
= CreateStreamOnHGlobal(NULL
, TRUE
, &pStream
);
294 ok_ole_success(hr
, CreateStreamOnHGlobal
);
295 hr
= CoMarshalInterface(pStream
, &IID_IWineTest
, (IUnknown
*)&Test_ClassFactory
, MSHCTX_INPROC
, NULL
, MSHLFLAGS_NORMAL
);
296 ok(hr
== E_NOINTERFACE
, "CoMarshalInterface should have returned E_NOINTERFACE instead of 0x%08x\n", hr
);
298 IStream_Release(pStream
);
301 /* tests normal marshal and then release without unmarshaling */
302 static void test_normal_marshal_and_release(void)
305 IStream
*pStream
= NULL
;
309 hr
= CreateStreamOnHGlobal(NULL
, TRUE
, &pStream
);
310 ok_ole_success(hr
, CreateStreamOnHGlobal
);
311 hr
= CoMarshalInterface(pStream
, &IID_IClassFactory
, (IUnknown
*)&Test_ClassFactory
, MSHCTX_INPROC
, NULL
, MSHLFLAGS_NORMAL
);
312 ok_ole_success(hr
, CoMarshalInterface
);
314 ok_more_than_one_lock();
316 IStream_Seek(pStream
, ullZero
, STREAM_SEEK_SET
, NULL
);
317 hr
= CoReleaseMarshalData(pStream
);
318 ok_ole_success(hr
, CoReleaseMarshalData
);
319 IStream_Release(pStream
);
324 /* tests success case of a same-thread marshal and unmarshal */
325 static void test_normal_marshal_and_unmarshal(void)
328 IStream
*pStream
= NULL
;
329 IUnknown
*pProxy
= NULL
;
333 hr
= CreateStreamOnHGlobal(NULL
, TRUE
, &pStream
);
334 ok_ole_success(hr
, CreateStreamOnHGlobal
);
335 hr
= CoMarshalInterface(pStream
, &IID_IClassFactory
, (IUnknown
*)&Test_ClassFactory
, MSHCTX_INPROC
, NULL
, MSHLFLAGS_NORMAL
);
336 ok_ole_success(hr
, CoMarshalInterface
);
338 ok_more_than_one_lock();
340 IStream_Seek(pStream
, ullZero
, STREAM_SEEK_SET
, NULL
);
341 hr
= CoUnmarshalInterface(pStream
, &IID_IClassFactory
, (void **)&pProxy
);
342 ok_ole_success(hr
, CoUnmarshalInterface
);
343 IStream_Release(pStream
);
345 ok_more_than_one_lock();
347 IUnknown_Release(pProxy
);
352 /* tests failure case of unmarshaling a freed object */
353 static void test_marshal_and_unmarshal_invalid(void)
356 IStream
*pStream
= NULL
;
357 IClassFactory
*pProxy
= NULL
;
364 hr
= CreateStreamOnHGlobal(NULL
, TRUE
, &pStream
);
365 ok_ole_success(hr
, CreateStreamOnHGlobal
);
366 tid
= start_host_object(pStream
, &IID_IClassFactory
, (IUnknown
*)&Test_ClassFactory
, MSHLFLAGS_NORMAL
, &thread
);
368 ok_more_than_one_lock();
370 IStream_Seek(pStream
, ullZero
, STREAM_SEEK_SET
, NULL
);
371 hr
= CoReleaseMarshalData(pStream
);
372 ok_ole_success(hr
, CoReleaseMarshalData
);
376 IStream_Seek(pStream
, ullZero
, STREAM_SEEK_SET
, NULL
);
377 hr
= CoUnmarshalInterface(pStream
, &IID_IClassFactory
, (void **)&pProxy
);
378 todo_wine
{ ok_ole_success(hr
, CoUnmarshalInterface
); }
384 hr
= IClassFactory_CreateInstance(pProxy
, NULL
, &IID_IUnknown
, &dummy
);
385 ok(hr
== RPC_E_DISCONNECTED
, "Remote call should have returned RPC_E_DISCONNECTED, instead of 0x%08x\n", hr
);
387 IClassFactory_Release(pProxy
);
390 IStream_Release(pStream
);
392 end_host_object(tid
, thread
);
395 static void test_same_apartment_unmarshal_failure(void)
400 static const LARGE_INTEGER llZero
;
404 hr
= CreateStreamOnHGlobal(NULL
, TRUE
, &pStream
);
405 ok_ole_success(hr
, CreateStreamOnHGlobal
);
407 hr
= CoMarshalInterface(pStream
, &IID_IUnknown
, (IUnknown
*)&Test_ClassFactory
, MSHCTX_INPROC
, NULL
, MSHLFLAGS_NORMAL
);
408 ok_ole_success(hr
, CoMarshalInterface
);
410 ok_more_than_one_lock();
412 hr
= IStream_Seek(pStream
, llZero
, STREAM_SEEK_SET
, NULL
);
413 ok_ole_success(hr
, IStream_Seek
);
415 hr
= CoUnmarshalInterface(pStream
, &IID_IParseDisplayName
, (void **)&pProxy
);
416 ok(hr
== E_NOINTERFACE
, "CoUnmarshalInterface should have returned E_NOINTERFACE instead of 0x%08x\n", hr
);
421 /* tests success case of an interthread marshal */
422 static void test_interthread_marshal_and_unmarshal(void)
425 IStream
*pStream
= NULL
;
426 IUnknown
*pProxy
= NULL
;
432 hr
= CreateStreamOnHGlobal(NULL
, TRUE
, &pStream
);
433 ok_ole_success(hr
, CreateStreamOnHGlobal
);
434 tid
= start_host_object(pStream
, &IID_IClassFactory
, (IUnknown
*)&Test_ClassFactory
, MSHLFLAGS_NORMAL
, &thread
);
436 ok_more_than_one_lock();
438 IStream_Seek(pStream
, ullZero
, STREAM_SEEK_SET
, NULL
);
439 hr
= CoUnmarshalInterface(pStream
, &IID_IClassFactory
, (void **)&pProxy
);
440 ok_ole_success(hr
, CoUnmarshalInterface
);
441 IStream_Release(pStream
);
443 ok_more_than_one_lock();
445 IUnknown_Release(pProxy
);
449 end_host_object(tid
, thread
);
452 /* the number of external references that Wine's proxy manager normally gives
453 * out, so we can test the border case of running out of references */
454 #define NORMALEXTREFS 5
456 /* tests success case of an interthread marshal and then marshaling the proxy */
457 static void test_proxy_marshal_and_unmarshal(void)
460 IStream
*pStream
= NULL
;
461 IUnknown
*pProxy
= NULL
;
462 IUnknown
*pProxy2
= NULL
;
469 hr
= CreateStreamOnHGlobal(NULL
, TRUE
, &pStream
);
470 ok_ole_success(hr
, CreateStreamOnHGlobal
);
471 tid
= start_host_object(pStream
, &IID_IClassFactory
, (IUnknown
*)&Test_ClassFactory
, MSHLFLAGS_NORMAL
, &thread
);
473 ok_more_than_one_lock();
475 IStream_Seek(pStream
, ullZero
, STREAM_SEEK_SET
, NULL
);
476 hr
= CoUnmarshalInterface(pStream
, &IID_IClassFactory
, (void **)&pProxy
);
477 ok_ole_success(hr
, CoUnmarshalInterface
);
479 ok_more_than_one_lock();
481 IStream_Seek(pStream
, ullZero
, STREAM_SEEK_SET
, NULL
);
482 /* marshal the proxy */
483 hr
= CoMarshalInterface(pStream
, &IID_IClassFactory
, pProxy
, MSHCTX_INPROC
, NULL
, MSHLFLAGS_NORMAL
);
484 ok_ole_success(hr
, CoMarshalInterface
);
486 ok_more_than_one_lock();
488 /* marshal 5 more times to exhaust the normal external references of 5 */
489 for (i
= 0; i
< NORMALEXTREFS
; i
++)
491 hr
= CoMarshalInterface(pStream
, &IID_IClassFactory
, pProxy
, MSHCTX_INPROC
, NULL
, MSHLFLAGS_NORMAL
);
492 ok_ole_success(hr
, CoMarshalInterface
);
495 ok_more_than_one_lock();
497 /* release the original proxy to test that we successfully keep the
498 * original object alive */
499 IUnknown_Release(pProxy
);
501 IStream_Seek(pStream
, ullZero
, STREAM_SEEK_SET
, NULL
);
502 hr
= CoUnmarshalInterface(pStream
, &IID_IClassFactory
, (void **)&pProxy2
);
503 ok_ole_success(hr
, CoUnmarshalInterface
);
505 ok_more_than_one_lock();
507 /* now the proxies should be as follows:
508 * pProxy2 -> &Test_ClassFactory
509 * they should NOT be as follows:
510 * pProxy -> &Test_ClassFactory
512 * the above can only really be tested by looking in +ole traces
515 IUnknown_Release(pProxy2
);
517 /* unmarshal all of the proxies to check that the object stub still exists */
518 for (i
= 0; i
< NORMALEXTREFS
; i
++)
520 hr
= CoUnmarshalInterface(pStream
, &IID_IClassFactory
, (void **)&pProxy2
);
521 ok_ole_success(hr
, CoUnmarshalInterface
);
523 IUnknown_Release(pProxy2
);
528 IStream_Release(pStream
);
530 end_host_object(tid
, thread
);
533 /* tests success case of an interthread marshal and then marshaling the proxy
534 * using an iid that hasn't previously been unmarshaled */
535 static void test_proxy_marshal_and_unmarshal2(void)
538 IStream
*pStream
= NULL
;
539 IUnknown
*pProxy
= NULL
;
540 IUnknown
*pProxy2
= NULL
;
546 hr
= CreateStreamOnHGlobal(NULL
, TRUE
, &pStream
);
547 ok_ole_success(hr
, CreateStreamOnHGlobal
);
548 tid
= start_host_object(pStream
, &IID_IUnknown
, (IUnknown
*)&Test_ClassFactory
, MSHLFLAGS_NORMAL
, &thread
);
550 ok_more_than_one_lock();
552 IStream_Seek(pStream
, ullZero
, STREAM_SEEK_SET
, NULL
);
553 hr
= CoUnmarshalInterface(pStream
, &IID_IUnknown
, (void **)&pProxy
);
554 ok_ole_success(hr
, CoUnmarshalInterface
);
556 ok_more_than_one_lock();
558 IStream_Seek(pStream
, ullZero
, STREAM_SEEK_SET
, NULL
);
559 /* marshal the proxy */
560 hr
= CoMarshalInterface(pStream
, &IID_IClassFactory
, pProxy
, MSHCTX_INPROC
, NULL
, MSHLFLAGS_NORMAL
);
561 ok_ole_success(hr
, CoMarshalInterface
);
563 ok_more_than_one_lock();
565 IStream_Seek(pStream
, ullZero
, STREAM_SEEK_SET
, NULL
);
566 /* unmarshal the second proxy to the object */
567 hr
= CoUnmarshalInterface(pStream
, &IID_IClassFactory
, (void **)&pProxy2
);
568 ok_ole_success(hr
, CoUnmarshalInterface
);
569 IStream_Release(pStream
);
571 /* now the proxies should be as follows:
572 * pProxy -> &Test_ClassFactory
573 * pProxy2 -> &Test_ClassFactory
574 * they should NOT be as follows:
575 * pProxy -> &Test_ClassFactory
577 * the above can only really be tested by looking in +ole traces
580 ok_more_than_one_lock();
582 IUnknown_Release(pProxy
);
584 ok_more_than_one_lock();
586 IUnknown_Release(pProxy2
);
590 end_host_object(tid
, thread
);
593 /* tests that stubs are released when the containing apartment is destroyed */
594 static void test_marshal_stub_apartment_shutdown(void)
597 IStream
*pStream
= NULL
;
598 IUnknown
*pProxy
= NULL
;
604 hr
= CreateStreamOnHGlobal(NULL
, TRUE
, &pStream
);
605 ok_ole_success(hr
, CreateStreamOnHGlobal
);
606 tid
= start_host_object(pStream
, &IID_IClassFactory
, (IUnknown
*)&Test_ClassFactory
, MSHLFLAGS_NORMAL
, &thread
);
608 ok_more_than_one_lock();
610 IStream_Seek(pStream
, ullZero
, STREAM_SEEK_SET
, NULL
);
611 hr
= CoUnmarshalInterface(pStream
, &IID_IClassFactory
, (void **)&pProxy
);
612 ok_ole_success(hr
, CoUnmarshalInterface
);
613 IStream_Release(pStream
);
615 ok_more_than_one_lock();
617 end_host_object(tid
, thread
);
621 IUnknown_Release(pProxy
);
626 /* tests that proxies are released when the containing apartment is destroyed */
627 static void test_marshal_proxy_apartment_shutdown(void)
630 IStream
*pStream
= NULL
;
631 IUnknown
*pProxy
= NULL
;
637 hr
= CreateStreamOnHGlobal(NULL
, TRUE
, &pStream
);
638 ok_ole_success(hr
, CreateStreamOnHGlobal
);
639 tid
= start_host_object(pStream
, &IID_IClassFactory
, (IUnknown
*)&Test_ClassFactory
, MSHLFLAGS_NORMAL
, &thread
);
641 ok_more_than_one_lock();
643 IStream_Seek(pStream
, ullZero
, STREAM_SEEK_SET
, NULL
);
644 hr
= CoUnmarshalInterface(pStream
, &IID_IClassFactory
, (void **)&pProxy
);
645 ok_ole_success(hr
, CoUnmarshalInterface
);
646 IStream_Release(pStream
);
648 ok_more_than_one_lock();
654 IUnknown_Release(pProxy
);
658 end_host_object(tid
, thread
);
660 pCoInitializeEx(NULL
, COINIT_APARTMENTTHREADED
);
663 /* tests that proxies are released when the containing mta apartment is destroyed */
664 static void test_marshal_proxy_mta_apartment_shutdown(void)
667 IStream
*pStream
= NULL
;
668 IUnknown
*pProxy
= NULL
;
673 pCoInitializeEx(NULL
, COINIT_MULTITHREADED
);
677 hr
= CreateStreamOnHGlobal(NULL
, TRUE
, &pStream
);
678 ok_ole_success(hr
, CreateStreamOnHGlobal
);
679 tid
= start_host_object(pStream
, &IID_IClassFactory
, (IUnknown
*)&Test_ClassFactory
, MSHLFLAGS_NORMAL
, &thread
);
681 ok_more_than_one_lock();
683 IStream_Seek(pStream
, ullZero
, STREAM_SEEK_SET
, NULL
);
684 hr
= CoUnmarshalInterface(pStream
, &IID_IClassFactory
, (void **)&pProxy
);
685 ok_ole_success(hr
, CoUnmarshalInterface
);
686 IStream_Release(pStream
);
688 ok_more_than_one_lock();
694 IUnknown_Release(pProxy
);
698 end_host_object(tid
, thread
);
700 pCoInitializeEx(NULL
, COINIT_APARTMENTTHREADED
);
706 HANDLE marshal_event
;
707 HANDLE unmarshal_event
;
710 /* helper for test_no_couninitialize_server */
711 static DWORD CALLBACK
no_couninitialize_server_proc(LPVOID p
)
713 struct ncu_params
*ncu_params
= (struct ncu_params
*)p
;
716 pCoInitializeEx(NULL
, COINIT_MULTITHREADED
);
718 hr
= CoMarshalInterface(ncu_params
->stream
, &IID_IClassFactory
, (IUnknown
*)&Test_ClassFactory
, MSHCTX_INPROC
, NULL
, MSHLFLAGS_NORMAL
);
719 ok_ole_success(hr
, CoMarshalInterface
);
721 SetEvent(ncu_params
->marshal_event
);
723 WaitForSingleObject(ncu_params
->unmarshal_event
, INFINITE
);
725 /* die without calling CoUninitialize */
730 /* tests apartment that an apartment with a stub is released without deadlock
731 * if the owning thread exits */
732 static void test_no_couninitialize_server(void)
735 IStream
*pStream
= NULL
;
736 IUnknown
*pProxy
= NULL
;
739 struct ncu_params ncu_params
;
743 ncu_params
.marshal_event
= CreateEvent(NULL
, TRUE
, FALSE
, NULL
);
744 ncu_params
.unmarshal_event
= CreateEvent(NULL
, TRUE
, FALSE
, NULL
);
746 hr
= CreateStreamOnHGlobal(NULL
, TRUE
, &pStream
);
747 ok_ole_success(hr
, CreateStreamOnHGlobal
);
748 ncu_params
.stream
= pStream
;
750 thread
= CreateThread(NULL
, 0, no_couninitialize_server_proc
, &ncu_params
, 0, &tid
);
752 WaitForSingleObject(ncu_params
.marshal_event
, INFINITE
);
753 ok_more_than_one_lock();
755 IStream_Seek(pStream
, ullZero
, STREAM_SEEK_SET
, NULL
);
756 hr
= CoUnmarshalInterface(pStream
, &IID_IClassFactory
, (void **)&pProxy
);
757 ok_ole_success(hr
, CoUnmarshalInterface
);
758 IStream_Release(pStream
);
760 ok_more_than_one_lock();
762 SetEvent(ncu_params
.unmarshal_event
);
763 WaitForSingleObject(thread
, INFINITE
);
768 CloseHandle(ncu_params
.marshal_event
);
769 CloseHandle(ncu_params
.unmarshal_event
);
771 IUnknown_Release(pProxy
);
776 /* STA -> STA call during DLL_THREAD_DETACH */
777 static DWORD CALLBACK
no_couninitialize_client_proc(LPVOID p
)
779 struct ncu_params
*ncu_params
= (struct ncu_params
*)p
;
781 IUnknown
*pProxy
= NULL
;
783 pCoInitializeEx(NULL
, COINIT_APARTMENTTHREADED
);
785 hr
= CoUnmarshalInterface(ncu_params
->stream
, &IID_IClassFactory
, (void **)&pProxy
);
786 ok_ole_success(hr
, CoUnmarshalInterface
);
787 IStream_Release(ncu_params
->stream
);
789 ok_more_than_one_lock();
791 /* die without calling CoUninitialize */
796 /* tests STA -> STA call during DLL_THREAD_DETACH doesn't deadlock */
797 static void test_no_couninitialize_client(void)
800 IStream
*pStream
= NULL
;
805 struct ncu_params ncu_params
;
809 hr
= CreateStreamOnHGlobal(NULL
, TRUE
, &pStream
);
810 ok_ole_success(hr
, CreateStreamOnHGlobal
);
811 ncu_params
.stream
= pStream
;
813 /* NOTE: assumes start_host_object uses an STA to host the object, as MTAs
814 * always deadlock when called from within DllMain */
815 host_tid
= start_host_object(pStream
, &IID_IClassFactory
, (IUnknown
*)&Test_ClassFactory
, MSHLFLAGS_NORMAL
, &host_thread
);
816 IStream_Seek(pStream
, ullZero
, STREAM_SEEK_SET
, NULL
);
818 ok_more_than_one_lock();
820 thread
= CreateThread(NULL
, 0, no_couninitialize_client_proc
, &ncu_params
, 0, &tid
);
822 WaitForSingleObject(thread
, INFINITE
);
827 end_host_object(host_tid
, host_thread
);
830 /* tests success case of a same-thread table-weak marshal, unmarshal, unmarshal */
831 static void test_tableweak_marshal_and_unmarshal_twice(void)
834 IStream
*pStream
= NULL
;
835 IUnknown
*pProxy1
= NULL
;
836 IUnknown
*pProxy2
= NULL
;
842 hr
= CreateStreamOnHGlobal(NULL
, TRUE
, &pStream
);
843 ok_ole_success(hr
, CreateStreamOnHGlobal
);
844 tid
= start_host_object(pStream
, &IID_IClassFactory
, (IUnknown
*)&Test_ClassFactory
, MSHLFLAGS_TABLEWEAK
, &thread
);
846 ok_more_than_one_lock();
848 IStream_Seek(pStream
, ullZero
, STREAM_SEEK_SET
, NULL
);
849 hr
= CoUnmarshalInterface(pStream
, &IID_IClassFactory
, (void **)&pProxy1
);
850 ok_ole_success(hr
, CoUnmarshalInterface
);
852 ok_more_than_one_lock();
854 IStream_Seek(pStream
, ullZero
, STREAM_SEEK_SET
, NULL
);
855 hr
= CoUnmarshalInterface(pStream
, &IID_IClassFactory
, (void **)&pProxy2
);
856 IStream_Release(pStream
);
857 ok_ole_success(hr
, CoUnmarshalInterface
);
859 ok_more_than_one_lock();
861 IUnknown_Release(pProxy1
);
862 IUnknown_Release(pProxy2
);
864 /* this line is shows the difference between weak and strong table marshaling:
865 * weak has cLocks == 0
866 * strong has cLocks > 0 */
869 end_host_object(tid
, thread
);
872 /* tests releasing after unmarshaling one object */
873 static void test_tableweak_marshal_releasedata1(void)
876 IStream
*pStream
= NULL
;
877 IUnknown
*pProxy1
= NULL
;
878 IUnknown
*pProxy2
= NULL
;
884 hr
= CreateStreamOnHGlobal(NULL
, TRUE
, &pStream
);
885 ok_ole_success(hr
, CreateStreamOnHGlobal
);
886 tid
= start_host_object(pStream
, &IID_IClassFactory
, (IUnknown
*)&Test_ClassFactory
, MSHLFLAGS_TABLEWEAK
, &thread
);
888 ok_more_than_one_lock();
890 IStream_Seek(pStream
, ullZero
, STREAM_SEEK_SET
, NULL
);
891 hr
= CoUnmarshalInterface(pStream
, &IID_IClassFactory
, (void **)&pProxy1
);
892 ok_ole_success(hr
, CoUnmarshalInterface
);
894 ok_more_than_one_lock();
896 /* release the remaining reference on the object by calling
897 * CoReleaseMarshalData in the hosting thread */
898 IStream_Seek(pStream
, ullZero
, STREAM_SEEK_SET
, NULL
);
899 release_host_object(tid
);
901 ok_more_than_one_lock();
903 IStream_Seek(pStream
, ullZero
, STREAM_SEEK_SET
, NULL
);
904 hr
= CoUnmarshalInterface(pStream
, &IID_IClassFactory
, (void **)&pProxy2
);
905 ok_ole_success(hr
, CoUnmarshalInterface
);
906 IStream_Release(pStream
);
908 ok_more_than_one_lock();
910 IUnknown_Release(pProxy1
);
912 IUnknown_Release(pProxy2
);
914 /* this line is shows the difference between weak and strong table marshaling:
915 * weak has cLocks == 0
916 * strong has cLocks > 0 */
919 end_host_object(tid
, thread
);
922 /* tests releasing after unmarshaling one object */
923 static void test_tableweak_marshal_releasedata2(void)
926 IStream
*pStream
= NULL
;
927 IUnknown
*pProxy
= NULL
;
933 hr
= CreateStreamOnHGlobal(NULL
, TRUE
, &pStream
);
934 ok_ole_success(hr
, CreateStreamOnHGlobal
);
935 tid
= start_host_object(pStream
, &IID_IClassFactory
, (IUnknown
*)&Test_ClassFactory
, MSHLFLAGS_TABLEWEAK
, &thread
);
937 ok_more_than_one_lock();
939 /* release the remaining reference on the object by calling
940 * CoReleaseMarshalData in the hosting thread */
941 IStream_Seek(pStream
, ullZero
, STREAM_SEEK_SET
, NULL
);
942 release_host_object(tid
);
946 IStream_Seek(pStream
, ullZero
, STREAM_SEEK_SET
, NULL
);
947 hr
= CoUnmarshalInterface(pStream
, &IID_IClassFactory
, (void **)&pProxy
);
950 ok(hr
== CO_E_OBJNOTREG
,
951 "CoUnmarshalInterface should have failed with CO_E_OBJNOTREG, but returned 0x%08x instead\n",
954 IStream_Release(pStream
);
958 end_host_object(tid
, thread
);
961 /* tests success case of a same-thread table-strong marshal, unmarshal, unmarshal */
962 static void test_tablestrong_marshal_and_unmarshal_twice(void)
965 IStream
*pStream
= NULL
;
966 IUnknown
*pProxy1
= NULL
;
967 IUnknown
*pProxy2
= NULL
;
973 hr
= CreateStreamOnHGlobal(NULL
, TRUE
, &pStream
);
974 ok_ole_success(hr
, CreateStreamOnHGlobal
);
975 tid
= start_host_object(pStream
, &IID_IClassFactory
, (IUnknown
*)&Test_ClassFactory
, MSHLFLAGS_TABLESTRONG
, &thread
);
977 ok_more_than_one_lock();
979 IStream_Seek(pStream
, ullZero
, STREAM_SEEK_SET
, NULL
);
980 hr
= CoUnmarshalInterface(pStream
, &IID_IClassFactory
, (void **)&pProxy1
);
981 ok_ole_success(hr
, CoUnmarshalInterface
);
983 ok_more_than_one_lock();
985 IStream_Seek(pStream
, ullZero
, STREAM_SEEK_SET
, NULL
);
986 hr
= CoUnmarshalInterface(pStream
, &IID_IClassFactory
, (void **)&pProxy2
);
987 ok_ole_success(hr
, CoUnmarshalInterface
);
989 ok_more_than_one_lock();
991 if (pProxy1
) IUnknown_Release(pProxy1
);
992 if (pProxy2
) IUnknown_Release(pProxy2
);
994 /* this line is shows the difference between weak and strong table marshaling:
995 * weak has cLocks == 0
996 * strong has cLocks > 0 */
997 ok_more_than_one_lock();
999 /* release the remaining reference on the object by calling
1000 * CoReleaseMarshalData in the hosting thread */
1001 IStream_Seek(pStream
, ullZero
, STREAM_SEEK_SET
, NULL
);
1002 release_host_object(tid
);
1003 IStream_Release(pStream
);
1007 end_host_object(tid
, thread
);
1010 /* tests CoLockObjectExternal */
1011 static void test_lock_object_external(void)
1014 IStream
*pStream
= NULL
;
1018 /* test the stub manager creation aspect of CoLockObjectExternal when the
1019 * object hasn't been marshaled yet */
1020 CoLockObjectExternal((IUnknown
*)&Test_ClassFactory
, TRUE
, TRUE
);
1022 ok_more_than_one_lock();
1024 CoDisconnectObject((IUnknown
*)&Test_ClassFactory
, 0);
1028 /* test our empty stub manager being handled correctly in
1029 * CoMarshalInterface */
1030 CoLockObjectExternal((IUnknown
*)&Test_ClassFactory
, TRUE
, TRUE
);
1032 hr
= CreateStreamOnHGlobal(NULL
, TRUE
, &pStream
);
1033 ok_ole_success(hr
, CreateStreamOnHGlobal
);
1034 hr
= CoMarshalInterface(pStream
, &IID_IClassFactory
, (IUnknown
*)&Test_ClassFactory
, MSHCTX_INPROC
, NULL
, MSHLFLAGS_NORMAL
);
1035 ok_ole_success(hr
, CoMarshalInterface
);
1037 CoLockObjectExternal((IUnknown
*)&Test_ClassFactory
, TRUE
, TRUE
);
1039 ok_more_than_one_lock();
1041 IStream_Seek(pStream
, ullZero
, STREAM_SEEK_SET
, NULL
);
1042 hr
= CoReleaseMarshalData(pStream
);
1043 ok_ole_success(hr
, CoReleaseMarshalData
);
1044 IStream_Release(pStream
);
1046 ok_more_than_one_lock();
1048 CoLockObjectExternal((IUnknown
*)&Test_ClassFactory
, FALSE
, TRUE
);
1050 ok_more_than_one_lock();
1052 CoLockObjectExternal((IUnknown
*)&Test_ClassFactory
, FALSE
, TRUE
);
1057 /* tests disconnecting stubs */
1058 static void test_disconnect_stub(void)
1061 IStream
*pStream
= NULL
;
1065 hr
= CreateStreamOnHGlobal(NULL
, TRUE
, &pStream
);
1066 ok_ole_success(hr
, CreateStreamOnHGlobal
);
1067 hr
= CoMarshalInterface(pStream
, &IID_IClassFactory
, (IUnknown
*)&Test_ClassFactory
, MSHCTX_INPROC
, NULL
, MSHLFLAGS_NORMAL
);
1068 ok_ole_success(hr
, CoMarshalInterface
);
1070 CoLockObjectExternal((IUnknown
*)&Test_ClassFactory
, TRUE
, TRUE
);
1072 ok_more_than_one_lock();
1074 IStream_Seek(pStream
, ullZero
, STREAM_SEEK_SET
, NULL
);
1075 hr
= CoReleaseMarshalData(pStream
);
1076 ok_ole_success(hr
, CoReleaseMarshalData
);
1077 IStream_Release(pStream
);
1079 ok_more_than_one_lock();
1081 CoDisconnectObject((IUnknown
*)&Test_ClassFactory
, 0);
1086 /* tests failure case of a same-thread marshal and unmarshal twice */
1087 static void test_normal_marshal_and_unmarshal_twice(void)
1090 IStream
*pStream
= NULL
;
1091 IUnknown
*pProxy1
= NULL
;
1092 IUnknown
*pProxy2
= NULL
;
1096 hr
= CreateStreamOnHGlobal(NULL
, TRUE
, &pStream
);
1097 ok_ole_success(hr
, CreateStreamOnHGlobal
);
1098 hr
= CoMarshalInterface(pStream
, &IID_IClassFactory
, (IUnknown
*)&Test_ClassFactory
, MSHCTX_INPROC
, NULL
, MSHLFLAGS_NORMAL
);
1099 ok_ole_success(hr
, CoMarshalInterface
);
1101 ok_more_than_one_lock();
1103 IStream_Seek(pStream
, ullZero
, STREAM_SEEK_SET
, NULL
);
1104 hr
= CoUnmarshalInterface(pStream
, &IID_IClassFactory
, (void **)&pProxy1
);
1105 ok_ole_success(hr
, CoUnmarshalInterface
);
1107 ok_more_than_one_lock();
1109 IStream_Seek(pStream
, ullZero
, STREAM_SEEK_SET
, NULL
);
1110 hr
= CoUnmarshalInterface(pStream
, &IID_IClassFactory
, (void **)&pProxy2
);
1111 ok(hr
== CO_E_OBJNOTCONNECTED
,
1112 "CoUnmarshalInterface should have failed with error CO_E_OBJNOTCONNECTED for double unmarshal, instead of 0x%08x\n", hr
);
1114 IStream_Release(pStream
);
1116 ok_more_than_one_lock();
1118 IUnknown_Release(pProxy1
);
1123 /* tests success case of marshaling and unmarshaling an HRESULT */
1124 static void test_hresult_marshaling(void)
1127 HRESULT hr_marshaled
= 0;
1128 IStream
*pStream
= NULL
;
1129 static const HRESULT E_DEADBEEF
= 0xdeadbeef;
1131 hr
= CreateStreamOnHGlobal(NULL
, TRUE
, &pStream
);
1132 ok_ole_success(hr
, CreateStreamOnHGlobal
);
1134 hr
= CoMarshalHresult(pStream
, E_DEADBEEF
);
1135 ok_ole_success(hr
, CoMarshalHresult
);
1137 IStream_Seek(pStream
, ullZero
, STREAM_SEEK_SET
, NULL
);
1138 hr
= IStream_Read(pStream
, &hr_marshaled
, sizeof(HRESULT
), NULL
);
1139 ok_ole_success(hr
, IStream_Read
);
1141 ok(hr_marshaled
== E_DEADBEEF
, "Didn't marshal HRESULT as expected: got value 0x%08x instead\n", hr_marshaled
);
1144 IStream_Seek(pStream
, ullZero
, STREAM_SEEK_SET
, NULL
);
1145 hr
= CoUnmarshalHresult(pStream
, &hr_marshaled
);
1146 ok_ole_success(hr
, CoUnmarshalHresult
);
1148 ok(hr_marshaled
== E_DEADBEEF
, "Didn't marshal HRESULT as expected: got value 0x%08x instead\n", hr_marshaled
);
1150 IStream_Release(pStream
);
1154 /* helper for test_proxy_used_in_wrong_thread */
1155 static DWORD CALLBACK
bad_thread_proc(LPVOID p
)
1157 IClassFactory
* cf
= (IClassFactory
*)p
;
1159 IUnknown
* proxy
= NULL
;
1161 pCoInitializeEx(NULL
, COINIT_MULTITHREADED
);
1163 hr
= IClassFactory_CreateInstance(cf
, NULL
, &IID_IUnknown
, (LPVOID
*)&proxy
);
1164 if (proxy
) IUnknown_Release(proxy
);
1165 ok(hr
== RPC_E_WRONG_THREAD
,
1166 "COM should have failed with RPC_E_WRONG_THREAD on using proxy from wrong apartment, but instead returned 0x%08x\n",
1174 /* tests failure case of a using a proxy in the wrong apartment */
1175 static void test_proxy_used_in_wrong_thread(void)
1178 IStream
*pStream
= NULL
;
1179 IUnknown
*pProxy
= NULL
;
1186 hr
= CreateStreamOnHGlobal(NULL
, TRUE
, &pStream
);
1187 ok_ole_success(hr
, CreateStreamOnHGlobal
);
1188 tid
= start_host_object(pStream
, &IID_IClassFactory
, (IUnknown
*)&Test_ClassFactory
, MSHLFLAGS_NORMAL
, &host_thread
);
1190 ok_more_than_one_lock();
1192 IStream_Seek(pStream
, ullZero
, STREAM_SEEK_SET
, NULL
);
1193 hr
= CoUnmarshalInterface(pStream
, &IID_IClassFactory
, (void **)&pProxy
);
1194 ok_ole_success(hr
, CoUnmarshalInterface
);
1195 IStream_Release(pStream
);
1197 ok_more_than_one_lock();
1199 /* create a thread that we can misbehave in */
1200 thread
= CreateThread(NULL
, 0, bad_thread_proc
, (LPVOID
)pProxy
, 0, &tid2
);
1202 WaitForSingleObject(thread
, INFINITE
);
1203 CloseHandle(thread
);
1205 IUnknown_Release(pProxy
);
1209 end_host_object(tid
, host_thread
);
1212 static HRESULT WINAPI
MessageFilter_QueryInterface(IMessageFilter
*iface
, REFIID riid
, void ** ppvObj
)
1214 if (ppvObj
== NULL
) return E_POINTER
;
1216 if (IsEqualGUID(riid
, &IID_IUnknown
) ||
1217 IsEqualGUID(riid
, &IID_IClassFactory
))
1219 *ppvObj
= (LPVOID
)iface
;
1220 IClassFactory_AddRef(iface
);
1224 return E_NOINTERFACE
;
1227 static ULONG WINAPI
MessageFilter_AddRef(IMessageFilter
*iface
)
1229 return 2; /* non-heap object */
1232 static ULONG WINAPI
MessageFilter_Release(IMessageFilter
*iface
)
1234 return 1; /* non-heap object */
1237 static DWORD WINAPI
MessageFilter_HandleInComingCall(
1238 IMessageFilter
*iface
,
1240 HTASK threadIDCaller
,
1242 LPINTERFACEINFO lpInterfaceInfo
)
1244 static int callcount
= 0;
1246 trace("HandleInComingCall\n");
1250 ret
= SERVERCALL_REJECTED
;
1253 ret
= SERVERCALL_RETRYLATER
;
1256 ret
= SERVERCALL_ISHANDLED
;
1263 static DWORD WINAPI
MessageFilter_RetryRejectedCall(
1264 IMessageFilter
*iface
,
1265 HTASK threadIDCallee
,
1269 trace("RetryRejectedCall\n");
1273 static DWORD WINAPI
MessageFilter_MessagePending(
1274 IMessageFilter
*iface
,
1275 HTASK threadIDCallee
,
1277 DWORD dwPendingType
)
1279 trace("MessagePending\n");
1280 return PENDINGMSG_WAITNOPROCESS
;
1283 static const IMessageFilterVtbl MessageFilter_Vtbl
=
1285 MessageFilter_QueryInterface
,
1286 MessageFilter_AddRef
,
1287 MessageFilter_Release
,
1288 MessageFilter_HandleInComingCall
,
1289 MessageFilter_RetryRejectedCall
,
1290 MessageFilter_MessagePending
1293 static IMessageFilter MessageFilter
= { &MessageFilter_Vtbl
};
1295 static void test_message_filter(void)
1298 IStream
*pStream
= NULL
;
1299 IClassFactory
*cf
= NULL
;
1301 IUnknown
*proxy
= NULL
;
1302 IMessageFilter
*prev_filter
= NULL
;
1307 hr
= CreateStreamOnHGlobal(NULL
, TRUE
, &pStream
);
1308 ok_ole_success(hr
, CreateStreamOnHGlobal
);
1309 tid
= start_host_object2(pStream
, &IID_IClassFactory
, (IUnknown
*)&Test_ClassFactory
, MSHLFLAGS_NORMAL
, &MessageFilter
, &thread
);
1311 ok_more_than_one_lock();
1313 IStream_Seek(pStream
, ullZero
, STREAM_SEEK_SET
, NULL
);
1314 hr
= CoUnmarshalInterface(pStream
, &IID_IClassFactory
, (void **)&cf
);
1315 ok_ole_success(hr
, CoUnmarshalInterface
);
1316 IStream_Release(pStream
);
1318 ok_more_than_one_lock();
1320 hr
= IClassFactory_CreateInstance(cf
, NULL
, &IID_IUnknown
, (LPVOID
*)&proxy
);
1321 ok(hr
== RPC_E_CALL_REJECTED
, "Call should have returned RPC_E_CALL_REJECTED, but return 0x%08x instead\n", hr
);
1322 if (proxy
) IUnknown_Release(proxy
);
1325 hr
= CoRegisterMessageFilter(&MessageFilter
, &prev_filter
);
1326 ok_ole_success(hr
, CoRegisterMessageFilter
);
1328 hr
= IClassFactory_CreateInstance(cf
, NULL
, &IID_IUnknown
, (LPVOID
*)&proxy
);
1329 ok_ole_success(hr
, IClassFactory_CreateInstance
);
1331 IUnknown_Release(proxy
);
1333 IClassFactory_Release(cf
);
1337 end_host_object(tid
, thread
);
1339 hr
= CoRegisterMessageFilter(prev_filter
, NULL
);
1340 ok_ole_success(hr
, CoRegisterMessageFilter
);
1343 /* test failure case of trying to unmarshal from bad stream */
1344 static void test_bad_marshal_stream(void)
1347 IStream
*pStream
= NULL
;
1349 hr
= CreateStreamOnHGlobal(NULL
, TRUE
, &pStream
);
1350 ok_ole_success(hr
, CreateStreamOnHGlobal
);
1351 hr
= CoMarshalInterface(pStream
, &IID_IClassFactory
, (IUnknown
*)&Test_ClassFactory
, MSHCTX_INPROC
, NULL
, MSHLFLAGS_NORMAL
);
1352 ok_ole_success(hr
, CoMarshalInterface
);
1354 ok_more_than_one_lock();
1356 /* try to read beyond end of stream */
1357 hr
= CoReleaseMarshalData(pStream
);
1358 ok(hr
== STG_E_READFAULT
, "Should have failed with STG_E_READFAULT, but returned 0x%08x instead\n", hr
);
1360 /* now release for real */
1361 IStream_Seek(pStream
, ullZero
, STREAM_SEEK_SET
, NULL
);
1362 hr
= CoReleaseMarshalData(pStream
);
1363 ok_ole_success(hr
, CoReleaseMarshalData
);
1365 IStream_Release(pStream
);
1368 /* tests that proxies implement certain interfaces */
1369 static void test_proxy_interfaces(void)
1372 IStream
*pStream
= NULL
;
1373 IUnknown
*pProxy
= NULL
;
1374 IUnknown
*pOtherUnknown
= NULL
;
1380 hr
= CreateStreamOnHGlobal(NULL
, TRUE
, &pStream
);
1381 ok_ole_success(hr
, CreateStreamOnHGlobal
);
1382 tid
= start_host_object(pStream
, &IID_IClassFactory
, (IUnknown
*)&Test_ClassFactory
, MSHLFLAGS_NORMAL
, &thread
);
1384 ok_more_than_one_lock();
1386 IStream_Seek(pStream
, ullZero
, STREAM_SEEK_SET
, NULL
);
1387 hr
= CoUnmarshalInterface(pStream
, &IID_IUnknown
, (void **)&pProxy
);
1388 ok_ole_success(hr
, CoUnmarshalInterface
);
1389 IStream_Release(pStream
);
1391 ok_more_than_one_lock();
1393 hr
= IUnknown_QueryInterface(pProxy
, &IID_IUnknown
, (LPVOID
*)&pOtherUnknown
);
1394 ok_ole_success(hr
, IUnknown_QueryInterface IID_IUnknown
);
1395 if (hr
== S_OK
) IUnknown_Release(pOtherUnknown
);
1397 hr
= IUnknown_QueryInterface(pProxy
, &IID_IClientSecurity
, (LPVOID
*)&pOtherUnknown
);
1398 todo_wine
{ ok_ole_success(hr
, IUnknown_QueryInterface IID_IClientSecurity
); }
1399 if (hr
== S_OK
) IUnknown_Release(pOtherUnknown
);
1401 hr
= IUnknown_QueryInterface(pProxy
, &IID_IMultiQI
, (LPVOID
*)&pOtherUnknown
);
1402 ok_ole_success(hr
, IUnknown_QueryInterface IID_IMultiQI
);
1403 if (hr
== S_OK
) IUnknown_Release(pOtherUnknown
);
1405 hr
= IUnknown_QueryInterface(pProxy
, &IID_IMarshal
, (LPVOID
*)&pOtherUnknown
);
1406 ok_ole_success(hr
, IUnknown_QueryInterface IID_IMarshal
);
1407 if (hr
== S_OK
) IUnknown_Release(pOtherUnknown
);
1409 /* IMarshal2 is also supported on NT-based systems, but is pretty much
1410 * useless as it has no more methods over IMarshal that it inherits from. */
1412 IUnknown_Release(pProxy
);
1416 end_host_object(tid
, thread
);
1421 const IUnknownVtbl
*lpVtbl
;
1425 static HRESULT WINAPI
HeapUnknown_QueryInterface(IUnknown
*iface
, REFIID riid
, void **ppv
)
1427 if (IsEqualIID(riid
, &IID_IUnknown
))
1429 IUnknown_AddRef(iface
);
1430 *ppv
= (LPVOID
)iface
;
1434 return E_NOINTERFACE
;
1437 static ULONG WINAPI
HeapUnknown_AddRef(IUnknown
*iface
)
1439 HeapUnknown
*This
= (HeapUnknown
*)iface
;
1440 trace("HeapUnknown_AddRef(%p)\n", iface
);
1441 return InterlockedIncrement((LONG
*)&This
->refs
);
1444 static ULONG WINAPI
HeapUnknown_Release(IUnknown
*iface
)
1446 HeapUnknown
*This
= (HeapUnknown
*)iface
;
1447 ULONG refs
= InterlockedDecrement((LONG
*)&This
->refs
);
1448 trace("HeapUnknown_Release(%p)\n", iface
);
1449 if (!refs
) HeapFree(GetProcessHeap(), 0, This
);
1453 static const IUnknownVtbl HeapUnknown_Vtbl
=
1455 HeapUnknown_QueryInterface
,
1460 static void test_proxybuffer(REFIID riid
)
1463 IPSFactoryBuffer
*psfb
;
1464 IRpcProxyBuffer
*proxy
;
1468 HeapUnknown
*pUnkOuter
= (HeapUnknown
*)HeapAlloc(GetProcessHeap(), 0, sizeof(*pUnkOuter
));
1470 pUnkOuter
->lpVtbl
= &HeapUnknown_Vtbl
;
1471 pUnkOuter
->refs
= 1;
1473 hr
= CoGetPSClsid(riid
, &clsid
);
1474 ok_ole_success(hr
, CoGetPSClsid
);
1476 hr
= CoGetClassObject(&clsid
, CLSCTX_INPROC_SERVER
, NULL
, &IID_IPSFactoryBuffer
, (LPVOID
*)&psfb
);
1477 ok_ole_success(hr
, CoGetClassObject
);
1479 hr
= IPSFactoryBuffer_CreateProxy(psfb
, (IUnknown
*)pUnkOuter
, riid
, &proxy
, &lpvtbl
);
1480 ok_ole_success(hr
, IPSFactoryBuffer_CreateProxy
);
1481 ok(lpvtbl
!= NULL
, "IPSFactoryBuffer_CreateProxy succeeded, but returned a NULL vtable!\n");
1483 /* release our reference to the outer unknown object - the PS factory
1484 * buffer will have AddRef's it in the CreateProxy call */
1485 refs
= IUnknown_Release((IUnknown
*)pUnkOuter
);
1486 ok(refs
== 1, "Ref count of outer unknown should have been 1 instead of %d\n", refs
);
1488 refs
= IPSFactoryBuffer_Release(psfb
);
1491 /* not reliable on native. maybe it leaks references! */
1492 ok(refs
== 0, "Ref-count leak of %d on IPSFactoryBuffer\n", refs
);
1495 refs
= IUnknown_Release((IUnknown
*)lpvtbl
);
1496 ok(refs
== 0, "Ref-count leak of %d on IRpcProxyBuffer\n", refs
);
1498 refs
= IRpcProxyBuffer_Release(proxy
);
1499 ok(refs
== 0, "Ref-count leak of %d on IRpcProxyBuffer\n", refs
);
1502 static void test_stubbuffer(REFIID riid
)
1505 IPSFactoryBuffer
*psfb
;
1506 IRpcStubBuffer
*stub
;
1512 hr
= CoGetPSClsid(riid
, &clsid
);
1513 ok_ole_success(hr
, CoGetPSClsid
);
1515 hr
= CoGetClassObject(&clsid
, CLSCTX_INPROC_SERVER
, NULL
, &IID_IPSFactoryBuffer
, (LPVOID
*)&psfb
);
1516 ok_ole_success(hr
, CoGetClassObject
);
1518 hr
= IPSFactoryBuffer_CreateStub(psfb
, riid
, (IUnknown
*)&Test_ClassFactory
, &stub
);
1519 ok_ole_success(hr
, IPSFactoryBuffer_CreateStub
);
1521 refs
= IPSFactoryBuffer_Release(psfb
);
1524 /* not reliable on native. maybe it leaks references */
1525 ok(refs
== 0, "Ref-count leak of %d on IPSFactoryBuffer\n", refs
);
1528 ok_more_than_one_lock();
1530 IRpcStubBuffer_Disconnect(stub
);
1534 refs
= IRpcStubBuffer_Release(stub
);
1535 ok(refs
== 0, "Ref-count leak of %d on IRpcProxyBuffer\n", refs
);
1538 static HWND hwnd_app
;
1540 static HRESULT WINAPI
TestRE_IClassFactory_CreateInstance(
1541 LPCLASSFACTORY iface
,
1542 LPUNKNOWN pUnkOuter
,
1547 if (IsEqualIID(riid
, &IID_IWineTest
))
1549 BOOL ret
= SendMessageTimeout(hwnd_app
, WM_NULL
, 0, 0, SMTO_BLOCK
, 5000, &res
);
1550 ok(ret
, "Timed out sending a message to originating window during RPC call\n");
1555 static const IClassFactoryVtbl TestREClassFactory_Vtbl
=
1557 Test_IClassFactory_QueryInterface
,
1558 Test_IClassFactory_AddRef
,
1559 Test_IClassFactory_Release
,
1560 TestRE_IClassFactory_CreateInstance
,
1561 Test_IClassFactory_LockServer
1564 IClassFactory TestRE_ClassFactory
= { &TestREClassFactory_Vtbl
};
1566 static LRESULT CALLBACK
window_proc(HWND hwnd
, UINT msg
, WPARAM wparam
, LPARAM lparam
)
1573 IStream
*pStream
= NULL
;
1574 IClassFactory
*proxy
= NULL
;
1581 hr
= CreateStreamOnHGlobal(NULL
, TRUE
, &pStream
);
1582 ok_ole_success(hr
, CreateStreamOnHGlobal
);
1583 tid
= start_host_object(pStream
, &IID_IClassFactory
, (IUnknown
*)&TestRE_ClassFactory
, MSHLFLAGS_NORMAL
, &thread
);
1585 ok_more_than_one_lock();
1587 IStream_Seek(pStream
, ullZero
, STREAM_SEEK_SET
, NULL
);
1588 hr
= CoUnmarshalInterface(pStream
, &IID_IClassFactory
, (void **)&proxy
);
1589 ok_ole_success(hr
, CoReleaseMarshalData
);
1590 IStream_Release(pStream
);
1592 ok_more_than_one_lock();
1594 /* note the use of the magic IID_IWineTest value to tell remote thread
1595 * to try to send a message back to us */
1596 hr
= IClassFactory_CreateInstance(proxy
, NULL
, &IID_IWineTest
, (void **)&object
);
1598 IClassFactory_Release(proxy
);
1602 end_host_object(tid
, thread
);
1604 PostMessage(hwnd
, WM_QUIT
, 0, 0);
1611 IStream
*pStream
= NULL
;
1612 IClassFactory
*proxy
= NULL
;
1619 hr
= CreateStreamOnHGlobal(NULL
, TRUE
, &pStream
);
1620 ok_ole_success(hr
, CreateStreamOnHGlobal
);
1621 tid
= start_host_object(pStream
, &IID_IClassFactory
, (IUnknown
*)&TestRE_ClassFactory
, MSHLFLAGS_NORMAL
, &thread
);
1623 ok_more_than_one_lock();
1625 IStream_Seek(pStream
, ullZero
, STREAM_SEEK_SET
, NULL
);
1626 hr
= CoUnmarshalInterface(pStream
, &IID_IClassFactory
, (void **)&proxy
);
1627 ok_ole_success(hr
, CoReleaseMarshalData
);
1628 IStream_Release(pStream
);
1630 ok_more_than_one_lock();
1632 /* post quit message before a doing a COM call to show that a pending
1633 * WM_QUIT message doesn't stop the call from succeeding */
1634 PostMessage(hwnd
, WM_QUIT
, 0, 0);
1635 hr
= IClassFactory_CreateInstance(proxy
, NULL
, &IID_IUnknown
, (void **)&object
);
1637 IClassFactory_Release(proxy
);
1641 end_host_object(tid
, thread
);
1648 IStream
*pStream
= NULL
;
1649 IClassFactory
*proxy
= NULL
;
1654 hr
= CreateStreamOnHGlobal(NULL
, TRUE
, &pStream
);
1655 ok_ole_success(hr
, CreateStreamOnHGlobal
);
1656 tid
= start_host_object(pStream
, &IID_IClassFactory
, (IUnknown
*)&Test_ClassFactory
, MSHLFLAGS_NORMAL
, &thread
);
1658 IStream_Seek(pStream
, ullZero
, STREAM_SEEK_SET
, NULL
);
1659 hr
= CoUnmarshalInterface(pStream
, &IID_IClassFactory
, (void **)&proxy
);
1660 ok_ole_success(hr
, CoReleaseMarshalData
);
1661 IStream_Release(pStream
);
1663 /* shows that COM calls executed during the processing of sent
1664 * messages should fail */
1665 hr
= IClassFactory_CreateInstance(proxy
, NULL
, &IID_IUnknown
, (void **)&object
);
1666 ok(hr
== RPC_E_CANTCALLOUT_ININPUTSYNCCALL
,
1667 "COM call during processing of sent message should return RPC_E_CANTCALLOUT_ININPUTSYNCCALL instead of 0x%08x\n", hr
);
1669 IClassFactory_Release(proxy
);
1671 end_host_object(tid
, thread
);
1678 return DefWindowProc(hwnd
, msg
, wparam
, lparam
);
1682 static void test_message_reentrancy(void)
1687 memset(&wndclass
, 0, sizeof(wndclass
));
1688 wndclass
.lpfnWndProc
= window_proc
;
1689 wndclass
.lpszClassName
= "WineCOMTest";
1690 RegisterClass(&wndclass
);
1692 hwnd_app
= CreateWindow("WineCOMTest", NULL
, 0, CW_USEDEFAULT
, CW_USEDEFAULT
, CW_USEDEFAULT
, CW_USEDEFAULT
, NULL
, NULL
, NULL
, 0);
1693 ok(hwnd_app
!= NULL
, "Window creation failed\n");
1695 /* start message re-entrancy test */
1696 PostMessage(hwnd_app
, WM_USER
, 0, 0);
1698 while (GetMessage(&msg
, NULL
, 0, 0))
1700 TranslateMessage(&msg
);
1701 DispatchMessage(&msg
);
1705 static HRESULT WINAPI
TestMsg_IClassFactory_CreateInstance(
1706 LPCLASSFACTORY iface
,
1707 LPUNKNOWN pUnkOuter
,
1712 SendMessage(hwnd_app
, WM_USER
+2, 0, 0);
1716 static IClassFactoryVtbl TestMsgClassFactory_Vtbl
=
1718 Test_IClassFactory_QueryInterface
,
1719 Test_IClassFactory_AddRef
,
1720 Test_IClassFactory_Release
,
1721 TestMsg_IClassFactory_CreateInstance
,
1722 Test_IClassFactory_LockServer
1725 IClassFactory TestMsg_ClassFactory
= { &TestMsgClassFactory_Vtbl
};
1727 static void test_call_from_message(void)
1732 IClassFactory
*proxy
;
1737 hwnd_app
= CreateWindow("WineCOMTest", NULL
, 0, CW_USEDEFAULT
, CW_USEDEFAULT
, CW_USEDEFAULT
, CW_USEDEFAULT
, NULL
, NULL
, NULL
, 0);
1738 ok(hwnd_app
!= NULL
, "Window creation failed\n");
1740 hr
= CreateStreamOnHGlobal(NULL
, TRUE
, &pStream
);
1741 ok_ole_success(hr
, CreateStreamOnHGlobal
);
1742 tid
= start_host_object(pStream
, &IID_IClassFactory
, (IUnknown
*)&TestMsg_ClassFactory
, MSHLFLAGS_NORMAL
, &thread
);
1744 ok_more_than_one_lock();
1746 IStream_Seek(pStream
, ullZero
, STREAM_SEEK_SET
, NULL
);
1747 hr
= CoUnmarshalInterface(pStream
, &IID_IClassFactory
, (void **)&proxy
);
1748 ok_ole_success(hr
, CoReleaseMarshalData
);
1749 IStream_Release(pStream
);
1751 ok_more_than_one_lock();
1753 /* start message re-entrancy test */
1754 hr
= IClassFactory_CreateInstance(proxy
, NULL
, &IID_IUnknown
, (void **)&object
);
1755 ok_ole_success(hr
, IClassFactory_CreateInstance
);
1757 IClassFactory_Release(proxy
);
1761 end_host_object(tid
, thread
);
1763 while (GetMessage(&msg
, NULL
, 0, 0))
1765 TranslateMessage(&msg
);
1766 DispatchMessage(&msg
);
1770 static void test_WM_QUIT_handling(void)
1774 hwnd_app
= CreateWindow("WineCOMTest", NULL
, 0, CW_USEDEFAULT
, CW_USEDEFAULT
, CW_USEDEFAULT
, CW_USEDEFAULT
, NULL
, NULL
, NULL
, 0);
1775 ok(hwnd_app
!= NULL
, "Window creation failed\n");
1777 /* start WM_QUIT handling test */
1778 PostMessage(hwnd_app
, WM_USER
+1, 0, 0);
1780 while (GetMessage(&msg
, NULL
, 0, 0))
1782 TranslateMessage(&msg
);
1783 DispatchMessage(&msg
);
1787 static void test_freethreadedmarshaldata(IStream
*pStream
, MSHCTX mshctx
, void *ptr
, DWORD mshlflags
)
1794 hr
= GetHGlobalFromStream(pStream
, &hglobal
);
1795 ok_ole_success(hr
, GetHGlobalFromStream
);
1797 size
= GlobalSize(hglobal
);
1799 marshal_data
= (char *)GlobalLock(hglobal
);
1801 if (mshctx
== MSHCTX_INPROC
)
1803 DWORD expected_size
= sizeof(DWORD
) + sizeof(void *) + sizeof(DWORD
) + sizeof(GUID
);
1804 ok(size
== expected_size
, "size should have been %d instead of %d\n", expected_size
, size
);
1806 ok(*(DWORD
*)marshal_data
== mshlflags
, "expected 0x%x, but got 0x%x for mshctx\n", mshlflags
, *(DWORD
*)marshal_data
);
1807 marshal_data
+= sizeof(DWORD
);
1808 ok(*(void **)marshal_data
== ptr
, "expected %p, but got %p for mshctx\n", ptr
, *(void **)marshal_data
);
1809 marshal_data
+= sizeof(void *);
1810 ok(*(DWORD
*)marshal_data
== 0, "expected 0x0, but got 0x%x\n", *(DWORD
*)marshal_data
);
1811 marshal_data
+= sizeof(DWORD
);
1812 trace("got guid data: {%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x}\n",
1813 ((GUID
*)marshal_data
)->Data1
, ((GUID
*)marshal_data
)->Data2
, ((GUID
*)marshal_data
)->Data3
,
1814 ((GUID
*)marshal_data
)->Data4
[0], ((GUID
*)marshal_data
)->Data4
[1], ((GUID
*)marshal_data
)->Data4
[2], ((GUID
*)marshal_data
)->Data4
[3],
1815 ((GUID
*)marshal_data
)->Data4
[4], ((GUID
*)marshal_data
)->Data4
[5], ((GUID
*)marshal_data
)->Data4
[6], ((GUID
*)marshal_data
)->Data4
[7]);
1819 ok(size
> sizeof(DWORD
), "size should have been > sizeof(DWORD), not %d\n", size
);
1820 ok(*(DWORD
*)marshal_data
== 0x574f454d /* MEOW */,
1821 "marshal data should be filled by standard marshal and start with MEOW signature\n");
1824 GlobalUnlock(hglobal
);
1827 static void test_freethreadedmarshaler(void)
1830 IUnknown
*pFTUnknown
;
1831 IMarshal
*pFTMarshal
;
1834 static const LARGE_INTEGER llZero
;
1837 hr
= CoCreateFreeThreadedMarshaler(NULL
, &pFTUnknown
);
1838 ok_ole_success(hr
, CoCreateFreeThreadedMarshaler
);
1839 hr
= IUnknown_QueryInterface(pFTUnknown
, &IID_IMarshal
, (void **)&pFTMarshal
);
1840 ok_ole_success(hr
, IUnknown_QueryInterface
);
1841 IUnknown_Release(pFTUnknown
);
1843 hr
= CreateStreamOnHGlobal(NULL
, TRUE
, &pStream
);
1844 ok_ole_success(hr
, CreateStreamOnHGlobal
);
1846 /* inproc normal marshaling */
1848 hr
= IMarshal_MarshalInterface(pFTMarshal
, pStream
, &IID_IClassFactory
,
1849 (IUnknown
*)&Test_ClassFactory
, MSHCTX_INPROC
, NULL
, MSHLFLAGS_NORMAL
);
1850 ok_ole_success(hr
, IMarshal_MarshalInterface
);
1852 ok_more_than_one_lock();
1854 test_freethreadedmarshaldata(pStream
, MSHCTX_INPROC
, &Test_ClassFactory
, MSHLFLAGS_NORMAL
);
1856 IStream_Seek(pStream
, llZero
, STREAM_SEEK_SET
, NULL
);
1857 hr
= IMarshal_UnmarshalInterface(pFTMarshal
, pStream
, &IID_IUnknown
, (void **)&pProxy
);
1858 ok_ole_success(hr
, IMarshal_UnmarshalInterface
);
1860 IUnknown_Release(pProxy
);
1864 /* native doesn't allow us to unmarshal or release the stream data,
1865 * presumably because it wants us to call CoMarshalInterface instead */
1868 /* local normal marshaling */
1870 IStream_Seek(pStream
, llZero
, STREAM_SEEK_SET
, NULL
);
1871 hr
= IMarshal_MarshalInterface(pFTMarshal
, pStream
, &IID_IClassFactory
, (IUnknown
*)&Test_ClassFactory
, MSHCTX_LOCAL
, NULL
, MSHLFLAGS_NORMAL
);
1872 ok_ole_success(hr
, IMarshal_MarshalInterface
);
1874 ok_more_than_one_lock();
1876 test_freethreadedmarshaldata(pStream
, MSHCTX_LOCAL
, &Test_ClassFactory
, MSHLFLAGS_NORMAL
);
1878 IStream_Seek(pStream
, llZero
, STREAM_SEEK_SET
, NULL
);
1879 hr
= IMarshal_ReleaseMarshalData(pFTMarshal
, pStream
);
1880 ok_ole_success(hr
, IMarshal_ReleaseMarshalData
);
1885 /* inproc table-strong marshaling */
1887 IStream_Seek(pStream
, llZero
, STREAM_SEEK_SET
, NULL
);
1888 hr
= IMarshal_MarshalInterface(pFTMarshal
, pStream
, &IID_IClassFactory
,
1889 (IUnknown
*)&Test_ClassFactory
, MSHCTX_INPROC
, (void *)0xdeadbeef,
1890 MSHLFLAGS_TABLESTRONG
);
1891 ok_ole_success(hr
, IMarshal_MarshalInterface
);
1893 ok_more_than_one_lock();
1895 test_freethreadedmarshaldata(pStream
, MSHCTX_INPROC
, &Test_ClassFactory
, MSHLFLAGS_TABLESTRONG
);
1897 IStream_Seek(pStream
, llZero
, STREAM_SEEK_SET
, NULL
);
1898 hr
= IMarshal_UnmarshalInterface(pFTMarshal
, pStream
, &IID_IUnknown
, (void **)&pProxy
);
1899 ok_ole_success(hr
, IMarshal_UnmarshalInterface
);
1901 IUnknown_Release(pProxy
);
1903 ok_more_than_one_lock();
1905 IStream_Seek(pStream
, llZero
, STREAM_SEEK_SET
, NULL
);
1906 hr
= IMarshal_ReleaseMarshalData(pFTMarshal
, pStream
);
1907 ok_ole_success(hr
, IMarshal_ReleaseMarshalData
);
1911 /* inproc table-weak marshaling */
1913 IStream_Seek(pStream
, llZero
, STREAM_SEEK_SET
, NULL
);
1914 hr
= IMarshal_MarshalInterface(pFTMarshal
, pStream
, &IID_IClassFactory
,
1915 (IUnknown
*)&Test_ClassFactory
, MSHCTX_INPROC
, (void *)0xdeadbeef,
1916 MSHLFLAGS_TABLEWEAK
);
1917 ok_ole_success(hr
, IMarshal_MarshalInterface
);
1921 test_freethreadedmarshaldata(pStream
, MSHCTX_INPROC
, &Test_ClassFactory
, MSHLFLAGS_TABLEWEAK
);
1923 IStream_Seek(pStream
, llZero
, STREAM_SEEK_SET
, NULL
);
1924 hr
= IMarshal_UnmarshalInterface(pFTMarshal
, pStream
, &IID_IUnknown
, (void **)&pProxy
);
1925 ok_ole_success(hr
, IMarshal_UnmarshalInterface
);
1927 ok_more_than_one_lock();
1929 IUnknown_Release(pProxy
);
1933 /* inproc normal marshaling (for extraordinary cases) */
1935 IStream_Seek(pStream
, llZero
, STREAM_SEEK_SET
, NULL
);
1936 hr
= IMarshal_MarshalInterface(pFTMarshal
, pStream
, &IID_IClassFactory
,
1937 (IUnknown
*)&Test_ClassFactory
, MSHCTX_INPROC
, NULL
, MSHLFLAGS_NORMAL
);
1938 ok_ole_success(hr
, IMarshal_MarshalInterface
);
1940 ok_more_than_one_lock();
1942 /* this call shows that DisconnectObject does nothing */
1943 hr
= IMarshal_DisconnectObject(pFTMarshal
, 0);
1944 ok_ole_success(hr
, IMarshal_DisconnectObject
);
1946 ok_more_than_one_lock();
1948 IStream_Seek(pStream
, llZero
, STREAM_SEEK_SET
, NULL
);
1949 hr
= IMarshal_ReleaseMarshalData(pFTMarshal
, pStream
);
1950 ok_ole_success(hr
, IMarshal_ReleaseMarshalData
);
1954 /* doesn't enforce marshaling rules here and allows us to unmarshal the
1955 * interface, even though it was freed above */
1956 IStream_Seek(pStream
, llZero
, STREAM_SEEK_SET
, NULL
);
1957 hr
= IMarshal_UnmarshalInterface(pFTMarshal
, pStream
, &IID_IUnknown
, (void **)&pProxy
);
1958 ok_ole_success(hr
, IMarshal_UnmarshalInterface
);
1962 IStream_Release(pStream
);
1963 IMarshal_Release(pFTMarshal
);
1966 static HANDLE heventShutdown
;
1968 static void LockModuleOOP(void)
1970 InterlockedIncrement(&cLocks
); /* for test purposes only */
1971 CoAddRefServerProcess();
1974 static void UnlockModuleOOP(void)
1976 InterlockedDecrement(&cLocks
); /* for test purposes only */
1977 if (!CoReleaseServerProcess())
1978 SetEvent(heventShutdown
);
1981 static HWND hwnd_app
;
1983 static HRESULT WINAPI
TestOOP_IClassFactory_QueryInterface(
1984 LPCLASSFACTORY iface
,
1988 if (ppvObj
== NULL
) return E_POINTER
;
1990 if (IsEqualGUID(riid
, &IID_IUnknown
) ||
1991 IsEqualGUID(riid
, &IID_IClassFactory
))
1993 *ppvObj
= (LPVOID
)iface
;
1994 IClassFactory_AddRef(iface
);
1998 return E_NOINTERFACE
;
2001 static ULONG WINAPI
TestOOP_IClassFactory_AddRef(LPCLASSFACTORY iface
)
2003 return 2; /* non-heap-based object */
2006 static ULONG WINAPI
TestOOP_IClassFactory_Release(LPCLASSFACTORY iface
)
2008 return 1; /* non-heap-based object */
2011 static HRESULT WINAPI
TestOOP_IClassFactory_CreateInstance(
2012 LPCLASSFACTORY iface
,
2013 LPUNKNOWN pUnkOuter
,
2017 return CLASS_E_CLASSNOTAVAILABLE
;
2020 static HRESULT WINAPI
TestOOP_IClassFactory_LockServer(
2021 LPCLASSFACTORY iface
,
2031 static const IClassFactoryVtbl TestClassFactoryOOP_Vtbl
=
2033 TestOOP_IClassFactory_QueryInterface
,
2034 TestOOP_IClassFactory_AddRef
,
2035 TestOOP_IClassFactory_Release
,
2036 TestOOP_IClassFactory_CreateInstance
,
2037 TestOOP_IClassFactory_LockServer
2040 static IClassFactory TestOOP_ClassFactory
= { &TestClassFactoryOOP_Vtbl
};
2042 /* tests functions commonly used by out of process COM servers */
2043 static void test_out_of_process_com(void)
2045 static const CLSID CLSID_WineOOPTest
= {
2049 {0xa1, 0xa2, 0x5d, 0x5a, 0x36, 0x54, 0xd3, 0xbd}
2050 }; /* 5201163f-8164-4fd0-a1a2-5d5a3654d3bd */
2056 heventShutdown
= CreateEvent(NULL
, TRUE
, FALSE
, NULL
);
2060 /* Start the object suspended */
2061 hr
= CoRegisterClassObject(&CLSID_WineOOPTest
, (IUnknown
*)&TestOOP_ClassFactory
,
2062 CLSCTX_LOCAL_SERVER
, REGCLS_MULTIPLEUSE
| REGCLS_SUSPENDED
, &cookie
);
2063 ok_ole_success(hr
, CoRegisterClassObject
);
2065 /* ... and CoGetClassObject does not find it and fails when it looks for the
2066 * class in the registry */
2067 hr
= CoGetClassObject(&CLSID_WineOOPTest
, CLSCTX_INPROC_SERVER
,
2068 NULL
, &IID_IClassFactory
, (LPVOID
*)&cf
);
2070 ok(hr
== REGDB_E_CLASSNOTREG
,
2071 "CoGetClassObject should have returned REGDB_E_CLASSNOTREG instead of 0x%08x\n", hr
);
2074 /* Resume the object suspended above ... */
2075 hr
= CoResumeClassObjects();
2076 ok_ole_success(hr
, CoResumeClassObjects
);
2078 /* ... and now it should succeed */
2079 hr
= CoGetClassObject(&CLSID_WineOOPTest
, CLSCTX_INPROC_SERVER
,
2080 NULL
, &IID_IClassFactory
, (LPVOID
*)&cf
);
2081 ok_ole_success(hr
, CoGetClassObject
);
2083 /* Now check the locking is working */
2084 /* NOTE: we are accessing the class directly, not through a proxy */
2088 hr
= IClassFactory_LockServer(cf
, TRUE
);
2089 trace("IClassFactory_LockServer returned 0x%08x\n", hr
);
2091 ok_more_than_one_lock();
2093 IClassFactory_LockServer(cf
, FALSE
);
2097 IClassFactory_Release(cf
);
2099 /* wait for shutdown signal */
2100 ret
= WaitForSingleObject(heventShutdown
, 5000);
2101 todo_wine
{ ok(ret
!= WAIT_TIMEOUT
, "Server didn't shut down or machine is under very heavy load\n"); }
2103 /* try to connect again after SCM has suspended registered class objects */
2104 hr
= CoGetClassObject(&CLSID_WineOOPTest
, CLSCTX_INPROC_SERVER
| CLSCTX_LOCAL_SERVER
, NULL
,
2105 &IID_IClassFactory
, (LPVOID
*)&cf
);
2107 ok(hr
== CO_E_SERVER_STOPPING
,
2108 "CoGetClassObject should have returned CO_E_SERVER_STOPPING instead of 0x%08x\n", hr
);
2111 hr
= CoRevokeClassObject(cookie
);
2112 ok_ole_success(hr
, CoRevokeClassObject
);
2114 CloseHandle(heventShutdown
);
2120 IGlobalInterfaceTable
*git
;
2123 static DWORD CALLBACK
get_global_interface_proc(LPVOID pv
)
2126 struct git_params
*params
= (struct git_params
*)pv
;
2129 hr
= IGlobalInterfaceTable_GetInterfaceFromGlobal(params
->git
, params
->cookie
, &IID_IClassFactory
, (void **)&cf
);
2130 ok(hr
== CO_E_NOTINITIALIZED
,
2131 "IGlobalInterfaceTable_GetInterfaceFromGlobal should have failed with error CO_E_NOTINITIALIZED instead of 0x%08x\n",
2135 hr
= IGlobalInterfaceTable_GetInterfaceFromGlobal(params
->git
, params
->cookie
, &IID_IClassFactory
, (void **)&cf
);
2136 ok_ole_success(hr
, IGlobalInterfaceTable_GetInterfaceFromGlobal
);
2138 IGlobalInterfaceTable_Release(params
->git
);
2145 static void test_globalinterfacetable(void)
2148 IGlobalInterfaceTable
*git
;
2152 struct git_params params
;
2155 hr
= CoCreateInstance(&CLSID_StdGlobalInterfaceTable
, NULL
, CLSCTX_INPROC_SERVER
, &IID_IGlobalInterfaceTable
, (void **)&git
);
2156 ok_ole_success(hr
, CoCreateInstance
);
2158 hr
= IGlobalInterfaceTable_RegisterInterfaceInGlobal(git
, (IUnknown
*)&Test_ClassFactory
, &IID_IClassFactory
, &cookie
);
2159 ok_ole_success(hr
, IGlobalInterfaceTable_RegisterInterfaceInGlobal
);
2161 params
.cookie
= cookie
;
2163 /* note: params is on stack so we MUST wait for get_global_interface_proc
2164 * to exit before we can return */
2165 thread
= CreateThread(NULL
, 0, get_global_interface_proc
, ¶ms
, 0, &tid
);
2167 ret
= MsgWaitForMultipleObjects(1, &thread
, FALSE
, INFINITE
, QS_ALLINPUT
);
2168 while (ret
== WAIT_OBJECT_0
+ 1)
2171 while (PeekMessage(&msg
, NULL
, 0, 0, PM_REMOVE
))
2172 DispatchMessage(&msg
);
2173 ret
= MsgWaitForMultipleObjects(1, &thread
, FALSE
, INFINITE
, QS_ALLINPUT
);
2176 CloseHandle(thread
);
2179 static const char *debugstr_iid(REFIID riid
)
2181 static char name
[256];
2185 LONG name_size
= sizeof(name
);
2186 StringFromGUID2(riid
, bufferW
, sizeof(bufferW
)/sizeof(bufferW
[0]));
2187 WideCharToMultiByte(CP_ACP
, 0, bufferW
, sizeof(bufferW
)/sizeof(bufferW
[0]), buffer
, sizeof(buffer
), NULL
, NULL
);
2188 if (RegOpenKeyEx(HKEY_CLASSES_ROOT
, "Interface", 0, KEY_QUERY_VALUE
, &hkeyInterface
) != ERROR_SUCCESS
)
2190 memcpy(name
, buffer
, sizeof(buffer
));
2193 if (RegQueryValue(hkeyInterface
, buffer
, name
, &name_size
) != ERROR_SUCCESS
)
2195 memcpy(name
, buffer
, sizeof(buffer
));
2198 RegCloseKey(hkeyInterface
);
2203 static HRESULT WINAPI
TestChannelHook_QueryInterface(IChannelHook
*iface
, REFIID riid
, void **ppv
)
2205 if (IsEqualIID(riid
, &IID_IUnknown
) || IsEqualIID(riid
, &IID_IChannelHook
))
2208 IUnknown_AddRef(iface
);
2213 return E_NOINTERFACE
;
2216 static ULONG WINAPI
TestChannelHook_AddRef(IChannelHook
*iface
)
2221 static ULONG WINAPI
TestChannelHook_Release(IChannelHook
*iface
)
2226 static void WINAPI
TestChannelHook_ClientGetSize(
2227 IChannelHook
*iface
,
2232 SChannelHookCallInfo
*info
= (SChannelHookCallInfo
*)riid
;
2233 trace("TestChannelHook_ClientGetBuffer\n");
2234 trace("\t%s method %d\n", debugstr_iid(riid
), info
->iMethod
);
2235 trace("\tcid: %s\n", debugstr_iid(&info
->uCausality
));
2236 ok(info
->cbSize
== sizeof(*info
), "info->cbSize was %d instead of %d\n", info
->cbSize
, (int)sizeof(*info
));
2238 ok(info
->dwServerPid
== GetCurrentProcessId(), "info->dwServerPid was 0x%x instead of 0x%x\n", info
->dwServerPid
, GetCurrentProcessId());
2240 ok(!info
->pObject
, "info->pObject should be NULL\n");
2241 ok(IsEqualGUID(uExtent
, &EXTENTID_WineTest
), "uExtent wasn't correct\n");
2246 static void WINAPI
TestChannelHook_ClientFillBuffer(
2247 IChannelHook
*iface
,
2253 SChannelHookCallInfo
*info
= (SChannelHookCallInfo
*)riid
;
2254 trace("TestChannelHook_ClientFillBuffer\n");
2255 ok(info
->cbSize
== sizeof(*info
), "info->cbSize was %d instead of %d\n", info
->cbSize
, (int)sizeof(*info
));
2257 ok(info
->dwServerPid
== GetCurrentProcessId(), "info->dwServerPid was 0x%x instead of 0x%x\n", info
->dwServerPid
, GetCurrentProcessId());
2259 ok(!info
->pObject
, "info->pObject should be NULL\n");
2260 ok(IsEqualGUID(uExtent
, &EXTENTID_WineTest
), "uExtent wasn't correct\n");
2262 *(unsigned char *)pDataBuffer
= 0xcc;
2266 static void WINAPI
TestChannelHook_ClientNotify(
2267 IChannelHook
*iface
,
2275 SChannelHookCallInfo
*info
= (SChannelHookCallInfo
*)riid
;
2276 trace("TestChannelHook_ClientNotify hrFault = 0x%08x\n", hrFault
);
2277 ok(info
->cbSize
== sizeof(*info
), "info->cbSize was %d instead of %d\n", info
->cbSize
, (int)sizeof(*info
));
2279 ok(info
->dwServerPid
== GetCurrentProcessId(), "info->dwServerPid was 0x%x instead of 0x%x\n", info
->dwServerPid
, GetCurrentProcessId());
2280 ok(info
->pObject
!= NULL
, "info->pObject shouldn't be NULL\n");
2282 ok(IsEqualGUID(uExtent
, &EXTENTID_WineTest
), "uExtent wasn't correct\n");
2285 static void WINAPI
TestChannelHook_ServerNotify(
2286 IChannelHook
*iface
,
2293 SChannelHookCallInfo
*info
= (SChannelHookCallInfo
*)riid
;
2294 trace("TestChannelHook_ServerNotify\n");
2295 ok(info
->cbSize
== sizeof(*info
), "info->cbSize was %d instead of %d\n", info
->cbSize
, (int)sizeof(*info
));
2296 ok(info
->dwServerPid
== GetCurrentProcessId(), "info->dwServerPid was 0x%x instead of 0x%x\n", info
->dwServerPid
, GetCurrentProcessId());
2297 ok(info
->pObject
!= NULL
, "info->pObject shouldn't be NULL\n");
2298 ok(cbDataSize
== 1, "cbDataSize should have been 1 instead of %d\n", cbDataSize
);
2299 ok(*(unsigned char *)pDataBuffer
== 0xcc, "pDataBuffer should have contained 0xcc instead of 0x%x\n", *(unsigned char *)pDataBuffer
);
2300 ok(IsEqualGUID(uExtent
, &EXTENTID_WineTest
), "uExtent wasn't correct\n");
2303 static void WINAPI
TestChannelHook_ServerGetSize(
2304 IChannelHook
*iface
,
2310 SChannelHookCallInfo
*info
= (SChannelHookCallInfo
*)riid
;
2311 trace("TestChannelHook_ServerGetSize\n");
2312 trace("\t%s method %d\n", debugstr_iid(riid
), info
->iMethod
);
2313 ok(info
->cbSize
== sizeof(*info
), "info->cbSize was %d instead of %d\n", info
->cbSize
, (int)sizeof(*info
));
2314 ok(info
->dwServerPid
== GetCurrentProcessId(), "info->dwServerPid was 0x%x instead of 0x%x\n", info
->dwServerPid
, GetCurrentProcessId());
2315 ok(info
->pObject
!= NULL
, "info->pObject shouldn't be NULL\n");
2316 ok(IsEqualGUID(uExtent
, &EXTENTID_WineTest
), "uExtent wasn't correct\n");
2317 if (hrFault
!= S_OK
)
2318 trace("\thrFault = 0x%08x\n", hrFault
);
2323 static void WINAPI
TestChannelHook_ServerFillBuffer(
2324 IChannelHook
*iface
,
2331 trace("TestChannelHook_ServerFillBuffer\n");
2332 ok(0, "TestChannelHook_ServerFillBuffer shouldn't be called\n");
2335 static const IChannelHookVtbl TestChannelHookVtbl
=
2337 TestChannelHook_QueryInterface
,
2338 TestChannelHook_AddRef
,
2339 TestChannelHook_Release
,
2340 TestChannelHook_ClientGetSize
,
2341 TestChannelHook_ClientFillBuffer
,
2342 TestChannelHook_ClientNotify
,
2343 TestChannelHook_ServerNotify
,
2344 TestChannelHook_ServerGetSize
,
2345 TestChannelHook_ServerFillBuffer
,
2348 static IChannelHook TestChannelHook
= { &TestChannelHookVtbl
};
2350 static void test_channel_hook(void)
2352 IStream
*pStream
= NULL
;
2353 IClassFactory
*cf
= NULL
;
2355 IUnknown
*proxy
= NULL
;
2359 hr
= CoRegisterChannelHook(&EXTENTID_WineTest
, &TestChannelHook
);
2360 ok_ole_success(hr
, CoRegisterChannelHook
);
2362 hr
= CoRegisterMessageFilter(&MessageFilter
, NULL
);
2363 ok_ole_success(hr
, CoRegisterMessageFilter
);
2367 hr
= CreateStreamOnHGlobal(NULL
, TRUE
, &pStream
);
2368 ok_ole_success(hr
, CreateStreamOnHGlobal
);
2369 tid
= start_host_object2(pStream
, &IID_IClassFactory
, (IUnknown
*)&Test_ClassFactory
, MSHLFLAGS_NORMAL
, &MessageFilter
, &thread
);
2371 ok_more_than_one_lock();
2373 IStream_Seek(pStream
, ullZero
, STREAM_SEEK_SET
, NULL
);
2374 hr
= CoUnmarshalInterface(pStream
, &IID_IClassFactory
, (void **)&cf
);
2375 ok_ole_success(hr
, CoUnmarshalInterface
);
2376 IStream_Release(pStream
);
2378 ok_more_than_one_lock();
2380 hr
= IClassFactory_CreateInstance(cf
, NULL
, &IID_IUnknown
, (LPVOID
*)&proxy
);
2381 ok_ole_success(hr
, IClassFactory_CreateInstance
);
2382 IUnknown_Release(proxy
);
2384 IClassFactory_Release(cf
);
2388 end_host_object(tid
, thread
);
2390 hr
= CoRegisterMessageFilter(NULL
, NULL
);
2391 ok_ole_success(hr
, CoRegisterMessageFilter
);
2397 HMODULE hOle32
= GetModuleHandle("ole32");
2398 if (!(pCoInitializeEx
= (void*)GetProcAddress(hOle32
, "CoInitializeEx"))) goto no_test
;
2400 /* register a window class used in several tests */
2401 memset(&wndclass
, 0, sizeof(wndclass
));
2402 wndclass
.lpfnWndProc
= window_proc
;
2403 wndclass
.lpszClassName
= "WineCOMTest";
2404 RegisterClass(&wndclass
);
2406 test_cocreateinstance_proxy();
2408 pCoInitializeEx(NULL
, COINIT_APARTMENTTHREADED
);
2410 /* FIXME: test CoCreateInstanceEx */
2412 /* lifecycle management and marshaling tests */
2413 test_no_marshaler();
2414 test_normal_marshal_and_release();
2415 test_normal_marshal_and_unmarshal();
2416 test_marshal_and_unmarshal_invalid();
2417 test_same_apartment_unmarshal_failure();
2418 test_interthread_marshal_and_unmarshal();
2419 test_proxy_marshal_and_unmarshal();
2420 test_proxy_marshal_and_unmarshal2();
2421 test_marshal_stub_apartment_shutdown();
2422 test_marshal_proxy_apartment_shutdown();
2423 test_marshal_proxy_mta_apartment_shutdown();
2424 test_no_couninitialize_server();
2425 test_no_couninitialize_client();
2426 test_tableweak_marshal_and_unmarshal_twice();
2427 test_tableweak_marshal_releasedata1();
2428 test_tableweak_marshal_releasedata2();
2429 test_tablestrong_marshal_and_unmarshal_twice();
2430 test_lock_object_external();
2431 test_disconnect_stub();
2432 test_normal_marshal_and_unmarshal_twice();
2433 test_hresult_marshaling();
2434 test_proxy_used_in_wrong_thread();
2435 test_message_filter();
2436 test_bad_marshal_stream();
2437 test_proxy_interfaces();
2438 test_stubbuffer(&IID_IClassFactory
);
2439 test_proxybuffer(&IID_IClassFactory
);
2440 test_message_reentrancy();
2441 test_call_from_message();
2442 test_WM_QUIT_handling();
2443 test_freethreadedmarshaler();
2445 /* doesn't pass with Win9x COM DLLs (even though Essential COM says it should) */
2446 if (0) test_out_of_process_com();
2448 test_globalinterfacetable();
2450 /* must be last test as channel hooks can't be unregistered */
2451 test_channel_hook();
2457 trace("You need DCOM95 installed to run this test\n");