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 %ld\n", cLocks)
39 #define ok_no_locks() ok(cLocks == 0, "Number of locks should be 0, but actually is %ld\n", cLocks)
40 #define ok_ole_success(hr, func) ok(hr == S_OK, #func " failed with error 0x%08lx\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 %ld\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%08lx\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%08lx\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);
760 ok_more_than_one_lock();
762 /* die without calling CoUninitialize */
767 /* tests STA -> STA call during DLL_THREAD_DETACH doesn't deadlock */
768 static void test_no_couninitialize_client(void)
771 IStream *pStream = NULL;
776 struct ncu_params ncu_params;
780 hr = CreateStreamOnHGlobal(NULL, TRUE, &pStream);
781 ok_ole_success(hr, CreateStreamOnHGlobal);
782 ncu_params.stream = pStream;
784 /* NOTE: assumes start_host_object uses an STA to host the object, as MTAs
785 * always deadlock when called from within DllMain */
786 host_tid = start_host_object(pStream, &IID_IClassFactory, (IUnknown *)&Test_ClassFactory, MSHLFLAGS_NORMAL, &host_thread);
787 IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
789 ok_more_than_one_lock();
791 thread = CreateThread(NULL, 0, no_couninitialize_client_proc, &ncu_params, 0, &tid);
793 WaitForSingleObject(thread, INFINITE);
798 end_host_object(host_tid, host_thread);
801 /* tests success case of a same-thread table-weak marshal, unmarshal, unmarshal */
802 static void test_tableweak_marshal_and_unmarshal_twice(void)
805 IStream *pStream = NULL;
806 IUnknown *pProxy1 = NULL;
807 IUnknown *pProxy2 = NULL;
813 hr = CreateStreamOnHGlobal(NULL, TRUE, &pStream);
814 ok_ole_success(hr, CreateStreamOnHGlobal);
815 tid = start_host_object(pStream, &IID_IClassFactory, (IUnknown*)&Test_ClassFactory, MSHLFLAGS_TABLEWEAK, &thread);
817 ok_more_than_one_lock();
819 IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
820 hr = CoUnmarshalInterface(pStream, &IID_IClassFactory, (void **)&pProxy1);
821 ok_ole_success(hr, CoUnmarshalInterface);
823 ok_more_than_one_lock();
825 IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
826 hr = CoUnmarshalInterface(pStream, &IID_IClassFactory, (void **)&pProxy2);
827 ok_ole_success(hr, CoUnmarshalInterface);
829 ok_more_than_one_lock();
831 IUnknown_Release(pProxy1);
832 IUnknown_Release(pProxy2);
834 /* this line is shows the difference between weak and strong table marshaling:
835 * weak has cLocks == 0
836 * strong has cLocks > 0 */
839 end_host_object(tid, thread);
842 /* tests releasing after unmarshaling one object */
843 static void test_tableweak_marshal_releasedata1(void)
846 IStream *pStream = NULL;
847 IUnknown *pProxy1 = NULL;
848 IUnknown *pProxy2 = NULL;
854 hr = CreateStreamOnHGlobal(NULL, TRUE, &pStream);
855 ok_ole_success(hr, CreateStreamOnHGlobal);
856 tid = start_host_object(pStream, &IID_IClassFactory, (IUnknown*)&Test_ClassFactory, MSHLFLAGS_TABLEWEAK, &thread);
858 ok_more_than_one_lock();
860 IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
861 hr = CoUnmarshalInterface(pStream, &IID_IClassFactory, (void **)&pProxy1);
862 ok_ole_success(hr, CoUnmarshalInterface);
864 ok_more_than_one_lock();
866 /* release the remaining reference on the object by calling
867 * CoReleaseMarshalData in the hosting thread */
868 IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
869 release_host_object(tid);
871 ok_more_than_one_lock();
873 IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
874 hr = CoUnmarshalInterface(pStream, &IID_IClassFactory, (void **)&pProxy2);
875 ok_ole_success(hr, CoUnmarshalInterface);
876 IStream_Release(pStream);
878 ok_more_than_one_lock();
880 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_releasedata2(void)
896 IStream *pStream = NULL;
897 IUnknown *pProxy = NULL;
903 hr = CreateStreamOnHGlobal(NULL, TRUE, &pStream);
904 ok_ole_success(hr, CreateStreamOnHGlobal);
905 tid = start_host_object(pStream, &IID_IClassFactory, (IUnknown*)&Test_ClassFactory, MSHLFLAGS_TABLEWEAK, &thread);
907 ok_more_than_one_lock();
909 /* release the remaining reference on the object by calling
910 * CoReleaseMarshalData in the hosting thread */
911 IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
912 release_host_object(tid);
916 IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
917 hr = CoUnmarshalInterface(pStream, &IID_IClassFactory, (void **)&pProxy);
920 ok(hr == CO_E_OBJNOTREG,
921 "CoUnmarshalInterface should have failed with CO_E_OBJNOTREG, but returned 0x%08lx instead\n",
924 IStream_Release(pStream);
928 end_host_object(tid, thread);
931 /* tests success case of a same-thread table-strong marshal, unmarshal, unmarshal */
932 static void test_tablestrong_marshal_and_unmarshal_twice(void)
935 IStream *pStream = NULL;
936 IUnknown *pProxy1 = NULL;
937 IUnknown *pProxy2 = NULL;
943 hr = CreateStreamOnHGlobal(NULL, TRUE, &pStream);
944 ok_ole_success(hr, CreateStreamOnHGlobal);
945 tid = start_host_object(pStream, &IID_IClassFactory, (IUnknown*)&Test_ClassFactory, MSHLFLAGS_TABLESTRONG, &thread);
947 ok_more_than_one_lock();
949 IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
950 hr = CoUnmarshalInterface(pStream, &IID_IClassFactory, (void **)&pProxy1);
951 ok_ole_success(hr, CoUnmarshalInterface);
953 ok_more_than_one_lock();
955 IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
956 hr = CoUnmarshalInterface(pStream, &IID_IClassFactory, (void **)&pProxy2);
957 ok_ole_success(hr, CoUnmarshalInterface);
959 ok_more_than_one_lock();
961 if (pProxy1) IUnknown_Release(pProxy1);
962 if (pProxy2) IUnknown_Release(pProxy2);
964 /* this line is shows the difference between weak and strong table marshaling:
965 * weak has cLocks == 0
966 * strong has cLocks > 0 */
967 ok_more_than_one_lock();
969 /* release the remaining reference on the object by calling
970 * CoReleaseMarshalData in the hosting thread */
971 IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
972 release_host_object(tid);
973 IStream_Release(pStream);
977 end_host_object(tid, thread);
980 /* tests CoLockObjectExternal */
981 static void test_lock_object_external(void)
984 IStream *pStream = NULL;
988 /* test the stub manager creation aspect of CoLockObjectExternal when the
989 * object hasn't been marshaled yet */
990 CoLockObjectExternal((IUnknown*)&Test_ClassFactory, TRUE, TRUE);
992 ok_more_than_one_lock();
994 CoDisconnectObject((IUnknown*)&Test_ClassFactory, 0);
998 /* test our empty stub manager being handled correctly in
999 * CoMarshalInterface */
1000 CoLockObjectExternal((IUnknown*)&Test_ClassFactory, TRUE, TRUE);
1002 hr = CreateStreamOnHGlobal(NULL, TRUE, &pStream);
1003 ok_ole_success(hr, CreateStreamOnHGlobal);
1004 hr = CoMarshalInterface(pStream, &IID_IClassFactory, (IUnknown*)&Test_ClassFactory, MSHCTX_INPROC, NULL, MSHLFLAGS_NORMAL);
1005 ok_ole_success(hr, CoMarshalInterface);
1007 CoLockObjectExternal((IUnknown*)&Test_ClassFactory, TRUE, TRUE);
1009 ok_more_than_one_lock();
1011 IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
1012 hr = CoReleaseMarshalData(pStream);
1013 ok_ole_success(hr, CoReleaseMarshalData);
1014 IStream_Release(pStream);
1016 ok_more_than_one_lock();
1018 CoLockObjectExternal((IUnknown*)&Test_ClassFactory, FALSE, TRUE);
1020 ok_more_than_one_lock();
1022 CoLockObjectExternal((IUnknown*)&Test_ClassFactory, FALSE, TRUE);
1027 /* tests disconnecting stubs */
1028 static void test_disconnect_stub(void)
1031 IStream *pStream = NULL;
1035 hr = CreateStreamOnHGlobal(NULL, TRUE, &pStream);
1036 ok_ole_success(hr, CreateStreamOnHGlobal);
1037 hr = CoMarshalInterface(pStream, &IID_IClassFactory, (IUnknown*)&Test_ClassFactory, MSHCTX_INPROC, NULL, MSHLFLAGS_NORMAL);
1038 ok_ole_success(hr, CoMarshalInterface);
1040 CoLockObjectExternal((IUnknown*)&Test_ClassFactory, TRUE, TRUE);
1042 ok_more_than_one_lock();
1044 IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
1045 hr = CoReleaseMarshalData(pStream);
1046 ok_ole_success(hr, CoReleaseMarshalData);
1047 IStream_Release(pStream);
1049 ok_more_than_one_lock();
1051 CoDisconnectObject((IUnknown*)&Test_ClassFactory, 0);
1056 /* tests failure case of a same-thread marshal and unmarshal twice */
1057 static void test_normal_marshal_and_unmarshal_twice(void)
1060 IStream *pStream = NULL;
1061 IUnknown *pProxy1 = NULL;
1062 IUnknown *pProxy2 = NULL;
1066 hr = CreateStreamOnHGlobal(NULL, TRUE, &pStream);
1067 ok_ole_success(hr, CreateStreamOnHGlobal);
1068 hr = CoMarshalInterface(pStream, &IID_IClassFactory, (IUnknown*)&Test_ClassFactory, MSHCTX_INPROC, NULL, MSHLFLAGS_NORMAL);
1069 ok_ole_success(hr, CoMarshalInterface);
1071 ok_more_than_one_lock();
1073 IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
1074 hr = CoUnmarshalInterface(pStream, &IID_IClassFactory, (void **)&pProxy1);
1075 ok_ole_success(hr, CoUnmarshalInterface);
1077 ok_more_than_one_lock();
1079 IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
1080 hr = CoUnmarshalInterface(pStream, &IID_IClassFactory, (void **)&pProxy2);
1081 ok(hr == CO_E_OBJNOTCONNECTED,
1082 "CoUnmarshalInterface should have failed with error CO_E_OBJNOTCONNECTED for double unmarshal, instead of 0x%08lx\n", hr);
1084 IStream_Release(pStream);
1086 ok_more_than_one_lock();
1088 IUnknown_Release(pProxy1);
1093 /* tests success case of marshaling and unmarshaling an HRESULT */
1094 static void test_hresult_marshaling(void)
1097 HRESULT hr_marshaled = 0;
1098 IStream *pStream = NULL;
1099 static const HRESULT E_DEADBEEF = 0xdeadbeef;
1101 hr = CreateStreamOnHGlobal(NULL, TRUE, &pStream);
1102 ok_ole_success(hr, CreateStreamOnHGlobal);
1104 hr = CoMarshalHresult(pStream, E_DEADBEEF);
1105 ok_ole_success(hr, CoMarshalHresult);
1107 IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
1108 hr = IStream_Read(pStream, &hr_marshaled, sizeof(HRESULT), NULL);
1109 ok_ole_success(hr, IStream_Read);
1111 ok(hr_marshaled == E_DEADBEEF, "Didn't marshal HRESULT as expected: got value 0x%08lx instead\n", hr_marshaled);
1114 IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
1115 hr = CoUnmarshalHresult(pStream, &hr_marshaled);
1116 ok_ole_success(hr, CoUnmarshalHresult);
1118 ok(hr_marshaled == E_DEADBEEF, "Didn't marshal HRESULT as expected: got value 0x%08lx instead\n", hr_marshaled);
1120 IStream_Release(pStream);
1124 /* helper for test_proxy_used_in_wrong_thread */
1125 static DWORD CALLBACK bad_thread_proc(LPVOID p)
1127 IClassFactory * cf = (IClassFactory *)p;
1129 IUnknown * proxy = NULL;
1131 pCoInitializeEx(NULL, COINIT_MULTITHREADED);
1133 hr = IClassFactory_CreateInstance(cf, NULL, &IID_IUnknown, (LPVOID*)&proxy);
1134 if (proxy) IUnknown_Release(proxy);
1135 ok(hr == RPC_E_WRONG_THREAD,
1136 "COM should have failed with RPC_E_WRONG_THREAD on using proxy from wrong apartment, but instead returned 0x%08lx\n",
1144 /* tests failure case of a using a proxy in the wrong apartment */
1145 static void test_proxy_used_in_wrong_thread(void)
1148 IStream *pStream = NULL;
1149 IUnknown *pProxy = NULL;
1156 hr = CreateStreamOnHGlobal(NULL, TRUE, &pStream);
1157 ok_ole_success(hr, CreateStreamOnHGlobal);
1158 tid = start_host_object(pStream, &IID_IClassFactory, (IUnknown*)&Test_ClassFactory, MSHLFLAGS_NORMAL, &host_thread);
1160 ok_more_than_one_lock();
1162 IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
1163 hr = CoUnmarshalInterface(pStream, &IID_IClassFactory, (void **)&pProxy);
1164 ok_ole_success(hr, CoUnmarshalInterface);
1165 IStream_Release(pStream);
1167 ok_more_than_one_lock();
1169 /* create a thread that we can misbehave in */
1170 thread = CreateThread(NULL, 0, bad_thread_proc, (LPVOID)pProxy, 0, &tid2);
1172 WaitForSingleObject(thread, INFINITE);
1173 CloseHandle(thread);
1175 IUnknown_Release(pProxy);
1179 end_host_object(tid, host_thread);
1182 static HRESULT WINAPI MessageFilter_QueryInterface(IMessageFilter *iface, REFIID riid, void ** ppvObj)
1184 if (ppvObj == NULL) return E_POINTER;
1186 if (IsEqualGUID(riid, &IID_IUnknown) ||
1187 IsEqualGUID(riid, &IID_IClassFactory))
1189 *ppvObj = (LPVOID)iface;
1190 IClassFactory_AddRef(iface);
1194 return E_NOINTERFACE;
1197 static ULONG WINAPI MessageFilter_AddRef(IMessageFilter *iface)
1199 return 2; /* non-heap object */
1202 static ULONG WINAPI MessageFilter_Release(IMessageFilter *iface)
1204 return 1; /* non-heap object */
1207 static DWORD WINAPI MessageFilter_HandleInComingCall(
1208 IMessageFilter *iface,
1210 HTASK threadIDCaller,
1212 LPINTERFACEINFO lpInterfaceInfo)
1214 static int callcount = 0;
1216 trace("HandleInComingCall\n");
1220 ret = SERVERCALL_REJECTED;
1223 ret = SERVERCALL_RETRYLATER;
1226 ret = SERVERCALL_ISHANDLED;
1233 static DWORD WINAPI MessageFilter_RetryRejectedCall(
1234 IMessageFilter *iface,
1235 HTASK threadIDCallee,
1239 trace("RetryRejectedCall\n");
1243 static DWORD WINAPI MessageFilter_MessagePending(
1244 IMessageFilter *iface,
1245 HTASK threadIDCallee,
1247 DWORD dwPendingType)
1249 trace("MessagePending\n");
1250 return PENDINGMSG_WAITNOPROCESS;
1253 static const IMessageFilterVtbl MessageFilter_Vtbl =
1255 MessageFilter_QueryInterface,
1256 MessageFilter_AddRef,
1257 MessageFilter_Release,
1258 MessageFilter_HandleInComingCall,
1259 MessageFilter_RetryRejectedCall,
1260 MessageFilter_MessagePending
1263 static IMessageFilter MessageFilter = { &MessageFilter_Vtbl };
1265 static void test_message_filter(void)
1268 IStream *pStream = NULL;
1269 IClassFactory *cf = NULL;
1271 IUnknown *proxy = NULL;
1272 IMessageFilter *prev_filter = NULL;
1277 hr = CreateStreamOnHGlobal(NULL, TRUE, &pStream);
1278 ok_ole_success(hr, CreateStreamOnHGlobal);
1279 tid = start_host_object2(pStream, &IID_IClassFactory, (IUnknown*)&Test_ClassFactory, MSHLFLAGS_NORMAL, &MessageFilter, &thread);
1281 ok_more_than_one_lock();
1283 IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
1284 hr = CoUnmarshalInterface(pStream, &IID_IClassFactory, (void **)&cf);
1285 ok_ole_success(hr, CoUnmarshalInterface);
1286 IStream_Release(pStream);
1288 ok_more_than_one_lock();
1290 hr = IClassFactory_CreateInstance(cf, NULL, &IID_IUnknown, (LPVOID*)&proxy);
1291 todo_wine { ok(hr == RPC_E_CALL_REJECTED, "Call should have returned RPC_E_CALL_REJECTED, but return 0x%08lx instead\n", hr); }
1292 if (proxy) IUnknown_Release(proxy);
1295 hr = CoRegisterMessageFilter(&MessageFilter, &prev_filter);
1296 ok_ole_success(hr, CoRegisterMessageFilter);
1297 if (prev_filter) IMessageFilter_Release(prev_filter);
1299 hr = IClassFactory_CreateInstance(cf, NULL, &IID_IUnknown, (LPVOID*)&proxy);
1300 ok_ole_success(hr, IClassFactory_CreateInstance);
1302 IUnknown_Release(proxy);
1304 IClassFactory_Release(cf);
1308 end_host_object(tid, thread);
1311 /* test failure case of trying to unmarshal from bad stream */
1312 static void test_bad_marshal_stream(void)
1315 IStream *pStream = NULL;
1317 hr = CreateStreamOnHGlobal(NULL, TRUE, &pStream);
1318 ok_ole_success(hr, CreateStreamOnHGlobal);
1319 hr = CoMarshalInterface(pStream, &IID_IClassFactory, (IUnknown*)&Test_ClassFactory, MSHCTX_INPROC, NULL, MSHLFLAGS_NORMAL);
1320 ok_ole_success(hr, CoMarshalInterface);
1322 ok_more_than_one_lock();
1324 /* try to read beyond end of stream */
1325 hr = CoReleaseMarshalData(pStream);
1326 ok(hr == STG_E_READFAULT, "Should have failed with STG_E_READFAULT, but returned 0x%08lx instead\n", hr);
1328 /* now release for real */
1329 IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
1330 hr = CoReleaseMarshalData(pStream);
1331 ok_ole_success(hr, CoReleaseMarshalData);
1333 IStream_Release(pStream);
1336 /* tests that proxies implement certain interfaces */
1337 static void test_proxy_interfaces(void)
1340 IStream *pStream = NULL;
1341 IUnknown *pProxy = NULL;
1342 IUnknown *pOtherUnknown = NULL;
1348 hr = CreateStreamOnHGlobal(NULL, TRUE, &pStream);
1349 ok_ole_success(hr, CreateStreamOnHGlobal);
1350 tid = start_host_object(pStream, &IID_IClassFactory, (IUnknown*)&Test_ClassFactory, MSHLFLAGS_NORMAL, &thread);
1352 ok_more_than_one_lock();
1354 IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
1355 hr = CoUnmarshalInterface(pStream, &IID_IUnknown, (void **)&pProxy);
1356 ok_ole_success(hr, CoUnmarshalInterface);
1357 IStream_Release(pStream);
1359 ok_more_than_one_lock();
1361 hr = IUnknown_QueryInterface(pProxy, &IID_IUnknown, (LPVOID*)&pOtherUnknown);
1362 ok_ole_success(hr, IUnknown_QueryInterface IID_IUnknown);
1363 if (hr == S_OK) IUnknown_Release(pOtherUnknown);
1365 hr = IUnknown_QueryInterface(pProxy, &IID_IClientSecurity, (LPVOID*)&pOtherUnknown);
1366 todo_wine { ok_ole_success(hr, IUnknown_QueryInterface IID_IClientSecurity); }
1367 if (hr == S_OK) IUnknown_Release(pOtherUnknown);
1369 hr = IUnknown_QueryInterface(pProxy, &IID_IMultiQI, (LPVOID*)&pOtherUnknown);
1370 ok_ole_success(hr, IUnknown_QueryInterface IID_IMultiQI);
1371 if (hr == S_OK) IUnknown_Release(pOtherUnknown);
1373 hr = IUnknown_QueryInterface(pProxy, &IID_IMarshal, (LPVOID*)&pOtherUnknown);
1374 ok_ole_success(hr, IUnknown_QueryInterface IID_IMarshal);
1375 if (hr == S_OK) IUnknown_Release(pOtherUnknown);
1377 /* IMarshal2 is also supported on NT-based systems, but is pretty much
1378 * useless as it has no more methods over IMarshal that it inherits from. */
1380 IUnknown_Release(pProxy);
1384 end_host_object(tid, thread);
1389 const IUnknownVtbl *lpVtbl;
1393 static HRESULT WINAPI HeapUnknown_QueryInterface(IUnknown *iface, REFIID riid, void **ppv)
1395 if (IsEqualIID(riid, &IID_IUnknown))
1397 IUnknown_AddRef(iface);
1398 *ppv = (LPVOID)iface;
1402 return E_NOINTERFACE;
1405 static ULONG WINAPI HeapUnknown_AddRef(IUnknown *iface)
1407 HeapUnknown *This = (HeapUnknown *)iface;
1408 trace("HeapUnknown_AddRef(%p)\n", iface);
1409 return InterlockedIncrement((LONG*)&This->refs);
1412 static ULONG WINAPI HeapUnknown_Release(IUnknown *iface)
1414 HeapUnknown *This = (HeapUnknown *)iface;
1415 ULONG refs = InterlockedDecrement((LONG*)&This->refs);
1416 trace("HeapUnknown_Release(%p)\n", iface);
1417 if (!refs) HeapFree(GetProcessHeap(), 0, This);
1421 static const IUnknownVtbl HeapUnknown_Vtbl =
1423 HeapUnknown_QueryInterface,
1428 static void test_proxybuffer(REFIID riid)
1431 IPSFactoryBuffer *psfb;
1432 IRpcProxyBuffer *proxy;
1436 HeapUnknown *pUnkOuter = (HeapUnknown *)HeapAlloc(GetProcessHeap(), 0, sizeof(*pUnkOuter));
1438 pUnkOuter->lpVtbl = &HeapUnknown_Vtbl;
1439 pUnkOuter->refs = 1;
1441 hr = CoGetPSClsid(riid, &clsid);
1442 ok_ole_success(hr, CoGetPSClsid);
1444 hr = CoGetClassObject(&clsid, CLSCTX_INPROC_SERVER, NULL, &IID_IPSFactoryBuffer, (LPVOID*)&psfb);
1445 ok_ole_success(hr, CoGetClassObject);
1447 hr = IPSFactoryBuffer_CreateProxy(psfb, (IUnknown*)pUnkOuter, riid, &proxy, &lpvtbl);
1448 ok_ole_success(hr, IPSFactoryBuffer_CreateProxy);
1449 ok(lpvtbl != NULL, "IPSFactoryBuffer_CreateProxy succeeded, but returned a NULL vtable!\n");
1451 /* release our reference to the outer unknown object - the PS factory
1452 * buffer will have AddRef's it in the CreateProxy call */
1453 refs = IUnknown_Release((IUnknown *)pUnkOuter);
1454 ok(refs == 1, "Ref count of outer unknown should have been 1 instead of %ld\n", refs);
1456 refs = IPSFactoryBuffer_Release(psfb);
1457 #if 0 /* not reliable on native. maybe it leaks references! */
1458 ok(refs == 0, "Ref-count leak of %ld on IPSFactoryBuffer\n", refs);
1461 refs = IUnknown_Release((IUnknown *)lpvtbl);
1462 ok(refs == 0, "Ref-count leak of %ld on IRpcProxyBuffer\n", refs);
1464 refs = IRpcProxyBuffer_Release(proxy);
1465 ok(refs == 0, "Ref-count leak of %ld on IRpcProxyBuffer\n", refs);
1468 static void test_stubbuffer(REFIID riid)
1471 IPSFactoryBuffer *psfb;
1472 IRpcStubBuffer *stub;
1478 hr = CoGetPSClsid(riid, &clsid);
1479 ok_ole_success(hr, CoGetPSClsid);
1481 hr = CoGetClassObject(&clsid, CLSCTX_INPROC_SERVER, NULL, &IID_IPSFactoryBuffer, (LPVOID*)&psfb);
1482 ok_ole_success(hr, CoGetClassObject);
1484 hr = IPSFactoryBuffer_CreateStub(psfb, riid, (IUnknown*)&Test_ClassFactory, &stub);
1485 ok_ole_success(hr, IPSFactoryBuffer_CreateStub);
1487 refs = IPSFactoryBuffer_Release(psfb);
1488 #if 0 /* not reliable on native. maybe it leaks references */
1489 ok(refs == 0, "Ref-count leak of %ld on IPSFactoryBuffer\n", refs);
1492 ok_more_than_one_lock();
1494 IRpcStubBuffer_Disconnect(stub);
1498 refs = IRpcStubBuffer_Release(stub);
1499 ok(refs == 0, "Ref-count leak of %ld on IRpcProxyBuffer\n", refs);
1502 static HWND hwnd_app;
1504 static HRESULT WINAPI TestRE_IClassFactory_CreateInstance(
1505 LPCLASSFACTORY iface,
1506 LPUNKNOWN pUnkOuter,
1511 if (IsEqualIID(riid, &IID_IWineTest))
1513 BOOL ret = SendMessageTimeout(hwnd_app, WM_NULL, 0, 0, SMTO_BLOCK, 5000, &res);
1514 ok(ret, "Timed out sending a message to originating window during RPC call\n");
1519 static const IClassFactoryVtbl TestREClassFactory_Vtbl =
1521 Test_IClassFactory_QueryInterface,
1522 Test_IClassFactory_AddRef,
1523 Test_IClassFactory_Release,
1524 TestRE_IClassFactory_CreateInstance,
1525 Test_IClassFactory_LockServer
1528 IClassFactory TestRE_ClassFactory = { &TestREClassFactory_Vtbl };
1530 static LRESULT CALLBACK window_proc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam)
1537 IStream *pStream = NULL;
1538 IClassFactory *proxy = NULL;
1545 hr = CreateStreamOnHGlobal(NULL, TRUE, &pStream);
1546 ok_ole_success(hr, CreateStreamOnHGlobal);
1547 tid = start_host_object(pStream, &IID_IClassFactory, (IUnknown*)&TestRE_ClassFactory, MSHLFLAGS_NORMAL, &thread);
1549 ok_more_than_one_lock();
1551 IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
1552 hr = CoUnmarshalInterface(pStream, &IID_IClassFactory, (void **)&proxy);
1553 ok_ole_success(hr, CoReleaseMarshalData);
1554 IStream_Release(pStream);
1556 ok_more_than_one_lock();
1558 /* note the use of the magic IID_IWineTest value to tell remote thread
1559 * to try to send a message back to us */
1560 hr = IClassFactory_CreateInstance(proxy, NULL, &IID_IWineTest, (void **)&object);
1562 IClassFactory_Release(proxy);
1566 end_host_object(tid, thread);
1568 PostMessage(hwnd, WM_QUIT, 0, 0);
1575 IStream *pStream = NULL;
1576 IClassFactory *proxy = NULL;
1583 hr = CreateStreamOnHGlobal(NULL, TRUE, &pStream);
1584 ok_ole_success(hr, CreateStreamOnHGlobal);
1585 tid = start_host_object(pStream, &IID_IClassFactory, (IUnknown*)&TestRE_ClassFactory, MSHLFLAGS_NORMAL, &thread);
1587 ok_more_than_one_lock();
1589 IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
1590 hr = CoUnmarshalInterface(pStream, &IID_IClassFactory, (void **)&proxy);
1591 ok_ole_success(hr, CoReleaseMarshalData);
1592 IStream_Release(pStream);
1594 ok_more_than_one_lock();
1596 /* post quit message before a doing a COM call to show that a pending
1597 * WM_QUIT message doesn't stop the call from succeeding */
1598 PostMessage(hwnd, WM_QUIT, 0, 0);
1599 hr = IClassFactory_CreateInstance(proxy, NULL, &IID_IUnknown, (void **)&object);
1601 IClassFactory_Release(proxy);
1605 end_host_object(tid, thread);
1610 return DefWindowProc(hwnd, msg, wparam, lparam);
1614 static void test_message_reentrancy(void)
1619 memset(&wndclass, 0, sizeof(wndclass));
1620 wndclass.lpfnWndProc = window_proc;
1621 wndclass.lpszClassName = "WineCOMTest";
1622 RegisterClass(&wndclass);
1624 hwnd_app = CreateWindow("WineCOMTest", NULL, 0, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, NULL, NULL, NULL, 0);
1625 ok(hwnd_app != NULL, "Window creation failed\n");
1627 /* start message re-entrancy test */
1628 PostMessage(hwnd_app, WM_USER, 0, 0);
1630 while (GetMessage(&msg, NULL, 0, 0))
1632 TranslateMessage(&msg);
1633 DispatchMessage(&msg);
1637 static void test_WM_QUIT_handling(void)
1641 hwnd_app = CreateWindow("WineCOMTest", NULL, 0, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, NULL, NULL, NULL, 0);
1642 ok(hwnd_app != NULL, "Window creation failed\n");
1644 /* start WM_QUIT handling test */
1645 PostMessage(hwnd_app, WM_USER+1, 0, 0);
1647 while (GetMessage(&msg, NULL, 0, 0))
1649 TranslateMessage(&msg);
1650 DispatchMessage(&msg);
1654 static void test_freethreadedmarshaldata(IStream *pStream, MSHCTX mshctx, void *ptr, DWORD mshlflags)
1661 hr = GetHGlobalFromStream(pStream, &hglobal);
1662 ok_ole_success(hr, GetHGlobalFromStream);
1664 size = GlobalSize(hglobal);
1666 marshal_data = (char *)GlobalLock(hglobal);
1668 if (mshctx == MSHCTX_INPROC)
1670 DWORD expected_size = sizeof(DWORD) + sizeof(void *) + sizeof(DWORD) + sizeof(GUID);
1671 ok(size == expected_size, "size should have been %ld instead of %ld\n", expected_size, size);
1673 ok(*(DWORD *)marshal_data == mshlflags, "expected 0x%lx, but got 0x%lx for mshctx\n", mshlflags, *(DWORD *)marshal_data);
1674 marshal_data += sizeof(DWORD);
1675 ok(*(void **)marshal_data == ptr, "expected %p, but got %p for mshctx\n", ptr, *(void **)marshal_data);
1676 marshal_data += sizeof(void *);
1677 ok(*(DWORD *)marshal_data == 0, "expected 0x0, but got 0x%lx\n", *(DWORD *)marshal_data);
1678 marshal_data += sizeof(DWORD);
1679 trace("got guid data: {%08lx-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x}\n",
1680 ((GUID *)marshal_data)->Data1, ((GUID *)marshal_data)->Data2, ((GUID *)marshal_data)->Data3,
1681 ((GUID *)marshal_data)->Data4[0], ((GUID *)marshal_data)->Data4[1], ((GUID *)marshal_data)->Data4[2], ((GUID *)marshal_data)->Data4[3],
1682 ((GUID *)marshal_data)->Data4[4], ((GUID *)marshal_data)->Data4[5], ((GUID *)marshal_data)->Data4[6], ((GUID *)marshal_data)->Data4[7]);
1686 ok(size > sizeof(DWORD), "size should have been > sizeof(DWORD), not %ld\n", size);
1687 ok(*(DWORD *)marshal_data == 0x574f454d /* MEOW */,
1688 "marshal data should be filled by standard marshal and start with MEOW signature\n");
1691 GlobalUnlock(hglobal);
1694 static void test_freethreadedmarshaler(void)
1697 IUnknown *pFTUnknown;
1698 IMarshal *pFTMarshal;
1701 static const LARGE_INTEGER llZero;
1704 hr = CoCreateFreeThreadedMarshaler(NULL, &pFTUnknown);
1705 ok_ole_success(hr, CoCreateFreeThreadedMarshaler);
1706 hr = IUnknown_QueryInterface(pFTUnknown, &IID_IMarshal, (void **)&pFTMarshal);
1707 ok_ole_success(hr, IUnknown_QueryInterface);
1708 IUnknown_Release(pFTUnknown);
1710 hr = CreateStreamOnHGlobal(NULL, TRUE, &pStream);
1711 ok_ole_success(hr, CreateStreamOnHGlobal);
1713 /* inproc normal marshaling */
1715 hr = IMarshal_MarshalInterface(pFTMarshal, pStream, &IID_IClassFactory,
1716 (IUnknown*)&Test_ClassFactory, MSHCTX_INPROC, NULL, MSHLFLAGS_NORMAL);
1717 ok_ole_success(hr, IMarshal_MarshalInterface);
1719 ok_more_than_one_lock();
1721 test_freethreadedmarshaldata(pStream, MSHCTX_INPROC, &Test_ClassFactory, MSHLFLAGS_NORMAL);
1723 IStream_Seek(pStream, llZero, STREAM_SEEK_SET, NULL);
1724 hr = IMarshal_UnmarshalInterface(pFTMarshal, pStream, &IID_IUnknown, (void **)&pProxy);
1725 ok_ole_success(hr, IMarshal_UnmarshalInterface);
1727 IUnknown_Release(pProxy);
1731 /* native doesn't allow us to unmarshal or release the stream data,
1732 * presumably because it wants us to call CoMarshalInterface instead */
1734 /* local normal marshaling */
1736 IStream_Seek(pStream, llZero, STREAM_SEEK_SET, NULL);
1737 hr = IMarshal_MarshalInterface(pFTMarshal, pStream, IID_IClassFactory, (IUnknown*)&Test_ClassFactory, MSHCTX_LOCAL, NULL, MSHLFLAGS_NORMAL);
1738 ok_ole_success(hr, IMarshal_MarshalInterface);
1740 ok_more_than_one_lock();
1742 test_freethreadedmarshaldata(pStream, MSHCTX_LOCAL, &Test_ClassFactory, MSHLFLAGS_NORMAL);
1744 IStream_Seek(pStream, llZero, STREAM_SEEK_SET, NULL);
1745 hr = IMarshal_ReleaseMarshalData(pFTMarshal, pStream);
1746 ok_ole_success(hr, IMarshal_ReleaseMarshalData);
1751 /* inproc table-strong marshaling */
1753 IStream_Seek(pStream, llZero, STREAM_SEEK_SET, NULL);
1754 hr = IMarshal_MarshalInterface(pFTMarshal, pStream, &IID_IClassFactory,
1755 (IUnknown*)&Test_ClassFactory, MSHCTX_INPROC, (void *)0xdeadbeef,
1756 MSHLFLAGS_TABLESTRONG);
1757 ok_ole_success(hr, IMarshal_MarshalInterface);
1759 ok_more_than_one_lock();
1761 test_freethreadedmarshaldata(pStream, MSHCTX_INPROC, &Test_ClassFactory, MSHLFLAGS_TABLESTRONG);
1763 IStream_Seek(pStream, llZero, STREAM_SEEK_SET, NULL);
1764 hr = IMarshal_UnmarshalInterface(pFTMarshal, pStream, &IID_IUnknown, (void **)&pProxy);
1765 ok_ole_success(hr, IMarshal_UnmarshalInterface);
1767 IUnknown_Release(pProxy);
1769 ok_more_than_one_lock();
1771 IStream_Seek(pStream, llZero, STREAM_SEEK_SET, NULL);
1772 hr = IMarshal_ReleaseMarshalData(pFTMarshal, pStream);
1773 ok_ole_success(hr, IMarshal_ReleaseMarshalData);
1777 /* inproc table-weak marshaling */
1779 IStream_Seek(pStream, llZero, STREAM_SEEK_SET, NULL);
1780 hr = IMarshal_MarshalInterface(pFTMarshal, pStream, &IID_IClassFactory,
1781 (IUnknown*)&Test_ClassFactory, MSHCTX_INPROC, (void *)0xdeadbeef,
1782 MSHLFLAGS_TABLEWEAK);
1783 ok_ole_success(hr, IMarshal_MarshalInterface);
1787 test_freethreadedmarshaldata(pStream, MSHCTX_INPROC, &Test_ClassFactory, MSHLFLAGS_TABLEWEAK);
1789 IStream_Seek(pStream, llZero, STREAM_SEEK_SET, NULL);
1790 hr = IMarshal_UnmarshalInterface(pFTMarshal, pStream, &IID_IUnknown, (void **)&pProxy);
1791 ok_ole_success(hr, IMarshal_UnmarshalInterface);
1793 ok_more_than_one_lock();
1795 IUnknown_Release(pProxy);
1799 /* inproc normal marshaling (for extraordinary cases) */
1801 IStream_Seek(pStream, llZero, STREAM_SEEK_SET, NULL);
1802 hr = IMarshal_MarshalInterface(pFTMarshal, pStream, &IID_IClassFactory,
1803 (IUnknown*)&Test_ClassFactory, MSHCTX_INPROC, NULL, MSHLFLAGS_NORMAL);
1804 ok_ole_success(hr, IMarshal_MarshalInterface);
1806 ok_more_than_one_lock();
1808 /* this call shows that DisconnectObject does nothing */
1809 hr = IMarshal_DisconnectObject(pFTMarshal, 0);
1810 ok_ole_success(hr, IMarshal_DisconnectObject);
1812 ok_more_than_one_lock();
1814 IStream_Seek(pStream, llZero, STREAM_SEEK_SET, NULL);
1815 hr = IMarshal_ReleaseMarshalData(pFTMarshal, pStream);
1816 ok_ole_success(hr, IMarshal_ReleaseMarshalData);
1820 /* doesn't enforce marshaling rules here and allows us to unmarshal the
1821 * interface, even though it was freed above */
1822 IStream_Seek(pStream, llZero, STREAM_SEEK_SET, NULL);
1823 hr = IMarshal_UnmarshalInterface(pFTMarshal, pStream, &IID_IUnknown, (void **)&pProxy);
1824 ok_ole_success(hr, IMarshal_UnmarshalInterface);
1828 IStream_Release(pStream);
1829 IMarshal_Release(pFTMarshal);
1832 static HANDLE heventShutdown;
1834 static void LockModuleOOP(void)
1836 InterlockedIncrement(&cLocks); /* for test purposes only */
1837 CoAddRefServerProcess();
1840 static void UnlockModuleOOP(void)
1842 InterlockedDecrement(&cLocks); /* for test purposes only */
1843 if (!CoReleaseServerProcess())
1844 SetEvent(heventShutdown);
1847 static HWND hwnd_app;
1849 static HRESULT WINAPI TestOOP_IClassFactory_QueryInterface(
1850 LPCLASSFACTORY iface,
1854 if (ppvObj == NULL) return E_POINTER;
1856 if (IsEqualGUID(riid, &IID_IUnknown) ||
1857 IsEqualGUID(riid, &IID_IClassFactory))
1859 *ppvObj = (LPVOID)iface;
1860 IClassFactory_AddRef(iface);
1864 return E_NOINTERFACE;
1867 static ULONG WINAPI TestOOP_IClassFactory_AddRef(LPCLASSFACTORY iface)
1869 return 2; /* non-heap-based object */
1872 static ULONG WINAPI TestOOP_IClassFactory_Release(LPCLASSFACTORY iface)
1874 return 1; /* non-heap-based object */
1877 static HRESULT WINAPI TestOOP_IClassFactory_CreateInstance(
1878 LPCLASSFACTORY iface,
1879 LPUNKNOWN pUnkOuter,
1883 return CLASS_E_CLASSNOTAVAILABLE;
1886 static HRESULT WINAPI TestOOP_IClassFactory_LockServer(
1887 LPCLASSFACTORY iface,
1897 static const IClassFactoryVtbl TestClassFactoryOOP_Vtbl =
1899 TestOOP_IClassFactory_QueryInterface,
1900 TestOOP_IClassFactory_AddRef,
1901 TestOOP_IClassFactory_Release,
1902 TestOOP_IClassFactory_CreateInstance,
1903 TestOOP_IClassFactory_LockServer
1906 static IClassFactory TestOOP_ClassFactory = { &TestClassFactoryOOP_Vtbl };
1908 /* tests functions commonly used by out of process COM servers */
1909 static void test_out_of_process_com(void)
1911 static const CLSID CLSID_WineOOPTest = {
1915 {0xa1, 0xa2, 0x5d, 0x5a, 0x36, 0x54, 0xd3, 0xbd}
1916 }; /* 5201163f-8164-4fd0-a1a2-5d5a3654d3bd */
1922 heventShutdown = CreateEvent(NULL, TRUE, FALSE, NULL);
1926 /* Start the object suspended */
1927 hr = CoRegisterClassObject(&CLSID_WineOOPTest, (IUnknown *)&TestOOP_ClassFactory,
1928 CLSCTX_LOCAL_SERVER, REGCLS_MULTIPLEUSE | REGCLS_SUSPENDED, &cookie);
1929 ok_ole_success(hr, CoRegisterClassObject);
1931 /* ... and CoGetClassObject does not find it and fails when it looks for the
1932 * class in the registry */
1933 hr = CoGetClassObject(&CLSID_WineOOPTest, CLSCTX_INPROC_SERVER,
1934 NULL, &IID_IClassFactory, (LPVOID*)&cf);
1936 ok(hr == REGDB_E_CLASSNOTREG,
1937 "CoGetClassObject should have returned REGDB_E_CLASSNOTREG instead of 0x%08lx\n", hr);
1940 /* Resume the object suspended above ... */
1941 hr = CoResumeClassObjects();
1942 ok_ole_success(hr, CoResumeClassObjects);
1944 /* ... and now it should succeed */
1945 hr = CoGetClassObject(&CLSID_WineOOPTest, CLSCTX_INPROC_SERVER,
1946 NULL, &IID_IClassFactory, (LPVOID*)&cf);
1947 ok_ole_success(hr, CoGetClassObject);
1949 /* Now check the locking is working */
1950 /* NOTE: we are accessing the class directly, not through a proxy */
1954 hr = IClassFactory_LockServer(cf, TRUE);
1955 trace("IClassFactory_LockServer returned 0x%08lx\n", hr);
1957 ok_more_than_one_lock();
1959 IClassFactory_LockServer(cf, FALSE);
1963 IClassFactory_Release(cf);
1965 /* wait for shutdown signal */
1966 ret = WaitForSingleObject(heventShutdown, 5000);
1967 todo_wine { ok(ret != WAIT_TIMEOUT, "Server didn't shut down or machine is under very heavy load\n"); }
1969 /* try to connect again after SCM has suspended registered class objects */
1970 hr = CoGetClassObject(&CLSID_WineOOPTest, CLSCTX_INPROC_SERVER | CLSCTX_LOCAL_SERVER, NULL,
1971 &IID_IClassFactory, (LPVOID*)&cf);
1973 ok(hr == CO_E_SERVER_STOPPING,
1974 "CoGetClassObject should have returned CO_E_SERVER_STOPPING instead of 0x%08lx\n", hr);
1977 hr = CoRevokeClassObject(cookie);
1978 ok_ole_success(hr, CoRevokeClassObject);
1980 CloseHandle(heventShutdown);
1983 static void test_ROT(void)
1985 static const WCHAR wszFileName[] = {'B','E','2','0','E','2','F','5','-',
1986 '1','9','0','3','-','4','A','A','E','-','B','1','A','F','-',
1987 '2','0','4','6','E','5','8','6','C','9','2','5',0};
1989 IMoniker *pMoniker = NULL;
1990 IRunningObjectTable *pROT = NULL;
1995 hr = CreateFileMoniker(wszFileName, &pMoniker);
1996 ok_ole_success(hr, CreateClassMoniker);
1997 hr = GetRunningObjectTable(0, &pROT);
1998 ok_ole_success(hr, GetRunningObjectTable);
1999 hr = IRunningObjectTable_Register(pROT, 0, (IUnknown*)&Test_ClassFactory, pMoniker, &dwCookie);
2000 ok_ole_success(hr, IRunningObjectTable_Register);
2002 ok_more_than_one_lock();
2004 hr = IRunningObjectTable_Revoke(pROT, dwCookie);
2005 ok_ole_success(hr, IRunningObjectTable_Revoke);
2013 IGlobalInterfaceTable *git;
2016 static DWORD CALLBACK get_global_interface_proc(LPVOID pv)
2019 struct git_params *params = (struct git_params *)pv;
2022 hr = IGlobalInterfaceTable_GetInterfaceFromGlobal(params->git, params->cookie, &IID_IClassFactory, (void **)&cf);
2023 ok(hr == CO_E_NOTINITIALIZED,
2024 "IGlobalInterfaceTable_GetInterfaceFromGlobal should have failed with error CO_E_NOTINITIALIZED instead of 0x%08lx\n",
2028 hr = IGlobalInterfaceTable_GetInterfaceFromGlobal(params->git, params->cookie, &IID_IClassFactory, (void **)&cf);
2029 ok_ole_success(hr, IGlobalInterfaceTable_GetInterfaceFromGlobal);
2035 static void test_globalinterfacetable(void)
2038 IGlobalInterfaceTable *git;
2042 struct git_params params;
2045 hr = CoCreateInstance(&CLSID_StdGlobalInterfaceTable, NULL, CLSCTX_INPROC_SERVER, &IID_IGlobalInterfaceTable, (void **)&git);
2046 ok_ole_success(hr, CoCreateInstance);
2048 hr = IGlobalInterfaceTable_RegisterInterfaceInGlobal(git, (IUnknown *)&Test_ClassFactory, &IID_IClassFactory, &cookie);
2049 ok_ole_success(hr, IGlobalInterfaceTable_RegisterInterfaceInGlobal);
2051 params.cookie = cookie;
2053 /* note: params is on stack so we MUST wait for get_global_interface_proc
2054 * to exit before we can return */
2055 thread = CreateThread(NULL, 0, get_global_interface_proc, ¶ms, 0, &tid);
2057 ret = MsgWaitForMultipleObjects(1, &thread, FALSE, INFINITE, QS_ALLINPUT);
2058 while (ret == WAIT_OBJECT_0 + 1)
2061 while (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
2062 DispatchMessage(&msg);
2063 ret = MsgWaitForMultipleObjects(1, &thread, FALSE, INFINITE, QS_ALLINPUT);
2066 CloseHandle(thread);
2069 static const char cf_marshaled[] =
2081 static void test_marshal_CLIPFORMAT(void)
2083 unsigned char *buffer;
2085 unsigned long flags = MAKELONG(MSHCTX_DIFFERENTMACHINE, NDR_LOCAL_DATA_REPRESENTATION);
2086 wireCLIPFORMAT wirecf;
2087 CLIPFORMAT cf = RegisterClipboardFormatA("MyFormat");
2090 size = CLIPFORMAT_UserSize(&flags, 0, &cf);
2091 ok(size == sizeof(*wirecf) + sizeof(cf_marshaled), "Wrong size %ld\n", size);
2093 buffer = HeapAlloc(GetProcessHeap(), 0, size);
2094 CLIPFORMAT_UserMarshal(&flags, buffer, &cf);
2095 wirecf = (wireCLIPFORMAT)buffer;
2096 ok(wirecf->fContext == WDT_REMOTE_CALL, "Context should be WDT_REMOTE_CALL instead of 0x%08lx\n", wirecf->fContext);
2097 ok(wirecf->u.dwValue == cf, "Marshaled value should be 0x%04x instead of 0x%04lx\n", cf, wirecf->u.dwValue);
2098 ok(!memcmp(wirecf+1, cf_marshaled, sizeof(cf_marshaled)), "Marshaled data differs\n");
2100 CLIPFORMAT_UserUnmarshal(&flags, buffer, &cf2);
2101 ok(cf == cf2, "Didn't unmarshal properly\n");
2102 HeapFree(GetProcessHeap(), 0, buffer);
2104 CLIPFORMAT_UserFree(&flags, &cf2);
2107 static void test_marshal_HWND(void)
2109 unsigned char *buffer;
2111 unsigned long flags = MAKELONG(MSHCTX_LOCAL, NDR_LOCAL_DATA_REPRESENTATION);
2112 HWND hwnd = GetDesktopWindow();
2116 size = HWND_UserSize(&flags, 0, &hwnd);
2117 ok(size == sizeof(*wirehwnd), "Wrong size %ld\n", size);
2119 buffer = HeapAlloc(GetProcessHeap(), 0, size);
2120 HWND_UserMarshal(&flags, buffer, &hwnd);
2121 wirehwnd = (wireHWND)buffer;
2122 ok(wirehwnd->fContext == WDT_INPROC_CALL, "Context should be WDT_INPROC_CALL instead of 0x%08lx\n", wirehwnd->fContext);
2123 ok(wirehwnd->u.hInproc == (LONG_PTR)hwnd, "Marshaled value should be %p instead of %p\n", hwnd, (HANDLE)wirehwnd->u.hRemote);
2125 HWND_UserUnmarshal(&flags, buffer, &hwnd2);
2126 ok(hwnd == hwnd2, "Didn't unmarshal properly\n");
2127 HeapFree(GetProcessHeap(), 0, buffer);
2129 HWND_UserFree(&flags, &hwnd2);
2132 static void test_marshal_HGLOBAL(void)
2134 unsigned char *buffer;
2136 unsigned long flags = MAKELONG(MSHCTX_LOCAL, NDR_LOCAL_DATA_REPRESENTATION);
2139 unsigned char *wirehglobal;
2143 flags = MAKELONG(MSHCTX_LOCAL, NDR_LOCAL_DATA_REPRESENTATION);
2144 size = HGLOBAL_UserSize(&flags, 0, &hglobal);
2145 /* native is poorly programmed and allocates 4 bytes more than it needs to
2146 * here - Wine doesn't have to emulate that */
2147 ok((size == 8) || (size == 12), "Size should be 12, instead of %ld\n", size);
2148 buffer = HeapAlloc(GetProcessHeap(), 0, size);
2149 HGLOBAL_UserMarshal(&flags, buffer, &hglobal);
2150 wirehglobal = buffer;
2151 ok(*(ULONG *)wirehglobal == WDT_REMOTE_CALL, "Context should be WDT_REMOTE_CALL instead of 0x%08lx\n", *(ULONG *)wirehglobal);
2152 wirehglobal += sizeof(ULONG);
2153 ok(*(ULONG *)wirehglobal == (ULONG)hglobal, "buffer+4 should be HGLOBAL\n");
2154 HGLOBAL_UserUnmarshal(&flags, buffer, &hglobal2);
2155 ok(hglobal2 == hglobal, "Didn't unmarshal properly\n");
2156 HeapFree(GetProcessHeap(), 0, buffer);
2157 HGLOBAL_UserFree(&flags, &hglobal2);
2159 hglobal = GlobalAlloc(0, 4);
2160 buffer = GlobalLock(hglobal);
2161 for (i = 0; i < 4; i++)
2163 GlobalUnlock(hglobal);
2164 flags = MAKELONG(MSHCTX_LOCAL, NDR_LOCAL_DATA_REPRESENTATION);
2165 size = HGLOBAL_UserSize(&flags, 0, &hglobal);
2166 /* native is poorly programmed and allocates 4 bytes more than it needs to
2167 * here - Wine doesn't have to emulate that */
2168 ok((size == 24) || (size == 28), "Size should be 24 or 28, instead of %ld\n", size);
2169 buffer = HeapAlloc(GetProcessHeap(), 0, size);
2170 HGLOBAL_UserMarshal(&flags, buffer, &hglobal);
2171 wirehglobal = buffer;
2172 ok(*(ULONG *)wirehglobal == WDT_REMOTE_CALL, "Context should be WDT_REMOTE_CALL instead of 0x%08lx\n", *(ULONG *)wirehglobal);
2173 wirehglobal += sizeof(ULONG);
2174 ok(*(ULONG *)wirehglobal == (ULONG)hglobal, "buffer+0x4 should be HGLOBAL\n");
2175 wirehglobal += sizeof(ULONG);
2176 ok(*(ULONG *)wirehglobal == 4, "buffer+0x8 should be size of HGLOBAL\n");
2177 wirehglobal += sizeof(ULONG);
2178 ok(*(ULONG *)wirehglobal == (ULONG)hglobal, "buffer+0xc should be HGLOBAL\n");
2179 wirehglobal += sizeof(ULONG);
2180 ok(*(ULONG *)wirehglobal == 4, "buffer+0x10 should be size of HGLOBAL\n");
2181 wirehglobal += sizeof(ULONG);
2182 for (i = 0; i < 4; i++)
2183 ok(wirehglobal[i] == i, "buffer+0x%x should be %d\n", 0x10 + i, i);
2184 HGLOBAL_UserUnmarshal(&flags, buffer, &hglobal2);
2185 ok(hglobal2 != NULL, "Didn't unmarshal properly\n");
2186 HeapFree(GetProcessHeap(), 0, buffer);
2187 HGLOBAL_UserFree(&flags, &hglobal2);
2188 GlobalFree(hglobal);
2191 static HENHMETAFILE create_emf(void)
2193 RECT rect = {0, 0, 100, 100};
2194 HDC hdc = CreateEnhMetaFile(NULL, NULL, &rect, "HENHMETAFILE Marshaling Test\0Test\0\0");
2195 ExtTextOut(hdc, 0, 0, ETO_OPAQUE, NULL, "Test String", strlen("Test String"), NULL);
2196 return CloseEnhMetaFile(hdc);
2199 static void test_marshal_HENHMETAFILE(void)
2201 unsigned char *buffer;
2203 unsigned long flags = MAKELONG(MSHCTX_DIFFERENTMACHINE, NDR_LOCAL_DATA_REPRESENTATION);
2205 HENHMETAFILE hemf2 = NULL;
2206 unsigned char *wirehemf;
2208 hemf = create_emf();
2210 size = HENHMETAFILE_UserSize(&flags, 0, &hemf);
2211 ok(size > 20, "size should be at least 20 bytes, not %ld\n", size);
2212 buffer = HeapAlloc(GetProcessHeap(), 0, size);
2213 HENHMETAFILE_UserMarshal(&flags, buffer, &hemf);
2215 ok(*(DWORD *)wirehemf == WDT_REMOTE_CALL, "wirestgm + 0x0 should be WDT_REMOTE_CALL instead of 0x%08lx\n", *(DWORD *)wirehemf);
2216 wirehemf += sizeof(DWORD);
2217 ok(*(DWORD *)wirehemf == (DWORD)(DWORD_PTR)hemf, "wirestgm + 0x4 should be hemf instead of 0x%08lx\n", *(DWORD *)wirehemf);
2218 wirehemf += sizeof(DWORD);
2219 ok(*(DWORD *)wirehemf == (size - 0x10), "wirestgm + 0x8 should be size - 0x10 instead of 0x%08lx\n", *(DWORD *)wirehemf);
2220 wirehemf += sizeof(DWORD);
2221 ok(*(DWORD *)wirehemf == (size - 0x10), "wirestgm + 0xc should be size - 0x10 instead of 0x%08lx\n", *(DWORD *)wirehemf);
2222 wirehemf += sizeof(DWORD);
2223 ok(*(DWORD *)wirehemf == EMR_HEADER, "wirestgm + 0x10 should be EMR_HEADER instead of %ld\n", *(DWORD *)wirehemf);
2224 wirehemf += sizeof(DWORD);
2225 /* ... rest of data not tested - refer to tests for GetEnhMetaFileBits
2228 HENHMETAFILE_UserUnmarshal(&flags, buffer, &hemf2);
2229 ok(hemf2 != NULL, "HENHMETAFILE didn't unmarshal\n");
2230 HeapFree(GetProcessHeap(), 0, buffer);
2231 HENHMETAFILE_UserFree(&flags, &hemf2);
2232 DeleteEnhMetaFile(hemf);
2237 size = HENHMETAFILE_UserSize(&flags, 0, &hemf);
2238 ok(size == 8, "size should be 8 bytes, not %ld\n", size);
2239 buffer = (unsigned char *)HeapAlloc(GetProcessHeap(), 0, size);
2240 HENHMETAFILE_UserMarshal(&flags, buffer, &hemf);
2242 ok(*(DWORD *)wirehemf == WDT_REMOTE_CALL, "wirestgm + 0x0 should be WDT_REMOTE_CALL instead of 0x%08lx\n", *(DWORD *)wirehemf);
2243 wirehemf += sizeof(DWORD);
2244 ok(*(DWORD *)wirehemf == (DWORD)(DWORD_PTR)hemf, "wirestgm + 0x4 should be hemf instead of 0x%08lx\n", *(DWORD *)wirehemf);
2245 wirehemf += sizeof(DWORD);
2247 HENHMETAFILE_UserUnmarshal(&flags, buffer, &hemf2);
2248 ok(hemf2 == NULL, "NULL HENHMETAFILE didn't unmarshal\n");
2249 HeapFree(GetProcessHeap(), 0, buffer);
2250 HENHMETAFILE_UserFree(&flags, &hemf2);
2256 HMODULE hOle32 = GetModuleHandle("ole32");
2257 if (!(pCoInitializeEx = (void*)GetProcAddress(hOle32, "CoInitializeEx"))) goto no_test;
2259 /* register a window class used in several tests */
2260 memset(&wndclass, 0, sizeof(wndclass));
2261 wndclass.lpfnWndProc = window_proc;
2262 wndclass.lpszClassName = "WineCOMTest";
2263 RegisterClass(&wndclass);
2265 test_cocreateinstance_proxy();
2267 pCoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
2269 /* FIXME: test CoCreateInstanceEx */
2271 /* lifecycle management and marshaling tests */
2272 test_no_marshaler();
2273 test_normal_marshal_and_release();
2274 test_normal_marshal_and_unmarshal();
2275 test_marshal_and_unmarshal_invalid();
2276 test_interthread_marshal_and_unmarshal();
2277 test_proxy_marshal_and_unmarshal();
2278 test_proxy_marshal_and_unmarshal2();
2279 test_marshal_stub_apartment_shutdown();
2280 test_marshal_proxy_apartment_shutdown();
2281 test_marshal_proxy_mta_apartment_shutdown();
2282 test_no_couninitialize_server();
2283 test_no_couninitialize_client();
2284 test_tableweak_marshal_and_unmarshal_twice();
2285 test_tableweak_marshal_releasedata1();
2286 test_tableweak_marshal_releasedata2();
2287 test_tablestrong_marshal_and_unmarshal_twice();
2288 test_lock_object_external();
2289 test_disconnect_stub();
2290 test_normal_marshal_and_unmarshal_twice();
2291 test_hresult_marshaling();
2292 test_proxy_used_in_wrong_thread();
2293 test_message_filter();
2294 test_bad_marshal_stream();
2295 test_proxy_interfaces();
2296 test_stubbuffer(&IID_IClassFactory);
2297 test_proxybuffer(&IID_IClassFactory);
2298 test_message_reentrancy();
2299 test_WM_QUIT_handling();
2300 test_freethreadedmarshaler();
2302 /* doesn't pass with Win9x COM DLLs (even though Essential COM says it should) */
2303 if (0) test_out_of_process_com();
2306 test_globalinterfacetable();
2308 test_marshal_CLIPFORMAT();
2309 test_marshal_HWND();
2310 test_marshal_HGLOBAL();
2311 test_marshal_HENHMETAFILE();
2317 trace("You need DCOM95 installed to run this test\n");