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
33 #include "wine/test.h"
35 /* functions that are not present on all versions of Windows */
36 HRESULT (WINAPI
* pCoInitializeEx
)(LPVOID lpReserved
, DWORD dwCoInit
);
38 /* helper macros to make tests a bit leaner */
39 #define ok_more_than_one_lock() ok(cLocks > 0, "Number of locks should be > 0, but actually is %d\n", cLocks)
40 #define ok_no_locks() ok(cLocks == 0, "Number of locks should be 0, but actually is %d\n", cLocks)
41 #define ok_ole_success(hr, func) ok(hr == S_OK, #func " failed with error 0x%08x\n", hr)
43 static const IID IID_IWineTest
=
48 {0xa1, 0xa2, 0x5d, 0x5a, 0x36, 0x54, 0xd3, 0xbd}
49 }; /* 5201163f-8164-4fd0-a1a2-5d5a3654d3bd */
51 static const IID IID_IRemUnknown
=
56 {0xc0,0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46}
59 #define EXTENTID_WineTest IID_IWineTest
60 #define CLSID_WineTest IID_IWineTest
62 static const CLSID CLSID_WineOOPTest
=
67 {0xa1, 0xa2, 0x5d, 0x5a, 0x36, 0x54, 0xd3, 0xbd}
68 }; /* 5201163f-8164-4fd0-a1a2-5d5a3654d3bd */
70 static void test_cocreateinstance_proxy(void)
76 pCoInitializeEx(NULL
, COINIT_MULTITHREADED
);
78 hr
= CoCreateInstance(&CLSID_ShellDesktop
, NULL
, CLSCTX_INPROC
, &IID_IUnknown
, (void **)&pProxy
);
79 ok_ole_success(hr
, CoCreateInstance
);
80 hr
= IUnknown_QueryInterface(pProxy
, &IID_IMultiQI
, (void **)&pMQI
);
82 ok(hr
== S_OK
, "created object is not a proxy, so was created in the wrong apartment\n");
84 IMultiQI_Release(pMQI
);
85 IUnknown_Release(pProxy
);
90 static const LARGE_INTEGER ullZero
;
93 static void LockModule(void)
95 InterlockedIncrement(&cLocks
);
98 static void UnlockModule(void)
100 InterlockedDecrement(&cLocks
);
104 static HRESULT WINAPI
Test_IUnknown_QueryInterface(
109 if (ppvObj
== NULL
) return E_POINTER
;
111 if (IsEqualGUID(riid
, &IID_IUnknown
))
113 *ppvObj
= (LPVOID
)iface
;
114 IUnknown_AddRef(iface
);
119 return E_NOINTERFACE
;
122 static ULONG WINAPI
Test_IUnknown_AddRef(LPUNKNOWN iface
)
125 return 2; /* non-heap-based object */
128 static ULONG WINAPI
Test_IUnknown_Release(LPUNKNOWN iface
)
131 return 1; /* non-heap-based object */
134 static const IUnknownVtbl TestUnknown_Vtbl
=
136 Test_IUnknown_QueryInterface
,
137 Test_IUnknown_AddRef
,
138 Test_IUnknown_Release
,
141 static IUnknown Test_Unknown
= { &TestUnknown_Vtbl
};
144 static HRESULT WINAPI
Test_IClassFactory_QueryInterface(
145 LPCLASSFACTORY iface
,
149 if (ppvObj
== NULL
) return E_POINTER
;
151 if (IsEqualGUID(riid
, &IID_IUnknown
) ||
152 IsEqualGUID(riid
, &IID_IClassFactory
) ||
153 /* the only other interface Wine is currently able to marshal (for testing two proxies) */
154 IsEqualGUID(riid
, &IID_IRemUnknown
))
156 *ppvObj
= (LPVOID
)iface
;
157 IClassFactory_AddRef(iface
);
162 return E_NOINTERFACE
;
165 static ULONG WINAPI
Test_IClassFactory_AddRef(LPCLASSFACTORY iface
)
168 return 2; /* non-heap-based object */
171 static ULONG WINAPI
Test_IClassFactory_Release(LPCLASSFACTORY iface
)
174 return 1; /* non-heap-based object */
177 static HRESULT WINAPI
Test_IClassFactory_CreateInstance(
178 LPCLASSFACTORY iface
,
183 if (pUnkOuter
) return CLASS_E_NOAGGREGATION
;
184 return IUnknown_QueryInterface((IUnknown
*)&Test_Unknown
, riid
, ppvObj
);
187 static HRESULT WINAPI
Test_IClassFactory_LockServer(
188 LPCLASSFACTORY iface
,
194 static const IClassFactoryVtbl TestClassFactory_Vtbl
=
196 Test_IClassFactory_QueryInterface
,
197 Test_IClassFactory_AddRef
,
198 Test_IClassFactory_Release
,
199 Test_IClassFactory_CreateInstance
,
200 Test_IClassFactory_LockServer
203 static IClassFactory Test_ClassFactory
= { &TestClassFactory_Vtbl
};
205 #define RELEASEMARSHALDATA WM_USER
207 struct host_object_data
212 MSHLFLAGS marshal_flags
;
213 HANDLE marshal_event
;
214 IMessageFilter
*filter
;
217 static DWORD CALLBACK
host_object_proc(LPVOID p
)
219 struct host_object_data
*data
= (struct host_object_data
*)p
;
223 pCoInitializeEx(NULL
, COINIT_APARTMENTTHREADED
);
227 IMessageFilter
* prev_filter
= NULL
;
228 hr
= CoRegisterMessageFilter(data
->filter
, &prev_filter
);
229 if (prev_filter
) IMessageFilter_Release(prev_filter
);
230 ok_ole_success(hr
, CoRegisterMessageFilter
);
233 hr
= CoMarshalInterface(data
->stream
, &data
->iid
, data
->object
, MSHCTX_INPROC
, NULL
, data
->marshal_flags
);
234 ok_ole_success(hr
, CoMarshalInterface
);
236 /* force the message queue to be created before signaling parent thread */
237 PeekMessage(&msg
, NULL
, WM_USER
, WM_USER
, PM_NOREMOVE
);
239 SetEvent(data
->marshal_event
);
241 while (GetMessage(&msg
, NULL
, 0, 0))
243 if (msg
.hwnd
== NULL
&& msg
.message
== RELEASEMARSHALDATA
)
245 trace("releasing marshal data\n");
246 CoReleaseMarshalData(data
->stream
);
247 SetEvent((HANDLE
)msg
.lParam
);
250 DispatchMessage(&msg
);
253 HeapFree(GetProcessHeap(), 0, data
);
260 static DWORD
start_host_object2(IStream
*stream
, REFIID riid
, IUnknown
*object
, MSHLFLAGS marshal_flags
, IMessageFilter
*filter
, HANDLE
*thread
)
263 HANDLE marshal_event
= CreateEvent(NULL
, FALSE
, FALSE
, NULL
);
264 struct host_object_data
*data
= HeapAlloc(GetProcessHeap(), 0, sizeof(*data
));
266 data
->stream
= stream
;
268 data
->object
= object
;
269 data
->marshal_flags
= marshal_flags
;
270 data
->marshal_event
= marshal_event
;
271 data
->filter
= filter
;
273 *thread
= CreateThread(NULL
, 0, host_object_proc
, data
, 0, &tid
);
275 /* wait for marshaling to complete before returning */
276 WaitForSingleObject(marshal_event
, INFINITE
);
277 CloseHandle(marshal_event
);
282 static DWORD
start_host_object(IStream
*stream
, REFIID riid
, IUnknown
*object
, MSHLFLAGS marshal_flags
, HANDLE
*thread
)
284 return start_host_object2(stream
, riid
, object
, marshal_flags
, NULL
, thread
);
287 /* asks thread to release the marshal data because it has to be done by the
288 * same thread that marshaled the interface in the first place. */
289 static void release_host_object(DWORD tid
)
291 HANDLE event
= CreateEvent(NULL
, FALSE
, FALSE
, NULL
);
292 PostThreadMessage(tid
, RELEASEMARSHALDATA
, 0, (LPARAM
)event
);
293 WaitForSingleObject(event
, INFINITE
);
297 static void end_host_object(DWORD tid
, HANDLE thread
)
299 BOOL ret
= PostThreadMessage(tid
, WM_QUIT
, 0, 0);
300 ok(ret
, "PostThreadMessage failed with error %d\n", GetLastError());
301 /* be careful of races - don't return until hosting thread has terminated */
302 WaitForSingleObject(thread
, INFINITE
);
306 /* tests failure case of interface not having a marshaler specified in the
308 static void test_no_marshaler(void)
313 hr
= CreateStreamOnHGlobal(NULL
, TRUE
, &pStream
);
314 ok_ole_success(hr
, CreateStreamOnHGlobal
);
315 hr
= CoMarshalInterface(pStream
, &IID_IWineTest
, (IUnknown
*)&Test_ClassFactory
, MSHCTX_INPROC
, NULL
, MSHLFLAGS_NORMAL
);
316 ok(hr
== E_NOINTERFACE
, "CoMarshalInterface should have returned E_NOINTERFACE instead of 0x%08x\n", hr
);
318 IStream_Release(pStream
);
321 /* tests normal marshal and then release without unmarshaling */
322 static void test_normal_marshal_and_release(void)
325 IStream
*pStream
= NULL
;
329 hr
= CreateStreamOnHGlobal(NULL
, TRUE
, &pStream
);
330 ok_ole_success(hr
, CreateStreamOnHGlobal
);
331 hr
= CoMarshalInterface(pStream
, &IID_IClassFactory
, (IUnknown
*)&Test_ClassFactory
, MSHCTX_INPROC
, NULL
, MSHLFLAGS_NORMAL
);
332 ok_ole_success(hr
, CoMarshalInterface
);
334 ok_more_than_one_lock();
336 IStream_Seek(pStream
, ullZero
, STREAM_SEEK_SET
, NULL
);
337 hr
= CoReleaseMarshalData(pStream
);
338 ok_ole_success(hr
, CoReleaseMarshalData
);
339 IStream_Release(pStream
);
344 /* tests success case of a same-thread marshal and unmarshal */
345 static void test_normal_marshal_and_unmarshal(void)
348 IStream
*pStream
= NULL
;
349 IUnknown
*pProxy
= NULL
;
353 hr
= CreateStreamOnHGlobal(NULL
, TRUE
, &pStream
);
354 ok_ole_success(hr
, CreateStreamOnHGlobal
);
355 hr
= CoMarshalInterface(pStream
, &IID_IClassFactory
, (IUnknown
*)&Test_ClassFactory
, MSHCTX_INPROC
, NULL
, MSHLFLAGS_NORMAL
);
356 ok_ole_success(hr
, CoMarshalInterface
);
358 ok_more_than_one_lock();
360 IStream_Seek(pStream
, ullZero
, STREAM_SEEK_SET
, NULL
);
361 hr
= CoUnmarshalInterface(pStream
, &IID_IClassFactory
, (void **)&pProxy
);
362 ok_ole_success(hr
, CoUnmarshalInterface
);
363 IStream_Release(pStream
);
365 ok_more_than_one_lock();
367 IUnknown_Release(pProxy
);
372 /* tests failure case of unmarshaling a freed object */
373 static void test_marshal_and_unmarshal_invalid(void)
376 IStream
*pStream
= NULL
;
377 IClassFactory
*pProxy
= NULL
;
384 hr
= CreateStreamOnHGlobal(NULL
, TRUE
, &pStream
);
385 ok_ole_success(hr
, CreateStreamOnHGlobal
);
386 tid
= start_host_object(pStream
, &IID_IClassFactory
, (IUnknown
*)&Test_ClassFactory
, MSHLFLAGS_NORMAL
, &thread
);
388 ok_more_than_one_lock();
390 IStream_Seek(pStream
, ullZero
, STREAM_SEEK_SET
, NULL
);
391 hr
= CoReleaseMarshalData(pStream
);
392 ok_ole_success(hr
, CoReleaseMarshalData
);
396 IStream_Seek(pStream
, ullZero
, STREAM_SEEK_SET
, NULL
);
397 hr
= CoUnmarshalInterface(pStream
, &IID_IClassFactory
, (void **)&pProxy
);
398 todo_wine
{ ok_ole_success(hr
, CoUnmarshalInterface
); }
404 hr
= IClassFactory_CreateInstance(pProxy
, NULL
, &IID_IUnknown
, &dummy
);
405 ok(hr
== RPC_E_DISCONNECTED
, "Remote call should have returned RPC_E_DISCONNECTED, instead of 0x%08x\n", hr
);
407 IClassFactory_Release(pProxy
);
410 IStream_Release(pStream
);
412 end_host_object(tid
, thread
);
415 static void test_same_apartment_unmarshal_failure(void)
420 static const LARGE_INTEGER llZero
;
424 hr
= CreateStreamOnHGlobal(NULL
, TRUE
, &pStream
);
425 ok_ole_success(hr
, CreateStreamOnHGlobal
);
427 hr
= CoMarshalInterface(pStream
, &IID_IUnknown
, (IUnknown
*)&Test_ClassFactory
, MSHCTX_INPROC
, NULL
, MSHLFLAGS_NORMAL
);
428 ok_ole_success(hr
, CoMarshalInterface
);
430 ok_more_than_one_lock();
432 hr
= IStream_Seek(pStream
, llZero
, STREAM_SEEK_SET
, NULL
);
433 ok_ole_success(hr
, IStream_Seek
);
435 hr
= CoUnmarshalInterface(pStream
, &IID_IParseDisplayName
, (void **)&pProxy
);
436 ok(hr
== E_NOINTERFACE
, "CoUnmarshalInterface should have returned E_NOINTERFACE instead of 0x%08x\n", hr
);
441 /* tests success case of an interthread marshal */
442 static void test_interthread_marshal_and_unmarshal(void)
445 IStream
*pStream
= NULL
;
446 IUnknown
*pProxy
= NULL
;
452 hr
= CreateStreamOnHGlobal(NULL
, TRUE
, &pStream
);
453 ok_ole_success(hr
, CreateStreamOnHGlobal
);
454 tid
= start_host_object(pStream
, &IID_IClassFactory
, (IUnknown
*)&Test_ClassFactory
, MSHLFLAGS_NORMAL
, &thread
);
456 ok_more_than_one_lock();
458 IStream_Seek(pStream
, ullZero
, STREAM_SEEK_SET
, NULL
);
459 hr
= CoUnmarshalInterface(pStream
, &IID_IClassFactory
, (void **)&pProxy
);
460 ok_ole_success(hr
, CoUnmarshalInterface
);
461 IStream_Release(pStream
);
463 ok_more_than_one_lock();
465 IUnknown_Release(pProxy
);
469 end_host_object(tid
, thread
);
472 /* the number of external references that Wine's proxy manager normally gives
473 * out, so we can test the border case of running out of references */
474 #define NORMALEXTREFS 5
476 /* tests success case of an interthread marshal and then marshaling the proxy */
477 static void test_proxy_marshal_and_unmarshal(void)
480 IStream
*pStream
= NULL
;
481 IUnknown
*pProxy
= NULL
;
482 IUnknown
*pProxy2
= NULL
;
489 hr
= CreateStreamOnHGlobal(NULL
, TRUE
, &pStream
);
490 ok_ole_success(hr
, CreateStreamOnHGlobal
);
491 tid
= start_host_object(pStream
, &IID_IClassFactory
, (IUnknown
*)&Test_ClassFactory
, MSHLFLAGS_NORMAL
, &thread
);
493 ok_more_than_one_lock();
495 IStream_Seek(pStream
, ullZero
, STREAM_SEEK_SET
, NULL
);
496 hr
= CoUnmarshalInterface(pStream
, &IID_IClassFactory
, (void **)&pProxy
);
497 ok_ole_success(hr
, CoUnmarshalInterface
);
499 ok_more_than_one_lock();
501 IStream_Seek(pStream
, ullZero
, STREAM_SEEK_SET
, NULL
);
502 /* marshal the proxy */
503 hr
= CoMarshalInterface(pStream
, &IID_IClassFactory
, pProxy
, MSHCTX_INPROC
, NULL
, MSHLFLAGS_NORMAL
);
504 ok_ole_success(hr
, CoMarshalInterface
);
506 ok_more_than_one_lock();
508 /* marshal 5 more times to exhaust the normal external references of 5 */
509 for (i
= 0; i
< NORMALEXTREFS
; i
++)
511 hr
= CoMarshalInterface(pStream
, &IID_IClassFactory
, pProxy
, MSHCTX_INPROC
, NULL
, MSHLFLAGS_NORMAL
);
512 ok_ole_success(hr
, CoMarshalInterface
);
515 ok_more_than_one_lock();
517 /* release the original proxy to test that we successfully keep the
518 * original object alive */
519 IUnknown_Release(pProxy
);
521 IStream_Seek(pStream
, ullZero
, STREAM_SEEK_SET
, NULL
);
522 hr
= CoUnmarshalInterface(pStream
, &IID_IClassFactory
, (void **)&pProxy2
);
523 ok_ole_success(hr
, CoUnmarshalInterface
);
525 ok_more_than_one_lock();
527 /* now the proxies should be as follows:
528 * pProxy2 -> &Test_ClassFactory
529 * they should NOT be as follows:
530 * pProxy -> &Test_ClassFactory
532 * the above can only really be tested by looking in +ole traces
535 IUnknown_Release(pProxy2
);
537 /* unmarshal all of the proxies to check that the object stub still exists */
538 for (i
= 0; i
< NORMALEXTREFS
; i
++)
540 hr
= CoUnmarshalInterface(pStream
, &IID_IClassFactory
, (void **)&pProxy2
);
541 ok_ole_success(hr
, CoUnmarshalInterface
);
543 IUnknown_Release(pProxy2
);
548 IStream_Release(pStream
);
550 end_host_object(tid
, thread
);
553 /* tests success case of an interthread marshal and then marshaling the proxy
554 * using an iid that hasn't previously been unmarshaled */
555 static void test_proxy_marshal_and_unmarshal2(void)
558 IStream
*pStream
= NULL
;
559 IUnknown
*pProxy
= NULL
;
560 IUnknown
*pProxy2
= NULL
;
566 hr
= CreateStreamOnHGlobal(NULL
, TRUE
, &pStream
);
567 ok_ole_success(hr
, CreateStreamOnHGlobal
);
568 tid
= start_host_object(pStream
, &IID_IUnknown
, (IUnknown
*)&Test_ClassFactory
, MSHLFLAGS_NORMAL
, &thread
);
570 ok_more_than_one_lock();
572 IStream_Seek(pStream
, ullZero
, STREAM_SEEK_SET
, NULL
);
573 hr
= CoUnmarshalInterface(pStream
, &IID_IUnknown
, (void **)&pProxy
);
574 ok_ole_success(hr
, CoUnmarshalInterface
);
576 ok_more_than_one_lock();
578 IStream_Seek(pStream
, ullZero
, STREAM_SEEK_SET
, NULL
);
579 /* marshal the proxy */
580 hr
= CoMarshalInterface(pStream
, &IID_IClassFactory
, pProxy
, MSHCTX_INPROC
, NULL
, MSHLFLAGS_NORMAL
);
581 ok_ole_success(hr
, CoMarshalInterface
);
583 ok_more_than_one_lock();
585 IStream_Seek(pStream
, ullZero
, STREAM_SEEK_SET
, NULL
);
586 /* unmarshal the second proxy to the object */
587 hr
= CoUnmarshalInterface(pStream
, &IID_IClassFactory
, (void **)&pProxy2
);
588 ok_ole_success(hr
, CoUnmarshalInterface
);
589 IStream_Release(pStream
);
591 /* now the proxies should be as follows:
592 * pProxy -> &Test_ClassFactory
593 * pProxy2 -> &Test_ClassFactory
594 * they should NOT be as follows:
595 * pProxy -> &Test_ClassFactory
597 * the above can only really be tested by looking in +ole traces
600 ok_more_than_one_lock();
602 IUnknown_Release(pProxy
);
604 ok_more_than_one_lock();
606 IUnknown_Release(pProxy2
);
610 end_host_object(tid
, thread
);
613 /* tests that stubs are released when the containing apartment is destroyed */
614 static void test_marshal_stub_apartment_shutdown(void)
617 IStream
*pStream
= NULL
;
618 IUnknown
*pProxy
= NULL
;
624 hr
= CreateStreamOnHGlobal(NULL
, TRUE
, &pStream
);
625 ok_ole_success(hr
, CreateStreamOnHGlobal
);
626 tid
= start_host_object(pStream
, &IID_IClassFactory
, (IUnknown
*)&Test_ClassFactory
, MSHLFLAGS_NORMAL
, &thread
);
628 ok_more_than_one_lock();
630 IStream_Seek(pStream
, ullZero
, STREAM_SEEK_SET
, NULL
);
631 hr
= CoUnmarshalInterface(pStream
, &IID_IClassFactory
, (void **)&pProxy
);
632 ok_ole_success(hr
, CoUnmarshalInterface
);
633 IStream_Release(pStream
);
635 ok_more_than_one_lock();
637 end_host_object(tid
, thread
);
641 IUnknown_Release(pProxy
);
646 /* tests that proxies are released when the containing apartment is destroyed */
647 static void test_marshal_proxy_apartment_shutdown(void)
650 IStream
*pStream
= NULL
;
651 IUnknown
*pProxy
= NULL
;
657 hr
= CreateStreamOnHGlobal(NULL
, TRUE
, &pStream
);
658 ok_ole_success(hr
, CreateStreamOnHGlobal
);
659 tid
= start_host_object(pStream
, &IID_IClassFactory
, (IUnknown
*)&Test_ClassFactory
, MSHLFLAGS_NORMAL
, &thread
);
661 ok_more_than_one_lock();
663 IStream_Seek(pStream
, ullZero
, STREAM_SEEK_SET
, NULL
);
664 hr
= CoUnmarshalInterface(pStream
, &IID_IClassFactory
, (void **)&pProxy
);
665 ok_ole_success(hr
, CoUnmarshalInterface
);
666 IStream_Release(pStream
);
668 ok_more_than_one_lock();
674 IUnknown_Release(pProxy
);
678 end_host_object(tid
, thread
);
680 pCoInitializeEx(NULL
, COINIT_APARTMENTTHREADED
);
683 /* tests that proxies are released when the containing mta apartment is destroyed */
684 static void test_marshal_proxy_mta_apartment_shutdown(void)
687 IStream
*pStream
= NULL
;
688 IUnknown
*pProxy
= NULL
;
693 pCoInitializeEx(NULL
, COINIT_MULTITHREADED
);
697 hr
= CreateStreamOnHGlobal(NULL
, TRUE
, &pStream
);
698 ok_ole_success(hr
, CreateStreamOnHGlobal
);
699 tid
= start_host_object(pStream
, &IID_IClassFactory
, (IUnknown
*)&Test_ClassFactory
, MSHLFLAGS_NORMAL
, &thread
);
701 ok_more_than_one_lock();
703 IStream_Seek(pStream
, ullZero
, STREAM_SEEK_SET
, NULL
);
704 hr
= CoUnmarshalInterface(pStream
, &IID_IClassFactory
, (void **)&pProxy
);
705 ok_ole_success(hr
, CoUnmarshalInterface
);
706 IStream_Release(pStream
);
708 ok_more_than_one_lock();
714 IUnknown_Release(pProxy
);
718 end_host_object(tid
, thread
);
720 pCoInitializeEx(NULL
, COINIT_APARTMENTTHREADED
);
726 HANDLE marshal_event
;
727 HANDLE unmarshal_event
;
730 /* helper for test_no_couninitialize_server */
731 static DWORD CALLBACK
no_couninitialize_server_proc(LPVOID p
)
733 struct ncu_params
*ncu_params
= (struct ncu_params
*)p
;
736 pCoInitializeEx(NULL
, COINIT_MULTITHREADED
);
738 hr
= CoMarshalInterface(ncu_params
->stream
, &IID_IClassFactory
, (IUnknown
*)&Test_ClassFactory
, MSHCTX_INPROC
, NULL
, MSHLFLAGS_NORMAL
);
739 ok_ole_success(hr
, CoMarshalInterface
);
741 SetEvent(ncu_params
->marshal_event
);
743 WaitForSingleObject(ncu_params
->unmarshal_event
, INFINITE
);
745 /* die without calling CoUninitialize */
750 /* tests apartment that an apartment with a stub is released without deadlock
751 * if the owning thread exits */
752 static void test_no_couninitialize_server(void)
755 IStream
*pStream
= NULL
;
756 IUnknown
*pProxy
= NULL
;
759 struct ncu_params ncu_params
;
763 ncu_params
.marshal_event
= CreateEvent(NULL
, TRUE
, FALSE
, NULL
);
764 ncu_params
.unmarshal_event
= CreateEvent(NULL
, TRUE
, FALSE
, NULL
);
766 hr
= CreateStreamOnHGlobal(NULL
, TRUE
, &pStream
);
767 ok_ole_success(hr
, CreateStreamOnHGlobal
);
768 ncu_params
.stream
= pStream
;
770 thread
= CreateThread(NULL
, 0, no_couninitialize_server_proc
, &ncu_params
, 0, &tid
);
772 WaitForSingleObject(ncu_params
.marshal_event
, INFINITE
);
773 ok_more_than_one_lock();
775 IStream_Seek(pStream
, ullZero
, STREAM_SEEK_SET
, NULL
);
776 hr
= CoUnmarshalInterface(pStream
, &IID_IClassFactory
, (void **)&pProxy
);
777 ok_ole_success(hr
, CoUnmarshalInterface
);
778 IStream_Release(pStream
);
780 ok_more_than_one_lock();
782 SetEvent(ncu_params
.unmarshal_event
);
783 WaitForSingleObject(thread
, INFINITE
);
788 CloseHandle(ncu_params
.marshal_event
);
789 CloseHandle(ncu_params
.unmarshal_event
);
791 IUnknown_Release(pProxy
);
796 /* STA -> STA call during DLL_THREAD_DETACH */
797 static DWORD CALLBACK
no_couninitialize_client_proc(LPVOID p
)
799 struct ncu_params
*ncu_params
= (struct ncu_params
*)p
;
801 IUnknown
*pProxy
= NULL
;
803 pCoInitializeEx(NULL
, COINIT_APARTMENTTHREADED
);
805 hr
= CoUnmarshalInterface(ncu_params
->stream
, &IID_IClassFactory
, (void **)&pProxy
);
806 ok_ole_success(hr
, CoUnmarshalInterface
);
807 IStream_Release(ncu_params
->stream
);
809 ok_more_than_one_lock();
811 /* die without calling CoUninitialize */
816 /* tests STA -> STA call during DLL_THREAD_DETACH doesn't deadlock */
817 static void test_no_couninitialize_client(void)
820 IStream
*pStream
= NULL
;
825 struct ncu_params ncu_params
;
829 hr
= CreateStreamOnHGlobal(NULL
, TRUE
, &pStream
);
830 ok_ole_success(hr
, CreateStreamOnHGlobal
);
831 ncu_params
.stream
= pStream
;
833 /* NOTE: assumes start_host_object uses an STA to host the object, as MTAs
834 * always deadlock when called from within DllMain */
835 host_tid
= start_host_object(pStream
, &IID_IClassFactory
, (IUnknown
*)&Test_ClassFactory
, MSHLFLAGS_NORMAL
, &host_thread
);
836 IStream_Seek(pStream
, ullZero
, STREAM_SEEK_SET
, NULL
);
838 ok_more_than_one_lock();
840 thread
= CreateThread(NULL
, 0, no_couninitialize_client_proc
, &ncu_params
, 0, &tid
);
842 WaitForSingleObject(thread
, INFINITE
);
847 end_host_object(host_tid
, host_thread
);
850 /* tests success case of a same-thread table-weak marshal, unmarshal, unmarshal */
851 static void test_tableweak_marshal_and_unmarshal_twice(void)
854 IStream
*pStream
= NULL
;
855 IUnknown
*pProxy1
= NULL
;
856 IUnknown
*pProxy2
= NULL
;
862 hr
= CreateStreamOnHGlobal(NULL
, TRUE
, &pStream
);
863 ok_ole_success(hr
, CreateStreamOnHGlobal
);
864 tid
= start_host_object(pStream
, &IID_IClassFactory
, (IUnknown
*)&Test_ClassFactory
, MSHLFLAGS_TABLEWEAK
, &thread
);
866 ok_more_than_one_lock();
868 IStream_Seek(pStream
, ullZero
, STREAM_SEEK_SET
, NULL
);
869 hr
= CoUnmarshalInterface(pStream
, &IID_IClassFactory
, (void **)&pProxy1
);
870 ok_ole_success(hr
, CoUnmarshalInterface
);
872 ok_more_than_one_lock();
874 IStream_Seek(pStream
, ullZero
, STREAM_SEEK_SET
, NULL
);
875 hr
= CoUnmarshalInterface(pStream
, &IID_IClassFactory
, (void **)&pProxy2
);
876 IStream_Release(pStream
);
877 ok_ole_success(hr
, CoUnmarshalInterface
);
879 ok_more_than_one_lock();
881 IUnknown_Release(pProxy1
);
882 IUnknown_Release(pProxy2
);
884 /* this line is shows the difference between weak and strong table marshaling:
885 * weak has cLocks == 0
886 * strong has cLocks > 0 */
889 end_host_object(tid
, thread
);
892 /* tests releasing after unmarshaling one object */
893 static void test_tableweak_marshal_releasedata1(void)
896 IStream
*pStream
= NULL
;
897 IUnknown
*pProxy1
= NULL
;
898 IUnknown
*pProxy2
= NULL
;
904 hr
= CreateStreamOnHGlobal(NULL
, TRUE
, &pStream
);
905 ok_ole_success(hr
, CreateStreamOnHGlobal
);
906 tid
= start_host_object(pStream
, &IID_IClassFactory
, (IUnknown
*)&Test_ClassFactory
, MSHLFLAGS_TABLEWEAK
, &thread
);
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 /* release the remaining reference on the object by calling
917 * CoReleaseMarshalData in the hosting thread */
918 IStream_Seek(pStream
, ullZero
, STREAM_SEEK_SET
, NULL
);
919 release_host_object(tid
);
921 ok_more_than_one_lock();
923 IStream_Seek(pStream
, ullZero
, STREAM_SEEK_SET
, NULL
);
924 hr
= CoUnmarshalInterface(pStream
, &IID_IClassFactory
, (void **)&pProxy2
);
925 ok_ole_success(hr
, CoUnmarshalInterface
);
926 IStream_Release(pStream
);
928 ok_more_than_one_lock();
930 IUnknown_Release(pProxy1
);
932 IUnknown_Release(pProxy2
);
934 /* this line is shows the difference between weak and strong table marshaling:
935 * weak has cLocks == 0
936 * strong has cLocks > 0 */
939 end_host_object(tid
, thread
);
942 /* tests releasing after unmarshaling one object */
943 static void test_tableweak_marshal_releasedata2(void)
946 IStream
*pStream
= NULL
;
947 IUnknown
*pProxy
= NULL
;
953 hr
= CreateStreamOnHGlobal(NULL
, TRUE
, &pStream
);
954 ok_ole_success(hr
, CreateStreamOnHGlobal
);
955 tid
= start_host_object(pStream
, &IID_IClassFactory
, (IUnknown
*)&Test_ClassFactory
, MSHLFLAGS_TABLEWEAK
, &thread
);
957 ok_more_than_one_lock();
959 /* release the remaining reference on the object by calling
960 * CoReleaseMarshalData in the hosting thread */
961 IStream_Seek(pStream
, ullZero
, STREAM_SEEK_SET
, NULL
);
962 release_host_object(tid
);
966 IStream_Seek(pStream
, ullZero
, STREAM_SEEK_SET
, NULL
);
967 hr
= CoUnmarshalInterface(pStream
, &IID_IClassFactory
, (void **)&pProxy
);
970 ok(hr
== CO_E_OBJNOTREG
,
971 "CoUnmarshalInterface should have failed with CO_E_OBJNOTREG, but returned 0x%08x instead\n",
974 IStream_Release(pStream
);
978 end_host_object(tid
, thread
);
981 /* tests success case of a same-thread table-strong marshal, unmarshal, unmarshal */
982 static void test_tablestrong_marshal_and_unmarshal_twice(void)
985 IStream
*pStream
= NULL
;
986 IUnknown
*pProxy1
= NULL
;
987 IUnknown
*pProxy2
= NULL
;
993 hr
= CreateStreamOnHGlobal(NULL
, TRUE
, &pStream
);
994 ok_ole_success(hr
, CreateStreamOnHGlobal
);
995 tid
= start_host_object(pStream
, &IID_IClassFactory
, (IUnknown
*)&Test_ClassFactory
, MSHLFLAGS_TABLESTRONG
, &thread
);
997 ok_more_than_one_lock();
999 IStream_Seek(pStream
, ullZero
, STREAM_SEEK_SET
, NULL
);
1000 hr
= CoUnmarshalInterface(pStream
, &IID_IClassFactory
, (void **)&pProxy1
);
1001 ok_ole_success(hr
, CoUnmarshalInterface
);
1003 ok_more_than_one_lock();
1005 IStream_Seek(pStream
, ullZero
, STREAM_SEEK_SET
, NULL
);
1006 hr
= CoUnmarshalInterface(pStream
, &IID_IClassFactory
, (void **)&pProxy2
);
1007 ok_ole_success(hr
, CoUnmarshalInterface
);
1009 ok_more_than_one_lock();
1011 if (pProxy1
) IUnknown_Release(pProxy1
);
1012 if (pProxy2
) IUnknown_Release(pProxy2
);
1014 /* this line is shows the difference between weak and strong table marshaling:
1015 * weak has cLocks == 0
1016 * strong has cLocks > 0 */
1017 ok_more_than_one_lock();
1019 /* release the remaining reference on the object by calling
1020 * CoReleaseMarshalData in the hosting thread */
1021 IStream_Seek(pStream
, ullZero
, STREAM_SEEK_SET
, NULL
);
1022 release_host_object(tid
);
1023 IStream_Release(pStream
);
1027 end_host_object(tid
, thread
);
1030 /* tests CoLockObjectExternal */
1031 static void test_lock_object_external(void)
1034 IStream
*pStream
= NULL
;
1038 /* test the stub manager creation aspect of CoLockObjectExternal when the
1039 * object hasn't been marshaled yet */
1040 CoLockObjectExternal((IUnknown
*)&Test_ClassFactory
, TRUE
, TRUE
);
1042 ok_more_than_one_lock();
1044 CoDisconnectObject((IUnknown
*)&Test_ClassFactory
, 0);
1048 /* test our empty stub manager being handled correctly in
1049 * CoMarshalInterface */
1050 CoLockObjectExternal((IUnknown
*)&Test_ClassFactory
, TRUE
, TRUE
);
1052 hr
= CreateStreamOnHGlobal(NULL
, TRUE
, &pStream
);
1053 ok_ole_success(hr
, CreateStreamOnHGlobal
);
1054 hr
= CoMarshalInterface(pStream
, &IID_IClassFactory
, (IUnknown
*)&Test_ClassFactory
, MSHCTX_INPROC
, NULL
, MSHLFLAGS_NORMAL
);
1055 ok_ole_success(hr
, CoMarshalInterface
);
1057 CoLockObjectExternal((IUnknown
*)&Test_ClassFactory
, TRUE
, TRUE
);
1059 ok_more_than_one_lock();
1061 IStream_Seek(pStream
, ullZero
, STREAM_SEEK_SET
, NULL
);
1062 hr
= CoReleaseMarshalData(pStream
);
1063 ok_ole_success(hr
, CoReleaseMarshalData
);
1064 IStream_Release(pStream
);
1066 ok_more_than_one_lock();
1068 CoLockObjectExternal((IUnknown
*)&Test_ClassFactory
, FALSE
, TRUE
);
1070 ok_more_than_one_lock();
1072 CoLockObjectExternal((IUnknown
*)&Test_ClassFactory
, FALSE
, TRUE
);
1077 /* tests disconnecting stubs */
1078 static void test_disconnect_stub(void)
1081 IStream
*pStream
= NULL
;
1085 hr
= CreateStreamOnHGlobal(NULL
, TRUE
, &pStream
);
1086 ok_ole_success(hr
, CreateStreamOnHGlobal
);
1087 hr
= CoMarshalInterface(pStream
, &IID_IClassFactory
, (IUnknown
*)&Test_ClassFactory
, MSHCTX_INPROC
, NULL
, MSHLFLAGS_NORMAL
);
1088 ok_ole_success(hr
, CoMarshalInterface
);
1090 CoLockObjectExternal((IUnknown
*)&Test_ClassFactory
, TRUE
, TRUE
);
1092 ok_more_than_one_lock();
1094 IStream_Seek(pStream
, ullZero
, STREAM_SEEK_SET
, NULL
);
1095 hr
= CoReleaseMarshalData(pStream
);
1096 ok_ole_success(hr
, CoReleaseMarshalData
);
1097 IStream_Release(pStream
);
1099 ok_more_than_one_lock();
1101 CoDisconnectObject((IUnknown
*)&Test_ClassFactory
, 0);
1106 /* tests failure case of a same-thread marshal and unmarshal twice */
1107 static void test_normal_marshal_and_unmarshal_twice(void)
1110 IStream
*pStream
= NULL
;
1111 IUnknown
*pProxy1
= NULL
;
1112 IUnknown
*pProxy2
= NULL
;
1116 hr
= CreateStreamOnHGlobal(NULL
, TRUE
, &pStream
);
1117 ok_ole_success(hr
, CreateStreamOnHGlobal
);
1118 hr
= CoMarshalInterface(pStream
, &IID_IClassFactory
, (IUnknown
*)&Test_ClassFactory
, MSHCTX_INPROC
, NULL
, MSHLFLAGS_NORMAL
);
1119 ok_ole_success(hr
, CoMarshalInterface
);
1121 ok_more_than_one_lock();
1123 IStream_Seek(pStream
, ullZero
, STREAM_SEEK_SET
, NULL
);
1124 hr
= CoUnmarshalInterface(pStream
, &IID_IClassFactory
, (void **)&pProxy1
);
1125 ok_ole_success(hr
, CoUnmarshalInterface
);
1127 ok_more_than_one_lock();
1129 IStream_Seek(pStream
, ullZero
, STREAM_SEEK_SET
, NULL
);
1130 hr
= CoUnmarshalInterface(pStream
, &IID_IClassFactory
, (void **)&pProxy2
);
1131 ok(hr
== CO_E_OBJNOTCONNECTED
,
1132 "CoUnmarshalInterface should have failed with error CO_E_OBJNOTCONNECTED for double unmarshal, instead of 0x%08x\n", hr
);
1134 IStream_Release(pStream
);
1136 ok_more_than_one_lock();
1138 IUnknown_Release(pProxy1
);
1143 /* tests success case of marshaling and unmarshaling an HRESULT */
1144 static void test_hresult_marshaling(void)
1147 HRESULT hr_marshaled
= 0;
1148 IStream
*pStream
= NULL
;
1149 static const HRESULT E_DEADBEEF
= 0xdeadbeef;
1151 hr
= CreateStreamOnHGlobal(NULL
, TRUE
, &pStream
);
1152 ok_ole_success(hr
, CreateStreamOnHGlobal
);
1154 hr
= CoMarshalHresult(pStream
, E_DEADBEEF
);
1155 ok_ole_success(hr
, CoMarshalHresult
);
1157 IStream_Seek(pStream
, ullZero
, STREAM_SEEK_SET
, NULL
);
1158 hr
= IStream_Read(pStream
, &hr_marshaled
, sizeof(HRESULT
), NULL
);
1159 ok_ole_success(hr
, IStream_Read
);
1161 ok(hr_marshaled
== E_DEADBEEF
, "Didn't marshal HRESULT as expected: got value 0x%08x instead\n", hr_marshaled
);
1164 IStream_Seek(pStream
, ullZero
, STREAM_SEEK_SET
, NULL
);
1165 hr
= CoUnmarshalHresult(pStream
, &hr_marshaled
);
1166 ok_ole_success(hr
, CoUnmarshalHresult
);
1168 ok(hr_marshaled
== E_DEADBEEF
, "Didn't marshal HRESULT as expected: got value 0x%08x instead\n", hr_marshaled
);
1170 IStream_Release(pStream
);
1174 /* helper for test_proxy_used_in_wrong_thread */
1175 static DWORD CALLBACK
bad_thread_proc(LPVOID p
)
1177 IClassFactory
* cf
= (IClassFactory
*)p
;
1179 IUnknown
* proxy
= NULL
;
1181 pCoInitializeEx(NULL
, COINIT_MULTITHREADED
);
1183 hr
= IClassFactory_CreateInstance(cf
, NULL
, &IID_IUnknown
, (LPVOID
*)&proxy
);
1184 if (proxy
) IUnknown_Release(proxy
);
1185 ok(hr
== RPC_E_WRONG_THREAD
,
1186 "COM should have failed with RPC_E_WRONG_THREAD on using proxy from wrong apartment, but instead returned 0x%08x\n",
1194 /* tests failure case of a using a proxy in the wrong apartment */
1195 static void test_proxy_used_in_wrong_thread(void)
1198 IStream
*pStream
= NULL
;
1199 IUnknown
*pProxy
= NULL
;
1206 hr
= CreateStreamOnHGlobal(NULL
, TRUE
, &pStream
);
1207 ok_ole_success(hr
, CreateStreamOnHGlobal
);
1208 tid
= start_host_object(pStream
, &IID_IClassFactory
, (IUnknown
*)&Test_ClassFactory
, MSHLFLAGS_NORMAL
, &host_thread
);
1210 ok_more_than_one_lock();
1212 IStream_Seek(pStream
, ullZero
, STREAM_SEEK_SET
, NULL
);
1213 hr
= CoUnmarshalInterface(pStream
, &IID_IClassFactory
, (void **)&pProxy
);
1214 ok_ole_success(hr
, CoUnmarshalInterface
);
1215 IStream_Release(pStream
);
1217 ok_more_than_one_lock();
1219 /* create a thread that we can misbehave in */
1220 thread
= CreateThread(NULL
, 0, bad_thread_proc
, (LPVOID
)pProxy
, 0, &tid2
);
1222 WaitForSingleObject(thread
, INFINITE
);
1223 CloseHandle(thread
);
1225 IUnknown_Release(pProxy
);
1229 end_host_object(tid
, host_thread
);
1232 static HRESULT WINAPI
MessageFilter_QueryInterface(IMessageFilter
*iface
, REFIID riid
, void ** ppvObj
)
1234 if (ppvObj
== NULL
) return E_POINTER
;
1236 if (IsEqualGUID(riid
, &IID_IUnknown
) ||
1237 IsEqualGUID(riid
, &IID_IClassFactory
))
1239 *ppvObj
= (LPVOID
)iface
;
1240 IClassFactory_AddRef(iface
);
1244 return E_NOINTERFACE
;
1247 static ULONG WINAPI
MessageFilter_AddRef(IMessageFilter
*iface
)
1249 return 2; /* non-heap object */
1252 static ULONG WINAPI
MessageFilter_Release(IMessageFilter
*iface
)
1254 return 1; /* non-heap object */
1257 static DWORD WINAPI
MessageFilter_HandleInComingCall(
1258 IMessageFilter
*iface
,
1260 HTASK threadIDCaller
,
1262 LPINTERFACEINFO lpInterfaceInfo
)
1264 static int callcount
= 0;
1266 trace("HandleInComingCall\n");
1270 ret
= SERVERCALL_REJECTED
;
1273 ret
= SERVERCALL_RETRYLATER
;
1276 ret
= SERVERCALL_ISHANDLED
;
1283 static DWORD WINAPI
MessageFilter_RetryRejectedCall(
1284 IMessageFilter
*iface
,
1285 HTASK threadIDCallee
,
1289 trace("RetryRejectedCall\n");
1293 static DWORD WINAPI
MessageFilter_MessagePending(
1294 IMessageFilter
*iface
,
1295 HTASK threadIDCallee
,
1297 DWORD dwPendingType
)
1299 trace("MessagePending\n");
1300 return PENDINGMSG_WAITNOPROCESS
;
1303 static const IMessageFilterVtbl MessageFilter_Vtbl
=
1305 MessageFilter_QueryInterface
,
1306 MessageFilter_AddRef
,
1307 MessageFilter_Release
,
1308 MessageFilter_HandleInComingCall
,
1309 MessageFilter_RetryRejectedCall
,
1310 MessageFilter_MessagePending
1313 static IMessageFilter MessageFilter
= { &MessageFilter_Vtbl
};
1315 static void test_message_filter(void)
1318 IStream
*pStream
= NULL
;
1319 IClassFactory
*cf
= NULL
;
1321 IUnknown
*proxy
= NULL
;
1322 IMessageFilter
*prev_filter
= NULL
;
1327 hr
= CreateStreamOnHGlobal(NULL
, TRUE
, &pStream
);
1328 ok_ole_success(hr
, CreateStreamOnHGlobal
);
1329 tid
= start_host_object2(pStream
, &IID_IClassFactory
, (IUnknown
*)&Test_ClassFactory
, MSHLFLAGS_NORMAL
, &MessageFilter
, &thread
);
1331 ok_more_than_one_lock();
1333 IStream_Seek(pStream
, ullZero
, STREAM_SEEK_SET
, NULL
);
1334 hr
= CoUnmarshalInterface(pStream
, &IID_IClassFactory
, (void **)&cf
);
1335 ok_ole_success(hr
, CoUnmarshalInterface
);
1336 IStream_Release(pStream
);
1338 ok_more_than_one_lock();
1340 hr
= IClassFactory_CreateInstance(cf
, NULL
, &IID_IUnknown
, (LPVOID
*)&proxy
);
1341 ok(hr
== RPC_E_CALL_REJECTED
, "Call should have returned RPC_E_CALL_REJECTED, but return 0x%08x instead\n", hr
);
1342 if (proxy
) IUnknown_Release(proxy
);
1345 hr
= CoRegisterMessageFilter(&MessageFilter
, &prev_filter
);
1346 ok_ole_success(hr
, CoRegisterMessageFilter
);
1348 hr
= IClassFactory_CreateInstance(cf
, NULL
, &IID_IUnknown
, (LPVOID
*)&proxy
);
1349 ok_ole_success(hr
, IClassFactory_CreateInstance
);
1351 IUnknown_Release(proxy
);
1353 IClassFactory_Release(cf
);
1357 end_host_object(tid
, thread
);
1359 hr
= CoRegisterMessageFilter(prev_filter
, NULL
);
1360 ok_ole_success(hr
, CoRegisterMessageFilter
);
1363 /* test failure case of trying to unmarshal from bad stream */
1364 static void test_bad_marshal_stream(void)
1367 IStream
*pStream
= NULL
;
1369 hr
= CreateStreamOnHGlobal(NULL
, TRUE
, &pStream
);
1370 ok_ole_success(hr
, CreateStreamOnHGlobal
);
1371 hr
= CoMarshalInterface(pStream
, &IID_IClassFactory
, (IUnknown
*)&Test_ClassFactory
, MSHCTX_INPROC
, NULL
, MSHLFLAGS_NORMAL
);
1372 ok_ole_success(hr
, CoMarshalInterface
);
1374 ok_more_than_one_lock();
1376 /* try to read beyond end of stream */
1377 hr
= CoReleaseMarshalData(pStream
);
1378 ok(hr
== STG_E_READFAULT
, "Should have failed with STG_E_READFAULT, but returned 0x%08x instead\n", hr
);
1380 /* now release for real */
1381 IStream_Seek(pStream
, ullZero
, STREAM_SEEK_SET
, NULL
);
1382 hr
= CoReleaseMarshalData(pStream
);
1383 ok_ole_success(hr
, CoReleaseMarshalData
);
1385 IStream_Release(pStream
);
1388 /* tests that proxies implement certain interfaces */
1389 static void test_proxy_interfaces(void)
1392 IStream
*pStream
= NULL
;
1393 IUnknown
*pProxy
= NULL
;
1394 IUnknown
*pOtherUnknown
= NULL
;
1400 hr
= CreateStreamOnHGlobal(NULL
, TRUE
, &pStream
);
1401 ok_ole_success(hr
, CreateStreamOnHGlobal
);
1402 tid
= start_host_object(pStream
, &IID_IClassFactory
, (IUnknown
*)&Test_ClassFactory
, MSHLFLAGS_NORMAL
, &thread
);
1404 ok_more_than_one_lock();
1406 IStream_Seek(pStream
, ullZero
, STREAM_SEEK_SET
, NULL
);
1407 hr
= CoUnmarshalInterface(pStream
, &IID_IUnknown
, (void **)&pProxy
);
1408 ok_ole_success(hr
, CoUnmarshalInterface
);
1409 IStream_Release(pStream
);
1411 ok_more_than_one_lock();
1413 hr
= IUnknown_QueryInterface(pProxy
, &IID_IUnknown
, (LPVOID
*)&pOtherUnknown
);
1414 ok_ole_success(hr
, IUnknown_QueryInterface IID_IUnknown
);
1415 if (hr
== S_OK
) IUnknown_Release(pOtherUnknown
);
1417 hr
= IUnknown_QueryInterface(pProxy
, &IID_IClientSecurity
, (LPVOID
*)&pOtherUnknown
);
1418 ok_ole_success(hr
, IUnknown_QueryInterface IID_IClientSecurity
);
1419 if (hr
== S_OK
) IUnknown_Release(pOtherUnknown
);
1421 hr
= IUnknown_QueryInterface(pProxy
, &IID_IMultiQI
, (LPVOID
*)&pOtherUnknown
);
1422 ok_ole_success(hr
, IUnknown_QueryInterface IID_IMultiQI
);
1423 if (hr
== S_OK
) IUnknown_Release(pOtherUnknown
);
1425 hr
= IUnknown_QueryInterface(pProxy
, &IID_IMarshal
, (LPVOID
*)&pOtherUnknown
);
1426 ok_ole_success(hr
, IUnknown_QueryInterface IID_IMarshal
);
1427 if (hr
== S_OK
) IUnknown_Release(pOtherUnknown
);
1429 /* IMarshal2 is also supported on NT-based systems, but is pretty much
1430 * useless as it has no more methods over IMarshal that it inherits from. */
1432 IUnknown_Release(pProxy
);
1436 end_host_object(tid
, thread
);
1441 const IUnknownVtbl
*lpVtbl
;
1445 static HRESULT WINAPI
HeapUnknown_QueryInterface(IUnknown
*iface
, REFIID riid
, void **ppv
)
1447 if (IsEqualIID(riid
, &IID_IUnknown
))
1449 IUnknown_AddRef(iface
);
1450 *ppv
= (LPVOID
)iface
;
1454 return E_NOINTERFACE
;
1457 static ULONG WINAPI
HeapUnknown_AddRef(IUnknown
*iface
)
1459 HeapUnknown
*This
= (HeapUnknown
*)iface
;
1460 return InterlockedIncrement((LONG
*)&This
->refs
);
1463 static ULONG WINAPI
HeapUnknown_Release(IUnknown
*iface
)
1465 HeapUnknown
*This
= (HeapUnknown
*)iface
;
1466 ULONG refs
= InterlockedDecrement((LONG
*)&This
->refs
);
1467 if (!refs
) HeapFree(GetProcessHeap(), 0, This
);
1471 static const IUnknownVtbl HeapUnknown_Vtbl
=
1473 HeapUnknown_QueryInterface
,
1478 static void test_proxybuffer(REFIID riid
)
1481 IPSFactoryBuffer
*psfb
;
1482 IRpcProxyBuffer
*proxy
;
1486 HeapUnknown
*pUnkOuter
= (HeapUnknown
*)HeapAlloc(GetProcessHeap(), 0, sizeof(*pUnkOuter
));
1488 pUnkOuter
->lpVtbl
= &HeapUnknown_Vtbl
;
1489 pUnkOuter
->refs
= 1;
1491 hr
= CoGetPSClsid(riid
, &clsid
);
1492 ok_ole_success(hr
, CoGetPSClsid
);
1494 hr
= CoGetClassObject(&clsid
, CLSCTX_INPROC_SERVER
, NULL
, &IID_IPSFactoryBuffer
, (LPVOID
*)&psfb
);
1495 ok_ole_success(hr
, CoGetClassObject
);
1497 hr
= IPSFactoryBuffer_CreateProxy(psfb
, (IUnknown
*)pUnkOuter
, riid
, &proxy
, &lpvtbl
);
1498 ok_ole_success(hr
, IPSFactoryBuffer_CreateProxy
);
1499 ok(lpvtbl
!= NULL
, "IPSFactoryBuffer_CreateProxy succeeded, but returned a NULL vtable!\n");
1501 /* release our reference to the outer unknown object - the PS factory
1502 * buffer will have AddRef's it in the CreateProxy call */
1503 refs
= IUnknown_Release((IUnknown
*)pUnkOuter
);
1504 ok(refs
== 1, "Ref count of outer unknown should have been 1 instead of %d\n", refs
);
1506 refs
= IPSFactoryBuffer_Release(psfb
);
1509 /* not reliable on native. maybe it leaks references! */
1510 ok(refs
== 0, "Ref-count leak of %d on IPSFactoryBuffer\n", refs
);
1513 refs
= IUnknown_Release((IUnknown
*)lpvtbl
);
1514 ok(refs
== 0, "Ref-count leak of %d on IRpcProxyBuffer\n", refs
);
1516 refs
= IRpcProxyBuffer_Release(proxy
);
1517 ok(refs
== 0, "Ref-count leak of %d on IRpcProxyBuffer\n", refs
);
1520 static void test_stubbuffer(REFIID riid
)
1523 IPSFactoryBuffer
*psfb
;
1524 IRpcStubBuffer
*stub
;
1530 hr
= CoGetPSClsid(riid
, &clsid
);
1531 ok_ole_success(hr
, CoGetPSClsid
);
1533 hr
= CoGetClassObject(&clsid
, CLSCTX_INPROC_SERVER
, NULL
, &IID_IPSFactoryBuffer
, (LPVOID
*)&psfb
);
1534 ok_ole_success(hr
, CoGetClassObject
);
1536 hr
= IPSFactoryBuffer_CreateStub(psfb
, riid
, (IUnknown
*)&Test_ClassFactory
, &stub
);
1537 ok_ole_success(hr
, IPSFactoryBuffer_CreateStub
);
1539 refs
= IPSFactoryBuffer_Release(psfb
);
1542 /* not reliable on native. maybe it leaks references */
1543 ok(refs
== 0, "Ref-count leak of %d on IPSFactoryBuffer\n", refs
);
1546 ok_more_than_one_lock();
1548 IRpcStubBuffer_Disconnect(stub
);
1552 refs
= IRpcStubBuffer_Release(stub
);
1553 ok(refs
== 0, "Ref-count leak of %d on IRpcProxyBuffer\n", refs
);
1556 static HWND hwnd_app
;
1558 static HRESULT WINAPI
TestRE_IClassFactory_CreateInstance(
1559 LPCLASSFACTORY iface
,
1560 LPUNKNOWN pUnkOuter
,
1565 if (IsEqualIID(riid
, &IID_IWineTest
))
1567 BOOL ret
= SendMessageTimeout(hwnd_app
, WM_NULL
, 0, 0, SMTO_BLOCK
, 5000, &res
);
1568 ok(ret
, "Timed out sending a message to originating window during RPC call\n");
1573 static const IClassFactoryVtbl TestREClassFactory_Vtbl
=
1575 Test_IClassFactory_QueryInterface
,
1576 Test_IClassFactory_AddRef
,
1577 Test_IClassFactory_Release
,
1578 TestRE_IClassFactory_CreateInstance
,
1579 Test_IClassFactory_LockServer
1582 IClassFactory TestRE_ClassFactory
= { &TestREClassFactory_Vtbl
};
1584 static LRESULT CALLBACK
window_proc(HWND hwnd
, UINT msg
, WPARAM wparam
, LPARAM lparam
)
1591 IStream
*pStream
= NULL
;
1592 IClassFactory
*proxy
= NULL
;
1599 hr
= CreateStreamOnHGlobal(NULL
, TRUE
, &pStream
);
1600 ok_ole_success(hr
, CreateStreamOnHGlobal
);
1601 tid
= start_host_object(pStream
, &IID_IClassFactory
, (IUnknown
*)&TestRE_ClassFactory
, MSHLFLAGS_NORMAL
, &thread
);
1603 ok_more_than_one_lock();
1605 IStream_Seek(pStream
, ullZero
, STREAM_SEEK_SET
, NULL
);
1606 hr
= CoUnmarshalInterface(pStream
, &IID_IClassFactory
, (void **)&proxy
);
1607 ok_ole_success(hr
, CoReleaseMarshalData
);
1608 IStream_Release(pStream
);
1610 ok_more_than_one_lock();
1612 /* note the use of the magic IID_IWineTest value to tell remote thread
1613 * to try to send a message back to us */
1614 hr
= IClassFactory_CreateInstance(proxy
, NULL
, &IID_IWineTest
, (void **)&object
);
1616 IClassFactory_Release(proxy
);
1620 end_host_object(tid
, thread
);
1622 PostMessage(hwnd
, WM_QUIT
, 0, 0);
1629 IStream
*pStream
= NULL
;
1630 IClassFactory
*proxy
= NULL
;
1637 hr
= CreateStreamOnHGlobal(NULL
, TRUE
, &pStream
);
1638 ok_ole_success(hr
, CreateStreamOnHGlobal
);
1639 tid
= start_host_object(pStream
, &IID_IClassFactory
, (IUnknown
*)&TestRE_ClassFactory
, MSHLFLAGS_NORMAL
, &thread
);
1641 ok_more_than_one_lock();
1643 IStream_Seek(pStream
, ullZero
, STREAM_SEEK_SET
, NULL
);
1644 hr
= CoUnmarshalInterface(pStream
, &IID_IClassFactory
, (void **)&proxy
);
1645 ok_ole_success(hr
, CoReleaseMarshalData
);
1646 IStream_Release(pStream
);
1648 ok_more_than_one_lock();
1650 /* post quit message before a doing a COM call to show that a pending
1651 * WM_QUIT message doesn't stop the call from succeeding */
1652 PostMessage(hwnd
, WM_QUIT
, 0, 0);
1653 hr
= IClassFactory_CreateInstance(proxy
, NULL
, &IID_IUnknown
, (void **)&object
);
1655 IClassFactory_Release(proxy
);
1659 end_host_object(tid
, thread
);
1666 IStream
*pStream
= NULL
;
1667 IClassFactory
*proxy
= NULL
;
1672 hr
= CreateStreamOnHGlobal(NULL
, TRUE
, &pStream
);
1673 ok_ole_success(hr
, CreateStreamOnHGlobal
);
1674 tid
= start_host_object(pStream
, &IID_IClassFactory
, (IUnknown
*)&Test_ClassFactory
, MSHLFLAGS_NORMAL
, &thread
);
1676 IStream_Seek(pStream
, ullZero
, STREAM_SEEK_SET
, NULL
);
1677 hr
= CoUnmarshalInterface(pStream
, &IID_IClassFactory
, (void **)&proxy
);
1678 ok_ole_success(hr
, CoReleaseMarshalData
);
1679 IStream_Release(pStream
);
1681 /* shows that COM calls executed during the processing of sent
1682 * messages should fail */
1683 hr
= IClassFactory_CreateInstance(proxy
, NULL
, &IID_IUnknown
, (void **)&object
);
1684 ok(hr
== RPC_E_CANTCALLOUT_ININPUTSYNCCALL
,
1685 "COM call during processing of sent message should return RPC_E_CANTCALLOUT_ININPUTSYNCCALL instead of 0x%08x\n", hr
);
1687 IClassFactory_Release(proxy
);
1689 end_host_object(tid
, thread
);
1696 return DefWindowProc(hwnd
, msg
, wparam
, lparam
);
1700 static void test_message_reentrancy(void)
1705 memset(&wndclass
, 0, sizeof(wndclass
));
1706 wndclass
.lpfnWndProc
= window_proc
;
1707 wndclass
.lpszClassName
= "WineCOMTest";
1708 RegisterClass(&wndclass
);
1710 hwnd_app
= CreateWindow("WineCOMTest", NULL
, 0, CW_USEDEFAULT
, CW_USEDEFAULT
, CW_USEDEFAULT
, CW_USEDEFAULT
, NULL
, NULL
, NULL
, 0);
1711 ok(hwnd_app
!= NULL
, "Window creation failed\n");
1713 /* start message re-entrancy test */
1714 PostMessage(hwnd_app
, WM_USER
, 0, 0);
1716 while (GetMessage(&msg
, NULL
, 0, 0))
1718 TranslateMessage(&msg
);
1719 DispatchMessage(&msg
);
1723 static HRESULT WINAPI
TestMsg_IClassFactory_CreateInstance(
1724 LPCLASSFACTORY iface
,
1725 LPUNKNOWN pUnkOuter
,
1730 SendMessage(hwnd_app
, WM_USER
+2, 0, 0);
1734 static IClassFactoryVtbl TestMsgClassFactory_Vtbl
=
1736 Test_IClassFactory_QueryInterface
,
1737 Test_IClassFactory_AddRef
,
1738 Test_IClassFactory_Release
,
1739 TestMsg_IClassFactory_CreateInstance
,
1740 Test_IClassFactory_LockServer
1743 IClassFactory TestMsg_ClassFactory
= { &TestMsgClassFactory_Vtbl
};
1745 static void test_call_from_message(void)
1750 IClassFactory
*proxy
;
1755 hwnd_app
= CreateWindow("WineCOMTest", NULL
, 0, CW_USEDEFAULT
, CW_USEDEFAULT
, CW_USEDEFAULT
, CW_USEDEFAULT
, NULL
, NULL
, NULL
, 0);
1756 ok(hwnd_app
!= NULL
, "Window creation failed\n");
1758 hr
= CreateStreamOnHGlobal(NULL
, TRUE
, &pStream
);
1759 ok_ole_success(hr
, CreateStreamOnHGlobal
);
1760 tid
= start_host_object(pStream
, &IID_IClassFactory
, (IUnknown
*)&TestMsg_ClassFactory
, MSHLFLAGS_NORMAL
, &thread
);
1762 ok_more_than_one_lock();
1764 IStream_Seek(pStream
, ullZero
, STREAM_SEEK_SET
, NULL
);
1765 hr
= CoUnmarshalInterface(pStream
, &IID_IClassFactory
, (void **)&proxy
);
1766 ok_ole_success(hr
, CoReleaseMarshalData
);
1767 IStream_Release(pStream
);
1769 ok_more_than_one_lock();
1771 /* start message re-entrancy test */
1772 hr
= IClassFactory_CreateInstance(proxy
, NULL
, &IID_IUnknown
, (void **)&object
);
1773 ok_ole_success(hr
, IClassFactory_CreateInstance
);
1775 IClassFactory_Release(proxy
);
1779 end_host_object(tid
, thread
);
1781 while (GetMessage(&msg
, NULL
, 0, 0))
1783 TranslateMessage(&msg
);
1784 DispatchMessage(&msg
);
1788 static void test_WM_QUIT_handling(void)
1792 hwnd_app
= CreateWindow("WineCOMTest", NULL
, 0, CW_USEDEFAULT
, CW_USEDEFAULT
, CW_USEDEFAULT
, CW_USEDEFAULT
, NULL
, NULL
, NULL
, 0);
1793 ok(hwnd_app
!= NULL
, "Window creation failed\n");
1795 /* start WM_QUIT handling test */
1796 PostMessage(hwnd_app
, WM_USER
+1, 0, 0);
1798 while (GetMessage(&msg
, NULL
, 0, 0))
1800 TranslateMessage(&msg
);
1801 DispatchMessage(&msg
);
1805 static void test_freethreadedmarshaldata(IStream
*pStream
, MSHCTX mshctx
, void *ptr
, DWORD mshlflags
)
1812 hr
= GetHGlobalFromStream(pStream
, &hglobal
);
1813 ok_ole_success(hr
, GetHGlobalFromStream
);
1815 size
= GlobalSize(hglobal
);
1817 marshal_data
= (char *)GlobalLock(hglobal
);
1819 if (mshctx
== MSHCTX_INPROC
)
1821 DWORD expected_size
= sizeof(DWORD
) + sizeof(void *) + sizeof(DWORD
) + sizeof(GUID
);
1822 ok(size
== expected_size
, "size should have been %d instead of %d\n", expected_size
, size
);
1824 ok(*(DWORD
*)marshal_data
== mshlflags
, "expected 0x%x, but got 0x%x for mshctx\n", mshlflags
, *(DWORD
*)marshal_data
);
1825 marshal_data
+= sizeof(DWORD
);
1826 ok(*(void **)marshal_data
== ptr
, "expected %p, but got %p for mshctx\n", ptr
, *(void **)marshal_data
);
1827 marshal_data
+= sizeof(void *);
1828 ok(*(DWORD
*)marshal_data
== 0, "expected 0x0, but got 0x%x\n", *(DWORD
*)marshal_data
);
1829 marshal_data
+= sizeof(DWORD
);
1830 trace("got guid data: {%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x}\n",
1831 ((GUID
*)marshal_data
)->Data1
, ((GUID
*)marshal_data
)->Data2
, ((GUID
*)marshal_data
)->Data3
,
1832 ((GUID
*)marshal_data
)->Data4
[0], ((GUID
*)marshal_data
)->Data4
[1], ((GUID
*)marshal_data
)->Data4
[2], ((GUID
*)marshal_data
)->Data4
[3],
1833 ((GUID
*)marshal_data
)->Data4
[4], ((GUID
*)marshal_data
)->Data4
[5], ((GUID
*)marshal_data
)->Data4
[6], ((GUID
*)marshal_data
)->Data4
[7]);
1837 ok(size
> sizeof(DWORD
), "size should have been > sizeof(DWORD), not %d\n", size
);
1838 ok(*(DWORD
*)marshal_data
== 0x574f454d /* MEOW */,
1839 "marshal data should be filled by standard marshal and start with MEOW signature\n");
1842 GlobalUnlock(hglobal
);
1845 static void test_freethreadedmarshaler(void)
1848 IUnknown
*pFTUnknown
;
1849 IMarshal
*pFTMarshal
;
1852 static const LARGE_INTEGER llZero
;
1855 hr
= CoCreateFreeThreadedMarshaler(NULL
, &pFTUnknown
);
1856 ok_ole_success(hr
, CoCreateFreeThreadedMarshaler
);
1857 hr
= IUnknown_QueryInterface(pFTUnknown
, &IID_IMarshal
, (void **)&pFTMarshal
);
1858 ok_ole_success(hr
, IUnknown_QueryInterface
);
1859 IUnknown_Release(pFTUnknown
);
1861 hr
= CreateStreamOnHGlobal(NULL
, TRUE
, &pStream
);
1862 ok_ole_success(hr
, CreateStreamOnHGlobal
);
1864 /* inproc normal marshaling */
1866 hr
= IMarshal_MarshalInterface(pFTMarshal
, pStream
, &IID_IClassFactory
,
1867 (IUnknown
*)&Test_ClassFactory
, MSHCTX_INPROC
, NULL
, MSHLFLAGS_NORMAL
);
1868 ok_ole_success(hr
, IMarshal_MarshalInterface
);
1870 ok_more_than_one_lock();
1872 test_freethreadedmarshaldata(pStream
, MSHCTX_INPROC
, &Test_ClassFactory
, MSHLFLAGS_NORMAL
);
1874 IStream_Seek(pStream
, llZero
, STREAM_SEEK_SET
, NULL
);
1875 hr
= IMarshal_UnmarshalInterface(pFTMarshal
, pStream
, &IID_IUnknown
, (void **)&pProxy
);
1876 ok_ole_success(hr
, IMarshal_UnmarshalInterface
);
1878 IUnknown_Release(pProxy
);
1882 /* native doesn't allow us to unmarshal or release the stream data,
1883 * presumably because it wants us to call CoMarshalInterface instead */
1886 /* local normal marshaling */
1888 IStream_Seek(pStream
, llZero
, STREAM_SEEK_SET
, NULL
);
1889 hr
= IMarshal_MarshalInterface(pFTMarshal
, pStream
, &IID_IClassFactory
, (IUnknown
*)&Test_ClassFactory
, MSHCTX_LOCAL
, NULL
, MSHLFLAGS_NORMAL
);
1890 ok_ole_success(hr
, IMarshal_MarshalInterface
);
1892 ok_more_than_one_lock();
1894 test_freethreadedmarshaldata(pStream
, MSHCTX_LOCAL
, &Test_ClassFactory
, MSHLFLAGS_NORMAL
);
1896 IStream_Seek(pStream
, llZero
, STREAM_SEEK_SET
, NULL
);
1897 hr
= IMarshal_ReleaseMarshalData(pFTMarshal
, pStream
);
1898 ok_ole_success(hr
, IMarshal_ReleaseMarshalData
);
1903 /* inproc table-strong marshaling */
1905 IStream_Seek(pStream
, llZero
, STREAM_SEEK_SET
, NULL
);
1906 hr
= IMarshal_MarshalInterface(pFTMarshal
, pStream
, &IID_IClassFactory
,
1907 (IUnknown
*)&Test_ClassFactory
, MSHCTX_INPROC
, (void *)0xdeadbeef,
1908 MSHLFLAGS_TABLESTRONG
);
1909 ok_ole_success(hr
, IMarshal_MarshalInterface
);
1911 ok_more_than_one_lock();
1913 test_freethreadedmarshaldata(pStream
, MSHCTX_INPROC
, &Test_ClassFactory
, MSHLFLAGS_TABLESTRONG
);
1915 IStream_Seek(pStream
, llZero
, STREAM_SEEK_SET
, NULL
);
1916 hr
= IMarshal_UnmarshalInterface(pFTMarshal
, pStream
, &IID_IUnknown
, (void **)&pProxy
);
1917 ok_ole_success(hr
, IMarshal_UnmarshalInterface
);
1919 IUnknown_Release(pProxy
);
1921 ok_more_than_one_lock();
1923 IStream_Seek(pStream
, llZero
, STREAM_SEEK_SET
, NULL
);
1924 hr
= IMarshal_ReleaseMarshalData(pFTMarshal
, pStream
);
1925 ok_ole_success(hr
, IMarshal_ReleaseMarshalData
);
1929 /* inproc table-weak marshaling */
1931 IStream_Seek(pStream
, llZero
, STREAM_SEEK_SET
, NULL
);
1932 hr
= IMarshal_MarshalInterface(pFTMarshal
, pStream
, &IID_IClassFactory
,
1933 (IUnknown
*)&Test_ClassFactory
, MSHCTX_INPROC
, (void *)0xdeadbeef,
1934 MSHLFLAGS_TABLEWEAK
);
1935 ok_ole_success(hr
, IMarshal_MarshalInterface
);
1939 test_freethreadedmarshaldata(pStream
, MSHCTX_INPROC
, &Test_ClassFactory
, MSHLFLAGS_TABLEWEAK
);
1941 IStream_Seek(pStream
, llZero
, STREAM_SEEK_SET
, NULL
);
1942 hr
= IMarshal_UnmarshalInterface(pFTMarshal
, pStream
, &IID_IUnknown
, (void **)&pProxy
);
1943 ok_ole_success(hr
, IMarshal_UnmarshalInterface
);
1945 ok_more_than_one_lock();
1947 IUnknown_Release(pProxy
);
1951 /* inproc normal marshaling (for extraordinary cases) */
1953 IStream_Seek(pStream
, llZero
, STREAM_SEEK_SET
, NULL
);
1954 hr
= IMarshal_MarshalInterface(pFTMarshal
, pStream
, &IID_IClassFactory
,
1955 (IUnknown
*)&Test_ClassFactory
, MSHCTX_INPROC
, NULL
, MSHLFLAGS_NORMAL
);
1956 ok_ole_success(hr
, IMarshal_MarshalInterface
);
1958 ok_more_than_one_lock();
1960 /* this call shows that DisconnectObject does nothing */
1961 hr
= IMarshal_DisconnectObject(pFTMarshal
, 0);
1962 ok_ole_success(hr
, IMarshal_DisconnectObject
);
1964 ok_more_than_one_lock();
1966 IStream_Seek(pStream
, llZero
, STREAM_SEEK_SET
, NULL
);
1967 hr
= IMarshal_ReleaseMarshalData(pFTMarshal
, pStream
);
1968 ok_ole_success(hr
, IMarshal_ReleaseMarshalData
);
1972 /* doesn't enforce marshaling rules here and allows us to unmarshal the
1973 * interface, even though it was freed above */
1974 IStream_Seek(pStream
, llZero
, STREAM_SEEK_SET
, NULL
);
1975 hr
= IMarshal_UnmarshalInterface(pFTMarshal
, pStream
, &IID_IUnknown
, (void **)&pProxy
);
1976 ok_ole_success(hr
, IMarshal_UnmarshalInterface
);
1980 IStream_Release(pStream
);
1981 IMarshal_Release(pFTMarshal
);
1984 static void test_inproc_handler(void)
1992 DWORD dwDisposition
;
1995 hr
= StringFromCLSID(&CLSID_WineTest
, &pszClsid
);
1996 ok_ole_success(hr
, "StringFromCLSID");
1997 strcpy(buffer
, "CLSID\\");
1998 WideCharToMultiByte(CP_ACP
, 0, pszClsid
, -1, buffer
+ strlen(buffer
), sizeof(buffer
) - strlen(buffer
), NULL
, NULL
);
1999 CoTaskMemFree(pszClsid
);
2000 strcat(buffer
, "\\InprocHandler32");
2001 error
= RegCreateKeyEx(HKEY_CLASSES_ROOT
, buffer
, 0, NULL
, 0, KEY_SET_VALUE
, NULL
, &hkey
, &dwDisposition
);
2002 ok(error
== ERROR_SUCCESS
, "RegCreateKeyEx failed with error %d\n", error
);
2003 error
= RegSetValueEx(hkey
, NULL
, 0, REG_SZ
, (const unsigned char *)"ole32.dll", strlen("ole32.dll") + 1);
2004 ok(error
== ERROR_SUCCESS
, "RegSetValueEx failed with error %d\n", error
);
2007 hr
= CoCreateInstance(&CLSID_WineTest
, NULL
, CLSCTX_INPROC_HANDLER
, &IID_IUnknown
, (void **)&pObject
);
2009 ok_ole_success(hr
, "CoCreateInstance");
2013 hr
= IUnknown_QueryInterface(pObject
, &IID_IWineTest
, (void **)&pObject2
);
2014 ok(hr
== E_NOINTERFACE
, "IUnknown_QueryInterface on handler for invalid interface returned 0x%08x instead of E_NOINTERFACE\n", hr
);
2016 /* it's a handler as it supports IOleObject */
2017 hr
= IUnknown_QueryInterface(pObject
, &IID_IOleObject
, (void **)&pObject2
);
2018 ok_ole_success(hr
, "IUnknown_QueryInterface(&IID_IOleObject)");
2019 IUnknown_Release(pObject2
);
2021 IUnknown_Release(pObject
);
2024 RegDeleteKey(HKEY_CLASSES_ROOT
, buffer
);
2025 *strrchr(buffer
, '\\') = '\0';
2026 RegDeleteKey(HKEY_CLASSES_ROOT
, buffer
);
2029 static HRESULT WINAPI
Test_SMI_QueryInterface(
2030 IStdMarshalInfo
*iface
,
2034 if (ppvObj
== NULL
) return E_POINTER
;
2036 if (IsEqualGUID(riid
, &IID_IUnknown
) ||
2037 IsEqualGUID(riid
, &IID_IStdMarshalInfo
))
2039 *ppvObj
= (LPVOID
)iface
;
2040 IClassFactory_AddRef(iface
);
2044 return E_NOINTERFACE
;
2047 static ULONG WINAPI
Test_SMI_AddRef(IStdMarshalInfo
*iface
)
2050 return 2; /* non-heap-based object */
2053 static ULONG WINAPI
Test_SMI_Release(IStdMarshalInfo
*iface
)
2056 return 1; /* non-heap-based object */
2059 static HRESULT WINAPI
Test_SMI_GetClassForHandler(
2060 IStdMarshalInfo
*iface
,
2061 DWORD dwDestContext
,
2062 void *pvDestContext
,
2065 *pClsid
= CLSID_WineTest
;
2069 static const IStdMarshalInfoVtbl Test_SMI_Vtbl
=
2071 Test_SMI_QueryInterface
,
2074 Test_SMI_GetClassForHandler
2077 static IStdMarshalInfo Test_SMI
= {&Test_SMI_Vtbl
};
2079 static void test_handler_marshaling(void)
2082 IStream
*pStream
= NULL
;
2083 IUnknown
*pProxy
= NULL
;
2087 static const LARGE_INTEGER ullZero
;
2091 hr
= CreateStreamOnHGlobal(NULL
, TRUE
, &pStream
);
2092 ok_ole_success(hr
, "CreateStreamOnHGlobal");
2093 tid
= start_host_object(pStream
, &IID_IUnknown
, (IUnknown
*)&Test_SMI
, MSHLFLAGS_NORMAL
, &thread
);
2095 ok_more_than_one_lock();
2097 IStream_Seek(pStream
, ullZero
, STREAM_SEEK_SET
, NULL
);
2098 hr
= CoUnmarshalInterface(pStream
, &IID_IUnknown
, (void **)&pProxy
);
2099 ok_ole_success(hr
, "CoUnmarshalInterface");
2100 IStream_Release(pStream
);
2102 ok_more_than_one_lock();
2104 hr
= IUnknown_QueryInterface(pProxy
, &IID_IWineTest
, (void **)&pObject
);
2105 ok(hr
== E_NOINTERFACE
, "IUnknown_QueryInterface with unknown IID should have returned E_NOINTERFACE instead of 0x%08x\n", hr
);
2107 /* it's a handler as it supports IOleObject */
2108 hr
= IUnknown_QueryInterface(pProxy
, &IID_IOleObject
, (void **)&pObject
);
2110 ok_ole_success(hr
, "IUnknown_QueryInterface(&IID_IOleObject)");
2111 if (SUCCEEDED(hr
)) IUnknown_Release(pObject
);
2113 IUnknown_Release(pProxy
);
2117 end_host_object(tid
, thread
);
2119 /* FIXME: test IPersist interface has the same effect as IStdMarshalInfo */
2123 static void test_client_security(void)
2126 IStream
*pStream
= NULL
;
2127 IClassFactory
*pProxy
= NULL
;
2128 IUnknown
*pProxy2
= NULL
;
2129 IUnknown
*pUnknown1
= NULL
;
2130 IUnknown
*pUnknown2
= NULL
;
2131 IClientSecurity
*pCliSec
= NULL
;
2135 static const LARGE_INTEGER ullZero
;
2138 OLECHAR
*pServerPrincName
;
2142 DWORD dwCapabilities
;
2147 hr
= CreateStreamOnHGlobal(NULL
, TRUE
, &pStream
);
2148 ok_ole_success(hr
, "CreateStreamOnHGlobal");
2149 tid
= start_host_object(pStream
, &IID_IClassFactory
, (IUnknown
*)&Test_ClassFactory
, MSHLFLAGS_NORMAL
, &thread
);
2151 IStream_Seek(pStream
, ullZero
, STREAM_SEEK_SET
, NULL
);
2152 hr
= CoUnmarshalInterface(pStream
, &IID_IClassFactory
, (void **)&pProxy
);
2153 ok_ole_success(hr
, "CoUnmarshalInterface");
2154 IStream_Release(pStream
);
2156 hr
= IUnknown_QueryInterface(pProxy
, &IID_IUnknown
, (LPVOID
*)&pUnknown1
);
2157 ok_ole_success(hr
, "IUnknown_QueryInterface IID_IUnknown");
2159 hr
= IUnknown_QueryInterface(pProxy
, &IID_IRemUnknown
, (LPVOID
*)&pProxy2
);
2160 ok_ole_success(hr
, "IUnknown_QueryInterface IID_IStream");
2162 hr
= IUnknown_QueryInterface(pProxy2
, &IID_IUnknown
, (LPVOID
*)&pUnknown2
);
2163 ok_ole_success(hr
, "IUnknown_QueryInterface IID_IUnknown");
2165 ok(pUnknown1
== pUnknown2
, "both proxy's IUnknowns should be the same - %p, %p\n", pUnknown1
, pUnknown2
);
2167 hr
= IUnknown_QueryInterface(pProxy
, &IID_IMarshal
, (LPVOID
*)&pMarshal
);
2168 ok_ole_success(hr
, "IUnknown_QueryInterface IID_IMarshal");
2170 hr
= IUnknown_QueryInterface(pProxy
, &IID_IClientSecurity
, (LPVOID
*)&pCliSec
);
2171 ok_ole_success(hr
, "IUnknown_QueryInterface IID_IClientSecurity");
2173 hr
= IClientSecurity_QueryBlanket(pCliSec
, (IUnknown
*)pProxy
, NULL
, NULL
, NULL
, NULL
, NULL
, NULL
, NULL
);
2174 todo_wine
ok_ole_success(hr
, "IClientSecurity_QueryBlanket (all NULLs)");
2176 hr
= IClientSecurity_QueryBlanket(pCliSec
, (IUnknown
*)pMarshal
, NULL
, NULL
, NULL
, NULL
, NULL
, NULL
, NULL
);
2177 todo_wine
ok(hr
== E_NOINTERFACE
, "IClientSecurity_QueryBlanket with local interface should have returned E_NOINTERFACE instead of 0x%08x\n", hr
);
2179 hr
= IClientSecurity_QueryBlanket(pCliSec
, (IUnknown
*)pProxy
, &dwAuthnSvc
, &dwAuthzSvc
, &pServerPrincName
, &dwAuthnLevel
, &dwImpLevel
, &pAuthInfo
, &dwCapabilities
);
2180 todo_wine
ok_ole_success(hr
, "IClientSecurity_QueryBlanket");
2182 hr
= IClientSecurity_SetBlanket(pCliSec
, (IUnknown
*)pProxy
, dwAuthnSvc
, dwAuthzSvc
, pServerPrincName
, dwAuthnLevel
, RPC_C_IMP_LEVEL_IMPERSONATE
, pAuthInfo
, dwCapabilities
);
2183 todo_wine
ok_ole_success(hr
, "IClientSecurity_SetBlanket");
2185 hr
= IClassFactory_CreateInstance(pProxy
, NULL
, &IID_IWineTest
, &pv
);
2186 ok(hr
== E_NOINTERFACE
, "COM call should have succeeded instead of returning 0x%08x\n", hr
);
2188 hr
= IClientSecurity_SetBlanket(pCliSec
, (IUnknown
*)pMarshal
, dwAuthnSvc
, dwAuthzSvc
, pServerPrincName
, dwAuthnLevel
, dwImpLevel
, pAuthInfo
, dwCapabilities
);
2189 todo_wine
ok(hr
== E_NOINTERFACE
, "IClientSecurity_SetBlanket with local interface should have returned E_NOINTERFACE instead of 0x%08x\n", hr
);
2191 hr
= IClientSecurity_SetBlanket(pCliSec
, (IUnknown
*)pProxy
, 0xdeadbeef, dwAuthzSvc
, pServerPrincName
, dwAuthnLevel
, dwImpLevel
, pAuthInfo
, dwCapabilities
);
2192 todo_wine
ok(hr
== E_INVALIDARG
, "IClientSecurity_SetBlanke with invalid dwAuthnSvc should have returned E_INVALIDARG instead of 0x%08x\n", hr
);
2194 CoTaskMemFree(pServerPrincName
);
2196 hr
= IClientSecurity_QueryBlanket(pCliSec
, (IUnknown
*)pUnknown1
, &dwAuthnSvc
, &dwAuthzSvc
, &pServerPrincName
, &dwAuthnLevel
, &dwImpLevel
, &pAuthInfo
, &dwCapabilities
);
2197 todo_wine
ok_ole_success(hr
, "IClientSecurity_QueryBlanket(IUnknown)");
2199 CoTaskMemFree(pServerPrincName
);
2201 IClassFactory_Release(pProxy
);
2202 IUnknown_Release(pProxy2
);
2203 IUnknown_Release(pUnknown1
);
2204 IUnknown_Release(pUnknown2
);
2205 IMarshal_Release(pMarshal
);
2206 IClientSecurity_Release(pCliSec
);
2208 end_host_object(tid
, thread
);
2211 static HANDLE heventShutdown
;
2213 static void LockModuleOOP(void)
2215 InterlockedIncrement(&cLocks
); /* for test purposes only */
2216 CoAddRefServerProcess();
2219 static void UnlockModuleOOP(void)
2221 InterlockedDecrement(&cLocks
); /* for test purposes only */
2222 if (!CoReleaseServerProcess())
2223 SetEvent(heventShutdown
);
2226 static HWND hwnd_app
;
2228 static HRESULT WINAPI
TestOOP_IClassFactory_QueryInterface(
2229 LPCLASSFACTORY iface
,
2233 if (ppvObj
== NULL
) return E_POINTER
;
2235 if (IsEqualGUID(riid
, &IID_IUnknown
) ||
2236 IsEqualGUID(riid
, &IID_IClassFactory
))
2238 *ppvObj
= (LPVOID
)iface
;
2239 IClassFactory_AddRef(iface
);
2243 return E_NOINTERFACE
;
2246 static ULONG WINAPI
TestOOP_IClassFactory_AddRef(LPCLASSFACTORY iface
)
2248 return 2; /* non-heap-based object */
2251 static ULONG WINAPI
TestOOP_IClassFactory_Release(LPCLASSFACTORY iface
)
2253 return 1; /* non-heap-based object */
2256 static HRESULT WINAPI
TestOOP_IClassFactory_CreateInstance(
2257 LPCLASSFACTORY iface
,
2258 LPUNKNOWN pUnkOuter
,
2262 if (IsEqualIID(riid
, &IID_IClassFactory
) || IsEqualIID(riid
, &IID_IUnknown
))
2267 return CLASS_E_CLASSNOTAVAILABLE
;
2270 static HRESULT WINAPI
TestOOP_IClassFactory_LockServer(
2271 LPCLASSFACTORY iface
,
2281 static const IClassFactoryVtbl TestClassFactoryOOP_Vtbl
=
2283 TestOOP_IClassFactory_QueryInterface
,
2284 TestOOP_IClassFactory_AddRef
,
2285 TestOOP_IClassFactory_Release
,
2286 TestOOP_IClassFactory_CreateInstance
,
2287 TestOOP_IClassFactory_LockServer
2290 static IClassFactory TestOOP_ClassFactory
= { &TestClassFactoryOOP_Vtbl
};
2292 static void test_register_local_server(void)
2300 heventShutdown
= CreateEvent(NULL
, TRUE
, FALSE
, NULL
);
2302 hr
= CoRegisterClassObject(&CLSID_WineOOPTest
, (IUnknown
*)&TestOOP_ClassFactory
,
2303 CLSCTX_LOCAL_SERVER
, REGCLS_SINGLEUSE
, &cookie
);
2304 ok_ole_success(hr
, CoRegisterClassObject
);
2306 ready_event
= CreateEvent(NULL
, FALSE
, FALSE
, "Wine COM Test Ready Event");
2307 SetEvent(ready_event
);
2309 quit_event
= CreateEvent(NULL
, FALSE
, FALSE
, "Wine COM Test Quit Event");
2313 wait
= MsgWaitForMultipleObjects(1, &quit_event
, FALSE
, INFINITE
, QS_ALLINPUT
);
2314 if (wait
== WAIT_OBJECT_0
+1)
2317 BOOL ret
= PeekMessage(&msg
, NULL
, 0, 0, PM_REMOVE
);
2320 trace("Message 0x%x\n", msg
.message
);
2321 TranslateMessage(&msg
);
2322 DispatchMessage(&msg
);
2326 while (wait
== WAIT_OBJECT_0
+1);
2328 hr
= CoRevokeClassObject(cookie
);
2329 ok_ole_success(hr
, CoRevokeClassObject
);
2332 static HANDLE
create_target_process(const char *arg
)
2335 char cmdline
[MAX_PATH
];
2336 PROCESS_INFORMATION pi
;
2337 STARTUPINFO si
= { 0 };
2340 winetest_get_mainargs( &argv
);
2341 sprintf(cmdline
, "%s %s %s", argv
[0], argv
[1], arg
);
2342 ok(CreateProcess(argv
[0], cmdline
, NULL
, NULL
, FALSE
, 0, NULL
, NULL
,
2343 &si
, &pi
) != 0, "error: %u\n", GetLastError());
2344 ok(CloseHandle(pi
.hThread
) != 0, "error %u\n", GetLastError());
2348 /* tests functions commonly used by out of process COM servers */
2349 static void test_local_server(void)
2359 heventShutdown
= CreateEvent(NULL
, TRUE
, FALSE
, NULL
);
2363 /* Start the object suspended */
2364 hr
= CoRegisterClassObject(&CLSID_WineOOPTest
, (IUnknown
*)&TestOOP_ClassFactory
,
2365 CLSCTX_LOCAL_SERVER
, REGCLS_MULTIPLEUSE
| REGCLS_SUSPENDED
, &cookie
);
2366 ok_ole_success(hr
, CoRegisterClassObject
);
2368 /* ... and CoGetClassObject does not find it and fails when it looks for the
2369 * class in the registry */
2370 hr
= CoGetClassObject(&CLSID_WineOOPTest
, CLSCTX_INPROC_SERVER
,
2371 NULL
, &IID_IClassFactory
, (LPVOID
*)&cf
);
2372 ok(hr
== REGDB_E_CLASSNOTREG
|| /* NT */
2373 hr
== S_OK
/* Win9x */,
2374 "CoGetClassObject should have returned REGDB_E_CLASSNOTREG instead of 0x%08x\n", hr
);
2376 /* Resume the object suspended above ... */
2377 hr
= CoResumeClassObjects();
2378 ok_ole_success(hr
, CoResumeClassObjects
);
2380 /* ... and now it should succeed */
2381 hr
= CoGetClassObject(&CLSID_WineOOPTest
, CLSCTX_INPROC_SERVER
,
2382 NULL
, &IID_IClassFactory
, (LPVOID
*)&cf
);
2383 ok_ole_success(hr
, CoGetClassObject
);
2385 /* Now check the locking is working */
2386 /* NOTE: we are accessing the class directly, not through a proxy */
2390 hr
= IClassFactory_LockServer(cf
, TRUE
);
2391 ok_ole_success(hr
, IClassFactory_LockServer
);
2393 ok_more_than_one_lock();
2395 IClassFactory_LockServer(cf
, FALSE
);
2396 ok_ole_success(hr
, IClassFactory_LockServer
);
2400 IClassFactory_Release(cf
);
2402 /* wait for shutdown signal */
2403 ret
= WaitForSingleObject(heventShutdown
, 0);
2404 ok(ret
!= WAIT_TIMEOUT
, "Server didn't shut down\n");
2406 /* try to connect again after SCM has suspended registered class objects */
2407 hr
= CoGetClassObject(&CLSID_WineOOPTest
, CLSCTX_INPROC_SERVER
| CLSCTX_LOCAL_SERVER
, NULL
,
2408 &IID_IClassFactory
, (LPVOID
*)&cf
);
2409 ok(hr
== CO_E_SERVER_STOPPING
|| /* NT */
2410 hr
== S_OK
/* Win9x */,
2411 "CoGetClassObject should have returned CO_E_SERVER_STOPPING instead of 0x%08x\n", hr
);
2413 hr
= CoRevokeClassObject(cookie
);
2414 ok_ole_success(hr
, CoRevokeClassObject
);
2416 CloseHandle(heventShutdown
);
2418 process
= create_target_process("-Embedding");
2419 ok(process
!= NULL
, "couldn't start local server process, error was %d\n", GetLastError());
2421 ready_event
= CreateEvent(NULL
, FALSE
, FALSE
, "Wine COM Test Ready Event");
2422 WaitForSingleObject(ready_event
, 1000);
2423 CloseHandle(ready_event
);
2425 hr
= CoCreateInstance(&CLSID_WineOOPTest
, NULL
, CLSCTX_LOCAL_SERVER
, &IID_IClassFactory
, (void **)&cf
);
2426 ok_ole_success(hr
, CoCreateInstance
);
2428 IClassFactory_Release(cf
);
2430 hr
= CoCreateInstance(&CLSID_WineOOPTest
, NULL
, CLSCTX_LOCAL_SERVER
, &IID_IClassFactory
, (void **)&cf
);
2431 ok(hr
== REGDB_E_CLASSNOTREG
, "Second CoCreateInstance on REGCLS_SINGLEUSE object should have failed\n");
2433 quit_event
= CreateEvent(NULL
, FALSE
, FALSE
, "Wine COM Test Quit Event");
2434 SetEvent(quit_event
);
2436 WaitForSingleObject(process
, INFINITE
);
2437 CloseHandle(quit_event
);
2438 CloseHandle(process
);
2444 IGlobalInterfaceTable
*git
;
2447 static DWORD CALLBACK
get_global_interface_proc(LPVOID pv
)
2450 struct git_params
*params
= (struct git_params
*)pv
;
2453 hr
= IGlobalInterfaceTable_GetInterfaceFromGlobal(params
->git
, params
->cookie
, &IID_IClassFactory
, (void **)&cf
);
2454 ok(hr
== CO_E_NOTINITIALIZED
,
2455 "IGlobalInterfaceTable_GetInterfaceFromGlobal should have failed with error CO_E_NOTINITIALIZED instead of 0x%08x\n",
2459 hr
= IGlobalInterfaceTable_GetInterfaceFromGlobal(params
->git
, params
->cookie
, &IID_IClassFactory
, (void **)&cf
);
2460 ok_ole_success(hr
, IGlobalInterfaceTable_GetInterfaceFromGlobal
);
2462 IGlobalInterfaceTable_Release(params
->git
);
2469 static void test_globalinterfacetable(void)
2472 IGlobalInterfaceTable
*git
;
2476 struct git_params params
;
2479 hr
= CoCreateInstance(&CLSID_StdGlobalInterfaceTable
, NULL
, CLSCTX_INPROC_SERVER
, &IID_IGlobalInterfaceTable
, (void **)&git
);
2480 ok_ole_success(hr
, CoCreateInstance
);
2482 hr
= IGlobalInterfaceTable_RegisterInterfaceInGlobal(git
, (IUnknown
*)&Test_ClassFactory
, &IID_IClassFactory
, &cookie
);
2483 ok_ole_success(hr
, IGlobalInterfaceTable_RegisterInterfaceInGlobal
);
2485 params
.cookie
= cookie
;
2487 /* note: params is on stack so we MUST wait for get_global_interface_proc
2488 * to exit before we can return */
2489 thread
= CreateThread(NULL
, 0, get_global_interface_proc
, ¶ms
, 0, &tid
);
2491 ret
= MsgWaitForMultipleObjects(1, &thread
, FALSE
, INFINITE
, QS_ALLINPUT
);
2492 while (ret
== WAIT_OBJECT_0
+ 1)
2495 while (PeekMessage(&msg
, NULL
, 0, 0, PM_REMOVE
))
2496 DispatchMessage(&msg
);
2497 ret
= MsgWaitForMultipleObjects(1, &thread
, FALSE
, INFINITE
, QS_ALLINPUT
);
2500 CloseHandle(thread
);
2503 static const char *debugstr_iid(REFIID riid
)
2505 static char name
[256];
2509 LONG name_size
= sizeof(name
);
2510 StringFromGUID2(riid
, bufferW
, sizeof(bufferW
)/sizeof(bufferW
[0]));
2511 WideCharToMultiByte(CP_ACP
, 0, bufferW
, sizeof(bufferW
)/sizeof(bufferW
[0]), buffer
, sizeof(buffer
), NULL
, NULL
);
2512 if (RegOpenKeyEx(HKEY_CLASSES_ROOT
, "Interface", 0, KEY_QUERY_VALUE
, &hkeyInterface
) != ERROR_SUCCESS
)
2514 memcpy(name
, buffer
, sizeof(buffer
));
2517 if (RegQueryValue(hkeyInterface
, buffer
, name
, &name_size
) != ERROR_SUCCESS
)
2519 memcpy(name
, buffer
, sizeof(buffer
));
2522 RegCloseKey(hkeyInterface
);
2527 static HRESULT WINAPI
TestChannelHook_QueryInterface(IChannelHook
*iface
, REFIID riid
, void **ppv
)
2529 if (IsEqualIID(riid
, &IID_IUnknown
) || IsEqualIID(riid
, &IID_IChannelHook
))
2532 IUnknown_AddRef(iface
);
2537 return E_NOINTERFACE
;
2540 static ULONG WINAPI
TestChannelHook_AddRef(IChannelHook
*iface
)
2545 static ULONG WINAPI
TestChannelHook_Release(IChannelHook
*iface
)
2550 static void WINAPI
TestChannelHook_ClientGetSize(
2551 IChannelHook
*iface
,
2556 SChannelHookCallInfo
*info
= (SChannelHookCallInfo
*)riid
;
2557 trace("TestChannelHook_ClientGetBuffer\n");
2558 trace("\t%s method %d\n", debugstr_iid(riid
), info
->iMethod
);
2559 trace("\tcid: %s\n", debugstr_iid(&info
->uCausality
));
2560 ok(info
->cbSize
== sizeof(*info
), "info->cbSize was %d instead of %d\n", info
->cbSize
, (int)sizeof(*info
));
2561 ok(info
->dwServerPid
== GetCurrentProcessId(), "info->dwServerPid was 0x%x instead of 0x%x\n", info
->dwServerPid
, GetCurrentProcessId());
2562 ok(!info
->pObject
, "info->pObject should be NULL\n");
2563 ok(IsEqualGUID(uExtent
, &EXTENTID_WineTest
), "uExtent wasn't correct\n");
2568 static void WINAPI
TestChannelHook_ClientFillBuffer(
2569 IChannelHook
*iface
,
2575 SChannelHookCallInfo
*info
= (SChannelHookCallInfo
*)riid
;
2576 trace("TestChannelHook_ClientFillBuffer\n");
2577 ok(info
->cbSize
== sizeof(*info
), "info->cbSize was %d instead of %d\n", info
->cbSize
, (int)sizeof(*info
));
2578 ok(info
->dwServerPid
== GetCurrentProcessId(), "info->dwServerPid was 0x%x instead of 0x%x\n", info
->dwServerPid
, GetCurrentProcessId());
2579 ok(!info
->pObject
, "info->pObject should be NULL\n");
2580 ok(IsEqualGUID(uExtent
, &EXTENTID_WineTest
), "uExtent wasn't correct\n");
2582 *(unsigned char *)pDataBuffer
= 0xcc;
2586 static void WINAPI
TestChannelHook_ClientNotify(
2587 IChannelHook
*iface
,
2595 SChannelHookCallInfo
*info
= (SChannelHookCallInfo
*)riid
;
2596 trace("TestChannelHook_ClientNotify hrFault = 0x%08x\n", hrFault
);
2597 ok(info
->cbSize
== sizeof(*info
), "info->cbSize was %d instead of %d\n", info
->cbSize
, (int)sizeof(*info
));
2598 ok(info
->dwServerPid
== GetCurrentProcessId(), "info->dwServerPid was 0x%x instead of 0x%x\n", info
->dwServerPid
, GetCurrentProcessId());
2600 ok(info
->pObject
!= NULL
, "info->pObject shouldn't be NULL\n");
2602 ok(IsEqualGUID(uExtent
, &EXTENTID_WineTest
), "uExtent wasn't correct\n");
2605 static void WINAPI
TestChannelHook_ServerNotify(
2606 IChannelHook
*iface
,
2613 SChannelHookCallInfo
*info
= (SChannelHookCallInfo
*)riid
;
2614 trace("TestChannelHook_ServerNotify\n");
2615 ok(info
->cbSize
== sizeof(*info
), "info->cbSize was %d instead of %d\n", info
->cbSize
, (int)sizeof(*info
));
2616 ok(info
->dwServerPid
== GetCurrentProcessId(), "info->dwServerPid was 0x%x instead of 0x%x\n", info
->dwServerPid
, GetCurrentProcessId());
2617 ok(info
->pObject
!= NULL
, "info->pObject shouldn't be NULL\n");
2618 ok(cbDataSize
== 1, "cbDataSize should have been 1 instead of %d\n", cbDataSize
);
2619 ok(*(unsigned char *)pDataBuffer
== 0xcc, "pDataBuffer should have contained 0xcc instead of 0x%x\n", *(unsigned char *)pDataBuffer
);
2620 ok(IsEqualGUID(uExtent
, &EXTENTID_WineTest
), "uExtent wasn't correct\n");
2623 static void WINAPI
TestChannelHook_ServerGetSize(
2624 IChannelHook
*iface
,
2630 SChannelHookCallInfo
*info
= (SChannelHookCallInfo
*)riid
;
2631 trace("TestChannelHook_ServerGetSize\n");
2632 trace("\t%s method %d\n", debugstr_iid(riid
), info
->iMethod
);
2633 ok(info
->cbSize
== sizeof(*info
), "info->cbSize was %d instead of %d\n", info
->cbSize
, (int)sizeof(*info
));
2634 ok(info
->dwServerPid
== GetCurrentProcessId(), "info->dwServerPid was 0x%x instead of 0x%x\n", info
->dwServerPid
, GetCurrentProcessId());
2635 ok(info
->pObject
!= NULL
, "info->pObject shouldn't be NULL\n");
2636 ok(IsEqualGUID(uExtent
, &EXTENTID_WineTest
), "uExtent wasn't correct\n");
2637 if (hrFault
!= S_OK
)
2638 trace("\thrFault = 0x%08x\n", hrFault
);
2643 static void WINAPI
TestChannelHook_ServerFillBuffer(
2644 IChannelHook
*iface
,
2651 trace("TestChannelHook_ServerFillBuffer\n");
2652 ok(0, "TestChannelHook_ServerFillBuffer shouldn't be called\n");
2655 static const IChannelHookVtbl TestChannelHookVtbl
=
2657 TestChannelHook_QueryInterface
,
2658 TestChannelHook_AddRef
,
2659 TestChannelHook_Release
,
2660 TestChannelHook_ClientGetSize
,
2661 TestChannelHook_ClientFillBuffer
,
2662 TestChannelHook_ClientNotify
,
2663 TestChannelHook_ServerNotify
,
2664 TestChannelHook_ServerGetSize
,
2665 TestChannelHook_ServerFillBuffer
,
2668 static IChannelHook TestChannelHook
= { &TestChannelHookVtbl
};
2670 static void test_channel_hook(void)
2672 IStream
*pStream
= NULL
;
2673 IClassFactory
*cf
= NULL
;
2675 IUnknown
*proxy
= NULL
;
2679 hr
= CoRegisterChannelHook(&EXTENTID_WineTest
, &TestChannelHook
);
2680 ok_ole_success(hr
, CoRegisterChannelHook
);
2682 hr
= CoRegisterMessageFilter(&MessageFilter
, NULL
);
2683 ok_ole_success(hr
, CoRegisterMessageFilter
);
2687 hr
= CreateStreamOnHGlobal(NULL
, TRUE
, &pStream
);
2688 ok_ole_success(hr
, CreateStreamOnHGlobal
);
2689 tid
= start_host_object2(pStream
, &IID_IClassFactory
, (IUnknown
*)&Test_ClassFactory
, MSHLFLAGS_NORMAL
, &MessageFilter
, &thread
);
2691 ok_more_than_one_lock();
2693 IStream_Seek(pStream
, ullZero
, STREAM_SEEK_SET
, NULL
);
2694 hr
= CoUnmarshalInterface(pStream
, &IID_IClassFactory
, (void **)&cf
);
2695 ok_ole_success(hr
, CoUnmarshalInterface
);
2696 IStream_Release(pStream
);
2698 ok_more_than_one_lock();
2700 hr
= IClassFactory_CreateInstance(cf
, NULL
, &IID_IUnknown
, (LPVOID
*)&proxy
);
2701 ok_ole_success(hr
, IClassFactory_CreateInstance
);
2702 IUnknown_Release(proxy
);
2704 IClassFactory_Release(cf
);
2708 end_host_object(tid
, thread
);
2710 hr
= CoRegisterMessageFilter(NULL
, NULL
);
2711 ok_ole_success(hr
, CoRegisterMessageFilter
);
2717 HMODULE hOle32
= GetModuleHandle("ole32");
2721 if (!(pCoInitializeEx
= (void*)GetProcAddress(hOle32
, "CoInitializeEx"))) goto no_test
;
2723 argc
= winetest_get_mainargs( &argv
);
2724 if (argc
> 2 && (!strcmp(argv
[2], "-Embedding")))
2726 pCoInitializeEx(NULL
, COINIT_APARTMENTTHREADED
);
2727 test_register_local_server();
2733 /* register a window class used in several tests */
2734 memset(&wndclass
, 0, sizeof(wndclass
));
2735 wndclass
.lpfnWndProc
= window_proc
;
2736 wndclass
.lpszClassName
= "WineCOMTest";
2737 RegisterClass(&wndclass
);
2739 test_cocreateinstance_proxy();
2741 pCoInitializeEx(NULL
, COINIT_APARTMENTTHREADED
);
2743 /* FIXME: test CoCreateInstanceEx */
2745 /* lifecycle management and marshaling tests */
2746 test_no_marshaler();
2747 test_normal_marshal_and_release();
2748 test_normal_marshal_and_unmarshal();
2749 test_marshal_and_unmarshal_invalid();
2750 test_same_apartment_unmarshal_failure();
2751 test_interthread_marshal_and_unmarshal();
2752 test_proxy_marshal_and_unmarshal();
2753 test_proxy_marshal_and_unmarshal2();
2754 test_marshal_stub_apartment_shutdown();
2755 test_marshal_proxy_apartment_shutdown();
2756 test_marshal_proxy_mta_apartment_shutdown();
2757 test_no_couninitialize_server();
2758 test_no_couninitialize_client();
2759 test_tableweak_marshal_and_unmarshal_twice();
2760 test_tableweak_marshal_releasedata1();
2761 test_tableweak_marshal_releasedata2();
2762 test_tablestrong_marshal_and_unmarshal_twice();
2763 test_lock_object_external();
2764 test_disconnect_stub();
2765 test_normal_marshal_and_unmarshal_twice();
2766 test_hresult_marshaling();
2767 test_proxy_used_in_wrong_thread();
2768 test_message_filter();
2769 test_bad_marshal_stream();
2770 test_proxy_interfaces();
2771 test_stubbuffer(&IID_IClassFactory
);
2772 test_proxybuffer(&IID_IClassFactory
);
2773 test_message_reentrancy();
2774 test_call_from_message();
2775 test_WM_QUIT_handling();
2776 test_freethreadedmarshaler();
2777 test_inproc_handler();
2778 test_handler_marshaling();
2779 test_client_security();
2781 test_local_server();
2783 test_globalinterfacetable();
2785 /* must be last test as channel hooks can't be unregistered */
2786 test_channel_hook();
2792 trace("You need DCOM95 installed to run this test\n");