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
31 #include "wine/test.h"
33 /* functions that are not present on all versions of Windows */
34 HRESULT (WINAPI * pCoInitializeEx)(LPVOID lpReserved, DWORD dwCoInit);
36 /* helper macros to make tests a bit leaner */
37 #define ok_more_than_one_lock() ok(cLocks > 0, "Number of locks should be > 0, but actually is %ld\n", cLocks)
38 #define ok_no_locks() ok(cLocks == 0, "Number of locks should be 0, but actually is %ld\n", cLocks)
39 #define ok_ole_success(hr, func) ok(hr == S_OK, #func " failed with error 0x%08lx\n", hr)
41 static const IID IID_IWineTest =
46 {0xa1, 0xa2, 0x5d, 0x5a, 0x36, 0x54, 0xd3, 0xbd}
47 }; /* 5201163f-8164-4fd0-a1a2-5d5a3654d3bd */
49 static void test_CoGetPSClsid(void)
54 hr = CoGetPSClsid(&IID_IClassFactory, &clsid);
55 ok_ole_success(hr, CoGetPSClsid);
57 hr = CoGetPSClsid(&IID_IWineTest, &clsid);
58 ok(hr == REGDB_E_IIDNOTREG,
59 "CoGetPSClsid for random IID returned 0x%08lx instead of REGDB_E_IIDNOTREG\n",
63 static void test_cocreateinstance_proxy(void)
69 pCoInitializeEx(NULL, COINIT_MULTITHREADED);
71 hr = CoCreateInstance(&CLSID_ShellDesktop, NULL, CLSCTX_INPROC, &IID_IUnknown, (void **)&pProxy);
72 ok_ole_success(hr, CoCreateInstance);
73 hr = IUnknown_QueryInterface(pProxy, &IID_IMultiQI, (void **)&pMQI);
75 ok(hr == S_OK, "created object is not a proxy, so was created in the wrong apartment\n");
77 IMultiQI_Release(pMQI);
78 IUnknown_Release(pProxy);
83 static const LARGE_INTEGER ullZero;
86 static void LockModule(void)
88 InterlockedIncrement(&cLocks);
91 static void UnlockModule(void)
93 InterlockedDecrement(&cLocks);
97 static HRESULT WINAPI Test_IUnknown_QueryInterface(
102 if (ppvObj == NULL) return E_POINTER;
104 if (IsEqualGUID(riid, &IID_IUnknown))
106 *ppvObj = (LPVOID)iface;
107 IUnknown_AddRef(iface);
112 return E_NOINTERFACE;
115 static ULONG WINAPI Test_IUnknown_AddRef(LPUNKNOWN iface)
118 return 2; /* non-heap-based object */
121 static ULONG WINAPI Test_IUnknown_Release(LPUNKNOWN iface)
124 return 1; /* non-heap-based object */
127 static const IUnknownVtbl TestUnknown_Vtbl =
129 Test_IUnknown_QueryInterface,
130 Test_IUnknown_AddRef,
131 Test_IUnknown_Release,
134 static IUnknown Test_Unknown = { &TestUnknown_Vtbl };
137 static HRESULT WINAPI Test_IClassFactory_QueryInterface(
138 LPCLASSFACTORY iface,
142 if (ppvObj == NULL) return E_POINTER;
144 if (IsEqualGUID(riid, &IID_IUnknown) ||
145 IsEqualGUID(riid, &IID_IClassFactory))
147 *ppvObj = (LPVOID)iface;
148 IClassFactory_AddRef(iface);
153 return E_NOINTERFACE;
156 static ULONG WINAPI Test_IClassFactory_AddRef(LPCLASSFACTORY iface)
159 return 2; /* non-heap-based object */
162 static ULONG WINAPI Test_IClassFactory_Release(LPCLASSFACTORY iface)
165 return 1; /* non-heap-based object */
168 static HRESULT WINAPI Test_IClassFactory_CreateInstance(
169 LPCLASSFACTORY iface,
174 if (pUnkOuter) return CLASS_E_NOAGGREGATION;
175 return IUnknown_QueryInterface((IUnknown*)&Test_Unknown, riid, ppvObj);
178 static HRESULT WINAPI Test_IClassFactory_LockServer(
179 LPCLASSFACTORY iface,
185 static const IClassFactoryVtbl TestClassFactory_Vtbl =
187 Test_IClassFactory_QueryInterface,
188 Test_IClassFactory_AddRef,
189 Test_IClassFactory_Release,
190 Test_IClassFactory_CreateInstance,
191 Test_IClassFactory_LockServer
194 static IClassFactory Test_ClassFactory = { &TestClassFactory_Vtbl };
196 #define RELEASEMARSHALDATA WM_USER
198 struct host_object_data
203 MSHLFLAGS marshal_flags;
204 HANDLE marshal_event;
205 IMessageFilter *filter;
208 static DWORD CALLBACK host_object_proc(LPVOID p)
210 struct host_object_data *data = (struct host_object_data *)p;
214 pCoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
218 IMessageFilter * prev_filter = NULL;
219 hr = CoRegisterMessageFilter(data->filter, &prev_filter);
220 if (prev_filter) IMessageFilter_Release(prev_filter);
221 ok_ole_success(hr, CoRegisterMessageFilter);
224 hr = CoMarshalInterface(data->stream, &data->iid, data->object, MSHCTX_INPROC, NULL, data->marshal_flags);
225 ok_ole_success(hr, CoMarshalInterface);
227 /* force the message queue to be created before signaling parent thread */
228 PeekMessage(&msg, NULL, WM_USER, WM_USER, PM_NOREMOVE);
230 SetEvent(data->marshal_event);
232 while (GetMessage(&msg, NULL, 0, 0))
234 if (msg.hwnd == NULL && msg.message == RELEASEMARSHALDATA)
236 trace("releasing marshal data\n");
237 CoReleaseMarshalData(data->stream);
238 SetEvent((HANDLE)msg.lParam);
241 DispatchMessage(&msg);
244 HeapFree(GetProcessHeap(), 0, data);
251 static DWORD start_host_object2(IStream *stream, REFIID riid, IUnknown *object, MSHLFLAGS marshal_flags, IMessageFilter *filter, HANDLE *thread)
254 HANDLE marshal_event = CreateEvent(NULL, FALSE, FALSE, NULL);
255 struct host_object_data *data = HeapAlloc(GetProcessHeap(), 0, sizeof(*data));
257 data->stream = stream;
259 data->object = object;
260 data->marshal_flags = marshal_flags;
261 data->marshal_event = marshal_event;
262 data->filter = filter;
264 *thread = CreateThread(NULL, 0, host_object_proc, data, 0, &tid);
266 /* wait for marshaling to complete before returning */
267 WaitForSingleObject(marshal_event, INFINITE);
268 CloseHandle(marshal_event);
273 static DWORD start_host_object(IStream *stream, REFIID riid, IUnknown *object, MSHLFLAGS marshal_flags, HANDLE *thread)
275 return start_host_object2(stream, riid, object, marshal_flags, NULL, thread);
278 /* asks thread to release the marshal data because it has to be done by the
279 * same thread that marshaled the interface in the first place. */
280 static void release_host_object(DWORD tid)
282 HANDLE event = CreateEvent(NULL, FALSE, FALSE, NULL);
283 PostThreadMessage(tid, RELEASEMARSHALDATA, 0, (LPARAM)event);
284 WaitForSingleObject(event, INFINITE);
288 static void end_host_object(DWORD tid, HANDLE thread)
290 BOOL ret = PostThreadMessage(tid, WM_QUIT, 0, 0);
291 ok(ret, "PostThreadMessage failed with error %ld\n", GetLastError());
292 /* be careful of races - don't return until hosting thread has terminated */
293 WaitForSingleObject(thread, INFINITE);
297 /* tests failure case of interface not having a marshaler specified in the
299 static void test_no_marshaler(void)
304 hr = CreateStreamOnHGlobal(NULL, TRUE, &pStream);
305 ok_ole_success(hr, CreateStreamOnHGlobal);
306 hr = CoMarshalInterface(pStream, &IID_IWineTest, (IUnknown*)&Test_ClassFactory, MSHCTX_INPROC, NULL, MSHLFLAGS_NORMAL);
307 ok(hr == E_NOINTERFACE, "CoMarshalInterface should have returned E_NOINTERFACE instead of 0x%08lx\n", hr);
309 IStream_Release(pStream);
312 /* tests normal marshal and then release without unmarshaling */
313 static void test_normal_marshal_and_release(void)
316 IStream *pStream = NULL;
320 hr = CreateStreamOnHGlobal(NULL, TRUE, &pStream);
321 ok_ole_success(hr, CreateStreamOnHGlobal);
322 hr = CoMarshalInterface(pStream, &IID_IClassFactory, (IUnknown*)&Test_ClassFactory, MSHCTX_INPROC, NULL, MSHLFLAGS_NORMAL);
323 ok_ole_success(hr, CoMarshalInterface);
325 ok_more_than_one_lock();
327 IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
328 hr = CoReleaseMarshalData(pStream);
329 ok_ole_success(hr, CoReleaseMarshalData);
330 IStream_Release(pStream);
335 /* tests success case of a same-thread marshal and unmarshal */
336 static void test_normal_marshal_and_unmarshal(void)
339 IStream *pStream = NULL;
340 IUnknown *pProxy = NULL;
344 hr = CreateStreamOnHGlobal(NULL, TRUE, &pStream);
345 ok_ole_success(hr, CreateStreamOnHGlobal);
346 hr = CoMarshalInterface(pStream, &IID_IClassFactory, (IUnknown*)&Test_ClassFactory, MSHCTX_INPROC, NULL, MSHLFLAGS_NORMAL);
347 ok_ole_success(hr, CoMarshalInterface);
349 ok_more_than_one_lock();
351 IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
352 hr = CoUnmarshalInterface(pStream, &IID_IClassFactory, (void **)&pProxy);
353 ok_ole_success(hr, CoUnmarshalInterface);
354 IStream_Release(pStream);
356 ok_more_than_one_lock();
358 IUnknown_Release(pProxy);
363 /* tests failure case of unmarshaling a freed object */
364 static void test_marshal_and_unmarshal_invalid(void)
367 IStream *pStream = NULL;
368 IClassFactory *pProxy = NULL;
375 hr = CreateStreamOnHGlobal(NULL, TRUE, &pStream);
376 ok_ole_success(hr, CreateStreamOnHGlobal);
377 tid = start_host_object(pStream, &IID_IClassFactory, (IUnknown*)&Test_ClassFactory, MSHLFLAGS_NORMAL, &thread);
379 ok_more_than_one_lock();
381 IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
382 hr = CoReleaseMarshalData(pStream);
383 ok_ole_success(hr, CoReleaseMarshalData);
387 IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
388 hr = CoUnmarshalInterface(pStream, &IID_IClassFactory, (void **)&pProxy);
389 todo_wine { ok_ole_success(hr, CoUnmarshalInterface); }
395 hr = IClassFactory_CreateInstance(pProxy, NULL, &IID_IUnknown, &dummy);
396 ok(hr == RPC_E_DISCONNECTED, "Remote call should have returned RPC_E_DISCONNECTED, instead of 0x%08lx\n", hr);
398 IClassFactory_Release(pProxy);
401 IStream_Release(pStream);
403 end_host_object(tid, thread);
406 /* tests success case of an interthread marshal */
407 static void test_interthread_marshal_and_unmarshal(void)
410 IStream *pStream = NULL;
411 IUnknown *pProxy = NULL;
417 hr = CreateStreamOnHGlobal(NULL, TRUE, &pStream);
418 ok_ole_success(hr, CreateStreamOnHGlobal);
419 tid = start_host_object(pStream, &IID_IClassFactory, (IUnknown*)&Test_ClassFactory, MSHLFLAGS_NORMAL, &thread);
421 ok_more_than_one_lock();
423 IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
424 hr = CoUnmarshalInterface(pStream, &IID_IClassFactory, (void **)&pProxy);
425 ok_ole_success(hr, CoUnmarshalInterface);
426 IStream_Release(pStream);
428 ok_more_than_one_lock();
430 IUnknown_Release(pProxy);
434 end_host_object(tid, thread);
437 /* the number of external references that Wine's proxy manager normally gives
438 * out, so we can test the border case of running out of references */
439 #define NORMALEXTREFS 5
441 /* tests success case of an interthread marshal and then marshaling the proxy */
442 static void test_proxy_marshal_and_unmarshal(void)
445 IStream *pStream = NULL;
446 IUnknown *pProxy = NULL;
447 IUnknown *pProxy2 = NULL;
454 hr = CreateStreamOnHGlobal(NULL, TRUE, &pStream);
455 ok_ole_success(hr, CreateStreamOnHGlobal);
456 tid = start_host_object(pStream, &IID_IClassFactory, (IUnknown*)&Test_ClassFactory, MSHLFLAGS_NORMAL, &thread);
458 ok_more_than_one_lock();
460 IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
461 hr = CoUnmarshalInterface(pStream, &IID_IClassFactory, (void **)&pProxy);
462 ok_ole_success(hr, CoUnmarshalInterface);
464 ok_more_than_one_lock();
466 IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
467 /* marshal the proxy */
468 hr = CoMarshalInterface(pStream, &IID_IClassFactory, pProxy, MSHCTX_INPROC, NULL, MSHLFLAGS_NORMAL);
469 ok_ole_success(hr, CoMarshalInterface);
471 ok_more_than_one_lock();
473 /* marshal 5 more times to exhaust the normal external references of 5 */
474 for (i = 0; i < NORMALEXTREFS; i++)
476 hr = CoMarshalInterface(pStream, &IID_IClassFactory, pProxy, MSHCTX_INPROC, NULL, MSHLFLAGS_NORMAL);
477 ok_ole_success(hr, CoMarshalInterface);
480 ok_more_than_one_lock();
482 /* release the original proxy to test that we successfully keep the
483 * original object alive */
484 IUnknown_Release(pProxy);
486 IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
487 hr = CoUnmarshalInterface(pStream, &IID_IClassFactory, (void **)&pProxy2);
488 ok_ole_success(hr, CoUnmarshalInterface);
490 ok_more_than_one_lock();
492 /* now the proxies should be as follows:
493 * pProxy2 -> &Test_ClassFactory
494 * they should NOT be as follows:
495 * pProxy -> &Test_ClassFactory
497 * the above can only really be tested by looking in +ole traces
500 IUnknown_Release(pProxy2);
502 /* unmarshal all of the proxies to check that the object stub still exists */
503 for (i = 0; i < NORMALEXTREFS; i++)
505 hr = CoUnmarshalInterface(pStream, &IID_IClassFactory, (void **)&pProxy2);
506 ok_ole_success(hr, CoUnmarshalInterface);
508 IUnknown_Release(pProxy2);
513 IStream_Release(pStream);
515 end_host_object(tid, thread);
518 /* tests success case of an interthread marshal and then marshaling the proxy
519 * using an iid that hasn't previously been unmarshaled */
520 static void test_proxy_marshal_and_unmarshal2(void)
523 IStream *pStream = NULL;
524 IUnknown *pProxy = NULL;
525 IUnknown *pProxy2 = NULL;
531 hr = CreateStreamOnHGlobal(NULL, TRUE, &pStream);
532 ok_ole_success(hr, CreateStreamOnHGlobal);
533 tid = start_host_object(pStream, &IID_IUnknown, (IUnknown*)&Test_ClassFactory, MSHLFLAGS_NORMAL, &thread);
535 ok_more_than_one_lock();
537 IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
538 hr = CoUnmarshalInterface(pStream, &IID_IUnknown, (void **)&pProxy);
539 ok_ole_success(hr, CoUnmarshalInterface);
541 ok_more_than_one_lock();
543 IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
544 /* marshal the proxy */
545 hr = CoMarshalInterface(pStream, &IID_IClassFactory, pProxy, MSHCTX_INPROC, NULL, MSHLFLAGS_NORMAL);
546 ok_ole_success(hr, CoMarshalInterface);
548 ok_more_than_one_lock();
550 IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
551 /* unmarshal the second proxy to the object */
552 hr = CoUnmarshalInterface(pStream, &IID_IClassFactory, (void **)&pProxy2);
553 ok_ole_success(hr, CoUnmarshalInterface);
554 IStream_Release(pStream);
556 /* now the proxies should be as follows:
557 * pProxy -> &Test_ClassFactory
558 * pProxy2 -> &Test_ClassFactory
559 * they should NOT be as follows:
560 * pProxy -> &Test_ClassFactory
562 * the above can only really be tested by looking in +ole traces
565 ok_more_than_one_lock();
567 IUnknown_Release(pProxy);
569 ok_more_than_one_lock();
571 IUnknown_Release(pProxy2);
575 end_host_object(tid, thread);
578 /* tests that stubs are released when the containing apartment is destroyed */
579 static void test_marshal_stub_apartment_shutdown(void)
582 IStream *pStream = NULL;
583 IUnknown *pProxy = NULL;
589 hr = CreateStreamOnHGlobal(NULL, TRUE, &pStream);
590 ok_ole_success(hr, CreateStreamOnHGlobal);
591 tid = start_host_object(pStream, &IID_IClassFactory, (IUnknown*)&Test_ClassFactory, MSHLFLAGS_NORMAL, &thread);
593 ok_more_than_one_lock();
595 IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
596 hr = CoUnmarshalInterface(pStream, &IID_IClassFactory, (void **)&pProxy);
597 ok_ole_success(hr, CoUnmarshalInterface);
598 IStream_Release(pStream);
600 ok_more_than_one_lock();
602 end_host_object(tid, thread);
606 IUnknown_Release(pProxy);
611 /* tests that proxies are released when the containing apartment is destroyed */
612 static void test_marshal_proxy_apartment_shutdown(void)
615 IStream *pStream = NULL;
616 IUnknown *pProxy = NULL;
622 hr = CreateStreamOnHGlobal(NULL, TRUE, &pStream);
623 ok_ole_success(hr, CreateStreamOnHGlobal);
624 tid = start_host_object(pStream, &IID_IClassFactory, (IUnknown*)&Test_ClassFactory, MSHLFLAGS_NORMAL, &thread);
626 ok_more_than_one_lock();
628 IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
629 hr = CoUnmarshalInterface(pStream, &IID_IClassFactory, (void **)&pProxy);
630 ok_ole_success(hr, CoUnmarshalInterface);
631 IStream_Release(pStream);
633 ok_more_than_one_lock();
639 IUnknown_Release(pProxy);
643 end_host_object(tid, thread);
645 pCoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
648 /* tests that proxies are released when the containing mta apartment is destroyed */
649 static void test_marshal_proxy_mta_apartment_shutdown(void)
652 IStream *pStream = NULL;
653 IUnknown *pProxy = NULL;
658 pCoInitializeEx(NULL, COINIT_MULTITHREADED);
662 hr = CreateStreamOnHGlobal(NULL, TRUE, &pStream);
663 ok_ole_success(hr, CreateStreamOnHGlobal);
664 tid = start_host_object(pStream, &IID_IClassFactory, (IUnknown*)&Test_ClassFactory, MSHLFLAGS_NORMAL, &thread);
666 ok_more_than_one_lock();
668 IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
669 hr = CoUnmarshalInterface(pStream, &IID_IClassFactory, (void **)&pProxy);
670 ok_ole_success(hr, CoUnmarshalInterface);
671 IStream_Release(pStream);
673 ok_more_than_one_lock();
679 IUnknown_Release(pProxy);
683 end_host_object(tid, thread);
685 pCoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
691 HANDLE marshal_event;
692 HANDLE unmarshal_event;
695 /* helper for test_no_couninitialize_server */
696 static DWORD CALLBACK no_couninitialize_server_proc(LPVOID p)
698 struct ncu_params *ncu_params = (struct ncu_params *)p;
701 pCoInitializeEx(NULL, COINIT_MULTITHREADED);
703 hr = CoMarshalInterface(ncu_params->stream, &IID_IClassFactory, (IUnknown*)&Test_ClassFactory, MSHCTX_INPROC, NULL, MSHLFLAGS_NORMAL);
704 ok_ole_success(hr, CoMarshalInterface);
706 SetEvent(ncu_params->marshal_event);
708 WaitForSingleObject(ncu_params->unmarshal_event, INFINITE);
710 /* die without calling CoUninitialize */
715 /* tests apartment that an apartment with a stub is released without deadlock
716 * if the owning thread exits */
717 static void test_no_couninitialize_server(void)
720 IStream *pStream = NULL;
721 IUnknown *pProxy = NULL;
724 struct ncu_params ncu_params;
728 ncu_params.marshal_event = CreateEvent(NULL, TRUE, FALSE, NULL);
729 ncu_params.unmarshal_event = CreateEvent(NULL, TRUE, FALSE, NULL);
731 hr = CreateStreamOnHGlobal(NULL, TRUE, &pStream);
732 ok_ole_success(hr, CreateStreamOnHGlobal);
733 ncu_params.stream = pStream;
735 thread = CreateThread(NULL, 0, no_couninitialize_server_proc, &ncu_params, 0, &tid);
737 WaitForSingleObject(ncu_params.marshal_event, INFINITE);
738 ok_more_than_one_lock();
740 IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
741 hr = CoUnmarshalInterface(pStream, &IID_IClassFactory, (void **)&pProxy);
742 ok_ole_success(hr, CoUnmarshalInterface);
743 IStream_Release(pStream);
745 ok_more_than_one_lock();
747 SetEvent(ncu_params.unmarshal_event);
748 WaitForSingleObject(thread, INFINITE);
753 CloseHandle(ncu_params.marshal_event);
754 CloseHandle(ncu_params.unmarshal_event);
756 IUnknown_Release(pProxy);
761 /* STA -> STA call during DLL_THREAD_DETACH */
762 static DWORD CALLBACK no_couninitialize_client_proc(LPVOID p)
764 struct ncu_params *ncu_params = (struct ncu_params *)p;
766 IUnknown *pProxy = NULL;
768 pCoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
770 hr = CoUnmarshalInterface(ncu_params->stream, &IID_IClassFactory, (void **)&pProxy);
771 ok_ole_success(hr, CoUnmarshalInterface);
773 ok_more_than_one_lock();
775 /* die without calling CoUninitialize */
780 /* tests STA -> STA call during DLL_THREAD_DETACH doesn't deadlock */
781 static void test_no_couninitialize_client(void)
784 IStream *pStream = NULL;
789 struct ncu_params ncu_params;
793 hr = CreateStreamOnHGlobal(NULL, TRUE, &pStream);
794 ok_ole_success(hr, CreateStreamOnHGlobal);
795 ncu_params.stream = pStream;
797 /* NOTE: assumes start_host_object uses an STA to host the object, as MTAs
798 * always deadlock when called from within DllMain */
799 host_tid = start_host_object(pStream, &IID_IClassFactory, (IUnknown *)&Test_ClassFactory, MSHLFLAGS_NORMAL, &host_thread);
800 IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
802 ok_more_than_one_lock();
804 thread = CreateThread(NULL, 0, no_couninitialize_client_proc, &ncu_params, 0, &tid);
806 WaitForSingleObject(thread, INFINITE);
811 end_host_object(host_tid, host_thread);
814 /* tests success case of a same-thread table-weak marshal, unmarshal, unmarshal */
815 static void test_tableweak_marshal_and_unmarshal_twice(void)
818 IStream *pStream = NULL;
819 IUnknown *pProxy1 = NULL;
820 IUnknown *pProxy2 = NULL;
826 hr = CreateStreamOnHGlobal(NULL, TRUE, &pStream);
827 ok_ole_success(hr, CreateStreamOnHGlobal);
828 tid = start_host_object(pStream, &IID_IClassFactory, (IUnknown*)&Test_ClassFactory, MSHLFLAGS_TABLEWEAK, &thread);
830 ok_more_than_one_lock();
832 IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
833 hr = CoUnmarshalInterface(pStream, &IID_IClassFactory, (void **)&pProxy1);
834 ok_ole_success(hr, CoUnmarshalInterface);
836 ok_more_than_one_lock();
838 IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
839 hr = CoUnmarshalInterface(pStream, &IID_IClassFactory, (void **)&pProxy2);
840 ok_ole_success(hr, CoUnmarshalInterface);
842 ok_more_than_one_lock();
844 IUnknown_Release(pProxy1);
845 IUnknown_Release(pProxy2);
847 /* this line is shows the difference between weak and strong table marshaling:
848 * weak has cLocks == 0
849 * strong has cLocks > 0 */
852 end_host_object(tid, thread);
855 /* tests releasing after unmarshaling one object */
856 static void test_tableweak_marshal_releasedata1(void)
859 IStream *pStream = NULL;
860 IUnknown *pProxy1 = NULL;
861 IUnknown *pProxy2 = NULL;
867 hr = CreateStreamOnHGlobal(NULL, TRUE, &pStream);
868 ok_ole_success(hr, CreateStreamOnHGlobal);
869 tid = start_host_object(pStream, &IID_IClassFactory, (IUnknown*)&Test_ClassFactory, MSHLFLAGS_TABLEWEAK, &thread);
871 ok_more_than_one_lock();
873 IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
874 hr = CoUnmarshalInterface(pStream, &IID_IClassFactory, (void **)&pProxy1);
875 ok_ole_success(hr, CoUnmarshalInterface);
877 ok_more_than_one_lock();
879 /* release the remaining reference on the object by calling
880 * CoReleaseMarshalData in the hosting thread */
881 IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
882 release_host_object(tid);
884 ok_more_than_one_lock();
886 IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
887 hr = CoUnmarshalInterface(pStream, &IID_IClassFactory, (void **)&pProxy2);
888 ok_ole_success(hr, CoUnmarshalInterface);
889 IStream_Release(pStream);
891 ok_more_than_one_lock();
893 IUnknown_Release(pProxy1);
895 IUnknown_Release(pProxy2);
897 /* this line is shows the difference between weak and strong table marshaling:
898 * weak has cLocks == 0
899 * strong has cLocks > 0 */
902 end_host_object(tid, thread);
905 /* tests releasing after unmarshaling one object */
906 static void test_tableweak_marshal_releasedata2(void)
909 IStream *pStream = NULL;
910 IUnknown *pProxy = NULL;
916 hr = CreateStreamOnHGlobal(NULL, TRUE, &pStream);
917 ok_ole_success(hr, CreateStreamOnHGlobal);
918 tid = start_host_object(pStream, &IID_IClassFactory, (IUnknown*)&Test_ClassFactory, MSHLFLAGS_TABLEWEAK, &thread);
920 ok_more_than_one_lock();
922 /* release the remaining reference on the object by calling
923 * CoReleaseMarshalData in the hosting thread */
924 IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
925 release_host_object(tid);
929 IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
930 hr = CoUnmarshalInterface(pStream, &IID_IClassFactory, (void **)&pProxy);
933 ok(hr == CO_E_OBJNOTREG,
934 "CoUnmarshalInterface should have failed with CO_E_OBJNOTREG, but returned 0x%08lx instead\n",
937 IStream_Release(pStream);
941 end_host_object(tid, thread);
944 /* tests success case of a same-thread table-strong marshal, unmarshal, unmarshal */
945 static void test_tablestrong_marshal_and_unmarshal_twice(void)
948 IStream *pStream = NULL;
949 IUnknown *pProxy1 = NULL;
950 IUnknown *pProxy2 = NULL;
956 hr = CreateStreamOnHGlobal(NULL, TRUE, &pStream);
957 ok_ole_success(hr, CreateStreamOnHGlobal);
958 tid = start_host_object(pStream, &IID_IClassFactory, (IUnknown*)&Test_ClassFactory, MSHLFLAGS_TABLESTRONG, &thread);
960 ok_more_than_one_lock();
962 IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
963 hr = CoUnmarshalInterface(pStream, &IID_IClassFactory, (void **)&pProxy1);
964 ok_ole_success(hr, CoUnmarshalInterface);
966 ok_more_than_one_lock();
968 IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
969 hr = CoUnmarshalInterface(pStream, &IID_IClassFactory, (void **)&pProxy2);
970 ok_ole_success(hr, CoUnmarshalInterface);
972 ok_more_than_one_lock();
974 if (pProxy1) IUnknown_Release(pProxy1);
975 if (pProxy2) IUnknown_Release(pProxy2);
977 /* this line is shows the difference between weak and strong table marshaling:
978 * weak has cLocks == 0
979 * strong has cLocks > 0 */
980 ok_more_than_one_lock();
982 /* release the remaining reference on the object by calling
983 * CoReleaseMarshalData in the hosting thread */
984 IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
985 release_host_object(tid);
986 IStream_Release(pStream);
990 end_host_object(tid, thread);
993 /* tests CoLockObjectExternal */
994 static void test_lock_object_external(void)
997 IStream *pStream = NULL;
1001 /* test the stub manager creation aspect of CoLockObjectExternal when the
1002 * object hasn't been marshaled yet */
1003 CoLockObjectExternal((IUnknown*)&Test_ClassFactory, TRUE, TRUE);
1005 ok_more_than_one_lock();
1007 CoDisconnectObject((IUnknown*)&Test_ClassFactory, 0);
1011 /* test our empty stub manager being handled correctly in
1012 * CoMarshalInterface */
1013 CoLockObjectExternal((IUnknown*)&Test_ClassFactory, TRUE, TRUE);
1015 hr = CreateStreamOnHGlobal(NULL, TRUE, &pStream);
1016 ok_ole_success(hr, CreateStreamOnHGlobal);
1017 hr = CoMarshalInterface(pStream, &IID_IClassFactory, (IUnknown*)&Test_ClassFactory, MSHCTX_INPROC, NULL, MSHLFLAGS_NORMAL);
1018 ok_ole_success(hr, CoMarshalInterface);
1020 CoLockObjectExternal((IUnknown*)&Test_ClassFactory, TRUE, TRUE);
1022 ok_more_than_one_lock();
1024 IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
1025 hr = CoReleaseMarshalData(pStream);
1026 ok_ole_success(hr, CoReleaseMarshalData);
1027 IStream_Release(pStream);
1029 ok_more_than_one_lock();
1031 CoLockObjectExternal((IUnknown*)&Test_ClassFactory, FALSE, TRUE);
1033 ok_more_than_one_lock();
1035 CoLockObjectExternal((IUnknown*)&Test_ClassFactory, FALSE, TRUE);
1040 /* tests disconnecting stubs */
1041 static void test_disconnect_stub(void)
1044 IStream *pStream = NULL;
1048 hr = CreateStreamOnHGlobal(NULL, TRUE, &pStream);
1049 ok_ole_success(hr, CreateStreamOnHGlobal);
1050 hr = CoMarshalInterface(pStream, &IID_IClassFactory, (IUnknown*)&Test_ClassFactory, MSHCTX_INPROC, NULL, MSHLFLAGS_NORMAL);
1051 ok_ole_success(hr, CoMarshalInterface);
1053 CoLockObjectExternal((IUnknown*)&Test_ClassFactory, TRUE, TRUE);
1055 ok_more_than_one_lock();
1057 IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
1058 hr = CoReleaseMarshalData(pStream);
1059 ok_ole_success(hr, CoReleaseMarshalData);
1060 IStream_Release(pStream);
1062 ok_more_than_one_lock();
1064 CoDisconnectObject((IUnknown*)&Test_ClassFactory, 0);
1069 /* tests failure case of a same-thread marshal and unmarshal twice */
1070 static void test_normal_marshal_and_unmarshal_twice(void)
1073 IStream *pStream = NULL;
1074 IUnknown *pProxy1 = NULL;
1075 IUnknown *pProxy2 = NULL;
1079 hr = CreateStreamOnHGlobal(NULL, TRUE, &pStream);
1080 ok_ole_success(hr, CreateStreamOnHGlobal);
1081 hr = CoMarshalInterface(pStream, &IID_IClassFactory, (IUnknown*)&Test_ClassFactory, MSHCTX_INPROC, NULL, MSHLFLAGS_NORMAL);
1082 ok_ole_success(hr, CoMarshalInterface);
1084 ok_more_than_one_lock();
1086 IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
1087 hr = CoUnmarshalInterface(pStream, &IID_IClassFactory, (void **)&pProxy1);
1088 ok_ole_success(hr, CoUnmarshalInterface);
1090 ok_more_than_one_lock();
1092 IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
1093 hr = CoUnmarshalInterface(pStream, &IID_IClassFactory, (void **)&pProxy2);
1094 ok(hr == CO_E_OBJNOTCONNECTED,
1095 "CoUnmarshalInterface should have failed with error CO_E_OBJNOTCONNECTED for double unmarshal, instead of 0x%08lx\n", hr);
1097 IStream_Release(pStream);
1099 ok_more_than_one_lock();
1101 IUnknown_Release(pProxy1);
1106 /* tests success case of marshaling and unmarshaling an HRESULT */
1107 static void test_hresult_marshaling(void)
1110 HRESULT hr_marshaled = 0;
1111 IStream *pStream = NULL;
1112 static const HRESULT E_DEADBEEF = 0xdeadbeef;
1114 hr = CreateStreamOnHGlobal(NULL, TRUE, &pStream);
1115 ok_ole_success(hr, CreateStreamOnHGlobal);
1117 hr = CoMarshalHresult(pStream, E_DEADBEEF);
1118 ok_ole_success(hr, CoMarshalHresult);
1120 IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
1121 hr = IStream_Read(pStream, &hr_marshaled, sizeof(HRESULT), NULL);
1122 ok_ole_success(hr, IStream_Read);
1124 ok(hr_marshaled == E_DEADBEEF, "Didn't marshal HRESULT as expected: got value 0x%08lx instead\n", hr_marshaled);
1127 IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
1128 hr = CoUnmarshalHresult(pStream, &hr_marshaled);
1129 ok_ole_success(hr, CoUnmarshalHresult);
1131 ok(hr_marshaled == E_DEADBEEF, "Didn't marshal HRESULT as expected: got value 0x%08lx instead\n", hr_marshaled);
1133 IStream_Release(pStream);
1137 /* helper for test_proxy_used_in_wrong_thread */
1138 static DWORD CALLBACK bad_thread_proc(LPVOID p)
1140 IClassFactory * cf = (IClassFactory *)p;
1142 IUnknown * proxy = NULL;
1144 pCoInitializeEx(NULL, COINIT_MULTITHREADED);
1146 hr = IClassFactory_CreateInstance(cf, NULL, &IID_IUnknown, (LPVOID*)&proxy);
1147 if (proxy) IUnknown_Release(proxy);
1148 ok(hr == RPC_E_WRONG_THREAD,
1149 "COM should have failed with RPC_E_WRONG_THREAD on using proxy from wrong apartment, but instead returned 0x%08lx\n",
1157 /* tests failure case of a using a proxy in the wrong apartment */
1158 static void test_proxy_used_in_wrong_thread(void)
1161 IStream *pStream = NULL;
1162 IUnknown *pProxy = NULL;
1169 hr = CreateStreamOnHGlobal(NULL, TRUE, &pStream);
1170 ok_ole_success(hr, CreateStreamOnHGlobal);
1171 tid = start_host_object(pStream, &IID_IClassFactory, (IUnknown*)&Test_ClassFactory, MSHLFLAGS_NORMAL, &host_thread);
1173 ok_more_than_one_lock();
1175 IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
1176 hr = CoUnmarshalInterface(pStream, &IID_IClassFactory, (void **)&pProxy);
1177 ok_ole_success(hr, CoUnmarshalInterface);
1178 IStream_Release(pStream);
1180 ok_more_than_one_lock();
1182 /* create a thread that we can misbehave in */
1183 thread = CreateThread(NULL, 0, bad_thread_proc, (LPVOID)pProxy, 0, &tid2);
1185 WaitForSingleObject(thread, INFINITE);
1186 CloseHandle(thread);
1188 IUnknown_Release(pProxy);
1192 end_host_object(tid, host_thread);
1195 static HRESULT WINAPI MessageFilter_QueryInterface(IMessageFilter *iface, REFIID riid, void ** ppvObj)
1197 if (ppvObj == NULL) return E_POINTER;
1199 if (IsEqualGUID(riid, &IID_IUnknown) ||
1200 IsEqualGUID(riid, &IID_IClassFactory))
1202 *ppvObj = (LPVOID)iface;
1203 IClassFactory_AddRef(iface);
1207 return E_NOINTERFACE;
1210 static ULONG WINAPI MessageFilter_AddRef(IMessageFilter *iface)
1212 return 2; /* non-heap object */
1215 static ULONG WINAPI MessageFilter_Release(IMessageFilter *iface)
1217 return 1; /* non-heap object */
1220 static DWORD WINAPI MessageFilter_HandleInComingCall(
1221 IMessageFilter *iface,
1223 HTASK threadIDCaller,
1225 LPINTERFACEINFO lpInterfaceInfo)
1227 static int callcount = 0;
1229 trace("HandleInComingCall\n");
1233 ret = SERVERCALL_REJECTED;
1236 ret = SERVERCALL_RETRYLATER;
1239 ret = SERVERCALL_ISHANDLED;
1246 static DWORD WINAPI MessageFilter_RetryRejectedCall(
1247 IMessageFilter *iface,
1248 HTASK threadIDCallee,
1252 trace("RetryRejectedCall\n");
1256 static DWORD WINAPI MessageFilter_MessagePending(
1257 IMessageFilter *iface,
1258 HTASK threadIDCallee,
1260 DWORD dwPendingType)
1262 trace("MessagePending\n");
1263 return PENDINGMSG_WAITNOPROCESS;
1266 static const IMessageFilterVtbl MessageFilter_Vtbl =
1268 MessageFilter_QueryInterface,
1269 MessageFilter_AddRef,
1270 MessageFilter_Release,
1271 MessageFilter_HandleInComingCall,
1272 MessageFilter_RetryRejectedCall,
1273 MessageFilter_MessagePending
1276 static IMessageFilter MessageFilter = { &MessageFilter_Vtbl };
1278 static void test_message_filter(void)
1281 IStream *pStream = NULL;
1282 IClassFactory *cf = NULL;
1284 IUnknown *proxy = NULL;
1285 IMessageFilter *prev_filter = NULL;
1290 hr = CreateStreamOnHGlobal(NULL, TRUE, &pStream);
1291 ok_ole_success(hr, CreateStreamOnHGlobal);
1292 tid = start_host_object2(pStream, &IID_IClassFactory, (IUnknown*)&Test_ClassFactory, MSHLFLAGS_NORMAL, &MessageFilter, &thread);
1294 ok_more_than_one_lock();
1296 IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
1297 hr = CoUnmarshalInterface(pStream, &IID_IClassFactory, (void **)&cf);
1298 ok_ole_success(hr, CoUnmarshalInterface);
1299 IStream_Release(pStream);
1301 ok_more_than_one_lock();
1303 hr = IClassFactory_CreateInstance(cf, NULL, &IID_IUnknown, (LPVOID*)&proxy);
1304 todo_wine { ok(hr == RPC_E_CALL_REJECTED, "Call should have returned RPC_E_CALL_REJECTED, but return 0x%08lx instead\n", hr); }
1305 if (proxy) IUnknown_Release(proxy);
1308 hr = CoRegisterMessageFilter(&MessageFilter, &prev_filter);
1309 ok_ole_success(hr, CoRegisterMessageFilter);
1310 if (prev_filter) IMessageFilter_Release(prev_filter);
1312 hr = IClassFactory_CreateInstance(cf, NULL, &IID_IUnknown, (LPVOID*)&proxy);
1313 ok_ole_success(hr, IClassFactory_CreateInstance);
1315 IUnknown_Release(proxy);
1317 IClassFactory_Release(cf);
1321 end_host_object(tid, thread);
1324 /* test failure case of trying to unmarshal from bad stream */
1325 static void test_bad_marshal_stream(void)
1328 IStream *pStream = NULL;
1330 hr = CreateStreamOnHGlobal(NULL, TRUE, &pStream);
1331 ok_ole_success(hr, CreateStreamOnHGlobal);
1332 hr = CoMarshalInterface(pStream, &IID_IClassFactory, (IUnknown*)&Test_ClassFactory, MSHCTX_INPROC, NULL, MSHLFLAGS_NORMAL);
1333 ok_ole_success(hr, CoMarshalInterface);
1335 ok_more_than_one_lock();
1337 /* try to read beyond end of stream */
1338 hr = CoReleaseMarshalData(pStream);
1339 ok(hr == STG_E_READFAULT, "Should have failed with STG_E_READFAULT, but returned 0x%08lx instead\n", hr);
1341 /* now release for real */
1342 IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
1343 hr = CoReleaseMarshalData(pStream);
1344 ok_ole_success(hr, CoReleaseMarshalData);
1346 IStream_Release(pStream);
1349 /* tests that proxies implement certain interfaces */
1350 static void test_proxy_interfaces(void)
1353 IStream *pStream = NULL;
1354 IUnknown *pProxy = NULL;
1355 IUnknown *pOtherUnknown = NULL;
1361 hr = CreateStreamOnHGlobal(NULL, TRUE, &pStream);
1362 ok_ole_success(hr, CreateStreamOnHGlobal);
1363 tid = start_host_object(pStream, &IID_IClassFactory, (IUnknown*)&Test_ClassFactory, MSHLFLAGS_NORMAL, &thread);
1365 ok_more_than_one_lock();
1367 IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
1368 hr = CoUnmarshalInterface(pStream, &IID_IUnknown, (void **)&pProxy);
1369 ok_ole_success(hr, CoUnmarshalInterface);
1370 IStream_Release(pStream);
1372 ok_more_than_one_lock();
1374 hr = IUnknown_QueryInterface(pProxy, &IID_IUnknown, (LPVOID*)&pOtherUnknown);
1375 ok_ole_success(hr, IUnknown_QueryInterface IID_IUnknown);
1376 if (hr == S_OK) IUnknown_Release(pOtherUnknown);
1378 hr = IUnknown_QueryInterface(pProxy, &IID_IClientSecurity, (LPVOID*)&pOtherUnknown);
1379 todo_wine { ok_ole_success(hr, IUnknown_QueryInterface IID_IClientSecurity); }
1380 if (hr == S_OK) IUnknown_Release(pOtherUnknown);
1382 hr = IUnknown_QueryInterface(pProxy, &IID_IMultiQI, (LPVOID*)&pOtherUnknown);
1383 ok_ole_success(hr, IUnknown_QueryInterface IID_IMultiQI);
1384 if (hr == S_OK) IUnknown_Release(pOtherUnknown);
1386 hr = IUnknown_QueryInterface(pProxy, &IID_IMarshal, (LPVOID*)&pOtherUnknown);
1387 ok_ole_success(hr, IUnknown_QueryInterface IID_IMarshal);
1388 if (hr == S_OK) IUnknown_Release(pOtherUnknown);
1390 /* IMarshal2 is also supported on NT-based systems, but is pretty much
1391 * useless as it has no more methods over IMarshal that it inherits from. */
1393 IUnknown_Release(pProxy);
1397 end_host_object(tid, thread);
1402 const IUnknownVtbl *lpVtbl;
1406 static HRESULT WINAPI HeapUnknown_QueryInterface(IUnknown *iface, REFIID riid, void **ppv)
1408 if (IsEqualIID(riid, &IID_IUnknown))
1410 IUnknown_AddRef(iface);
1411 *ppv = (LPVOID)iface;
1415 return E_NOINTERFACE;
1418 static ULONG WINAPI HeapUnknown_AddRef(IUnknown *iface)
1420 HeapUnknown *This = (HeapUnknown *)iface;
1421 trace("HeapUnknown_AddRef(%p)\n", iface);
1422 return InterlockedIncrement((LONG*)&This->refs);
1425 static ULONG WINAPI HeapUnknown_Release(IUnknown *iface)
1427 HeapUnknown *This = (HeapUnknown *)iface;
1428 ULONG refs = InterlockedDecrement((LONG*)&This->refs);
1429 trace("HeapUnknown_Release(%p)\n", iface);
1430 if (!refs) HeapFree(GetProcessHeap(), 0, This);
1434 static const IUnknownVtbl HeapUnknown_Vtbl =
1436 HeapUnknown_QueryInterface,
1441 static void test_proxybuffer(REFIID riid)
1444 IPSFactoryBuffer *psfb;
1445 IRpcProxyBuffer *proxy;
1449 HeapUnknown *pUnkOuter = (HeapUnknown *)HeapAlloc(GetProcessHeap(), 0, sizeof(*pUnkOuter));
1451 pUnkOuter->lpVtbl = &HeapUnknown_Vtbl;
1452 pUnkOuter->refs = 1;
1454 hr = CoGetPSClsid(riid, &clsid);
1455 ok_ole_success(hr, CoGetPSClsid);
1457 hr = CoGetClassObject(&clsid, CLSCTX_INPROC_SERVER, NULL, &IID_IPSFactoryBuffer, (LPVOID*)&psfb);
1458 ok_ole_success(hr, CoGetClassObject);
1460 hr = IPSFactoryBuffer_CreateProxy(psfb, (IUnknown*)pUnkOuter, riid, &proxy, &lpvtbl);
1461 ok_ole_success(hr, IPSFactoryBuffer_CreateProxy);
1462 ok(lpvtbl != NULL, "IPSFactoryBuffer_CreateProxy succeeded, but returned a NULL vtable!\n");
1464 /* release our reference to the outer unknown object - the PS factory
1465 * buffer will have AddRef's it in the CreateProxy call */
1466 refs = IUnknown_Release((IUnknown *)pUnkOuter);
1467 ok(refs == 1, "Ref count of outer unknown should have been 1 instead of %ld\n", refs);
1469 refs = IPSFactoryBuffer_Release(psfb);
1470 #if 0 /* not reliable on native. maybe it leaks references! */
1471 ok(refs == 0, "Ref-count leak of %ld on IPSFactoryBuffer\n", refs);
1474 refs = IUnknown_Release((IUnknown *)lpvtbl);
1475 ok(refs == 0, "Ref-count leak of %ld on IRpcProxyBuffer\n", refs);
1477 refs = IRpcProxyBuffer_Release(proxy);
1478 ok(refs == 0, "Ref-count leak of %ld on IRpcProxyBuffer\n", refs);
1481 static void test_stubbuffer(REFIID riid)
1484 IPSFactoryBuffer *psfb;
1485 IRpcStubBuffer *stub;
1491 hr = CoGetPSClsid(riid, &clsid);
1492 ok_ole_success(hr, CoGetPSClsid);
1494 hr = CoGetClassObject(&clsid, CLSCTX_INPROC_SERVER, NULL, &IID_IPSFactoryBuffer, (LPVOID*)&psfb);
1495 ok_ole_success(hr, CoGetClassObject);
1497 hr = IPSFactoryBuffer_CreateStub(psfb, riid, (IUnknown*)&Test_ClassFactory, &stub);
1498 ok_ole_success(hr, IPSFactoryBuffer_CreateStub);
1500 refs = IPSFactoryBuffer_Release(psfb);
1501 #if 0 /* not reliable on native. maybe it leaks references */
1502 ok(refs == 0, "Ref-count leak of %ld on IPSFactoryBuffer\n", refs);
1505 ok_more_than_one_lock();
1507 IRpcStubBuffer_Disconnect(stub);
1511 refs = IRpcStubBuffer_Release(stub);
1512 ok(refs == 0, "Ref-count leak of %ld on IRpcProxyBuffer\n", refs);
1515 static HWND hwnd_app;
1517 static HRESULT WINAPI TestRE_IClassFactory_CreateInstance(
1518 LPCLASSFACTORY iface,
1519 LPUNKNOWN pUnkOuter,
1524 if (IsEqualIID(riid, &IID_IWineTest))
1526 BOOL ret = SendMessageTimeout(hwnd_app, WM_NULL, 0, 0, SMTO_BLOCK, 5000, &res);
1527 ok(ret, "Timed out sending a message to originating window during RPC call\n");
1532 static const IClassFactoryVtbl TestREClassFactory_Vtbl =
1534 Test_IClassFactory_QueryInterface,
1535 Test_IClassFactory_AddRef,
1536 Test_IClassFactory_Release,
1537 TestRE_IClassFactory_CreateInstance,
1538 Test_IClassFactory_LockServer
1541 IClassFactory TestRE_ClassFactory = { &TestREClassFactory_Vtbl };
1543 static LRESULT CALLBACK window_proc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam)
1550 IStream *pStream = NULL;
1551 IClassFactory *proxy = NULL;
1558 hr = CreateStreamOnHGlobal(NULL, TRUE, &pStream);
1559 ok_ole_success(hr, CreateStreamOnHGlobal);
1560 tid = start_host_object(pStream, &IID_IClassFactory, (IUnknown*)&TestRE_ClassFactory, MSHLFLAGS_NORMAL, &thread);
1562 ok_more_than_one_lock();
1564 IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
1565 hr = CoUnmarshalInterface(pStream, &IID_IClassFactory, (void **)&proxy);
1566 ok_ole_success(hr, CoReleaseMarshalData);
1567 IStream_Release(pStream);
1569 ok_more_than_one_lock();
1571 /* note the use of the magic IID_IWineTest value to tell remote thread
1572 * to try to send a message back to us */
1573 hr = IClassFactory_CreateInstance(proxy, NULL, &IID_IWineTest, (void **)&object);
1575 IClassFactory_Release(proxy);
1579 end_host_object(tid, thread);
1581 PostMessage(hwnd, WM_QUIT, 0, 0);
1588 IStream *pStream = NULL;
1589 IClassFactory *proxy = NULL;
1596 hr = CreateStreamOnHGlobal(NULL, TRUE, &pStream);
1597 ok_ole_success(hr, CreateStreamOnHGlobal);
1598 tid = start_host_object(pStream, &IID_IClassFactory, (IUnknown*)&TestRE_ClassFactory, MSHLFLAGS_NORMAL, &thread);
1600 ok_more_than_one_lock();
1602 IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
1603 hr = CoUnmarshalInterface(pStream, &IID_IClassFactory, (void **)&proxy);
1604 ok_ole_success(hr, CoReleaseMarshalData);
1605 IStream_Release(pStream);
1607 ok_more_than_one_lock();
1609 /* post quit message before a doing a COM call to show that a pending
1610 * WM_QUIT message doesn't stop the call from succeeding */
1611 PostMessage(hwnd, WM_QUIT, 0, 0);
1612 hr = IClassFactory_CreateInstance(proxy, NULL, &IID_IUnknown, (void **)&object);
1614 IClassFactory_Release(proxy);
1618 end_host_object(tid, thread);
1623 return DefWindowProc(hwnd, msg, wparam, lparam);
1627 static void test_message_reentrancy(void)
1632 memset(&wndclass, 0, sizeof(wndclass));
1633 wndclass.lpfnWndProc = window_proc;
1634 wndclass.lpszClassName = "WineCOMTest";
1635 RegisterClass(&wndclass);
1637 hwnd_app = CreateWindow("WineCOMTest", NULL, 0, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, NULL, NULL, NULL, 0);
1638 ok(hwnd_app != NULL, "Window creation failed\n");
1640 /* start message re-entrancy test */
1641 PostMessage(hwnd_app, WM_USER, 0, 0);
1643 while (GetMessage(&msg, NULL, 0, 0))
1645 TranslateMessage(&msg);
1646 DispatchMessage(&msg);
1650 static void test_WM_QUIT_handling(void)
1654 hwnd_app = CreateWindow("WineCOMTest", NULL, 0, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, NULL, NULL, NULL, 0);
1655 ok(hwnd_app != NULL, "Window creation failed\n");
1657 /* start WM_QUIT handling test */
1658 PostMessage(hwnd_app, WM_USER+1, 0, 0);
1660 while (GetMessage(&msg, NULL, 0, 0))
1662 TranslateMessage(&msg);
1663 DispatchMessage(&msg);
1667 static void test_freethreadedmarshaldata(IStream *pStream, MSHCTX mshctx, void *ptr, DWORD mshlflags)
1674 hr = GetHGlobalFromStream(pStream, &hglobal);
1675 ok_ole_success(hr, GetHGlobalFromStream);
1677 size = GlobalSize(hglobal);
1679 marshal_data = (char *)GlobalLock(hglobal);
1681 if (mshctx == MSHCTX_INPROC)
1683 DWORD expected_size = sizeof(DWORD) + sizeof(void *) + sizeof(DWORD) + sizeof(GUID);
1684 ok(size == expected_size, "size should have been %ld instead of %ld\n", expected_size, size);
1686 ok(*(DWORD *)marshal_data == mshlflags, "expected 0x%lx, but got 0x%lx for mshctx\n", mshlflags, *(DWORD *)marshal_data);
1687 marshal_data += sizeof(DWORD);
1688 ok(*(void **)marshal_data == ptr, "expected %p, but got %p for mshctx\n", ptr, *(void **)marshal_data);
1689 marshal_data += sizeof(void *);
1690 ok(*(DWORD *)marshal_data == 0, "expected 0x0, but got 0x%lx\n", *(DWORD *)marshal_data);
1691 marshal_data += sizeof(DWORD);
1692 trace("got guid data: {%08lx-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x}\n",
1693 ((GUID *)marshal_data)->Data1, ((GUID *)marshal_data)->Data2, ((GUID *)marshal_data)->Data3,
1694 ((GUID *)marshal_data)->Data4[0], ((GUID *)marshal_data)->Data4[1], ((GUID *)marshal_data)->Data4[2], ((GUID *)marshal_data)->Data4[3],
1695 ((GUID *)marshal_data)->Data4[4], ((GUID *)marshal_data)->Data4[5], ((GUID *)marshal_data)->Data4[6], ((GUID *)marshal_data)->Data4[7]);
1699 ok(size > sizeof(DWORD), "size should have been > sizeof(DWORD), not %ld\n", size);
1700 ok(*(DWORD *)marshal_data == 0x574f454d /* MEOW */,
1701 "marshal data should be filled by standard marshal and start with MEOW signature\n");
1704 GlobalUnlock(hglobal);
1707 static void test_freethreadedmarshaler(void)
1710 IUnknown *pFTUnknown;
1711 IMarshal *pFTMarshal;
1714 static const LARGE_INTEGER llZero;
1717 hr = CoCreateFreeThreadedMarshaler(NULL, &pFTUnknown);
1718 ok_ole_success(hr, CoCreateFreeThreadedMarshaler);
1719 hr = IUnknown_QueryInterface(pFTUnknown, &IID_IMarshal, (void **)&pFTMarshal);
1720 ok_ole_success(hr, IUnknown_QueryInterface);
1721 IUnknown_Release(pFTUnknown);
1723 hr = CreateStreamOnHGlobal(NULL, TRUE, &pStream);
1724 ok_ole_success(hr, CreateStreamOnHGlobal);
1726 /* inproc normal marshaling */
1728 hr = IMarshal_MarshalInterface(pFTMarshal, pStream, &IID_IClassFactory,
1729 (IUnknown*)&Test_ClassFactory, MSHCTX_INPROC, NULL, MSHLFLAGS_NORMAL);
1730 ok_ole_success(hr, IMarshal_MarshalInterface);
1732 ok_more_than_one_lock();
1734 test_freethreadedmarshaldata(pStream, MSHCTX_INPROC, &Test_ClassFactory, MSHLFLAGS_NORMAL);
1736 IStream_Seek(pStream, llZero, STREAM_SEEK_SET, NULL);
1737 hr = IMarshal_UnmarshalInterface(pFTMarshal, pStream, &IID_IUnknown, (void **)&pProxy);
1738 ok_ole_success(hr, IMarshal_UnmarshalInterface);
1740 IUnknown_Release(pProxy);
1744 /* native doesn't allow us to unmarshal or release the stream data,
1745 * presumably because it wants us to call CoMarshalInterface instead */
1747 /* local normal marshaling */
1749 IStream_Seek(pStream, llZero, STREAM_SEEK_SET, NULL);
1750 hr = IMarshal_MarshalInterface(pFTMarshal, pStream, IID_IClassFactory, (IUnknown*)&Test_ClassFactory, MSHCTX_LOCAL, NULL, MSHLFLAGS_NORMAL);
1751 ok_ole_success(hr, IMarshal_MarshalInterface);
1753 ok_more_than_one_lock();
1755 test_freethreadedmarshaldata(pStream, MSHCTX_LOCAL, &Test_ClassFactory, MSHLFLAGS_NORMAL);
1757 IStream_Seek(pStream, llZero, STREAM_SEEK_SET, NULL);
1758 hr = IMarshal_ReleaseMarshalData(pFTMarshal, pStream);
1759 ok_ole_success(hr, IMarshal_ReleaseMarshalData);
1764 /* inproc table-strong marshaling */
1766 IStream_Seek(pStream, llZero, STREAM_SEEK_SET, NULL);
1767 hr = IMarshal_MarshalInterface(pFTMarshal, pStream, &IID_IClassFactory,
1768 (IUnknown*)&Test_ClassFactory, MSHCTX_INPROC, (void *)0xdeadbeef,
1769 MSHLFLAGS_TABLESTRONG);
1770 ok_ole_success(hr, IMarshal_MarshalInterface);
1772 ok_more_than_one_lock();
1774 test_freethreadedmarshaldata(pStream, MSHCTX_INPROC, &Test_ClassFactory, MSHLFLAGS_TABLESTRONG);
1776 IStream_Seek(pStream, llZero, STREAM_SEEK_SET, NULL);
1777 hr = IMarshal_UnmarshalInterface(pFTMarshal, pStream, &IID_IUnknown, (void **)&pProxy);
1778 ok_ole_success(hr, IMarshal_UnmarshalInterface);
1780 IUnknown_Release(pProxy);
1782 ok_more_than_one_lock();
1784 IStream_Seek(pStream, llZero, STREAM_SEEK_SET, NULL);
1785 hr = IMarshal_ReleaseMarshalData(pFTMarshal, pStream);
1786 ok_ole_success(hr, IMarshal_ReleaseMarshalData);
1790 /* inproc table-weak marshaling */
1792 IStream_Seek(pStream, llZero, STREAM_SEEK_SET, NULL);
1793 hr = IMarshal_MarshalInterface(pFTMarshal, pStream, &IID_IClassFactory,
1794 (IUnknown*)&Test_ClassFactory, MSHCTX_INPROC, (void *)0xdeadbeef,
1795 MSHLFLAGS_TABLEWEAK);
1796 ok_ole_success(hr, IMarshal_MarshalInterface);
1800 test_freethreadedmarshaldata(pStream, MSHCTX_INPROC, &Test_ClassFactory, MSHLFLAGS_TABLEWEAK);
1802 IStream_Seek(pStream, llZero, STREAM_SEEK_SET, NULL);
1803 hr = IMarshal_UnmarshalInterface(pFTMarshal, pStream, &IID_IUnknown, (void **)&pProxy);
1804 ok_ole_success(hr, IMarshal_UnmarshalInterface);
1806 ok_more_than_one_lock();
1808 IUnknown_Release(pProxy);
1812 /* inproc normal marshaling (for extraordinary cases) */
1814 IStream_Seek(pStream, llZero, STREAM_SEEK_SET, NULL);
1815 hr = IMarshal_MarshalInterface(pFTMarshal, pStream, &IID_IClassFactory,
1816 (IUnknown*)&Test_ClassFactory, MSHCTX_INPROC, NULL, MSHLFLAGS_NORMAL);
1817 ok_ole_success(hr, IMarshal_MarshalInterface);
1819 ok_more_than_one_lock();
1821 /* this call shows that DisconnectObject does nothing */
1822 hr = IMarshal_DisconnectObject(pFTMarshal, 0);
1823 ok_ole_success(hr, IMarshal_DisconnectObject);
1825 ok_more_than_one_lock();
1827 IStream_Seek(pStream, llZero, STREAM_SEEK_SET, NULL);
1828 hr = IMarshal_ReleaseMarshalData(pFTMarshal, pStream);
1829 ok_ole_success(hr, IMarshal_ReleaseMarshalData);
1833 /* doesn't enforce marshaling rules here and allows us to unmarshal the
1834 * interface, even though it was freed above */
1835 IStream_Seek(pStream, llZero, STREAM_SEEK_SET, NULL);
1836 hr = IMarshal_UnmarshalInterface(pFTMarshal, pStream, &IID_IUnknown, (void **)&pProxy);
1837 ok_ole_success(hr, IMarshal_UnmarshalInterface);
1841 IStream_Release(pStream);
1842 IMarshal_Release(pFTMarshal);
1845 static HANDLE heventShutdown;
1847 static void LockModuleOOP(void)
1849 InterlockedIncrement(&cLocks); /* for test purposes only */
1850 CoAddRefServerProcess();
1853 static void UnlockModuleOOP(void)
1855 InterlockedDecrement(&cLocks); /* for test purposes only */
1856 if (!CoReleaseServerProcess())
1857 SetEvent(heventShutdown);
1860 static HWND hwnd_app;
1862 static HRESULT WINAPI TestOOP_IClassFactory_QueryInterface(
1863 LPCLASSFACTORY iface,
1867 if (ppvObj == NULL) return E_POINTER;
1869 if (IsEqualGUID(riid, &IID_IUnknown) ||
1870 IsEqualGUID(riid, &IID_IClassFactory))
1872 *ppvObj = (LPVOID)iface;
1873 IClassFactory_AddRef(iface);
1877 return E_NOINTERFACE;
1880 static ULONG WINAPI TestOOP_IClassFactory_AddRef(LPCLASSFACTORY iface)
1882 return 2; /* non-heap-based object */
1885 static ULONG WINAPI TestOOP_IClassFactory_Release(LPCLASSFACTORY iface)
1887 return 1; /* non-heap-based object */
1890 static HRESULT WINAPI TestOOP_IClassFactory_CreateInstance(
1891 LPCLASSFACTORY iface,
1892 LPUNKNOWN pUnkOuter,
1896 return CLASS_E_CLASSNOTAVAILABLE;
1899 static HRESULT WINAPI TestOOP_IClassFactory_LockServer(
1900 LPCLASSFACTORY iface,
1910 static const IClassFactoryVtbl TestClassFactoryOOP_Vtbl =
1912 TestOOP_IClassFactory_QueryInterface,
1913 TestOOP_IClassFactory_AddRef,
1914 TestOOP_IClassFactory_Release,
1915 TestOOP_IClassFactory_CreateInstance,
1916 TestOOP_IClassFactory_LockServer
1919 static IClassFactory TestOOP_ClassFactory = { &TestClassFactoryOOP_Vtbl };
1921 /* tests functions commonly used by out of process COM servers */
1922 static void test_out_of_process_com(void)
1924 static const CLSID CLSID_WineOOPTest = {
1928 {0xa1, 0xa2, 0x5d, 0x5a, 0x36, 0x54, 0xd3, 0xbd}
1929 }; /* 5201163f-8164-4fd0-a1a2-5d5a3654d3bd */
1935 heventShutdown = CreateEvent(NULL, TRUE, FALSE, NULL);
1939 /* Start the object suspended */
1940 hr = CoRegisterClassObject(&CLSID_WineOOPTest, (IUnknown *)&TestOOP_ClassFactory,
1941 CLSCTX_LOCAL_SERVER, REGCLS_MULTIPLEUSE | REGCLS_SUSPENDED, &cookie);
1942 ok_ole_success(hr, CoRegisterClassObject);
1944 /* ... and CoGetClassObject does not find it and fails when it looks for the
1945 * class in the registry */
1946 hr = CoGetClassObject(&CLSID_WineOOPTest, CLSCTX_INPROC_SERVER,
1947 NULL, &IID_IClassFactory, (LPVOID*)&cf);
1949 ok(hr == REGDB_E_CLASSNOTREG,
1950 "CoGetClassObject should have returned REGDB_E_CLASSNOTREG instead of 0x%08lx\n", hr);
1953 /* Resume the object suspended above ... */
1954 hr = CoResumeClassObjects();
1955 ok_ole_success(hr, CoResumeClassObjects);
1957 /* ... and now it should succeed */
1958 hr = CoGetClassObject(&CLSID_WineOOPTest, CLSCTX_INPROC_SERVER,
1959 NULL, &IID_IClassFactory, (LPVOID*)&cf);
1960 ok_ole_success(hr, CoGetClassObject);
1962 /* Now check the locking is working */
1963 /* NOTE: we are accessing the class directly, not through a proxy */
1967 hr = IClassFactory_LockServer(cf, TRUE);
1968 trace("IClassFactory_LockServer returned 0x%08lx\n", hr);
1970 ok_more_than_one_lock();
1972 IClassFactory_LockServer(cf, FALSE);
1976 IClassFactory_Release(cf);
1978 /* wait for shutdown signal */
1979 ret = WaitForSingleObject(heventShutdown, 5000);
1980 todo_wine { ok(ret != WAIT_TIMEOUT, "Server didn't shut down or machine is under very heavy load\n"); }
1982 /* try to connect again after SCM has suspended registered class objects */
1983 hr = CoGetClassObject(&CLSID_WineOOPTest, CLSCTX_INPROC_SERVER | CLSCTX_LOCAL_SERVER, NULL,
1984 &IID_IClassFactory, (LPVOID*)&cf);
1986 ok(hr == CO_E_SERVER_STOPPING,
1987 "CoGetClassObject should have returned CO_E_SERVER_STOPPING instead of 0x%08lx\n", hr);
1990 hr = CoRevokeClassObject(cookie);
1991 ok_ole_success(hr, CoRevokeClassObject);
1993 CloseHandle(heventShutdown);
1996 static void test_ROT(void)
1998 static const WCHAR wszFileName[] = {'B','E','2','0','E','2','F','5','-',
1999 '1','9','0','3','-','4','A','A','E','-','B','1','A','F','-',
2000 '2','0','4','6','E','5','8','6','C','9','2','5',0};
2002 IMoniker *pMoniker = NULL;
2003 IRunningObjectTable *pROT = NULL;
2008 hr = CreateFileMoniker(wszFileName, &pMoniker);
2009 ok_ole_success(hr, CreateClassMoniker);
2010 hr = GetRunningObjectTable(0, &pROT);
2011 ok_ole_success(hr, GetRunningObjectTable);
2012 hr = IRunningObjectTable_Register(pROT, 0, (IUnknown*)&Test_ClassFactory, pMoniker, &dwCookie);
2013 ok_ole_success(hr, IRunningObjectTable_Register);
2015 ok_more_than_one_lock();
2017 hr = IRunningObjectTable_Revoke(pROT, dwCookie);
2018 ok_ole_success(hr, IRunningObjectTable_Revoke);
2026 IGlobalInterfaceTable *git;
2029 static DWORD CALLBACK get_global_interface_proc(LPVOID pv)
2032 struct git_params *params = (struct git_params *)pv;
2035 hr = IGlobalInterfaceTable_GetInterfaceFromGlobal(params->git, params->cookie, &IID_IClassFactory, (void **)&cf);
2036 ok(hr == CO_E_NOTINITIALIZED,
2037 "IGlobalInterfaceTable_GetInterfaceFromGlobal should have failed with error CO_E_NOTINITIALIZED instead of 0x%08lx\n",
2041 hr = IGlobalInterfaceTable_GetInterfaceFromGlobal(params->git, params->cookie, &IID_IClassFactory, (void **)&cf);
2042 ok_ole_success(hr, IGlobalInterfaceTable_GetInterfaceFromGlobal);
2048 static void test_globalinterfacetable(void)
2051 IGlobalInterfaceTable *git;
2055 struct git_params params;
2058 hr = CoCreateInstance(&CLSID_StdGlobalInterfaceTable, NULL, CLSCTX_INPROC_SERVER, &IID_IGlobalInterfaceTable, (void **)&git);
2059 ok_ole_success(hr, CoCreateInstance);
2061 hr = IGlobalInterfaceTable_RegisterInterfaceInGlobal(git, (IUnknown *)&Test_ClassFactory, &IID_IClassFactory, &cookie);
2062 ok_ole_success(hr, IGlobalInterfaceTable_RegisterInterfaceInGlobal);
2064 params.cookie = cookie;
2066 /* note: params is on stack so we MUST wait for get_global_interface_proc
2067 * to exit before we can return */
2068 thread = CreateThread(NULL, 0, get_global_interface_proc, ¶ms, 0, &tid);
2070 ret = MsgWaitForMultipleObjects(1, &thread, FALSE, INFINITE, QS_ALLINPUT);
2071 while (ret == WAIT_OBJECT_0 + 1)
2074 while (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
2075 DispatchMessage(&msg);
2076 ret = MsgWaitForMultipleObjects(1, &thread, FALSE, INFINITE, QS_ALLINPUT);
2079 CloseHandle(thread);
2082 static const char cf_marshaled[] =
2094 static void test_marshal_CLIPFORMAT(void)
2096 unsigned char *buffer;
2098 unsigned long flags = MAKELONG(MSHCTX_DIFFERENTMACHINE, NDR_LOCAL_DATA_REPRESENTATION);
2099 wireCLIPFORMAT wirecf;
2100 CLIPFORMAT cf = RegisterClipboardFormatA("MyFormat");
2103 size = CLIPFORMAT_UserSize(&flags, 0, &cf);
2104 ok(size == sizeof(*wirecf) + sizeof(cf_marshaled), "Wrong size %ld\n", size);
2106 buffer = HeapAlloc(GetProcessHeap(), 0, size);
2107 CLIPFORMAT_UserMarshal(&flags, buffer, &cf);
2108 wirecf = (wireCLIPFORMAT)buffer;
2109 ok(wirecf->fContext == WDT_REMOTE_CALL, "Context should be WDT_REMOTE_CALL instead of 0x%08lx\n", wirecf->fContext);
2110 ok(wirecf->u.dwValue == cf, "Marshaled value should be 0x%04x instead of 0x%04lx\n", cf, wirecf->u.dwValue);
2111 ok(!memcmp(wirecf+1, cf_marshaled, sizeof(cf_marshaled)), "Marshaled data differs\n");
2113 CLIPFORMAT_UserUnmarshal(&flags, buffer, &cf2);
2114 ok(cf == cf2, "Didn't unmarshal properly\n");
2115 HeapFree(GetProcessHeap(), 0, buffer);
2117 CLIPFORMAT_UserFree(&flags, &cf2);
2120 static void test_marshal_HWND(void)
2122 unsigned char *buffer;
2124 unsigned long flags = MAKELONG(MSHCTX_LOCAL, NDR_LOCAL_DATA_REPRESENTATION);
2125 HWND hwnd = GetDesktopWindow();
2129 size = HWND_UserSize(&flags, 0, &hwnd);
2130 ok(size == sizeof(*wirehwnd), "Wrong size %ld\n", size);
2132 buffer = HeapAlloc(GetProcessHeap(), 0, size);
2133 HWND_UserMarshal(&flags, buffer, &hwnd);
2134 wirehwnd = (wireHWND)buffer;
2135 ok(wirehwnd->fContext == WDT_INPROC_CALL, "Context should be WDT_INPROC_CALL instead of 0x%08lx\n", wirehwnd->fContext);
2136 ok(wirehwnd->u.hInproc == (LONG_PTR)hwnd, "Marshaled value should be %p instead of %p\n", hwnd, (HANDLE)wirehwnd->u.hRemote);
2138 HWND_UserUnmarshal(&flags, buffer, &hwnd2);
2139 ok(hwnd == hwnd2, "Didn't unmarshal properly\n");
2140 HeapFree(GetProcessHeap(), 0, buffer);
2142 HWND_UserFree(&flags, &hwnd2);
2145 static void test_marshal_HGLOBAL(void)
2147 unsigned char *buffer;
2149 unsigned long flags = MAKELONG(MSHCTX_LOCAL, NDR_LOCAL_DATA_REPRESENTATION);
2152 unsigned char *wirehglobal;
2156 flags = MAKELONG(MSHCTX_LOCAL, NDR_LOCAL_DATA_REPRESENTATION);
2157 size = HGLOBAL_UserSize(&flags, 0, &hglobal);
2158 /* native is poorly programmed and allocates 4 bytes more than it needs to
2159 * here - Wine doesn't have to emulate that */
2160 ok((size == 8) || (size == 12), "Size should be 12, instead of %ld\n", size);
2161 buffer = HeapAlloc(GetProcessHeap(), 0, size);
2162 HGLOBAL_UserMarshal(&flags, buffer, &hglobal);
2163 wirehglobal = buffer;
2164 ok(*(ULONG *)wirehglobal == WDT_REMOTE_CALL, "Context should be WDT_REMOTE_CALL instead of 0x%08lx\n", *(ULONG *)wirehglobal);
2165 wirehglobal += sizeof(ULONG);
2166 ok(*(ULONG *)wirehglobal == (ULONG)hglobal, "buffer+4 should be HGLOBAL\n");
2167 HGLOBAL_UserUnmarshal(&flags, buffer, &hglobal2);
2168 ok(hglobal2 == hglobal, "Didn't unmarshal properly\n");
2169 HeapFree(GetProcessHeap(), 0, buffer);
2170 HGLOBAL_UserFree(&flags, &hglobal2);
2172 hglobal = GlobalAlloc(0, 4);
2173 buffer = GlobalLock(hglobal);
2174 for (i = 0; i < 4; i++)
2176 GlobalUnlock(hglobal);
2177 flags = MAKELONG(MSHCTX_LOCAL, NDR_LOCAL_DATA_REPRESENTATION);
2178 size = HGLOBAL_UserSize(&flags, 0, &hglobal);
2179 /* native is poorly programmed and allocates 4 bytes more than it needs to
2180 * here - Wine doesn't have to emulate that */
2181 ok((size == 24) || (size == 28), "Size should be 24 or 28, instead of %ld\n", size);
2182 buffer = HeapAlloc(GetProcessHeap(), 0, size);
2183 HGLOBAL_UserMarshal(&flags, buffer, &hglobal);
2184 wirehglobal = buffer;
2185 ok(*(ULONG *)wirehglobal == WDT_REMOTE_CALL, "Context should be WDT_REMOTE_CALL instead of 0x%08lx\n", *(ULONG *)wirehglobal);
2186 wirehglobal += sizeof(ULONG);
2187 ok(*(ULONG *)wirehglobal == (ULONG)hglobal, "buffer+0x4 should be HGLOBAL\n");
2188 wirehglobal += sizeof(ULONG);
2189 ok(*(ULONG *)wirehglobal == 4, "buffer+0x8 should be size of HGLOBAL\n");
2190 wirehglobal += sizeof(ULONG);
2191 ok(*(ULONG *)wirehglobal == (ULONG)hglobal, "buffer+0xc should be HGLOBAL\n");
2192 wirehglobal += sizeof(ULONG);
2193 ok(*(ULONG *)wirehglobal == 4, "buffer+0x10 should be size of HGLOBAL\n");
2194 wirehglobal += sizeof(ULONG);
2195 for (i = 0; i < 4; i++)
2196 ok(wirehglobal[i] == i, "buffer+0x%x should be %d\n", 0x10 + i, i);
2197 HGLOBAL_UserUnmarshal(&flags, buffer, &hglobal2);
2198 ok(hglobal2 != NULL, "Didn't unmarshal properly\n");
2199 HeapFree(GetProcessHeap(), 0, buffer);
2200 HGLOBAL_UserFree(&flags, &hglobal2);
2201 GlobalFree(hglobal);
2204 static HENHMETAFILE create_emf(void)
2206 RECT rect = {0, 0, 100, 100};
2207 HDC hdc = CreateEnhMetaFile(NULL, NULL, &rect, "HENHMETAFILE Marshaling Test\0Test\0\0");
2208 ExtTextOut(hdc, 0, 0, ETO_OPAQUE, NULL, "Test String", strlen("Test String"), NULL);
2209 return CloseEnhMetaFile(hdc);
2212 static void test_marshal_HENHMETAFILE(void)
2214 unsigned char *buffer;
2216 unsigned long flags = MAKELONG(MSHCTX_DIFFERENTMACHINE, NDR_LOCAL_DATA_REPRESENTATION);
2218 HENHMETAFILE hemf2 = NULL;
2219 unsigned char *wirehemf;
2221 hemf = create_emf();
2223 size = HENHMETAFILE_UserSize(&flags, 0, &hemf);
2224 ok(size > 20, "size should be at least 20 bytes, not %ld\n", size);
2225 buffer = HeapAlloc(GetProcessHeap(), 0, size);
2226 HENHMETAFILE_UserMarshal(&flags, buffer, &hemf);
2228 ok(*(DWORD *)wirehemf == WDT_REMOTE_CALL, "wirestgm + 0x0 should be WDT_REMOTE_CALL instead of 0x%08lx\n", *(DWORD *)wirehemf);
2229 wirehemf += sizeof(DWORD);
2230 ok(*(DWORD *)wirehemf == (DWORD)(DWORD_PTR)hemf, "wirestgm + 0x4 should be hemf instead of 0x%08lx\n", *(DWORD *)wirehemf);
2231 wirehemf += sizeof(DWORD);
2232 ok(*(DWORD *)wirehemf == (size - 0x10), "wirestgm + 0x8 should be size - 0x10 instead of 0x%08lx\n", *(DWORD *)wirehemf);
2233 wirehemf += sizeof(DWORD);
2234 ok(*(DWORD *)wirehemf == (size - 0x10), "wirestgm + 0xc should be size - 0x10 instead of 0x%08lx\n", *(DWORD *)wirehemf);
2235 wirehemf += sizeof(DWORD);
2236 ok(*(DWORD *)wirehemf == EMR_HEADER, "wirestgm + 0x10 should be EMR_HEADER instead of %ld\n", *(DWORD *)wirehemf);
2237 wirehemf += sizeof(DWORD);
2238 /* ... rest of data not tested - refer to tests for GetEnhMetaFileBits
2241 HENHMETAFILE_UserUnmarshal(&flags, buffer, &hemf2);
2242 ok(hemf2 != NULL, "HENHMETAFILE didn't unmarshal\n");
2243 HeapFree(GetProcessHeap(), 0, buffer);
2244 HENHMETAFILE_UserFree(&flags, &hemf2);
2245 DeleteEnhMetaFile(hemf);
2250 size = HENHMETAFILE_UserSize(&flags, 0, &hemf);
2251 ok(size == 8, "size should be 8 bytes, not %ld\n", size);
2252 buffer = (unsigned char *)HeapAlloc(GetProcessHeap(), 0, size);
2253 HENHMETAFILE_UserMarshal(&flags, buffer, &hemf);
2255 ok(*(DWORD *)wirehemf == WDT_REMOTE_CALL, "wirestgm + 0x0 should be WDT_REMOTE_CALL instead of 0x%08lx\n", *(DWORD *)wirehemf);
2256 wirehemf += sizeof(DWORD);
2257 ok(*(DWORD *)wirehemf == (DWORD)(DWORD_PTR)hemf, "wirestgm + 0x4 should be hemf instead of 0x%08lx\n", *(DWORD *)wirehemf);
2258 wirehemf += sizeof(DWORD);
2260 HENHMETAFILE_UserUnmarshal(&flags, buffer, &hemf2);
2261 ok(hemf2 == NULL, "NULL HENHMETAFILE didn't unmarshal\n");
2262 HeapFree(GetProcessHeap(), 0, buffer);
2263 HENHMETAFILE_UserFree(&flags, &hemf2);
2269 HMODULE hOle32 = GetModuleHandle("ole32");
2270 if (!(pCoInitializeEx = (void*)GetProcAddress(hOle32, "CoInitializeEx"))) goto no_test;
2272 /* register a window class used in several tests */
2273 memset(&wndclass, 0, sizeof(wndclass));
2274 wndclass.lpfnWndProc = window_proc;
2275 wndclass.lpszClassName = "WineCOMTest";
2276 RegisterClass(&wndclass);
2278 test_cocreateinstance_proxy();
2280 pCoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
2282 /* FIXME: test CoCreateInstanceEx */
2284 /* helper function tests */
2285 test_CoGetPSClsid();
2287 /* lifecycle management and marshaling tests */
2288 test_no_marshaler();
2289 test_normal_marshal_and_release();
2290 test_normal_marshal_and_unmarshal();
2291 test_marshal_and_unmarshal_invalid();
2292 test_interthread_marshal_and_unmarshal();
2293 test_proxy_marshal_and_unmarshal();
2294 test_proxy_marshal_and_unmarshal2();
2295 test_marshal_stub_apartment_shutdown();
2296 test_marshal_proxy_apartment_shutdown();
2297 test_marshal_proxy_mta_apartment_shutdown();
2298 test_no_couninitialize_server();
2299 test_no_couninitialize_client();
2300 test_tableweak_marshal_and_unmarshal_twice();
2301 test_tableweak_marshal_releasedata1();
2302 test_tableweak_marshal_releasedata2();
2303 test_tablestrong_marshal_and_unmarshal_twice();
2304 test_lock_object_external();
2305 test_disconnect_stub();
2306 test_normal_marshal_and_unmarshal_twice();
2307 test_hresult_marshaling();
2308 test_proxy_used_in_wrong_thread();
2309 test_message_filter();
2310 test_bad_marshal_stream();
2311 test_proxy_interfaces();
2312 test_stubbuffer(&IID_IClassFactory);
2313 test_proxybuffer(&IID_IClassFactory);
2314 test_message_reentrancy();
2315 test_WM_QUIT_handling();
2316 test_freethreadedmarshaler();
2318 /* doesn't pass with Win9x COM DLLs (even though Essential COM says it should) */
2319 if (0) test_out_of_process_com();
2322 test_globalinterfacetable();
2324 test_marshal_CLIPFORMAT();
2325 test_marshal_HWND();
2326 test_marshal_HGLOBAL();
2327 test_marshal_HENHMETAFILE();
2333 trace("You need DCOM95 installed to run this test\n");