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 static void test_cocreateinstance_proxy(void)
56 pCoInitializeEx(NULL, COINIT_MULTITHREADED);
58 hr = CoCreateInstance(&CLSID_ShellDesktop, NULL, CLSCTX_INPROC, &IID_IUnknown, (void **)&pProxy);
59 ok_ole_success(hr, CoCreateInstance);
60 hr = IUnknown_QueryInterface(pProxy, &IID_IMultiQI, (void **)&pMQI);
62 ok(hr == S_OK, "created object is not a proxy, so was created in the wrong apartment\n");
64 IMultiQI_Release(pMQI);
65 IUnknown_Release(pProxy);
70 static const LARGE_INTEGER ullZero;
73 static void LockModule(void)
75 InterlockedIncrement(&cLocks);
78 static void UnlockModule(void)
80 InterlockedDecrement(&cLocks);
84 static HRESULT WINAPI Test_IUnknown_QueryInterface(
89 if (ppvObj == NULL) return E_POINTER;
91 if (IsEqualGUID(riid, &IID_IUnknown))
93 *ppvObj = (LPVOID)iface;
94 IUnknown_AddRef(iface);
102 static ULONG WINAPI Test_IUnknown_AddRef(LPUNKNOWN iface)
105 return 2; /* non-heap-based object */
108 static ULONG WINAPI Test_IUnknown_Release(LPUNKNOWN iface)
111 return 1; /* non-heap-based object */
114 static const IUnknownVtbl TestUnknown_Vtbl =
116 Test_IUnknown_QueryInterface,
117 Test_IUnknown_AddRef,
118 Test_IUnknown_Release,
121 static IUnknown Test_Unknown = { &TestUnknown_Vtbl };
124 static HRESULT WINAPI Test_IClassFactory_QueryInterface(
125 LPCLASSFACTORY iface,
129 if (ppvObj == NULL) return E_POINTER;
131 if (IsEqualGUID(riid, &IID_IUnknown) ||
132 IsEqualGUID(riid, &IID_IClassFactory))
134 *ppvObj = (LPVOID)iface;
135 IClassFactory_AddRef(iface);
140 return E_NOINTERFACE;
143 static ULONG WINAPI Test_IClassFactory_AddRef(LPCLASSFACTORY iface)
146 return 2; /* non-heap-based object */
149 static ULONG WINAPI Test_IClassFactory_Release(LPCLASSFACTORY iface)
152 return 1; /* non-heap-based object */
155 static HRESULT WINAPI Test_IClassFactory_CreateInstance(
156 LPCLASSFACTORY iface,
161 if (pUnkOuter) return CLASS_E_NOAGGREGATION;
162 return IUnknown_QueryInterface((IUnknown*)&Test_Unknown, riid, ppvObj);
165 static HRESULT WINAPI Test_IClassFactory_LockServer(
166 LPCLASSFACTORY iface,
172 static const IClassFactoryVtbl TestClassFactory_Vtbl =
174 Test_IClassFactory_QueryInterface,
175 Test_IClassFactory_AddRef,
176 Test_IClassFactory_Release,
177 Test_IClassFactory_CreateInstance,
178 Test_IClassFactory_LockServer
181 static IClassFactory Test_ClassFactory = { &TestClassFactory_Vtbl };
183 #define RELEASEMARSHALDATA WM_USER
185 struct host_object_data
190 MSHLFLAGS marshal_flags;
191 HANDLE marshal_event;
192 IMessageFilter *filter;
195 static DWORD CALLBACK host_object_proc(LPVOID p)
197 struct host_object_data *data = (struct host_object_data *)p;
201 pCoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
205 IMessageFilter * prev_filter = NULL;
206 hr = CoRegisterMessageFilter(data->filter, &prev_filter);
207 if (prev_filter) IMessageFilter_Release(prev_filter);
208 ok_ole_success(hr, CoRegisterMessageFilter);
211 hr = CoMarshalInterface(data->stream, &data->iid, data->object, MSHCTX_INPROC, NULL, data->marshal_flags);
212 ok_ole_success(hr, CoMarshalInterface);
214 /* force the message queue to be created before signaling parent thread */
215 PeekMessage(&msg, NULL, WM_USER, WM_USER, PM_NOREMOVE);
217 SetEvent(data->marshal_event);
219 while (GetMessage(&msg, NULL, 0, 0))
221 if (msg.hwnd == NULL && msg.message == RELEASEMARSHALDATA)
223 trace("releasing marshal data\n");
224 CoReleaseMarshalData(data->stream);
225 SetEvent((HANDLE)msg.lParam);
228 DispatchMessage(&msg);
231 HeapFree(GetProcessHeap(), 0, data);
238 static DWORD start_host_object2(IStream *stream, REFIID riid, IUnknown *object, MSHLFLAGS marshal_flags, IMessageFilter *filter, HANDLE *thread)
241 HANDLE marshal_event = CreateEvent(NULL, FALSE, FALSE, NULL);
242 struct host_object_data *data = HeapAlloc(GetProcessHeap(), 0, sizeof(*data));
244 data->stream = stream;
246 data->object = object;
247 data->marshal_flags = marshal_flags;
248 data->marshal_event = marshal_event;
249 data->filter = filter;
251 *thread = CreateThread(NULL, 0, host_object_proc, data, 0, &tid);
253 /* wait for marshaling to complete before returning */
254 WaitForSingleObject(marshal_event, INFINITE);
255 CloseHandle(marshal_event);
260 static DWORD start_host_object(IStream *stream, REFIID riid, IUnknown *object, MSHLFLAGS marshal_flags, HANDLE *thread)
262 return start_host_object2(stream, riid, object, marshal_flags, NULL, thread);
265 /* asks thread to release the marshal data because it has to be done by the
266 * same thread that marshaled the interface in the first place. */
267 static void release_host_object(DWORD tid)
269 HANDLE event = CreateEvent(NULL, FALSE, FALSE, NULL);
270 PostThreadMessage(tid, RELEASEMARSHALDATA, 0, (LPARAM)event);
271 WaitForSingleObject(event, INFINITE);
275 static void end_host_object(DWORD tid, HANDLE thread)
277 BOOL ret = PostThreadMessage(tid, WM_QUIT, 0, 0);
278 ok(ret, "PostThreadMessage failed with error %d\n", GetLastError());
279 /* be careful of races - don't return until hosting thread has terminated */
280 WaitForSingleObject(thread, INFINITE);
284 /* tests failure case of interface not having a marshaler specified in the
286 static void test_no_marshaler(void)
291 hr = CreateStreamOnHGlobal(NULL, TRUE, &pStream);
292 ok_ole_success(hr, CreateStreamOnHGlobal);
293 hr = CoMarshalInterface(pStream, &IID_IWineTest, (IUnknown*)&Test_ClassFactory, MSHCTX_INPROC, NULL, MSHLFLAGS_NORMAL);
294 ok(hr == E_NOINTERFACE, "CoMarshalInterface should have returned E_NOINTERFACE instead of 0x%08x\n", hr);
296 IStream_Release(pStream);
299 /* tests normal marshal and then release without unmarshaling */
300 static void test_normal_marshal_and_release(void)
303 IStream *pStream = NULL;
307 hr = CreateStreamOnHGlobal(NULL, TRUE, &pStream);
308 ok_ole_success(hr, CreateStreamOnHGlobal);
309 hr = CoMarshalInterface(pStream, &IID_IClassFactory, (IUnknown*)&Test_ClassFactory, MSHCTX_INPROC, NULL, MSHLFLAGS_NORMAL);
310 ok_ole_success(hr, CoMarshalInterface);
312 ok_more_than_one_lock();
314 IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
315 hr = CoReleaseMarshalData(pStream);
316 ok_ole_success(hr, CoReleaseMarshalData);
317 IStream_Release(pStream);
322 /* tests success case of a same-thread marshal and unmarshal */
323 static void test_normal_marshal_and_unmarshal(void)
326 IStream *pStream = NULL;
327 IUnknown *pProxy = NULL;
331 hr = CreateStreamOnHGlobal(NULL, TRUE, &pStream);
332 ok_ole_success(hr, CreateStreamOnHGlobal);
333 hr = CoMarshalInterface(pStream, &IID_IClassFactory, (IUnknown*)&Test_ClassFactory, MSHCTX_INPROC, NULL, MSHLFLAGS_NORMAL);
334 ok_ole_success(hr, CoMarshalInterface);
336 ok_more_than_one_lock();
338 IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
339 hr = CoUnmarshalInterface(pStream, &IID_IClassFactory, (void **)&pProxy);
340 ok_ole_success(hr, CoUnmarshalInterface);
341 IStream_Release(pStream);
343 ok_more_than_one_lock();
345 IUnknown_Release(pProxy);
350 /* tests failure case of unmarshaling a freed object */
351 static void test_marshal_and_unmarshal_invalid(void)
354 IStream *pStream = NULL;
355 IClassFactory *pProxy = NULL;
362 hr = CreateStreamOnHGlobal(NULL, TRUE, &pStream);
363 ok_ole_success(hr, CreateStreamOnHGlobal);
364 tid = start_host_object(pStream, &IID_IClassFactory, (IUnknown*)&Test_ClassFactory, MSHLFLAGS_NORMAL, &thread);
366 ok_more_than_one_lock();
368 IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
369 hr = CoReleaseMarshalData(pStream);
370 ok_ole_success(hr, CoReleaseMarshalData);
374 IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
375 hr = CoUnmarshalInterface(pStream, &IID_IClassFactory, (void **)&pProxy);
376 todo_wine { ok_ole_success(hr, CoUnmarshalInterface); }
382 hr = IClassFactory_CreateInstance(pProxy, NULL, &IID_IUnknown, &dummy);
383 ok(hr == RPC_E_DISCONNECTED, "Remote call should have returned RPC_E_DISCONNECTED, instead of 0x%08x\n", hr);
385 IClassFactory_Release(pProxy);
388 IStream_Release(pStream);
390 end_host_object(tid, thread);
393 /* tests success case of an interthread marshal */
394 static void test_interthread_marshal_and_unmarshal(void)
397 IStream *pStream = NULL;
398 IUnknown *pProxy = NULL;
404 hr = CreateStreamOnHGlobal(NULL, TRUE, &pStream);
405 ok_ole_success(hr, CreateStreamOnHGlobal);
406 tid = start_host_object(pStream, &IID_IClassFactory, (IUnknown*)&Test_ClassFactory, MSHLFLAGS_NORMAL, &thread);
408 ok_more_than_one_lock();
410 IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
411 hr = CoUnmarshalInterface(pStream, &IID_IClassFactory, (void **)&pProxy);
412 ok_ole_success(hr, CoUnmarshalInterface);
413 IStream_Release(pStream);
415 ok_more_than_one_lock();
417 IUnknown_Release(pProxy);
421 end_host_object(tid, thread);
424 /* the number of external references that Wine's proxy manager normally gives
425 * out, so we can test the border case of running out of references */
426 #define NORMALEXTREFS 5
428 /* tests success case of an interthread marshal and then marshaling the proxy */
429 static void test_proxy_marshal_and_unmarshal(void)
432 IStream *pStream = NULL;
433 IUnknown *pProxy = NULL;
434 IUnknown *pProxy2 = NULL;
441 hr = CreateStreamOnHGlobal(NULL, TRUE, &pStream);
442 ok_ole_success(hr, CreateStreamOnHGlobal);
443 tid = start_host_object(pStream, &IID_IClassFactory, (IUnknown*)&Test_ClassFactory, MSHLFLAGS_NORMAL, &thread);
445 ok_more_than_one_lock();
447 IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
448 hr = CoUnmarshalInterface(pStream, &IID_IClassFactory, (void **)&pProxy);
449 ok_ole_success(hr, CoUnmarshalInterface);
451 ok_more_than_one_lock();
453 IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
454 /* marshal the proxy */
455 hr = CoMarshalInterface(pStream, &IID_IClassFactory, pProxy, MSHCTX_INPROC, NULL, MSHLFLAGS_NORMAL);
456 ok_ole_success(hr, CoMarshalInterface);
458 ok_more_than_one_lock();
460 /* marshal 5 more times to exhaust the normal external references of 5 */
461 for (i = 0; i < NORMALEXTREFS; i++)
463 hr = CoMarshalInterface(pStream, &IID_IClassFactory, pProxy, MSHCTX_INPROC, NULL, MSHLFLAGS_NORMAL);
464 ok_ole_success(hr, CoMarshalInterface);
467 ok_more_than_one_lock();
469 /* release the original proxy to test that we successfully keep the
470 * original object alive */
471 IUnknown_Release(pProxy);
473 IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
474 hr = CoUnmarshalInterface(pStream, &IID_IClassFactory, (void **)&pProxy2);
475 ok_ole_success(hr, CoUnmarshalInterface);
477 ok_more_than_one_lock();
479 /* now the proxies should be as follows:
480 * pProxy2 -> &Test_ClassFactory
481 * they should NOT be as follows:
482 * pProxy -> &Test_ClassFactory
484 * the above can only really be tested by looking in +ole traces
487 IUnknown_Release(pProxy2);
489 /* unmarshal all of the proxies to check that the object stub still exists */
490 for (i = 0; i < NORMALEXTREFS; i++)
492 hr = CoUnmarshalInterface(pStream, &IID_IClassFactory, (void **)&pProxy2);
493 ok_ole_success(hr, CoUnmarshalInterface);
495 IUnknown_Release(pProxy2);
500 IStream_Release(pStream);
502 end_host_object(tid, thread);
505 /* tests success case of an interthread marshal and then marshaling the proxy
506 * using an iid that hasn't previously been unmarshaled */
507 static void test_proxy_marshal_and_unmarshal2(void)
510 IStream *pStream = NULL;
511 IUnknown *pProxy = NULL;
512 IUnknown *pProxy2 = NULL;
518 hr = CreateStreamOnHGlobal(NULL, TRUE, &pStream);
519 ok_ole_success(hr, CreateStreamOnHGlobal);
520 tid = start_host_object(pStream, &IID_IUnknown, (IUnknown*)&Test_ClassFactory, MSHLFLAGS_NORMAL, &thread);
522 ok_more_than_one_lock();
524 IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
525 hr = CoUnmarshalInterface(pStream, &IID_IUnknown, (void **)&pProxy);
526 ok_ole_success(hr, CoUnmarshalInterface);
528 ok_more_than_one_lock();
530 IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
531 /* marshal the proxy */
532 hr = CoMarshalInterface(pStream, &IID_IClassFactory, pProxy, MSHCTX_INPROC, NULL, MSHLFLAGS_NORMAL);
533 ok_ole_success(hr, CoMarshalInterface);
535 ok_more_than_one_lock();
537 IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
538 /* unmarshal the second proxy to the object */
539 hr = CoUnmarshalInterface(pStream, &IID_IClassFactory, (void **)&pProxy2);
540 ok_ole_success(hr, CoUnmarshalInterface);
541 IStream_Release(pStream);
543 /* now the proxies should be as follows:
544 * pProxy -> &Test_ClassFactory
545 * pProxy2 -> &Test_ClassFactory
546 * they should NOT be as follows:
547 * pProxy -> &Test_ClassFactory
549 * the above can only really be tested by looking in +ole traces
552 ok_more_than_one_lock();
554 IUnknown_Release(pProxy);
556 ok_more_than_one_lock();
558 IUnknown_Release(pProxy2);
562 end_host_object(tid, thread);
565 /* tests that stubs are released when the containing apartment is destroyed */
566 static void test_marshal_stub_apartment_shutdown(void)
569 IStream *pStream = NULL;
570 IUnknown *pProxy = NULL;
576 hr = CreateStreamOnHGlobal(NULL, TRUE, &pStream);
577 ok_ole_success(hr, CreateStreamOnHGlobal);
578 tid = start_host_object(pStream, &IID_IClassFactory, (IUnknown*)&Test_ClassFactory, MSHLFLAGS_NORMAL, &thread);
580 ok_more_than_one_lock();
582 IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
583 hr = CoUnmarshalInterface(pStream, &IID_IClassFactory, (void **)&pProxy);
584 ok_ole_success(hr, CoUnmarshalInterface);
585 IStream_Release(pStream);
587 ok_more_than_one_lock();
589 end_host_object(tid, thread);
593 IUnknown_Release(pProxy);
598 /* tests that proxies are released when the containing apartment is destroyed */
599 static void test_marshal_proxy_apartment_shutdown(void)
602 IStream *pStream = NULL;
603 IUnknown *pProxy = NULL;
609 hr = CreateStreamOnHGlobal(NULL, TRUE, &pStream);
610 ok_ole_success(hr, CreateStreamOnHGlobal);
611 tid = start_host_object(pStream, &IID_IClassFactory, (IUnknown*)&Test_ClassFactory, MSHLFLAGS_NORMAL, &thread);
613 ok_more_than_one_lock();
615 IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
616 hr = CoUnmarshalInterface(pStream, &IID_IClassFactory, (void **)&pProxy);
617 ok_ole_success(hr, CoUnmarshalInterface);
618 IStream_Release(pStream);
620 ok_more_than_one_lock();
626 IUnknown_Release(pProxy);
630 end_host_object(tid, thread);
632 pCoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
635 /* tests that proxies are released when the containing mta apartment is destroyed */
636 static void test_marshal_proxy_mta_apartment_shutdown(void)
639 IStream *pStream = NULL;
640 IUnknown *pProxy = NULL;
645 pCoInitializeEx(NULL, COINIT_MULTITHREADED);
649 hr = CreateStreamOnHGlobal(NULL, TRUE, &pStream);
650 ok_ole_success(hr, CreateStreamOnHGlobal);
651 tid = start_host_object(pStream, &IID_IClassFactory, (IUnknown*)&Test_ClassFactory, MSHLFLAGS_NORMAL, &thread);
653 ok_more_than_one_lock();
655 IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
656 hr = CoUnmarshalInterface(pStream, &IID_IClassFactory, (void **)&pProxy);
657 ok_ole_success(hr, CoUnmarshalInterface);
658 IStream_Release(pStream);
660 ok_more_than_one_lock();
666 IUnknown_Release(pProxy);
670 end_host_object(tid, thread);
672 pCoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
678 HANDLE marshal_event;
679 HANDLE unmarshal_event;
682 /* helper for test_no_couninitialize_server */
683 static DWORD CALLBACK no_couninitialize_server_proc(LPVOID p)
685 struct ncu_params *ncu_params = (struct ncu_params *)p;
688 pCoInitializeEx(NULL, COINIT_MULTITHREADED);
690 hr = CoMarshalInterface(ncu_params->stream, &IID_IClassFactory, (IUnknown*)&Test_ClassFactory, MSHCTX_INPROC, NULL, MSHLFLAGS_NORMAL);
691 ok_ole_success(hr, CoMarshalInterface);
693 SetEvent(ncu_params->marshal_event);
695 WaitForSingleObject(ncu_params->unmarshal_event, INFINITE);
697 /* die without calling CoUninitialize */
702 /* tests apartment that an apartment with a stub is released without deadlock
703 * if the owning thread exits */
704 static void test_no_couninitialize_server(void)
707 IStream *pStream = NULL;
708 IUnknown *pProxy = NULL;
711 struct ncu_params ncu_params;
715 ncu_params.marshal_event = CreateEvent(NULL, TRUE, FALSE, NULL);
716 ncu_params.unmarshal_event = CreateEvent(NULL, TRUE, FALSE, NULL);
718 hr = CreateStreamOnHGlobal(NULL, TRUE, &pStream);
719 ok_ole_success(hr, CreateStreamOnHGlobal);
720 ncu_params.stream = pStream;
722 thread = CreateThread(NULL, 0, no_couninitialize_server_proc, &ncu_params, 0, &tid);
724 WaitForSingleObject(ncu_params.marshal_event, INFINITE);
725 ok_more_than_one_lock();
727 IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
728 hr = CoUnmarshalInterface(pStream, &IID_IClassFactory, (void **)&pProxy);
729 ok_ole_success(hr, CoUnmarshalInterface);
730 IStream_Release(pStream);
732 ok_more_than_one_lock();
734 SetEvent(ncu_params.unmarshal_event);
735 WaitForSingleObject(thread, INFINITE);
740 CloseHandle(ncu_params.marshal_event);
741 CloseHandle(ncu_params.unmarshal_event);
743 IUnknown_Release(pProxy);
748 /* STA -> STA call during DLL_THREAD_DETACH */
749 static DWORD CALLBACK no_couninitialize_client_proc(LPVOID p)
751 struct ncu_params *ncu_params = (struct ncu_params *)p;
753 IUnknown *pProxy = NULL;
755 pCoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
757 hr = CoUnmarshalInterface(ncu_params->stream, &IID_IClassFactory, (void **)&pProxy);
758 ok_ole_success(hr, CoUnmarshalInterface);
759 IStream_Release(ncu_params->stream);
761 ok_more_than_one_lock();
763 /* die without calling CoUninitialize */
768 /* tests STA -> STA call during DLL_THREAD_DETACH doesn't deadlock */
769 static void test_no_couninitialize_client(void)
772 IStream *pStream = NULL;
777 struct ncu_params ncu_params;
781 hr = CreateStreamOnHGlobal(NULL, TRUE, &pStream);
782 ok_ole_success(hr, CreateStreamOnHGlobal);
783 ncu_params.stream = pStream;
785 /* NOTE: assumes start_host_object uses an STA to host the object, as MTAs
786 * always deadlock when called from within DllMain */
787 host_tid = start_host_object(pStream, &IID_IClassFactory, (IUnknown *)&Test_ClassFactory, MSHLFLAGS_NORMAL, &host_thread);
788 IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
790 ok_more_than_one_lock();
792 thread = CreateThread(NULL, 0, no_couninitialize_client_proc, &ncu_params, 0, &tid);
794 WaitForSingleObject(thread, INFINITE);
799 end_host_object(host_tid, host_thread);
802 /* tests success case of a same-thread table-weak marshal, unmarshal, unmarshal */
803 static void test_tableweak_marshal_and_unmarshal_twice(void)
806 IStream *pStream = NULL;
807 IUnknown *pProxy1 = NULL;
808 IUnknown *pProxy2 = NULL;
814 hr = CreateStreamOnHGlobal(NULL, TRUE, &pStream);
815 ok_ole_success(hr, CreateStreamOnHGlobal);
816 tid = start_host_object(pStream, &IID_IClassFactory, (IUnknown*)&Test_ClassFactory, MSHLFLAGS_TABLEWEAK, &thread);
818 ok_more_than_one_lock();
820 IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
821 hr = CoUnmarshalInterface(pStream, &IID_IClassFactory, (void **)&pProxy1);
822 ok_ole_success(hr, CoUnmarshalInterface);
824 ok_more_than_one_lock();
826 IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
827 hr = CoUnmarshalInterface(pStream, &IID_IClassFactory, (void **)&pProxy2);
828 IStream_Release(pStream);
829 ok_ole_success(hr, CoUnmarshalInterface);
831 ok_more_than_one_lock();
833 IUnknown_Release(pProxy1);
834 IUnknown_Release(pProxy2);
836 /* this line is shows the difference between weak and strong table marshaling:
837 * weak has cLocks == 0
838 * strong has cLocks > 0 */
841 end_host_object(tid, thread);
844 /* tests releasing after unmarshaling one object */
845 static void test_tableweak_marshal_releasedata1(void)
848 IStream *pStream = NULL;
849 IUnknown *pProxy1 = NULL;
850 IUnknown *pProxy2 = NULL;
856 hr = CreateStreamOnHGlobal(NULL, TRUE, &pStream);
857 ok_ole_success(hr, CreateStreamOnHGlobal);
858 tid = start_host_object(pStream, &IID_IClassFactory, (IUnknown*)&Test_ClassFactory, MSHLFLAGS_TABLEWEAK, &thread);
860 ok_more_than_one_lock();
862 IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
863 hr = CoUnmarshalInterface(pStream, &IID_IClassFactory, (void **)&pProxy1);
864 ok_ole_success(hr, CoUnmarshalInterface);
866 ok_more_than_one_lock();
868 /* release the remaining reference on the object by calling
869 * CoReleaseMarshalData in the hosting thread */
870 IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
871 release_host_object(tid);
873 ok_more_than_one_lock();
875 IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
876 hr = CoUnmarshalInterface(pStream, &IID_IClassFactory, (void **)&pProxy2);
877 ok_ole_success(hr, CoUnmarshalInterface);
878 IStream_Release(pStream);
880 ok_more_than_one_lock();
882 IUnknown_Release(pProxy1);
884 IUnknown_Release(pProxy2);
886 /* this line is shows the difference between weak and strong table marshaling:
887 * weak has cLocks == 0
888 * strong has cLocks > 0 */
891 end_host_object(tid, thread);
894 /* tests releasing after unmarshaling one object */
895 static void test_tableweak_marshal_releasedata2(void)
898 IStream *pStream = NULL;
899 IUnknown *pProxy = NULL;
905 hr = CreateStreamOnHGlobal(NULL, TRUE, &pStream);
906 ok_ole_success(hr, CreateStreamOnHGlobal);
907 tid = start_host_object(pStream, &IID_IClassFactory, (IUnknown*)&Test_ClassFactory, MSHLFLAGS_TABLEWEAK, &thread);
909 ok_more_than_one_lock();
911 /* release the remaining reference on the object by calling
912 * CoReleaseMarshalData in the hosting thread */
913 IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
914 release_host_object(tid);
918 IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
919 hr = CoUnmarshalInterface(pStream, &IID_IClassFactory, (void **)&pProxy);
922 ok(hr == CO_E_OBJNOTREG,
923 "CoUnmarshalInterface should have failed with CO_E_OBJNOTREG, but returned 0x%08x instead\n",
926 IStream_Release(pStream);
930 end_host_object(tid, thread);
933 /* tests success case of a same-thread table-strong marshal, unmarshal, unmarshal */
934 static void test_tablestrong_marshal_and_unmarshal_twice(void)
937 IStream *pStream = NULL;
938 IUnknown *pProxy1 = NULL;
939 IUnknown *pProxy2 = NULL;
945 hr = CreateStreamOnHGlobal(NULL, TRUE, &pStream);
946 ok_ole_success(hr, CreateStreamOnHGlobal);
947 tid = start_host_object(pStream, &IID_IClassFactory, (IUnknown*)&Test_ClassFactory, MSHLFLAGS_TABLESTRONG, &thread);
949 ok_more_than_one_lock();
951 IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
952 hr = CoUnmarshalInterface(pStream, &IID_IClassFactory, (void **)&pProxy1);
953 ok_ole_success(hr, CoUnmarshalInterface);
955 ok_more_than_one_lock();
957 IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
958 hr = CoUnmarshalInterface(pStream, &IID_IClassFactory, (void **)&pProxy2);
959 ok_ole_success(hr, CoUnmarshalInterface);
961 ok_more_than_one_lock();
963 if (pProxy1) IUnknown_Release(pProxy1);
964 if (pProxy2) IUnknown_Release(pProxy2);
966 /* this line is shows the difference between weak and strong table marshaling:
967 * weak has cLocks == 0
968 * strong has cLocks > 0 */
969 ok_more_than_one_lock();
971 /* release the remaining reference on the object by calling
972 * CoReleaseMarshalData in the hosting thread */
973 IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
974 release_host_object(tid);
975 IStream_Release(pStream);
979 end_host_object(tid, thread);
982 /* tests CoLockObjectExternal */
983 static void test_lock_object_external(void)
986 IStream *pStream = NULL;
990 /* test the stub manager creation aspect of CoLockObjectExternal when the
991 * object hasn't been marshaled yet */
992 CoLockObjectExternal((IUnknown*)&Test_ClassFactory, TRUE, TRUE);
994 ok_more_than_one_lock();
996 CoDisconnectObject((IUnknown*)&Test_ClassFactory, 0);
1000 /* test our empty stub manager being handled correctly in
1001 * CoMarshalInterface */
1002 CoLockObjectExternal((IUnknown*)&Test_ClassFactory, TRUE, TRUE);
1004 hr = CreateStreamOnHGlobal(NULL, TRUE, &pStream);
1005 ok_ole_success(hr, CreateStreamOnHGlobal);
1006 hr = CoMarshalInterface(pStream, &IID_IClassFactory, (IUnknown*)&Test_ClassFactory, MSHCTX_INPROC, NULL, MSHLFLAGS_NORMAL);
1007 ok_ole_success(hr, CoMarshalInterface);
1009 CoLockObjectExternal((IUnknown*)&Test_ClassFactory, TRUE, TRUE);
1011 ok_more_than_one_lock();
1013 IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
1014 hr = CoReleaseMarshalData(pStream);
1015 ok_ole_success(hr, CoReleaseMarshalData);
1016 IStream_Release(pStream);
1018 ok_more_than_one_lock();
1020 CoLockObjectExternal((IUnknown*)&Test_ClassFactory, FALSE, TRUE);
1022 ok_more_than_one_lock();
1024 CoLockObjectExternal((IUnknown*)&Test_ClassFactory, FALSE, TRUE);
1029 /* tests disconnecting stubs */
1030 static void test_disconnect_stub(void)
1033 IStream *pStream = NULL;
1037 hr = CreateStreamOnHGlobal(NULL, TRUE, &pStream);
1038 ok_ole_success(hr, CreateStreamOnHGlobal);
1039 hr = CoMarshalInterface(pStream, &IID_IClassFactory, (IUnknown*)&Test_ClassFactory, MSHCTX_INPROC, NULL, MSHLFLAGS_NORMAL);
1040 ok_ole_success(hr, CoMarshalInterface);
1042 CoLockObjectExternal((IUnknown*)&Test_ClassFactory, TRUE, TRUE);
1044 ok_more_than_one_lock();
1046 IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
1047 hr = CoReleaseMarshalData(pStream);
1048 ok_ole_success(hr, CoReleaseMarshalData);
1049 IStream_Release(pStream);
1051 ok_more_than_one_lock();
1053 CoDisconnectObject((IUnknown*)&Test_ClassFactory, 0);
1058 /* tests failure case of a same-thread marshal and unmarshal twice */
1059 static void test_normal_marshal_and_unmarshal_twice(void)
1062 IStream *pStream = NULL;
1063 IUnknown *pProxy1 = NULL;
1064 IUnknown *pProxy2 = NULL;
1068 hr = CreateStreamOnHGlobal(NULL, TRUE, &pStream);
1069 ok_ole_success(hr, CreateStreamOnHGlobal);
1070 hr = CoMarshalInterface(pStream, &IID_IClassFactory, (IUnknown*)&Test_ClassFactory, MSHCTX_INPROC, NULL, MSHLFLAGS_NORMAL);
1071 ok_ole_success(hr, CoMarshalInterface);
1073 ok_more_than_one_lock();
1075 IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
1076 hr = CoUnmarshalInterface(pStream, &IID_IClassFactory, (void **)&pProxy1);
1077 ok_ole_success(hr, CoUnmarshalInterface);
1079 ok_more_than_one_lock();
1081 IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
1082 hr = CoUnmarshalInterface(pStream, &IID_IClassFactory, (void **)&pProxy2);
1083 ok(hr == CO_E_OBJNOTCONNECTED,
1084 "CoUnmarshalInterface should have failed with error CO_E_OBJNOTCONNECTED for double unmarshal, instead of 0x%08x\n", hr);
1086 IStream_Release(pStream);
1088 ok_more_than_one_lock();
1090 IUnknown_Release(pProxy1);
1095 /* tests success case of marshaling and unmarshaling an HRESULT */
1096 static void test_hresult_marshaling(void)
1099 HRESULT hr_marshaled = 0;
1100 IStream *pStream = NULL;
1101 static const HRESULT E_DEADBEEF = 0xdeadbeef;
1103 hr = CreateStreamOnHGlobal(NULL, TRUE, &pStream);
1104 ok_ole_success(hr, CreateStreamOnHGlobal);
1106 hr = CoMarshalHresult(pStream, E_DEADBEEF);
1107 ok_ole_success(hr, CoMarshalHresult);
1109 IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
1110 hr = IStream_Read(pStream, &hr_marshaled, sizeof(HRESULT), NULL);
1111 ok_ole_success(hr, IStream_Read);
1113 ok(hr_marshaled == E_DEADBEEF, "Didn't marshal HRESULT as expected: got value 0x%08x instead\n", hr_marshaled);
1116 IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
1117 hr = CoUnmarshalHresult(pStream, &hr_marshaled);
1118 ok_ole_success(hr, CoUnmarshalHresult);
1120 ok(hr_marshaled == E_DEADBEEF, "Didn't marshal HRESULT as expected: got value 0x%08x instead\n", hr_marshaled);
1122 IStream_Release(pStream);
1126 /* helper for test_proxy_used_in_wrong_thread */
1127 static DWORD CALLBACK bad_thread_proc(LPVOID p)
1129 IClassFactory * cf = (IClassFactory *)p;
1131 IUnknown * proxy = NULL;
1133 pCoInitializeEx(NULL, COINIT_MULTITHREADED);
1135 hr = IClassFactory_CreateInstance(cf, NULL, &IID_IUnknown, (LPVOID*)&proxy);
1136 if (proxy) IUnknown_Release(proxy);
1137 ok(hr == RPC_E_WRONG_THREAD,
1138 "COM should have failed with RPC_E_WRONG_THREAD on using proxy from wrong apartment, but instead returned 0x%08x\n",
1146 /* tests failure case of a using a proxy in the wrong apartment */
1147 static void test_proxy_used_in_wrong_thread(void)
1150 IStream *pStream = NULL;
1151 IUnknown *pProxy = NULL;
1158 hr = CreateStreamOnHGlobal(NULL, TRUE, &pStream);
1159 ok_ole_success(hr, CreateStreamOnHGlobal);
1160 tid = start_host_object(pStream, &IID_IClassFactory, (IUnknown*)&Test_ClassFactory, MSHLFLAGS_NORMAL, &host_thread);
1162 ok_more_than_one_lock();
1164 IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
1165 hr = CoUnmarshalInterface(pStream, &IID_IClassFactory, (void **)&pProxy);
1166 ok_ole_success(hr, CoUnmarshalInterface);
1167 IStream_Release(pStream);
1169 ok_more_than_one_lock();
1171 /* create a thread that we can misbehave in */
1172 thread = CreateThread(NULL, 0, bad_thread_proc, (LPVOID)pProxy, 0, &tid2);
1174 WaitForSingleObject(thread, INFINITE);
1175 CloseHandle(thread);
1177 IUnknown_Release(pProxy);
1181 end_host_object(tid, host_thread);
1184 static HRESULT WINAPI MessageFilter_QueryInterface(IMessageFilter *iface, REFIID riid, void ** ppvObj)
1186 if (ppvObj == NULL) return E_POINTER;
1188 if (IsEqualGUID(riid, &IID_IUnknown) ||
1189 IsEqualGUID(riid, &IID_IClassFactory))
1191 *ppvObj = (LPVOID)iface;
1192 IClassFactory_AddRef(iface);
1196 return E_NOINTERFACE;
1199 static ULONG WINAPI MessageFilter_AddRef(IMessageFilter *iface)
1201 return 2; /* non-heap object */
1204 static ULONG WINAPI MessageFilter_Release(IMessageFilter *iface)
1206 return 1; /* non-heap object */
1209 static DWORD WINAPI MessageFilter_HandleInComingCall(
1210 IMessageFilter *iface,
1212 HTASK threadIDCaller,
1214 LPINTERFACEINFO lpInterfaceInfo)
1216 static int callcount = 0;
1218 trace("HandleInComingCall\n");
1222 ret = SERVERCALL_REJECTED;
1225 ret = SERVERCALL_RETRYLATER;
1228 ret = SERVERCALL_ISHANDLED;
1235 static DWORD WINAPI MessageFilter_RetryRejectedCall(
1236 IMessageFilter *iface,
1237 HTASK threadIDCallee,
1241 trace("RetryRejectedCall\n");
1245 static DWORD WINAPI MessageFilter_MessagePending(
1246 IMessageFilter *iface,
1247 HTASK threadIDCallee,
1249 DWORD dwPendingType)
1251 trace("MessagePending\n");
1252 return PENDINGMSG_WAITNOPROCESS;
1255 static const IMessageFilterVtbl MessageFilter_Vtbl =
1257 MessageFilter_QueryInterface,
1258 MessageFilter_AddRef,
1259 MessageFilter_Release,
1260 MessageFilter_HandleInComingCall,
1261 MessageFilter_RetryRejectedCall,
1262 MessageFilter_MessagePending
1265 static IMessageFilter MessageFilter = { &MessageFilter_Vtbl };
1267 static void test_message_filter(void)
1270 IStream *pStream = NULL;
1271 IClassFactory *cf = NULL;
1273 IUnknown *proxy = NULL;
1274 IMessageFilter *prev_filter = NULL;
1279 hr = CreateStreamOnHGlobal(NULL, TRUE, &pStream);
1280 ok_ole_success(hr, CreateStreamOnHGlobal);
1281 tid = start_host_object2(pStream, &IID_IClassFactory, (IUnknown*)&Test_ClassFactory, MSHLFLAGS_NORMAL, &MessageFilter, &thread);
1283 ok_more_than_one_lock();
1285 IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
1286 hr = CoUnmarshalInterface(pStream, &IID_IClassFactory, (void **)&cf);
1287 ok_ole_success(hr, CoUnmarshalInterface);
1288 IStream_Release(pStream);
1290 ok_more_than_one_lock();
1292 hr = IClassFactory_CreateInstance(cf, NULL, &IID_IUnknown, (LPVOID*)&proxy);
1293 todo_wine { ok(hr == RPC_E_CALL_REJECTED, "Call should have returned RPC_E_CALL_REJECTED, but return 0x%08x instead\n", hr); }
1294 if (proxy) IUnknown_Release(proxy);
1297 hr = CoRegisterMessageFilter(&MessageFilter, &prev_filter);
1298 ok_ole_success(hr, CoRegisterMessageFilter);
1299 if (prev_filter) IMessageFilter_Release(prev_filter);
1301 hr = IClassFactory_CreateInstance(cf, NULL, &IID_IUnknown, (LPVOID*)&proxy);
1302 ok_ole_success(hr, IClassFactory_CreateInstance);
1304 IUnknown_Release(proxy);
1306 IClassFactory_Release(cf);
1310 end_host_object(tid, thread);
1313 /* test failure case of trying to unmarshal from bad stream */
1314 static void test_bad_marshal_stream(void)
1317 IStream *pStream = NULL;
1319 hr = CreateStreamOnHGlobal(NULL, TRUE, &pStream);
1320 ok_ole_success(hr, CreateStreamOnHGlobal);
1321 hr = CoMarshalInterface(pStream, &IID_IClassFactory, (IUnknown*)&Test_ClassFactory, MSHCTX_INPROC, NULL, MSHLFLAGS_NORMAL);
1322 ok_ole_success(hr, CoMarshalInterface);
1324 ok_more_than_one_lock();
1326 /* try to read beyond end of stream */
1327 hr = CoReleaseMarshalData(pStream);
1328 ok(hr == STG_E_READFAULT, "Should have failed with STG_E_READFAULT, but returned 0x%08x instead\n", hr);
1330 /* now release for real */
1331 IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
1332 hr = CoReleaseMarshalData(pStream);
1333 ok_ole_success(hr, CoReleaseMarshalData);
1335 IStream_Release(pStream);
1338 /* tests that proxies implement certain interfaces */
1339 static void test_proxy_interfaces(void)
1342 IStream *pStream = NULL;
1343 IUnknown *pProxy = NULL;
1344 IUnknown *pOtherUnknown = NULL;
1350 hr = CreateStreamOnHGlobal(NULL, TRUE, &pStream);
1351 ok_ole_success(hr, CreateStreamOnHGlobal);
1352 tid = start_host_object(pStream, &IID_IClassFactory, (IUnknown*)&Test_ClassFactory, MSHLFLAGS_NORMAL, &thread);
1354 ok_more_than_one_lock();
1356 IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
1357 hr = CoUnmarshalInterface(pStream, &IID_IUnknown, (void **)&pProxy);
1358 ok_ole_success(hr, CoUnmarshalInterface);
1359 IStream_Release(pStream);
1361 ok_more_than_one_lock();
1363 hr = IUnknown_QueryInterface(pProxy, &IID_IUnknown, (LPVOID*)&pOtherUnknown);
1364 ok_ole_success(hr, IUnknown_QueryInterface IID_IUnknown);
1365 if (hr == S_OK) IUnknown_Release(pOtherUnknown);
1367 hr = IUnknown_QueryInterface(pProxy, &IID_IClientSecurity, (LPVOID*)&pOtherUnknown);
1368 todo_wine { ok_ole_success(hr, IUnknown_QueryInterface IID_IClientSecurity); }
1369 if (hr == S_OK) IUnknown_Release(pOtherUnknown);
1371 hr = IUnknown_QueryInterface(pProxy, &IID_IMultiQI, (LPVOID*)&pOtherUnknown);
1372 ok_ole_success(hr, IUnknown_QueryInterface IID_IMultiQI);
1373 if (hr == S_OK) IUnknown_Release(pOtherUnknown);
1375 hr = IUnknown_QueryInterface(pProxy, &IID_IMarshal, (LPVOID*)&pOtherUnknown);
1376 ok_ole_success(hr, IUnknown_QueryInterface IID_IMarshal);
1377 if (hr == S_OK) IUnknown_Release(pOtherUnknown);
1379 /* IMarshal2 is also supported on NT-based systems, but is pretty much
1380 * useless as it has no more methods over IMarshal that it inherits from. */
1382 IUnknown_Release(pProxy);
1386 end_host_object(tid, thread);
1391 const IUnknownVtbl *lpVtbl;
1395 static HRESULT WINAPI HeapUnknown_QueryInterface(IUnknown *iface, REFIID riid, void **ppv)
1397 if (IsEqualIID(riid, &IID_IUnknown))
1399 IUnknown_AddRef(iface);
1400 *ppv = (LPVOID)iface;
1404 return E_NOINTERFACE;
1407 static ULONG WINAPI HeapUnknown_AddRef(IUnknown *iface)
1409 HeapUnknown *This = (HeapUnknown *)iface;
1410 trace("HeapUnknown_AddRef(%p)\n", iface);
1411 return InterlockedIncrement((LONG*)&This->refs);
1414 static ULONG WINAPI HeapUnknown_Release(IUnknown *iface)
1416 HeapUnknown *This = (HeapUnknown *)iface;
1417 ULONG refs = InterlockedDecrement((LONG*)&This->refs);
1418 trace("HeapUnknown_Release(%p)\n", iface);
1419 if (!refs) HeapFree(GetProcessHeap(), 0, This);
1423 static const IUnknownVtbl HeapUnknown_Vtbl =
1425 HeapUnknown_QueryInterface,
1430 static void test_proxybuffer(REFIID riid)
1433 IPSFactoryBuffer *psfb;
1434 IRpcProxyBuffer *proxy;
1438 HeapUnknown *pUnkOuter = (HeapUnknown *)HeapAlloc(GetProcessHeap(), 0, sizeof(*pUnkOuter));
1440 pUnkOuter->lpVtbl = &HeapUnknown_Vtbl;
1441 pUnkOuter->refs = 1;
1443 hr = CoGetPSClsid(riid, &clsid);
1444 ok_ole_success(hr, CoGetPSClsid);
1446 hr = CoGetClassObject(&clsid, CLSCTX_INPROC_SERVER, NULL, &IID_IPSFactoryBuffer, (LPVOID*)&psfb);
1447 ok_ole_success(hr, CoGetClassObject);
1449 hr = IPSFactoryBuffer_CreateProxy(psfb, (IUnknown*)pUnkOuter, riid, &proxy, &lpvtbl);
1450 ok_ole_success(hr, IPSFactoryBuffer_CreateProxy);
1451 ok(lpvtbl != NULL, "IPSFactoryBuffer_CreateProxy succeeded, but returned a NULL vtable!\n");
1453 /* release our reference to the outer unknown object - the PS factory
1454 * buffer will have AddRef's it in the CreateProxy call */
1455 refs = IUnknown_Release((IUnknown *)pUnkOuter);
1456 ok(refs == 1, "Ref count of outer unknown should have been 1 instead of %d\n", refs);
1458 refs = IPSFactoryBuffer_Release(psfb);
1459 #if 0 /* not reliable on native. maybe it leaks references! */
1460 ok(refs == 0, "Ref-count leak of %ld on IPSFactoryBuffer\n", refs);
1463 refs = IUnknown_Release((IUnknown *)lpvtbl);
1464 ok(refs == 0, "Ref-count leak of %d on IRpcProxyBuffer\n", refs);
1466 refs = IRpcProxyBuffer_Release(proxy);
1467 ok(refs == 0, "Ref-count leak of %d on IRpcProxyBuffer\n", refs);
1470 static void test_stubbuffer(REFIID riid)
1473 IPSFactoryBuffer *psfb;
1474 IRpcStubBuffer *stub;
1480 hr = CoGetPSClsid(riid, &clsid);
1481 ok_ole_success(hr, CoGetPSClsid);
1483 hr = CoGetClassObject(&clsid, CLSCTX_INPROC_SERVER, NULL, &IID_IPSFactoryBuffer, (LPVOID*)&psfb);
1484 ok_ole_success(hr, CoGetClassObject);
1486 hr = IPSFactoryBuffer_CreateStub(psfb, riid, (IUnknown*)&Test_ClassFactory, &stub);
1487 ok_ole_success(hr, IPSFactoryBuffer_CreateStub);
1489 refs = IPSFactoryBuffer_Release(psfb);
1490 #if 0 /* not reliable on native. maybe it leaks references */
1491 ok(refs == 0, "Ref-count leak of %ld on IPSFactoryBuffer\n", refs);
1494 ok_more_than_one_lock();
1496 IRpcStubBuffer_Disconnect(stub);
1500 refs = IRpcStubBuffer_Release(stub);
1501 ok(refs == 0, "Ref-count leak of %d on IRpcProxyBuffer\n", refs);
1504 static HWND hwnd_app;
1506 static HRESULT WINAPI TestRE_IClassFactory_CreateInstance(
1507 LPCLASSFACTORY iface,
1508 LPUNKNOWN pUnkOuter,
1513 if (IsEqualIID(riid, &IID_IWineTest))
1515 BOOL ret = SendMessageTimeout(hwnd_app, WM_NULL, 0, 0, SMTO_BLOCK, 5000, &res);
1516 ok(ret, "Timed out sending a message to originating window during RPC call\n");
1521 static const IClassFactoryVtbl TestREClassFactory_Vtbl =
1523 Test_IClassFactory_QueryInterface,
1524 Test_IClassFactory_AddRef,
1525 Test_IClassFactory_Release,
1526 TestRE_IClassFactory_CreateInstance,
1527 Test_IClassFactory_LockServer
1530 IClassFactory TestRE_ClassFactory = { &TestREClassFactory_Vtbl };
1532 static LRESULT CALLBACK window_proc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam)
1539 IStream *pStream = NULL;
1540 IClassFactory *proxy = NULL;
1547 hr = CreateStreamOnHGlobal(NULL, TRUE, &pStream);
1548 ok_ole_success(hr, CreateStreamOnHGlobal);
1549 tid = start_host_object(pStream, &IID_IClassFactory, (IUnknown*)&TestRE_ClassFactory, MSHLFLAGS_NORMAL, &thread);
1551 ok_more_than_one_lock();
1553 IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
1554 hr = CoUnmarshalInterface(pStream, &IID_IClassFactory, (void **)&proxy);
1555 ok_ole_success(hr, CoReleaseMarshalData);
1556 IStream_Release(pStream);
1558 ok_more_than_one_lock();
1560 /* note the use of the magic IID_IWineTest value to tell remote thread
1561 * to try to send a message back to us */
1562 hr = IClassFactory_CreateInstance(proxy, NULL, &IID_IWineTest, (void **)&object);
1564 IClassFactory_Release(proxy);
1568 end_host_object(tid, thread);
1570 PostMessage(hwnd, WM_QUIT, 0, 0);
1577 IStream *pStream = NULL;
1578 IClassFactory *proxy = NULL;
1585 hr = CreateStreamOnHGlobal(NULL, TRUE, &pStream);
1586 ok_ole_success(hr, CreateStreamOnHGlobal);
1587 tid = start_host_object(pStream, &IID_IClassFactory, (IUnknown*)&TestRE_ClassFactory, MSHLFLAGS_NORMAL, &thread);
1589 ok_more_than_one_lock();
1591 IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
1592 hr = CoUnmarshalInterface(pStream, &IID_IClassFactory, (void **)&proxy);
1593 ok_ole_success(hr, CoReleaseMarshalData);
1594 IStream_Release(pStream);
1596 ok_more_than_one_lock();
1598 /* post quit message before a doing a COM call to show that a pending
1599 * WM_QUIT message doesn't stop the call from succeeding */
1600 PostMessage(hwnd, WM_QUIT, 0, 0);
1601 hr = IClassFactory_CreateInstance(proxy, NULL, &IID_IUnknown, (void **)&object);
1603 IClassFactory_Release(proxy);
1607 end_host_object(tid, thread);
1612 return DefWindowProc(hwnd, msg, wparam, lparam);
1616 static void test_message_reentrancy(void)
1621 memset(&wndclass, 0, sizeof(wndclass));
1622 wndclass.lpfnWndProc = window_proc;
1623 wndclass.lpszClassName = "WineCOMTest";
1624 RegisterClass(&wndclass);
1626 hwnd_app = CreateWindow("WineCOMTest", NULL, 0, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, NULL, NULL, NULL, 0);
1627 ok(hwnd_app != NULL, "Window creation failed\n");
1629 /* start message re-entrancy test */
1630 PostMessage(hwnd_app, WM_USER, 0, 0);
1632 while (GetMessage(&msg, NULL, 0, 0))
1634 TranslateMessage(&msg);
1635 DispatchMessage(&msg);
1639 static void test_WM_QUIT_handling(void)
1643 hwnd_app = CreateWindow("WineCOMTest", NULL, 0, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, NULL, NULL, NULL, 0);
1644 ok(hwnd_app != NULL, "Window creation failed\n");
1646 /* start WM_QUIT handling test */
1647 PostMessage(hwnd_app, WM_USER+1, 0, 0);
1649 while (GetMessage(&msg, NULL, 0, 0))
1651 TranslateMessage(&msg);
1652 DispatchMessage(&msg);
1656 static void test_freethreadedmarshaldata(IStream *pStream, MSHCTX mshctx, void *ptr, DWORD mshlflags)
1663 hr = GetHGlobalFromStream(pStream, &hglobal);
1664 ok_ole_success(hr, GetHGlobalFromStream);
1666 size = GlobalSize(hglobal);
1668 marshal_data = (char *)GlobalLock(hglobal);
1670 if (mshctx == MSHCTX_INPROC)
1672 DWORD expected_size = sizeof(DWORD) + sizeof(void *) + sizeof(DWORD) + sizeof(GUID);
1673 ok(size == expected_size, "size should have been %d instead of %d\n", expected_size, size);
1675 ok(*(DWORD *)marshal_data == mshlflags, "expected 0x%x, but got 0x%x for mshctx\n", mshlflags, *(DWORD *)marshal_data);
1676 marshal_data += sizeof(DWORD);
1677 ok(*(void **)marshal_data == ptr, "expected %p, but got %p for mshctx\n", ptr, *(void **)marshal_data);
1678 marshal_data += sizeof(void *);
1679 ok(*(DWORD *)marshal_data == 0, "expected 0x0, but got 0x%x\n", *(DWORD *)marshal_data);
1680 marshal_data += sizeof(DWORD);
1681 trace("got guid data: {%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x}\n",
1682 ((GUID *)marshal_data)->Data1, ((GUID *)marshal_data)->Data2, ((GUID *)marshal_data)->Data3,
1683 ((GUID *)marshal_data)->Data4[0], ((GUID *)marshal_data)->Data4[1], ((GUID *)marshal_data)->Data4[2], ((GUID *)marshal_data)->Data4[3],
1684 ((GUID *)marshal_data)->Data4[4], ((GUID *)marshal_data)->Data4[5], ((GUID *)marshal_data)->Data4[6], ((GUID *)marshal_data)->Data4[7]);
1688 ok(size > sizeof(DWORD), "size should have been > sizeof(DWORD), not %d\n", size);
1689 ok(*(DWORD *)marshal_data == 0x574f454d /* MEOW */,
1690 "marshal data should be filled by standard marshal and start with MEOW signature\n");
1693 GlobalUnlock(hglobal);
1696 static void test_freethreadedmarshaler(void)
1699 IUnknown *pFTUnknown;
1700 IMarshal *pFTMarshal;
1703 static const LARGE_INTEGER llZero;
1706 hr = CoCreateFreeThreadedMarshaler(NULL, &pFTUnknown);
1707 ok_ole_success(hr, CoCreateFreeThreadedMarshaler);
1708 hr = IUnknown_QueryInterface(pFTUnknown, &IID_IMarshal, (void **)&pFTMarshal);
1709 ok_ole_success(hr, IUnknown_QueryInterface);
1710 IUnknown_Release(pFTUnknown);
1712 hr = CreateStreamOnHGlobal(NULL, TRUE, &pStream);
1713 ok_ole_success(hr, CreateStreamOnHGlobal);
1715 /* inproc normal marshaling */
1717 hr = IMarshal_MarshalInterface(pFTMarshal, pStream, &IID_IClassFactory,
1718 (IUnknown*)&Test_ClassFactory, MSHCTX_INPROC, NULL, MSHLFLAGS_NORMAL);
1719 ok_ole_success(hr, IMarshal_MarshalInterface);
1721 ok_more_than_one_lock();
1723 test_freethreadedmarshaldata(pStream, MSHCTX_INPROC, &Test_ClassFactory, MSHLFLAGS_NORMAL);
1725 IStream_Seek(pStream, llZero, STREAM_SEEK_SET, NULL);
1726 hr = IMarshal_UnmarshalInterface(pFTMarshal, pStream, &IID_IUnknown, (void **)&pProxy);
1727 ok_ole_success(hr, IMarshal_UnmarshalInterface);
1729 IUnknown_Release(pProxy);
1733 /* native doesn't allow us to unmarshal or release the stream data,
1734 * presumably because it wants us to call CoMarshalInterface instead */
1736 /* local normal marshaling */
1738 IStream_Seek(pStream, llZero, STREAM_SEEK_SET, NULL);
1739 hr = IMarshal_MarshalInterface(pFTMarshal, pStream, IID_IClassFactory, (IUnknown*)&Test_ClassFactory, MSHCTX_LOCAL, NULL, MSHLFLAGS_NORMAL);
1740 ok_ole_success(hr, IMarshal_MarshalInterface);
1742 ok_more_than_one_lock();
1744 test_freethreadedmarshaldata(pStream, MSHCTX_LOCAL, &Test_ClassFactory, MSHLFLAGS_NORMAL);
1746 IStream_Seek(pStream, llZero, STREAM_SEEK_SET, NULL);
1747 hr = IMarshal_ReleaseMarshalData(pFTMarshal, pStream);
1748 ok_ole_success(hr, IMarshal_ReleaseMarshalData);
1753 /* inproc table-strong marshaling */
1755 IStream_Seek(pStream, llZero, STREAM_SEEK_SET, NULL);
1756 hr = IMarshal_MarshalInterface(pFTMarshal, pStream, &IID_IClassFactory,
1757 (IUnknown*)&Test_ClassFactory, MSHCTX_INPROC, (void *)0xdeadbeef,
1758 MSHLFLAGS_TABLESTRONG);
1759 ok_ole_success(hr, IMarshal_MarshalInterface);
1761 ok_more_than_one_lock();
1763 test_freethreadedmarshaldata(pStream, MSHCTX_INPROC, &Test_ClassFactory, MSHLFLAGS_TABLESTRONG);
1765 IStream_Seek(pStream, llZero, STREAM_SEEK_SET, NULL);
1766 hr = IMarshal_UnmarshalInterface(pFTMarshal, pStream, &IID_IUnknown, (void **)&pProxy);
1767 ok_ole_success(hr, IMarshal_UnmarshalInterface);
1769 IUnknown_Release(pProxy);
1771 ok_more_than_one_lock();
1773 IStream_Seek(pStream, llZero, STREAM_SEEK_SET, NULL);
1774 hr = IMarshal_ReleaseMarshalData(pFTMarshal, pStream);
1775 ok_ole_success(hr, IMarshal_ReleaseMarshalData);
1779 /* inproc table-weak marshaling */
1781 IStream_Seek(pStream, llZero, STREAM_SEEK_SET, NULL);
1782 hr = IMarshal_MarshalInterface(pFTMarshal, pStream, &IID_IClassFactory,
1783 (IUnknown*)&Test_ClassFactory, MSHCTX_INPROC, (void *)0xdeadbeef,
1784 MSHLFLAGS_TABLEWEAK);
1785 ok_ole_success(hr, IMarshal_MarshalInterface);
1789 test_freethreadedmarshaldata(pStream, MSHCTX_INPROC, &Test_ClassFactory, MSHLFLAGS_TABLEWEAK);
1791 IStream_Seek(pStream, llZero, STREAM_SEEK_SET, NULL);
1792 hr = IMarshal_UnmarshalInterface(pFTMarshal, pStream, &IID_IUnknown, (void **)&pProxy);
1793 ok_ole_success(hr, IMarshal_UnmarshalInterface);
1795 ok_more_than_one_lock();
1797 IUnknown_Release(pProxy);
1801 /* inproc normal marshaling (for extraordinary cases) */
1803 IStream_Seek(pStream, llZero, STREAM_SEEK_SET, NULL);
1804 hr = IMarshal_MarshalInterface(pFTMarshal, pStream, &IID_IClassFactory,
1805 (IUnknown*)&Test_ClassFactory, MSHCTX_INPROC, NULL, MSHLFLAGS_NORMAL);
1806 ok_ole_success(hr, IMarshal_MarshalInterface);
1808 ok_more_than_one_lock();
1810 /* this call shows that DisconnectObject does nothing */
1811 hr = IMarshal_DisconnectObject(pFTMarshal, 0);
1812 ok_ole_success(hr, IMarshal_DisconnectObject);
1814 ok_more_than_one_lock();
1816 IStream_Seek(pStream, llZero, STREAM_SEEK_SET, NULL);
1817 hr = IMarshal_ReleaseMarshalData(pFTMarshal, pStream);
1818 ok_ole_success(hr, IMarshal_ReleaseMarshalData);
1822 /* doesn't enforce marshaling rules here and allows us to unmarshal the
1823 * interface, even though it was freed above */
1824 IStream_Seek(pStream, llZero, STREAM_SEEK_SET, NULL);
1825 hr = IMarshal_UnmarshalInterface(pFTMarshal, pStream, &IID_IUnknown, (void **)&pProxy);
1826 ok_ole_success(hr, IMarshal_UnmarshalInterface);
1830 IStream_Release(pStream);
1831 IMarshal_Release(pFTMarshal);
1834 static HANDLE heventShutdown;
1836 static void LockModuleOOP(void)
1838 InterlockedIncrement(&cLocks); /* for test purposes only */
1839 CoAddRefServerProcess();
1842 static void UnlockModuleOOP(void)
1844 InterlockedDecrement(&cLocks); /* for test purposes only */
1845 if (!CoReleaseServerProcess())
1846 SetEvent(heventShutdown);
1849 static HWND hwnd_app;
1851 static HRESULT WINAPI TestOOP_IClassFactory_QueryInterface(
1852 LPCLASSFACTORY iface,
1856 if (ppvObj == NULL) return E_POINTER;
1858 if (IsEqualGUID(riid, &IID_IUnknown) ||
1859 IsEqualGUID(riid, &IID_IClassFactory))
1861 *ppvObj = (LPVOID)iface;
1862 IClassFactory_AddRef(iface);
1866 return E_NOINTERFACE;
1869 static ULONG WINAPI TestOOP_IClassFactory_AddRef(LPCLASSFACTORY iface)
1871 return 2; /* non-heap-based object */
1874 static ULONG WINAPI TestOOP_IClassFactory_Release(LPCLASSFACTORY iface)
1876 return 1; /* non-heap-based object */
1879 static HRESULT WINAPI TestOOP_IClassFactory_CreateInstance(
1880 LPCLASSFACTORY iface,
1881 LPUNKNOWN pUnkOuter,
1885 return CLASS_E_CLASSNOTAVAILABLE;
1888 static HRESULT WINAPI TestOOP_IClassFactory_LockServer(
1889 LPCLASSFACTORY iface,
1899 static const IClassFactoryVtbl TestClassFactoryOOP_Vtbl =
1901 TestOOP_IClassFactory_QueryInterface,
1902 TestOOP_IClassFactory_AddRef,
1903 TestOOP_IClassFactory_Release,
1904 TestOOP_IClassFactory_CreateInstance,
1905 TestOOP_IClassFactory_LockServer
1908 static IClassFactory TestOOP_ClassFactory = { &TestClassFactoryOOP_Vtbl };
1910 /* tests functions commonly used by out of process COM servers */
1911 static void test_out_of_process_com(void)
1913 static const CLSID CLSID_WineOOPTest = {
1917 {0xa1, 0xa2, 0x5d, 0x5a, 0x36, 0x54, 0xd3, 0xbd}
1918 }; /* 5201163f-8164-4fd0-a1a2-5d5a3654d3bd */
1924 heventShutdown = CreateEvent(NULL, TRUE, FALSE, NULL);
1928 /* Start the object suspended */
1929 hr = CoRegisterClassObject(&CLSID_WineOOPTest, (IUnknown *)&TestOOP_ClassFactory,
1930 CLSCTX_LOCAL_SERVER, REGCLS_MULTIPLEUSE | REGCLS_SUSPENDED, &cookie);
1931 ok_ole_success(hr, CoRegisterClassObject);
1933 /* ... and CoGetClassObject does not find it and fails when it looks for the
1934 * class in the registry */
1935 hr = CoGetClassObject(&CLSID_WineOOPTest, CLSCTX_INPROC_SERVER,
1936 NULL, &IID_IClassFactory, (LPVOID*)&cf);
1938 ok(hr == REGDB_E_CLASSNOTREG,
1939 "CoGetClassObject should have returned REGDB_E_CLASSNOTREG instead of 0x%08x\n", hr);
1942 /* Resume the object suspended above ... */
1943 hr = CoResumeClassObjects();
1944 ok_ole_success(hr, CoResumeClassObjects);
1946 /* ... and now it should succeed */
1947 hr = CoGetClassObject(&CLSID_WineOOPTest, CLSCTX_INPROC_SERVER,
1948 NULL, &IID_IClassFactory, (LPVOID*)&cf);
1949 ok_ole_success(hr, CoGetClassObject);
1951 /* Now check the locking is working */
1952 /* NOTE: we are accessing the class directly, not through a proxy */
1956 hr = IClassFactory_LockServer(cf, TRUE);
1957 trace("IClassFactory_LockServer returned 0x%08x\n", hr);
1959 ok_more_than_one_lock();
1961 IClassFactory_LockServer(cf, FALSE);
1965 IClassFactory_Release(cf);
1967 /* wait for shutdown signal */
1968 ret = WaitForSingleObject(heventShutdown, 5000);
1969 todo_wine { ok(ret != WAIT_TIMEOUT, "Server didn't shut down or machine is under very heavy load\n"); }
1971 /* try to connect again after SCM has suspended registered class objects */
1972 hr = CoGetClassObject(&CLSID_WineOOPTest, CLSCTX_INPROC_SERVER | CLSCTX_LOCAL_SERVER, NULL,
1973 &IID_IClassFactory, (LPVOID*)&cf);
1975 ok(hr == CO_E_SERVER_STOPPING,
1976 "CoGetClassObject should have returned CO_E_SERVER_STOPPING instead of 0x%08x\n", hr);
1979 hr = CoRevokeClassObject(cookie);
1980 ok_ole_success(hr, CoRevokeClassObject);
1982 CloseHandle(heventShutdown);
1985 static void test_ROT(void)
1987 static const WCHAR wszFileName[] = {'B','E','2','0','E','2','F','5','-',
1988 '1','9','0','3','-','4','A','A','E','-','B','1','A','F','-',
1989 '2','0','4','6','E','5','8','6','C','9','2','5',0};
1991 IMoniker *pMoniker = NULL;
1992 IRunningObjectTable *pROT = NULL;
1997 hr = CreateFileMoniker(wszFileName, &pMoniker);
1998 ok_ole_success(hr, CreateClassMoniker);
1999 hr = GetRunningObjectTable(0, &pROT);
2000 ok_ole_success(hr, GetRunningObjectTable);
2001 hr = IRunningObjectTable_Register(pROT, 0, (IUnknown*)&Test_ClassFactory, pMoniker, &dwCookie);
2002 ok_ole_success(hr, IRunningObjectTable_Register);
2003 IMoniker_Release(pMoniker);
2005 ok_more_than_one_lock();
2007 hr = IRunningObjectTable_Revoke(pROT, dwCookie);
2008 ok_ole_success(hr, IRunningObjectTable_Revoke);
2016 IGlobalInterfaceTable *git;
2019 static DWORD CALLBACK get_global_interface_proc(LPVOID pv)
2022 struct git_params *params = (struct git_params *)pv;
2025 hr = IGlobalInterfaceTable_GetInterfaceFromGlobal(params->git, params->cookie, &IID_IClassFactory, (void **)&cf);
2026 ok(hr == CO_E_NOTINITIALIZED,
2027 "IGlobalInterfaceTable_GetInterfaceFromGlobal should have failed with error CO_E_NOTINITIALIZED instead of 0x%08x\n",
2031 hr = IGlobalInterfaceTable_GetInterfaceFromGlobal(params->git, params->cookie, &IID_IClassFactory, (void **)&cf);
2032 ok_ole_success(hr, IGlobalInterfaceTable_GetInterfaceFromGlobal);
2038 static void test_globalinterfacetable(void)
2041 IGlobalInterfaceTable *git;
2045 struct git_params params;
2048 hr = CoCreateInstance(&CLSID_StdGlobalInterfaceTable, NULL, CLSCTX_INPROC_SERVER, &IID_IGlobalInterfaceTable, (void **)&git);
2049 ok_ole_success(hr, CoCreateInstance);
2051 hr = IGlobalInterfaceTable_RegisterInterfaceInGlobal(git, (IUnknown *)&Test_ClassFactory, &IID_IClassFactory, &cookie);
2052 ok_ole_success(hr, IGlobalInterfaceTable_RegisterInterfaceInGlobal);
2054 params.cookie = cookie;
2056 /* note: params is on stack so we MUST wait for get_global_interface_proc
2057 * to exit before we can return */
2058 thread = CreateThread(NULL, 0, get_global_interface_proc, ¶ms, 0, &tid);
2060 ret = MsgWaitForMultipleObjects(1, &thread, FALSE, INFINITE, QS_ALLINPUT);
2061 while (ret == WAIT_OBJECT_0 + 1)
2064 while (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
2065 DispatchMessage(&msg);
2066 ret = MsgWaitForMultipleObjects(1, &thread, FALSE, INFINITE, QS_ALLINPUT);
2069 CloseHandle(thread);
2072 static const char cf_marshaled[] =
2084 static void test_marshal_CLIPFORMAT(void)
2086 unsigned char *buffer;
2088 ULONG flags = MAKELONG(MSHCTX_DIFFERENTMACHINE, NDR_LOCAL_DATA_REPRESENTATION);
2089 wireCLIPFORMAT wirecf;
2090 CLIPFORMAT cf = RegisterClipboardFormatA("MyFormat");
2093 size = CLIPFORMAT_UserSize(&flags, 0, &cf);
2094 ok(size == sizeof(*wirecf) + sizeof(cf_marshaled), "Wrong size %d\n", size);
2096 buffer = HeapAlloc(GetProcessHeap(), 0, size);
2097 CLIPFORMAT_UserMarshal(&flags, buffer, &cf);
2098 wirecf = (wireCLIPFORMAT)buffer;
2099 ok(wirecf->fContext == WDT_REMOTE_CALL, "Context should be WDT_REMOTE_CALL instead of 0x%08lx\n", wirecf->fContext);
2100 ok(wirecf->u.dwValue == cf, "Marshaled value should be 0x%04x instead of 0x%04x\n", cf, wirecf->u.dwValue);
2101 ok(!memcmp(wirecf+1, cf_marshaled, sizeof(cf_marshaled)), "Marshaled data differs\n");
2103 CLIPFORMAT_UserUnmarshal(&flags, buffer, &cf2);
2104 ok(cf == cf2, "Didn't unmarshal properly\n");
2105 HeapFree(GetProcessHeap(), 0, buffer);
2107 CLIPFORMAT_UserFree(&flags, &cf2);
2110 static void test_marshal_HWND(void)
2112 unsigned char *buffer;
2114 ULONG flags = MAKELONG(MSHCTX_LOCAL, NDR_LOCAL_DATA_REPRESENTATION);
2115 HWND hwnd = GetDesktopWindow();
2119 size = HWND_UserSize(&flags, 0, &hwnd);
2120 ok(size == sizeof(*wirehwnd), "Wrong size %d\n", size);
2122 buffer = HeapAlloc(GetProcessHeap(), 0, size);
2123 HWND_UserMarshal(&flags, buffer, &hwnd);
2124 wirehwnd = (wireHWND)buffer;
2125 ok(wirehwnd->fContext == WDT_INPROC_CALL, "Context should be WDT_INPROC_CALL instead of 0x%08lx\n", wirehwnd->fContext);
2126 ok(wirehwnd->u.hInproc == (LONG_PTR)hwnd, "Marshaled value should be %p instead of %p\n", hwnd, (HANDLE)wirehwnd->u.hRemote);
2128 HWND_UserUnmarshal(&flags, buffer, &hwnd2);
2129 ok(hwnd == hwnd2, "Didn't unmarshal properly\n");
2130 HeapFree(GetProcessHeap(), 0, buffer);
2132 HWND_UserFree(&flags, &hwnd2);
2135 static void test_marshal_HGLOBAL(void)
2137 unsigned char *buffer;
2139 ULONG flags = MAKELONG(MSHCTX_LOCAL, NDR_LOCAL_DATA_REPRESENTATION);
2142 unsigned char *wirehglobal;
2146 flags = MAKELONG(MSHCTX_LOCAL, NDR_LOCAL_DATA_REPRESENTATION);
2147 size = HGLOBAL_UserSize(&flags, 0, &hglobal);
2148 /* native is poorly programmed and allocates 4 bytes more than it needs to
2149 * here - Wine doesn't have to emulate that */
2150 ok((size == 8) || (size == 12), "Size should be 12, instead of %d\n", size);
2151 buffer = HeapAlloc(GetProcessHeap(), 0, size);
2152 HGLOBAL_UserMarshal(&flags, buffer, &hglobal);
2153 wirehglobal = buffer;
2154 ok(*(ULONG *)wirehglobal == WDT_REMOTE_CALL, "Context should be WDT_REMOTE_CALL instead of 0x%08x\n", *(ULONG *)wirehglobal);
2155 wirehglobal += sizeof(ULONG);
2156 ok(*(ULONG *)wirehglobal == (ULONG)hglobal, "buffer+4 should be HGLOBAL\n");
2157 HGLOBAL_UserUnmarshal(&flags, buffer, &hglobal2);
2158 ok(hglobal2 == hglobal, "Didn't unmarshal properly\n");
2159 HeapFree(GetProcessHeap(), 0, buffer);
2160 HGLOBAL_UserFree(&flags, &hglobal2);
2162 hglobal = GlobalAlloc(0, 4);
2163 buffer = GlobalLock(hglobal);
2164 for (i = 0; i < 4; i++)
2166 GlobalUnlock(hglobal);
2167 flags = MAKELONG(MSHCTX_LOCAL, NDR_LOCAL_DATA_REPRESENTATION);
2168 size = HGLOBAL_UserSize(&flags, 0, &hglobal);
2169 /* native is poorly programmed and allocates 4 bytes more than it needs to
2170 * here - Wine doesn't have to emulate that */
2171 ok((size == 24) || (size == 28), "Size should be 24 or 28, instead of %d\n", size);
2172 buffer = HeapAlloc(GetProcessHeap(), 0, size);
2173 HGLOBAL_UserMarshal(&flags, buffer, &hglobal);
2174 wirehglobal = buffer;
2175 ok(*(ULONG *)wirehglobal == WDT_REMOTE_CALL, "Context should be WDT_REMOTE_CALL instead of 0x%08x\n", *(ULONG *)wirehglobal);
2176 wirehglobal += sizeof(ULONG);
2177 ok(*(ULONG *)wirehglobal == (ULONG)hglobal, "buffer+0x4 should be HGLOBAL\n");
2178 wirehglobal += sizeof(ULONG);
2179 ok(*(ULONG *)wirehglobal == 4, "buffer+0x8 should be size of HGLOBAL\n");
2180 wirehglobal += sizeof(ULONG);
2181 ok(*(ULONG *)wirehglobal == (ULONG)hglobal, "buffer+0xc should be HGLOBAL\n");
2182 wirehglobal += sizeof(ULONG);
2183 ok(*(ULONG *)wirehglobal == 4, "buffer+0x10 should be size of HGLOBAL\n");
2184 wirehglobal += sizeof(ULONG);
2185 for (i = 0; i < 4; i++)
2186 ok(wirehglobal[i] == i, "buffer+0x%x should be %d\n", 0x10 + i, i);
2187 HGLOBAL_UserUnmarshal(&flags, buffer, &hglobal2);
2188 ok(hglobal2 != NULL, "Didn't unmarshal properly\n");
2189 HeapFree(GetProcessHeap(), 0, buffer);
2190 HGLOBAL_UserFree(&flags, &hglobal2);
2191 GlobalFree(hglobal);
2194 static HENHMETAFILE create_emf(void)
2196 RECT rect = {0, 0, 100, 100};
2197 HDC hdc = CreateEnhMetaFile(NULL, NULL, &rect, "HENHMETAFILE Marshaling Test\0Test\0\0");
2198 ExtTextOut(hdc, 0, 0, ETO_OPAQUE, NULL, "Test String", strlen("Test String"), NULL);
2199 return CloseEnhMetaFile(hdc);
2202 static void test_marshal_HENHMETAFILE(void)
2204 unsigned char *buffer;
2206 ULONG flags = MAKELONG(MSHCTX_DIFFERENTMACHINE, NDR_LOCAL_DATA_REPRESENTATION);
2208 HENHMETAFILE hemf2 = NULL;
2209 unsigned char *wirehemf;
2211 hemf = create_emf();
2213 size = HENHMETAFILE_UserSize(&flags, 0, &hemf);
2214 ok(size > 20, "size should be at least 20 bytes, not %d\n", size);
2215 buffer = HeapAlloc(GetProcessHeap(), 0, size);
2216 HENHMETAFILE_UserMarshal(&flags, buffer, &hemf);
2218 ok(*(DWORD *)wirehemf == WDT_REMOTE_CALL, "wirestgm + 0x0 should be WDT_REMOTE_CALL instead of 0x%08x\n", *(DWORD *)wirehemf);
2219 wirehemf += sizeof(DWORD);
2220 ok(*(DWORD *)wirehemf == (DWORD)(DWORD_PTR)hemf, "wirestgm + 0x4 should be hemf instead of 0x%08x\n", *(DWORD *)wirehemf);
2221 wirehemf += sizeof(DWORD);
2222 ok(*(DWORD *)wirehemf == (size - 0x10), "wirestgm + 0x8 should be size - 0x10 instead of 0x%08x\n", *(DWORD *)wirehemf);
2223 wirehemf += sizeof(DWORD);
2224 ok(*(DWORD *)wirehemf == (size - 0x10), "wirestgm + 0xc should be size - 0x10 instead of 0x%08x\n", *(DWORD *)wirehemf);
2225 wirehemf += sizeof(DWORD);
2226 ok(*(DWORD *)wirehemf == EMR_HEADER, "wirestgm + 0x10 should be EMR_HEADER instead of %d\n", *(DWORD *)wirehemf);
2227 wirehemf += sizeof(DWORD);
2228 /* ... rest of data not tested - refer to tests for GetEnhMetaFileBits
2231 HENHMETAFILE_UserUnmarshal(&flags, buffer, &hemf2);
2232 ok(hemf2 != NULL, "HENHMETAFILE didn't unmarshal\n");
2233 HeapFree(GetProcessHeap(), 0, buffer);
2234 HENHMETAFILE_UserFree(&flags, &hemf2);
2235 DeleteEnhMetaFile(hemf);
2240 size = HENHMETAFILE_UserSize(&flags, 0, &hemf);
2241 ok(size == 8, "size should be 8 bytes, not %d\n", size);
2242 buffer = (unsigned char *)HeapAlloc(GetProcessHeap(), 0, size);
2243 HENHMETAFILE_UserMarshal(&flags, buffer, &hemf);
2245 ok(*(DWORD *)wirehemf == WDT_REMOTE_CALL, "wirestgm + 0x0 should be WDT_REMOTE_CALL instead of 0x%08x\n", *(DWORD *)wirehemf);
2246 wirehemf += sizeof(DWORD);
2247 ok(*(DWORD *)wirehemf == (DWORD)(DWORD_PTR)hemf, "wirestgm + 0x4 should be hemf instead of 0x%08x\n", *(DWORD *)wirehemf);
2248 wirehemf += sizeof(DWORD);
2250 HENHMETAFILE_UserUnmarshal(&flags, buffer, &hemf2);
2251 ok(hemf2 == NULL, "NULL HENHMETAFILE didn't unmarshal\n");
2252 HeapFree(GetProcessHeap(), 0, buffer);
2253 HENHMETAFILE_UserFree(&flags, &hemf2);
2256 static void test_CoGetInterfaceAndReleaseStream(void)
2261 hr = CoGetInterfaceAndReleaseStream(NULL, &IID_IUnknown, (void**)&pUnk);
2262 ok(hr == E_INVALIDARG, "hr %08x\n", hr);
2268 HMODULE hOle32 = GetModuleHandle("ole32");
2269 if (!(pCoInitializeEx = (void*)GetProcAddress(hOle32, "CoInitializeEx"))) goto no_test;
2271 /* register a window class used in several tests */
2272 memset(&wndclass, 0, sizeof(wndclass));
2273 wndclass.lpfnWndProc = window_proc;
2274 wndclass.lpszClassName = "WineCOMTest";
2275 RegisterClass(&wndclass);
2277 test_cocreateinstance_proxy();
2279 pCoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
2281 /* FIXME: test CoCreateInstanceEx */
2283 /* lifecycle management and marshaling tests */
2284 test_no_marshaler();
2285 test_normal_marshal_and_release();
2286 test_normal_marshal_and_unmarshal();
2287 test_marshal_and_unmarshal_invalid();
2288 test_interthread_marshal_and_unmarshal();
2289 test_proxy_marshal_and_unmarshal();
2290 test_proxy_marshal_and_unmarshal2();
2291 test_marshal_stub_apartment_shutdown();
2292 test_marshal_proxy_apartment_shutdown();
2293 test_marshal_proxy_mta_apartment_shutdown();
2294 test_no_couninitialize_server();
2295 test_no_couninitialize_client();
2296 test_tableweak_marshal_and_unmarshal_twice();
2297 test_tableweak_marshal_releasedata1();
2298 test_tableweak_marshal_releasedata2();
2299 test_tablestrong_marshal_and_unmarshal_twice();
2300 test_lock_object_external();
2301 test_disconnect_stub();
2302 test_normal_marshal_and_unmarshal_twice();
2303 test_hresult_marshaling();
2304 test_proxy_used_in_wrong_thread();
2305 test_message_filter();
2306 test_bad_marshal_stream();
2307 test_proxy_interfaces();
2308 test_stubbuffer(&IID_IClassFactory);
2309 test_proxybuffer(&IID_IClassFactory);
2310 test_message_reentrancy();
2311 test_WM_QUIT_handling();
2312 test_freethreadedmarshaler();
2314 /* doesn't pass with Win9x COM DLLs (even though Essential COM says it should) */
2315 if (0) test_out_of_process_com();
2318 test_globalinterfacetable();
2320 test_marshal_CLIPFORMAT();
2321 test_marshal_HWND();
2322 test_marshal_HGLOBAL();
2323 test_marshal_HENHMETAFILE();
2325 test_CoGetInterfaceAndReleaseStream();
2331 trace("You need DCOM95 installed to run this test\n");