gdi32: Revert 1440eb5a35dc95dea1836d9035b51e2b15d83703 and add the test showing that...
[wine/hacks.git] / dlls / ole32 / tests / marshal.c
blob11f03dff916fe7a9cb4004691eef663b9d3d4717
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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
21 #define _WIN32_DCOM
22 #define COBJMACROS
23 #define CONST_VTABLE
25 #include <stdarg.h>
27 #include "windef.h"
28 #include "winbase.h"
29 #include "objbase.h"
30 #include "shlguid.h"
32 #include "wine/test.h"
34 /* functions that are not present on all versions of Windows */
35 HRESULT (WINAPI * pCoInitializeEx)(LPVOID lpReserved, DWORD dwCoInit);
37 /* helper macros to make tests a bit leaner */
38 #define ok_more_than_one_lock() ok(cLocks > 0, "Number of locks should be > 0, but actually is %d\n", cLocks)
39 #define ok_no_locks() ok(cLocks == 0, "Number of locks should be 0, but actually is %d\n", cLocks)
40 #define ok_ole_success(hr, func) ok(hr == S_OK, #func " failed with error 0x%08x\n", hr)
42 static const IID IID_IWineTest =
44 0x5201163f,
45 0x8164,
46 0x4fd0,
47 {0xa1, 0xa2, 0x5d, 0x5a, 0x36, 0x54, 0xd3, 0xbd}
48 }; /* 5201163f-8164-4fd0-a1a2-5d5a3654d3bd */
50 #define EXTENTID_WineTest IID_IWineTest
52 static void test_cocreateinstance_proxy(void)
54 IUnknown *pProxy;
55 IMultiQI *pMQI;
56 HRESULT hr;
58 pCoInitializeEx(NULL, COINIT_MULTITHREADED);
60 hr = CoCreateInstance(&CLSID_ShellDesktop, NULL, CLSCTX_INPROC, &IID_IUnknown, (void **)&pProxy);
61 ok_ole_success(hr, CoCreateInstance);
62 hr = IUnknown_QueryInterface(pProxy, &IID_IMultiQI, (void **)&pMQI);
63 todo_wine
64 ok(hr == S_OK, "created object is not a proxy, so was created in the wrong apartment\n");
65 if (hr == S_OK)
66 IMultiQI_Release(pMQI);
67 IUnknown_Release(pProxy);
69 CoUninitialize();
72 static const LARGE_INTEGER ullZero;
73 static LONG cLocks;
75 static void LockModule(void)
77 InterlockedIncrement(&cLocks);
80 static void UnlockModule(void)
82 InterlockedDecrement(&cLocks);
86 static HRESULT WINAPI Test_IUnknown_QueryInterface(
87 LPUNKNOWN iface,
88 REFIID riid,
89 LPVOID *ppvObj)
91 if (ppvObj == NULL) return E_POINTER;
93 if (IsEqualGUID(riid, &IID_IUnknown))
95 *ppvObj = (LPVOID)iface;
96 IUnknown_AddRef(iface);
97 return S_OK;
100 *ppvObj = NULL;
101 return E_NOINTERFACE;
104 static ULONG WINAPI Test_IUnknown_AddRef(LPUNKNOWN iface)
106 LockModule();
107 return 2; /* non-heap-based object */
110 static ULONG WINAPI Test_IUnknown_Release(LPUNKNOWN iface)
112 UnlockModule();
113 return 1; /* non-heap-based object */
116 static const IUnknownVtbl TestUnknown_Vtbl =
118 Test_IUnknown_QueryInterface,
119 Test_IUnknown_AddRef,
120 Test_IUnknown_Release,
123 static IUnknown Test_Unknown = { &TestUnknown_Vtbl };
126 static HRESULT WINAPI Test_IClassFactory_QueryInterface(
127 LPCLASSFACTORY iface,
128 REFIID riid,
129 LPVOID *ppvObj)
131 if (ppvObj == NULL) return E_POINTER;
133 if (IsEqualGUID(riid, &IID_IUnknown) ||
134 IsEqualGUID(riid, &IID_IClassFactory))
136 *ppvObj = (LPVOID)iface;
137 IClassFactory_AddRef(iface);
138 return S_OK;
141 *ppvObj = NULL;
142 return E_NOINTERFACE;
145 static ULONG WINAPI Test_IClassFactory_AddRef(LPCLASSFACTORY iface)
147 LockModule();
148 return 2; /* non-heap-based object */
151 static ULONG WINAPI Test_IClassFactory_Release(LPCLASSFACTORY iface)
153 UnlockModule();
154 return 1; /* non-heap-based object */
157 static HRESULT WINAPI Test_IClassFactory_CreateInstance(
158 LPCLASSFACTORY iface,
159 LPUNKNOWN pUnkOuter,
160 REFIID riid,
161 LPVOID *ppvObj)
163 if (pUnkOuter) return CLASS_E_NOAGGREGATION;
164 return IUnknown_QueryInterface((IUnknown*)&Test_Unknown, riid, ppvObj);
167 static HRESULT WINAPI Test_IClassFactory_LockServer(
168 LPCLASSFACTORY iface,
169 BOOL fLock)
171 return S_OK;
174 static const IClassFactoryVtbl TestClassFactory_Vtbl =
176 Test_IClassFactory_QueryInterface,
177 Test_IClassFactory_AddRef,
178 Test_IClassFactory_Release,
179 Test_IClassFactory_CreateInstance,
180 Test_IClassFactory_LockServer
183 static IClassFactory Test_ClassFactory = { &TestClassFactory_Vtbl };
185 #define RELEASEMARSHALDATA WM_USER
187 struct host_object_data
189 IStream *stream;
190 IID iid;
191 IUnknown *object;
192 MSHLFLAGS marshal_flags;
193 HANDLE marshal_event;
194 IMessageFilter *filter;
197 static DWORD CALLBACK host_object_proc(LPVOID p)
199 struct host_object_data *data = (struct host_object_data *)p;
200 HRESULT hr;
201 MSG msg;
203 pCoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
205 if (data->filter)
207 IMessageFilter * prev_filter = NULL;
208 hr = CoRegisterMessageFilter(data->filter, &prev_filter);
209 if (prev_filter) IMessageFilter_Release(prev_filter);
210 ok_ole_success(hr, CoRegisterMessageFilter);
213 hr = CoMarshalInterface(data->stream, &data->iid, data->object, MSHCTX_INPROC, NULL, data->marshal_flags);
214 ok_ole_success(hr, CoMarshalInterface);
216 /* force the message queue to be created before signaling parent thread */
217 PeekMessage(&msg, NULL, WM_USER, WM_USER, PM_NOREMOVE);
219 SetEvent(data->marshal_event);
221 while (GetMessage(&msg, NULL, 0, 0))
223 if (msg.hwnd == NULL && msg.message == RELEASEMARSHALDATA)
225 trace("releasing marshal data\n");
226 CoReleaseMarshalData(data->stream);
227 SetEvent((HANDLE)msg.lParam);
229 else
230 DispatchMessage(&msg);
233 HeapFree(GetProcessHeap(), 0, data);
235 CoUninitialize();
237 return hr;
240 static DWORD start_host_object2(IStream *stream, REFIID riid, IUnknown *object, MSHLFLAGS marshal_flags, IMessageFilter *filter, HANDLE *thread)
242 DWORD tid = 0;
243 HANDLE marshal_event = CreateEvent(NULL, FALSE, FALSE, NULL);
244 struct host_object_data *data = HeapAlloc(GetProcessHeap(), 0, sizeof(*data));
246 data->stream = stream;
247 data->iid = *riid;
248 data->object = object;
249 data->marshal_flags = marshal_flags;
250 data->marshal_event = marshal_event;
251 data->filter = filter;
253 *thread = CreateThread(NULL, 0, host_object_proc, data, 0, &tid);
255 /* wait for marshaling to complete before returning */
256 WaitForSingleObject(marshal_event, INFINITE);
257 CloseHandle(marshal_event);
259 return tid;
262 static DWORD start_host_object(IStream *stream, REFIID riid, IUnknown *object, MSHLFLAGS marshal_flags, HANDLE *thread)
264 return start_host_object2(stream, riid, object, marshal_flags, NULL, thread);
267 /* asks thread to release the marshal data because it has to be done by the
268 * same thread that marshaled the interface in the first place. */
269 static void release_host_object(DWORD tid)
271 HANDLE event = CreateEvent(NULL, FALSE, FALSE, NULL);
272 PostThreadMessage(tid, RELEASEMARSHALDATA, 0, (LPARAM)event);
273 WaitForSingleObject(event, INFINITE);
274 CloseHandle(event);
277 static void end_host_object(DWORD tid, HANDLE thread)
279 BOOL ret = PostThreadMessage(tid, WM_QUIT, 0, 0);
280 ok(ret, "PostThreadMessage failed with error %d\n", GetLastError());
281 /* be careful of races - don't return until hosting thread has terminated */
282 WaitForSingleObject(thread, INFINITE);
283 CloseHandle(thread);
286 /* tests failure case of interface not having a marshaler specified in the
287 * registry */
288 static void test_no_marshaler(void)
290 IStream *pStream;
291 HRESULT hr;
293 hr = CreateStreamOnHGlobal(NULL, TRUE, &pStream);
294 ok_ole_success(hr, CreateStreamOnHGlobal);
295 hr = CoMarshalInterface(pStream, &IID_IWineTest, (IUnknown*)&Test_ClassFactory, MSHCTX_INPROC, NULL, MSHLFLAGS_NORMAL);
296 ok(hr == E_NOINTERFACE, "CoMarshalInterface should have returned E_NOINTERFACE instead of 0x%08x\n", hr);
298 IStream_Release(pStream);
301 /* tests normal marshal and then release without unmarshaling */
302 static void test_normal_marshal_and_release(void)
304 HRESULT hr;
305 IStream *pStream = NULL;
307 cLocks = 0;
309 hr = CreateStreamOnHGlobal(NULL, TRUE, &pStream);
310 ok_ole_success(hr, CreateStreamOnHGlobal);
311 hr = CoMarshalInterface(pStream, &IID_IClassFactory, (IUnknown*)&Test_ClassFactory, MSHCTX_INPROC, NULL, MSHLFLAGS_NORMAL);
312 ok_ole_success(hr, CoMarshalInterface);
314 ok_more_than_one_lock();
316 IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
317 hr = CoReleaseMarshalData(pStream);
318 ok_ole_success(hr, CoReleaseMarshalData);
319 IStream_Release(pStream);
321 ok_no_locks();
324 /* tests success case of a same-thread marshal and unmarshal */
325 static void test_normal_marshal_and_unmarshal(void)
327 HRESULT hr;
328 IStream *pStream = NULL;
329 IUnknown *pProxy = NULL;
331 cLocks = 0;
333 hr = CreateStreamOnHGlobal(NULL, TRUE, &pStream);
334 ok_ole_success(hr, CreateStreamOnHGlobal);
335 hr = CoMarshalInterface(pStream, &IID_IClassFactory, (IUnknown*)&Test_ClassFactory, MSHCTX_INPROC, NULL, MSHLFLAGS_NORMAL);
336 ok_ole_success(hr, CoMarshalInterface);
338 ok_more_than_one_lock();
340 IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
341 hr = CoUnmarshalInterface(pStream, &IID_IClassFactory, (void **)&pProxy);
342 ok_ole_success(hr, CoUnmarshalInterface);
343 IStream_Release(pStream);
345 ok_more_than_one_lock();
347 IUnknown_Release(pProxy);
349 ok_no_locks();
352 /* tests failure case of unmarshaling a freed object */
353 static void test_marshal_and_unmarshal_invalid(void)
355 HRESULT hr;
356 IStream *pStream = NULL;
357 IClassFactory *pProxy = NULL;
358 DWORD tid;
359 void * dummy;
360 HANDLE thread;
362 cLocks = 0;
364 hr = CreateStreamOnHGlobal(NULL, TRUE, &pStream);
365 ok_ole_success(hr, CreateStreamOnHGlobal);
366 tid = start_host_object(pStream, &IID_IClassFactory, (IUnknown*)&Test_ClassFactory, MSHLFLAGS_NORMAL, &thread);
368 ok_more_than_one_lock();
370 IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
371 hr = CoReleaseMarshalData(pStream);
372 ok_ole_success(hr, CoReleaseMarshalData);
374 ok_no_locks();
376 IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
377 hr = CoUnmarshalInterface(pStream, &IID_IClassFactory, (void **)&pProxy);
378 todo_wine { ok_ole_success(hr, CoUnmarshalInterface); }
380 ok_no_locks();
382 if (pProxy)
384 hr = IClassFactory_CreateInstance(pProxy, NULL, &IID_IUnknown, &dummy);
385 ok(hr == RPC_E_DISCONNECTED, "Remote call should have returned RPC_E_DISCONNECTED, instead of 0x%08x\n", hr);
387 IClassFactory_Release(pProxy);
390 IStream_Release(pStream);
392 end_host_object(tid, thread);
395 static void test_same_apartment_unmarshal_failure(void)
397 HRESULT hr;
398 IStream *pStream;
399 IUnknown *pProxy;
400 static const LARGE_INTEGER llZero;
402 cLocks = 0;
404 hr = CreateStreamOnHGlobal(NULL, TRUE, &pStream);
405 ok_ole_success(hr, CreateStreamOnHGlobal);
407 hr = CoMarshalInterface(pStream, &IID_IUnknown, (IUnknown *)&Test_ClassFactory, MSHCTX_INPROC, NULL, MSHLFLAGS_NORMAL);
408 ok_ole_success(hr, CoMarshalInterface);
410 ok_more_than_one_lock();
412 hr = IStream_Seek(pStream, llZero, STREAM_SEEK_SET, NULL);
413 ok_ole_success(hr, IStream_Seek);
415 hr = CoUnmarshalInterface(pStream, &IID_IParseDisplayName, (void **)&pProxy);
416 ok(hr == E_NOINTERFACE, "CoUnmarshalInterface should have returned E_NOINTERFACE instead of 0x%08x\n", hr);
418 ok_no_locks();
421 /* tests success case of an interthread marshal */
422 static void test_interthread_marshal_and_unmarshal(void)
424 HRESULT hr;
425 IStream *pStream = NULL;
426 IUnknown *pProxy = NULL;
427 DWORD tid;
428 HANDLE thread;
430 cLocks = 0;
432 hr = CreateStreamOnHGlobal(NULL, TRUE, &pStream);
433 ok_ole_success(hr, CreateStreamOnHGlobal);
434 tid = start_host_object(pStream, &IID_IClassFactory, (IUnknown*)&Test_ClassFactory, MSHLFLAGS_NORMAL, &thread);
436 ok_more_than_one_lock();
438 IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
439 hr = CoUnmarshalInterface(pStream, &IID_IClassFactory, (void **)&pProxy);
440 ok_ole_success(hr, CoUnmarshalInterface);
441 IStream_Release(pStream);
443 ok_more_than_one_lock();
445 IUnknown_Release(pProxy);
447 ok_no_locks();
449 end_host_object(tid, thread);
452 /* the number of external references that Wine's proxy manager normally gives
453 * out, so we can test the border case of running out of references */
454 #define NORMALEXTREFS 5
456 /* tests success case of an interthread marshal and then marshaling the proxy */
457 static void test_proxy_marshal_and_unmarshal(void)
459 HRESULT hr;
460 IStream *pStream = NULL;
461 IUnknown *pProxy = NULL;
462 IUnknown *pProxy2 = NULL;
463 DWORD tid;
464 HANDLE thread;
465 int i;
467 cLocks = 0;
469 hr = CreateStreamOnHGlobal(NULL, TRUE, &pStream);
470 ok_ole_success(hr, CreateStreamOnHGlobal);
471 tid = start_host_object(pStream, &IID_IClassFactory, (IUnknown*)&Test_ClassFactory, MSHLFLAGS_NORMAL, &thread);
473 ok_more_than_one_lock();
475 IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
476 hr = CoUnmarshalInterface(pStream, &IID_IClassFactory, (void **)&pProxy);
477 ok_ole_success(hr, CoUnmarshalInterface);
479 ok_more_than_one_lock();
481 IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
482 /* marshal the proxy */
483 hr = CoMarshalInterface(pStream, &IID_IClassFactory, pProxy, MSHCTX_INPROC, NULL, MSHLFLAGS_NORMAL);
484 ok_ole_success(hr, CoMarshalInterface);
486 ok_more_than_one_lock();
488 /* marshal 5 more times to exhaust the normal external references of 5 */
489 for (i = 0; i < NORMALEXTREFS; i++)
491 hr = CoMarshalInterface(pStream, &IID_IClassFactory, pProxy, MSHCTX_INPROC, NULL, MSHLFLAGS_NORMAL);
492 ok_ole_success(hr, CoMarshalInterface);
495 ok_more_than_one_lock();
497 /* release the original proxy to test that we successfully keep the
498 * original object alive */
499 IUnknown_Release(pProxy);
501 IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
502 hr = CoUnmarshalInterface(pStream, &IID_IClassFactory, (void **)&pProxy2);
503 ok_ole_success(hr, CoUnmarshalInterface);
505 ok_more_than_one_lock();
507 /* now the proxies should be as follows:
508 * pProxy2 -> &Test_ClassFactory
509 * they should NOT be as follows:
510 * pProxy -> &Test_ClassFactory
511 * pProxy2 -> pProxy
512 * the above can only really be tested by looking in +ole traces
515 IUnknown_Release(pProxy2);
517 /* unmarshal all of the proxies to check that the object stub still exists */
518 for (i = 0; i < NORMALEXTREFS; i++)
520 hr = CoUnmarshalInterface(pStream, &IID_IClassFactory, (void **)&pProxy2);
521 ok_ole_success(hr, CoUnmarshalInterface);
523 IUnknown_Release(pProxy2);
526 ok_no_locks();
528 IStream_Release(pStream);
530 end_host_object(tid, thread);
533 /* tests success case of an interthread marshal and then marshaling the proxy
534 * using an iid that hasn't previously been unmarshaled */
535 static void test_proxy_marshal_and_unmarshal2(void)
537 HRESULT hr;
538 IStream *pStream = NULL;
539 IUnknown *pProxy = NULL;
540 IUnknown *pProxy2 = 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_IUnknown, (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_IUnknown, (void **)&pProxy);
554 ok_ole_success(hr, CoUnmarshalInterface);
556 ok_more_than_one_lock();
558 IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
559 /* marshal the proxy */
560 hr = CoMarshalInterface(pStream, &IID_IClassFactory, pProxy, MSHCTX_INPROC, NULL, MSHLFLAGS_NORMAL);
561 ok_ole_success(hr, CoMarshalInterface);
563 ok_more_than_one_lock();
565 IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
566 /* unmarshal the second proxy to the object */
567 hr = CoUnmarshalInterface(pStream, &IID_IClassFactory, (void **)&pProxy2);
568 ok_ole_success(hr, CoUnmarshalInterface);
569 IStream_Release(pStream);
571 /* now the proxies should be as follows:
572 * pProxy -> &Test_ClassFactory
573 * pProxy2 -> &Test_ClassFactory
574 * they should NOT be as follows:
575 * pProxy -> &Test_ClassFactory
576 * pProxy2 -> pProxy
577 * the above can only really be tested by looking in +ole traces
580 ok_more_than_one_lock();
582 IUnknown_Release(pProxy);
584 ok_more_than_one_lock();
586 IUnknown_Release(pProxy2);
588 ok_no_locks();
590 end_host_object(tid, thread);
593 /* tests that stubs are released when the containing apartment is destroyed */
594 static void test_marshal_stub_apartment_shutdown(void)
596 HRESULT hr;
597 IStream *pStream = NULL;
598 IUnknown *pProxy = NULL;
599 DWORD tid;
600 HANDLE thread;
602 cLocks = 0;
604 hr = CreateStreamOnHGlobal(NULL, TRUE, &pStream);
605 ok_ole_success(hr, CreateStreamOnHGlobal);
606 tid = start_host_object(pStream, &IID_IClassFactory, (IUnknown*)&Test_ClassFactory, MSHLFLAGS_NORMAL, &thread);
608 ok_more_than_one_lock();
610 IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
611 hr = CoUnmarshalInterface(pStream, &IID_IClassFactory, (void **)&pProxy);
612 ok_ole_success(hr, CoUnmarshalInterface);
613 IStream_Release(pStream);
615 ok_more_than_one_lock();
617 end_host_object(tid, thread);
619 ok_no_locks();
621 IUnknown_Release(pProxy);
623 ok_no_locks();
626 /* tests that proxies are released when the containing apartment is destroyed */
627 static void test_marshal_proxy_apartment_shutdown(void)
629 HRESULT hr;
630 IStream *pStream = NULL;
631 IUnknown *pProxy = NULL;
632 DWORD tid;
633 HANDLE thread;
635 cLocks = 0;
637 hr = CreateStreamOnHGlobal(NULL, TRUE, &pStream);
638 ok_ole_success(hr, CreateStreamOnHGlobal);
639 tid = start_host_object(pStream, &IID_IClassFactory, (IUnknown*)&Test_ClassFactory, MSHLFLAGS_NORMAL, &thread);
641 ok_more_than_one_lock();
643 IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
644 hr = CoUnmarshalInterface(pStream, &IID_IClassFactory, (void **)&pProxy);
645 ok_ole_success(hr, CoUnmarshalInterface);
646 IStream_Release(pStream);
648 ok_more_than_one_lock();
650 CoUninitialize();
652 ok_no_locks();
654 IUnknown_Release(pProxy);
656 ok_no_locks();
658 end_host_object(tid, thread);
660 pCoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
663 /* tests that proxies are released when the containing mta apartment is destroyed */
664 static void test_marshal_proxy_mta_apartment_shutdown(void)
666 HRESULT hr;
667 IStream *pStream = NULL;
668 IUnknown *pProxy = NULL;
669 DWORD tid;
670 HANDLE thread;
672 CoUninitialize();
673 pCoInitializeEx(NULL, COINIT_MULTITHREADED);
675 cLocks = 0;
677 hr = CreateStreamOnHGlobal(NULL, TRUE, &pStream);
678 ok_ole_success(hr, CreateStreamOnHGlobal);
679 tid = start_host_object(pStream, &IID_IClassFactory, (IUnknown*)&Test_ClassFactory, MSHLFLAGS_NORMAL, &thread);
681 ok_more_than_one_lock();
683 IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
684 hr = CoUnmarshalInterface(pStream, &IID_IClassFactory, (void **)&pProxy);
685 ok_ole_success(hr, CoUnmarshalInterface);
686 IStream_Release(pStream);
688 ok_more_than_one_lock();
690 CoUninitialize();
692 ok_no_locks();
694 IUnknown_Release(pProxy);
696 ok_no_locks();
698 end_host_object(tid, thread);
700 pCoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
703 struct ncu_params
705 LPSTREAM stream;
706 HANDLE marshal_event;
707 HANDLE unmarshal_event;
710 /* helper for test_no_couninitialize_server */
711 static DWORD CALLBACK no_couninitialize_server_proc(LPVOID p)
713 struct ncu_params *ncu_params = (struct ncu_params *)p;
714 HRESULT hr;
716 pCoInitializeEx(NULL, COINIT_MULTITHREADED);
718 hr = CoMarshalInterface(ncu_params->stream, &IID_IClassFactory, (IUnknown*)&Test_ClassFactory, MSHCTX_INPROC, NULL, MSHLFLAGS_NORMAL);
719 ok_ole_success(hr, CoMarshalInterface);
721 SetEvent(ncu_params->marshal_event);
723 WaitForSingleObject(ncu_params->unmarshal_event, INFINITE);
725 /* die without calling CoUninitialize */
727 return 0;
730 /* tests apartment that an apartment with a stub is released without deadlock
731 * if the owning thread exits */
732 static void test_no_couninitialize_server(void)
734 HRESULT hr;
735 IStream *pStream = NULL;
736 IUnknown *pProxy = NULL;
737 DWORD tid;
738 HANDLE thread;
739 struct ncu_params ncu_params;
741 cLocks = 0;
743 ncu_params.marshal_event = CreateEvent(NULL, TRUE, FALSE, NULL);
744 ncu_params.unmarshal_event = CreateEvent(NULL, TRUE, FALSE, NULL);
746 hr = CreateStreamOnHGlobal(NULL, TRUE, &pStream);
747 ok_ole_success(hr, CreateStreamOnHGlobal);
748 ncu_params.stream = pStream;
750 thread = CreateThread(NULL, 0, no_couninitialize_server_proc, &ncu_params, 0, &tid);
752 WaitForSingleObject(ncu_params.marshal_event, INFINITE);
753 ok_more_than_one_lock();
755 IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
756 hr = CoUnmarshalInterface(pStream, &IID_IClassFactory, (void **)&pProxy);
757 ok_ole_success(hr, CoUnmarshalInterface);
758 IStream_Release(pStream);
760 ok_more_than_one_lock();
762 SetEvent(ncu_params.unmarshal_event);
763 WaitForSingleObject(thread, INFINITE);
765 ok_no_locks();
767 CloseHandle(thread);
768 CloseHandle(ncu_params.marshal_event);
769 CloseHandle(ncu_params.unmarshal_event);
771 IUnknown_Release(pProxy);
773 ok_no_locks();
776 /* STA -> STA call during DLL_THREAD_DETACH */
777 static DWORD CALLBACK no_couninitialize_client_proc(LPVOID p)
779 struct ncu_params *ncu_params = (struct ncu_params *)p;
780 HRESULT hr;
781 IUnknown *pProxy = NULL;
783 pCoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
785 hr = CoUnmarshalInterface(ncu_params->stream, &IID_IClassFactory, (void **)&pProxy);
786 ok_ole_success(hr, CoUnmarshalInterface);
787 IStream_Release(ncu_params->stream);
789 ok_more_than_one_lock();
791 /* die without calling CoUninitialize */
793 return 0;
796 /* tests STA -> STA call during DLL_THREAD_DETACH doesn't deadlock */
797 static void test_no_couninitialize_client(void)
799 HRESULT hr;
800 IStream *pStream = NULL;
801 DWORD tid;
802 DWORD host_tid;
803 HANDLE thread;
804 HANDLE host_thread;
805 struct ncu_params ncu_params;
807 cLocks = 0;
809 hr = CreateStreamOnHGlobal(NULL, TRUE, &pStream);
810 ok_ole_success(hr, CreateStreamOnHGlobal);
811 ncu_params.stream = pStream;
813 /* NOTE: assumes start_host_object uses an STA to host the object, as MTAs
814 * always deadlock when called from within DllMain */
815 host_tid = start_host_object(pStream, &IID_IClassFactory, (IUnknown *)&Test_ClassFactory, MSHLFLAGS_NORMAL, &host_thread);
816 IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
818 ok_more_than_one_lock();
820 thread = CreateThread(NULL, 0, no_couninitialize_client_proc, &ncu_params, 0, &tid);
822 WaitForSingleObject(thread, INFINITE);
823 CloseHandle(thread);
825 ok_no_locks();
827 end_host_object(host_tid, host_thread);
830 /* tests success case of a same-thread table-weak marshal, unmarshal, unmarshal */
831 static void test_tableweak_marshal_and_unmarshal_twice(void)
833 HRESULT hr;
834 IStream *pStream = NULL;
835 IUnknown *pProxy1 = NULL;
836 IUnknown *pProxy2 = NULL;
837 DWORD tid;
838 HANDLE thread;
840 cLocks = 0;
842 hr = CreateStreamOnHGlobal(NULL, TRUE, &pStream);
843 ok_ole_success(hr, CreateStreamOnHGlobal);
844 tid = start_host_object(pStream, &IID_IClassFactory, (IUnknown*)&Test_ClassFactory, MSHLFLAGS_TABLEWEAK, &thread);
846 ok_more_than_one_lock();
848 IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
849 hr = CoUnmarshalInterface(pStream, &IID_IClassFactory, (void **)&pProxy1);
850 ok_ole_success(hr, CoUnmarshalInterface);
852 ok_more_than_one_lock();
854 IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
855 hr = CoUnmarshalInterface(pStream, &IID_IClassFactory, (void **)&pProxy2);
856 IStream_Release(pStream);
857 ok_ole_success(hr, CoUnmarshalInterface);
859 ok_more_than_one_lock();
861 IUnknown_Release(pProxy1);
862 IUnknown_Release(pProxy2);
864 /* this line is shows the difference between weak and strong table marshaling:
865 * weak has cLocks == 0
866 * strong has cLocks > 0 */
867 ok_no_locks();
869 end_host_object(tid, thread);
872 /* tests releasing after unmarshaling one object */
873 static void test_tableweak_marshal_releasedata1(void)
875 HRESULT hr;
876 IStream *pStream = NULL;
877 IUnknown *pProxy1 = NULL;
878 IUnknown *pProxy2 = NULL;
879 DWORD tid;
880 HANDLE thread;
882 cLocks = 0;
884 hr = CreateStreamOnHGlobal(NULL, TRUE, &pStream);
885 ok_ole_success(hr, CreateStreamOnHGlobal);
886 tid = start_host_object(pStream, &IID_IClassFactory, (IUnknown*)&Test_ClassFactory, MSHLFLAGS_TABLEWEAK, &thread);
888 ok_more_than_one_lock();
890 IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
891 hr = CoUnmarshalInterface(pStream, &IID_IClassFactory, (void **)&pProxy1);
892 ok_ole_success(hr, CoUnmarshalInterface);
894 ok_more_than_one_lock();
896 /* release the remaining reference on the object by calling
897 * CoReleaseMarshalData in the hosting thread */
898 IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
899 release_host_object(tid);
901 ok_more_than_one_lock();
903 IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
904 hr = CoUnmarshalInterface(pStream, &IID_IClassFactory, (void **)&pProxy2);
905 ok_ole_success(hr, CoUnmarshalInterface);
906 IStream_Release(pStream);
908 ok_more_than_one_lock();
910 IUnknown_Release(pProxy1);
911 if (pProxy2)
912 IUnknown_Release(pProxy2);
914 /* this line is shows the difference between weak and strong table marshaling:
915 * weak has cLocks == 0
916 * strong has cLocks > 0 */
917 ok_no_locks();
919 end_host_object(tid, thread);
922 /* tests releasing after unmarshaling one object */
923 static void test_tableweak_marshal_releasedata2(void)
925 HRESULT hr;
926 IStream *pStream = NULL;
927 IUnknown *pProxy = NULL;
928 DWORD tid;
929 HANDLE thread;
931 cLocks = 0;
933 hr = CreateStreamOnHGlobal(NULL, TRUE, &pStream);
934 ok_ole_success(hr, CreateStreamOnHGlobal);
935 tid = start_host_object(pStream, &IID_IClassFactory, (IUnknown*)&Test_ClassFactory, MSHLFLAGS_TABLEWEAK, &thread);
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);
944 ok_no_locks();
946 IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
947 hr = CoUnmarshalInterface(pStream, &IID_IClassFactory, (void **)&pProxy);
948 todo_wine
950 ok(hr == CO_E_OBJNOTREG,
951 "CoUnmarshalInterface should have failed with CO_E_OBJNOTREG, but returned 0x%08x instead\n",
952 hr);
954 IStream_Release(pStream);
956 ok_no_locks();
958 end_host_object(tid, thread);
961 /* tests success case of a same-thread table-strong marshal, unmarshal, unmarshal */
962 static void test_tablestrong_marshal_and_unmarshal_twice(void)
964 HRESULT hr;
965 IStream *pStream = NULL;
966 IUnknown *pProxy1 = NULL;
967 IUnknown *pProxy2 = NULL;
968 DWORD tid;
969 HANDLE thread;
971 cLocks = 0;
973 hr = CreateStreamOnHGlobal(NULL, TRUE, &pStream);
974 ok_ole_success(hr, CreateStreamOnHGlobal);
975 tid = start_host_object(pStream, &IID_IClassFactory, (IUnknown*)&Test_ClassFactory, MSHLFLAGS_TABLESTRONG, &thread);
977 ok_more_than_one_lock();
979 IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
980 hr = CoUnmarshalInterface(pStream, &IID_IClassFactory, (void **)&pProxy1);
981 ok_ole_success(hr, CoUnmarshalInterface);
983 ok_more_than_one_lock();
985 IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
986 hr = CoUnmarshalInterface(pStream, &IID_IClassFactory, (void **)&pProxy2);
987 ok_ole_success(hr, CoUnmarshalInterface);
989 ok_more_than_one_lock();
991 if (pProxy1) IUnknown_Release(pProxy1);
992 if (pProxy2) IUnknown_Release(pProxy2);
994 /* this line is shows the difference between weak and strong table marshaling:
995 * weak has cLocks == 0
996 * strong has cLocks > 0 */
997 ok_more_than_one_lock();
999 /* release the remaining reference on the object by calling
1000 * CoReleaseMarshalData in the hosting thread */
1001 IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
1002 release_host_object(tid);
1003 IStream_Release(pStream);
1005 ok_no_locks();
1007 end_host_object(tid, thread);
1010 /* tests CoLockObjectExternal */
1011 static void test_lock_object_external(void)
1013 HRESULT hr;
1014 IStream *pStream = NULL;
1016 cLocks = 0;
1018 /* test the stub manager creation aspect of CoLockObjectExternal when the
1019 * object hasn't been marshaled yet */
1020 CoLockObjectExternal((IUnknown*)&Test_ClassFactory, TRUE, TRUE);
1022 ok_more_than_one_lock();
1024 CoDisconnectObject((IUnknown*)&Test_ClassFactory, 0);
1026 ok_no_locks();
1028 /* test our empty stub manager being handled correctly in
1029 * CoMarshalInterface */
1030 CoLockObjectExternal((IUnknown*)&Test_ClassFactory, TRUE, TRUE);
1032 hr = CreateStreamOnHGlobal(NULL, TRUE, &pStream);
1033 ok_ole_success(hr, CreateStreamOnHGlobal);
1034 hr = CoMarshalInterface(pStream, &IID_IClassFactory, (IUnknown*)&Test_ClassFactory, MSHCTX_INPROC, NULL, MSHLFLAGS_NORMAL);
1035 ok_ole_success(hr, CoMarshalInterface);
1037 CoLockObjectExternal((IUnknown*)&Test_ClassFactory, TRUE, TRUE);
1039 ok_more_than_one_lock();
1041 IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
1042 hr = CoReleaseMarshalData(pStream);
1043 ok_ole_success(hr, CoReleaseMarshalData);
1044 IStream_Release(pStream);
1046 ok_more_than_one_lock();
1048 CoLockObjectExternal((IUnknown*)&Test_ClassFactory, FALSE, TRUE);
1050 ok_more_than_one_lock();
1052 CoLockObjectExternal((IUnknown*)&Test_ClassFactory, FALSE, TRUE);
1054 ok_no_locks();
1057 /* tests disconnecting stubs */
1058 static void test_disconnect_stub(void)
1060 HRESULT hr;
1061 IStream *pStream = NULL;
1063 cLocks = 0;
1065 hr = CreateStreamOnHGlobal(NULL, TRUE, &pStream);
1066 ok_ole_success(hr, CreateStreamOnHGlobal);
1067 hr = CoMarshalInterface(pStream, &IID_IClassFactory, (IUnknown*)&Test_ClassFactory, MSHCTX_INPROC, NULL, MSHLFLAGS_NORMAL);
1068 ok_ole_success(hr, CoMarshalInterface);
1070 CoLockObjectExternal((IUnknown*)&Test_ClassFactory, TRUE, TRUE);
1072 ok_more_than_one_lock();
1074 IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
1075 hr = CoReleaseMarshalData(pStream);
1076 ok_ole_success(hr, CoReleaseMarshalData);
1077 IStream_Release(pStream);
1079 ok_more_than_one_lock();
1081 CoDisconnectObject((IUnknown*)&Test_ClassFactory, 0);
1083 ok_no_locks();
1086 /* tests failure case of a same-thread marshal and unmarshal twice */
1087 static void test_normal_marshal_and_unmarshal_twice(void)
1089 HRESULT hr;
1090 IStream *pStream = NULL;
1091 IUnknown *pProxy1 = NULL;
1092 IUnknown *pProxy2 = NULL;
1094 cLocks = 0;
1096 hr = CreateStreamOnHGlobal(NULL, TRUE, &pStream);
1097 ok_ole_success(hr, CreateStreamOnHGlobal);
1098 hr = CoMarshalInterface(pStream, &IID_IClassFactory, (IUnknown*)&Test_ClassFactory, MSHCTX_INPROC, NULL, MSHLFLAGS_NORMAL);
1099 ok_ole_success(hr, CoMarshalInterface);
1101 ok_more_than_one_lock();
1103 IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
1104 hr = CoUnmarshalInterface(pStream, &IID_IClassFactory, (void **)&pProxy1);
1105 ok_ole_success(hr, CoUnmarshalInterface);
1107 ok_more_than_one_lock();
1109 IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
1110 hr = CoUnmarshalInterface(pStream, &IID_IClassFactory, (void **)&pProxy2);
1111 ok(hr == CO_E_OBJNOTCONNECTED,
1112 "CoUnmarshalInterface should have failed with error CO_E_OBJNOTCONNECTED for double unmarshal, instead of 0x%08x\n", hr);
1114 IStream_Release(pStream);
1116 ok_more_than_one_lock();
1118 IUnknown_Release(pProxy1);
1120 ok_no_locks();
1123 /* tests success case of marshaling and unmarshaling an HRESULT */
1124 static void test_hresult_marshaling(void)
1126 HRESULT hr;
1127 HRESULT hr_marshaled = 0;
1128 IStream *pStream = NULL;
1129 static const HRESULT E_DEADBEEF = 0xdeadbeef;
1131 hr = CreateStreamOnHGlobal(NULL, TRUE, &pStream);
1132 ok_ole_success(hr, CreateStreamOnHGlobal);
1134 hr = CoMarshalHresult(pStream, E_DEADBEEF);
1135 ok_ole_success(hr, CoMarshalHresult);
1137 IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
1138 hr = IStream_Read(pStream, &hr_marshaled, sizeof(HRESULT), NULL);
1139 ok_ole_success(hr, IStream_Read);
1141 ok(hr_marshaled == E_DEADBEEF, "Didn't marshal HRESULT as expected: got value 0x%08x instead\n", hr_marshaled);
1143 hr_marshaled = 0;
1144 IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
1145 hr = CoUnmarshalHresult(pStream, &hr_marshaled);
1146 ok_ole_success(hr, CoUnmarshalHresult);
1148 ok(hr_marshaled == E_DEADBEEF, "Didn't marshal HRESULT as expected: got value 0x%08x instead\n", hr_marshaled);
1150 IStream_Release(pStream);
1154 /* helper for test_proxy_used_in_wrong_thread */
1155 static DWORD CALLBACK bad_thread_proc(LPVOID p)
1157 IClassFactory * cf = (IClassFactory *)p;
1158 HRESULT hr;
1159 IUnknown * proxy = NULL;
1161 pCoInitializeEx(NULL, COINIT_MULTITHREADED);
1163 hr = IClassFactory_CreateInstance(cf, NULL, &IID_IUnknown, (LPVOID*)&proxy);
1164 if (proxy) IUnknown_Release(proxy);
1165 ok(hr == RPC_E_WRONG_THREAD,
1166 "COM should have failed with RPC_E_WRONG_THREAD on using proxy from wrong apartment, but instead returned 0x%08x\n",
1167 hr);
1169 CoUninitialize();
1171 return 0;
1174 /* tests failure case of a using a proxy in the wrong apartment */
1175 static void test_proxy_used_in_wrong_thread(void)
1177 HRESULT hr;
1178 IStream *pStream = NULL;
1179 IUnknown *pProxy = NULL;
1180 DWORD tid, tid2;
1181 HANDLE thread;
1182 HANDLE host_thread;
1184 cLocks = 0;
1186 hr = CreateStreamOnHGlobal(NULL, TRUE, &pStream);
1187 ok_ole_success(hr, CreateStreamOnHGlobal);
1188 tid = start_host_object(pStream, &IID_IClassFactory, (IUnknown*)&Test_ClassFactory, MSHLFLAGS_NORMAL, &host_thread);
1190 ok_more_than_one_lock();
1192 IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
1193 hr = CoUnmarshalInterface(pStream, &IID_IClassFactory, (void **)&pProxy);
1194 ok_ole_success(hr, CoUnmarshalInterface);
1195 IStream_Release(pStream);
1197 ok_more_than_one_lock();
1199 /* create a thread that we can misbehave in */
1200 thread = CreateThread(NULL, 0, bad_thread_proc, (LPVOID)pProxy, 0, &tid2);
1202 WaitForSingleObject(thread, INFINITE);
1203 CloseHandle(thread);
1205 IUnknown_Release(pProxy);
1207 ok_no_locks();
1209 end_host_object(tid, host_thread);
1212 static HRESULT WINAPI MessageFilter_QueryInterface(IMessageFilter *iface, REFIID riid, void ** ppvObj)
1214 if (ppvObj == NULL) return E_POINTER;
1216 if (IsEqualGUID(riid, &IID_IUnknown) ||
1217 IsEqualGUID(riid, &IID_IClassFactory))
1219 *ppvObj = (LPVOID)iface;
1220 IClassFactory_AddRef(iface);
1221 return S_OK;
1224 return E_NOINTERFACE;
1227 static ULONG WINAPI MessageFilter_AddRef(IMessageFilter *iface)
1229 return 2; /* non-heap object */
1232 static ULONG WINAPI MessageFilter_Release(IMessageFilter *iface)
1234 return 1; /* non-heap object */
1237 static DWORD WINAPI MessageFilter_HandleInComingCall(
1238 IMessageFilter *iface,
1239 DWORD dwCallType,
1240 HTASK threadIDCaller,
1241 DWORD dwTickCount,
1242 LPINTERFACEINFO lpInterfaceInfo)
1244 static int callcount = 0;
1245 DWORD ret;
1246 trace("HandleInComingCall\n");
1247 switch (callcount)
1249 case 0:
1250 ret = SERVERCALL_REJECTED;
1251 break;
1252 case 1:
1253 ret = SERVERCALL_RETRYLATER;
1254 break;
1255 default:
1256 ret = SERVERCALL_ISHANDLED;
1257 break;
1259 callcount++;
1260 return ret;
1263 static DWORD WINAPI MessageFilter_RetryRejectedCall(
1264 IMessageFilter *iface,
1265 HTASK threadIDCallee,
1266 DWORD dwTickCount,
1267 DWORD dwRejectType)
1269 trace("RetryRejectedCall\n");
1270 return 0;
1273 static DWORD WINAPI MessageFilter_MessagePending(
1274 IMessageFilter *iface,
1275 HTASK threadIDCallee,
1276 DWORD dwTickCount,
1277 DWORD dwPendingType)
1279 trace("MessagePending\n");
1280 return PENDINGMSG_WAITNOPROCESS;
1283 static const IMessageFilterVtbl MessageFilter_Vtbl =
1285 MessageFilter_QueryInterface,
1286 MessageFilter_AddRef,
1287 MessageFilter_Release,
1288 MessageFilter_HandleInComingCall,
1289 MessageFilter_RetryRejectedCall,
1290 MessageFilter_MessagePending
1293 static IMessageFilter MessageFilter = { &MessageFilter_Vtbl };
1295 static void test_message_filter(void)
1297 HRESULT hr;
1298 IStream *pStream = NULL;
1299 IClassFactory *cf = NULL;
1300 DWORD tid;
1301 IUnknown *proxy = NULL;
1302 IMessageFilter *prev_filter = NULL;
1303 HANDLE thread;
1305 cLocks = 0;
1307 hr = CreateStreamOnHGlobal(NULL, TRUE, &pStream);
1308 ok_ole_success(hr, CreateStreamOnHGlobal);
1309 tid = start_host_object2(pStream, &IID_IClassFactory, (IUnknown*)&Test_ClassFactory, MSHLFLAGS_NORMAL, &MessageFilter, &thread);
1311 ok_more_than_one_lock();
1313 IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
1314 hr = CoUnmarshalInterface(pStream, &IID_IClassFactory, (void **)&cf);
1315 ok_ole_success(hr, CoUnmarshalInterface);
1316 IStream_Release(pStream);
1318 ok_more_than_one_lock();
1320 hr = IClassFactory_CreateInstance(cf, NULL, &IID_IUnknown, (LPVOID*)&proxy);
1321 ok(hr == RPC_E_CALL_REJECTED, "Call should have returned RPC_E_CALL_REJECTED, but return 0x%08x instead\n", hr);
1322 if (proxy) IUnknown_Release(proxy);
1323 proxy = NULL;
1325 hr = CoRegisterMessageFilter(&MessageFilter, &prev_filter);
1326 ok_ole_success(hr, CoRegisterMessageFilter);
1328 hr = IClassFactory_CreateInstance(cf, NULL, &IID_IUnknown, (LPVOID*)&proxy);
1329 ok_ole_success(hr, IClassFactory_CreateInstance);
1331 IUnknown_Release(proxy);
1333 IClassFactory_Release(cf);
1335 ok_no_locks();
1337 end_host_object(tid, thread);
1339 hr = CoRegisterMessageFilter(prev_filter, NULL);
1340 ok_ole_success(hr, CoRegisterMessageFilter);
1343 /* test failure case of trying to unmarshal from bad stream */
1344 static void test_bad_marshal_stream(void)
1346 HRESULT hr;
1347 IStream *pStream = NULL;
1349 hr = CreateStreamOnHGlobal(NULL, TRUE, &pStream);
1350 ok_ole_success(hr, CreateStreamOnHGlobal);
1351 hr = CoMarshalInterface(pStream, &IID_IClassFactory, (IUnknown*)&Test_ClassFactory, MSHCTX_INPROC, NULL, MSHLFLAGS_NORMAL);
1352 ok_ole_success(hr, CoMarshalInterface);
1354 ok_more_than_one_lock();
1356 /* try to read beyond end of stream */
1357 hr = CoReleaseMarshalData(pStream);
1358 ok(hr == STG_E_READFAULT, "Should have failed with STG_E_READFAULT, but returned 0x%08x instead\n", hr);
1360 /* now release for real */
1361 IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
1362 hr = CoReleaseMarshalData(pStream);
1363 ok_ole_success(hr, CoReleaseMarshalData);
1365 IStream_Release(pStream);
1368 /* tests that proxies implement certain interfaces */
1369 static void test_proxy_interfaces(void)
1371 HRESULT hr;
1372 IStream *pStream = NULL;
1373 IUnknown *pProxy = NULL;
1374 IUnknown *pOtherUnknown = NULL;
1375 DWORD tid;
1376 HANDLE thread;
1378 cLocks = 0;
1380 hr = CreateStreamOnHGlobal(NULL, TRUE, &pStream);
1381 ok_ole_success(hr, CreateStreamOnHGlobal);
1382 tid = start_host_object(pStream, &IID_IClassFactory, (IUnknown*)&Test_ClassFactory, MSHLFLAGS_NORMAL, &thread);
1384 ok_more_than_one_lock();
1386 IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
1387 hr = CoUnmarshalInterface(pStream, &IID_IUnknown, (void **)&pProxy);
1388 ok_ole_success(hr, CoUnmarshalInterface);
1389 IStream_Release(pStream);
1391 ok_more_than_one_lock();
1393 hr = IUnknown_QueryInterface(pProxy, &IID_IUnknown, (LPVOID*)&pOtherUnknown);
1394 ok_ole_success(hr, IUnknown_QueryInterface IID_IUnknown);
1395 if (hr == S_OK) IUnknown_Release(pOtherUnknown);
1397 hr = IUnknown_QueryInterface(pProxy, &IID_IClientSecurity, (LPVOID*)&pOtherUnknown);
1398 todo_wine { ok_ole_success(hr, IUnknown_QueryInterface IID_IClientSecurity); }
1399 if (hr == S_OK) IUnknown_Release(pOtherUnknown);
1401 hr = IUnknown_QueryInterface(pProxy, &IID_IMultiQI, (LPVOID*)&pOtherUnknown);
1402 ok_ole_success(hr, IUnknown_QueryInterface IID_IMultiQI);
1403 if (hr == S_OK) IUnknown_Release(pOtherUnknown);
1405 hr = IUnknown_QueryInterface(pProxy, &IID_IMarshal, (LPVOID*)&pOtherUnknown);
1406 ok_ole_success(hr, IUnknown_QueryInterface IID_IMarshal);
1407 if (hr == S_OK) IUnknown_Release(pOtherUnknown);
1409 /* IMarshal2 is also supported on NT-based systems, but is pretty much
1410 * useless as it has no more methods over IMarshal that it inherits from. */
1412 IUnknown_Release(pProxy);
1414 ok_no_locks();
1416 end_host_object(tid, thread);
1419 typedef struct
1421 const IUnknownVtbl *lpVtbl;
1422 ULONG refs;
1423 } HeapUnknown;
1425 static HRESULT WINAPI HeapUnknown_QueryInterface(IUnknown *iface, REFIID riid, void **ppv)
1427 if (IsEqualIID(riid, &IID_IUnknown))
1429 IUnknown_AddRef(iface);
1430 *ppv = (LPVOID)iface;
1431 return S_OK;
1433 *ppv = NULL;
1434 return E_NOINTERFACE;
1437 static ULONG WINAPI HeapUnknown_AddRef(IUnknown *iface)
1439 HeapUnknown *This = (HeapUnknown *)iface;
1440 trace("HeapUnknown_AddRef(%p)\n", iface);
1441 return InterlockedIncrement((LONG*)&This->refs);
1444 static ULONG WINAPI HeapUnknown_Release(IUnknown *iface)
1446 HeapUnknown *This = (HeapUnknown *)iface;
1447 ULONG refs = InterlockedDecrement((LONG*)&This->refs);
1448 trace("HeapUnknown_Release(%p)\n", iface);
1449 if (!refs) HeapFree(GetProcessHeap(), 0, This);
1450 return refs;
1453 static const IUnknownVtbl HeapUnknown_Vtbl =
1455 HeapUnknown_QueryInterface,
1456 HeapUnknown_AddRef,
1457 HeapUnknown_Release
1460 static void test_proxybuffer(REFIID riid)
1462 HRESULT hr;
1463 IPSFactoryBuffer *psfb;
1464 IRpcProxyBuffer *proxy;
1465 LPVOID lpvtbl;
1466 ULONG refs;
1467 CLSID clsid;
1468 HeapUnknown *pUnkOuter = (HeapUnknown *)HeapAlloc(GetProcessHeap(), 0, sizeof(*pUnkOuter));
1470 pUnkOuter->lpVtbl = &HeapUnknown_Vtbl;
1471 pUnkOuter->refs = 1;
1473 hr = CoGetPSClsid(riid, &clsid);
1474 ok_ole_success(hr, CoGetPSClsid);
1476 hr = CoGetClassObject(&clsid, CLSCTX_INPROC_SERVER, NULL, &IID_IPSFactoryBuffer, (LPVOID*)&psfb);
1477 ok_ole_success(hr, CoGetClassObject);
1479 hr = IPSFactoryBuffer_CreateProxy(psfb, (IUnknown*)pUnkOuter, riid, &proxy, &lpvtbl);
1480 ok_ole_success(hr, IPSFactoryBuffer_CreateProxy);
1481 ok(lpvtbl != NULL, "IPSFactoryBuffer_CreateProxy succeeded, but returned a NULL vtable!\n");
1483 /* release our reference to the outer unknown object - the PS factory
1484 * buffer will have AddRef's it in the CreateProxy call */
1485 refs = IUnknown_Release((IUnknown *)pUnkOuter);
1486 ok(refs == 1, "Ref count of outer unknown should have been 1 instead of %d\n", refs);
1488 refs = IPSFactoryBuffer_Release(psfb);
1489 if (0)
1491 /* not reliable on native. maybe it leaks references! */
1492 ok(refs == 0, "Ref-count leak of %d on IPSFactoryBuffer\n", refs);
1495 refs = IUnknown_Release((IUnknown *)lpvtbl);
1496 ok(refs == 0, "Ref-count leak of %d on IRpcProxyBuffer\n", refs);
1498 refs = IRpcProxyBuffer_Release(proxy);
1499 ok(refs == 0, "Ref-count leak of %d on IRpcProxyBuffer\n", refs);
1502 static void test_stubbuffer(REFIID riid)
1504 HRESULT hr;
1505 IPSFactoryBuffer *psfb;
1506 IRpcStubBuffer *stub;
1507 ULONG refs;
1508 CLSID clsid;
1510 cLocks = 0;
1512 hr = CoGetPSClsid(riid, &clsid);
1513 ok_ole_success(hr, CoGetPSClsid);
1515 hr = CoGetClassObject(&clsid, CLSCTX_INPROC_SERVER, NULL, &IID_IPSFactoryBuffer, (LPVOID*)&psfb);
1516 ok_ole_success(hr, CoGetClassObject);
1518 hr = IPSFactoryBuffer_CreateStub(psfb, riid, (IUnknown*)&Test_ClassFactory, &stub);
1519 ok_ole_success(hr, IPSFactoryBuffer_CreateStub);
1521 refs = IPSFactoryBuffer_Release(psfb);
1522 if (0)
1524 /* not reliable on native. maybe it leaks references */
1525 ok(refs == 0, "Ref-count leak of %d on IPSFactoryBuffer\n", refs);
1528 ok_more_than_one_lock();
1530 IRpcStubBuffer_Disconnect(stub);
1532 ok_no_locks();
1534 refs = IRpcStubBuffer_Release(stub);
1535 ok(refs == 0, "Ref-count leak of %d on IRpcProxyBuffer\n", refs);
1538 static HWND hwnd_app;
1540 static HRESULT WINAPI TestRE_IClassFactory_CreateInstance(
1541 LPCLASSFACTORY iface,
1542 LPUNKNOWN pUnkOuter,
1543 REFIID riid,
1544 LPVOID *ppvObj)
1546 DWORD_PTR res;
1547 if (IsEqualIID(riid, &IID_IWineTest))
1549 BOOL ret = SendMessageTimeout(hwnd_app, WM_NULL, 0, 0, SMTO_BLOCK, 5000, &res);
1550 ok(ret, "Timed out sending a message to originating window during RPC call\n");
1552 return S_FALSE;
1555 static const IClassFactoryVtbl TestREClassFactory_Vtbl =
1557 Test_IClassFactory_QueryInterface,
1558 Test_IClassFactory_AddRef,
1559 Test_IClassFactory_Release,
1560 TestRE_IClassFactory_CreateInstance,
1561 Test_IClassFactory_LockServer
1564 IClassFactory TestRE_ClassFactory = { &TestREClassFactory_Vtbl };
1566 static LRESULT CALLBACK window_proc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam)
1568 switch (msg)
1570 case WM_USER:
1572 HRESULT hr;
1573 IStream *pStream = NULL;
1574 IClassFactory *proxy = NULL;
1575 IUnknown *object;
1576 DWORD tid;
1577 HANDLE thread;
1579 cLocks = 0;
1581 hr = CreateStreamOnHGlobal(NULL, TRUE, &pStream);
1582 ok_ole_success(hr, CreateStreamOnHGlobal);
1583 tid = start_host_object(pStream, &IID_IClassFactory, (IUnknown*)&TestRE_ClassFactory, MSHLFLAGS_NORMAL, &thread);
1585 ok_more_than_one_lock();
1587 IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
1588 hr = CoUnmarshalInterface(pStream, &IID_IClassFactory, (void **)&proxy);
1589 ok_ole_success(hr, CoReleaseMarshalData);
1590 IStream_Release(pStream);
1592 ok_more_than_one_lock();
1594 /* note the use of the magic IID_IWineTest value to tell remote thread
1595 * to try to send a message back to us */
1596 hr = IClassFactory_CreateInstance(proxy, NULL, &IID_IWineTest, (void **)&object);
1598 IClassFactory_Release(proxy);
1600 ok_no_locks();
1602 end_host_object(tid, thread);
1604 PostMessage(hwnd, WM_QUIT, 0, 0);
1606 return 0;
1608 case WM_USER+1:
1610 HRESULT hr;
1611 IStream *pStream = NULL;
1612 IClassFactory *proxy = NULL;
1613 IUnknown *object;
1614 DWORD tid;
1615 HANDLE thread;
1617 cLocks = 0;
1619 hr = CreateStreamOnHGlobal(NULL, TRUE, &pStream);
1620 ok_ole_success(hr, CreateStreamOnHGlobal);
1621 tid = start_host_object(pStream, &IID_IClassFactory, (IUnknown*)&TestRE_ClassFactory, MSHLFLAGS_NORMAL, &thread);
1623 ok_more_than_one_lock();
1625 IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
1626 hr = CoUnmarshalInterface(pStream, &IID_IClassFactory, (void **)&proxy);
1627 ok_ole_success(hr, CoReleaseMarshalData);
1628 IStream_Release(pStream);
1630 ok_more_than_one_lock();
1632 /* post quit message before a doing a COM call to show that a pending
1633 * WM_QUIT message doesn't stop the call from succeeding */
1634 PostMessage(hwnd, WM_QUIT, 0, 0);
1635 hr = IClassFactory_CreateInstance(proxy, NULL, &IID_IUnknown, (void **)&object);
1637 IClassFactory_Release(proxy);
1639 ok_no_locks();
1641 end_host_object(tid, thread);
1643 return 0;
1645 case WM_USER+2:
1647 HRESULT hr;
1648 IStream *pStream = NULL;
1649 IClassFactory *proxy = NULL;
1650 IUnknown *object;
1651 DWORD tid;
1652 HANDLE thread;
1654 hr = CreateStreamOnHGlobal(NULL, TRUE, &pStream);
1655 ok_ole_success(hr, CreateStreamOnHGlobal);
1656 tid = start_host_object(pStream, &IID_IClassFactory, (IUnknown*)&Test_ClassFactory, MSHLFLAGS_NORMAL, &thread);
1658 IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
1659 hr = CoUnmarshalInterface(pStream, &IID_IClassFactory, (void **)&proxy);
1660 ok_ole_success(hr, CoReleaseMarshalData);
1661 IStream_Release(pStream);
1663 /* shows that COM calls executed during the processing of sent
1664 * messages should fail */
1665 hr = IClassFactory_CreateInstance(proxy, NULL, &IID_IUnknown, (void **)&object);
1666 ok(hr == RPC_E_CANTCALLOUT_ININPUTSYNCCALL,
1667 "COM call during processing of sent message should return RPC_E_CANTCALLOUT_ININPUTSYNCCALL instead of 0x%08x\n", hr);
1669 IClassFactory_Release(proxy);
1671 end_host_object(tid, thread);
1673 PostQuitMessage(0);
1675 return 0;
1677 default:
1678 return DefWindowProc(hwnd, msg, wparam, lparam);
1682 static void test_message_reentrancy(void)
1684 WNDCLASS wndclass;
1685 MSG msg;
1687 memset(&wndclass, 0, sizeof(wndclass));
1688 wndclass.lpfnWndProc = window_proc;
1689 wndclass.lpszClassName = "WineCOMTest";
1690 RegisterClass(&wndclass);
1692 hwnd_app = CreateWindow("WineCOMTest", NULL, 0, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, NULL, NULL, NULL, 0);
1693 ok(hwnd_app != NULL, "Window creation failed\n");
1695 /* start message re-entrancy test */
1696 PostMessage(hwnd_app, WM_USER, 0, 0);
1698 while (GetMessage(&msg, NULL, 0, 0))
1700 TranslateMessage(&msg);
1701 DispatchMessage(&msg);
1705 static HRESULT WINAPI TestMsg_IClassFactory_CreateInstance(
1706 LPCLASSFACTORY iface,
1707 LPUNKNOWN pUnkOuter,
1708 REFIID riid,
1709 LPVOID *ppvObj)
1711 *ppvObj = NULL;
1712 SendMessage(hwnd_app, WM_USER+2, 0, 0);
1713 return S_OK;
1716 static IClassFactoryVtbl TestMsgClassFactory_Vtbl =
1718 Test_IClassFactory_QueryInterface,
1719 Test_IClassFactory_AddRef,
1720 Test_IClassFactory_Release,
1721 TestMsg_IClassFactory_CreateInstance,
1722 Test_IClassFactory_LockServer
1725 IClassFactory TestMsg_ClassFactory = { &TestMsgClassFactory_Vtbl };
1727 static void test_call_from_message(void)
1729 MSG msg;
1730 IStream *pStream;
1731 HRESULT hr;
1732 IClassFactory *proxy;
1733 DWORD tid;
1734 HANDLE thread;
1735 IUnknown *object;
1737 hwnd_app = CreateWindow("WineCOMTest", NULL, 0, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, NULL, NULL, NULL, 0);
1738 ok(hwnd_app != NULL, "Window creation failed\n");
1740 hr = CreateStreamOnHGlobal(NULL, TRUE, &pStream);
1741 ok_ole_success(hr, CreateStreamOnHGlobal);
1742 tid = start_host_object(pStream, &IID_IClassFactory, (IUnknown*)&TestMsg_ClassFactory, MSHLFLAGS_NORMAL, &thread);
1744 ok_more_than_one_lock();
1746 IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
1747 hr = CoUnmarshalInterface(pStream, &IID_IClassFactory, (void **)&proxy);
1748 ok_ole_success(hr, CoReleaseMarshalData);
1749 IStream_Release(pStream);
1751 ok_more_than_one_lock();
1753 /* start message re-entrancy test */
1754 hr = IClassFactory_CreateInstance(proxy, NULL, &IID_IUnknown, (void **)&object);
1755 ok_ole_success(hr, IClassFactory_CreateInstance);
1757 IClassFactory_Release(proxy);
1759 ok_no_locks();
1761 end_host_object(tid, thread);
1763 while (GetMessage(&msg, NULL, 0, 0))
1765 TranslateMessage(&msg);
1766 DispatchMessage(&msg);
1770 static void test_WM_QUIT_handling(void)
1772 MSG msg;
1774 hwnd_app = CreateWindow("WineCOMTest", NULL, 0, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, NULL, NULL, NULL, 0);
1775 ok(hwnd_app != NULL, "Window creation failed\n");
1777 /* start WM_QUIT handling test */
1778 PostMessage(hwnd_app, WM_USER+1, 0, 0);
1780 while (GetMessage(&msg, NULL, 0, 0))
1782 TranslateMessage(&msg);
1783 DispatchMessage(&msg);
1787 static void test_freethreadedmarshaldata(IStream *pStream, MSHCTX mshctx, void *ptr, DWORD mshlflags)
1789 HGLOBAL hglobal;
1790 DWORD size;
1791 char *marshal_data;
1792 HRESULT hr;
1794 hr = GetHGlobalFromStream(pStream, &hglobal);
1795 ok_ole_success(hr, GetHGlobalFromStream);
1797 size = GlobalSize(hglobal);
1799 marshal_data = (char *)GlobalLock(hglobal);
1801 if (mshctx == MSHCTX_INPROC)
1803 DWORD expected_size = sizeof(DWORD) + sizeof(void *) + sizeof(DWORD) + sizeof(GUID);
1804 ok(size == expected_size, "size should have been %d instead of %d\n", expected_size, size);
1806 ok(*(DWORD *)marshal_data == mshlflags, "expected 0x%x, but got 0x%x for mshctx\n", mshlflags, *(DWORD *)marshal_data);
1807 marshal_data += sizeof(DWORD);
1808 ok(*(void **)marshal_data == ptr, "expected %p, but got %p for mshctx\n", ptr, *(void **)marshal_data);
1809 marshal_data += sizeof(void *);
1810 ok(*(DWORD *)marshal_data == 0, "expected 0x0, but got 0x%x\n", *(DWORD *)marshal_data);
1811 marshal_data += sizeof(DWORD);
1812 trace("got guid data: {%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x}\n",
1813 ((GUID *)marshal_data)->Data1, ((GUID *)marshal_data)->Data2, ((GUID *)marshal_data)->Data3,
1814 ((GUID *)marshal_data)->Data4[0], ((GUID *)marshal_data)->Data4[1], ((GUID *)marshal_data)->Data4[2], ((GUID *)marshal_data)->Data4[3],
1815 ((GUID *)marshal_data)->Data4[4], ((GUID *)marshal_data)->Data4[5], ((GUID *)marshal_data)->Data4[6], ((GUID *)marshal_data)->Data4[7]);
1817 else
1819 ok(size > sizeof(DWORD), "size should have been > sizeof(DWORD), not %d\n", size);
1820 ok(*(DWORD *)marshal_data == 0x574f454d /* MEOW */,
1821 "marshal data should be filled by standard marshal and start with MEOW signature\n");
1824 GlobalUnlock(hglobal);
1827 static void test_freethreadedmarshaler(void)
1829 HRESULT hr;
1830 IUnknown *pFTUnknown;
1831 IMarshal *pFTMarshal;
1832 IStream *pStream;
1833 IUnknown *pProxy;
1834 static const LARGE_INTEGER llZero;
1836 cLocks = 0;
1837 hr = CoCreateFreeThreadedMarshaler(NULL, &pFTUnknown);
1838 ok_ole_success(hr, CoCreateFreeThreadedMarshaler);
1839 hr = IUnknown_QueryInterface(pFTUnknown, &IID_IMarshal, (void **)&pFTMarshal);
1840 ok_ole_success(hr, IUnknown_QueryInterface);
1841 IUnknown_Release(pFTUnknown);
1843 hr = CreateStreamOnHGlobal(NULL, TRUE, &pStream);
1844 ok_ole_success(hr, CreateStreamOnHGlobal);
1846 /* inproc normal marshaling */
1848 hr = IMarshal_MarshalInterface(pFTMarshal, pStream, &IID_IClassFactory,
1849 (IUnknown*)&Test_ClassFactory, MSHCTX_INPROC, NULL, MSHLFLAGS_NORMAL);
1850 ok_ole_success(hr, IMarshal_MarshalInterface);
1852 ok_more_than_one_lock();
1854 test_freethreadedmarshaldata(pStream, MSHCTX_INPROC, &Test_ClassFactory, MSHLFLAGS_NORMAL);
1856 IStream_Seek(pStream, llZero, STREAM_SEEK_SET, NULL);
1857 hr = IMarshal_UnmarshalInterface(pFTMarshal, pStream, &IID_IUnknown, (void **)&pProxy);
1858 ok_ole_success(hr, IMarshal_UnmarshalInterface);
1860 IUnknown_Release(pProxy);
1862 ok_no_locks();
1864 /* native doesn't allow us to unmarshal or release the stream data,
1865 * presumably because it wants us to call CoMarshalInterface instead */
1866 if (0)
1868 /* local normal marshaling */
1870 IStream_Seek(pStream, llZero, STREAM_SEEK_SET, NULL);
1871 hr = IMarshal_MarshalInterface(pFTMarshal, pStream, &IID_IClassFactory, (IUnknown*)&Test_ClassFactory, MSHCTX_LOCAL, NULL, MSHLFLAGS_NORMAL);
1872 ok_ole_success(hr, IMarshal_MarshalInterface);
1874 ok_more_than_one_lock();
1876 test_freethreadedmarshaldata(pStream, MSHCTX_LOCAL, &Test_ClassFactory, MSHLFLAGS_NORMAL);
1878 IStream_Seek(pStream, llZero, STREAM_SEEK_SET, NULL);
1879 hr = IMarshal_ReleaseMarshalData(pFTMarshal, pStream);
1880 ok_ole_success(hr, IMarshal_ReleaseMarshalData);
1882 ok_no_locks();
1885 /* inproc table-strong marshaling */
1887 IStream_Seek(pStream, llZero, STREAM_SEEK_SET, NULL);
1888 hr = IMarshal_MarshalInterface(pFTMarshal, pStream, &IID_IClassFactory,
1889 (IUnknown*)&Test_ClassFactory, MSHCTX_INPROC, (void *)0xdeadbeef,
1890 MSHLFLAGS_TABLESTRONG);
1891 ok_ole_success(hr, IMarshal_MarshalInterface);
1893 ok_more_than_one_lock();
1895 test_freethreadedmarshaldata(pStream, MSHCTX_INPROC, &Test_ClassFactory, MSHLFLAGS_TABLESTRONG);
1897 IStream_Seek(pStream, llZero, STREAM_SEEK_SET, NULL);
1898 hr = IMarshal_UnmarshalInterface(pFTMarshal, pStream, &IID_IUnknown, (void **)&pProxy);
1899 ok_ole_success(hr, IMarshal_UnmarshalInterface);
1901 IUnknown_Release(pProxy);
1903 ok_more_than_one_lock();
1905 IStream_Seek(pStream, llZero, STREAM_SEEK_SET, NULL);
1906 hr = IMarshal_ReleaseMarshalData(pFTMarshal, pStream);
1907 ok_ole_success(hr, IMarshal_ReleaseMarshalData);
1909 ok_no_locks();
1911 /* inproc table-weak marshaling */
1913 IStream_Seek(pStream, llZero, STREAM_SEEK_SET, NULL);
1914 hr = IMarshal_MarshalInterface(pFTMarshal, pStream, &IID_IClassFactory,
1915 (IUnknown*)&Test_ClassFactory, MSHCTX_INPROC, (void *)0xdeadbeef,
1916 MSHLFLAGS_TABLEWEAK);
1917 ok_ole_success(hr, IMarshal_MarshalInterface);
1919 ok_no_locks();
1921 test_freethreadedmarshaldata(pStream, MSHCTX_INPROC, &Test_ClassFactory, MSHLFLAGS_TABLEWEAK);
1923 IStream_Seek(pStream, llZero, STREAM_SEEK_SET, NULL);
1924 hr = IMarshal_UnmarshalInterface(pFTMarshal, pStream, &IID_IUnknown, (void **)&pProxy);
1925 ok_ole_success(hr, IMarshal_UnmarshalInterface);
1927 ok_more_than_one_lock();
1929 IUnknown_Release(pProxy);
1931 ok_no_locks();
1933 /* inproc normal marshaling (for extraordinary cases) */
1935 IStream_Seek(pStream, llZero, STREAM_SEEK_SET, NULL);
1936 hr = IMarshal_MarshalInterface(pFTMarshal, pStream, &IID_IClassFactory,
1937 (IUnknown*)&Test_ClassFactory, MSHCTX_INPROC, NULL, MSHLFLAGS_NORMAL);
1938 ok_ole_success(hr, IMarshal_MarshalInterface);
1940 ok_more_than_one_lock();
1942 /* this call shows that DisconnectObject does nothing */
1943 hr = IMarshal_DisconnectObject(pFTMarshal, 0);
1944 ok_ole_success(hr, IMarshal_DisconnectObject);
1946 ok_more_than_one_lock();
1948 IStream_Seek(pStream, llZero, STREAM_SEEK_SET, NULL);
1949 hr = IMarshal_ReleaseMarshalData(pFTMarshal, pStream);
1950 ok_ole_success(hr, IMarshal_ReleaseMarshalData);
1952 ok_no_locks();
1954 /* doesn't enforce marshaling rules here and allows us to unmarshal the
1955 * interface, even though it was freed above */
1956 IStream_Seek(pStream, llZero, STREAM_SEEK_SET, NULL);
1957 hr = IMarshal_UnmarshalInterface(pFTMarshal, pStream, &IID_IUnknown, (void **)&pProxy);
1958 ok_ole_success(hr, IMarshal_UnmarshalInterface);
1960 ok_no_locks();
1962 IStream_Release(pStream);
1963 IMarshal_Release(pFTMarshal);
1966 static HANDLE heventShutdown;
1968 static void LockModuleOOP(void)
1970 InterlockedIncrement(&cLocks); /* for test purposes only */
1971 CoAddRefServerProcess();
1974 static void UnlockModuleOOP(void)
1976 InterlockedDecrement(&cLocks); /* for test purposes only */
1977 if (!CoReleaseServerProcess())
1978 SetEvent(heventShutdown);
1981 static HWND hwnd_app;
1983 static HRESULT WINAPI TestOOP_IClassFactory_QueryInterface(
1984 LPCLASSFACTORY iface,
1985 REFIID riid,
1986 LPVOID *ppvObj)
1988 if (ppvObj == NULL) return E_POINTER;
1990 if (IsEqualGUID(riid, &IID_IUnknown) ||
1991 IsEqualGUID(riid, &IID_IClassFactory))
1993 *ppvObj = (LPVOID)iface;
1994 IClassFactory_AddRef(iface);
1995 return S_OK;
1998 return E_NOINTERFACE;
2001 static ULONG WINAPI TestOOP_IClassFactory_AddRef(LPCLASSFACTORY iface)
2003 return 2; /* non-heap-based object */
2006 static ULONG WINAPI TestOOP_IClassFactory_Release(LPCLASSFACTORY iface)
2008 return 1; /* non-heap-based object */
2011 static HRESULT WINAPI TestOOP_IClassFactory_CreateInstance(
2012 LPCLASSFACTORY iface,
2013 LPUNKNOWN pUnkOuter,
2014 REFIID riid,
2015 LPVOID *ppvObj)
2017 return CLASS_E_CLASSNOTAVAILABLE;
2020 static HRESULT WINAPI TestOOP_IClassFactory_LockServer(
2021 LPCLASSFACTORY iface,
2022 BOOL fLock)
2024 if (fLock)
2025 LockModuleOOP();
2026 else
2027 UnlockModuleOOP();
2028 return S_OK;
2031 static const IClassFactoryVtbl TestClassFactoryOOP_Vtbl =
2033 TestOOP_IClassFactory_QueryInterface,
2034 TestOOP_IClassFactory_AddRef,
2035 TestOOP_IClassFactory_Release,
2036 TestOOP_IClassFactory_CreateInstance,
2037 TestOOP_IClassFactory_LockServer
2040 static IClassFactory TestOOP_ClassFactory = { &TestClassFactoryOOP_Vtbl };
2042 /* tests functions commonly used by out of process COM servers */
2043 static void test_out_of_process_com(void)
2045 static const CLSID CLSID_WineOOPTest = {
2046 0x5201163f,
2047 0x8164,
2048 0x4fd0,
2049 {0xa1, 0xa2, 0x5d, 0x5a, 0x36, 0x54, 0xd3, 0xbd}
2050 }; /* 5201163f-8164-4fd0-a1a2-5d5a3654d3bd */
2051 DWORD cookie;
2052 HRESULT hr;
2053 IClassFactory * cf;
2054 DWORD ret;
2056 heventShutdown = CreateEvent(NULL, TRUE, FALSE, NULL);
2058 cLocks = 0;
2060 /* Start the object suspended */
2061 hr = CoRegisterClassObject(&CLSID_WineOOPTest, (IUnknown *)&TestOOP_ClassFactory,
2062 CLSCTX_LOCAL_SERVER, REGCLS_MULTIPLEUSE | REGCLS_SUSPENDED, &cookie);
2063 ok_ole_success(hr, CoRegisterClassObject);
2065 /* ... and CoGetClassObject does not find it and fails when it looks for the
2066 * class in the registry */
2067 hr = CoGetClassObject(&CLSID_WineOOPTest, CLSCTX_INPROC_SERVER,
2068 NULL, &IID_IClassFactory, (LPVOID*)&cf);
2069 todo_wine {
2070 ok(hr == REGDB_E_CLASSNOTREG,
2071 "CoGetClassObject should have returned REGDB_E_CLASSNOTREG instead of 0x%08x\n", hr);
2074 /* Resume the object suspended above ... */
2075 hr = CoResumeClassObjects();
2076 ok_ole_success(hr, CoResumeClassObjects);
2078 /* ... and now it should succeed */
2079 hr = CoGetClassObject(&CLSID_WineOOPTest, CLSCTX_INPROC_SERVER,
2080 NULL, &IID_IClassFactory, (LPVOID*)&cf);
2081 ok_ole_success(hr, CoGetClassObject);
2083 /* Now check the locking is working */
2084 /* NOTE: we are accessing the class directly, not through a proxy */
2086 ok_no_locks();
2088 hr = IClassFactory_LockServer(cf, TRUE);
2089 trace("IClassFactory_LockServer returned 0x%08x\n", hr);
2091 ok_more_than_one_lock();
2093 IClassFactory_LockServer(cf, FALSE);
2095 ok_no_locks();
2097 IClassFactory_Release(cf);
2099 /* wait for shutdown signal */
2100 ret = WaitForSingleObject(heventShutdown, 5000);
2101 todo_wine { ok(ret != WAIT_TIMEOUT, "Server didn't shut down or machine is under very heavy load\n"); }
2103 /* try to connect again after SCM has suspended registered class objects */
2104 hr = CoGetClassObject(&CLSID_WineOOPTest, CLSCTX_INPROC_SERVER | CLSCTX_LOCAL_SERVER, NULL,
2105 &IID_IClassFactory, (LPVOID*)&cf);
2106 todo_wine {
2107 ok(hr == CO_E_SERVER_STOPPING,
2108 "CoGetClassObject should have returned CO_E_SERVER_STOPPING instead of 0x%08x\n", hr);
2111 hr = CoRevokeClassObject(cookie);
2112 ok_ole_success(hr, CoRevokeClassObject);
2114 CloseHandle(heventShutdown);
2117 struct git_params
2119 DWORD cookie;
2120 IGlobalInterfaceTable *git;
2123 static DWORD CALLBACK get_global_interface_proc(LPVOID pv)
2125 HRESULT hr;
2126 struct git_params *params = (struct git_params *)pv;
2127 IClassFactory *cf;
2129 hr = IGlobalInterfaceTable_GetInterfaceFromGlobal(params->git, params->cookie, &IID_IClassFactory, (void **)&cf);
2130 ok(hr == CO_E_NOTINITIALIZED,
2131 "IGlobalInterfaceTable_GetInterfaceFromGlobal should have failed with error CO_E_NOTINITIALIZED instead of 0x%08x\n",
2132 hr);
2134 CoInitialize(NULL);
2135 hr = IGlobalInterfaceTable_GetInterfaceFromGlobal(params->git, params->cookie, &IID_IClassFactory, (void **)&cf);
2136 ok_ole_success(hr, IGlobalInterfaceTable_GetInterfaceFromGlobal);
2138 IGlobalInterfaceTable_Release(params->git);
2140 CoUninitialize();
2142 return hr;
2145 static void test_globalinterfacetable(void)
2147 HRESULT hr;
2148 IGlobalInterfaceTable *git;
2149 DWORD cookie;
2150 HANDLE thread;
2151 DWORD tid;
2152 struct git_params params;
2153 DWORD ret;
2155 hr = CoCreateInstance(&CLSID_StdGlobalInterfaceTable, NULL, CLSCTX_INPROC_SERVER, &IID_IGlobalInterfaceTable, (void **)&git);
2156 ok_ole_success(hr, CoCreateInstance);
2158 hr = IGlobalInterfaceTable_RegisterInterfaceInGlobal(git, (IUnknown *)&Test_ClassFactory, &IID_IClassFactory, &cookie);
2159 ok_ole_success(hr, IGlobalInterfaceTable_RegisterInterfaceInGlobal);
2161 params.cookie = cookie;
2162 params.git = git;
2163 /* note: params is on stack so we MUST wait for get_global_interface_proc
2164 * to exit before we can return */
2165 thread = CreateThread(NULL, 0, get_global_interface_proc, &params, 0, &tid);
2167 ret = MsgWaitForMultipleObjects(1, &thread, FALSE, INFINITE, QS_ALLINPUT);
2168 while (ret == WAIT_OBJECT_0 + 1)
2170 MSG msg;
2171 while (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
2172 DispatchMessage(&msg);
2173 ret = MsgWaitForMultipleObjects(1, &thread, FALSE, INFINITE, QS_ALLINPUT);
2176 CloseHandle(thread);
2179 static const char *debugstr_iid(REFIID riid)
2181 static char name[256];
2182 HKEY hkeyInterface;
2183 WCHAR bufferW[39];
2184 char buffer[39];
2185 LONG name_size = sizeof(name);
2186 StringFromGUID2(riid, bufferW, sizeof(bufferW)/sizeof(bufferW[0]));
2187 WideCharToMultiByte(CP_ACP, 0, bufferW, sizeof(bufferW)/sizeof(bufferW[0]), buffer, sizeof(buffer), NULL, NULL);
2188 if (RegOpenKeyEx(HKEY_CLASSES_ROOT, "Interface", 0, KEY_QUERY_VALUE, &hkeyInterface) != ERROR_SUCCESS)
2190 memcpy(name, buffer, sizeof(buffer));
2191 goto done;
2193 if (RegQueryValue(hkeyInterface, buffer, name, &name_size) != ERROR_SUCCESS)
2195 memcpy(name, buffer, sizeof(buffer));
2196 goto done;
2198 RegCloseKey(hkeyInterface);
2199 done:
2200 return name;
2203 static HRESULT WINAPI TestChannelHook_QueryInterface(IChannelHook *iface, REFIID riid, void **ppv)
2205 if (IsEqualIID(riid, &IID_IUnknown) || IsEqualIID(riid, &IID_IChannelHook))
2207 *ppv = iface;
2208 IUnknown_AddRef(iface);
2209 return S_OK;
2212 *ppv = NULL;
2213 return E_NOINTERFACE;
2216 static ULONG WINAPI TestChannelHook_AddRef(IChannelHook *iface)
2218 return 2;
2221 static ULONG WINAPI TestChannelHook_Release(IChannelHook *iface)
2223 return 1;
2226 static void WINAPI TestChannelHook_ClientGetSize(
2227 IChannelHook *iface,
2228 REFGUID uExtent,
2229 REFIID riid,
2230 ULONG *pDataSize )
2232 SChannelHookCallInfo *info = (SChannelHookCallInfo *)riid;
2233 trace("TestChannelHook_ClientGetBuffer\n");
2234 trace("\t%s method %d\n", debugstr_iid(riid), info->iMethod);
2235 trace("\tcid: %s\n", debugstr_iid(&info->uCausality));
2236 ok(info->cbSize == sizeof(*info), "info->cbSize was %d instead of %d\n", info->cbSize, (int)sizeof(*info));
2237 todo_wine {
2238 ok(info->dwServerPid == GetCurrentProcessId(), "info->dwServerPid was 0x%x instead of 0x%x\n", info->dwServerPid, GetCurrentProcessId());
2240 ok(!info->pObject, "info->pObject should be NULL\n");
2241 ok(IsEqualGUID(uExtent, &EXTENTID_WineTest), "uExtent wasn't correct\n");
2243 *pDataSize = 1;
2246 static void WINAPI TestChannelHook_ClientFillBuffer(
2247 IChannelHook *iface,
2248 REFGUID uExtent,
2249 REFIID riid,
2250 ULONG *pDataSize,
2251 void *pDataBuffer )
2253 SChannelHookCallInfo *info = (SChannelHookCallInfo *)riid;
2254 trace("TestChannelHook_ClientFillBuffer\n");
2255 ok(info->cbSize == sizeof(*info), "info->cbSize was %d instead of %d\n", info->cbSize, (int)sizeof(*info));
2256 todo_wine {
2257 ok(info->dwServerPid == GetCurrentProcessId(), "info->dwServerPid was 0x%x instead of 0x%x\n", info->dwServerPid, GetCurrentProcessId());
2259 ok(!info->pObject, "info->pObject should be NULL\n");
2260 ok(IsEqualGUID(uExtent, &EXTENTID_WineTest), "uExtent wasn't correct\n");
2262 *(unsigned char *)pDataBuffer = 0xcc;
2263 *pDataSize = 1;
2266 static void WINAPI TestChannelHook_ClientNotify(
2267 IChannelHook *iface,
2268 REFGUID uExtent,
2269 REFIID riid,
2270 ULONG cbDataSize,
2271 void *pDataBuffer,
2272 DWORD lDataRep,
2273 HRESULT hrFault )
2275 SChannelHookCallInfo *info = (SChannelHookCallInfo *)riid;
2276 trace("TestChannelHook_ClientNotify hrFault = 0x%08x\n", hrFault);
2277 ok(info->cbSize == sizeof(*info), "info->cbSize was %d instead of %d\n", info->cbSize, (int)sizeof(*info));
2278 todo_wine {
2279 ok(info->dwServerPid == GetCurrentProcessId(), "info->dwServerPid was 0x%x instead of 0x%x\n", info->dwServerPid, GetCurrentProcessId());
2280 ok(info->pObject != NULL, "info->pObject shouldn't be NULL\n");
2282 ok(IsEqualGUID(uExtent, &EXTENTID_WineTest), "uExtent wasn't correct\n");
2285 static void WINAPI TestChannelHook_ServerNotify(
2286 IChannelHook *iface,
2287 REFGUID uExtent,
2288 REFIID riid,
2289 ULONG cbDataSize,
2290 void *pDataBuffer,
2291 DWORD lDataRep )
2293 SChannelHookCallInfo *info = (SChannelHookCallInfo *)riid;
2294 trace("TestChannelHook_ServerNotify\n");
2295 ok(info->cbSize == sizeof(*info), "info->cbSize was %d instead of %d\n", info->cbSize, (int)sizeof(*info));
2296 ok(info->dwServerPid == GetCurrentProcessId(), "info->dwServerPid was 0x%x instead of 0x%x\n", info->dwServerPid, GetCurrentProcessId());
2297 ok(info->pObject != NULL, "info->pObject shouldn't be NULL\n");
2298 ok(cbDataSize == 1, "cbDataSize should have been 1 instead of %d\n", cbDataSize);
2299 ok(*(unsigned char *)pDataBuffer == 0xcc, "pDataBuffer should have contained 0xcc instead of 0x%x\n", *(unsigned char *)pDataBuffer);
2300 ok(IsEqualGUID(uExtent, &EXTENTID_WineTest), "uExtent wasn't correct\n");
2303 static void WINAPI TestChannelHook_ServerGetSize(
2304 IChannelHook *iface,
2305 REFGUID uExtent,
2306 REFIID riid,
2307 HRESULT hrFault,
2308 ULONG *pDataSize )
2310 SChannelHookCallInfo *info = (SChannelHookCallInfo *)riid;
2311 trace("TestChannelHook_ServerGetSize\n");
2312 trace("\t%s method %d\n", debugstr_iid(riid), info->iMethod);
2313 ok(info->cbSize == sizeof(*info), "info->cbSize was %d instead of %d\n", info->cbSize, (int)sizeof(*info));
2314 ok(info->dwServerPid == GetCurrentProcessId(), "info->dwServerPid was 0x%x instead of 0x%x\n", info->dwServerPid, GetCurrentProcessId());
2315 ok(info->pObject != NULL, "info->pObject shouldn't be NULL\n");
2316 ok(IsEqualGUID(uExtent, &EXTENTID_WineTest), "uExtent wasn't correct\n");
2317 if (hrFault != S_OK)
2318 trace("\thrFault = 0x%08x\n", hrFault);
2320 *pDataSize = 0;
2323 static void WINAPI TestChannelHook_ServerFillBuffer(
2324 IChannelHook *iface,
2325 REFGUID uExtent,
2326 REFIID riid,
2327 ULONG *pDataSize,
2328 void *pDataBuffer,
2329 HRESULT hrFault )
2331 trace("TestChannelHook_ServerFillBuffer\n");
2332 ok(0, "TestChannelHook_ServerFillBuffer shouldn't be called\n");
2335 static const IChannelHookVtbl TestChannelHookVtbl =
2337 TestChannelHook_QueryInterface,
2338 TestChannelHook_AddRef,
2339 TestChannelHook_Release,
2340 TestChannelHook_ClientGetSize,
2341 TestChannelHook_ClientFillBuffer,
2342 TestChannelHook_ClientNotify,
2343 TestChannelHook_ServerNotify,
2344 TestChannelHook_ServerGetSize,
2345 TestChannelHook_ServerFillBuffer,
2348 static IChannelHook TestChannelHook = { &TestChannelHookVtbl };
2350 static void test_channel_hook(void)
2352 IStream *pStream = NULL;
2353 IClassFactory *cf = NULL;
2354 DWORD tid;
2355 IUnknown *proxy = NULL;
2356 HANDLE thread;
2357 HRESULT hr;
2359 hr = CoRegisterChannelHook(&EXTENTID_WineTest, &TestChannelHook);
2360 ok_ole_success(hr, CoRegisterChannelHook);
2362 hr = CoRegisterMessageFilter(&MessageFilter, NULL);
2363 ok_ole_success(hr, CoRegisterMessageFilter);
2365 cLocks = 0;
2367 hr = CreateStreamOnHGlobal(NULL, TRUE, &pStream);
2368 ok_ole_success(hr, CreateStreamOnHGlobal);
2369 tid = start_host_object2(pStream, &IID_IClassFactory, (IUnknown*)&Test_ClassFactory, MSHLFLAGS_NORMAL, &MessageFilter, &thread);
2371 ok_more_than_one_lock();
2373 IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
2374 hr = CoUnmarshalInterface(pStream, &IID_IClassFactory, (void **)&cf);
2375 ok_ole_success(hr, CoUnmarshalInterface);
2376 IStream_Release(pStream);
2378 ok_more_than_one_lock();
2380 hr = IClassFactory_CreateInstance(cf, NULL, &IID_IUnknown, (LPVOID*)&proxy);
2381 ok_ole_success(hr, IClassFactory_CreateInstance);
2382 IUnknown_Release(proxy);
2384 IClassFactory_Release(cf);
2386 ok_no_locks();
2388 end_host_object(tid, thread);
2390 hr = CoRegisterMessageFilter(NULL, NULL);
2391 ok_ole_success(hr, CoRegisterMessageFilter);
2394 START_TEST(marshal)
2396 WNDCLASS wndclass;
2397 HMODULE hOle32 = GetModuleHandle("ole32");
2398 if (!(pCoInitializeEx = (void*)GetProcAddress(hOle32, "CoInitializeEx"))) goto no_test;
2400 /* register a window class used in several tests */
2401 memset(&wndclass, 0, sizeof(wndclass));
2402 wndclass.lpfnWndProc = window_proc;
2403 wndclass.lpszClassName = "WineCOMTest";
2404 RegisterClass(&wndclass);
2406 test_cocreateinstance_proxy();
2408 pCoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
2410 /* FIXME: test CoCreateInstanceEx */
2412 /* lifecycle management and marshaling tests */
2413 test_no_marshaler();
2414 test_normal_marshal_and_release();
2415 test_normal_marshal_and_unmarshal();
2416 test_marshal_and_unmarshal_invalid();
2417 test_same_apartment_unmarshal_failure();
2418 test_interthread_marshal_and_unmarshal();
2419 test_proxy_marshal_and_unmarshal();
2420 test_proxy_marshal_and_unmarshal2();
2421 test_marshal_stub_apartment_shutdown();
2422 test_marshal_proxy_apartment_shutdown();
2423 test_marshal_proxy_mta_apartment_shutdown();
2424 test_no_couninitialize_server();
2425 test_no_couninitialize_client();
2426 test_tableweak_marshal_and_unmarshal_twice();
2427 test_tableweak_marshal_releasedata1();
2428 test_tableweak_marshal_releasedata2();
2429 test_tablestrong_marshal_and_unmarshal_twice();
2430 test_lock_object_external();
2431 test_disconnect_stub();
2432 test_normal_marshal_and_unmarshal_twice();
2433 test_hresult_marshaling();
2434 test_proxy_used_in_wrong_thread();
2435 test_message_filter();
2436 test_bad_marshal_stream();
2437 test_proxy_interfaces();
2438 test_stubbuffer(&IID_IClassFactory);
2439 test_proxybuffer(&IID_IClassFactory);
2440 test_message_reentrancy();
2441 test_call_from_message();
2442 test_WM_QUIT_handling();
2443 test_freethreadedmarshaler();
2445 /* doesn't pass with Win9x COM DLLs (even though Essential COM says it should) */
2446 if (0) test_out_of_process_com();
2448 test_globalinterfacetable();
2450 /* must be last test as channel hooks can't be unregistered */
2451 test_channel_hook();
2453 CoUninitialize();
2454 return;
2456 no_test:
2457 trace("You need DCOM95 installed to run this test\n");
2458 return;