ole: Fix marshaling of proxies for interfaces that haven't already been unmarshaled.
[wine/testsucceed.git] / dlls / ole32 / tests / marshal.c
blob3de88a937ec30d5e437bc50a179fb582f607e6d2
1 /*
2 * Marshaling Tests
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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
21 #define _WIN32_DCOM
22 #define COBJMACROS
24 #include <stdarg.h>
26 #include "windef.h"
27 #include "winbase.h"
28 #include "objbase.h"
30 #include "wine/test.h"
32 /* functions that are not present on all versions of Windows */
33 HRESULT (WINAPI * pCoInitializeEx)(LPVOID lpReserved, DWORD dwCoInit);
35 /* helper macros to make tests a bit leaner */
36 #define ok_more_than_one_lock() ok(cLocks > 0, "Number of locks should be > 0, but actually is %ld\n", cLocks)
37 #define ok_no_locks() ok(cLocks == 0, "Number of locks should be 0, but actually is %ld\n", cLocks)
38 #define ok_ole_success(hr, func) ok(hr == S_OK, #func " failed with error 0x%08lx\n", hr)
40 static const IID IID_IWineTest =
42 0x5201163f,
43 0x8164,
44 0x4fd0,
45 {0xa1, 0xa2, 0x5d, 0x5a, 0x36, 0x54, 0xd3, 0xbd}
46 }; /* 5201163f-8164-4fd0-a1a2-5d5a3654d3bd */
48 static void test_CoGetPSClsid(void)
50 HRESULT hr;
51 CLSID clsid;
53 hr = CoGetPSClsid(&IID_IClassFactory, &clsid);
54 ok_ole_success(hr, CoGetPSClsid);
56 hr = CoGetPSClsid(&IID_IWineTest, &clsid);
57 ok(hr == REGDB_E_IIDNOTREG,
58 "CoGetPSClsid for random IID returned 0x%08lx instead of REGDB_E_IIDNOTREG\n",
59 hr);
62 static const LARGE_INTEGER ullZero;
63 static LONG cLocks;
65 static void LockModule(void)
67 InterlockedIncrement(&cLocks);
70 static void UnlockModule(void)
72 InterlockedDecrement(&cLocks);
76 static HRESULT WINAPI Test_IUnknown_QueryInterface(
77 LPUNKNOWN iface,
78 REFIID riid,
79 LPVOID *ppvObj)
81 if (ppvObj == NULL) return E_POINTER;
83 if (IsEqualGUID(riid, &IID_IUnknown))
85 *ppvObj = (LPVOID)iface;
86 IUnknown_AddRef(iface);
87 return S_OK;
90 *ppvObj = NULL;
91 return E_NOINTERFACE;
94 static ULONG WINAPI Test_IUnknown_AddRef(LPUNKNOWN iface)
96 LockModule();
97 return 2; /* non-heap-based object */
100 static ULONG WINAPI Test_IUnknown_Release(LPUNKNOWN iface)
102 UnlockModule();
103 return 1; /* non-heap-based object */
106 static const IUnknownVtbl TestUnknown_Vtbl =
108 Test_IUnknown_QueryInterface,
109 Test_IUnknown_AddRef,
110 Test_IUnknown_Release,
113 static IUnknown Test_Unknown = { &TestUnknown_Vtbl };
116 static HRESULT WINAPI Test_IClassFactory_QueryInterface(
117 LPCLASSFACTORY iface,
118 REFIID riid,
119 LPVOID *ppvObj)
121 if (ppvObj == NULL) return E_POINTER;
123 if (IsEqualGUID(riid, &IID_IUnknown) ||
124 IsEqualGUID(riid, &IID_IClassFactory))
126 *ppvObj = (LPVOID)iface;
127 IClassFactory_AddRef(iface);
128 return S_OK;
131 *ppvObj = NULL;
132 return E_NOINTERFACE;
135 static ULONG WINAPI Test_IClassFactory_AddRef(LPCLASSFACTORY iface)
137 LockModule();
138 return 2; /* non-heap-based object */
141 static ULONG WINAPI Test_IClassFactory_Release(LPCLASSFACTORY iface)
143 UnlockModule();
144 return 1; /* non-heap-based object */
147 static HRESULT WINAPI Test_IClassFactory_CreateInstance(
148 LPCLASSFACTORY iface,
149 LPUNKNOWN pUnkOuter,
150 REFIID riid,
151 LPVOID *ppvObj)
153 if (pUnkOuter) return CLASS_E_NOAGGREGATION;
154 return IUnknown_QueryInterface((IUnknown*)&Test_Unknown, riid, ppvObj);
157 static HRESULT WINAPI Test_IClassFactory_LockServer(
158 LPCLASSFACTORY iface,
159 BOOL fLock)
161 return S_OK;
164 static const IClassFactoryVtbl TestClassFactory_Vtbl =
166 Test_IClassFactory_QueryInterface,
167 Test_IClassFactory_AddRef,
168 Test_IClassFactory_Release,
169 Test_IClassFactory_CreateInstance,
170 Test_IClassFactory_LockServer
173 static IClassFactory Test_ClassFactory = { &TestClassFactory_Vtbl };
175 #define RELEASEMARSHALDATA WM_USER
177 struct host_object_data
179 IStream *stream;
180 IID iid;
181 IUnknown *object;
182 MSHLFLAGS marshal_flags;
183 HANDLE marshal_event;
184 IMessageFilter *filter;
187 static DWORD CALLBACK host_object_proc(LPVOID p)
189 struct host_object_data *data = (struct host_object_data *)p;
190 HRESULT hr;
191 MSG msg;
193 pCoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
195 if (data->filter)
197 IMessageFilter * prev_filter = NULL;
198 hr = CoRegisterMessageFilter(data->filter, &prev_filter);
199 if (prev_filter) IMessageFilter_Release(prev_filter);
200 ok_ole_success(hr, CoRegisterMessageFilter);
203 hr = CoMarshalInterface(data->stream, &data->iid, data->object, MSHCTX_INPROC, NULL, data->marshal_flags);
204 ok_ole_success(hr, CoMarshalInterface);
206 /* force the message queue to be created before signaling parent thread */
207 PeekMessage(&msg, NULL, WM_USER, WM_USER, PM_NOREMOVE);
209 SetEvent(data->marshal_event);
211 while (GetMessage(&msg, NULL, 0, 0))
213 if (msg.hwnd == NULL && msg.message == RELEASEMARSHALDATA)
215 trace("releasing marshal data\n");
216 CoReleaseMarshalData(data->stream);
217 SetEvent((HANDLE)msg.lParam);
219 else
220 DispatchMessage(&msg);
223 HeapFree(GetProcessHeap(), 0, data);
225 CoUninitialize();
227 return hr;
230 static DWORD start_host_object2(IStream *stream, REFIID riid, IUnknown *object, MSHLFLAGS marshal_flags, IMessageFilter *filter, HANDLE *thread)
232 DWORD tid = 0;
233 HANDLE marshal_event = CreateEvent(NULL, FALSE, FALSE, NULL);
234 struct host_object_data *data = HeapAlloc(GetProcessHeap(), 0, sizeof(*data));
236 data->stream = stream;
237 data->iid = *riid;
238 data->object = object;
239 data->marshal_flags = marshal_flags;
240 data->marshal_event = marshal_event;
241 data->filter = filter;
243 *thread = CreateThread(NULL, 0, host_object_proc, data, 0, &tid);
245 /* wait for marshaling to complete before returning */
246 WaitForSingleObject(marshal_event, INFINITE);
247 CloseHandle(marshal_event);
249 return tid;
252 static DWORD start_host_object(IStream *stream, REFIID riid, IUnknown *object, MSHLFLAGS marshal_flags, HANDLE *thread)
254 return start_host_object2(stream, riid, object, marshal_flags, NULL, thread);
257 /* asks thread to release the marshal data because it has to be done by the
258 * same thread that marshaled the interface in the first place. */
259 static void release_host_object(DWORD tid)
261 HANDLE event = CreateEvent(NULL, FALSE, FALSE, NULL);
262 PostThreadMessage(tid, RELEASEMARSHALDATA, 0, (LPARAM)event);
263 WaitForSingleObject(event, INFINITE);
264 CloseHandle(event);
267 static void end_host_object(DWORD tid, HANDLE thread)
269 BOOL ret = PostThreadMessage(tid, WM_QUIT, 0, 0);
270 ok(ret, "PostThreadMessage failed with error %ld\n", GetLastError());
271 /* be careful of races - don't return until hosting thread has terminated */
272 WaitForSingleObject(thread, INFINITE);
273 CloseHandle(thread);
276 /* tests failure case of interface not having a marshaler specified in the
277 * registry */
278 static void test_no_marshaler(void)
280 IStream *pStream;
281 HRESULT hr;
283 hr = CreateStreamOnHGlobal(NULL, TRUE, &pStream);
284 ok_ole_success(hr, CreateStreamOnHGlobal);
285 hr = CoMarshalInterface(pStream, &IID_IWineTest, (IUnknown*)&Test_ClassFactory, MSHCTX_INPROC, NULL, MSHLFLAGS_NORMAL);
286 ok(hr == E_NOINTERFACE, "CoMarshalInterface should have returned E_NOINTERFACE instead of 0x%08lx\n", hr);
288 IStream_Release(pStream);
291 /* tests normal marshal and then release without unmarshaling */
292 static void test_normal_marshal_and_release(void)
294 HRESULT hr;
295 IStream *pStream = NULL;
297 cLocks = 0;
299 hr = CreateStreamOnHGlobal(NULL, TRUE, &pStream);
300 ok_ole_success(hr, CreateStreamOnHGlobal);
301 hr = CoMarshalInterface(pStream, &IID_IClassFactory, (IUnknown*)&Test_ClassFactory, MSHCTX_INPROC, NULL, MSHLFLAGS_NORMAL);
302 ok_ole_success(hr, CoMarshalInterface);
304 ok_more_than_one_lock();
306 IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
307 hr = CoReleaseMarshalData(pStream);
308 ok_ole_success(hr, CoReleaseMarshalData);
309 IStream_Release(pStream);
311 ok_no_locks();
314 /* tests success case of a same-thread marshal and unmarshal */
315 static void test_normal_marshal_and_unmarshal(void)
317 HRESULT hr;
318 IStream *pStream = NULL;
319 IUnknown *pProxy = NULL;
321 cLocks = 0;
323 hr = CreateStreamOnHGlobal(NULL, TRUE, &pStream);
324 ok_ole_success(hr, CreateStreamOnHGlobal);
325 hr = CoMarshalInterface(pStream, &IID_IClassFactory, (IUnknown*)&Test_ClassFactory, MSHCTX_INPROC, NULL, MSHLFLAGS_NORMAL);
326 ok_ole_success(hr, CoMarshalInterface);
328 ok_more_than_one_lock();
330 IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
331 hr = CoUnmarshalInterface(pStream, &IID_IClassFactory, (void **)&pProxy);
332 ok_ole_success(hr, CoUnmarshalInterface);
333 IStream_Release(pStream);
335 ok_more_than_one_lock();
337 IUnknown_Release(pProxy);
339 ok_no_locks();
342 /* tests failure case of unmarshaling a freed object */
343 static void test_marshal_and_unmarshal_invalid(void)
345 HRESULT hr;
346 IStream *pStream = NULL;
347 IClassFactory *pProxy = NULL;
348 DWORD tid;
349 void * dummy;
350 HANDLE thread;
352 cLocks = 0;
354 hr = CreateStreamOnHGlobal(NULL, TRUE, &pStream);
355 ok_ole_success(hr, CreateStreamOnHGlobal);
356 tid = start_host_object(pStream, &IID_IClassFactory, (IUnknown*)&Test_ClassFactory, MSHLFLAGS_NORMAL, &thread);
358 ok_more_than_one_lock();
360 IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
361 hr = CoReleaseMarshalData(pStream);
362 ok_ole_success(hr, CoReleaseMarshalData);
364 ok_no_locks();
366 IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
367 hr = CoUnmarshalInterface(pStream, &IID_IClassFactory, (void **)&pProxy);
368 todo_wine { ok_ole_success(hr, CoUnmarshalInterface); }
370 ok_no_locks();
372 if (pProxy)
374 hr = IClassFactory_CreateInstance(pProxy, NULL, &IID_IUnknown, &dummy);
375 ok(hr == RPC_E_DISCONNECTED, "Remote call should have returned RPC_E_DISCONNECTED, instead of 0x%08lx\n", hr);
377 IClassFactory_Release(pProxy);
380 IStream_Release(pStream);
382 end_host_object(tid, thread);
385 /* tests success case of an interthread marshal */
386 static void test_interthread_marshal_and_unmarshal(void)
388 HRESULT hr;
389 IStream *pStream = NULL;
390 IUnknown *pProxy = NULL;
391 DWORD tid;
392 HANDLE thread;
394 cLocks = 0;
396 hr = CreateStreamOnHGlobal(NULL, TRUE, &pStream);
397 ok_ole_success(hr, CreateStreamOnHGlobal);
398 tid = start_host_object(pStream, &IID_IClassFactory, (IUnknown*)&Test_ClassFactory, MSHLFLAGS_NORMAL, &thread);
400 ok_more_than_one_lock();
402 IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
403 hr = CoUnmarshalInterface(pStream, &IID_IClassFactory, (void **)&pProxy);
404 ok_ole_success(hr, CoUnmarshalInterface);
405 IStream_Release(pStream);
407 ok_more_than_one_lock();
409 IUnknown_Release(pProxy);
411 ok_no_locks();
413 end_host_object(tid, thread);
416 /* tests success case of an interthread marshal and then marshaling the proxy */
417 static void test_proxy_marshal_and_unmarshal(void)
419 HRESULT hr;
420 IStream *pStream = NULL;
421 IUnknown *pProxy = NULL;
422 IUnknown *pProxy2 = NULL;
423 DWORD tid;
424 HANDLE thread;
426 cLocks = 0;
428 hr = CreateStreamOnHGlobal(NULL, TRUE, &pStream);
429 ok_ole_success(hr, CreateStreamOnHGlobal);
430 tid = start_host_object(pStream, &IID_IClassFactory, (IUnknown*)&Test_ClassFactory, MSHLFLAGS_NORMAL, &thread);
432 ok_more_than_one_lock();
434 IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
435 hr = CoUnmarshalInterface(pStream, &IID_IClassFactory, (void **)&pProxy);
436 ok_ole_success(hr, CoUnmarshalInterface);
438 ok_more_than_one_lock();
440 IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
441 /* marshal the proxy */
442 hr = CoMarshalInterface(pStream, &IID_IClassFactory, pProxy, MSHCTX_INPROC, NULL, MSHLFLAGS_NORMAL);
443 ok_ole_success(hr, CoMarshalInterface);
445 ok_more_than_one_lock();
447 IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
448 /* unmarshal the second proxy to the object */
449 hr = CoUnmarshalInterface(pStream, &IID_IClassFactory, (void **)&pProxy2);
450 ok_ole_success(hr, CoUnmarshalInterface);
451 IStream_Release(pStream);
453 /* now the proxies should be as follows:
454 * pProxy -> &Test_ClassFactory
455 * pProxy2 -> &Test_ClassFactory
456 * they should NOT be as follows:
457 * pProxy -> &Test_ClassFactory
458 * pProxy2 -> pProxy
459 * the above can only really be tested by looking in +ole traces
462 ok_more_than_one_lock();
464 IUnknown_Release(pProxy);
466 ok_more_than_one_lock();
468 IUnknown_Release(pProxy2);
470 ok_no_locks();
472 end_host_object(tid, thread);
475 /* tests success case of an interthread marshal and then marshaling the proxy
476 * using an iid that hasn't previously been unmarshaled */
477 static void test_proxy_marshal_and_unmarshal2(void)
479 HRESULT hr;
480 IStream *pStream = NULL;
481 IUnknown *pProxy = NULL;
482 IUnknown *pProxy2 = NULL;
483 DWORD tid;
484 HANDLE thread;
486 cLocks = 0;
488 hr = CreateStreamOnHGlobal(NULL, TRUE, &pStream);
489 ok_ole_success(hr, CreateStreamOnHGlobal);
490 tid = start_host_object(pStream, &IID_IUnknown, (IUnknown*)&Test_ClassFactory, MSHLFLAGS_NORMAL, &thread);
492 ok_more_than_one_lock();
494 IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
495 hr = CoUnmarshalInterface(pStream, &IID_IUnknown, (void **)&pProxy);
496 ok_ole_success(hr, CoUnmarshalInterface);
498 ok_more_than_one_lock();
500 IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
501 /* marshal the proxy */
502 hr = CoMarshalInterface(pStream, &IID_IClassFactory, pProxy, MSHCTX_INPROC, NULL, MSHLFLAGS_NORMAL);
503 ok_ole_success(hr, CoMarshalInterface);
505 ok_more_than_one_lock();
507 IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
508 /* unmarshal the second proxy to the object */
509 hr = CoUnmarshalInterface(pStream, &IID_IClassFactory, (void **)&pProxy2);
510 ok_ole_success(hr, CoUnmarshalInterface);
511 IStream_Release(pStream);
513 /* now the proxies should be as follows:
514 * pProxy -> &Test_ClassFactory
515 * pProxy2 -> &Test_ClassFactory
516 * they should NOT be as follows:
517 * pProxy -> &Test_ClassFactory
518 * pProxy2 -> pProxy
519 * the above can only really be tested by looking in +ole traces
522 ok_more_than_one_lock();
524 IUnknown_Release(pProxy);
526 ok_more_than_one_lock();
528 IUnknown_Release(pProxy2);
530 ok_no_locks();
532 end_host_object(tid, thread);
535 /* tests that stubs are released when the containing apartment is destroyed */
536 static void test_marshal_stub_apartment_shutdown(void)
538 HRESULT hr;
539 IStream *pStream = NULL;
540 IUnknown *pProxy = NULL;
541 DWORD tid;
542 HANDLE thread;
544 cLocks = 0;
546 hr = CreateStreamOnHGlobal(NULL, TRUE, &pStream);
547 ok_ole_success(hr, CreateStreamOnHGlobal);
548 tid = start_host_object(pStream, &IID_IClassFactory, (IUnknown*)&Test_ClassFactory, MSHLFLAGS_NORMAL, &thread);
550 ok_more_than_one_lock();
552 IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
553 hr = CoUnmarshalInterface(pStream, &IID_IClassFactory, (void **)&pProxy);
554 ok_ole_success(hr, CoUnmarshalInterface);
555 IStream_Release(pStream);
557 ok_more_than_one_lock();
559 end_host_object(tid, thread);
561 ok_no_locks();
563 IUnknown_Release(pProxy);
565 ok_no_locks();
568 /* tests that proxies are released when the containing apartment is destroyed */
569 static void test_marshal_proxy_apartment_shutdown(void)
571 HRESULT hr;
572 IStream *pStream = NULL;
573 IUnknown *pProxy = NULL;
574 DWORD tid;
575 HANDLE thread;
577 cLocks = 0;
579 hr = CreateStreamOnHGlobal(NULL, TRUE, &pStream);
580 ok_ole_success(hr, CreateStreamOnHGlobal);
581 tid = start_host_object(pStream, &IID_IClassFactory, (IUnknown*)&Test_ClassFactory, MSHLFLAGS_NORMAL, &thread);
583 ok_more_than_one_lock();
585 IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
586 hr = CoUnmarshalInterface(pStream, &IID_IClassFactory, (void **)&pProxy);
587 ok_ole_success(hr, CoUnmarshalInterface);
588 IStream_Release(pStream);
590 ok_more_than_one_lock();
592 CoUninitialize();
594 ok_no_locks();
596 IUnknown_Release(pProxy);
598 ok_no_locks();
600 end_host_object(tid, thread);
602 pCoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
605 /* tests that proxies are released when the containing mta apartment is destroyed */
606 static void test_marshal_proxy_mta_apartment_shutdown(void)
608 HRESULT hr;
609 IStream *pStream = NULL;
610 IUnknown *pProxy = NULL;
611 DWORD tid;
612 HANDLE thread;
614 CoUninitialize();
615 pCoInitializeEx(NULL, COINIT_MULTITHREADED);
617 cLocks = 0;
619 hr = CreateStreamOnHGlobal(NULL, TRUE, &pStream);
620 ok_ole_success(hr, CreateStreamOnHGlobal);
621 tid = start_host_object(pStream, &IID_IClassFactory, (IUnknown*)&Test_ClassFactory, MSHLFLAGS_NORMAL, &thread);
623 ok_more_than_one_lock();
625 IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
626 hr = CoUnmarshalInterface(pStream, &IID_IClassFactory, (void **)&pProxy);
627 ok_ole_success(hr, CoUnmarshalInterface);
628 IStream_Release(pStream);
630 ok_more_than_one_lock();
632 CoUninitialize();
634 ok_no_locks();
636 IUnknown_Release(pProxy);
638 ok_no_locks();
640 end_host_object(tid, thread);
642 pCoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
645 struct ncu_params
647 LPSTREAM stream;
648 HANDLE marshal_event;
649 HANDLE unmarshal_event;
652 /* helper for test_no_couninitialize_server */
653 static DWORD CALLBACK no_couninitialize_server_proc(LPVOID p)
655 struct ncu_params *ncu_params = (struct ncu_params *)p;
656 HRESULT hr;
658 pCoInitializeEx(NULL, COINIT_MULTITHREADED);
660 hr = CoMarshalInterface(ncu_params->stream, &IID_IClassFactory, (IUnknown*)&Test_ClassFactory, MSHCTX_INPROC, NULL, MSHLFLAGS_NORMAL);
661 ok_ole_success(hr, CoMarshalInterface);
663 SetEvent(ncu_params->marshal_event);
665 WaitForSingleObject(ncu_params->unmarshal_event, INFINITE);
667 /* die without calling CoUninitialize */
669 return 0;
672 /* tests apartment that an apartment with a stub is released without deadlock
673 * if the owning thread exits */
674 static void test_no_couninitialize_server(void)
676 HRESULT hr;
677 IStream *pStream = NULL;
678 IUnknown *pProxy = NULL;
679 DWORD tid;
680 HANDLE thread;
681 struct ncu_params ncu_params;
683 cLocks = 0;
685 ncu_params.marshal_event = CreateEvent(NULL, TRUE, FALSE, NULL);
686 ncu_params.unmarshal_event = CreateEvent(NULL, TRUE, FALSE, NULL);
688 hr = CreateStreamOnHGlobal(NULL, TRUE, &pStream);
689 ok_ole_success(hr, CreateStreamOnHGlobal);
690 ncu_params.stream = pStream;
692 thread = CreateThread(NULL, 0, no_couninitialize_server_proc, &ncu_params, 0, &tid);
694 WaitForSingleObject(ncu_params.marshal_event, INFINITE);
695 ok_more_than_one_lock();
697 IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
698 hr = CoUnmarshalInterface(pStream, &IID_IClassFactory, (void **)&pProxy);
699 ok_ole_success(hr, CoUnmarshalInterface);
700 IStream_Release(pStream);
702 ok_more_than_one_lock();
704 SetEvent(ncu_params.unmarshal_event);
705 WaitForSingleObject(thread, INFINITE);
707 ok_no_locks();
709 CloseHandle(thread);
710 CloseHandle(ncu_params.marshal_event);
711 CloseHandle(ncu_params.unmarshal_event);
713 IUnknown_Release(pProxy);
715 ok_no_locks();
718 /* STA -> STA call during DLL_THREAD_DETACH */
719 static DWORD CALLBACK no_couninitialize_client_proc(LPVOID p)
721 struct ncu_params *ncu_params = (struct ncu_params *)p;
722 HRESULT hr;
723 IUnknown *pProxy = NULL;
725 pCoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
727 hr = CoUnmarshalInterface(ncu_params->stream, &IID_IClassFactory, (void **)&pProxy);
728 ok_ole_success(hr, CoUnmarshalInterface);
730 ok_more_than_one_lock();
732 /* die without calling CoUninitialize */
734 return 0;
737 /* tests STA -> STA call during DLL_THREAD_DETACH doesn't deadlock */
738 static void test_no_couninitialize_client(void)
740 HRESULT hr;
741 IStream *pStream = NULL;
742 DWORD tid;
743 DWORD host_tid;
744 HANDLE thread;
745 HANDLE host_thread;
746 struct ncu_params ncu_params;
748 cLocks = 0;
750 hr = CreateStreamOnHGlobal(NULL, TRUE, &pStream);
751 ok_ole_success(hr, CreateStreamOnHGlobal);
752 ncu_params.stream = pStream;
754 /* NOTE: assumes start_host_object uses an STA to host the object, as MTAs
755 * always deadlock when called from within DllMain */
756 host_tid = start_host_object(pStream, &IID_IClassFactory, (IUnknown *)&Test_ClassFactory, MSHLFLAGS_NORMAL, &host_thread);
757 IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
759 ok_more_than_one_lock();
761 thread = CreateThread(NULL, 0, no_couninitialize_client_proc, &ncu_params, 0, &tid);
763 WaitForSingleObject(thread, INFINITE);
764 CloseHandle(thread);
766 ok_no_locks();
768 end_host_object(host_tid, host_thread);
771 /* tests success case of a same-thread table-weak marshal, unmarshal, unmarshal */
772 static void test_tableweak_marshal_and_unmarshal_twice(void)
774 HRESULT hr;
775 IStream *pStream = NULL;
776 IUnknown *pProxy1 = NULL;
777 IUnknown *pProxy2 = NULL;
778 DWORD tid;
779 HANDLE thread;
781 cLocks = 0;
783 hr = CreateStreamOnHGlobal(NULL, TRUE, &pStream);
784 ok_ole_success(hr, CreateStreamOnHGlobal);
785 tid = start_host_object(pStream, &IID_IClassFactory, (IUnknown*)&Test_ClassFactory, MSHLFLAGS_TABLEWEAK, &thread);
787 ok_more_than_one_lock();
789 IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
790 hr = CoUnmarshalInterface(pStream, &IID_IClassFactory, (void **)&pProxy1);
791 ok_ole_success(hr, CoUnmarshalInterface);
793 ok_more_than_one_lock();
795 IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
796 hr = CoUnmarshalInterface(pStream, &IID_IClassFactory, (void **)&pProxy2);
797 ok_ole_success(hr, CoUnmarshalInterface);
799 ok_more_than_one_lock();
801 IUnknown_Release(pProxy1);
802 IUnknown_Release(pProxy2);
804 /* this line is shows the difference between weak and strong table marshaling:
805 * weak has cLocks == 0
806 * strong has cLocks > 0 */
807 ok_no_locks();
809 end_host_object(tid, thread);
812 /* tests releasing after unmarshaling one object */
813 static void test_tableweak_marshal_releasedata1(void)
815 HRESULT hr;
816 IStream *pStream = NULL;
817 IUnknown *pProxy1 = NULL;
818 IUnknown *pProxy2 = NULL;
819 DWORD tid;
820 HANDLE thread;
822 cLocks = 0;
824 hr = CreateStreamOnHGlobal(NULL, TRUE, &pStream);
825 ok_ole_success(hr, CreateStreamOnHGlobal);
826 tid = start_host_object(pStream, &IID_IClassFactory, (IUnknown*)&Test_ClassFactory, MSHLFLAGS_TABLEWEAK, &thread);
828 ok_more_than_one_lock();
830 IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
831 hr = CoUnmarshalInterface(pStream, &IID_IClassFactory, (void **)&pProxy1);
832 ok_ole_success(hr, CoUnmarshalInterface);
834 ok_more_than_one_lock();
836 /* release the remaining reference on the object by calling
837 * CoReleaseMarshalData in the hosting thread */
838 IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
839 release_host_object(tid);
841 ok_more_than_one_lock();
843 IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
844 hr = CoUnmarshalInterface(pStream, &IID_IClassFactory, (void **)&pProxy2);
845 ok_ole_success(hr, CoUnmarshalInterface);
846 IStream_Release(pStream);
848 ok_more_than_one_lock();
850 IUnknown_Release(pProxy1);
851 if (pProxy2)
852 IUnknown_Release(pProxy2);
854 /* this line is shows the difference between weak and strong table marshaling:
855 * weak has cLocks == 0
856 * strong has cLocks > 0 */
857 ok_no_locks();
859 end_host_object(tid, thread);
862 /* tests releasing after unmarshaling one object */
863 static void test_tableweak_marshal_releasedata2(void)
865 HRESULT hr;
866 IStream *pStream = NULL;
867 IUnknown *pProxy = NULL;
868 DWORD tid;
869 HANDLE thread;
871 cLocks = 0;
873 hr = CreateStreamOnHGlobal(NULL, TRUE, &pStream);
874 ok_ole_success(hr, CreateStreamOnHGlobal);
875 tid = start_host_object(pStream, &IID_IClassFactory, (IUnknown*)&Test_ClassFactory, MSHLFLAGS_TABLEWEAK, &thread);
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_no_locks();
886 IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
887 hr = CoUnmarshalInterface(pStream, &IID_IClassFactory, (void **)&pProxy);
888 todo_wine
890 ok(hr == CO_E_OBJNOTREG,
891 "CoUnmarshalInterface should have failed with CO_E_OBJNOTREG, but returned 0x%08lx instead\n",
892 hr);
894 IStream_Release(pStream);
896 ok_no_locks();
898 end_host_object(tid, thread);
901 /* tests success case of a same-thread table-strong marshal, unmarshal, unmarshal */
902 static void test_tablestrong_marshal_and_unmarshal_twice(void)
904 HRESULT hr;
905 IStream *pStream = NULL;
906 IUnknown *pProxy1 = NULL;
907 IUnknown *pProxy2 = NULL;
908 DWORD tid;
909 HANDLE thread;
911 cLocks = 0;
913 hr = CreateStreamOnHGlobal(NULL, TRUE, &pStream);
914 ok_ole_success(hr, CreateStreamOnHGlobal);
915 tid = start_host_object(pStream, &IID_IClassFactory, (IUnknown*)&Test_ClassFactory, MSHLFLAGS_TABLESTRONG, &thread);
917 ok_more_than_one_lock();
919 IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
920 hr = CoUnmarshalInterface(pStream, &IID_IClassFactory, (void **)&pProxy1);
921 ok_ole_success(hr, CoUnmarshalInterface);
923 ok_more_than_one_lock();
925 IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
926 hr = CoUnmarshalInterface(pStream, &IID_IClassFactory, (void **)&pProxy2);
927 ok_ole_success(hr, CoUnmarshalInterface);
929 ok_more_than_one_lock();
931 if (pProxy1) IUnknown_Release(pProxy1);
932 if (pProxy2) IUnknown_Release(pProxy2);
934 /* this line is shows the difference between weak and strong table marshaling:
935 * weak has cLocks == 0
936 * strong has cLocks > 0 */
937 ok_more_than_one_lock();
939 /* release the remaining reference on the object by calling
940 * CoReleaseMarshalData in the hosting thread */
941 IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
942 release_host_object(tid);
943 IStream_Release(pStream);
945 ok_no_locks();
947 end_host_object(tid, thread);
950 /* tests CoLockObjectExternal */
951 static void test_lock_object_external(void)
953 HRESULT hr;
954 IStream *pStream = NULL;
956 cLocks = 0;
958 hr = CreateStreamOnHGlobal(NULL, TRUE, &pStream);
959 ok_ole_success(hr, CreateStreamOnHGlobal);
960 hr = CoMarshalInterface(pStream, &IID_IClassFactory, (IUnknown*)&Test_ClassFactory, MSHCTX_INPROC, NULL, MSHLFLAGS_NORMAL);
961 ok_ole_success(hr, CoMarshalInterface);
963 CoLockObjectExternal((IUnknown*)&Test_ClassFactory, TRUE, TRUE);
965 ok_more_than_one_lock();
967 IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
968 hr = CoReleaseMarshalData(pStream);
969 ok_ole_success(hr, CoReleaseMarshalData);
970 IStream_Release(pStream);
972 ok_more_than_one_lock();
974 CoLockObjectExternal((IUnknown*)&Test_ClassFactory, FALSE, TRUE);
976 ok_no_locks();
979 /* tests disconnecting stubs */
980 static void test_disconnect_stub(void)
982 HRESULT hr;
983 IStream *pStream = NULL;
985 cLocks = 0;
987 hr = CreateStreamOnHGlobal(NULL, TRUE, &pStream);
988 ok_ole_success(hr, CreateStreamOnHGlobal);
989 hr = CoMarshalInterface(pStream, &IID_IClassFactory, (IUnknown*)&Test_ClassFactory, MSHCTX_INPROC, NULL, MSHLFLAGS_NORMAL);
990 ok_ole_success(hr, CoMarshalInterface);
992 CoLockObjectExternal((IUnknown*)&Test_ClassFactory, TRUE, TRUE);
994 ok_more_than_one_lock();
996 IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
997 hr = CoReleaseMarshalData(pStream);
998 ok_ole_success(hr, CoReleaseMarshalData);
999 IStream_Release(pStream);
1001 ok_more_than_one_lock();
1003 CoDisconnectObject((IUnknown*)&Test_ClassFactory, 0);
1005 ok_no_locks();
1008 /* tests failure case of a same-thread marshal and unmarshal twice */
1009 static void test_normal_marshal_and_unmarshal_twice(void)
1011 HRESULT hr;
1012 IStream *pStream = NULL;
1013 IUnknown *pProxy1 = NULL;
1014 IUnknown *pProxy2 = NULL;
1016 cLocks = 0;
1018 hr = CreateStreamOnHGlobal(NULL, TRUE, &pStream);
1019 ok_ole_success(hr, CreateStreamOnHGlobal);
1020 hr = CoMarshalInterface(pStream, &IID_IClassFactory, (IUnknown*)&Test_ClassFactory, MSHCTX_INPROC, NULL, MSHLFLAGS_NORMAL);
1021 ok_ole_success(hr, CoMarshalInterface);
1023 ok_more_than_one_lock();
1025 IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
1026 hr = CoUnmarshalInterface(pStream, &IID_IClassFactory, (void **)&pProxy1);
1027 ok_ole_success(hr, CoUnmarshalInterface);
1029 ok_more_than_one_lock();
1031 IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
1032 hr = CoUnmarshalInterface(pStream, &IID_IClassFactory, (void **)&pProxy2);
1033 ok(hr == CO_E_OBJNOTCONNECTED,
1034 "CoUnmarshalInterface should have failed with error CO_E_OBJNOTCONNECTED for double unmarshal, instead of 0x%08lx\n", hr);
1036 IStream_Release(pStream);
1038 ok_more_than_one_lock();
1040 IUnknown_Release(pProxy1);
1042 ok_no_locks();
1045 /* tests success case of marshaling and unmarshaling an HRESULT */
1046 static void test_hresult_marshaling(void)
1048 HRESULT hr;
1049 HRESULT hr_marshaled = 0;
1050 IStream *pStream = NULL;
1051 static const HRESULT E_DEADBEEF = 0xdeadbeef;
1053 hr = CreateStreamOnHGlobal(NULL, TRUE, &pStream);
1054 ok_ole_success(hr, CreateStreamOnHGlobal);
1056 hr = CoMarshalHresult(pStream, E_DEADBEEF);
1057 ok_ole_success(hr, CoMarshalHresult);
1059 IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
1060 hr = IStream_Read(pStream, &hr_marshaled, sizeof(HRESULT), NULL);
1061 ok_ole_success(hr, IStream_Read);
1063 ok(hr_marshaled == E_DEADBEEF, "Didn't marshal HRESULT as expected: got value 0x%08lx instead\n", hr_marshaled);
1065 hr_marshaled = 0;
1066 IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
1067 hr = CoUnmarshalHresult(pStream, &hr_marshaled);
1068 ok_ole_success(hr, CoUnmarshalHresult);
1070 ok(hr_marshaled == E_DEADBEEF, "Didn't marshal HRESULT as expected: got value 0x%08lx instead\n", hr_marshaled);
1072 IStream_Release(pStream);
1076 /* helper for test_proxy_used_in_wrong_thread */
1077 static DWORD CALLBACK bad_thread_proc(LPVOID p)
1079 IClassFactory * cf = (IClassFactory *)p;
1080 HRESULT hr;
1081 IUnknown * proxy = NULL;
1083 pCoInitializeEx(NULL, COINIT_MULTITHREADED);
1085 hr = IClassFactory_CreateInstance(cf, NULL, &IID_IUnknown, (LPVOID*)&proxy);
1086 if (proxy) IUnknown_Release(proxy);
1087 ok(hr == RPC_E_WRONG_THREAD,
1088 "COM should have failed with RPC_E_WRONG_THREAD on using proxy from wrong apartment, but instead returned 0x%08lx\n",
1089 hr);
1091 CoUninitialize();
1093 return 0;
1096 /* tests failure case of a using a proxy in the wrong apartment */
1097 static void test_proxy_used_in_wrong_thread(void)
1099 HRESULT hr;
1100 IStream *pStream = NULL;
1101 IUnknown *pProxy = NULL;
1102 DWORD tid, tid2;
1103 HANDLE thread;
1104 HANDLE host_thread;
1106 cLocks = 0;
1108 hr = CreateStreamOnHGlobal(NULL, TRUE, &pStream);
1109 ok_ole_success(hr, CreateStreamOnHGlobal);
1110 tid = start_host_object(pStream, &IID_IClassFactory, (IUnknown*)&Test_ClassFactory, MSHLFLAGS_NORMAL, &host_thread);
1112 ok_more_than_one_lock();
1114 IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
1115 hr = CoUnmarshalInterface(pStream, &IID_IClassFactory, (void **)&pProxy);
1116 ok_ole_success(hr, CoUnmarshalInterface);
1117 IStream_Release(pStream);
1119 ok_more_than_one_lock();
1121 /* create a thread that we can misbehave in */
1122 thread = CreateThread(NULL, 0, bad_thread_proc, (LPVOID)pProxy, 0, &tid2);
1124 WaitForSingleObject(thread, INFINITE);
1125 CloseHandle(thread);
1127 IUnknown_Release(pProxy);
1129 ok_no_locks();
1131 end_host_object(tid, host_thread);
1134 static HRESULT WINAPI MessageFilter_QueryInterface(IMessageFilter *iface, REFIID riid, void ** ppvObj)
1136 if (ppvObj == NULL) return E_POINTER;
1138 if (IsEqualGUID(riid, &IID_IUnknown) ||
1139 IsEqualGUID(riid, &IID_IClassFactory))
1141 *ppvObj = (LPVOID)iface;
1142 IClassFactory_AddRef(iface);
1143 return S_OK;
1146 return E_NOINTERFACE;
1149 static ULONG WINAPI MessageFilter_AddRef(IMessageFilter *iface)
1151 return 2; /* non-heap object */
1154 static ULONG WINAPI MessageFilter_Release(IMessageFilter *iface)
1156 return 1; /* non-heap object */
1159 static DWORD WINAPI MessageFilter_HandleInComingCall(
1160 IMessageFilter *iface,
1161 DWORD dwCallType,
1162 HTASK threadIDCaller,
1163 DWORD dwTickCount,
1164 LPINTERFACEINFO lpInterfaceInfo)
1166 static int callcount = 0;
1167 DWORD ret;
1168 trace("HandleInComingCall\n");
1169 switch (callcount)
1171 case 0:
1172 ret = SERVERCALL_REJECTED;
1173 break;
1174 case 1:
1175 ret = SERVERCALL_RETRYLATER;
1176 break;
1177 default:
1178 ret = SERVERCALL_ISHANDLED;
1179 break;
1181 callcount++;
1182 return ret;
1185 static DWORD WINAPI MessageFilter_RetryRejectedCall(
1186 IMessageFilter *iface,
1187 HTASK threadIDCallee,
1188 DWORD dwTickCount,
1189 DWORD dwRejectType)
1191 trace("RetryRejectedCall\n");
1192 return 0;
1195 static DWORD WINAPI MessageFilter_MessagePending(
1196 IMessageFilter *iface,
1197 HTASK threadIDCallee,
1198 DWORD dwTickCount,
1199 DWORD dwPendingType)
1201 trace("MessagePending\n");
1202 return PENDINGMSG_WAITNOPROCESS;
1205 static const IMessageFilterVtbl MessageFilter_Vtbl =
1207 MessageFilter_QueryInterface,
1208 MessageFilter_AddRef,
1209 MessageFilter_Release,
1210 MessageFilter_HandleInComingCall,
1211 MessageFilter_RetryRejectedCall,
1212 MessageFilter_MessagePending
1215 static IMessageFilter MessageFilter = { &MessageFilter_Vtbl };
1217 static void test_message_filter(void)
1219 HRESULT hr;
1220 IStream *pStream = NULL;
1221 IClassFactory *cf = NULL;
1222 DWORD tid;
1223 IUnknown *proxy = NULL;
1224 IMessageFilter *prev_filter = NULL;
1225 HANDLE thread;
1227 cLocks = 0;
1229 hr = CreateStreamOnHGlobal(NULL, TRUE, &pStream);
1230 ok_ole_success(hr, CreateStreamOnHGlobal);
1231 tid = start_host_object2(pStream, &IID_IClassFactory, (IUnknown*)&Test_ClassFactory, MSHLFLAGS_NORMAL, &MessageFilter, &thread);
1233 ok_more_than_one_lock();
1235 IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
1236 hr = CoUnmarshalInterface(pStream, &IID_IClassFactory, (void **)&cf);
1237 ok_ole_success(hr, CoUnmarshalInterface);
1238 IStream_Release(pStream);
1240 ok_more_than_one_lock();
1242 hr = IClassFactory_CreateInstance(cf, NULL, &IID_IUnknown, (LPVOID*)&proxy);
1243 todo_wine { ok(hr == RPC_E_CALL_REJECTED, "Call should have returned RPC_E_CALL_REJECTED, but return 0x%08lx instead\n", hr); }
1244 if (proxy) IUnknown_Release(proxy);
1245 proxy = NULL;
1247 hr = CoRegisterMessageFilter(&MessageFilter, &prev_filter);
1248 ok_ole_success(hr, CoRegisterMessageFilter);
1249 if (prev_filter) IMessageFilter_Release(prev_filter);
1251 hr = IClassFactory_CreateInstance(cf, NULL, &IID_IUnknown, (LPVOID*)&proxy);
1252 ok_ole_success(hr, IClassFactory_CreateInstance);
1254 IUnknown_Release(proxy);
1256 IClassFactory_Release(cf);
1258 ok_no_locks();
1260 end_host_object(tid, thread);
1263 /* test failure case of trying to unmarshal from bad stream */
1264 static void test_bad_marshal_stream(void)
1266 HRESULT hr;
1267 IStream *pStream = NULL;
1269 hr = CreateStreamOnHGlobal(NULL, TRUE, &pStream);
1270 ok_ole_success(hr, CreateStreamOnHGlobal);
1271 hr = CoMarshalInterface(pStream, &IID_IClassFactory, (IUnknown*)&Test_ClassFactory, MSHCTX_INPROC, NULL, MSHLFLAGS_NORMAL);
1272 ok_ole_success(hr, CoMarshalInterface);
1274 ok_more_than_one_lock();
1276 /* try to read beyond end of stream */
1277 hr = CoReleaseMarshalData(pStream);
1278 ok(hr == STG_E_READFAULT, "Should have failed with STG_E_READFAULT, but returned 0x%08lx instead\n", hr);
1280 /* now release for real */
1281 IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
1282 hr = CoReleaseMarshalData(pStream);
1283 ok_ole_success(hr, CoReleaseMarshalData);
1285 IStream_Release(pStream);
1288 /* tests that proxies implement certain interfaces */
1289 static void test_proxy_interfaces(void)
1291 HRESULT hr;
1292 IStream *pStream = NULL;
1293 IUnknown *pProxy = NULL;
1294 IUnknown *pOtherUnknown = NULL;
1295 DWORD tid;
1296 HANDLE thread;
1298 cLocks = 0;
1300 hr = CreateStreamOnHGlobal(NULL, TRUE, &pStream);
1301 ok_ole_success(hr, CreateStreamOnHGlobal);
1302 tid = start_host_object(pStream, &IID_IClassFactory, (IUnknown*)&Test_ClassFactory, MSHLFLAGS_NORMAL, &thread);
1304 ok_more_than_one_lock();
1306 IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
1307 hr = CoUnmarshalInterface(pStream, &IID_IUnknown, (void **)&pProxy);
1308 ok_ole_success(hr, CoUnmarshalInterface);
1309 IStream_Release(pStream);
1311 ok_more_than_one_lock();
1313 hr = IUnknown_QueryInterface(pProxy, &IID_IUnknown, (LPVOID*)&pOtherUnknown);
1314 ok_ole_success(hr, IUnknown_QueryInterface IID_IUnknown);
1315 if (hr == S_OK) IUnknown_Release(pOtherUnknown);
1317 hr = IUnknown_QueryInterface(pProxy, &IID_IClientSecurity, (LPVOID*)&pOtherUnknown);
1318 todo_wine { ok_ole_success(hr, IUnknown_QueryInterface IID_IClientSecurity); }
1319 if (hr == S_OK) IUnknown_Release(pOtherUnknown);
1321 hr = IUnknown_QueryInterface(pProxy, &IID_IMultiQI, (LPVOID*)&pOtherUnknown);
1322 ok_ole_success(hr, IUnknown_QueryInterface IID_IMultiQI);
1323 if (hr == S_OK) IUnknown_Release(pOtherUnknown);
1325 hr = IUnknown_QueryInterface(pProxy, &IID_IMarshal, (LPVOID*)&pOtherUnknown);
1326 ok_ole_success(hr, IUnknown_QueryInterface IID_IMarshal);
1327 if (hr == S_OK) IUnknown_Release(pOtherUnknown);
1329 /* IMarshal2 is also supported on NT-based systems, but is pretty much
1330 * useless as it has no more methods over IMarshal that it inherits from. */
1332 IUnknown_Release(pProxy);
1334 ok_no_locks();
1336 end_host_object(tid, thread);
1339 typedef struct
1341 const IUnknownVtbl *lpVtbl;
1342 ULONG refs;
1343 } HeapUnknown;
1345 static HRESULT WINAPI HeapUnknown_QueryInterface(IUnknown *iface, REFIID riid, void **ppv)
1347 if (IsEqualIID(riid, &IID_IUnknown))
1349 IUnknown_AddRef(iface);
1350 *ppv = (LPVOID)iface;
1351 return S_OK;
1353 *ppv = NULL;
1354 return E_NOINTERFACE;
1357 static ULONG WINAPI HeapUnknown_AddRef(IUnknown *iface)
1359 HeapUnknown *This = (HeapUnknown *)iface;
1360 trace("HeapUnknown_AddRef(%p)\n", iface);
1361 return InterlockedIncrement((LONG*)&This->refs);
1364 static ULONG WINAPI HeapUnknown_Release(IUnknown *iface)
1366 HeapUnknown *This = (HeapUnknown *)iface;
1367 ULONG refs = InterlockedDecrement((LONG*)&This->refs);
1368 trace("HeapUnknown_Release(%p)\n", iface);
1369 if (!refs) HeapFree(GetProcessHeap(), 0, This);
1370 return refs;
1373 static const IUnknownVtbl HeapUnknown_Vtbl =
1375 HeapUnknown_QueryInterface,
1376 HeapUnknown_AddRef,
1377 HeapUnknown_Release
1380 static void test_proxybuffer(REFIID riid)
1382 HRESULT hr;
1383 IPSFactoryBuffer *psfb;
1384 IRpcProxyBuffer *proxy;
1385 LPVOID lpvtbl;
1386 ULONG refs;
1387 CLSID clsid;
1388 HeapUnknown *pUnkOuter = (HeapUnknown *)HeapAlloc(GetProcessHeap(), 0, sizeof(*pUnkOuter));
1390 pUnkOuter->lpVtbl = &HeapUnknown_Vtbl;
1391 pUnkOuter->refs = 1;
1393 hr = CoGetPSClsid(riid, &clsid);
1394 ok_ole_success(hr, CoGetPSClsid);
1396 hr = CoGetClassObject(&clsid, CLSCTX_INPROC_SERVER, NULL, &IID_IPSFactoryBuffer, (LPVOID*)&psfb);
1397 ok_ole_success(hr, CoGetClassObject);
1399 hr = IPSFactoryBuffer_CreateProxy(psfb, (IUnknown*)pUnkOuter, riid, &proxy, &lpvtbl);
1400 ok_ole_success(hr, IPSFactoryBuffer_CreateProxy);
1401 ok(lpvtbl != NULL, "IPSFactoryBuffer_CreateProxy succeeded, but returned a NULL vtable!\n");
1403 refs = IPSFactoryBuffer_Release(psfb);
1404 #if 0 /* not reliable on native. maybe it leaks references! */
1405 ok(refs == 0, "Ref-count leak of %ld on IPSFactoryBuffer\n", refs);
1406 #endif
1408 refs = IUnknown_Release((IUnknown *)lpvtbl);
1409 ok(refs == 1, "Ref-count leak of %ld on IRpcProxyBuffer\n", refs-1);
1411 refs = IRpcProxyBuffer_Release(proxy);
1412 ok(refs == 0, "Ref-count leak of %ld on IRpcProxyBuffer\n", refs);
1415 static void test_stubbuffer(REFIID riid)
1417 HRESULT hr;
1418 IPSFactoryBuffer *psfb;
1419 IRpcStubBuffer *stub;
1420 ULONG refs;
1421 CLSID clsid;
1423 cLocks = 0;
1425 hr = CoGetPSClsid(riid, &clsid);
1426 ok_ole_success(hr, CoGetPSClsid);
1428 hr = CoGetClassObject(&clsid, CLSCTX_INPROC_SERVER, NULL, &IID_IPSFactoryBuffer, (LPVOID*)&psfb);
1429 ok_ole_success(hr, CoGetClassObject);
1431 hr = IPSFactoryBuffer_CreateStub(psfb, riid, (IUnknown*)&Test_ClassFactory, &stub);
1432 ok_ole_success(hr, IPSFactoryBuffer_CreateStub);
1434 refs = IPSFactoryBuffer_Release(psfb);
1435 #if 0 /* not reliable on native. maybe it leaks references */
1436 ok(refs == 0, "Ref-count leak of %ld on IPSFactoryBuffer\n", refs);
1437 #endif
1439 ok_more_than_one_lock();
1441 IRpcStubBuffer_Disconnect(stub);
1443 ok_no_locks();
1445 refs = IRpcStubBuffer_Release(stub);
1446 ok(refs == 0, "Ref-count leak of %ld on IRpcProxyBuffer\n", refs);
1449 static HWND hwnd_app;
1451 static HRESULT WINAPI TestRE_IClassFactory_CreateInstance(
1452 LPCLASSFACTORY iface,
1453 LPUNKNOWN pUnkOuter,
1454 REFIID riid,
1455 LPVOID *ppvObj)
1457 DWORD_PTR res;
1458 if (IsEqualIID(riid, &IID_IWineTest))
1460 BOOL ret = SendMessageTimeout(hwnd_app, WM_NULL, 0, 0, SMTO_BLOCK, 5000, &res);
1461 ok(ret, "Timed out sending a message to originating window during RPC call\n");
1463 return S_FALSE;
1466 static const IClassFactoryVtbl TestREClassFactory_Vtbl =
1468 Test_IClassFactory_QueryInterface,
1469 Test_IClassFactory_AddRef,
1470 Test_IClassFactory_Release,
1471 TestRE_IClassFactory_CreateInstance,
1472 Test_IClassFactory_LockServer
1475 IClassFactory TestRE_ClassFactory = { &TestREClassFactory_Vtbl };
1477 static LRESULT CALLBACK window_proc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam)
1479 switch (msg)
1481 case WM_USER:
1483 HRESULT hr;
1484 IStream *pStream = NULL;
1485 IClassFactory *proxy = NULL;
1486 IUnknown *object;
1487 DWORD tid;
1488 HANDLE thread;
1490 cLocks = 0;
1492 hr = CreateStreamOnHGlobal(NULL, TRUE, &pStream);
1493 ok_ole_success(hr, CreateStreamOnHGlobal);
1494 tid = start_host_object(pStream, &IID_IClassFactory, (IUnknown*)&TestRE_ClassFactory, MSHLFLAGS_NORMAL, &thread);
1496 ok_more_than_one_lock();
1498 IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
1499 hr = CoUnmarshalInterface(pStream, &IID_IClassFactory, (void **)&proxy);
1500 ok_ole_success(hr, CoReleaseMarshalData);
1501 IStream_Release(pStream);
1503 ok_more_than_one_lock();
1505 /* note the use of the magic IID_IWineTest value to tell remote thread
1506 * to try to send a message back to us */
1507 hr = IClassFactory_CreateInstance(proxy, NULL, &IID_IWineTest, (void **)&object);
1509 IClassFactory_Release(proxy);
1511 ok_no_locks();
1513 end_host_object(tid, thread);
1515 PostMessage(hwnd, WM_QUIT, 0, 0);
1517 return 0;
1519 case WM_USER+1:
1521 HRESULT hr;
1522 IStream *pStream = NULL;
1523 IClassFactory *proxy = NULL;
1524 IUnknown *object;
1525 DWORD tid;
1526 HANDLE thread;
1528 cLocks = 0;
1530 hr = CreateStreamOnHGlobal(NULL, TRUE, &pStream);
1531 ok_ole_success(hr, CreateStreamOnHGlobal);
1532 tid = start_host_object(pStream, &IID_IClassFactory, (IUnknown*)&TestRE_ClassFactory, MSHLFLAGS_NORMAL, &thread);
1534 ok_more_than_one_lock();
1536 IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
1537 hr = CoUnmarshalInterface(pStream, &IID_IClassFactory, (void **)&proxy);
1538 ok_ole_success(hr, CoReleaseMarshalData);
1539 IStream_Release(pStream);
1541 ok_more_than_one_lock();
1543 /* post quit message before a doing a COM call to show that a pending
1544 * WM_QUIT message doesn't stop the call from succeeding */
1545 PostMessage(hwnd, WM_QUIT, 0, 0);
1546 hr = IClassFactory_CreateInstance(proxy, NULL, &IID_IUnknown, (void **)&object);
1548 IClassFactory_Release(proxy);
1550 ok_no_locks();
1552 end_host_object(tid, thread);
1554 return 0;
1556 default:
1557 return DefWindowProc(hwnd, msg, wparam, lparam);
1561 static void test_message_reentrancy(void)
1563 WNDCLASS wndclass;
1564 MSG msg;
1566 memset(&wndclass, 0, sizeof(wndclass));
1567 wndclass.lpfnWndProc = window_proc;
1568 wndclass.lpszClassName = "WineCOMTest";
1569 RegisterClass(&wndclass);
1571 hwnd_app = CreateWindow("WineCOMTest", NULL, 0, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, NULL, NULL, NULL, 0);
1572 ok(hwnd_app != NULL, "Window creation failed\n");
1574 /* start message re-entrancy test */
1575 PostMessage(hwnd_app, WM_USER, 0, 0);
1577 while (GetMessage(&msg, NULL, 0, 0))
1579 TranslateMessage(&msg);
1580 DispatchMessage(&msg);
1584 static void test_WM_QUIT_handling(void)
1586 MSG msg;
1588 hwnd_app = CreateWindow("WineCOMTest", NULL, 0, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, NULL, NULL, NULL, 0);
1589 ok(hwnd_app != NULL, "Window creation failed\n");
1591 /* start WM_QUIT handling test */
1592 PostMessage(hwnd_app, WM_USER+1, 0, 0);
1594 while (GetMessage(&msg, NULL, 0, 0))
1596 TranslateMessage(&msg);
1597 DispatchMessage(&msg);
1601 /* doesn't pass with Win9x COM DLLs (even though Essential COM says it should) */
1602 #if 0
1604 static HANDLE heventShutdown;
1606 static void LockModuleOOP()
1608 InterlockedIncrement(&cLocks); /* for test purposes only */
1609 CoAddRefServerProcess();
1612 static void UnlockModuleOOP()
1614 InterlockedDecrement(&cLocks); /* for test purposes only */
1615 if (!CoReleaseServerProcess())
1616 SetEvent(heventShutdown);
1619 static HWND hwnd_app;
1621 static HRESULT WINAPI TestOOP_IClassFactory_QueryInterface(
1622 LPCLASSFACTORY iface,
1623 REFIID riid,
1624 LPVOID *ppvObj)
1626 if (ppvObj == NULL) return E_POINTER;
1628 if (IsEqualGUID(riid, &IID_IUnknown) ||
1629 IsEqualGUID(riid, &IID_IClassFactory))
1631 *ppvObj = (LPVOID)iface;
1632 IClassFactory_AddRef(iface);
1633 return S_OK;
1636 return E_NOINTERFACE;
1639 static ULONG WINAPI TestOOP_IClassFactory_AddRef(LPCLASSFACTORY iface)
1641 return 2; /* non-heap-based object */
1644 static ULONG WINAPI TestOOP_IClassFactory_Release(LPCLASSFACTORY iface)
1646 return 1; /* non-heap-based object */
1649 static HRESULT WINAPI TestOOP_IClassFactory_CreateInstance(
1650 LPCLASSFACTORY iface,
1651 LPUNKNOWN pUnkOuter,
1652 REFIID riid,
1653 LPVOID *ppvObj)
1655 return CLASS_E_CLASSNOTAVAILABLE;
1658 static HRESULT WINAPI TestOOP_IClassFactory_LockServer(
1659 LPCLASSFACTORY iface,
1660 BOOL fLock)
1662 if (fLock)
1663 LockModuleOOP();
1664 else
1665 UnlockModuleOOP();
1666 return S_OK;
1669 static const IClassFactoryVtbl TestClassFactoryOOP_Vtbl =
1671 TestOOP_IClassFactory_QueryInterface,
1672 TestOOP_IClassFactory_AddRef,
1673 TestOOP_IClassFactory_Release,
1674 TestOOP_IClassFactory_CreateInstance,
1675 TestOOP_IClassFactory_LockServer
1678 static IClassFactory TestOOP_ClassFactory = { &TestClassFactoryOOP_Vtbl };
1680 /* tests functions commonly used by out of process COM servers */
1681 static void test_out_of_process_com(void)
1683 static const CLSID CLSID_WineOOPTest = {
1684 0x5201163f,
1685 0x8164,
1686 0x4fd0,
1687 {0xa1, 0xa2, 0x5d, 0x5a, 0x36, 0x54, 0xd3, 0xbd}
1688 }; /* 5201163f-8164-4fd0-a1a2-5d5a3654d3bd */
1689 DWORD cookie;
1690 HRESULT hr;
1691 IClassFactory * cf;
1692 DWORD ret;
1694 heventShutdown = CreateEvent(NULL, TRUE, FALSE, NULL);
1696 cLocks = 0;
1698 /* Start the object suspended */
1699 hr = CoRegisterClassObject(&CLSID_WineOOPTest, (IUnknown *)&TestOOP_ClassFactory,
1700 CLSCTX_LOCAL_SERVER, REGCLS_MULTIPLEUSE | REGCLS_SUSPENDED, &cookie);
1701 ok_ole_success(hr, CoRegisterClassObject);
1703 /* ... and CoGetClassObject does not find it and fails when it looks for the
1704 * class in the registry */
1705 hr = CoGetClassObject(&CLSID_WineOOPTest, CLSCTX_INPROC_SERVER,
1706 NULL, &IID_IClassFactory, (LPVOID*)&cf);
1707 todo_wine {
1708 ok(hr == REGDB_E_CLASSNOTREG,
1709 "CoGetClassObject should have returned REGDB_E_CLASSNOTREG instead of 0x%08lx\n", hr);
1712 /* Resume the object suspended above ... */
1713 hr = CoResumeClassObjects();
1714 ok_ole_success(hr, CoResumeClassObjects);
1716 /* ... and now it should succeed */
1717 hr = CoGetClassObject(&CLSID_WineOOPTest, CLSCTX_INPROC_SERVER,
1718 NULL, &IID_IClassFactory, (LPVOID*)&cf);
1719 ok_ole_success(hr, CoGetClassObject);
1721 /* Now check the locking is working */
1722 /* NOTE: we are accessing the class directly, not through a proxy */
1724 ok_no_locks();
1726 hr = IClassFactory_LockServer(cf, TRUE);
1727 trace("IClassFactory_LockServer returned 0x%08lx\n", hr);
1729 ok_more_than_one_lock();
1731 IClassFactory_LockServer(cf, FALSE);
1733 ok_no_locks();
1735 IClassFactory_Release(cf);
1737 /* wait for shutdown signal */
1738 ret = WaitForSingleObject(heventShutdown, 5000);
1739 todo_wine { ok(ret != WAIT_TIMEOUT, "Server didn't shut down or machine is under very heavy load\n"); }
1741 /* try to connect again after SCM has suspended registered class objects */
1742 hr = CoGetClassObject(&CLSID_WineOOPTest, CLSCTX_INPROC_SERVER | CLSCTX_LOCAL_SERVER, NULL,
1743 &IID_IClassFactory, (LPVOID*)&cf);
1744 todo_wine {
1745 ok(hr == CO_E_SERVER_STOPPING,
1746 "CoGetClassObject should have returned CO_E_SERVER_STOPPING instead of 0x%08lx\n", hr);
1749 hr = CoRevokeClassObject(cookie);
1750 ok_ole_success(hr, CoRevokeClassObject);
1752 CloseHandle(heventShutdown);
1754 #endif
1756 static void test_ROT(void)
1758 static const WCHAR wszFileName[] = {'B','E','2','0','E','2','F','5','-',
1759 '1','9','0','3','-','4','A','A','E','-','B','1','A','F','-',
1760 '2','0','4','6','E','5','8','6','C','9','2','5',0};
1761 HRESULT hr;
1762 IMoniker *pMoniker = NULL;
1763 IRunningObjectTable *pROT = NULL;
1764 DWORD dwCookie;
1766 cLocks = 0;
1768 hr = CreateFileMoniker(wszFileName, &pMoniker);
1769 ok_ole_success(hr, CreateClassMoniker);
1770 hr = GetRunningObjectTable(0, &pROT);
1771 ok_ole_success(hr, GetRunningObjectTable);
1772 hr = IRunningObjectTable_Register(pROT, 0, (IUnknown*)&Test_ClassFactory, pMoniker, &dwCookie);
1773 ok_ole_success(hr, IRunningObjectTable_Register);
1775 ok_more_than_one_lock();
1777 hr = IRunningObjectTable_Revoke(pROT, dwCookie);
1778 ok_ole_success(hr, IRunningObjectTable_Revoke);
1780 ok_no_locks();
1783 static const char cf_marshaled[] =
1785 0x9, 0x0, 0x0, 0x0,
1786 0x0, 0x0, 0x0, 0x0,
1787 0x9, 0x0, 0x0, 0x0,
1788 'M', 0x0, 'y', 0x0,
1789 'F', 0x0, 'o', 0x0,
1790 'r', 0x0, 'm', 0x0,
1791 'a', 0x0, 't', 0x0,
1792 0x0, 0x0
1795 static void test_marshal_CLIPFORMAT(void)
1797 unsigned char *buffer;
1798 unsigned long size;
1799 unsigned long flags = MAKELONG(MSHCTX_DIFFERENTMACHINE, NDR_LOCAL_DATA_REPRESENTATION);
1800 wireCLIPFORMAT wirecf;
1801 CLIPFORMAT cf = RegisterClipboardFormatA("MyFormat");
1802 CLIPFORMAT cf2;
1804 size = CLIPFORMAT_UserSize(&flags, 0, &cf);
1805 ok(size == sizeof(*wirecf) + sizeof(cf_marshaled), "Size should be %d, instead of %ld\n", sizeof(*wirecf) + sizeof(cf_marshaled), size);
1807 buffer = HeapAlloc(GetProcessHeap(), 0, size);
1808 CLIPFORMAT_UserMarshal(&flags, buffer, &cf);
1809 wirecf = (wireCLIPFORMAT)buffer;
1810 ok(wirecf->fContext == WDT_REMOTE_CALL, "Context should be WDT_REMOTE_CALL instead of 0x%08lx\n", wirecf->fContext);
1811 ok(wirecf->u.dwValue == cf, "Marshaled value should be 0x%04x instead of 0x%04lx\n", cf, wirecf->u.dwValue);
1812 ok(!memcmp(wirecf+1, cf_marshaled, sizeof(cf_marshaled)), "Marshaled data differs\n");
1814 CLIPFORMAT_UserUnmarshal(&flags, buffer, &cf2);
1815 ok(cf == cf2, "Didn't unmarshal properly\n");
1816 HeapFree(GetProcessHeap(), 0, buffer);
1818 CLIPFORMAT_UserFree(&flags, &cf2);
1821 static void test_marshal_HWND(void)
1823 unsigned char *buffer;
1824 unsigned long size;
1825 unsigned long flags = MAKELONG(MSHCTX_LOCAL, NDR_LOCAL_DATA_REPRESENTATION);
1826 HWND hwnd = GetDesktopWindow();
1827 HWND hwnd2;
1828 wireHWND wirehwnd;
1830 size = HWND_UserSize(&flags, 0, &hwnd);
1831 ok(size == sizeof(*wirehwnd), "Size should be %d, instead of %ld\n", sizeof(*wirehwnd), size);
1833 buffer = HeapAlloc(GetProcessHeap(), 0, size);
1834 HWND_UserMarshal(&flags, buffer, &hwnd);
1835 wirehwnd = (wireHWND)buffer;
1836 ok(wirehwnd->fContext == WDT_INPROC_CALL, "Context should be WDT_INPROC_CALL instead of 0x%08lx\n", wirehwnd->fContext);
1837 ok(wirehwnd->u.hInproc == (LONG_PTR)hwnd, "Marshaled value should be %p instead of %p\n", hwnd, (HANDLE)wirehwnd->u.hRemote);
1839 HWND_UserUnmarshal(&flags, buffer, &hwnd2);
1840 ok(hwnd == hwnd2, "Didn't unmarshal properly\n");
1841 HeapFree(GetProcessHeap(), 0, buffer);
1843 HWND_UserFree(&flags, &hwnd2);
1846 static void test_marshal_HGLOBAL(void)
1848 unsigned char *buffer;
1849 unsigned long size;
1850 unsigned long flags = MAKELONG(MSHCTX_LOCAL, NDR_LOCAL_DATA_REPRESENTATION);
1851 HGLOBAL hglobal;
1852 HGLOBAL hglobal2;
1853 unsigned char *wirehglobal;
1854 int i;
1856 hglobal = NULL;
1857 flags = MAKELONG(MSHCTX_LOCAL, NDR_LOCAL_DATA_REPRESENTATION);
1858 size = HGLOBAL_UserSize(&flags, 0, &hglobal);
1859 /* native is poorly programmed and allocates 4 bytes more than it needs to
1860 * here - Wine doesn't have to emulate that */
1861 ok((size == 8) || (size == 12), "Size should be 12, instead of %ld\n", size);
1862 buffer = HeapAlloc(GetProcessHeap(), 0, size);
1863 HGLOBAL_UserMarshal(&flags, buffer, &hglobal);
1864 wirehglobal = buffer;
1865 ok(*(ULONG *)wirehglobal == WDT_REMOTE_CALL, "Context should be WDT_REMOTE_CALL instead of 0x%08lx\n", *(ULONG *)wirehglobal);
1866 wirehglobal += sizeof(ULONG);
1867 ok(*(ULONG *)wirehglobal == (ULONG)hglobal, "buffer+4 should be HGLOBAL\n");
1868 HGLOBAL_UserUnmarshal(&flags, buffer, &hglobal2);
1869 ok(hglobal2 == hglobal, "Didn't unmarshal properly\n");
1870 HeapFree(GetProcessHeap(), 0, buffer);
1871 HGLOBAL_UserFree(&flags, &hglobal2);
1873 hglobal = GlobalAlloc(0, 4);
1874 buffer = GlobalLock(hglobal);
1875 for (i = 0; i < 4; i++)
1876 buffer[i] = i;
1877 GlobalUnlock(hglobal);
1878 flags = MAKELONG(MSHCTX_LOCAL, NDR_LOCAL_DATA_REPRESENTATION);
1879 size = HGLOBAL_UserSize(&flags, 0, &hglobal);
1880 /* native is poorly programmed and allocates 4 bytes more than it needs to
1881 * here - Wine doesn't have to emulate that */
1882 ok((size == 24) || (size == 28), "Size should be 24 or 28, instead of %ld\n", size);
1883 buffer = HeapAlloc(GetProcessHeap(), 0, size);
1884 HGLOBAL_UserMarshal(&flags, buffer, &hglobal);
1885 wirehglobal = buffer;
1886 ok(*(ULONG *)wirehglobal == WDT_REMOTE_CALL, "Context should be WDT_REMOTE_CALL instead of 0x%08lx\n", *(ULONG *)wirehglobal);
1887 wirehglobal += sizeof(ULONG);
1888 ok(*(ULONG *)wirehglobal == (ULONG)hglobal, "buffer+0x4 should be HGLOBAL\n");
1889 wirehglobal += sizeof(ULONG);
1890 ok(*(ULONG *)wirehglobal == 4, "buffer+0x8 should be size of HGLOBAL\n");
1891 wirehglobal += sizeof(ULONG);
1892 ok(*(ULONG *)wirehglobal == (ULONG)hglobal, "buffer+0xc should be HGLOBAL\n");
1893 wirehglobal += sizeof(ULONG);
1894 ok(*(ULONG *)wirehglobal == 4, "buffer+0x10 should be size of HGLOBAL\n");
1895 wirehglobal += sizeof(ULONG);
1896 for (i = 0; i < 4; i++)
1897 ok(wirehglobal[i] == i, "buffer+0x%x should be %d\n", 0x10 + i, i);
1898 HGLOBAL_UserUnmarshal(&flags, buffer, &hglobal2);
1899 ok(hglobal2 != NULL, "Didn't unmarshal properly\n");
1900 HeapFree(GetProcessHeap(), 0, buffer);
1901 HGLOBAL_UserFree(&flags, &hglobal2);
1902 GlobalFree(hglobal);
1905 static HENHMETAFILE create_emf(void)
1907 RECT rect = {0, 0, 100, 100};
1908 HDC hdc = CreateEnhMetaFile(NULL, NULL, &rect, "HENHMETAFILE Marshaling Test\0Test\0\0");
1909 ExtTextOut(hdc, 0, 0, ETO_OPAQUE, NULL, "Test String", strlen("Test String"), NULL);
1910 return CloseEnhMetaFile(hdc);
1913 static void test_marshal_HENHMETAFILE(void)
1915 unsigned char *buffer;
1916 unsigned long size;
1917 unsigned long flags = MAKELONG(MSHCTX_DIFFERENTMACHINE, NDR_LOCAL_DATA_REPRESENTATION);
1918 HENHMETAFILE hemf;
1919 HENHMETAFILE hemf2 = NULL;
1920 unsigned char *wirehemf;
1922 hemf = create_emf();
1924 size = HENHMETAFILE_UserSize(&flags, 0, &hemf);
1925 ok(size > 20, "size should be at least 20 bytes, not %ld\n", size);
1926 buffer = HeapAlloc(GetProcessHeap(), 0, size);
1927 HENHMETAFILE_UserMarshal(&flags, buffer, &hemf);
1928 wirehemf = buffer;
1929 ok(*(DWORD *)wirehemf == WDT_REMOTE_CALL, "wirestgm + 0x0 should be WDT_REMOTE_CALL instead of 0x%08lx\n", *(DWORD *)wirehemf);
1930 wirehemf += sizeof(DWORD);
1931 ok(*(DWORD *)wirehemf == (DWORD)(DWORD_PTR)hemf, "wirestgm + 0x4 should be hemf instead of 0x%08lx\n", *(DWORD *)wirehemf);
1932 wirehemf += sizeof(DWORD);
1933 ok(*(DWORD *)wirehemf == (size - 0x10), "wirestgm + 0x8 should be size - 0x10 instead of 0x%08lx\n", *(DWORD *)wirehemf);
1934 wirehemf += sizeof(DWORD);
1935 ok(*(DWORD *)wirehemf == (size - 0x10), "wirestgm + 0xc should be size - 0x10 instead of 0x%08lx\n", *(DWORD *)wirehemf);
1936 wirehemf += sizeof(DWORD);
1937 ok(*(DWORD *)wirehemf == EMR_HEADER, "wirestgm + 0x10 should be EMR_HEADER instead of %ld\n", *(DWORD *)wirehemf);
1938 wirehemf += sizeof(DWORD);
1939 /* ... rest of data not tested - refer to tests for GetEnhMetaFileBits
1940 * at this point */
1942 HENHMETAFILE_UserUnmarshal(&flags, buffer, &hemf2);
1943 ok(hemf2 != NULL, "HENHMETAFILE didn't unmarshal\n");
1944 HeapFree(GetProcessHeap(), 0, buffer);
1945 HENHMETAFILE_UserFree(&flags, &hemf2);
1946 DeleteEnhMetaFile(hemf);
1948 /* test NULL emf */
1949 hemf = NULL;
1951 size = HENHMETAFILE_UserSize(&flags, 0, &hemf);
1952 ok(size == 8, "size should be 8 bytes, not %ld\n", size);
1953 buffer = (unsigned char *)HeapAlloc(GetProcessHeap(), 0, size);
1954 HENHMETAFILE_UserMarshal(&flags, buffer, &hemf);
1955 wirehemf = buffer;
1956 ok(*(DWORD *)wirehemf == WDT_REMOTE_CALL, "wirestgm + 0x0 should be WDT_REMOTE_CALL instead of 0x%08lx\n", *(DWORD *)wirehemf);
1957 wirehemf += sizeof(DWORD);
1958 ok(*(DWORD *)wirehemf == (DWORD)(DWORD_PTR)hemf, "wirestgm + 0x4 should be hemf instead of 0x%08lx\n", *(DWORD *)wirehemf);
1959 wirehemf += sizeof(DWORD);
1961 HENHMETAFILE_UserUnmarshal(&flags, buffer, &hemf2);
1962 ok(hemf2 == NULL, "NULL HENHMETAFILE didn't unmarshal\n");
1963 HeapFree(GetProcessHeap(), 0, buffer);
1964 HENHMETAFILE_UserFree(&flags, &hemf2);
1967 START_TEST(marshal)
1969 WNDCLASS wndclass;
1970 HMODULE hOle32 = GetModuleHandle("ole32");
1971 if (!(pCoInitializeEx = (void*)GetProcAddress(hOle32, "CoInitializeEx"))) goto no_test;
1973 /* register a window class used in several tests */
1974 memset(&wndclass, 0, sizeof(wndclass));
1975 wndclass.lpfnWndProc = window_proc;
1976 wndclass.lpszClassName = "WineCOMTest";
1977 RegisterClass(&wndclass);
1979 pCoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
1981 /* FIXME: test CoCreateInstanceEx */
1983 /* helper function tests */
1984 test_CoGetPSClsid();
1986 /* lifecycle management and marshaling tests */
1987 test_no_marshaler();
1988 test_normal_marshal_and_release();
1989 test_normal_marshal_and_unmarshal();
1990 test_marshal_and_unmarshal_invalid();
1991 test_interthread_marshal_and_unmarshal();
1992 test_proxy_marshal_and_unmarshal();
1993 test_proxy_marshal_and_unmarshal2();
1994 test_marshal_stub_apartment_shutdown();
1995 test_marshal_proxy_apartment_shutdown();
1996 test_marshal_proxy_mta_apartment_shutdown();
1997 test_no_couninitialize_server();
1998 test_no_couninitialize_client();
1999 test_tableweak_marshal_and_unmarshal_twice();
2000 test_tableweak_marshal_releasedata1();
2001 test_tableweak_marshal_releasedata2();
2002 test_tablestrong_marshal_and_unmarshal_twice();
2003 test_lock_object_external();
2004 test_disconnect_stub();
2005 test_normal_marshal_and_unmarshal_twice();
2006 test_hresult_marshaling();
2007 test_proxy_used_in_wrong_thread();
2008 test_message_filter();
2009 test_bad_marshal_stream();
2010 test_proxy_interfaces();
2011 test_stubbuffer(&IID_IClassFactory);
2012 test_proxybuffer(&IID_IClassFactory);
2013 test_message_reentrancy();
2014 test_WM_QUIT_handling();
2016 /* test_out_of_process_com(); */
2018 test_ROT();
2019 /* FIXME: test GIT */
2021 test_marshal_CLIPFORMAT();
2022 test_marshal_HWND();
2023 test_marshal_HGLOBAL();
2024 test_marshal_HENHMETAFILE();
2026 CoUninitialize();
2027 return;
2029 no_test:
2030 trace("You need DCOM95 installed to run this test\n");
2031 return;