push 17e95bb5b89ca06d3b4ab9c4a2ab44cb05c88b95
[wine/hacks.git] / dlls / ole32 / tests / marshal.c
blob7e3e82e766a44b44d0cde91d46bfecf18e5393c8
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>
26 #include <stdio.h>
28 #include "windef.h"
29 #include "winbase.h"
30 #include "objbase.h"
31 #include "shlguid.h"
33 #include "wine/test.h"
35 /* functions that are not present on all versions of Windows */
36 HRESULT (WINAPI * pCoInitializeEx)(LPVOID lpReserved, DWORD dwCoInit);
38 /* helper macros to make tests a bit leaner */
39 #define ok_more_than_one_lock() ok(cLocks > 0, "Number of locks should be > 0, but actually is %d\n", cLocks)
40 #define ok_no_locks() ok(cLocks == 0, "Number of locks should be 0, but actually is %d\n", cLocks)
41 #define ok_ole_success(hr, func) ok(hr == S_OK, #func " failed with error 0x%08x\n", hr)
43 static const IID IID_IWineTest =
45 0x5201163f,
46 0x8164,
47 0x4fd0,
48 {0xa1, 0xa2, 0x5d, 0x5a, 0x36, 0x54, 0xd3, 0xbd}
49 }; /* 5201163f-8164-4fd0-a1a2-5d5a3654d3bd */
51 static const IID IID_IRemUnknown =
53 0x00000131,
54 0x0000,
55 0x0000,
56 {0xc0,0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46}
59 #define EXTENTID_WineTest IID_IWineTest
60 #define CLSID_WineTest IID_IWineTest
62 static const CLSID CLSID_WineOOPTest =
64 0x5201163f,
65 0x8164,
66 0x4fd0,
67 {0xa1, 0xa2, 0x5d, 0x5a, 0x36, 0x54, 0xd3, 0xbd}
68 }; /* 5201163f-8164-4fd0-a1a2-5d5a3654d3bd */
70 static void test_cocreateinstance_proxy(void)
72 IUnknown *pProxy;
73 IMultiQI *pMQI;
74 HRESULT hr;
76 pCoInitializeEx(NULL, COINIT_MULTITHREADED);
78 hr = CoCreateInstance(&CLSID_ShellDesktop, NULL, CLSCTX_INPROC, &IID_IUnknown, (void **)&pProxy);
79 ok_ole_success(hr, CoCreateInstance);
80 hr = IUnknown_QueryInterface(pProxy, &IID_IMultiQI, (void **)&pMQI);
81 todo_wine
82 ok(hr == S_OK, "created object is not a proxy, so was created in the wrong apartment\n");
83 if (hr == S_OK)
84 IMultiQI_Release(pMQI);
85 IUnknown_Release(pProxy);
87 CoUninitialize();
90 static const LARGE_INTEGER ullZero;
91 static LONG cLocks;
93 static void LockModule(void)
95 InterlockedIncrement(&cLocks);
98 static void UnlockModule(void)
100 InterlockedDecrement(&cLocks);
104 static HRESULT WINAPI Test_IUnknown_QueryInterface(
105 LPUNKNOWN iface,
106 REFIID riid,
107 LPVOID *ppvObj)
109 if (ppvObj == NULL) return E_POINTER;
111 if (IsEqualGUID(riid, &IID_IUnknown))
113 *ppvObj = (LPVOID)iface;
114 IUnknown_AddRef(iface);
115 return S_OK;
118 *ppvObj = NULL;
119 return E_NOINTERFACE;
122 static ULONG WINAPI Test_IUnknown_AddRef(LPUNKNOWN iface)
124 LockModule();
125 return 2; /* non-heap-based object */
128 static ULONG WINAPI Test_IUnknown_Release(LPUNKNOWN iface)
130 UnlockModule();
131 return 1; /* non-heap-based object */
134 static const IUnknownVtbl TestUnknown_Vtbl =
136 Test_IUnknown_QueryInterface,
137 Test_IUnknown_AddRef,
138 Test_IUnknown_Release,
141 static IUnknown Test_Unknown = { &TestUnknown_Vtbl };
144 static HRESULT WINAPI Test_IClassFactory_QueryInterface(
145 LPCLASSFACTORY iface,
146 REFIID riid,
147 LPVOID *ppvObj)
149 if (ppvObj == NULL) return E_POINTER;
151 if (IsEqualGUID(riid, &IID_IUnknown) ||
152 IsEqualGUID(riid, &IID_IClassFactory) ||
153 /* the only other interface Wine is currently able to marshal (for testing two proxies) */
154 IsEqualGUID(riid, &IID_IRemUnknown))
156 *ppvObj = (LPVOID)iface;
157 IClassFactory_AddRef(iface);
158 return S_OK;
161 *ppvObj = NULL;
162 return E_NOINTERFACE;
165 static ULONG WINAPI Test_IClassFactory_AddRef(LPCLASSFACTORY iface)
167 LockModule();
168 return 2; /* non-heap-based object */
171 static ULONG WINAPI Test_IClassFactory_Release(LPCLASSFACTORY iface)
173 UnlockModule();
174 return 1; /* non-heap-based object */
177 static HRESULT WINAPI Test_IClassFactory_CreateInstance(
178 LPCLASSFACTORY iface,
179 LPUNKNOWN pUnkOuter,
180 REFIID riid,
181 LPVOID *ppvObj)
183 if (pUnkOuter) return CLASS_E_NOAGGREGATION;
184 return IUnknown_QueryInterface((IUnknown*)&Test_Unknown, riid, ppvObj);
187 static HRESULT WINAPI Test_IClassFactory_LockServer(
188 LPCLASSFACTORY iface,
189 BOOL fLock)
191 return S_OK;
194 static const IClassFactoryVtbl TestClassFactory_Vtbl =
196 Test_IClassFactory_QueryInterface,
197 Test_IClassFactory_AddRef,
198 Test_IClassFactory_Release,
199 Test_IClassFactory_CreateInstance,
200 Test_IClassFactory_LockServer
203 static IClassFactory Test_ClassFactory = { &TestClassFactory_Vtbl };
205 #define RELEASEMARSHALDATA WM_USER
207 struct host_object_data
209 IStream *stream;
210 IID iid;
211 IUnknown *object;
212 MSHLFLAGS marshal_flags;
213 HANDLE marshal_event;
214 IMessageFilter *filter;
217 static DWORD CALLBACK host_object_proc(LPVOID p)
219 struct host_object_data *data = (struct host_object_data *)p;
220 HRESULT hr;
221 MSG msg;
223 pCoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
225 if (data->filter)
227 IMessageFilter * prev_filter = NULL;
228 hr = CoRegisterMessageFilter(data->filter, &prev_filter);
229 if (prev_filter) IMessageFilter_Release(prev_filter);
230 ok_ole_success(hr, CoRegisterMessageFilter);
233 hr = CoMarshalInterface(data->stream, &data->iid, data->object, MSHCTX_INPROC, NULL, data->marshal_flags);
234 ok_ole_success(hr, CoMarshalInterface);
236 /* force the message queue to be created before signaling parent thread */
237 PeekMessage(&msg, NULL, WM_USER, WM_USER, PM_NOREMOVE);
239 SetEvent(data->marshal_event);
241 while (GetMessage(&msg, NULL, 0, 0))
243 if (msg.hwnd == NULL && msg.message == RELEASEMARSHALDATA)
245 trace("releasing marshal data\n");
246 CoReleaseMarshalData(data->stream);
247 SetEvent((HANDLE)msg.lParam);
249 else
250 DispatchMessage(&msg);
253 HeapFree(GetProcessHeap(), 0, data);
255 CoUninitialize();
257 return hr;
260 static DWORD start_host_object2(IStream *stream, REFIID riid, IUnknown *object, MSHLFLAGS marshal_flags, IMessageFilter *filter, HANDLE *thread)
262 DWORD tid = 0;
263 HANDLE marshal_event = CreateEvent(NULL, FALSE, FALSE, NULL);
264 struct host_object_data *data = HeapAlloc(GetProcessHeap(), 0, sizeof(*data));
266 data->stream = stream;
267 data->iid = *riid;
268 data->object = object;
269 data->marshal_flags = marshal_flags;
270 data->marshal_event = marshal_event;
271 data->filter = filter;
273 *thread = CreateThread(NULL, 0, host_object_proc, data, 0, &tid);
275 /* wait for marshaling to complete before returning */
276 WaitForSingleObject(marshal_event, INFINITE);
277 CloseHandle(marshal_event);
279 return tid;
282 static DWORD start_host_object(IStream *stream, REFIID riid, IUnknown *object, MSHLFLAGS marshal_flags, HANDLE *thread)
284 return start_host_object2(stream, riid, object, marshal_flags, NULL, thread);
287 /* asks thread to release the marshal data because it has to be done by the
288 * same thread that marshaled the interface in the first place. */
289 static void release_host_object(DWORD tid)
291 HANDLE event = CreateEvent(NULL, FALSE, FALSE, NULL);
292 PostThreadMessage(tid, RELEASEMARSHALDATA, 0, (LPARAM)event);
293 WaitForSingleObject(event, INFINITE);
294 CloseHandle(event);
297 static void end_host_object(DWORD tid, HANDLE thread)
299 BOOL ret = PostThreadMessage(tid, WM_QUIT, 0, 0);
300 ok(ret, "PostThreadMessage failed with error %d\n", GetLastError());
301 /* be careful of races - don't return until hosting thread has terminated */
302 WaitForSingleObject(thread, INFINITE);
303 CloseHandle(thread);
306 /* tests failure case of interface not having a marshaler specified in the
307 * registry */
308 static void test_no_marshaler(void)
310 IStream *pStream;
311 HRESULT hr;
313 hr = CreateStreamOnHGlobal(NULL, TRUE, &pStream);
314 ok_ole_success(hr, CreateStreamOnHGlobal);
315 hr = CoMarshalInterface(pStream, &IID_IWineTest, (IUnknown*)&Test_ClassFactory, MSHCTX_INPROC, NULL, MSHLFLAGS_NORMAL);
316 ok(hr == E_NOINTERFACE, "CoMarshalInterface should have returned E_NOINTERFACE instead of 0x%08x\n", hr);
318 IStream_Release(pStream);
321 /* tests normal marshal and then release without unmarshaling */
322 static void test_normal_marshal_and_release(void)
324 HRESULT hr;
325 IStream *pStream = NULL;
327 cLocks = 0;
329 hr = CreateStreamOnHGlobal(NULL, TRUE, &pStream);
330 ok_ole_success(hr, CreateStreamOnHGlobal);
331 hr = CoMarshalInterface(pStream, &IID_IClassFactory, (IUnknown*)&Test_ClassFactory, MSHCTX_INPROC, NULL, MSHLFLAGS_NORMAL);
332 ok_ole_success(hr, CoMarshalInterface);
334 ok_more_than_one_lock();
336 IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
337 hr = CoReleaseMarshalData(pStream);
338 ok_ole_success(hr, CoReleaseMarshalData);
339 IStream_Release(pStream);
341 ok_no_locks();
344 /* tests success case of a same-thread marshal and unmarshal */
345 static void test_normal_marshal_and_unmarshal(void)
347 HRESULT hr;
348 IStream *pStream = NULL;
349 IUnknown *pProxy = NULL;
351 cLocks = 0;
353 hr = CreateStreamOnHGlobal(NULL, TRUE, &pStream);
354 ok_ole_success(hr, CreateStreamOnHGlobal);
355 hr = CoMarshalInterface(pStream, &IID_IClassFactory, (IUnknown*)&Test_ClassFactory, MSHCTX_INPROC, NULL, MSHLFLAGS_NORMAL);
356 ok_ole_success(hr, CoMarshalInterface);
358 ok_more_than_one_lock();
360 IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
361 hr = CoUnmarshalInterface(pStream, &IID_IClassFactory, (void **)&pProxy);
362 ok_ole_success(hr, CoUnmarshalInterface);
363 IStream_Release(pStream);
365 ok_more_than_one_lock();
367 IUnknown_Release(pProxy);
369 ok_no_locks();
372 /* tests failure case of unmarshaling a freed object */
373 static void test_marshal_and_unmarshal_invalid(void)
375 HRESULT hr;
376 IStream *pStream = NULL;
377 IClassFactory *pProxy = NULL;
378 DWORD tid;
379 void * dummy;
380 HANDLE thread;
382 cLocks = 0;
384 hr = CreateStreamOnHGlobal(NULL, TRUE, &pStream);
385 ok_ole_success(hr, CreateStreamOnHGlobal);
386 tid = start_host_object(pStream, &IID_IClassFactory, (IUnknown*)&Test_ClassFactory, MSHLFLAGS_NORMAL, &thread);
388 ok_more_than_one_lock();
390 IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
391 hr = CoReleaseMarshalData(pStream);
392 ok_ole_success(hr, CoReleaseMarshalData);
394 ok_no_locks();
396 IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
397 hr = CoUnmarshalInterface(pStream, &IID_IClassFactory, (void **)&pProxy);
398 todo_wine { ok_ole_success(hr, CoUnmarshalInterface); }
400 ok_no_locks();
402 if (pProxy)
404 hr = IClassFactory_CreateInstance(pProxy, NULL, &IID_IUnknown, &dummy);
405 ok(hr == RPC_E_DISCONNECTED, "Remote call should have returned RPC_E_DISCONNECTED, instead of 0x%08x\n", hr);
407 IClassFactory_Release(pProxy);
410 IStream_Release(pStream);
412 end_host_object(tid, thread);
415 static void test_same_apartment_unmarshal_failure(void)
417 HRESULT hr;
418 IStream *pStream;
419 IUnknown *pProxy;
420 static const LARGE_INTEGER llZero;
422 cLocks = 0;
424 hr = CreateStreamOnHGlobal(NULL, TRUE, &pStream);
425 ok_ole_success(hr, CreateStreamOnHGlobal);
427 hr = CoMarshalInterface(pStream, &IID_IUnknown, (IUnknown *)&Test_ClassFactory, MSHCTX_INPROC, NULL, MSHLFLAGS_NORMAL);
428 ok_ole_success(hr, CoMarshalInterface);
430 ok_more_than_one_lock();
432 hr = IStream_Seek(pStream, llZero, STREAM_SEEK_SET, NULL);
433 ok_ole_success(hr, IStream_Seek);
435 hr = CoUnmarshalInterface(pStream, &IID_IParseDisplayName, (void **)&pProxy);
436 ok(hr == E_NOINTERFACE, "CoUnmarshalInterface should have returned E_NOINTERFACE instead of 0x%08x\n", hr);
438 ok_no_locks();
441 /* tests success case of an interthread marshal */
442 static void test_interthread_marshal_and_unmarshal(void)
444 HRESULT hr;
445 IStream *pStream = NULL;
446 IUnknown *pProxy = NULL;
447 DWORD tid;
448 HANDLE thread;
450 cLocks = 0;
452 hr = CreateStreamOnHGlobal(NULL, TRUE, &pStream);
453 ok_ole_success(hr, CreateStreamOnHGlobal);
454 tid = start_host_object(pStream, &IID_IClassFactory, (IUnknown*)&Test_ClassFactory, MSHLFLAGS_NORMAL, &thread);
456 ok_more_than_one_lock();
458 IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
459 hr = CoUnmarshalInterface(pStream, &IID_IClassFactory, (void **)&pProxy);
460 ok_ole_success(hr, CoUnmarshalInterface);
461 IStream_Release(pStream);
463 ok_more_than_one_lock();
465 IUnknown_Release(pProxy);
467 ok_no_locks();
469 end_host_object(tid, thread);
472 /* the number of external references that Wine's proxy manager normally gives
473 * out, so we can test the border case of running out of references */
474 #define NORMALEXTREFS 5
476 /* tests success case of an interthread marshal and then marshaling the proxy */
477 static void test_proxy_marshal_and_unmarshal(void)
479 HRESULT hr;
480 IStream *pStream = NULL;
481 IUnknown *pProxy = NULL;
482 IUnknown *pProxy2 = NULL;
483 DWORD tid;
484 HANDLE thread;
485 int i;
487 cLocks = 0;
489 hr = CreateStreamOnHGlobal(NULL, TRUE, &pStream);
490 ok_ole_success(hr, CreateStreamOnHGlobal);
491 tid = start_host_object(pStream, &IID_IClassFactory, (IUnknown*)&Test_ClassFactory, MSHLFLAGS_NORMAL, &thread);
493 ok_more_than_one_lock();
495 IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
496 hr = CoUnmarshalInterface(pStream, &IID_IClassFactory, (void **)&pProxy);
497 ok_ole_success(hr, CoUnmarshalInterface);
499 ok_more_than_one_lock();
501 IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
502 /* marshal the proxy */
503 hr = CoMarshalInterface(pStream, &IID_IClassFactory, pProxy, MSHCTX_INPROC, NULL, MSHLFLAGS_NORMAL);
504 ok_ole_success(hr, CoMarshalInterface);
506 ok_more_than_one_lock();
508 /* marshal 5 more times to exhaust the normal external references of 5 */
509 for (i = 0; i < NORMALEXTREFS; i++)
511 hr = CoMarshalInterface(pStream, &IID_IClassFactory, pProxy, MSHCTX_INPROC, NULL, MSHLFLAGS_NORMAL);
512 ok_ole_success(hr, CoMarshalInterface);
515 ok_more_than_one_lock();
517 /* release the original proxy to test that we successfully keep the
518 * original object alive */
519 IUnknown_Release(pProxy);
521 IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
522 hr = CoUnmarshalInterface(pStream, &IID_IClassFactory, (void **)&pProxy2);
523 ok_ole_success(hr, CoUnmarshalInterface);
525 ok_more_than_one_lock();
527 /* now the proxies should be as follows:
528 * pProxy2 -> &Test_ClassFactory
529 * they should NOT be as follows:
530 * pProxy -> &Test_ClassFactory
531 * pProxy2 -> pProxy
532 * the above can only really be tested by looking in +ole traces
535 IUnknown_Release(pProxy2);
537 /* unmarshal all of the proxies to check that the object stub still exists */
538 for (i = 0; i < NORMALEXTREFS; i++)
540 hr = CoUnmarshalInterface(pStream, &IID_IClassFactory, (void **)&pProxy2);
541 ok_ole_success(hr, CoUnmarshalInterface);
543 IUnknown_Release(pProxy2);
546 ok_no_locks();
548 IStream_Release(pStream);
550 end_host_object(tid, thread);
553 /* tests success case of an interthread marshal and then marshaling the proxy
554 * using an iid that hasn't previously been unmarshaled */
555 static void test_proxy_marshal_and_unmarshal2(void)
557 HRESULT hr;
558 IStream *pStream = NULL;
559 IUnknown *pProxy = NULL;
560 IUnknown *pProxy2 = NULL;
561 DWORD tid;
562 HANDLE thread;
564 cLocks = 0;
566 hr = CreateStreamOnHGlobal(NULL, TRUE, &pStream);
567 ok_ole_success(hr, CreateStreamOnHGlobal);
568 tid = start_host_object(pStream, &IID_IUnknown, (IUnknown*)&Test_ClassFactory, MSHLFLAGS_NORMAL, &thread);
570 ok_more_than_one_lock();
572 IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
573 hr = CoUnmarshalInterface(pStream, &IID_IUnknown, (void **)&pProxy);
574 ok_ole_success(hr, CoUnmarshalInterface);
576 ok_more_than_one_lock();
578 IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
579 /* marshal the proxy */
580 hr = CoMarshalInterface(pStream, &IID_IClassFactory, pProxy, MSHCTX_INPROC, NULL, MSHLFLAGS_NORMAL);
581 ok_ole_success(hr, CoMarshalInterface);
583 ok_more_than_one_lock();
585 IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
586 /* unmarshal the second proxy to the object */
587 hr = CoUnmarshalInterface(pStream, &IID_IClassFactory, (void **)&pProxy2);
588 ok_ole_success(hr, CoUnmarshalInterface);
589 IStream_Release(pStream);
591 /* now the proxies should be as follows:
592 * pProxy -> &Test_ClassFactory
593 * pProxy2 -> &Test_ClassFactory
594 * they should NOT be as follows:
595 * pProxy -> &Test_ClassFactory
596 * pProxy2 -> pProxy
597 * the above can only really be tested by looking in +ole traces
600 ok_more_than_one_lock();
602 IUnknown_Release(pProxy);
604 ok_more_than_one_lock();
606 IUnknown_Release(pProxy2);
608 ok_no_locks();
610 end_host_object(tid, thread);
613 /* tests that stubs are released when the containing apartment is destroyed */
614 static void test_marshal_stub_apartment_shutdown(void)
616 HRESULT hr;
617 IStream *pStream = NULL;
618 IUnknown *pProxy = NULL;
619 DWORD tid;
620 HANDLE thread;
622 cLocks = 0;
624 hr = CreateStreamOnHGlobal(NULL, TRUE, &pStream);
625 ok_ole_success(hr, CreateStreamOnHGlobal);
626 tid = start_host_object(pStream, &IID_IClassFactory, (IUnknown*)&Test_ClassFactory, MSHLFLAGS_NORMAL, &thread);
628 ok_more_than_one_lock();
630 IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
631 hr = CoUnmarshalInterface(pStream, &IID_IClassFactory, (void **)&pProxy);
632 ok_ole_success(hr, CoUnmarshalInterface);
633 IStream_Release(pStream);
635 ok_more_than_one_lock();
637 end_host_object(tid, thread);
639 ok_no_locks();
641 IUnknown_Release(pProxy);
643 ok_no_locks();
646 /* tests that proxies are released when the containing apartment is destroyed */
647 static void test_marshal_proxy_apartment_shutdown(void)
649 HRESULT hr;
650 IStream *pStream = NULL;
651 IUnknown *pProxy = NULL;
652 DWORD tid;
653 HANDLE thread;
655 cLocks = 0;
657 hr = CreateStreamOnHGlobal(NULL, TRUE, &pStream);
658 ok_ole_success(hr, CreateStreamOnHGlobal);
659 tid = start_host_object(pStream, &IID_IClassFactory, (IUnknown*)&Test_ClassFactory, MSHLFLAGS_NORMAL, &thread);
661 ok_more_than_one_lock();
663 IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
664 hr = CoUnmarshalInterface(pStream, &IID_IClassFactory, (void **)&pProxy);
665 ok_ole_success(hr, CoUnmarshalInterface);
666 IStream_Release(pStream);
668 ok_more_than_one_lock();
670 CoUninitialize();
672 ok_no_locks();
674 IUnknown_Release(pProxy);
676 ok_no_locks();
678 end_host_object(tid, thread);
680 pCoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
683 /* tests that proxies are released when the containing mta apartment is destroyed */
684 static void test_marshal_proxy_mta_apartment_shutdown(void)
686 HRESULT hr;
687 IStream *pStream = NULL;
688 IUnknown *pProxy = NULL;
689 DWORD tid;
690 HANDLE thread;
692 CoUninitialize();
693 pCoInitializeEx(NULL, COINIT_MULTITHREADED);
695 cLocks = 0;
697 hr = CreateStreamOnHGlobal(NULL, TRUE, &pStream);
698 ok_ole_success(hr, CreateStreamOnHGlobal);
699 tid = start_host_object(pStream, &IID_IClassFactory, (IUnknown*)&Test_ClassFactory, MSHLFLAGS_NORMAL, &thread);
701 ok_more_than_one_lock();
703 IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
704 hr = CoUnmarshalInterface(pStream, &IID_IClassFactory, (void **)&pProxy);
705 ok_ole_success(hr, CoUnmarshalInterface);
706 IStream_Release(pStream);
708 ok_more_than_one_lock();
710 CoUninitialize();
712 ok_no_locks();
714 IUnknown_Release(pProxy);
716 ok_no_locks();
718 end_host_object(tid, thread);
720 pCoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
723 struct ncu_params
725 LPSTREAM stream;
726 HANDLE marshal_event;
727 HANDLE unmarshal_event;
730 /* helper for test_no_couninitialize_server */
731 static DWORD CALLBACK no_couninitialize_server_proc(LPVOID p)
733 struct ncu_params *ncu_params = (struct ncu_params *)p;
734 HRESULT hr;
736 pCoInitializeEx(NULL, COINIT_MULTITHREADED);
738 hr = CoMarshalInterface(ncu_params->stream, &IID_IClassFactory, (IUnknown*)&Test_ClassFactory, MSHCTX_INPROC, NULL, MSHLFLAGS_NORMAL);
739 ok_ole_success(hr, CoMarshalInterface);
741 SetEvent(ncu_params->marshal_event);
743 WaitForSingleObject(ncu_params->unmarshal_event, INFINITE);
745 /* die without calling CoUninitialize */
747 return 0;
750 /* tests apartment that an apartment with a stub is released without deadlock
751 * if the owning thread exits */
752 static void test_no_couninitialize_server(void)
754 HRESULT hr;
755 IStream *pStream = NULL;
756 IUnknown *pProxy = NULL;
757 DWORD tid;
758 HANDLE thread;
759 struct ncu_params ncu_params;
761 cLocks = 0;
763 ncu_params.marshal_event = CreateEvent(NULL, TRUE, FALSE, NULL);
764 ncu_params.unmarshal_event = CreateEvent(NULL, TRUE, FALSE, NULL);
766 hr = CreateStreamOnHGlobal(NULL, TRUE, &pStream);
767 ok_ole_success(hr, CreateStreamOnHGlobal);
768 ncu_params.stream = pStream;
770 thread = CreateThread(NULL, 0, no_couninitialize_server_proc, &ncu_params, 0, &tid);
772 WaitForSingleObject(ncu_params.marshal_event, INFINITE);
773 ok_more_than_one_lock();
775 IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
776 hr = CoUnmarshalInterface(pStream, &IID_IClassFactory, (void **)&pProxy);
777 ok_ole_success(hr, CoUnmarshalInterface);
778 IStream_Release(pStream);
780 ok_more_than_one_lock();
782 SetEvent(ncu_params.unmarshal_event);
783 WaitForSingleObject(thread, INFINITE);
785 ok_no_locks();
787 CloseHandle(thread);
788 CloseHandle(ncu_params.marshal_event);
789 CloseHandle(ncu_params.unmarshal_event);
791 IUnknown_Release(pProxy);
793 ok_no_locks();
796 /* STA -> STA call during DLL_THREAD_DETACH */
797 static DWORD CALLBACK no_couninitialize_client_proc(LPVOID p)
799 struct ncu_params *ncu_params = (struct ncu_params *)p;
800 HRESULT hr;
801 IUnknown *pProxy = NULL;
803 pCoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
805 hr = CoUnmarshalInterface(ncu_params->stream, &IID_IClassFactory, (void **)&pProxy);
806 ok_ole_success(hr, CoUnmarshalInterface);
807 IStream_Release(ncu_params->stream);
809 ok_more_than_one_lock();
811 /* die without calling CoUninitialize */
813 return 0;
816 /* tests STA -> STA call during DLL_THREAD_DETACH doesn't deadlock */
817 static void test_no_couninitialize_client(void)
819 HRESULT hr;
820 IStream *pStream = NULL;
821 DWORD tid;
822 DWORD host_tid;
823 HANDLE thread;
824 HANDLE host_thread;
825 struct ncu_params ncu_params;
827 cLocks = 0;
829 hr = CreateStreamOnHGlobal(NULL, TRUE, &pStream);
830 ok_ole_success(hr, CreateStreamOnHGlobal);
831 ncu_params.stream = pStream;
833 /* NOTE: assumes start_host_object uses an STA to host the object, as MTAs
834 * always deadlock when called from within DllMain */
835 host_tid = start_host_object(pStream, &IID_IClassFactory, (IUnknown *)&Test_ClassFactory, MSHLFLAGS_NORMAL, &host_thread);
836 IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
838 ok_more_than_one_lock();
840 thread = CreateThread(NULL, 0, no_couninitialize_client_proc, &ncu_params, 0, &tid);
842 WaitForSingleObject(thread, INFINITE);
843 CloseHandle(thread);
845 ok_no_locks();
847 end_host_object(host_tid, host_thread);
850 /* tests success case of a same-thread table-weak marshal, unmarshal, unmarshal */
851 static void test_tableweak_marshal_and_unmarshal_twice(void)
853 HRESULT hr;
854 IStream *pStream = NULL;
855 IUnknown *pProxy1 = NULL;
856 IUnknown *pProxy2 = NULL;
857 DWORD tid;
858 HANDLE thread;
860 cLocks = 0;
862 hr = CreateStreamOnHGlobal(NULL, TRUE, &pStream);
863 ok_ole_success(hr, CreateStreamOnHGlobal);
864 tid = start_host_object(pStream, &IID_IClassFactory, (IUnknown*)&Test_ClassFactory, MSHLFLAGS_TABLEWEAK, &thread);
866 ok_more_than_one_lock();
868 IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
869 hr = CoUnmarshalInterface(pStream, &IID_IClassFactory, (void **)&pProxy1);
870 ok_ole_success(hr, CoUnmarshalInterface);
872 ok_more_than_one_lock();
874 IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
875 hr = CoUnmarshalInterface(pStream, &IID_IClassFactory, (void **)&pProxy2);
876 IStream_Release(pStream);
877 ok_ole_success(hr, CoUnmarshalInterface);
879 ok_more_than_one_lock();
881 IUnknown_Release(pProxy1);
882 IUnknown_Release(pProxy2);
884 /* this line is shows the difference between weak and strong table marshaling:
885 * weak has cLocks == 0
886 * strong has cLocks > 0 */
887 ok_no_locks();
889 end_host_object(tid, thread);
892 /* tests releasing after unmarshaling one object */
893 static void test_tableweak_marshal_releasedata1(void)
895 HRESULT hr;
896 IStream *pStream = NULL;
897 IUnknown *pProxy1 = NULL;
898 IUnknown *pProxy2 = NULL;
899 DWORD tid;
900 HANDLE thread;
902 cLocks = 0;
904 hr = CreateStreamOnHGlobal(NULL, TRUE, &pStream);
905 ok_ole_success(hr, CreateStreamOnHGlobal);
906 tid = start_host_object(pStream, &IID_IClassFactory, (IUnknown*)&Test_ClassFactory, MSHLFLAGS_TABLEWEAK, &thread);
908 ok_more_than_one_lock();
910 IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
911 hr = CoUnmarshalInterface(pStream, &IID_IClassFactory, (void **)&pProxy1);
912 ok_ole_success(hr, CoUnmarshalInterface);
914 ok_more_than_one_lock();
916 /* release the remaining reference on the object by calling
917 * CoReleaseMarshalData in the hosting thread */
918 IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
919 release_host_object(tid);
921 ok_more_than_one_lock();
923 IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
924 hr = CoUnmarshalInterface(pStream, &IID_IClassFactory, (void **)&pProxy2);
925 ok_ole_success(hr, CoUnmarshalInterface);
926 IStream_Release(pStream);
928 ok_more_than_one_lock();
930 IUnknown_Release(pProxy1);
931 if (pProxy2)
932 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_no_locks();
939 end_host_object(tid, thread);
942 /* tests releasing after unmarshaling one object */
943 static void test_tableweak_marshal_releasedata2(void)
945 HRESULT hr;
946 IStream *pStream = NULL;
947 IUnknown *pProxy = NULL;
948 DWORD tid;
949 HANDLE thread;
951 cLocks = 0;
953 hr = CreateStreamOnHGlobal(NULL, TRUE, &pStream);
954 ok_ole_success(hr, CreateStreamOnHGlobal);
955 tid = start_host_object(pStream, &IID_IClassFactory, (IUnknown*)&Test_ClassFactory, MSHLFLAGS_TABLEWEAK, &thread);
957 ok_more_than_one_lock();
959 /* release the remaining reference on the object by calling
960 * CoReleaseMarshalData in the hosting thread */
961 IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
962 release_host_object(tid);
964 ok_no_locks();
966 IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
967 hr = CoUnmarshalInterface(pStream, &IID_IClassFactory, (void **)&pProxy);
968 todo_wine
970 ok(hr == CO_E_OBJNOTREG,
971 "CoUnmarshalInterface should have failed with CO_E_OBJNOTREG, but returned 0x%08x instead\n",
972 hr);
974 IStream_Release(pStream);
976 ok_no_locks();
978 end_host_object(tid, thread);
981 /* tests success case of a same-thread table-strong marshal, unmarshal, unmarshal */
982 static void test_tablestrong_marshal_and_unmarshal_twice(void)
984 HRESULT hr;
985 IStream *pStream = NULL;
986 IUnknown *pProxy1 = NULL;
987 IUnknown *pProxy2 = NULL;
988 DWORD tid;
989 HANDLE thread;
991 cLocks = 0;
993 hr = CreateStreamOnHGlobal(NULL, TRUE, &pStream);
994 ok_ole_success(hr, CreateStreamOnHGlobal);
995 tid = start_host_object(pStream, &IID_IClassFactory, (IUnknown*)&Test_ClassFactory, MSHLFLAGS_TABLESTRONG, &thread);
997 ok_more_than_one_lock();
999 IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
1000 hr = CoUnmarshalInterface(pStream, &IID_IClassFactory, (void **)&pProxy1);
1001 ok_ole_success(hr, CoUnmarshalInterface);
1003 ok_more_than_one_lock();
1005 IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
1006 hr = CoUnmarshalInterface(pStream, &IID_IClassFactory, (void **)&pProxy2);
1007 ok_ole_success(hr, CoUnmarshalInterface);
1009 ok_more_than_one_lock();
1011 if (pProxy1) IUnknown_Release(pProxy1);
1012 if (pProxy2) IUnknown_Release(pProxy2);
1014 /* this line is shows the difference between weak and strong table marshaling:
1015 * weak has cLocks == 0
1016 * strong has cLocks > 0 */
1017 ok_more_than_one_lock();
1019 /* release the remaining reference on the object by calling
1020 * CoReleaseMarshalData in the hosting thread */
1021 IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
1022 release_host_object(tid);
1023 IStream_Release(pStream);
1025 ok_no_locks();
1027 end_host_object(tid, thread);
1030 /* tests CoLockObjectExternal */
1031 static void test_lock_object_external(void)
1033 HRESULT hr;
1034 IStream *pStream = NULL;
1036 cLocks = 0;
1038 /* test the stub manager creation aspect of CoLockObjectExternal when the
1039 * object hasn't been marshaled yet */
1040 CoLockObjectExternal((IUnknown*)&Test_ClassFactory, TRUE, TRUE);
1042 ok_more_than_one_lock();
1044 CoDisconnectObject((IUnknown*)&Test_ClassFactory, 0);
1046 ok_no_locks();
1048 /* test our empty stub manager being handled correctly in
1049 * CoMarshalInterface */
1050 CoLockObjectExternal((IUnknown*)&Test_ClassFactory, TRUE, TRUE);
1052 hr = CreateStreamOnHGlobal(NULL, TRUE, &pStream);
1053 ok_ole_success(hr, CreateStreamOnHGlobal);
1054 hr = CoMarshalInterface(pStream, &IID_IClassFactory, (IUnknown*)&Test_ClassFactory, MSHCTX_INPROC, NULL, MSHLFLAGS_NORMAL);
1055 ok_ole_success(hr, CoMarshalInterface);
1057 CoLockObjectExternal((IUnknown*)&Test_ClassFactory, TRUE, TRUE);
1059 ok_more_than_one_lock();
1061 IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
1062 hr = CoReleaseMarshalData(pStream);
1063 ok_ole_success(hr, CoReleaseMarshalData);
1064 IStream_Release(pStream);
1066 ok_more_than_one_lock();
1068 CoLockObjectExternal((IUnknown*)&Test_ClassFactory, FALSE, TRUE);
1070 ok_more_than_one_lock();
1072 CoLockObjectExternal((IUnknown*)&Test_ClassFactory, FALSE, TRUE);
1074 ok_no_locks();
1077 /* tests disconnecting stubs */
1078 static void test_disconnect_stub(void)
1080 HRESULT hr;
1081 IStream *pStream = NULL;
1083 cLocks = 0;
1085 hr = CreateStreamOnHGlobal(NULL, TRUE, &pStream);
1086 ok_ole_success(hr, CreateStreamOnHGlobal);
1087 hr = CoMarshalInterface(pStream, &IID_IClassFactory, (IUnknown*)&Test_ClassFactory, MSHCTX_INPROC, NULL, MSHLFLAGS_NORMAL);
1088 ok_ole_success(hr, CoMarshalInterface);
1090 CoLockObjectExternal((IUnknown*)&Test_ClassFactory, TRUE, TRUE);
1092 ok_more_than_one_lock();
1094 IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
1095 hr = CoReleaseMarshalData(pStream);
1096 ok_ole_success(hr, CoReleaseMarshalData);
1097 IStream_Release(pStream);
1099 ok_more_than_one_lock();
1101 CoDisconnectObject((IUnknown*)&Test_ClassFactory, 0);
1103 ok_no_locks();
1106 /* tests failure case of a same-thread marshal and unmarshal twice */
1107 static void test_normal_marshal_and_unmarshal_twice(void)
1109 HRESULT hr;
1110 IStream *pStream = NULL;
1111 IUnknown *pProxy1 = NULL;
1112 IUnknown *pProxy2 = NULL;
1114 cLocks = 0;
1116 hr = CreateStreamOnHGlobal(NULL, TRUE, &pStream);
1117 ok_ole_success(hr, CreateStreamOnHGlobal);
1118 hr = CoMarshalInterface(pStream, &IID_IClassFactory, (IUnknown*)&Test_ClassFactory, MSHCTX_INPROC, NULL, MSHLFLAGS_NORMAL);
1119 ok_ole_success(hr, CoMarshalInterface);
1121 ok_more_than_one_lock();
1123 IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
1124 hr = CoUnmarshalInterface(pStream, &IID_IClassFactory, (void **)&pProxy1);
1125 ok_ole_success(hr, CoUnmarshalInterface);
1127 ok_more_than_one_lock();
1129 IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
1130 hr = CoUnmarshalInterface(pStream, &IID_IClassFactory, (void **)&pProxy2);
1131 ok(hr == CO_E_OBJNOTCONNECTED,
1132 "CoUnmarshalInterface should have failed with error CO_E_OBJNOTCONNECTED for double unmarshal, instead of 0x%08x\n", hr);
1134 IStream_Release(pStream);
1136 ok_more_than_one_lock();
1138 IUnknown_Release(pProxy1);
1140 ok_no_locks();
1143 /* tests success case of marshaling and unmarshaling an HRESULT */
1144 static void test_hresult_marshaling(void)
1146 HRESULT hr;
1147 HRESULT hr_marshaled = 0;
1148 IStream *pStream = NULL;
1149 static const HRESULT E_DEADBEEF = 0xdeadbeef;
1151 hr = CreateStreamOnHGlobal(NULL, TRUE, &pStream);
1152 ok_ole_success(hr, CreateStreamOnHGlobal);
1154 hr = CoMarshalHresult(pStream, E_DEADBEEF);
1155 ok_ole_success(hr, CoMarshalHresult);
1157 IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
1158 hr = IStream_Read(pStream, &hr_marshaled, sizeof(HRESULT), NULL);
1159 ok_ole_success(hr, IStream_Read);
1161 ok(hr_marshaled == E_DEADBEEF, "Didn't marshal HRESULT as expected: got value 0x%08x instead\n", hr_marshaled);
1163 hr_marshaled = 0;
1164 IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
1165 hr = CoUnmarshalHresult(pStream, &hr_marshaled);
1166 ok_ole_success(hr, CoUnmarshalHresult);
1168 ok(hr_marshaled == E_DEADBEEF, "Didn't marshal HRESULT as expected: got value 0x%08x instead\n", hr_marshaled);
1170 IStream_Release(pStream);
1174 /* helper for test_proxy_used_in_wrong_thread */
1175 static DWORD CALLBACK bad_thread_proc(LPVOID p)
1177 IClassFactory * cf = (IClassFactory *)p;
1178 HRESULT hr;
1179 IUnknown * proxy = NULL;
1181 pCoInitializeEx(NULL, COINIT_MULTITHREADED);
1183 hr = IClassFactory_CreateInstance(cf, NULL, &IID_IUnknown, (LPVOID*)&proxy);
1184 if (proxy) IUnknown_Release(proxy);
1185 ok(hr == RPC_E_WRONG_THREAD,
1186 "COM should have failed with RPC_E_WRONG_THREAD on using proxy from wrong apartment, but instead returned 0x%08x\n",
1187 hr);
1189 CoUninitialize();
1191 return 0;
1194 /* tests failure case of a using a proxy in the wrong apartment */
1195 static void test_proxy_used_in_wrong_thread(void)
1197 HRESULT hr;
1198 IStream *pStream = NULL;
1199 IUnknown *pProxy = NULL;
1200 DWORD tid, tid2;
1201 HANDLE thread;
1202 HANDLE host_thread;
1204 cLocks = 0;
1206 hr = CreateStreamOnHGlobal(NULL, TRUE, &pStream);
1207 ok_ole_success(hr, CreateStreamOnHGlobal);
1208 tid = start_host_object(pStream, &IID_IClassFactory, (IUnknown*)&Test_ClassFactory, MSHLFLAGS_NORMAL, &host_thread);
1210 ok_more_than_one_lock();
1212 IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
1213 hr = CoUnmarshalInterface(pStream, &IID_IClassFactory, (void **)&pProxy);
1214 ok_ole_success(hr, CoUnmarshalInterface);
1215 IStream_Release(pStream);
1217 ok_more_than_one_lock();
1219 /* create a thread that we can misbehave in */
1220 thread = CreateThread(NULL, 0, bad_thread_proc, (LPVOID)pProxy, 0, &tid2);
1222 WaitForSingleObject(thread, INFINITE);
1223 CloseHandle(thread);
1225 IUnknown_Release(pProxy);
1227 ok_no_locks();
1229 end_host_object(tid, host_thread);
1232 static HRESULT WINAPI MessageFilter_QueryInterface(IMessageFilter *iface, REFIID riid, void ** ppvObj)
1234 if (ppvObj == NULL) return E_POINTER;
1236 if (IsEqualGUID(riid, &IID_IUnknown) ||
1237 IsEqualGUID(riid, &IID_IClassFactory))
1239 *ppvObj = (LPVOID)iface;
1240 IClassFactory_AddRef(iface);
1241 return S_OK;
1244 return E_NOINTERFACE;
1247 static ULONG WINAPI MessageFilter_AddRef(IMessageFilter *iface)
1249 return 2; /* non-heap object */
1252 static ULONG WINAPI MessageFilter_Release(IMessageFilter *iface)
1254 return 1; /* non-heap object */
1257 static DWORD WINAPI MessageFilter_HandleInComingCall(
1258 IMessageFilter *iface,
1259 DWORD dwCallType,
1260 HTASK threadIDCaller,
1261 DWORD dwTickCount,
1262 LPINTERFACEINFO lpInterfaceInfo)
1264 static int callcount = 0;
1265 DWORD ret;
1266 trace("HandleInComingCall\n");
1267 switch (callcount)
1269 case 0:
1270 ret = SERVERCALL_REJECTED;
1271 break;
1272 case 1:
1273 ret = SERVERCALL_RETRYLATER;
1274 break;
1275 default:
1276 ret = SERVERCALL_ISHANDLED;
1277 break;
1279 callcount++;
1280 return ret;
1283 static DWORD WINAPI MessageFilter_RetryRejectedCall(
1284 IMessageFilter *iface,
1285 HTASK threadIDCallee,
1286 DWORD dwTickCount,
1287 DWORD dwRejectType)
1289 trace("RetryRejectedCall\n");
1290 return 0;
1293 static DWORD WINAPI MessageFilter_MessagePending(
1294 IMessageFilter *iface,
1295 HTASK threadIDCallee,
1296 DWORD dwTickCount,
1297 DWORD dwPendingType)
1299 trace("MessagePending\n");
1300 return PENDINGMSG_WAITNOPROCESS;
1303 static const IMessageFilterVtbl MessageFilter_Vtbl =
1305 MessageFilter_QueryInterface,
1306 MessageFilter_AddRef,
1307 MessageFilter_Release,
1308 MessageFilter_HandleInComingCall,
1309 MessageFilter_RetryRejectedCall,
1310 MessageFilter_MessagePending
1313 static IMessageFilter MessageFilter = { &MessageFilter_Vtbl };
1315 static void test_message_filter(void)
1317 HRESULT hr;
1318 IStream *pStream = NULL;
1319 IClassFactory *cf = NULL;
1320 DWORD tid;
1321 IUnknown *proxy = NULL;
1322 IMessageFilter *prev_filter = NULL;
1323 HANDLE thread;
1325 cLocks = 0;
1327 hr = CreateStreamOnHGlobal(NULL, TRUE, &pStream);
1328 ok_ole_success(hr, CreateStreamOnHGlobal);
1329 tid = start_host_object2(pStream, &IID_IClassFactory, (IUnknown*)&Test_ClassFactory, MSHLFLAGS_NORMAL, &MessageFilter, &thread);
1331 ok_more_than_one_lock();
1333 IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
1334 hr = CoUnmarshalInterface(pStream, &IID_IClassFactory, (void **)&cf);
1335 ok_ole_success(hr, CoUnmarshalInterface);
1336 IStream_Release(pStream);
1338 ok_more_than_one_lock();
1340 hr = IClassFactory_CreateInstance(cf, NULL, &IID_IUnknown, (LPVOID*)&proxy);
1341 ok(hr == RPC_E_CALL_REJECTED, "Call should have returned RPC_E_CALL_REJECTED, but return 0x%08x instead\n", hr);
1342 if (proxy) IUnknown_Release(proxy);
1343 proxy = NULL;
1345 hr = CoRegisterMessageFilter(&MessageFilter, &prev_filter);
1346 ok_ole_success(hr, CoRegisterMessageFilter);
1348 hr = IClassFactory_CreateInstance(cf, NULL, &IID_IUnknown, (LPVOID*)&proxy);
1349 ok_ole_success(hr, IClassFactory_CreateInstance);
1351 IUnknown_Release(proxy);
1353 IClassFactory_Release(cf);
1355 ok_no_locks();
1357 end_host_object(tid, thread);
1359 hr = CoRegisterMessageFilter(prev_filter, NULL);
1360 ok_ole_success(hr, CoRegisterMessageFilter);
1363 /* test failure case of trying to unmarshal from bad stream */
1364 static void test_bad_marshal_stream(void)
1366 HRESULT hr;
1367 IStream *pStream = NULL;
1369 hr = CreateStreamOnHGlobal(NULL, TRUE, &pStream);
1370 ok_ole_success(hr, CreateStreamOnHGlobal);
1371 hr = CoMarshalInterface(pStream, &IID_IClassFactory, (IUnknown*)&Test_ClassFactory, MSHCTX_INPROC, NULL, MSHLFLAGS_NORMAL);
1372 ok_ole_success(hr, CoMarshalInterface);
1374 ok_more_than_one_lock();
1376 /* try to read beyond end of stream */
1377 hr = CoReleaseMarshalData(pStream);
1378 ok(hr == STG_E_READFAULT, "Should have failed with STG_E_READFAULT, but returned 0x%08x instead\n", hr);
1380 /* now release for real */
1381 IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
1382 hr = CoReleaseMarshalData(pStream);
1383 ok_ole_success(hr, CoReleaseMarshalData);
1385 IStream_Release(pStream);
1388 /* tests that proxies implement certain interfaces */
1389 static void test_proxy_interfaces(void)
1391 HRESULT hr;
1392 IStream *pStream = NULL;
1393 IUnknown *pProxy = NULL;
1394 IUnknown *pOtherUnknown = NULL;
1395 DWORD tid;
1396 HANDLE thread;
1398 cLocks = 0;
1400 hr = CreateStreamOnHGlobal(NULL, TRUE, &pStream);
1401 ok_ole_success(hr, CreateStreamOnHGlobal);
1402 tid = start_host_object(pStream, &IID_IClassFactory, (IUnknown*)&Test_ClassFactory, MSHLFLAGS_NORMAL, &thread);
1404 ok_more_than_one_lock();
1406 IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
1407 hr = CoUnmarshalInterface(pStream, &IID_IUnknown, (void **)&pProxy);
1408 ok_ole_success(hr, CoUnmarshalInterface);
1409 IStream_Release(pStream);
1411 ok_more_than_one_lock();
1413 hr = IUnknown_QueryInterface(pProxy, &IID_IUnknown, (LPVOID*)&pOtherUnknown);
1414 ok_ole_success(hr, IUnknown_QueryInterface IID_IUnknown);
1415 if (hr == S_OK) IUnknown_Release(pOtherUnknown);
1417 hr = IUnknown_QueryInterface(pProxy, &IID_IClientSecurity, (LPVOID*)&pOtherUnknown);
1418 ok_ole_success(hr, IUnknown_QueryInterface IID_IClientSecurity);
1419 if (hr == S_OK) IUnknown_Release(pOtherUnknown);
1421 hr = IUnknown_QueryInterface(pProxy, &IID_IMultiQI, (LPVOID*)&pOtherUnknown);
1422 ok_ole_success(hr, IUnknown_QueryInterface IID_IMultiQI);
1423 if (hr == S_OK) IUnknown_Release(pOtherUnknown);
1425 hr = IUnknown_QueryInterface(pProxy, &IID_IMarshal, (LPVOID*)&pOtherUnknown);
1426 ok_ole_success(hr, IUnknown_QueryInterface IID_IMarshal);
1427 if (hr == S_OK) IUnknown_Release(pOtherUnknown);
1429 /* IMarshal2 is also supported on NT-based systems, but is pretty much
1430 * useless as it has no more methods over IMarshal that it inherits from. */
1432 IUnknown_Release(pProxy);
1434 ok_no_locks();
1436 end_host_object(tid, thread);
1439 typedef struct
1441 const IUnknownVtbl *lpVtbl;
1442 ULONG refs;
1443 } HeapUnknown;
1445 static HRESULT WINAPI HeapUnknown_QueryInterface(IUnknown *iface, REFIID riid, void **ppv)
1447 if (IsEqualIID(riid, &IID_IUnknown))
1449 IUnknown_AddRef(iface);
1450 *ppv = (LPVOID)iface;
1451 return S_OK;
1453 *ppv = NULL;
1454 return E_NOINTERFACE;
1457 static ULONG WINAPI HeapUnknown_AddRef(IUnknown *iface)
1459 HeapUnknown *This = (HeapUnknown *)iface;
1460 return InterlockedIncrement((LONG*)&This->refs);
1463 static ULONG WINAPI HeapUnknown_Release(IUnknown *iface)
1465 HeapUnknown *This = (HeapUnknown *)iface;
1466 ULONG refs = InterlockedDecrement((LONG*)&This->refs);
1467 if (!refs) HeapFree(GetProcessHeap(), 0, This);
1468 return refs;
1471 static const IUnknownVtbl HeapUnknown_Vtbl =
1473 HeapUnknown_QueryInterface,
1474 HeapUnknown_AddRef,
1475 HeapUnknown_Release
1478 static void test_proxybuffer(REFIID riid)
1480 HRESULT hr;
1481 IPSFactoryBuffer *psfb;
1482 IRpcProxyBuffer *proxy;
1483 LPVOID lpvtbl;
1484 ULONG refs;
1485 CLSID clsid;
1486 HeapUnknown *pUnkOuter = (HeapUnknown *)HeapAlloc(GetProcessHeap(), 0, sizeof(*pUnkOuter));
1488 pUnkOuter->lpVtbl = &HeapUnknown_Vtbl;
1489 pUnkOuter->refs = 1;
1491 hr = CoGetPSClsid(riid, &clsid);
1492 ok_ole_success(hr, CoGetPSClsid);
1494 hr = CoGetClassObject(&clsid, CLSCTX_INPROC_SERVER, NULL, &IID_IPSFactoryBuffer, (LPVOID*)&psfb);
1495 ok_ole_success(hr, CoGetClassObject);
1497 hr = IPSFactoryBuffer_CreateProxy(psfb, (IUnknown*)pUnkOuter, riid, &proxy, &lpvtbl);
1498 ok_ole_success(hr, IPSFactoryBuffer_CreateProxy);
1499 ok(lpvtbl != NULL, "IPSFactoryBuffer_CreateProxy succeeded, but returned a NULL vtable!\n");
1501 /* release our reference to the outer unknown object - the PS factory
1502 * buffer will have AddRef's it in the CreateProxy call */
1503 refs = IUnknown_Release((IUnknown *)pUnkOuter);
1504 ok(refs == 1, "Ref count of outer unknown should have been 1 instead of %d\n", refs);
1506 refs = IPSFactoryBuffer_Release(psfb);
1507 if (0)
1509 /* not reliable on native. maybe it leaks references! */
1510 ok(refs == 0, "Ref-count leak of %d on IPSFactoryBuffer\n", refs);
1513 refs = IUnknown_Release((IUnknown *)lpvtbl);
1514 ok(refs == 0, "Ref-count leak of %d on IRpcProxyBuffer\n", refs);
1516 refs = IRpcProxyBuffer_Release(proxy);
1517 ok(refs == 0, "Ref-count leak of %d on IRpcProxyBuffer\n", refs);
1520 static void test_stubbuffer(REFIID riid)
1522 HRESULT hr;
1523 IPSFactoryBuffer *psfb;
1524 IRpcStubBuffer *stub;
1525 ULONG refs;
1526 CLSID clsid;
1528 cLocks = 0;
1530 hr = CoGetPSClsid(riid, &clsid);
1531 ok_ole_success(hr, CoGetPSClsid);
1533 hr = CoGetClassObject(&clsid, CLSCTX_INPROC_SERVER, NULL, &IID_IPSFactoryBuffer, (LPVOID*)&psfb);
1534 ok_ole_success(hr, CoGetClassObject);
1536 hr = IPSFactoryBuffer_CreateStub(psfb, riid, (IUnknown*)&Test_ClassFactory, &stub);
1537 ok_ole_success(hr, IPSFactoryBuffer_CreateStub);
1539 refs = IPSFactoryBuffer_Release(psfb);
1540 if (0)
1542 /* not reliable on native. maybe it leaks references */
1543 ok(refs == 0, "Ref-count leak of %d on IPSFactoryBuffer\n", refs);
1546 ok_more_than_one_lock();
1548 IRpcStubBuffer_Disconnect(stub);
1550 ok_no_locks();
1552 refs = IRpcStubBuffer_Release(stub);
1553 ok(refs == 0, "Ref-count leak of %d on IRpcProxyBuffer\n", refs);
1556 static HWND hwnd_app;
1558 static HRESULT WINAPI TestRE_IClassFactory_CreateInstance(
1559 LPCLASSFACTORY iface,
1560 LPUNKNOWN pUnkOuter,
1561 REFIID riid,
1562 LPVOID *ppvObj)
1564 DWORD_PTR res;
1565 if (IsEqualIID(riid, &IID_IWineTest))
1567 BOOL ret = SendMessageTimeout(hwnd_app, WM_NULL, 0, 0, SMTO_BLOCK, 5000, &res);
1568 ok(ret, "Timed out sending a message to originating window during RPC call\n");
1570 return S_FALSE;
1573 static const IClassFactoryVtbl TestREClassFactory_Vtbl =
1575 Test_IClassFactory_QueryInterface,
1576 Test_IClassFactory_AddRef,
1577 Test_IClassFactory_Release,
1578 TestRE_IClassFactory_CreateInstance,
1579 Test_IClassFactory_LockServer
1582 IClassFactory TestRE_ClassFactory = { &TestREClassFactory_Vtbl };
1584 static LRESULT CALLBACK window_proc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam)
1586 switch (msg)
1588 case WM_USER:
1590 HRESULT hr;
1591 IStream *pStream = NULL;
1592 IClassFactory *proxy = NULL;
1593 IUnknown *object;
1594 DWORD tid;
1595 HANDLE thread;
1597 cLocks = 0;
1599 hr = CreateStreamOnHGlobal(NULL, TRUE, &pStream);
1600 ok_ole_success(hr, CreateStreamOnHGlobal);
1601 tid = start_host_object(pStream, &IID_IClassFactory, (IUnknown*)&TestRE_ClassFactory, MSHLFLAGS_NORMAL, &thread);
1603 ok_more_than_one_lock();
1605 IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
1606 hr = CoUnmarshalInterface(pStream, &IID_IClassFactory, (void **)&proxy);
1607 ok_ole_success(hr, CoReleaseMarshalData);
1608 IStream_Release(pStream);
1610 ok_more_than_one_lock();
1612 /* note the use of the magic IID_IWineTest value to tell remote thread
1613 * to try to send a message back to us */
1614 hr = IClassFactory_CreateInstance(proxy, NULL, &IID_IWineTest, (void **)&object);
1616 IClassFactory_Release(proxy);
1618 ok_no_locks();
1620 end_host_object(tid, thread);
1622 PostMessage(hwnd, WM_QUIT, 0, 0);
1624 return 0;
1626 case WM_USER+1:
1628 HRESULT hr;
1629 IStream *pStream = NULL;
1630 IClassFactory *proxy = NULL;
1631 IUnknown *object;
1632 DWORD tid;
1633 HANDLE thread;
1635 cLocks = 0;
1637 hr = CreateStreamOnHGlobal(NULL, TRUE, &pStream);
1638 ok_ole_success(hr, CreateStreamOnHGlobal);
1639 tid = start_host_object(pStream, &IID_IClassFactory, (IUnknown*)&TestRE_ClassFactory, MSHLFLAGS_NORMAL, &thread);
1641 ok_more_than_one_lock();
1643 IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
1644 hr = CoUnmarshalInterface(pStream, &IID_IClassFactory, (void **)&proxy);
1645 ok_ole_success(hr, CoReleaseMarshalData);
1646 IStream_Release(pStream);
1648 ok_more_than_one_lock();
1650 /* post quit message before a doing a COM call to show that a pending
1651 * WM_QUIT message doesn't stop the call from succeeding */
1652 PostMessage(hwnd, WM_QUIT, 0, 0);
1653 hr = IClassFactory_CreateInstance(proxy, NULL, &IID_IUnknown, (void **)&object);
1655 IClassFactory_Release(proxy);
1657 ok_no_locks();
1659 end_host_object(tid, thread);
1661 return 0;
1663 case WM_USER+2:
1665 HRESULT hr;
1666 IStream *pStream = NULL;
1667 IClassFactory *proxy = NULL;
1668 IUnknown *object;
1669 DWORD tid;
1670 HANDLE thread;
1672 hr = CreateStreamOnHGlobal(NULL, TRUE, &pStream);
1673 ok_ole_success(hr, CreateStreamOnHGlobal);
1674 tid = start_host_object(pStream, &IID_IClassFactory, (IUnknown*)&Test_ClassFactory, MSHLFLAGS_NORMAL, &thread);
1676 IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
1677 hr = CoUnmarshalInterface(pStream, &IID_IClassFactory, (void **)&proxy);
1678 ok_ole_success(hr, CoReleaseMarshalData);
1679 IStream_Release(pStream);
1681 /* shows that COM calls executed during the processing of sent
1682 * messages should fail */
1683 hr = IClassFactory_CreateInstance(proxy, NULL, &IID_IUnknown, (void **)&object);
1684 ok(hr == RPC_E_CANTCALLOUT_ININPUTSYNCCALL,
1685 "COM call during processing of sent message should return RPC_E_CANTCALLOUT_ININPUTSYNCCALL instead of 0x%08x\n", hr);
1687 IClassFactory_Release(proxy);
1689 end_host_object(tid, thread);
1691 PostQuitMessage(0);
1693 return 0;
1695 default:
1696 return DefWindowProc(hwnd, msg, wparam, lparam);
1700 static void test_message_reentrancy(void)
1702 WNDCLASS wndclass;
1703 MSG msg;
1705 memset(&wndclass, 0, sizeof(wndclass));
1706 wndclass.lpfnWndProc = window_proc;
1707 wndclass.lpszClassName = "WineCOMTest";
1708 RegisterClass(&wndclass);
1710 hwnd_app = CreateWindow("WineCOMTest", NULL, 0, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, NULL, NULL, NULL, 0);
1711 ok(hwnd_app != NULL, "Window creation failed\n");
1713 /* start message re-entrancy test */
1714 PostMessage(hwnd_app, WM_USER, 0, 0);
1716 while (GetMessage(&msg, NULL, 0, 0))
1718 TranslateMessage(&msg);
1719 DispatchMessage(&msg);
1723 static HRESULT WINAPI TestMsg_IClassFactory_CreateInstance(
1724 LPCLASSFACTORY iface,
1725 LPUNKNOWN pUnkOuter,
1726 REFIID riid,
1727 LPVOID *ppvObj)
1729 *ppvObj = NULL;
1730 SendMessage(hwnd_app, WM_USER+2, 0, 0);
1731 return S_OK;
1734 static IClassFactoryVtbl TestMsgClassFactory_Vtbl =
1736 Test_IClassFactory_QueryInterface,
1737 Test_IClassFactory_AddRef,
1738 Test_IClassFactory_Release,
1739 TestMsg_IClassFactory_CreateInstance,
1740 Test_IClassFactory_LockServer
1743 IClassFactory TestMsg_ClassFactory = { &TestMsgClassFactory_Vtbl };
1745 static void test_call_from_message(void)
1747 MSG msg;
1748 IStream *pStream;
1749 HRESULT hr;
1750 IClassFactory *proxy;
1751 DWORD tid;
1752 HANDLE thread;
1753 IUnknown *object;
1755 hwnd_app = CreateWindow("WineCOMTest", NULL, 0, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, NULL, NULL, NULL, 0);
1756 ok(hwnd_app != NULL, "Window creation failed\n");
1758 hr = CreateStreamOnHGlobal(NULL, TRUE, &pStream);
1759 ok_ole_success(hr, CreateStreamOnHGlobal);
1760 tid = start_host_object(pStream, &IID_IClassFactory, (IUnknown*)&TestMsg_ClassFactory, MSHLFLAGS_NORMAL, &thread);
1762 ok_more_than_one_lock();
1764 IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
1765 hr = CoUnmarshalInterface(pStream, &IID_IClassFactory, (void **)&proxy);
1766 ok_ole_success(hr, CoReleaseMarshalData);
1767 IStream_Release(pStream);
1769 ok_more_than_one_lock();
1771 /* start message re-entrancy test */
1772 hr = IClassFactory_CreateInstance(proxy, NULL, &IID_IUnknown, (void **)&object);
1773 ok_ole_success(hr, IClassFactory_CreateInstance);
1775 IClassFactory_Release(proxy);
1777 ok_no_locks();
1779 end_host_object(tid, thread);
1781 while (GetMessage(&msg, NULL, 0, 0))
1783 TranslateMessage(&msg);
1784 DispatchMessage(&msg);
1788 static void test_WM_QUIT_handling(void)
1790 MSG msg;
1792 hwnd_app = CreateWindow("WineCOMTest", NULL, 0, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, NULL, NULL, NULL, 0);
1793 ok(hwnd_app != NULL, "Window creation failed\n");
1795 /* start WM_QUIT handling test */
1796 PostMessage(hwnd_app, WM_USER+1, 0, 0);
1798 while (GetMessage(&msg, NULL, 0, 0))
1800 TranslateMessage(&msg);
1801 DispatchMessage(&msg);
1805 static void test_freethreadedmarshaldata(IStream *pStream, MSHCTX mshctx, void *ptr, DWORD mshlflags)
1807 HGLOBAL hglobal;
1808 DWORD size;
1809 char *marshal_data;
1810 HRESULT hr;
1812 hr = GetHGlobalFromStream(pStream, &hglobal);
1813 ok_ole_success(hr, GetHGlobalFromStream);
1815 size = GlobalSize(hglobal);
1817 marshal_data = (char *)GlobalLock(hglobal);
1819 if (mshctx == MSHCTX_INPROC)
1821 DWORD expected_size = sizeof(DWORD) + sizeof(void *) + sizeof(DWORD) + sizeof(GUID);
1822 ok(size == expected_size, "size should have been %d instead of %d\n", expected_size, size);
1824 ok(*(DWORD *)marshal_data == mshlflags, "expected 0x%x, but got 0x%x for mshctx\n", mshlflags, *(DWORD *)marshal_data);
1825 marshal_data += sizeof(DWORD);
1826 ok(*(void **)marshal_data == ptr, "expected %p, but got %p for mshctx\n", ptr, *(void **)marshal_data);
1827 marshal_data += sizeof(void *);
1828 ok(*(DWORD *)marshal_data == 0, "expected 0x0, but got 0x%x\n", *(DWORD *)marshal_data);
1829 marshal_data += sizeof(DWORD);
1830 trace("got guid data: {%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x}\n",
1831 ((GUID *)marshal_data)->Data1, ((GUID *)marshal_data)->Data2, ((GUID *)marshal_data)->Data3,
1832 ((GUID *)marshal_data)->Data4[0], ((GUID *)marshal_data)->Data4[1], ((GUID *)marshal_data)->Data4[2], ((GUID *)marshal_data)->Data4[3],
1833 ((GUID *)marshal_data)->Data4[4], ((GUID *)marshal_data)->Data4[5], ((GUID *)marshal_data)->Data4[6], ((GUID *)marshal_data)->Data4[7]);
1835 else
1837 ok(size > sizeof(DWORD), "size should have been > sizeof(DWORD), not %d\n", size);
1838 ok(*(DWORD *)marshal_data == 0x574f454d /* MEOW */,
1839 "marshal data should be filled by standard marshal and start with MEOW signature\n");
1842 GlobalUnlock(hglobal);
1845 static void test_freethreadedmarshaler(void)
1847 HRESULT hr;
1848 IUnknown *pFTUnknown;
1849 IMarshal *pFTMarshal;
1850 IStream *pStream;
1851 IUnknown *pProxy;
1852 static const LARGE_INTEGER llZero;
1854 cLocks = 0;
1855 hr = CoCreateFreeThreadedMarshaler(NULL, &pFTUnknown);
1856 ok_ole_success(hr, CoCreateFreeThreadedMarshaler);
1857 hr = IUnknown_QueryInterface(pFTUnknown, &IID_IMarshal, (void **)&pFTMarshal);
1858 ok_ole_success(hr, IUnknown_QueryInterface);
1859 IUnknown_Release(pFTUnknown);
1861 hr = CreateStreamOnHGlobal(NULL, TRUE, &pStream);
1862 ok_ole_success(hr, CreateStreamOnHGlobal);
1864 /* inproc normal marshaling */
1866 hr = IMarshal_MarshalInterface(pFTMarshal, pStream, &IID_IClassFactory,
1867 (IUnknown*)&Test_ClassFactory, MSHCTX_INPROC, NULL, MSHLFLAGS_NORMAL);
1868 ok_ole_success(hr, IMarshal_MarshalInterface);
1870 ok_more_than_one_lock();
1872 test_freethreadedmarshaldata(pStream, MSHCTX_INPROC, &Test_ClassFactory, MSHLFLAGS_NORMAL);
1874 IStream_Seek(pStream, llZero, STREAM_SEEK_SET, NULL);
1875 hr = IMarshal_UnmarshalInterface(pFTMarshal, pStream, &IID_IUnknown, (void **)&pProxy);
1876 ok_ole_success(hr, IMarshal_UnmarshalInterface);
1878 IUnknown_Release(pProxy);
1880 ok_no_locks();
1882 /* native doesn't allow us to unmarshal or release the stream data,
1883 * presumably because it wants us to call CoMarshalInterface instead */
1884 if (0)
1886 /* local normal marshaling */
1888 IStream_Seek(pStream, llZero, STREAM_SEEK_SET, NULL);
1889 hr = IMarshal_MarshalInterface(pFTMarshal, pStream, &IID_IClassFactory, (IUnknown*)&Test_ClassFactory, MSHCTX_LOCAL, NULL, MSHLFLAGS_NORMAL);
1890 ok_ole_success(hr, IMarshal_MarshalInterface);
1892 ok_more_than_one_lock();
1894 test_freethreadedmarshaldata(pStream, MSHCTX_LOCAL, &Test_ClassFactory, MSHLFLAGS_NORMAL);
1896 IStream_Seek(pStream, llZero, STREAM_SEEK_SET, NULL);
1897 hr = IMarshal_ReleaseMarshalData(pFTMarshal, pStream);
1898 ok_ole_success(hr, IMarshal_ReleaseMarshalData);
1900 ok_no_locks();
1903 /* inproc table-strong marshaling */
1905 IStream_Seek(pStream, llZero, STREAM_SEEK_SET, NULL);
1906 hr = IMarshal_MarshalInterface(pFTMarshal, pStream, &IID_IClassFactory,
1907 (IUnknown*)&Test_ClassFactory, MSHCTX_INPROC, (void *)0xdeadbeef,
1908 MSHLFLAGS_TABLESTRONG);
1909 ok_ole_success(hr, IMarshal_MarshalInterface);
1911 ok_more_than_one_lock();
1913 test_freethreadedmarshaldata(pStream, MSHCTX_INPROC, &Test_ClassFactory, MSHLFLAGS_TABLESTRONG);
1915 IStream_Seek(pStream, llZero, STREAM_SEEK_SET, NULL);
1916 hr = IMarshal_UnmarshalInterface(pFTMarshal, pStream, &IID_IUnknown, (void **)&pProxy);
1917 ok_ole_success(hr, IMarshal_UnmarshalInterface);
1919 IUnknown_Release(pProxy);
1921 ok_more_than_one_lock();
1923 IStream_Seek(pStream, llZero, STREAM_SEEK_SET, NULL);
1924 hr = IMarshal_ReleaseMarshalData(pFTMarshal, pStream);
1925 ok_ole_success(hr, IMarshal_ReleaseMarshalData);
1927 ok_no_locks();
1929 /* inproc table-weak marshaling */
1931 IStream_Seek(pStream, llZero, STREAM_SEEK_SET, NULL);
1932 hr = IMarshal_MarshalInterface(pFTMarshal, pStream, &IID_IClassFactory,
1933 (IUnknown*)&Test_ClassFactory, MSHCTX_INPROC, (void *)0xdeadbeef,
1934 MSHLFLAGS_TABLEWEAK);
1935 ok_ole_success(hr, IMarshal_MarshalInterface);
1937 ok_no_locks();
1939 test_freethreadedmarshaldata(pStream, MSHCTX_INPROC, &Test_ClassFactory, MSHLFLAGS_TABLEWEAK);
1941 IStream_Seek(pStream, llZero, STREAM_SEEK_SET, NULL);
1942 hr = IMarshal_UnmarshalInterface(pFTMarshal, pStream, &IID_IUnknown, (void **)&pProxy);
1943 ok_ole_success(hr, IMarshal_UnmarshalInterface);
1945 ok_more_than_one_lock();
1947 IUnknown_Release(pProxy);
1949 ok_no_locks();
1951 /* inproc normal marshaling (for extraordinary cases) */
1953 IStream_Seek(pStream, llZero, STREAM_SEEK_SET, NULL);
1954 hr = IMarshal_MarshalInterface(pFTMarshal, pStream, &IID_IClassFactory,
1955 (IUnknown*)&Test_ClassFactory, MSHCTX_INPROC, NULL, MSHLFLAGS_NORMAL);
1956 ok_ole_success(hr, IMarshal_MarshalInterface);
1958 ok_more_than_one_lock();
1960 /* this call shows that DisconnectObject does nothing */
1961 hr = IMarshal_DisconnectObject(pFTMarshal, 0);
1962 ok_ole_success(hr, IMarshal_DisconnectObject);
1964 ok_more_than_one_lock();
1966 IStream_Seek(pStream, llZero, STREAM_SEEK_SET, NULL);
1967 hr = IMarshal_ReleaseMarshalData(pFTMarshal, pStream);
1968 ok_ole_success(hr, IMarshal_ReleaseMarshalData);
1970 ok_no_locks();
1972 /* doesn't enforce marshaling rules here and allows us to unmarshal the
1973 * interface, even though it was freed above */
1974 IStream_Seek(pStream, llZero, STREAM_SEEK_SET, NULL);
1975 hr = IMarshal_UnmarshalInterface(pFTMarshal, pStream, &IID_IUnknown, (void **)&pProxy);
1976 ok_ole_success(hr, IMarshal_UnmarshalInterface);
1978 ok_no_locks();
1980 IStream_Release(pStream);
1981 IMarshal_Release(pFTMarshal);
1984 static void test_inproc_handler(void)
1986 HRESULT hr;
1987 IUnknown *pObject;
1988 IUnknown *pObject2;
1989 char buffer[256];
1990 LPOLESTR pszClsid;
1991 HKEY hkey;
1992 DWORD dwDisposition;
1993 DWORD error;
1995 hr = StringFromCLSID(&CLSID_WineTest, &pszClsid);
1996 ok_ole_success(hr, "StringFromCLSID");
1997 strcpy(buffer, "CLSID\\");
1998 WideCharToMultiByte(CP_ACP, 0, pszClsid, -1, buffer + strlen(buffer), sizeof(buffer) - strlen(buffer), NULL, NULL);
1999 CoTaskMemFree(pszClsid);
2000 strcat(buffer, "\\InprocHandler32");
2001 error = RegCreateKeyEx(HKEY_CLASSES_ROOT, buffer, 0, NULL, 0, KEY_SET_VALUE, NULL, &hkey, &dwDisposition);
2002 ok(error == ERROR_SUCCESS, "RegCreateKeyEx failed with error %d\n", error);
2003 error = RegSetValueEx(hkey, NULL, 0, REG_SZ, (const unsigned char *)"ole32.dll", strlen("ole32.dll") + 1);
2004 ok(error == ERROR_SUCCESS, "RegSetValueEx failed with error %d\n", error);
2005 RegCloseKey(hkey);
2007 hr = CoCreateInstance(&CLSID_WineTest, NULL, CLSCTX_INPROC_HANDLER, &IID_IUnknown, (void **)&pObject);
2008 todo_wine
2009 ok_ole_success(hr, "CoCreateInstance");
2011 if (SUCCEEDED(hr))
2013 hr = IUnknown_QueryInterface(pObject, &IID_IWineTest, (void **)&pObject2);
2014 ok(hr == E_NOINTERFACE, "IUnknown_QueryInterface on handler for invalid interface returned 0x%08x instead of E_NOINTERFACE\n", hr);
2016 /* it's a handler as it supports IOleObject */
2017 hr = IUnknown_QueryInterface(pObject, &IID_IOleObject, (void **)&pObject2);
2018 ok_ole_success(hr, "IUnknown_QueryInterface(&IID_IOleObject)");
2019 IUnknown_Release(pObject2);
2021 IUnknown_Release(pObject);
2024 RegDeleteKey(HKEY_CLASSES_ROOT, buffer);
2025 *strrchr(buffer, '\\') = '\0';
2026 RegDeleteKey(HKEY_CLASSES_ROOT, buffer);
2029 static HRESULT WINAPI Test_SMI_QueryInterface(
2030 IStdMarshalInfo *iface,
2031 REFIID riid,
2032 LPVOID *ppvObj)
2034 if (ppvObj == NULL) return E_POINTER;
2036 if (IsEqualGUID(riid, &IID_IUnknown) ||
2037 IsEqualGUID(riid, &IID_IStdMarshalInfo))
2039 *ppvObj = (LPVOID)iface;
2040 IClassFactory_AddRef(iface);
2041 return S_OK;
2044 return E_NOINTERFACE;
2047 static ULONG WINAPI Test_SMI_AddRef(IStdMarshalInfo *iface)
2049 LockModule();
2050 return 2; /* non-heap-based object */
2053 static ULONG WINAPI Test_SMI_Release(IStdMarshalInfo *iface)
2055 UnlockModule();
2056 return 1; /* non-heap-based object */
2059 static HRESULT WINAPI Test_SMI_GetClassForHandler(
2060 IStdMarshalInfo *iface,
2061 DWORD dwDestContext,
2062 void *pvDestContext,
2063 CLSID *pClsid)
2065 *pClsid = CLSID_WineTest;
2066 return S_OK;
2069 static const IStdMarshalInfoVtbl Test_SMI_Vtbl =
2071 Test_SMI_QueryInterface,
2072 Test_SMI_AddRef,
2073 Test_SMI_Release,
2074 Test_SMI_GetClassForHandler
2077 static IStdMarshalInfo Test_SMI = {&Test_SMI_Vtbl};
2079 static void test_handler_marshaling(void)
2081 HRESULT hr;
2082 IStream *pStream = NULL;
2083 IUnknown *pProxy = NULL;
2084 IUnknown *pObject;
2085 DWORD tid;
2086 HANDLE thread;
2087 static const LARGE_INTEGER ullZero;
2089 cLocks = 0;
2091 hr = CreateStreamOnHGlobal(NULL, TRUE, &pStream);
2092 ok_ole_success(hr, "CreateStreamOnHGlobal");
2093 tid = start_host_object(pStream, &IID_IUnknown, (IUnknown*)&Test_SMI, MSHLFLAGS_NORMAL, &thread);
2095 ok_more_than_one_lock();
2097 IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
2098 hr = CoUnmarshalInterface(pStream, &IID_IUnknown, (void **)&pProxy);
2099 ok_ole_success(hr, "CoUnmarshalInterface");
2100 IStream_Release(pStream);
2102 ok_more_than_one_lock();
2104 hr = IUnknown_QueryInterface(pProxy, &IID_IWineTest, (void **)&pObject);
2105 ok(hr == E_NOINTERFACE, "IUnknown_QueryInterface with unknown IID should have returned E_NOINTERFACE instead of 0x%08x\n", hr);
2107 /* it's a handler as it supports IOleObject */
2108 hr = IUnknown_QueryInterface(pProxy, &IID_IOleObject, (void **)&pObject);
2109 todo_wine
2110 ok_ole_success(hr, "IUnknown_QueryInterface(&IID_IOleObject)");
2111 if (SUCCEEDED(hr)) IUnknown_Release(pObject);
2113 IUnknown_Release(pProxy);
2115 ok_no_locks();
2117 end_host_object(tid, thread);
2119 /* FIXME: test IPersist interface has the same effect as IStdMarshalInfo */
2123 static void test_client_security(void)
2125 HRESULT hr;
2126 IStream *pStream = NULL;
2127 IClassFactory *pProxy = NULL;
2128 IUnknown *pProxy2 = NULL;
2129 IUnknown *pUnknown1 = NULL;
2130 IUnknown *pUnknown2 = NULL;
2131 IClientSecurity *pCliSec = NULL;
2132 IMarshal *pMarshal;
2133 DWORD tid;
2134 HANDLE thread;
2135 static const LARGE_INTEGER ullZero;
2136 DWORD dwAuthnSvc;
2137 DWORD dwAuthzSvc;
2138 OLECHAR *pServerPrincName;
2139 DWORD dwAuthnLevel;
2140 DWORD dwImpLevel;
2141 void *pAuthInfo;
2142 DWORD dwCapabilities;
2143 void *pv;
2145 cLocks = 0;
2147 hr = CreateStreamOnHGlobal(NULL, TRUE, &pStream);
2148 ok_ole_success(hr, "CreateStreamOnHGlobal");
2149 tid = start_host_object(pStream, &IID_IClassFactory, (IUnknown*)&Test_ClassFactory, MSHLFLAGS_NORMAL, &thread);
2151 IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
2152 hr = CoUnmarshalInterface(pStream, &IID_IClassFactory, (void **)&pProxy);
2153 ok_ole_success(hr, "CoUnmarshalInterface");
2154 IStream_Release(pStream);
2156 hr = IUnknown_QueryInterface(pProxy, &IID_IUnknown, (LPVOID*)&pUnknown1);
2157 ok_ole_success(hr, "IUnknown_QueryInterface IID_IUnknown");
2159 hr = IUnknown_QueryInterface(pProxy, &IID_IRemUnknown, (LPVOID*)&pProxy2);
2160 ok_ole_success(hr, "IUnknown_QueryInterface IID_IStream");
2162 hr = IUnknown_QueryInterface(pProxy2, &IID_IUnknown, (LPVOID*)&pUnknown2);
2163 ok_ole_success(hr, "IUnknown_QueryInterface IID_IUnknown");
2165 ok(pUnknown1 == pUnknown2, "both proxy's IUnknowns should be the same - %p, %p\n", pUnknown1, pUnknown2);
2167 hr = IUnknown_QueryInterface(pProxy, &IID_IMarshal, (LPVOID*)&pMarshal);
2168 ok_ole_success(hr, "IUnknown_QueryInterface IID_IMarshal");
2170 hr = IUnknown_QueryInterface(pProxy, &IID_IClientSecurity, (LPVOID*)&pCliSec);
2171 ok_ole_success(hr, "IUnknown_QueryInterface IID_IClientSecurity");
2173 hr = IClientSecurity_QueryBlanket(pCliSec, (IUnknown *)pProxy, NULL, NULL, NULL, NULL, NULL, NULL, NULL);
2174 todo_wine ok_ole_success(hr, "IClientSecurity_QueryBlanket (all NULLs)");
2176 hr = IClientSecurity_QueryBlanket(pCliSec, (IUnknown *)pMarshal, NULL, NULL, NULL, NULL, NULL, NULL, NULL);
2177 todo_wine ok(hr == E_NOINTERFACE, "IClientSecurity_QueryBlanket with local interface should have returned E_NOINTERFACE instead of 0x%08x\n", hr);
2179 hr = IClientSecurity_QueryBlanket(pCliSec, (IUnknown *)pProxy, &dwAuthnSvc, &dwAuthzSvc, &pServerPrincName, &dwAuthnLevel, &dwImpLevel, &pAuthInfo, &dwCapabilities);
2180 todo_wine ok_ole_success(hr, "IClientSecurity_QueryBlanket");
2182 hr = IClientSecurity_SetBlanket(pCliSec, (IUnknown *)pProxy, dwAuthnSvc, dwAuthzSvc, pServerPrincName, dwAuthnLevel, RPC_C_IMP_LEVEL_IMPERSONATE, pAuthInfo, dwCapabilities);
2183 todo_wine ok_ole_success(hr, "IClientSecurity_SetBlanket");
2185 hr = IClassFactory_CreateInstance(pProxy, NULL, &IID_IWineTest, &pv);
2186 ok(hr == E_NOINTERFACE, "COM call should have succeeded instead of returning 0x%08x\n", hr);
2188 hr = IClientSecurity_SetBlanket(pCliSec, (IUnknown *)pMarshal, dwAuthnSvc, dwAuthzSvc, pServerPrincName, dwAuthnLevel, dwImpLevel, pAuthInfo, dwCapabilities);
2189 todo_wine ok(hr == E_NOINTERFACE, "IClientSecurity_SetBlanket with local interface should have returned E_NOINTERFACE instead of 0x%08x\n", hr);
2191 hr = IClientSecurity_SetBlanket(pCliSec, (IUnknown *)pProxy, 0xdeadbeef, dwAuthzSvc, pServerPrincName, dwAuthnLevel, dwImpLevel, pAuthInfo, dwCapabilities);
2192 todo_wine ok(hr == E_INVALIDARG, "IClientSecurity_SetBlanke with invalid dwAuthnSvc should have returned E_INVALIDARG instead of 0x%08x\n", hr);
2194 CoTaskMemFree(pServerPrincName);
2196 hr = IClientSecurity_QueryBlanket(pCliSec, (IUnknown *)pUnknown1, &dwAuthnSvc, &dwAuthzSvc, &pServerPrincName, &dwAuthnLevel, &dwImpLevel, &pAuthInfo, &dwCapabilities);
2197 todo_wine ok_ole_success(hr, "IClientSecurity_QueryBlanket(IUnknown)");
2199 CoTaskMemFree(pServerPrincName);
2201 IClassFactory_Release(pProxy);
2202 IUnknown_Release(pProxy2);
2203 IUnknown_Release(pUnknown1);
2204 IUnknown_Release(pUnknown2);
2205 IMarshal_Release(pMarshal);
2206 IClientSecurity_Release(pCliSec);
2208 end_host_object(tid, thread);
2211 static HANDLE heventShutdown;
2213 static void LockModuleOOP(void)
2215 InterlockedIncrement(&cLocks); /* for test purposes only */
2216 CoAddRefServerProcess();
2219 static void UnlockModuleOOP(void)
2221 InterlockedDecrement(&cLocks); /* for test purposes only */
2222 if (!CoReleaseServerProcess())
2223 SetEvent(heventShutdown);
2226 static HWND hwnd_app;
2228 static HRESULT WINAPI TestOOP_IClassFactory_QueryInterface(
2229 LPCLASSFACTORY iface,
2230 REFIID riid,
2231 LPVOID *ppvObj)
2233 if (ppvObj == NULL) return E_POINTER;
2235 if (IsEqualGUID(riid, &IID_IUnknown) ||
2236 IsEqualGUID(riid, &IID_IClassFactory))
2238 *ppvObj = (LPVOID)iface;
2239 IClassFactory_AddRef(iface);
2240 return S_OK;
2243 return E_NOINTERFACE;
2246 static ULONG WINAPI TestOOP_IClassFactory_AddRef(LPCLASSFACTORY iface)
2248 return 2; /* non-heap-based object */
2251 static ULONG WINAPI TestOOP_IClassFactory_Release(LPCLASSFACTORY iface)
2253 return 1; /* non-heap-based object */
2256 static HRESULT WINAPI TestOOP_IClassFactory_CreateInstance(
2257 LPCLASSFACTORY iface,
2258 LPUNKNOWN pUnkOuter,
2259 REFIID riid,
2260 LPVOID *ppvObj)
2262 if (IsEqualIID(riid, &IID_IClassFactory) || IsEqualIID(riid, &IID_IUnknown))
2264 *ppvObj = iface;
2265 return S_OK;
2267 return CLASS_E_CLASSNOTAVAILABLE;
2270 static HRESULT WINAPI TestOOP_IClassFactory_LockServer(
2271 LPCLASSFACTORY iface,
2272 BOOL fLock)
2274 if (fLock)
2275 LockModuleOOP();
2276 else
2277 UnlockModuleOOP();
2278 return S_OK;
2281 static const IClassFactoryVtbl TestClassFactoryOOP_Vtbl =
2283 TestOOP_IClassFactory_QueryInterface,
2284 TestOOP_IClassFactory_AddRef,
2285 TestOOP_IClassFactory_Release,
2286 TestOOP_IClassFactory_CreateInstance,
2287 TestOOP_IClassFactory_LockServer
2290 static IClassFactory TestOOP_ClassFactory = { &TestClassFactoryOOP_Vtbl };
2292 static void test_register_local_server(void)
2294 DWORD cookie;
2295 HRESULT hr;
2296 HANDLE ready_event;
2297 HANDLE quit_event;
2298 DWORD wait;
2300 heventShutdown = CreateEvent(NULL, TRUE, FALSE, NULL);
2302 hr = CoRegisterClassObject(&CLSID_WineOOPTest, (IUnknown *)&TestOOP_ClassFactory,
2303 CLSCTX_LOCAL_SERVER, REGCLS_SINGLEUSE, &cookie);
2304 ok_ole_success(hr, CoRegisterClassObject);
2306 ready_event = CreateEvent(NULL, FALSE, FALSE, "Wine COM Test Ready Event");
2307 SetEvent(ready_event);
2309 quit_event = CreateEvent(NULL, FALSE, FALSE, "Wine COM Test Quit Event");
2313 wait = MsgWaitForMultipleObjects(1, &quit_event, FALSE, INFINITE, QS_ALLINPUT);
2314 if (wait == WAIT_OBJECT_0+1)
2316 MSG msg;
2317 BOOL ret = PeekMessage(&msg, NULL, 0, 0, PM_REMOVE);
2318 if (ret)
2320 trace("Message 0x%x\n", msg.message);
2321 TranslateMessage(&msg);
2322 DispatchMessage(&msg);
2326 while (wait == WAIT_OBJECT_0+1);
2328 hr = CoRevokeClassObject(cookie);
2329 ok_ole_success(hr, CoRevokeClassObject);
2332 static HANDLE create_target_process(const char *arg)
2334 char **argv;
2335 char cmdline[MAX_PATH];
2336 PROCESS_INFORMATION pi;
2337 STARTUPINFO si = { 0 };
2338 si.cb = sizeof(si);
2340 winetest_get_mainargs( &argv );
2341 sprintf(cmdline, "%s %s %s", argv[0], argv[1], arg);
2342 ok(CreateProcess(argv[0], cmdline, NULL, NULL, FALSE, 0, NULL, NULL,
2343 &si, &pi) != 0, "error: %u\n", GetLastError());
2344 ok(CloseHandle(pi.hThread) != 0, "error %u\n", GetLastError());
2345 return pi.hProcess;
2348 /* tests functions commonly used by out of process COM servers */
2349 static void test_local_server(void)
2351 DWORD cookie;
2352 HRESULT hr;
2353 IClassFactory * cf;
2354 DWORD ret;
2355 HANDLE process;
2356 HANDLE quit_event;
2357 HANDLE ready_event;
2359 heventShutdown = CreateEvent(NULL, TRUE, FALSE, NULL);
2361 cLocks = 0;
2363 /* Start the object suspended */
2364 hr = CoRegisterClassObject(&CLSID_WineOOPTest, (IUnknown *)&TestOOP_ClassFactory,
2365 CLSCTX_LOCAL_SERVER, REGCLS_MULTIPLEUSE | REGCLS_SUSPENDED, &cookie);
2366 ok_ole_success(hr, CoRegisterClassObject);
2368 /* ... and CoGetClassObject does not find it and fails when it looks for the
2369 * class in the registry */
2370 hr = CoGetClassObject(&CLSID_WineOOPTest, CLSCTX_INPROC_SERVER,
2371 NULL, &IID_IClassFactory, (LPVOID*)&cf);
2372 ok(hr == REGDB_E_CLASSNOTREG || /* NT */
2373 hr == S_OK /* Win9x */,
2374 "CoGetClassObject should have returned REGDB_E_CLASSNOTREG instead of 0x%08x\n", hr);
2376 /* Resume the object suspended above ... */
2377 hr = CoResumeClassObjects();
2378 ok_ole_success(hr, CoResumeClassObjects);
2380 /* ... and now it should succeed */
2381 hr = CoGetClassObject(&CLSID_WineOOPTest, CLSCTX_INPROC_SERVER,
2382 NULL, &IID_IClassFactory, (LPVOID*)&cf);
2383 ok_ole_success(hr, CoGetClassObject);
2385 /* Now check the locking is working */
2386 /* NOTE: we are accessing the class directly, not through a proxy */
2388 ok_no_locks();
2390 hr = IClassFactory_LockServer(cf, TRUE);
2391 ok_ole_success(hr, IClassFactory_LockServer);
2393 ok_more_than_one_lock();
2395 IClassFactory_LockServer(cf, FALSE);
2396 ok_ole_success(hr, IClassFactory_LockServer);
2398 ok_no_locks();
2400 IClassFactory_Release(cf);
2402 /* wait for shutdown signal */
2403 ret = WaitForSingleObject(heventShutdown, 0);
2404 ok(ret != WAIT_TIMEOUT, "Server didn't shut down\n");
2406 /* try to connect again after SCM has suspended registered class objects */
2407 hr = CoGetClassObject(&CLSID_WineOOPTest, CLSCTX_INPROC_SERVER | CLSCTX_LOCAL_SERVER, NULL,
2408 &IID_IClassFactory, (LPVOID*)&cf);
2409 ok(hr == CO_E_SERVER_STOPPING || /* NT */
2410 hr == S_OK /* Win9x */,
2411 "CoGetClassObject should have returned CO_E_SERVER_STOPPING instead of 0x%08x\n", hr);
2413 hr = CoRevokeClassObject(cookie);
2414 ok_ole_success(hr, CoRevokeClassObject);
2416 CloseHandle(heventShutdown);
2418 process = create_target_process("-Embedding");
2419 ok(process != NULL, "couldn't start local server process, error was %d\n", GetLastError());
2421 ready_event = CreateEvent(NULL, FALSE, FALSE, "Wine COM Test Ready Event");
2422 WaitForSingleObject(ready_event, 1000);
2423 CloseHandle(ready_event);
2425 hr = CoCreateInstance(&CLSID_WineOOPTest, NULL, CLSCTX_LOCAL_SERVER, &IID_IClassFactory, (void **)&cf);
2426 ok_ole_success(hr, CoCreateInstance);
2428 IClassFactory_Release(cf);
2430 hr = CoCreateInstance(&CLSID_WineOOPTest, NULL, CLSCTX_LOCAL_SERVER, &IID_IClassFactory, (void **)&cf);
2431 ok(hr == REGDB_E_CLASSNOTREG, "Second CoCreateInstance on REGCLS_SINGLEUSE object should have failed\n");
2433 quit_event = CreateEvent(NULL, FALSE, FALSE, "Wine COM Test Quit Event");
2434 SetEvent(quit_event);
2436 WaitForSingleObject(process, INFINITE);
2437 CloseHandle(quit_event);
2438 CloseHandle(process);
2441 struct git_params
2443 DWORD cookie;
2444 IGlobalInterfaceTable *git;
2447 static DWORD CALLBACK get_global_interface_proc(LPVOID pv)
2449 HRESULT hr;
2450 struct git_params *params = (struct git_params *)pv;
2451 IClassFactory *cf;
2453 hr = IGlobalInterfaceTable_GetInterfaceFromGlobal(params->git, params->cookie, &IID_IClassFactory, (void **)&cf);
2454 ok(hr == CO_E_NOTINITIALIZED,
2455 "IGlobalInterfaceTable_GetInterfaceFromGlobal should have failed with error CO_E_NOTINITIALIZED instead of 0x%08x\n",
2456 hr);
2458 CoInitialize(NULL);
2459 hr = IGlobalInterfaceTable_GetInterfaceFromGlobal(params->git, params->cookie, &IID_IClassFactory, (void **)&cf);
2460 ok_ole_success(hr, IGlobalInterfaceTable_GetInterfaceFromGlobal);
2462 IGlobalInterfaceTable_Release(params->git);
2464 CoUninitialize();
2466 return hr;
2469 static void test_globalinterfacetable(void)
2471 HRESULT hr;
2472 IGlobalInterfaceTable *git;
2473 DWORD cookie;
2474 HANDLE thread;
2475 DWORD tid;
2476 struct git_params params;
2477 DWORD ret;
2479 hr = CoCreateInstance(&CLSID_StdGlobalInterfaceTable, NULL, CLSCTX_INPROC_SERVER, &IID_IGlobalInterfaceTable, (void **)&git);
2480 ok_ole_success(hr, CoCreateInstance);
2482 hr = IGlobalInterfaceTable_RegisterInterfaceInGlobal(git, (IUnknown *)&Test_ClassFactory, &IID_IClassFactory, &cookie);
2483 ok_ole_success(hr, IGlobalInterfaceTable_RegisterInterfaceInGlobal);
2485 params.cookie = cookie;
2486 params.git = git;
2487 /* note: params is on stack so we MUST wait for get_global_interface_proc
2488 * to exit before we can return */
2489 thread = CreateThread(NULL, 0, get_global_interface_proc, &params, 0, &tid);
2491 ret = MsgWaitForMultipleObjects(1, &thread, FALSE, INFINITE, QS_ALLINPUT);
2492 while (ret == WAIT_OBJECT_0 + 1)
2494 MSG msg;
2495 while (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
2496 DispatchMessage(&msg);
2497 ret = MsgWaitForMultipleObjects(1, &thread, FALSE, INFINITE, QS_ALLINPUT);
2500 CloseHandle(thread);
2503 static const char *debugstr_iid(REFIID riid)
2505 static char name[256];
2506 HKEY hkeyInterface;
2507 WCHAR bufferW[39];
2508 char buffer[39];
2509 LONG name_size = sizeof(name);
2510 StringFromGUID2(riid, bufferW, sizeof(bufferW)/sizeof(bufferW[0]));
2511 WideCharToMultiByte(CP_ACP, 0, bufferW, sizeof(bufferW)/sizeof(bufferW[0]), buffer, sizeof(buffer), NULL, NULL);
2512 if (RegOpenKeyEx(HKEY_CLASSES_ROOT, "Interface", 0, KEY_QUERY_VALUE, &hkeyInterface) != ERROR_SUCCESS)
2514 memcpy(name, buffer, sizeof(buffer));
2515 goto done;
2517 if (RegQueryValue(hkeyInterface, buffer, name, &name_size) != ERROR_SUCCESS)
2519 memcpy(name, buffer, sizeof(buffer));
2520 goto done;
2522 RegCloseKey(hkeyInterface);
2523 done:
2524 return name;
2527 static HRESULT WINAPI TestChannelHook_QueryInterface(IChannelHook *iface, REFIID riid, void **ppv)
2529 if (IsEqualIID(riid, &IID_IUnknown) || IsEqualIID(riid, &IID_IChannelHook))
2531 *ppv = iface;
2532 IUnknown_AddRef(iface);
2533 return S_OK;
2536 *ppv = NULL;
2537 return E_NOINTERFACE;
2540 static ULONG WINAPI TestChannelHook_AddRef(IChannelHook *iface)
2542 return 2;
2545 static ULONG WINAPI TestChannelHook_Release(IChannelHook *iface)
2547 return 1;
2550 static void WINAPI TestChannelHook_ClientGetSize(
2551 IChannelHook *iface,
2552 REFGUID uExtent,
2553 REFIID riid,
2554 ULONG *pDataSize )
2556 SChannelHookCallInfo *info = (SChannelHookCallInfo *)riid;
2557 trace("TestChannelHook_ClientGetBuffer\n");
2558 trace("\t%s method %d\n", debugstr_iid(riid), info->iMethod);
2559 trace("\tcid: %s\n", debugstr_iid(&info->uCausality));
2560 ok(info->cbSize == sizeof(*info), "info->cbSize was %d instead of %d\n", info->cbSize, (int)sizeof(*info));
2561 ok(info->dwServerPid == GetCurrentProcessId(), "info->dwServerPid was 0x%x instead of 0x%x\n", info->dwServerPid, GetCurrentProcessId());
2562 ok(!info->pObject, "info->pObject should be NULL\n");
2563 ok(IsEqualGUID(uExtent, &EXTENTID_WineTest), "uExtent wasn't correct\n");
2565 *pDataSize = 1;
2568 static void WINAPI TestChannelHook_ClientFillBuffer(
2569 IChannelHook *iface,
2570 REFGUID uExtent,
2571 REFIID riid,
2572 ULONG *pDataSize,
2573 void *pDataBuffer )
2575 SChannelHookCallInfo *info = (SChannelHookCallInfo *)riid;
2576 trace("TestChannelHook_ClientFillBuffer\n");
2577 ok(info->cbSize == sizeof(*info), "info->cbSize was %d instead of %d\n", info->cbSize, (int)sizeof(*info));
2578 ok(info->dwServerPid == GetCurrentProcessId(), "info->dwServerPid was 0x%x instead of 0x%x\n", info->dwServerPid, GetCurrentProcessId());
2579 ok(!info->pObject, "info->pObject should be NULL\n");
2580 ok(IsEqualGUID(uExtent, &EXTENTID_WineTest), "uExtent wasn't correct\n");
2582 *(unsigned char *)pDataBuffer = 0xcc;
2583 *pDataSize = 1;
2586 static void WINAPI TestChannelHook_ClientNotify(
2587 IChannelHook *iface,
2588 REFGUID uExtent,
2589 REFIID riid,
2590 ULONG cbDataSize,
2591 void *pDataBuffer,
2592 DWORD lDataRep,
2593 HRESULT hrFault )
2595 SChannelHookCallInfo *info = (SChannelHookCallInfo *)riid;
2596 trace("TestChannelHook_ClientNotify hrFault = 0x%08x\n", hrFault);
2597 ok(info->cbSize == sizeof(*info), "info->cbSize was %d instead of %d\n", info->cbSize, (int)sizeof(*info));
2598 ok(info->dwServerPid == GetCurrentProcessId(), "info->dwServerPid was 0x%x instead of 0x%x\n", info->dwServerPid, GetCurrentProcessId());
2599 todo_wine {
2600 ok(info->pObject != NULL, "info->pObject shouldn't be NULL\n");
2602 ok(IsEqualGUID(uExtent, &EXTENTID_WineTest), "uExtent wasn't correct\n");
2605 static void WINAPI TestChannelHook_ServerNotify(
2606 IChannelHook *iface,
2607 REFGUID uExtent,
2608 REFIID riid,
2609 ULONG cbDataSize,
2610 void *pDataBuffer,
2611 DWORD lDataRep )
2613 SChannelHookCallInfo *info = (SChannelHookCallInfo *)riid;
2614 trace("TestChannelHook_ServerNotify\n");
2615 ok(info->cbSize == sizeof(*info), "info->cbSize was %d instead of %d\n", info->cbSize, (int)sizeof(*info));
2616 ok(info->dwServerPid == GetCurrentProcessId(), "info->dwServerPid was 0x%x instead of 0x%x\n", info->dwServerPid, GetCurrentProcessId());
2617 ok(info->pObject != NULL, "info->pObject shouldn't be NULL\n");
2618 ok(cbDataSize == 1, "cbDataSize should have been 1 instead of %d\n", cbDataSize);
2619 ok(*(unsigned char *)pDataBuffer == 0xcc, "pDataBuffer should have contained 0xcc instead of 0x%x\n", *(unsigned char *)pDataBuffer);
2620 ok(IsEqualGUID(uExtent, &EXTENTID_WineTest), "uExtent wasn't correct\n");
2623 static void WINAPI TestChannelHook_ServerGetSize(
2624 IChannelHook *iface,
2625 REFGUID uExtent,
2626 REFIID riid,
2627 HRESULT hrFault,
2628 ULONG *pDataSize )
2630 SChannelHookCallInfo *info = (SChannelHookCallInfo *)riid;
2631 trace("TestChannelHook_ServerGetSize\n");
2632 trace("\t%s method %d\n", debugstr_iid(riid), info->iMethod);
2633 ok(info->cbSize == sizeof(*info), "info->cbSize was %d instead of %d\n", info->cbSize, (int)sizeof(*info));
2634 ok(info->dwServerPid == GetCurrentProcessId(), "info->dwServerPid was 0x%x instead of 0x%x\n", info->dwServerPid, GetCurrentProcessId());
2635 ok(info->pObject != NULL, "info->pObject shouldn't be NULL\n");
2636 ok(IsEqualGUID(uExtent, &EXTENTID_WineTest), "uExtent wasn't correct\n");
2637 if (hrFault != S_OK)
2638 trace("\thrFault = 0x%08x\n", hrFault);
2640 *pDataSize = 0;
2643 static void WINAPI TestChannelHook_ServerFillBuffer(
2644 IChannelHook *iface,
2645 REFGUID uExtent,
2646 REFIID riid,
2647 ULONG *pDataSize,
2648 void *pDataBuffer,
2649 HRESULT hrFault )
2651 trace("TestChannelHook_ServerFillBuffer\n");
2652 ok(0, "TestChannelHook_ServerFillBuffer shouldn't be called\n");
2655 static const IChannelHookVtbl TestChannelHookVtbl =
2657 TestChannelHook_QueryInterface,
2658 TestChannelHook_AddRef,
2659 TestChannelHook_Release,
2660 TestChannelHook_ClientGetSize,
2661 TestChannelHook_ClientFillBuffer,
2662 TestChannelHook_ClientNotify,
2663 TestChannelHook_ServerNotify,
2664 TestChannelHook_ServerGetSize,
2665 TestChannelHook_ServerFillBuffer,
2668 static IChannelHook TestChannelHook = { &TestChannelHookVtbl };
2670 static void test_channel_hook(void)
2672 IStream *pStream = NULL;
2673 IClassFactory *cf = NULL;
2674 DWORD tid;
2675 IUnknown *proxy = NULL;
2676 HANDLE thread;
2677 HRESULT hr;
2679 hr = CoRegisterChannelHook(&EXTENTID_WineTest, &TestChannelHook);
2680 ok_ole_success(hr, CoRegisterChannelHook);
2682 hr = CoRegisterMessageFilter(&MessageFilter, NULL);
2683 ok_ole_success(hr, CoRegisterMessageFilter);
2685 cLocks = 0;
2687 hr = CreateStreamOnHGlobal(NULL, TRUE, &pStream);
2688 ok_ole_success(hr, CreateStreamOnHGlobal);
2689 tid = start_host_object2(pStream, &IID_IClassFactory, (IUnknown*)&Test_ClassFactory, MSHLFLAGS_NORMAL, &MessageFilter, &thread);
2691 ok_more_than_one_lock();
2693 IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
2694 hr = CoUnmarshalInterface(pStream, &IID_IClassFactory, (void **)&cf);
2695 ok_ole_success(hr, CoUnmarshalInterface);
2696 IStream_Release(pStream);
2698 ok_more_than_one_lock();
2700 hr = IClassFactory_CreateInstance(cf, NULL, &IID_IUnknown, (LPVOID*)&proxy);
2701 ok_ole_success(hr, IClassFactory_CreateInstance);
2702 IUnknown_Release(proxy);
2704 IClassFactory_Release(cf);
2706 ok_no_locks();
2708 end_host_object(tid, thread);
2710 hr = CoRegisterMessageFilter(NULL, NULL);
2711 ok_ole_success(hr, CoRegisterMessageFilter);
2714 START_TEST(marshal)
2716 WNDCLASS wndclass;
2717 HMODULE hOle32 = GetModuleHandle("ole32");
2718 int argc;
2719 char **argv;
2721 if (!(pCoInitializeEx = (void*)GetProcAddress(hOle32, "CoInitializeEx"))) goto no_test;
2723 argc = winetest_get_mainargs( &argv );
2724 if (argc > 2 && (!strcmp(argv[2], "-Embedding")))
2726 pCoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
2727 test_register_local_server();
2728 CoUninitialize();
2730 return;
2733 /* register a window class used in several tests */
2734 memset(&wndclass, 0, sizeof(wndclass));
2735 wndclass.lpfnWndProc = window_proc;
2736 wndclass.lpszClassName = "WineCOMTest";
2737 RegisterClass(&wndclass);
2739 test_cocreateinstance_proxy();
2741 pCoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
2743 /* FIXME: test CoCreateInstanceEx */
2745 /* lifecycle management and marshaling tests */
2746 test_no_marshaler();
2747 test_normal_marshal_and_release();
2748 test_normal_marshal_and_unmarshal();
2749 test_marshal_and_unmarshal_invalid();
2750 test_same_apartment_unmarshal_failure();
2751 test_interthread_marshal_and_unmarshal();
2752 test_proxy_marshal_and_unmarshal();
2753 test_proxy_marshal_and_unmarshal2();
2754 test_marshal_stub_apartment_shutdown();
2755 test_marshal_proxy_apartment_shutdown();
2756 test_marshal_proxy_mta_apartment_shutdown();
2757 test_no_couninitialize_server();
2758 test_no_couninitialize_client();
2759 test_tableweak_marshal_and_unmarshal_twice();
2760 test_tableweak_marshal_releasedata1();
2761 test_tableweak_marshal_releasedata2();
2762 test_tablestrong_marshal_and_unmarshal_twice();
2763 test_lock_object_external();
2764 test_disconnect_stub();
2765 test_normal_marshal_and_unmarshal_twice();
2766 test_hresult_marshaling();
2767 test_proxy_used_in_wrong_thread();
2768 test_message_filter();
2769 test_bad_marshal_stream();
2770 test_proxy_interfaces();
2771 test_stubbuffer(&IID_IClassFactory);
2772 test_proxybuffer(&IID_IClassFactory);
2773 test_message_reentrancy();
2774 test_call_from_message();
2775 test_WM_QUIT_handling();
2776 test_freethreadedmarshaler();
2777 test_inproc_handler();
2778 test_handler_marshaling();
2779 test_client_security();
2781 test_local_server();
2783 test_globalinterfacetable();
2785 /* must be last test as channel hooks can't be unregistered */
2786 test_channel_hook();
2788 CoUninitialize();
2789 return;
2791 no_test:
2792 trace("You need DCOM95 installed to run this test\n");
2793 return;