vbscript: Moved Error object implementation to global.c.
[wine/multimedia.git] / dlls / ole32 / tests / marshal.c
blob5ff6ab2c4b76bc7065e33b3ea1031d70ef07cfec
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 "olectl.h"
32 #include "shlguid.h"
33 #include "shobjidl.h"
34 #include "initguid.h"
36 #include "wine/test.h"
38 DEFINE_GUID(CLSID_StdGlobalInterfaceTable,0x00000323,0x0000,0x0000,0xc0,0x00,0x00,0x00,0x00,0x00,0x00,0x46);
39 DEFINE_GUID(CLSID_ManualResetEvent, 0x0000032c,0x0000,0x0000,0xc0,0x00,0x00,0x00,0x00,0x00,0x00,0x46);
41 /* functions that are not present on all versions of Windows */
42 static HRESULT (WINAPI * pCoInitializeEx)(LPVOID lpReserved, DWORD dwCoInit);
43 static HRESULT (WINAPI *pDllGetClassObject)(REFCLSID,REFIID,LPVOID);
45 /* helper macros to make tests a bit leaner */
46 #define ok_more_than_one_lock() ok(cLocks > 0, "Number of locks should be > 0, but actually is %d\n", cLocks)
47 #define ok_no_locks() ok(cLocks == 0, "Number of locks should be 0, but actually is %d\n", cLocks)
48 #define ok_ole_success(hr, func) ok(hr == S_OK, #func " failed with error 0x%08x\n", hr)
49 #define ok_non_zero_external_conn() do {if (with_external_conn) ok(external_connections, "got no external connections\n");} while(0);
50 #define ok_zero_external_conn() do {if (with_external_conn) ok(!external_connections, "got %d external connections\n", external_connections);} while(0);
51 #define ok_last_release_closes(b) do {if (with_external_conn) ok(last_release_closes == b, "got %d expected %d\n", last_release_closes, b);} while(0);
53 static const IID IID_IWineTest =
55 0x5201163f,
56 0x8164,
57 0x4fd0,
58 {0xa1, 0xa2, 0x5d, 0x5a, 0x36, 0x54, 0xd3, 0xbd}
59 }; /* 5201163f-8164-4fd0-a1a2-5d5a3654d3bd */
61 static const IID IID_IRemUnknown =
63 0x00000131,
64 0x0000,
65 0x0000,
66 {0xc0,0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46}
69 #define EXTENTID_WineTest IID_IWineTest
70 #define CLSID_WineTest IID_IWineTest
72 static const CLSID CLSID_WineOOPTest =
74 0x5201163f,
75 0x8164,
76 0x4fd0,
77 {0xa1, 0xa2, 0x5d, 0x5a, 0x36, 0x54, 0xd3, 0xbd}
78 }; /* 5201163f-8164-4fd0-a1a2-5d5a3654d3bd */
80 static void test_cocreateinstance_proxy(void)
82 IUnknown *pProxy;
83 IMultiQI *pMQI;
84 HRESULT hr;
86 pCoInitializeEx(NULL, COINIT_MULTITHREADED);
88 hr = CoCreateInstance(&CLSID_ShellDesktop, NULL, CLSCTX_INPROC, &IID_IUnknown, (void **)&pProxy);
89 ok_ole_success(hr, CoCreateInstance);
90 hr = IUnknown_QueryInterface(pProxy, &IID_IMultiQI, (void **)&pMQI);
91 ok(hr == S_OK, "created object is not a proxy, so was created in the wrong apartment\n");
92 if (hr == S_OK)
93 IMultiQI_Release(pMQI);
94 IUnknown_Release(pProxy);
96 CoUninitialize();
99 static const LARGE_INTEGER ullZero;
100 static LONG cLocks;
102 static void LockModule(void)
104 InterlockedIncrement(&cLocks);
107 static void UnlockModule(void)
109 InterlockedDecrement(&cLocks);
112 static BOOL with_external_conn;
113 static DWORD external_connections;
114 static BOOL last_release_closes;
116 static HRESULT WINAPI ExternalConnection_QueryInterface(IExternalConnection *iface, REFIID riid, void **ppv)
118 ok(0, "unxpected call\n");
119 *ppv = NULL;
120 return E_NOINTERFACE;
123 static ULONG WINAPI ExternalConnection_AddRef(IExternalConnection *iface)
125 return 2;
128 static ULONG WINAPI ExternalConnection_Release(IExternalConnection *iface)
130 return 1;
133 static DWORD WINAPI ExternalConnection_AddConnection(IExternalConnection *iface, DWORD extconn, DWORD reserved)
135 trace("add connection\n");
136 return ++external_connections;
140 static DWORD WINAPI ExternalConnection_ReleaseConnection(IExternalConnection *iface, DWORD extconn,
141 DWORD reserved, BOOL fLastReleaseCloses)
143 trace("release connection %d\n", fLastReleaseCloses);
144 last_release_closes = fLastReleaseCloses;
145 return --external_connections;
148 static const IExternalConnectionVtbl ExternalConnectionVtbl = {
149 ExternalConnection_QueryInterface,
150 ExternalConnection_AddRef,
151 ExternalConnection_Release,
152 ExternalConnection_AddConnection,
153 ExternalConnection_ReleaseConnection
156 static IExternalConnection ExternalConnection = { &ExternalConnectionVtbl };
159 static HRESULT WINAPI Test_IUnknown_QueryInterface(
160 LPUNKNOWN iface,
161 REFIID riid,
162 LPVOID *ppvObj)
164 if (ppvObj == NULL) return E_POINTER;
166 if (IsEqualGUID(riid, &IID_IUnknown))
168 *ppvObj = iface;
169 IUnknown_AddRef(iface);
170 return S_OK;
173 *ppvObj = NULL;
174 return E_NOINTERFACE;
177 static ULONG WINAPI Test_IUnknown_AddRef(LPUNKNOWN iface)
179 LockModule();
180 return 2; /* non-heap-based object */
183 static ULONG WINAPI Test_IUnknown_Release(LPUNKNOWN iface)
185 UnlockModule();
186 return 1; /* non-heap-based object */
189 static const IUnknownVtbl TestUnknown_Vtbl =
191 Test_IUnknown_QueryInterface,
192 Test_IUnknown_AddRef,
193 Test_IUnknown_Release,
196 static IUnknown Test_Unknown = { &TestUnknown_Vtbl };
199 static HRESULT WINAPI Test_IClassFactory_QueryInterface(
200 LPCLASSFACTORY iface,
201 REFIID riid,
202 LPVOID *ppvObj)
204 if (ppvObj == NULL) return E_POINTER;
206 if (IsEqualGUID(riid, &IID_IUnknown) ||
207 IsEqualGUID(riid, &IID_IClassFactory) ||
208 /* the only other interface Wine is currently able to marshal (for testing two proxies) */
209 IsEqualGUID(riid, &IID_IRemUnknown))
211 *ppvObj = iface;
212 IClassFactory_AddRef(iface);
213 return S_OK;
216 if (with_external_conn && IsEqualGUID(riid, &IID_IExternalConnection))
218 *ppvObj = &ExternalConnection;
219 return S_OK;
222 *ppvObj = NULL;
223 return E_NOINTERFACE;
226 static ULONG WINAPI Test_IClassFactory_AddRef(LPCLASSFACTORY iface)
228 LockModule();
229 return 2; /* non-heap-based object */
232 static ULONG WINAPI Test_IClassFactory_Release(LPCLASSFACTORY iface)
234 UnlockModule();
235 return 1; /* non-heap-based object */
238 static HRESULT WINAPI Test_IClassFactory_CreateInstance(
239 LPCLASSFACTORY iface,
240 LPUNKNOWN pUnkOuter,
241 REFIID riid,
242 LPVOID *ppvObj)
244 if (pUnkOuter) return CLASS_E_NOAGGREGATION;
245 return IUnknown_QueryInterface((IUnknown*)&Test_Unknown, riid, ppvObj);
248 static HRESULT WINAPI Test_IClassFactory_LockServer(
249 LPCLASSFACTORY iface,
250 BOOL fLock)
252 return S_OK;
255 static const IClassFactoryVtbl TestClassFactory_Vtbl =
257 Test_IClassFactory_QueryInterface,
258 Test_IClassFactory_AddRef,
259 Test_IClassFactory_Release,
260 Test_IClassFactory_CreateInstance,
261 Test_IClassFactory_LockServer
264 static IClassFactory Test_ClassFactory = { &TestClassFactory_Vtbl };
266 #define RELEASEMARSHALDATA WM_USER
268 struct host_object_data
270 IStream *stream;
271 IID iid;
272 IUnknown *object;
273 MSHLFLAGS marshal_flags;
274 HANDLE marshal_event;
275 IMessageFilter *filter;
278 static DWORD CALLBACK host_object_proc(LPVOID p)
280 struct host_object_data *data = p;
281 HRESULT hr;
282 MSG msg;
284 pCoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
286 if (data->filter)
288 IMessageFilter * prev_filter = NULL;
289 hr = CoRegisterMessageFilter(data->filter, &prev_filter);
290 if (prev_filter) IMessageFilter_Release(prev_filter);
291 ok_ole_success(hr, CoRegisterMessageFilter);
294 hr = CoMarshalInterface(data->stream, &data->iid, data->object, MSHCTX_INPROC, NULL, data->marshal_flags);
295 ok_ole_success(hr, CoMarshalInterface);
297 /* force the message queue to be created before signaling parent thread */
298 PeekMessageA(&msg, NULL, WM_USER, WM_USER, PM_NOREMOVE);
300 SetEvent(data->marshal_event);
302 while (GetMessageA(&msg, NULL, 0, 0))
304 if (msg.hwnd == NULL && msg.message == RELEASEMARSHALDATA)
306 CoReleaseMarshalData(data->stream);
307 SetEvent((HANDLE)msg.lParam);
309 else
310 DispatchMessageA(&msg);
313 HeapFree(GetProcessHeap(), 0, data);
315 CoUninitialize();
317 return hr;
320 static DWORD start_host_object2(IStream *stream, REFIID riid, IUnknown *object, MSHLFLAGS marshal_flags, IMessageFilter *filter, HANDLE *thread)
322 DWORD tid = 0;
323 HANDLE marshal_event = CreateEventA(NULL, FALSE, FALSE, NULL);
324 struct host_object_data *data = HeapAlloc(GetProcessHeap(), 0, sizeof(*data));
326 data->stream = stream;
327 data->iid = *riid;
328 data->object = object;
329 data->marshal_flags = marshal_flags;
330 data->marshal_event = marshal_event;
331 data->filter = filter;
333 *thread = CreateThread(NULL, 0, host_object_proc, data, 0, &tid);
335 /* wait for marshaling to complete before returning */
336 ok( !WaitForSingleObject(marshal_event, 10000), "wait timed out\n" );
337 CloseHandle(marshal_event);
339 return tid;
342 static DWORD start_host_object(IStream *stream, REFIID riid, IUnknown *object, MSHLFLAGS marshal_flags, HANDLE *thread)
344 return start_host_object2(stream, riid, object, marshal_flags, NULL, thread);
347 /* asks thread to release the marshal data because it has to be done by the
348 * same thread that marshaled the interface in the first place. */
349 static void release_host_object(DWORD tid, WPARAM wp)
351 HANDLE event = CreateEventA(NULL, FALSE, FALSE, NULL);
352 PostThreadMessageA(tid, RELEASEMARSHALDATA, wp, (LPARAM)event);
353 ok( !WaitForSingleObject(event, 10000), "wait timed out\n" );
354 CloseHandle(event);
357 static void end_host_object(DWORD tid, HANDLE thread)
359 BOOL ret = PostThreadMessageA(tid, WM_QUIT, 0, 0);
360 ok(ret, "PostThreadMessage failed with error %d\n", GetLastError());
361 /* be careful of races - don't return until hosting thread has terminated */
362 ok( !WaitForSingleObject(thread, 10000), "wait timed out\n" );
363 CloseHandle(thread);
366 /* tests failure case of interface not having a marshaler specified in the
367 * registry */
368 static void test_no_marshaler(void)
370 IStream *pStream;
371 HRESULT hr;
373 hr = CreateStreamOnHGlobal(NULL, TRUE, &pStream);
374 ok_ole_success(hr, CreateStreamOnHGlobal);
375 hr = CoMarshalInterface(pStream, &IID_IWineTest, (IUnknown*)&Test_ClassFactory, MSHCTX_INPROC, NULL, MSHLFLAGS_NORMAL);
376 ok(hr == E_NOINTERFACE, "CoMarshalInterface should have returned E_NOINTERFACE instead of 0x%08x\n", hr);
378 IStream_Release(pStream);
381 /* tests normal marshal and then release without unmarshaling */
382 static void test_normal_marshal_and_release(void)
384 HRESULT hr;
385 IStream *pStream = NULL;
387 cLocks = 0;
388 external_connections = 0;
390 hr = CreateStreamOnHGlobal(NULL, TRUE, &pStream);
391 ok_ole_success(hr, CreateStreamOnHGlobal);
392 hr = CoMarshalInterface(pStream, &IID_IClassFactory, (IUnknown*)&Test_ClassFactory, MSHCTX_INPROC, NULL, MSHLFLAGS_NORMAL);
393 ok_ole_success(hr, CoMarshalInterface);
395 ok_more_than_one_lock();
396 ok_non_zero_external_conn();
398 IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
399 hr = CoReleaseMarshalData(pStream);
400 ok_ole_success(hr, CoReleaseMarshalData);
401 IStream_Release(pStream);
403 ok_no_locks();
404 ok_zero_external_conn();
405 ok_last_release_closes(TRUE);
408 /* tests success case of a same-thread marshal and unmarshal */
409 static void test_normal_marshal_and_unmarshal(void)
411 HRESULT hr;
412 IStream *pStream = NULL;
413 IUnknown *pProxy = NULL;
415 cLocks = 0;
416 external_connections = 0;
418 hr = CreateStreamOnHGlobal(NULL, TRUE, &pStream);
419 ok_ole_success(hr, CreateStreamOnHGlobal);
420 hr = CoMarshalInterface(pStream, &IID_IClassFactory, (IUnknown*)&Test_ClassFactory, MSHCTX_INPROC, NULL, MSHLFLAGS_NORMAL);
421 ok_ole_success(hr, CoMarshalInterface);
423 ok_more_than_one_lock();
424 ok_non_zero_external_conn();
426 IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
427 hr = CoUnmarshalInterface(pStream, &IID_IClassFactory, (void **)&pProxy);
428 ok_ole_success(hr, CoUnmarshalInterface);
429 IStream_Release(pStream);
431 ok_more_than_one_lock();
432 ok_zero_external_conn();
433 ok_last_release_closes(FALSE);
435 IUnknown_Release(pProxy);
437 ok_no_locks();
440 /* tests failure case of unmarshaling a freed object */
441 static void test_marshal_and_unmarshal_invalid(void)
443 HRESULT hr;
444 IStream *pStream = NULL;
445 IClassFactory *pProxy = NULL;
446 DWORD tid;
447 void * dummy;
448 HANDLE thread;
450 cLocks = 0;
451 external_connections = 0;
453 hr = CreateStreamOnHGlobal(NULL, TRUE, &pStream);
454 ok_ole_success(hr, CreateStreamOnHGlobal);
455 tid = start_host_object(pStream, &IID_IClassFactory, (IUnknown*)&Test_ClassFactory, MSHLFLAGS_NORMAL, &thread);
457 ok_more_than_one_lock();
458 ok_non_zero_external_conn();
460 IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
461 hr = CoReleaseMarshalData(pStream);
462 ok_ole_success(hr, CoReleaseMarshalData);
464 ok_no_locks();
465 ok_zero_external_conn();
466 ok_last_release_closes(TRUE);
468 IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
469 hr = CoUnmarshalInterface(pStream, &IID_IClassFactory, (void **)&pProxy);
470 todo_wine { ok_ole_success(hr, CoUnmarshalInterface); }
472 ok_no_locks();
474 if (pProxy)
476 hr = IClassFactory_CreateInstance(pProxy, NULL, &IID_IUnknown, &dummy);
477 ok(hr == RPC_E_DISCONNECTED, "Remote call should have returned RPC_E_DISCONNECTED, instead of 0x%08x\n", hr);
479 IClassFactory_Release(pProxy);
482 IStream_Release(pStream);
484 end_host_object(tid, thread);
487 static void test_same_apartment_unmarshal_failure(void)
489 HRESULT hr;
490 IStream *pStream;
491 IUnknown *pProxy;
492 static const LARGE_INTEGER llZero;
494 cLocks = 0;
495 external_connections = 0;
497 hr = CreateStreamOnHGlobal(NULL, TRUE, &pStream);
498 ok_ole_success(hr, CreateStreamOnHGlobal);
500 hr = CoMarshalInterface(pStream, &IID_IUnknown, (IUnknown *)&Test_ClassFactory, MSHCTX_INPROC, NULL, MSHLFLAGS_NORMAL);
501 ok_ole_success(hr, CoMarshalInterface);
503 ok_more_than_one_lock();
504 ok_non_zero_external_conn();
506 hr = IStream_Seek(pStream, llZero, STREAM_SEEK_SET, NULL);
507 ok_ole_success(hr, IStream_Seek);
509 hr = CoUnmarshalInterface(pStream, &IID_IParseDisplayName, (void **)&pProxy);
510 ok(hr == E_NOINTERFACE, "CoUnmarshalInterface should have returned E_NOINTERFACE instead of 0x%08x\n", hr);
512 ok_no_locks();
513 ok_zero_external_conn();
514 ok_last_release_closes(FALSE);
516 IStream_Release(pStream);
519 /* tests success case of an interthread marshal */
520 static void test_interthread_marshal_and_unmarshal(void)
522 HRESULT hr;
523 IStream *pStream = NULL;
524 IUnknown *pProxy = NULL;
525 DWORD tid;
526 HANDLE thread;
528 cLocks = 0;
529 external_connections = 0;
531 hr = CreateStreamOnHGlobal(NULL, TRUE, &pStream);
532 ok_ole_success(hr, CreateStreamOnHGlobal);
533 tid = start_host_object(pStream, &IID_IClassFactory, (IUnknown*)&Test_ClassFactory, MSHLFLAGS_NORMAL, &thread);
535 ok_more_than_one_lock();
536 ok_non_zero_external_conn();
538 IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
539 hr = CoUnmarshalInterface(pStream, &IID_IClassFactory, (void **)&pProxy);
540 ok_ole_success(hr, CoUnmarshalInterface);
541 IStream_Release(pStream);
543 ok_more_than_one_lock();
544 ok_non_zero_external_conn();
546 IUnknown_Release(pProxy);
548 ok_no_locks();
549 ok_zero_external_conn();
550 ok_last_release_closes(TRUE);
552 end_host_object(tid, thread);
555 /* the number of external references that Wine's proxy manager normally gives
556 * out, so we can test the border case of running out of references */
557 #define NORMALEXTREFS 5
559 /* tests success case of an interthread marshal and then marshaling the proxy */
560 static void test_proxy_marshal_and_unmarshal(void)
562 HRESULT hr;
563 IStream *pStream = NULL;
564 IUnknown *pProxy = NULL;
565 IUnknown *pProxy2 = NULL;
566 DWORD tid;
567 HANDLE thread;
568 int i;
570 cLocks = 0;
571 external_connections = 0;
573 hr = CreateStreamOnHGlobal(NULL, TRUE, &pStream);
574 ok_ole_success(hr, CreateStreamOnHGlobal);
575 tid = start_host_object(pStream, &IID_IClassFactory, (IUnknown*)&Test_ClassFactory, MSHLFLAGS_NORMAL, &thread);
577 ok_more_than_one_lock();
578 ok_non_zero_external_conn();
580 IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
581 hr = CoUnmarshalInterface(pStream, &IID_IClassFactory, (void **)&pProxy);
582 ok_ole_success(hr, CoUnmarshalInterface);
584 ok_more_than_one_lock();
586 IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
587 /* marshal the proxy */
588 hr = CoMarshalInterface(pStream, &IID_IClassFactory, pProxy, MSHCTX_INPROC, NULL, MSHLFLAGS_NORMAL);
589 ok_ole_success(hr, CoMarshalInterface);
591 ok_more_than_one_lock();
593 /* marshal 5 more times to exhaust the normal external references of 5 */
594 for (i = 0; i < NORMALEXTREFS; i++)
596 hr = CoMarshalInterface(pStream, &IID_IClassFactory, pProxy, MSHCTX_INPROC, NULL, MSHLFLAGS_NORMAL);
597 ok_ole_success(hr, CoMarshalInterface);
600 ok_more_than_one_lock();
602 /* release the original proxy to test that we successfully keep the
603 * original object alive */
604 IUnknown_Release(pProxy);
606 IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
607 hr = CoUnmarshalInterface(pStream, &IID_IClassFactory, (void **)&pProxy2);
608 ok_ole_success(hr, CoUnmarshalInterface);
610 ok_more_than_one_lock();
611 ok_non_zero_external_conn();
613 IUnknown_Release(pProxy2);
615 /* unmarshal all of the proxies to check that the object stub still exists */
616 for (i = 0; i < NORMALEXTREFS; i++)
618 hr = CoUnmarshalInterface(pStream, &IID_IClassFactory, (void **)&pProxy2);
619 ok_ole_success(hr, CoUnmarshalInterface);
621 IUnknown_Release(pProxy2);
624 ok_no_locks();
625 ok_zero_external_conn();
626 ok_last_release_closes(TRUE);
628 IStream_Release(pStream);
630 end_host_object(tid, thread);
633 /* tests success case of an interthread marshal and then marshaling the proxy
634 * using an iid that hasn't previously been unmarshaled */
635 static void test_proxy_marshal_and_unmarshal2(void)
637 HRESULT hr;
638 IStream *pStream = NULL;
639 IUnknown *pProxy = NULL;
640 IUnknown *pProxy2 = NULL;
641 DWORD tid;
642 HANDLE thread;
644 cLocks = 0;
645 external_connections = 0;
647 hr = CreateStreamOnHGlobal(NULL, TRUE, &pStream);
648 ok_ole_success(hr, CreateStreamOnHGlobal);
649 tid = start_host_object(pStream, &IID_IUnknown, (IUnknown*)&Test_ClassFactory, MSHLFLAGS_NORMAL, &thread);
651 ok_more_than_one_lock();
652 ok_non_zero_external_conn();
654 IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
655 hr = CoUnmarshalInterface(pStream, &IID_IUnknown, (void **)&pProxy);
656 ok_ole_success(hr, CoUnmarshalInterface);
658 ok_more_than_one_lock();
660 IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
661 /* marshal the proxy */
662 hr = CoMarshalInterface(pStream, &IID_IClassFactory, pProxy, MSHCTX_INPROC, NULL, MSHLFLAGS_NORMAL);
663 ok_ole_success(hr, CoMarshalInterface);
665 ok_more_than_one_lock();
667 IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
668 /* unmarshal the second proxy to the object */
669 hr = CoUnmarshalInterface(pStream, &IID_IClassFactory, (void **)&pProxy2);
670 ok_ole_success(hr, CoUnmarshalInterface);
671 IStream_Release(pStream);
673 /* now the proxies should be as follows:
674 * pProxy -> &Test_ClassFactory
675 * pProxy2 -> &Test_ClassFactory
676 * they should NOT be as follows:
677 * pProxy -> &Test_ClassFactory
678 * pProxy2 -> pProxy
679 * the above can only really be tested by looking in +ole traces
682 ok_more_than_one_lock();
684 IUnknown_Release(pProxy);
686 ok_more_than_one_lock();
687 ok_non_zero_external_conn();
689 IUnknown_Release(pProxy2);
691 ok_no_locks();
692 ok_zero_external_conn();
693 ok_last_release_closes(TRUE);
695 end_host_object(tid, thread);
698 /* tests success case of an interthread marshal and then table-weak-marshaling the proxy */
699 static void test_proxy_marshal_and_unmarshal_weak(void)
701 HRESULT hr;
702 IStream *pStream = NULL;
703 IUnknown *pProxy = NULL;
704 IUnknown *pProxy2 = NULL;
705 DWORD tid;
706 HANDLE thread;
708 cLocks = 0;
709 external_connections = 0;
711 hr = CreateStreamOnHGlobal(NULL, TRUE, &pStream);
712 ok_ole_success(hr, CreateStreamOnHGlobal);
713 tid = start_host_object(pStream, &IID_IClassFactory, (IUnknown*)&Test_ClassFactory, MSHLFLAGS_NORMAL, &thread);
715 ok_more_than_one_lock();
716 ok_non_zero_external_conn();
718 IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
719 hr = CoUnmarshalInterface(pStream, &IID_IClassFactory, (void **)&pProxy);
720 ok_ole_success(hr, CoUnmarshalInterface);
722 ok_more_than_one_lock();
723 ok_non_zero_external_conn();
725 IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
726 /* marshal the proxy */
727 hr = CoMarshalInterface(pStream, &IID_IClassFactory, pProxy, MSHCTX_INPROC, NULL, MSHLFLAGS_TABLEWEAK);
728 ok_ole_success(hr, CoMarshalInterface);
730 ok_more_than_one_lock();
731 ok_non_zero_external_conn();
733 /* release the original proxy to test that we successfully keep the
734 * original object alive */
735 IUnknown_Release(pProxy);
737 IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
738 hr = CoUnmarshalInterface(pStream, &IID_IClassFactory, (void **)&pProxy2);
739 todo_wine
740 ok(hr == CO_E_OBJNOTREG, "CoUnmarshalInterface should return CO_E_OBJNOTREG instead of 0x%08x\n", hr);
742 ok_no_locks();
743 ok_zero_external_conn();
744 ok_last_release_closes(TRUE);
746 IStream_Release(pStream);
748 end_host_object(tid, thread);
751 /* tests success case of an interthread marshal and then table-strong-marshaling the proxy */
752 static void test_proxy_marshal_and_unmarshal_strong(void)
754 HRESULT hr;
755 IStream *pStream = NULL;
756 IUnknown *pProxy = NULL;
757 IUnknown *pProxy2 = NULL;
758 DWORD tid;
759 HANDLE thread;
761 cLocks = 0;
762 external_connections = 0;
764 hr = CreateStreamOnHGlobal(NULL, TRUE, &pStream);
765 ok_ole_success(hr, CreateStreamOnHGlobal);
766 tid = start_host_object(pStream, &IID_IClassFactory, (IUnknown*)&Test_ClassFactory, MSHLFLAGS_NORMAL, &thread);
768 ok_more_than_one_lock();
769 ok_non_zero_external_conn();
771 IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
772 hr = CoUnmarshalInterface(pStream, &IID_IClassFactory, (void **)&pProxy);
773 ok_ole_success(hr, CoUnmarshalInterface);
775 ok_more_than_one_lock();
776 ok_non_zero_external_conn();
778 IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
779 /* marshal the proxy */
780 hr = CoMarshalInterface(pStream, &IID_IClassFactory, pProxy, MSHCTX_INPROC, NULL, MSHLFLAGS_TABLESTRONG);
781 ok(hr == S_OK /* WinNT */ || hr == E_INVALIDARG /* Win9x */,
782 "CoMarshalInterface should have return S_OK or E_INVALIDARG instead of 0x%08x\n", hr);
783 if (FAILED(hr))
785 IUnknown_Release(pProxy);
786 goto end;
789 ok_more_than_one_lock();
790 ok_non_zero_external_conn();
792 /* release the original proxy to test that we successfully keep the
793 * original object alive */
794 IUnknown_Release(pProxy);
796 IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
797 hr = CoUnmarshalInterface(pStream, &IID_IClassFactory, (void **)&pProxy2);
798 ok_ole_success(hr, CoUnmarshalInterface);
800 ok_more_than_one_lock();
801 ok_non_zero_external_conn();
803 IUnknown_Release(pProxy2);
805 ok_more_than_one_lock();
806 ok_non_zero_external_conn();
808 end:
809 IStream_Release(pStream);
811 end_host_object(tid, thread);
813 ok_no_locks();
814 todo_wine {
815 ok_zero_external_conn();
816 ok_last_release_closes(FALSE);
820 /* tests that stubs are released when the containing apartment is destroyed */
821 static void test_marshal_stub_apartment_shutdown(void)
823 HRESULT hr;
824 IStream *pStream = NULL;
825 IUnknown *pProxy = NULL;
826 DWORD tid;
827 HANDLE thread;
829 cLocks = 0;
830 external_connections = 0;
832 hr = CreateStreamOnHGlobal(NULL, TRUE, &pStream);
833 ok_ole_success(hr, CreateStreamOnHGlobal);
834 tid = start_host_object(pStream, &IID_IClassFactory, (IUnknown*)&Test_ClassFactory, MSHLFLAGS_NORMAL, &thread);
836 ok_more_than_one_lock();
837 ok_non_zero_external_conn();
839 IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
840 hr = CoUnmarshalInterface(pStream, &IID_IClassFactory, (void **)&pProxy);
841 ok_ole_success(hr, CoUnmarshalInterface);
842 IStream_Release(pStream);
844 ok_more_than_one_lock();
845 ok_non_zero_external_conn();
847 end_host_object(tid, thread);
849 ok_no_locks();
850 todo_wine {
851 ok_zero_external_conn();
852 ok_last_release_closes(FALSE);
855 IUnknown_Release(pProxy);
857 ok_no_locks();
860 /* tests that proxies are released when the containing apartment is destroyed */
861 static void test_marshal_proxy_apartment_shutdown(void)
863 HRESULT hr;
864 IStream *pStream = NULL;
865 IUnknown *pProxy = NULL;
866 DWORD tid;
867 HANDLE thread;
869 cLocks = 0;
870 external_connections = 0;
872 hr = CreateStreamOnHGlobal(NULL, TRUE, &pStream);
873 ok_ole_success(hr, CreateStreamOnHGlobal);
874 tid = start_host_object(pStream, &IID_IClassFactory, (IUnknown*)&Test_ClassFactory, MSHLFLAGS_NORMAL, &thread);
876 ok_more_than_one_lock();
877 ok_non_zero_external_conn();
879 IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
880 hr = CoUnmarshalInterface(pStream, &IID_IClassFactory, (void **)&pProxy);
881 ok_ole_success(hr, CoUnmarshalInterface);
882 IStream_Release(pStream);
884 ok_more_than_one_lock();
885 ok_non_zero_external_conn();
887 CoUninitialize();
889 ok_no_locks();
890 ok_zero_external_conn();
891 ok_last_release_closes(TRUE);
893 IUnknown_Release(pProxy);
895 ok_no_locks();
897 end_host_object(tid, thread);
899 pCoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
902 /* tests that proxies are released when the containing mta apartment is destroyed */
903 static void test_marshal_proxy_mta_apartment_shutdown(void)
905 HRESULT hr;
906 IStream *pStream = NULL;
907 IUnknown *pProxy = NULL;
908 DWORD tid;
909 HANDLE thread;
911 CoUninitialize();
912 pCoInitializeEx(NULL, COINIT_MULTITHREADED);
914 cLocks = 0;
915 external_connections = 0;
917 hr = CreateStreamOnHGlobal(NULL, TRUE, &pStream);
918 ok_ole_success(hr, CreateStreamOnHGlobal);
919 tid = start_host_object(pStream, &IID_IClassFactory, (IUnknown*)&Test_ClassFactory, MSHLFLAGS_NORMAL, &thread);
921 ok_more_than_one_lock();
922 ok_non_zero_external_conn();
924 IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
925 hr = CoUnmarshalInterface(pStream, &IID_IClassFactory, (void **)&pProxy);
926 ok_ole_success(hr, CoUnmarshalInterface);
927 IStream_Release(pStream);
929 ok_more_than_one_lock();
930 ok_non_zero_external_conn();
932 CoUninitialize();
934 ok_no_locks();
935 ok_zero_external_conn();
936 ok_last_release_closes(TRUE);
938 IUnknown_Release(pProxy);
940 ok_no_locks();
942 end_host_object(tid, thread);
944 pCoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
947 struct ncu_params
949 LPSTREAM stream;
950 HANDLE marshal_event;
951 HANDLE unmarshal_event;
954 /* helper for test_no_couninitialize_server */
955 static DWORD CALLBACK no_couninitialize_server_proc(LPVOID p)
957 struct ncu_params *ncu_params = p;
958 HRESULT hr;
960 pCoInitializeEx(NULL, COINIT_MULTITHREADED);
962 hr = CoMarshalInterface(ncu_params->stream, &IID_IClassFactory, (IUnknown*)&Test_ClassFactory, MSHCTX_INPROC, NULL, MSHLFLAGS_NORMAL);
963 ok_ole_success(hr, CoMarshalInterface);
965 SetEvent(ncu_params->marshal_event);
967 ok( !WaitForSingleObject(ncu_params->unmarshal_event, 10000), "wait timed out\n" );
969 /* die without calling CoUninitialize */
971 return 0;
974 /* tests apartment that an apartment with a stub is released without deadlock
975 * if the owning thread exits */
976 static void test_no_couninitialize_server(void)
978 HRESULT hr;
979 IStream *pStream = NULL;
980 IUnknown *pProxy = NULL;
981 DWORD tid;
982 HANDLE thread;
983 struct ncu_params ncu_params;
985 cLocks = 0;
986 external_connections = 0;
988 ncu_params.marshal_event = CreateEventA(NULL, TRUE, FALSE, NULL);
989 ncu_params.unmarshal_event = CreateEventA(NULL, TRUE, FALSE, NULL);
991 hr = CreateStreamOnHGlobal(NULL, TRUE, &pStream);
992 ok_ole_success(hr, CreateStreamOnHGlobal);
993 ncu_params.stream = pStream;
995 thread = CreateThread(NULL, 0, no_couninitialize_server_proc, &ncu_params, 0, &tid);
997 ok( !WaitForSingleObject(ncu_params.marshal_event, 10000), "wait timed out\n" );
998 ok_more_than_one_lock();
999 ok_non_zero_external_conn();
1001 IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
1002 hr = CoUnmarshalInterface(pStream, &IID_IClassFactory, (void **)&pProxy);
1003 ok_ole_success(hr, CoUnmarshalInterface);
1004 IStream_Release(pStream);
1006 ok_more_than_one_lock();
1007 ok_non_zero_external_conn();
1009 SetEvent(ncu_params.unmarshal_event);
1010 ok( !WaitForSingleObject(thread, 10000), "wait timed out\n" );
1012 ok_no_locks();
1013 todo_wine {
1014 ok_zero_external_conn();
1015 ok_last_release_closes(FALSE);
1018 CloseHandle(thread);
1019 CloseHandle(ncu_params.marshal_event);
1020 CloseHandle(ncu_params.unmarshal_event);
1022 IUnknown_Release(pProxy);
1024 ok_no_locks();
1027 /* STA -> STA call during DLL_THREAD_DETACH */
1028 static DWORD CALLBACK no_couninitialize_client_proc(LPVOID p)
1030 struct ncu_params *ncu_params = p;
1031 HRESULT hr;
1032 IUnknown *pProxy = NULL;
1034 pCoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
1036 hr = CoUnmarshalInterface(ncu_params->stream, &IID_IClassFactory, (void **)&pProxy);
1037 ok_ole_success(hr, CoUnmarshalInterface);
1038 IStream_Release(ncu_params->stream);
1040 ok_more_than_one_lock();
1042 /* die without calling CoUninitialize */
1044 return 0;
1047 /* tests STA -> STA call during DLL_THREAD_DETACH doesn't deadlock */
1048 static void test_no_couninitialize_client(void)
1050 HRESULT hr;
1051 IStream *pStream = NULL;
1052 DWORD tid;
1053 DWORD host_tid;
1054 HANDLE thread;
1055 HANDLE host_thread;
1056 struct ncu_params ncu_params;
1058 cLocks = 0;
1059 external_connections = 0;
1061 hr = CreateStreamOnHGlobal(NULL, TRUE, &pStream);
1062 ok_ole_success(hr, CreateStreamOnHGlobal);
1063 ncu_params.stream = pStream;
1065 /* NOTE: assumes start_host_object uses an STA to host the object, as MTAs
1066 * always deadlock when called from within DllMain */
1067 host_tid = start_host_object(pStream, &IID_IClassFactory, (IUnknown *)&Test_ClassFactory, MSHLFLAGS_NORMAL, &host_thread);
1068 IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
1070 ok_more_than_one_lock();
1071 ok_non_zero_external_conn();
1073 thread = CreateThread(NULL, 0, no_couninitialize_client_proc, &ncu_params, 0, &tid);
1075 ok( !WaitForSingleObject(thread, 10000), "wait timed out\n" );
1076 CloseHandle(thread);
1078 ok_no_locks();
1079 ok_zero_external_conn();
1080 ok_last_release_closes(TRUE);
1082 end_host_object(host_tid, host_thread);
1085 /* tests success case of a same-thread table-weak marshal, unmarshal, unmarshal */
1086 static void test_tableweak_marshal_and_unmarshal_twice(void)
1088 HRESULT hr;
1089 IStream *pStream = NULL;
1090 IUnknown *pProxy1 = NULL;
1091 IUnknown *pProxy2 = NULL;
1092 DWORD tid;
1093 HANDLE thread;
1095 cLocks = 0;
1096 external_connections = 0;
1098 hr = CreateStreamOnHGlobal(NULL, TRUE, &pStream);
1099 ok_ole_success(hr, CreateStreamOnHGlobal);
1100 tid = start_host_object(pStream, &IID_IClassFactory, (IUnknown*)&Test_ClassFactory, MSHLFLAGS_TABLEWEAK, &thread);
1102 ok_more_than_one_lock();
1103 ok_zero_external_conn();
1105 IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
1106 hr = CoUnmarshalInterface(pStream, &IID_IClassFactory, (void **)&pProxy1);
1107 ok_ole_success(hr, CoUnmarshalInterface);
1109 ok_more_than_one_lock();
1110 ok_non_zero_external_conn();
1112 IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
1113 hr = CoUnmarshalInterface(pStream, &IID_IClassFactory, (void **)&pProxy2);
1114 ok_ole_success(hr, CoUnmarshalInterface);
1116 ok_more_than_one_lock();
1118 IUnknown_Release(pProxy1);
1119 ok_non_zero_external_conn();
1120 IUnknown_Release(pProxy2);
1121 ok_zero_external_conn();
1122 ok_last_release_closes(TRUE);
1124 /* When IExternalConnection is present COM's lifetime management
1125 * behaviour is altered; the remaining weak ref prevents stub shutdown. */
1126 if (with_external_conn)
1128 ok_more_than_one_lock();
1129 IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
1130 release_host_object(tid, 0);
1133 /* Without IExternalConnection this line is shows the difference between weak and strong table marshaling
1134 * weak has cLocks == 0, strong has cLocks > 0. */
1135 ok_no_locks();
1137 IStream_Release(pStream);
1138 end_host_object(tid, thread);
1141 /* tests releasing after unmarshaling one object */
1142 static void test_tableweak_marshal_releasedata1(void)
1144 HRESULT hr;
1145 IStream *pStream = NULL;
1146 IUnknown *pProxy1 = NULL;
1147 IUnknown *pProxy2 = NULL;
1148 DWORD tid;
1149 HANDLE thread;
1151 cLocks = 0;
1152 external_connections = 0;
1154 hr = CreateStreamOnHGlobal(NULL, TRUE, &pStream);
1155 ok_ole_success(hr, CreateStreamOnHGlobal);
1156 tid = start_host_object(pStream, &IID_IClassFactory, (IUnknown*)&Test_ClassFactory, MSHLFLAGS_TABLEWEAK, &thread);
1158 ok_more_than_one_lock();
1159 ok_zero_external_conn();
1161 IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
1162 hr = CoUnmarshalInterface(pStream, &IID_IClassFactory, (void **)&pProxy1);
1163 ok_ole_success(hr, CoUnmarshalInterface);
1165 ok_more_than_one_lock();
1166 ok_non_zero_external_conn();
1168 /* release the remaining reference on the object by calling
1169 * CoReleaseMarshalData in the hosting thread */
1170 IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
1171 release_host_object(tid, 0);
1173 ok_more_than_one_lock();
1174 ok_non_zero_external_conn();
1176 IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
1177 hr = CoUnmarshalInterface(pStream, &IID_IClassFactory, (void **)&pProxy2);
1178 ok_ole_success(hr, CoUnmarshalInterface);
1179 IStream_Release(pStream);
1181 ok_more_than_one_lock();
1182 ok_non_zero_external_conn();
1184 IUnknown_Release(pProxy1);
1186 if (pProxy2)
1188 ok_non_zero_external_conn();
1189 IUnknown_Release(pProxy2);
1192 /* this line is shows the difference between weak and strong table marshaling:
1193 * weak has cLocks == 0
1194 * strong has cLocks > 0 */
1195 ok_no_locks();
1196 ok_zero_external_conn();
1197 ok_last_release_closes(TRUE);
1199 end_host_object(tid, thread);
1202 /* tests releasing after unmarshaling one object */
1203 static void test_tableweak_marshal_releasedata2(void)
1205 HRESULT hr;
1206 IStream *pStream = NULL;
1207 IUnknown *pProxy = NULL;
1208 DWORD tid;
1209 HANDLE thread;
1211 cLocks = 0;
1212 external_connections = 0;
1214 hr = CreateStreamOnHGlobal(NULL, TRUE, &pStream);
1215 ok_ole_success(hr, CreateStreamOnHGlobal);
1216 tid = start_host_object(pStream, &IID_IClassFactory, (IUnknown*)&Test_ClassFactory, MSHLFLAGS_TABLEWEAK, &thread);
1218 ok_more_than_one_lock();
1219 ok_zero_external_conn();
1221 /* release the remaining reference on the object by calling
1222 * CoReleaseMarshalData in the hosting thread */
1223 IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
1224 release_host_object(tid, 0);
1226 ok_no_locks();
1228 IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
1229 hr = CoUnmarshalInterface(pStream, &IID_IClassFactory, (void **)&pProxy);
1230 todo_wine
1232 ok(hr == CO_E_OBJNOTREG,
1233 "CoUnmarshalInterface should have failed with CO_E_OBJNOTREG, but returned 0x%08x instead\n",
1234 hr);
1236 IStream_Release(pStream);
1238 ok_no_locks();
1239 ok_zero_external_conn();
1241 end_host_object(tid, thread);
1244 struct duo_marshal_data
1246 MSHLFLAGS marshal_flags1, marshal_flags2;
1247 IStream *pStream1, *pStream2;
1248 HANDLE hReadyEvent;
1249 HANDLE hQuitEvent;
1252 static DWORD CALLBACK duo_marshal_thread_proc(void *p)
1254 HRESULT hr;
1255 struct duo_marshal_data *data = p;
1256 HANDLE hQuitEvent = data->hQuitEvent;
1257 MSG msg;
1259 pCoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
1261 hr = CoMarshalInterface(data->pStream1, &IID_IClassFactory, (IUnknown*)&Test_ClassFactory, MSHCTX_INPROC, NULL, data->marshal_flags1);
1262 ok_ole_success(hr, "CoMarshalInterface");
1264 hr = CoMarshalInterface(data->pStream2, &IID_IClassFactory, (IUnknown*)&Test_ClassFactory, MSHCTX_INPROC, NULL, data->marshal_flags2);
1265 ok_ole_success(hr, "CoMarshalInterface");
1267 /* force the message queue to be created before signaling parent thread */
1268 PeekMessageA(&msg, NULL, WM_USER, WM_USER, PM_NOREMOVE);
1270 SetEvent(data->hReadyEvent);
1272 while (WAIT_OBJECT_0 + 1 == MsgWaitForMultipleObjects(1, &hQuitEvent, FALSE, 10000, QS_ALLINPUT))
1274 while (PeekMessageA(&msg, NULL, 0, 0, PM_REMOVE))
1276 if (msg.hwnd == NULL && msg.message == RELEASEMARSHALDATA)
1278 CoReleaseMarshalData(msg.wParam == 1 ? data->pStream1 : data->pStream2);
1279 SetEvent((HANDLE)msg.lParam);
1281 else
1282 DispatchMessageA(&msg);
1285 CloseHandle(hQuitEvent);
1287 CoUninitialize();
1289 return 0;
1292 /* tests interaction between table-weak and normal marshalling of an object */
1293 static void test_tableweak_and_normal_marshal_and_unmarshal(void)
1295 HRESULT hr;
1296 IUnknown *pProxyWeak = NULL;
1297 IUnknown *pProxyNormal = NULL;
1298 DWORD tid;
1299 HANDLE thread;
1300 struct duo_marshal_data data;
1302 cLocks = 0;
1303 external_connections = 0;
1305 data.hReadyEvent = CreateEventA(NULL, FALSE, FALSE, NULL);
1306 data.hQuitEvent = CreateEventA(NULL, FALSE, FALSE, NULL);
1307 data.marshal_flags1 = MSHLFLAGS_TABLEWEAK;
1308 data.marshal_flags2 = MSHLFLAGS_NORMAL;
1309 hr = CreateStreamOnHGlobal(NULL, TRUE, &data.pStream1);
1310 ok_ole_success(hr, CreateStreamOnHGlobal);
1311 hr = CreateStreamOnHGlobal(NULL, TRUE, &data.pStream2);
1312 ok_ole_success(hr, CreateStreamOnHGlobal);
1314 thread = CreateThread(NULL, 0, duo_marshal_thread_proc, &data, 0, &tid);
1315 ok( !WaitForSingleObject(data.hReadyEvent, 10000), "wait timed out\n" );
1316 CloseHandle(data.hReadyEvent);
1318 ok_more_than_one_lock();
1319 ok_non_zero_external_conn();
1321 /* weak */
1322 IStream_Seek(data.pStream1, ullZero, STREAM_SEEK_SET, NULL);
1323 hr = CoUnmarshalInterface(data.pStream1, &IID_IClassFactory, (void **)&pProxyWeak);
1324 ok_ole_success(hr, CoUnmarshalInterface);
1326 ok_more_than_one_lock();
1328 /* normal */
1329 IStream_Seek(data.pStream2, ullZero, STREAM_SEEK_SET, NULL);
1330 hr = CoUnmarshalInterface(data.pStream2, &IID_IClassFactory, (void **)&pProxyNormal);
1331 ok_ole_success(hr, CoUnmarshalInterface);
1333 ok_more_than_one_lock();
1335 IUnknown_Release(pProxyNormal);
1337 ok_more_than_one_lock();
1338 ok_non_zero_external_conn();
1340 IUnknown_Release(pProxyWeak);
1342 ok_zero_external_conn();
1343 ok_last_release_closes(TRUE);
1345 /* When IExternalConnection is present COM's lifetime management
1346 * behaviour is altered; the remaining weak ref prevents stub shutdown. */
1347 if (with_external_conn)
1349 ok_more_than_one_lock();
1350 IStream_Seek(data.pStream1, ullZero, STREAM_SEEK_SET, NULL);
1351 release_host_object(tid, 1);
1353 ok_no_locks();
1355 IStream_Release(data.pStream1);
1356 IStream_Release(data.pStream2);
1358 SetEvent(data.hQuitEvent);
1359 ok( !WaitForSingleObject(thread, 10000), "wait timed out\n" );
1360 CloseHandle(thread);
1363 static void test_tableweak_and_normal_marshal_and_releasedata(void)
1365 HRESULT hr;
1366 DWORD tid;
1367 HANDLE thread;
1368 struct duo_marshal_data data;
1370 cLocks = 0;
1371 external_connections = 0;
1373 data.hReadyEvent = CreateEventA(NULL, FALSE, FALSE, NULL);
1374 data.hQuitEvent = CreateEventA(NULL, FALSE, FALSE, NULL);
1375 data.marshal_flags1 = MSHLFLAGS_TABLEWEAK;
1376 data.marshal_flags2 = MSHLFLAGS_NORMAL;
1377 hr = CreateStreamOnHGlobal(NULL, TRUE, &data.pStream1);
1378 ok_ole_success(hr, CreateStreamOnHGlobal);
1379 hr = CreateStreamOnHGlobal(NULL, TRUE, &data.pStream2);
1380 ok_ole_success(hr, CreateStreamOnHGlobal);
1382 thread = CreateThread(NULL, 0, duo_marshal_thread_proc, &data, 0, &tid);
1383 ok( !WaitForSingleObject(data.hReadyEvent, 10000), "wait timed out\n" );
1384 CloseHandle(data.hReadyEvent);
1386 ok_more_than_one_lock();
1387 ok_non_zero_external_conn();
1389 /* release normal - which in the non-external conn case will free the object despite the weak ref. */
1390 IStream_Seek(data.pStream2, ullZero, STREAM_SEEK_SET, NULL);
1391 release_host_object(tid, 2);
1393 ok_zero_external_conn();
1394 ok_last_release_closes(TRUE);
1396 if (with_external_conn)
1398 ok_more_than_one_lock();
1399 IStream_Seek(data.pStream1, ullZero, STREAM_SEEK_SET, NULL);
1400 release_host_object(tid, 1);
1403 ok_no_locks();
1405 IStream_Release(data.pStream1);
1406 IStream_Release(data.pStream2);
1408 SetEvent(data.hQuitEvent);
1409 ok( !WaitForSingleObject(thread, 10000), "wait timed out\n" );
1410 CloseHandle(thread);
1413 static void test_two_tableweak_marshal_and_releasedata(void)
1415 HRESULT hr;
1416 DWORD tid;
1417 HANDLE thread;
1418 struct duo_marshal_data data;
1420 cLocks = 0;
1421 external_connections = 0;
1423 data.hReadyEvent = CreateEventA(NULL, FALSE, FALSE, NULL);
1424 data.hQuitEvent = CreateEventA(NULL, FALSE, FALSE, NULL);
1425 data.marshal_flags1 = MSHLFLAGS_TABLEWEAK;
1426 data.marshal_flags2 = MSHLFLAGS_TABLEWEAK;
1427 hr = CreateStreamOnHGlobal(NULL, TRUE, &data.pStream1);
1428 ok_ole_success(hr, CreateStreamOnHGlobal);
1429 hr = CreateStreamOnHGlobal(NULL, TRUE, &data.pStream2);
1430 ok_ole_success(hr, CreateStreamOnHGlobal);
1432 thread = CreateThread(NULL, 0, duo_marshal_thread_proc, &data, 0, &tid);
1433 ok( !WaitForSingleObject(data.hReadyEvent, 10000), "wait timed out\n" );
1434 CloseHandle(data.hReadyEvent);
1436 ok_more_than_one_lock();
1437 ok_zero_external_conn();
1439 /* release one weak ref - the remaining weak ref will keep the obj alive */
1440 IStream_Seek(data.pStream1, ullZero, STREAM_SEEK_SET, NULL);
1441 release_host_object(tid, 1);
1443 ok_more_than_one_lock();
1445 IStream_Seek(data.pStream2, ullZero, STREAM_SEEK_SET, NULL);
1446 release_host_object(tid, 2);
1448 ok_no_locks();
1450 IStream_Release(data.pStream1);
1451 IStream_Release(data.pStream2);
1453 SetEvent(data.hQuitEvent);
1454 ok( !WaitForSingleObject(thread, 10000), "wait timed out\n" );
1455 CloseHandle(thread);
1458 /* tests success case of a same-thread table-strong marshal, unmarshal, unmarshal */
1459 static void test_tablestrong_marshal_and_unmarshal_twice(void)
1461 HRESULT hr;
1462 IStream *pStream = NULL;
1463 IUnknown *pProxy1 = NULL;
1464 IUnknown *pProxy2 = NULL;
1465 DWORD tid;
1466 HANDLE thread;
1468 cLocks = 0;
1469 external_connections = 0;
1471 hr = CreateStreamOnHGlobal(NULL, TRUE, &pStream);
1472 ok_ole_success(hr, CreateStreamOnHGlobal);
1473 tid = start_host_object(pStream, &IID_IClassFactory, (IUnknown*)&Test_ClassFactory, MSHLFLAGS_TABLESTRONG, &thread);
1475 ok_more_than_one_lock();
1476 ok_non_zero_external_conn();
1478 IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
1479 hr = CoUnmarshalInterface(pStream, &IID_IClassFactory, (void **)&pProxy1);
1480 ok_ole_success(hr, CoUnmarshalInterface);
1482 ok_more_than_one_lock();
1484 IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
1485 hr = CoUnmarshalInterface(pStream, &IID_IClassFactory, (void **)&pProxy2);
1486 ok_ole_success(hr, CoUnmarshalInterface);
1488 ok_more_than_one_lock();
1490 if (pProxy1) IUnknown_Release(pProxy1);
1491 if (pProxy2) IUnknown_Release(pProxy2);
1493 /* this line is shows the difference between weak and strong table marshaling:
1494 * weak has cLocks == 0
1495 * strong has cLocks > 0 */
1496 ok_more_than_one_lock();
1498 /* release the remaining reference on the object by calling
1499 * CoReleaseMarshalData in the hosting thread */
1500 IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
1501 release_host_object(tid, 0);
1502 IStream_Release(pStream);
1504 ok_no_locks();
1505 ok_zero_external_conn();
1506 ok_last_release_closes(TRUE);
1508 end_host_object(tid, thread);
1511 /* tests CoLockObjectExternal */
1512 static void test_lock_object_external(void)
1514 HRESULT hr;
1515 IStream *pStream = NULL;
1517 cLocks = 0;
1518 external_connections = 0;
1520 /* test the stub manager creation aspect of CoLockObjectExternal when the
1521 * object hasn't been marshaled yet */
1522 CoLockObjectExternal((IUnknown*)&Test_ClassFactory, TRUE, TRUE);
1524 ok_more_than_one_lock();
1525 ok_non_zero_external_conn();
1527 CoDisconnectObject((IUnknown*)&Test_ClassFactory, 0);
1529 ok_no_locks();
1530 ok_non_zero_external_conn();
1531 external_connections = 0;
1533 /* test our empty stub manager being handled correctly in
1534 * CoMarshalInterface */
1535 CoLockObjectExternal((IUnknown*)&Test_ClassFactory, TRUE, TRUE);
1537 hr = CreateStreamOnHGlobal(NULL, TRUE, &pStream);
1538 ok_ole_success(hr, CreateStreamOnHGlobal);
1539 hr = CoMarshalInterface(pStream, &IID_IClassFactory, (IUnknown*)&Test_ClassFactory, MSHCTX_INPROC, NULL, MSHLFLAGS_NORMAL);
1540 ok_ole_success(hr, CoMarshalInterface);
1542 CoLockObjectExternal((IUnknown*)&Test_ClassFactory, TRUE, TRUE);
1544 ok_more_than_one_lock();
1545 ok_non_zero_external_conn();
1547 IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
1548 hr = CoReleaseMarshalData(pStream);
1549 ok_ole_success(hr, CoReleaseMarshalData);
1550 IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
1552 ok_more_than_one_lock();
1553 ok_non_zero_external_conn();
1554 ok_last_release_closes(TRUE);
1556 CoLockObjectExternal((IUnknown*)&Test_ClassFactory, FALSE, TRUE);
1558 ok_more_than_one_lock();
1559 ok_non_zero_external_conn();
1560 ok_last_release_closes(TRUE);
1562 CoLockObjectExternal((IUnknown*)&Test_ClassFactory, FALSE, TRUE);
1564 ok_no_locks();
1565 ok_zero_external_conn();
1566 ok_last_release_closes(TRUE);
1568 /* test CoLockObjectExternal releases reference to object with
1569 * fLastUnlockReleases as TRUE and there are only strong references on
1570 * the object */
1571 CoLockObjectExternal((IUnknown*)&Test_ClassFactory, TRUE, FALSE);
1573 ok_more_than_one_lock();
1574 ok_non_zero_external_conn();
1576 CoLockObjectExternal((IUnknown*)&Test_ClassFactory, FALSE, FALSE);
1578 ok_no_locks();
1579 ok_zero_external_conn();
1580 ok_last_release_closes(FALSE);
1582 /* test CoLockObjectExternal doesn't release the last reference to an
1583 * object with fLastUnlockReleases as TRUE and there is a weak reference
1584 * on the object */
1585 hr = CoMarshalInterface(pStream, &IID_IClassFactory, (IUnknown*)&Test_ClassFactory, MSHCTX_INPROC, NULL, MSHLFLAGS_TABLEWEAK);
1586 ok_ole_success(hr, CoMarshalInterface);
1588 ok_more_than_one_lock();
1589 ok_zero_external_conn();
1591 CoLockObjectExternal((IUnknown*)&Test_ClassFactory, TRUE, FALSE);
1593 ok_more_than_one_lock();
1594 ok_non_zero_external_conn();
1596 CoLockObjectExternal((IUnknown*)&Test_ClassFactory, FALSE, FALSE);
1598 ok_more_than_one_lock();
1599 ok_zero_external_conn();
1600 ok_last_release_closes(FALSE);
1602 CoDisconnectObject((IUnknown*)&Test_ClassFactory, 0);
1604 ok_no_locks();
1606 IStream_Release(pStream);
1609 /* tests disconnecting stubs */
1610 static void test_disconnect_stub(void)
1612 HRESULT hr;
1613 IStream *pStream = NULL;
1615 cLocks = 0;
1616 external_connections = 0;
1618 hr = CreateStreamOnHGlobal(NULL, TRUE, &pStream);
1619 ok_ole_success(hr, CreateStreamOnHGlobal);
1620 hr = CoMarshalInterface(pStream, &IID_IClassFactory, (IUnknown*)&Test_ClassFactory, MSHCTX_INPROC, NULL, MSHLFLAGS_NORMAL);
1621 ok_ole_success(hr, CoMarshalInterface);
1623 ok_non_zero_external_conn();
1625 CoLockObjectExternal((IUnknown*)&Test_ClassFactory, TRUE, TRUE);
1627 ok_more_than_one_lock();
1628 ok_non_zero_external_conn();
1630 IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
1631 hr = CoReleaseMarshalData(pStream);
1632 ok_ole_success(hr, CoReleaseMarshalData);
1633 IStream_Release(pStream);
1635 ok_more_than_one_lock();
1636 ok_non_zero_external_conn();
1638 CoDisconnectObject((IUnknown*)&Test_ClassFactory, 0);
1640 ok_no_locks();
1641 ok_non_zero_external_conn();
1643 hr = CoDisconnectObject(NULL, 0);
1644 ok( hr == E_INVALIDARG, "wrong status %x\n", hr );
1647 /* tests failure case of a same-thread marshal and unmarshal twice */
1648 static void test_normal_marshal_and_unmarshal_twice(void)
1650 HRESULT hr;
1651 IStream *pStream = NULL;
1652 IUnknown *pProxy1 = NULL;
1653 IUnknown *pProxy2 = NULL;
1655 cLocks = 0;
1656 external_connections = 0;
1658 hr = CreateStreamOnHGlobal(NULL, TRUE, &pStream);
1659 ok_ole_success(hr, CreateStreamOnHGlobal);
1660 hr = CoMarshalInterface(pStream, &IID_IClassFactory, (IUnknown*)&Test_ClassFactory, MSHCTX_INPROC, NULL, MSHLFLAGS_NORMAL);
1661 ok_ole_success(hr, CoMarshalInterface);
1663 ok_more_than_one_lock();
1664 ok_non_zero_external_conn();
1666 IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
1667 hr = CoUnmarshalInterface(pStream, &IID_IClassFactory, (void **)&pProxy1);
1668 ok_ole_success(hr, CoUnmarshalInterface);
1670 ok_more_than_one_lock();
1671 ok_zero_external_conn();
1672 ok_last_release_closes(FALSE);
1674 IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
1675 hr = CoUnmarshalInterface(pStream, &IID_IClassFactory, (void **)&pProxy2);
1676 ok(hr == CO_E_OBJNOTCONNECTED,
1677 "CoUnmarshalInterface should have failed with error CO_E_OBJNOTCONNECTED for double unmarshal, instead of 0x%08x\n", hr);
1679 IStream_Release(pStream);
1681 ok_more_than_one_lock();
1683 IUnknown_Release(pProxy1);
1685 ok_no_locks();
1688 /* tests success case of marshaling and unmarshaling an HRESULT */
1689 static void test_hresult_marshaling(void)
1691 HRESULT hr;
1692 HRESULT hr_marshaled = 0;
1693 IStream *pStream = NULL;
1694 static const HRESULT E_DEADBEEF = 0xdeadbeef;
1696 hr = CreateStreamOnHGlobal(NULL, TRUE, &pStream);
1697 ok_ole_success(hr, CreateStreamOnHGlobal);
1699 hr = CoMarshalHresult(pStream, E_DEADBEEF);
1700 ok_ole_success(hr, CoMarshalHresult);
1702 IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
1703 hr = IStream_Read(pStream, &hr_marshaled, sizeof(HRESULT), NULL);
1704 ok_ole_success(hr, IStream_Read);
1706 ok(hr_marshaled == E_DEADBEEF, "Didn't marshal HRESULT as expected: got value 0x%08x instead\n", hr_marshaled);
1708 hr_marshaled = 0;
1709 IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
1710 hr = CoUnmarshalHresult(pStream, &hr_marshaled);
1711 ok_ole_success(hr, CoUnmarshalHresult);
1713 ok(hr_marshaled == E_DEADBEEF, "Didn't marshal HRESULT as expected: got value 0x%08x instead\n", hr_marshaled);
1715 IStream_Release(pStream);
1719 /* helper for test_proxy_used_in_wrong_thread */
1720 static DWORD CALLBACK bad_thread_proc(LPVOID p)
1722 IClassFactory * cf = p;
1723 HRESULT hr;
1724 IUnknown * proxy = NULL;
1726 hr = IClassFactory_CreateInstance(cf, NULL, &IID_IUnknown, (LPVOID*)&proxy);
1727 todo_wine
1728 ok(hr == CO_E_NOTINITIALIZED,
1729 "COM should have failed with CO_E_NOTINITIALIZED on using proxy without apartment, but instead returned 0x%08x\n",
1730 hr);
1732 hr = IClassFactory_QueryInterface(cf, &IID_IMultiQI, (LPVOID *)&proxy);
1733 /* Win9x returns S_OK, whilst NT returns RPC_E_WRONG_THREAD */
1734 trace("call to proxy's QueryInterface for local interface without apartment returned 0x%08x\n", hr);
1735 if (SUCCEEDED(hr))
1736 IUnknown_Release(proxy);
1738 hr = IClassFactory_QueryInterface(cf, &IID_IStream, (LPVOID *)&proxy);
1739 /* Win9x returns E_NOINTERFACE, whilst NT returns RPC_E_WRONG_THREAD */
1740 trace("call to proxy's QueryInterface without apartment returned 0x%08x\n", hr);
1741 if (SUCCEEDED(hr))
1742 IUnknown_Release(proxy);
1744 pCoInitializeEx(NULL, COINIT_MULTITHREADED);
1746 hr = IClassFactory_CreateInstance(cf, NULL, &IID_IUnknown, (LPVOID*)&proxy);
1747 if (proxy) IUnknown_Release(proxy);
1748 ok(hr == RPC_E_WRONG_THREAD,
1749 "COM should have failed with RPC_E_WRONG_THREAD on using proxy from wrong apartment, but instead returned 0x%08x\n",
1750 hr);
1752 hr = IClassFactory_QueryInterface(cf, &IID_IStream, (LPVOID *)&proxy);
1753 /* Win9x returns E_NOINTERFACE, whilst NT returns RPC_E_WRONG_THREAD */
1754 trace("call to proxy's QueryInterface from wrong apartment returned 0x%08x\n", hr);
1756 /* now be really bad and release the proxy from the wrong apartment */
1757 IClassFactory_Release(cf);
1759 CoUninitialize();
1761 return 0;
1764 /* tests failure case of a using a proxy in the wrong apartment */
1765 static void test_proxy_used_in_wrong_thread(void)
1767 HRESULT hr;
1768 IStream *pStream = NULL;
1769 IUnknown *pProxy = NULL;
1770 DWORD tid, tid2;
1771 HANDLE thread;
1772 HANDLE host_thread;
1774 cLocks = 0;
1776 hr = CreateStreamOnHGlobal(NULL, TRUE, &pStream);
1777 ok_ole_success(hr, CreateStreamOnHGlobal);
1778 tid = start_host_object(pStream, &IID_IClassFactory, (IUnknown*)&Test_ClassFactory, MSHLFLAGS_NORMAL, &host_thread);
1780 ok_more_than_one_lock();
1782 IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
1783 hr = CoUnmarshalInterface(pStream, &IID_IClassFactory, (void **)&pProxy);
1784 ok_ole_success(hr, CoUnmarshalInterface);
1785 IStream_Release(pStream);
1787 ok_more_than_one_lock();
1789 /* do a call that will fail, but result in IRemUnknown being used by the proxy */
1790 IUnknown_QueryInterface(pProxy, &IID_IStream, (LPVOID *)&pStream);
1792 /* create a thread that we can misbehave in */
1793 thread = CreateThread(NULL, 0, bad_thread_proc, pProxy, 0, &tid2);
1795 ok( !WaitForSingleObject(thread, 10000), "wait timed out\n" );
1796 CloseHandle(thread);
1798 /* do release statement on Win9x that we should have done above */
1799 if (!GetProcAddress(GetModuleHandleA("ole32"), "CoRegisterSurrogateEx"))
1800 IUnknown_Release(pProxy);
1802 ok_no_locks();
1804 end_host_object(tid, host_thread);
1807 static HRESULT WINAPI MessageFilter_QueryInterface(IMessageFilter *iface, REFIID riid, void ** ppvObj)
1809 if (ppvObj == NULL) return E_POINTER;
1811 if (IsEqualGUID(riid, &IID_IUnknown) ||
1812 IsEqualGUID(riid, &IID_IClassFactory))
1814 *ppvObj = iface;
1815 IMessageFilter_AddRef(iface);
1816 return S_OK;
1819 return E_NOINTERFACE;
1822 static ULONG WINAPI MessageFilter_AddRef(IMessageFilter *iface)
1824 return 2; /* non-heap object */
1827 static ULONG WINAPI MessageFilter_Release(IMessageFilter *iface)
1829 return 1; /* non-heap object */
1832 static DWORD WINAPI MessageFilter_HandleInComingCall(
1833 IMessageFilter *iface,
1834 DWORD dwCallType,
1835 HTASK threadIDCaller,
1836 DWORD dwTickCount,
1837 LPINTERFACEINFO lpInterfaceInfo)
1839 static int callcount = 0;
1840 DWORD ret;
1841 trace("HandleInComingCall\n");
1842 switch (callcount)
1844 case 0:
1845 ret = SERVERCALL_REJECTED;
1846 break;
1847 case 1:
1848 ret = SERVERCALL_RETRYLATER;
1849 break;
1850 default:
1851 ret = SERVERCALL_ISHANDLED;
1852 break;
1854 callcount++;
1855 return ret;
1858 static DWORD WINAPI MessageFilter_RetryRejectedCall(
1859 IMessageFilter *iface,
1860 HTASK threadIDCallee,
1861 DWORD dwTickCount,
1862 DWORD dwRejectType)
1864 trace("RetryRejectedCall\n");
1865 return 0;
1868 static DWORD WINAPI MessageFilter_MessagePending(
1869 IMessageFilter *iface,
1870 HTASK threadIDCallee,
1871 DWORD dwTickCount,
1872 DWORD dwPendingType)
1874 trace("MessagePending\n");
1875 return PENDINGMSG_WAITNOPROCESS;
1878 static const IMessageFilterVtbl MessageFilter_Vtbl =
1880 MessageFilter_QueryInterface,
1881 MessageFilter_AddRef,
1882 MessageFilter_Release,
1883 MessageFilter_HandleInComingCall,
1884 MessageFilter_RetryRejectedCall,
1885 MessageFilter_MessagePending
1888 static IMessageFilter MessageFilter = { &MessageFilter_Vtbl };
1890 static void test_message_filter(void)
1892 HRESULT hr;
1893 IStream *pStream = NULL;
1894 IClassFactory *cf = NULL;
1895 DWORD tid;
1896 IUnknown *proxy = NULL;
1897 IMessageFilter *prev_filter = NULL;
1898 HANDLE thread;
1900 cLocks = 0;
1902 hr = CreateStreamOnHGlobal(NULL, TRUE, &pStream);
1903 ok_ole_success(hr, CreateStreamOnHGlobal);
1904 tid = start_host_object2(pStream, &IID_IClassFactory, (IUnknown*)&Test_ClassFactory, MSHLFLAGS_NORMAL, &MessageFilter, &thread);
1906 ok_more_than_one_lock();
1908 IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
1909 hr = CoUnmarshalInterface(pStream, &IID_IClassFactory, (void **)&cf);
1910 ok_ole_success(hr, CoUnmarshalInterface);
1911 IStream_Release(pStream);
1913 ok_more_than_one_lock();
1915 hr = IClassFactory_CreateInstance(cf, NULL, &IID_IUnknown, (LPVOID*)&proxy);
1916 ok(hr == RPC_E_CALL_REJECTED, "Call should have returned RPC_E_CALL_REJECTED, but return 0x%08x instead\n", hr);
1917 if (proxy) IUnknown_Release(proxy);
1918 proxy = NULL;
1920 hr = CoRegisterMessageFilter(&MessageFilter, &prev_filter);
1921 ok_ole_success(hr, CoRegisterMessageFilter);
1923 hr = IClassFactory_CreateInstance(cf, NULL, &IID_IUnknown, (LPVOID*)&proxy);
1924 ok_ole_success(hr, IClassFactory_CreateInstance);
1926 IUnknown_Release(proxy);
1928 IClassFactory_Release(cf);
1930 ok_no_locks();
1932 end_host_object(tid, thread);
1934 hr = CoRegisterMessageFilter(prev_filter, NULL);
1935 ok_ole_success(hr, CoRegisterMessageFilter);
1938 /* test failure case of trying to unmarshal from bad stream */
1939 static void test_bad_marshal_stream(void)
1941 HRESULT hr;
1942 IStream *pStream = NULL;
1944 hr = CreateStreamOnHGlobal(NULL, TRUE, &pStream);
1945 ok_ole_success(hr, CreateStreamOnHGlobal);
1946 hr = CoMarshalInterface(pStream, &IID_IClassFactory, (IUnknown*)&Test_ClassFactory, MSHCTX_INPROC, NULL, MSHLFLAGS_NORMAL);
1947 ok_ole_success(hr, CoMarshalInterface);
1949 ok_more_than_one_lock();
1951 /* try to read beyond end of stream */
1952 hr = CoReleaseMarshalData(pStream);
1953 ok(hr == STG_E_READFAULT, "Should have failed with STG_E_READFAULT, but returned 0x%08x instead\n", hr);
1955 /* now release for real */
1956 IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
1957 hr = CoReleaseMarshalData(pStream);
1958 ok_ole_success(hr, CoReleaseMarshalData);
1960 IStream_Release(pStream);
1963 /* tests that proxies implement certain interfaces */
1964 static void test_proxy_interfaces(void)
1966 HRESULT hr;
1967 IStream *pStream = NULL;
1968 IUnknown *pProxy = NULL;
1969 IUnknown *pOtherUnknown = NULL;
1970 DWORD tid;
1971 HANDLE thread;
1973 cLocks = 0;
1975 hr = CreateStreamOnHGlobal(NULL, TRUE, &pStream);
1976 ok_ole_success(hr, CreateStreamOnHGlobal);
1977 tid = start_host_object(pStream, &IID_IClassFactory, (IUnknown*)&Test_ClassFactory, MSHLFLAGS_NORMAL, &thread);
1979 ok_more_than_one_lock();
1981 IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
1982 hr = CoUnmarshalInterface(pStream, &IID_IUnknown, (void **)&pProxy);
1983 ok_ole_success(hr, CoUnmarshalInterface);
1984 IStream_Release(pStream);
1986 ok_more_than_one_lock();
1988 hr = IUnknown_QueryInterface(pProxy, &IID_IUnknown, (LPVOID*)&pOtherUnknown);
1989 ok_ole_success(hr, IUnknown_QueryInterface IID_IUnknown);
1990 if (hr == S_OK) IUnknown_Release(pOtherUnknown);
1992 hr = IUnknown_QueryInterface(pProxy, &IID_IClientSecurity, (LPVOID*)&pOtherUnknown);
1993 ok_ole_success(hr, IUnknown_QueryInterface IID_IClientSecurity);
1994 if (hr == S_OK) IUnknown_Release(pOtherUnknown);
1996 hr = IUnknown_QueryInterface(pProxy, &IID_IMultiQI, (LPVOID*)&pOtherUnknown);
1997 ok_ole_success(hr, IUnknown_QueryInterface IID_IMultiQI);
1998 if (hr == S_OK) IUnknown_Release(pOtherUnknown);
2000 hr = IUnknown_QueryInterface(pProxy, &IID_IMarshal, (LPVOID*)&pOtherUnknown);
2001 ok_ole_success(hr, IUnknown_QueryInterface IID_IMarshal);
2002 if (hr == S_OK) IUnknown_Release(pOtherUnknown);
2004 /* IMarshal2 is also supported on NT-based systems, but is pretty much
2005 * useless as it has no more methods over IMarshal that it inherits from. */
2007 IUnknown_Release(pProxy);
2009 ok_no_locks();
2011 end_host_object(tid, thread);
2014 typedef struct
2016 IUnknown IUnknown_iface;
2017 ULONG refs;
2018 } HeapUnknown;
2020 static inline HeapUnknown *impl_from_IUnknown(IUnknown *iface)
2022 return CONTAINING_RECORD(iface, HeapUnknown, IUnknown_iface);
2025 static HRESULT WINAPI HeapUnknown_QueryInterface(IUnknown *iface, REFIID riid, void **ppv)
2027 if (IsEqualIID(riid, &IID_IUnknown))
2029 IUnknown_AddRef(iface);
2030 *ppv = iface;
2031 return S_OK;
2033 *ppv = NULL;
2034 return E_NOINTERFACE;
2037 static ULONG WINAPI HeapUnknown_AddRef(IUnknown *iface)
2039 HeapUnknown *This = impl_from_IUnknown(iface);
2040 return InterlockedIncrement((LONG*)&This->refs);
2043 static ULONG WINAPI HeapUnknown_Release(IUnknown *iface)
2045 HeapUnknown *This = impl_from_IUnknown(iface);
2046 ULONG refs = InterlockedDecrement((LONG*)&This->refs);
2047 if (!refs) HeapFree(GetProcessHeap(), 0, This);
2048 return refs;
2051 static const IUnknownVtbl HeapUnknown_Vtbl =
2053 HeapUnknown_QueryInterface,
2054 HeapUnknown_AddRef,
2055 HeapUnknown_Release
2058 static void test_proxybuffer(REFIID riid)
2060 HRESULT hr;
2061 IPSFactoryBuffer *psfb;
2062 IRpcProxyBuffer *proxy;
2063 LPVOID lpvtbl;
2064 ULONG refs;
2065 CLSID clsid;
2066 HeapUnknown *pUnkOuter = HeapAlloc(GetProcessHeap(), 0, sizeof(*pUnkOuter));
2068 pUnkOuter->IUnknown_iface.lpVtbl = &HeapUnknown_Vtbl;
2069 pUnkOuter->refs = 1;
2071 hr = CoGetPSClsid(riid, &clsid);
2072 ok_ole_success(hr, CoGetPSClsid);
2074 hr = CoGetClassObject(&clsid, CLSCTX_INPROC_SERVER, NULL, &IID_IPSFactoryBuffer, (LPVOID*)&psfb);
2075 ok_ole_success(hr, CoGetClassObject);
2077 hr = IPSFactoryBuffer_CreateProxy(psfb, &pUnkOuter->IUnknown_iface, riid, &proxy, &lpvtbl);
2078 ok_ole_success(hr, IPSFactoryBuffer_CreateProxy);
2079 ok(lpvtbl != NULL, "IPSFactoryBuffer_CreateProxy succeeded, but returned a NULL vtable!\n");
2081 /* release our reference to the outer unknown object - the PS factory
2082 * buffer will have AddRef's it in the CreateProxy call */
2083 refs = IUnknown_Release(&pUnkOuter->IUnknown_iface);
2084 ok(refs == 1, "Ref count of outer unknown should have been 1 instead of %d\n", refs);
2086 /* Not checking return, unreliable on native. Maybe it leaks references? */
2087 IPSFactoryBuffer_Release(psfb);
2089 refs = IUnknown_Release((IUnknown *)lpvtbl);
2090 ok(refs == 0, "Ref-count leak of %d on IRpcProxyBuffer\n", refs);
2092 refs = IRpcProxyBuffer_Release(proxy);
2093 ok(refs == 0, "Ref-count leak of %d on IRpcProxyBuffer\n", refs);
2096 static void test_stubbuffer(REFIID riid)
2098 HRESULT hr;
2099 IPSFactoryBuffer *psfb;
2100 IRpcStubBuffer *stub;
2101 ULONG refs;
2102 CLSID clsid;
2104 cLocks = 0;
2106 hr = CoGetPSClsid(riid, &clsid);
2107 ok_ole_success(hr, CoGetPSClsid);
2109 hr = CoGetClassObject(&clsid, CLSCTX_INPROC_SERVER, NULL, &IID_IPSFactoryBuffer, (LPVOID*)&psfb);
2110 ok_ole_success(hr, CoGetClassObject);
2112 hr = IPSFactoryBuffer_CreateStub(psfb, riid, (IUnknown*)&Test_ClassFactory, &stub);
2113 ok_ole_success(hr, IPSFactoryBuffer_CreateStub);
2115 /* Not checking return, unreliable on native. Maybe it leaks references? */
2116 IPSFactoryBuffer_Release(psfb);
2118 ok_more_than_one_lock();
2120 IRpcStubBuffer_Disconnect(stub);
2122 ok_no_locks();
2124 refs = IRpcStubBuffer_Release(stub);
2125 ok(refs == 0, "Ref-count leak of %d on IRpcProxyBuffer\n", refs);
2128 static HWND hwnd_app;
2130 static HRESULT WINAPI TestRE_IClassFactory_CreateInstance(
2131 LPCLASSFACTORY iface,
2132 LPUNKNOWN pUnkOuter,
2133 REFIID riid,
2134 LPVOID *ppvObj)
2136 DWORD_PTR res;
2137 if (IsEqualIID(riid, &IID_IWineTest))
2139 BOOL ret = SendMessageTimeoutA(hwnd_app, WM_NULL, 0, 0, SMTO_BLOCK, 5000, &res);
2140 ok(ret, "Timed out sending a message to originating window during RPC call\n");
2142 *ppvObj = NULL;
2143 return S_FALSE;
2146 static const IClassFactoryVtbl TestREClassFactory_Vtbl =
2148 Test_IClassFactory_QueryInterface,
2149 Test_IClassFactory_AddRef,
2150 Test_IClassFactory_Release,
2151 TestRE_IClassFactory_CreateInstance,
2152 Test_IClassFactory_LockServer
2155 static IClassFactory TestRE_ClassFactory = { &TestREClassFactory_Vtbl };
2157 static LRESULT CALLBACK window_proc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam)
2159 switch (msg)
2161 case WM_USER:
2163 HRESULT hr;
2164 IStream *pStream = NULL;
2165 IClassFactory *proxy = NULL;
2166 IUnknown *object;
2167 DWORD tid;
2168 HANDLE thread;
2170 cLocks = 0;
2172 hr = CreateStreamOnHGlobal(NULL, TRUE, &pStream);
2173 ok_ole_success(hr, CreateStreamOnHGlobal);
2174 tid = start_host_object(pStream, &IID_IClassFactory, (IUnknown*)&TestRE_ClassFactory, MSHLFLAGS_NORMAL, &thread);
2176 ok_more_than_one_lock();
2178 IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
2179 hr = CoUnmarshalInterface(pStream, &IID_IClassFactory, (void **)&proxy);
2180 ok_ole_success(hr, CoReleaseMarshalData);
2181 IStream_Release(pStream);
2183 ok_more_than_one_lock();
2185 /* note the use of the magic IID_IWineTest value to tell remote thread
2186 * to try to send a message back to us */
2187 hr = IClassFactory_CreateInstance(proxy, NULL, &IID_IWineTest, (void **)&object);
2188 ok(hr == S_FALSE, "expected S_FALSE, got %d\n", hr);
2190 IClassFactory_Release(proxy);
2192 ok_no_locks();
2194 end_host_object(tid, thread);
2196 PostMessageA(hwnd, WM_QUIT, 0, 0);
2198 return 0;
2200 case WM_USER+1:
2202 HRESULT hr;
2203 IStream *pStream = NULL;
2204 IClassFactory *proxy = NULL;
2205 IUnknown *object;
2206 DWORD tid;
2207 HANDLE thread;
2209 cLocks = 0;
2211 hr = CreateStreamOnHGlobal(NULL, TRUE, &pStream);
2212 ok_ole_success(hr, CreateStreamOnHGlobal);
2213 tid = start_host_object(pStream, &IID_IClassFactory, (IUnknown*)&TestRE_ClassFactory, MSHLFLAGS_NORMAL, &thread);
2215 ok_more_than_one_lock();
2217 IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
2218 hr = CoUnmarshalInterface(pStream, &IID_IClassFactory, (void **)&proxy);
2219 ok_ole_success(hr, CoReleaseMarshalData);
2220 IStream_Release(pStream);
2222 ok_more_than_one_lock();
2224 /* post quit message before a doing a COM call to show that a pending
2225 * WM_QUIT message doesn't stop the call from succeeding */
2226 PostMessageA(hwnd, WM_QUIT, 0, 0);
2227 hr = IClassFactory_CreateInstance(proxy, NULL, &IID_IUnknown, (void **)&object);
2228 ok(hr == S_FALSE, "IClassFactory_CreateInstance returned 0x%08x, expected S_FALSE\n", hr);
2230 IClassFactory_Release(proxy);
2232 ok_no_locks();
2234 end_host_object(tid, thread);
2236 return 0;
2238 case WM_USER+2:
2240 HRESULT hr;
2241 IStream *pStream = NULL;
2242 IClassFactory *proxy = NULL;
2243 IUnknown *object;
2244 DWORD tid;
2245 HANDLE thread;
2247 hr = CreateStreamOnHGlobal(NULL, TRUE, &pStream);
2248 ok_ole_success(hr, CreateStreamOnHGlobal);
2249 tid = start_host_object(pStream, &IID_IClassFactory, (IUnknown*)&Test_ClassFactory, MSHLFLAGS_NORMAL, &thread);
2251 IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
2252 hr = CoUnmarshalInterface(pStream, &IID_IClassFactory, (void **)&proxy);
2253 ok_ole_success(hr, CoReleaseMarshalData);
2254 IStream_Release(pStream);
2256 /* shows that COM calls executed during the processing of sent
2257 * messages should fail */
2258 hr = IClassFactory_CreateInstance(proxy, NULL, &IID_IUnknown, (void **)&object);
2259 ok(hr == RPC_E_CANTCALLOUT_ININPUTSYNCCALL,
2260 "COM call during processing of sent message should return RPC_E_CANTCALLOUT_ININPUTSYNCCALL instead of 0x%08x\n", hr);
2262 IClassFactory_Release(proxy);
2264 end_host_object(tid, thread);
2266 PostQuitMessage(0);
2268 return 0;
2270 default:
2271 return DefWindowProcA(hwnd, msg, wparam, lparam);
2275 static void register_test_window(void)
2277 WNDCLASSA wndclass;
2279 memset(&wndclass, 0, sizeof(wndclass));
2280 wndclass.lpfnWndProc = window_proc;
2281 wndclass.lpszClassName = "WineCOMTest";
2282 RegisterClassA(&wndclass);
2285 static void test_message_reentrancy(void)
2287 MSG msg;
2289 hwnd_app = CreateWindowA("WineCOMTest", NULL, 0, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, NULL, NULL, NULL, 0);
2290 ok(hwnd_app != NULL, "Window creation failed\n");
2292 /* start message re-entrancy test */
2293 PostMessageA(hwnd_app, WM_USER, 0, 0);
2295 while (GetMessageA(&msg, NULL, 0, 0))
2297 TranslateMessage(&msg);
2298 DispatchMessageA(&msg);
2300 DestroyWindow(hwnd_app);
2303 static HRESULT WINAPI TestMsg_IClassFactory_CreateInstance(
2304 LPCLASSFACTORY iface,
2305 LPUNKNOWN pUnkOuter,
2306 REFIID riid,
2307 LPVOID *ppvObj)
2309 *ppvObj = NULL;
2310 SendMessageA(hwnd_app, WM_USER+2, 0, 0);
2311 return S_OK;
2314 static IClassFactoryVtbl TestMsgClassFactory_Vtbl =
2316 Test_IClassFactory_QueryInterface,
2317 Test_IClassFactory_AddRef,
2318 Test_IClassFactory_Release,
2319 TestMsg_IClassFactory_CreateInstance,
2320 Test_IClassFactory_LockServer
2323 static IClassFactory TestMsg_ClassFactory = { &TestMsgClassFactory_Vtbl };
2325 static void test_call_from_message(void)
2327 MSG msg;
2328 IStream *pStream;
2329 HRESULT hr;
2330 IClassFactory *proxy;
2331 DWORD tid;
2332 HANDLE thread;
2333 IUnknown *object;
2335 hwnd_app = CreateWindowA("WineCOMTest", NULL, 0, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, NULL, NULL, NULL, 0);
2336 ok(hwnd_app != NULL, "Window creation failed\n");
2338 hr = CreateStreamOnHGlobal(NULL, TRUE, &pStream);
2339 ok_ole_success(hr, CreateStreamOnHGlobal);
2340 tid = start_host_object(pStream, &IID_IClassFactory, (IUnknown*)&TestMsg_ClassFactory, MSHLFLAGS_NORMAL, &thread);
2342 ok_more_than_one_lock();
2344 IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
2345 hr = CoUnmarshalInterface(pStream, &IID_IClassFactory, (void **)&proxy);
2346 ok_ole_success(hr, CoReleaseMarshalData);
2347 IStream_Release(pStream);
2349 ok_more_than_one_lock();
2351 /* start message re-entrancy test */
2352 hr = IClassFactory_CreateInstance(proxy, NULL, &IID_IUnknown, (void **)&object);
2353 ok_ole_success(hr, IClassFactory_CreateInstance);
2355 IClassFactory_Release(proxy);
2357 ok_no_locks();
2359 end_host_object(tid, thread);
2361 while (GetMessageA(&msg, NULL, 0, 0))
2363 TranslateMessage(&msg);
2364 DispatchMessageA(&msg);
2366 DestroyWindow(hwnd_app);
2369 static void test_WM_QUIT_handling(void)
2371 MSG msg;
2373 hwnd_app = CreateWindowA("WineCOMTest", NULL, 0, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, NULL, NULL, NULL, 0);
2374 ok(hwnd_app != NULL, "Window creation failed\n");
2376 /* start WM_QUIT handling test */
2377 PostMessageA(hwnd_app, WM_USER+1, 0, 0);
2379 while (GetMessageA(&msg, NULL, 0, 0))
2381 TranslateMessage(&msg);
2382 DispatchMessageA(&msg);
2386 static SIZE_T round_global_size(SIZE_T size)
2388 static SIZE_T global_size_alignment = -1;
2389 if (global_size_alignment == -1)
2391 void *p = GlobalAlloc(GMEM_FIXED, 1);
2392 global_size_alignment = GlobalSize(p);
2393 GlobalFree(p);
2396 return ((size + global_size_alignment - 1) & ~(global_size_alignment - 1));
2399 static void test_freethreadedmarshaldata(IStream *pStream, MSHCTX mshctx, void *ptr, DWORD mshlflags)
2401 HGLOBAL hglobal;
2402 DWORD size;
2403 char *marshal_data;
2404 HRESULT hr;
2406 hr = GetHGlobalFromStream(pStream, &hglobal);
2407 ok_ole_success(hr, GetHGlobalFromStream);
2409 size = GlobalSize(hglobal);
2411 marshal_data = GlobalLock(hglobal);
2413 if (mshctx == MSHCTX_INPROC)
2415 DWORD expected_size = round_global_size(3*sizeof(DWORD) + sizeof(GUID));
2416 ok(size == expected_size ||
2417 broken(size == (2*sizeof(DWORD))) /* Win9x & NT4 */,
2418 "size should have been %d instead of %d\n", expected_size, size);
2420 ok(*(DWORD *)marshal_data == mshlflags, "expected 0x%x, but got 0x%x for mshctx\n", mshlflags, *(DWORD *)marshal_data);
2421 marshal_data += sizeof(DWORD);
2422 ok(*(void **)marshal_data == ptr, "expected %p, but got %p for mshctx\n", ptr, *(void **)marshal_data);
2423 marshal_data += sizeof(void *);
2424 if (sizeof(void*) == 4 && size >= 3*sizeof(DWORD))
2426 ok(*(DWORD *)marshal_data == 0, "expected 0x0, but got 0x%x\n", *(DWORD *)marshal_data);
2427 marshal_data += sizeof(DWORD);
2429 if (size >= 3*sizeof(DWORD) + sizeof(GUID))
2431 trace("got guid data: %s\n", wine_dbgstr_guid((GUID *)marshal_data));
2434 else
2436 ok(size > sizeof(DWORD), "size should have been > sizeof(DWORD), not %d\n", size);
2437 ok(*(DWORD *)marshal_data == 0x574f454d /* MEOW */,
2438 "marshal data should be filled by standard marshal and start with MEOW signature\n");
2441 GlobalUnlock(hglobal);
2444 static void test_freethreadedmarshaler(void)
2446 HRESULT hr;
2447 IUnknown *pFTUnknown;
2448 IMarshal *pFTMarshal;
2449 IStream *pStream;
2450 IUnknown *pProxy;
2451 static const LARGE_INTEGER llZero;
2453 cLocks = 0;
2454 hr = CoCreateFreeThreadedMarshaler(NULL, &pFTUnknown);
2455 ok_ole_success(hr, CoCreateFreeThreadedMarshaler);
2456 hr = IUnknown_QueryInterface(pFTUnknown, &IID_IMarshal, (void **)&pFTMarshal);
2457 ok_ole_success(hr, IUnknown_QueryInterface);
2458 IUnknown_Release(pFTUnknown);
2460 hr = CreateStreamOnHGlobal(NULL, TRUE, &pStream);
2461 ok_ole_success(hr, CreateStreamOnHGlobal);
2463 /* inproc normal marshaling */
2465 hr = IMarshal_MarshalInterface(pFTMarshal, pStream, &IID_IClassFactory,
2466 &Test_ClassFactory, MSHCTX_INPROC, NULL, MSHLFLAGS_NORMAL);
2467 ok_ole_success(hr, IMarshal_MarshalInterface);
2469 ok_more_than_one_lock();
2471 test_freethreadedmarshaldata(pStream, MSHCTX_INPROC, &Test_ClassFactory, MSHLFLAGS_NORMAL);
2473 IStream_Seek(pStream, llZero, STREAM_SEEK_SET, NULL);
2474 hr = IMarshal_UnmarshalInterface(pFTMarshal, pStream, &IID_IUnknown, (void **)&pProxy);
2475 ok_ole_success(hr, IMarshal_UnmarshalInterface);
2477 IUnknown_Release(pProxy);
2479 ok_no_locks();
2481 /* native doesn't allow us to unmarshal or release the stream data,
2482 * presumably because it wants us to call CoMarshalInterface instead */
2483 if (0)
2485 /* local normal marshaling */
2487 IStream_Seek(pStream, llZero, STREAM_SEEK_SET, NULL);
2488 hr = IMarshal_MarshalInterface(pFTMarshal, pStream, &IID_IClassFactory, &Test_ClassFactory, MSHCTX_LOCAL, NULL, MSHLFLAGS_NORMAL);
2489 ok_ole_success(hr, IMarshal_MarshalInterface);
2491 ok_more_than_one_lock();
2493 test_freethreadedmarshaldata(pStream, MSHCTX_LOCAL, &Test_ClassFactory, MSHLFLAGS_NORMAL);
2495 IStream_Seek(pStream, llZero, STREAM_SEEK_SET, NULL);
2496 hr = IMarshal_ReleaseMarshalData(pFTMarshal, pStream);
2497 ok_ole_success(hr, IMarshal_ReleaseMarshalData);
2499 ok_no_locks();
2502 /* inproc table-strong marshaling */
2504 IStream_Seek(pStream, llZero, STREAM_SEEK_SET, NULL);
2505 hr = IMarshal_MarshalInterface(pFTMarshal, pStream, &IID_IClassFactory,
2506 (IUnknown*)&Test_ClassFactory, MSHCTX_INPROC, (void *)0xdeadbeef,
2507 MSHLFLAGS_TABLESTRONG);
2508 ok_ole_success(hr, IMarshal_MarshalInterface);
2510 ok_more_than_one_lock();
2512 test_freethreadedmarshaldata(pStream, MSHCTX_INPROC, &Test_ClassFactory, MSHLFLAGS_TABLESTRONG);
2514 IStream_Seek(pStream, llZero, STREAM_SEEK_SET, NULL);
2515 hr = IMarshal_UnmarshalInterface(pFTMarshal, pStream, &IID_IUnknown, (void **)&pProxy);
2516 ok_ole_success(hr, IMarshal_UnmarshalInterface);
2518 IUnknown_Release(pProxy);
2520 ok_more_than_one_lock();
2522 IStream_Seek(pStream, llZero, STREAM_SEEK_SET, NULL);
2523 hr = IMarshal_ReleaseMarshalData(pFTMarshal, pStream);
2524 ok_ole_success(hr, IMarshal_ReleaseMarshalData);
2526 ok_no_locks();
2528 /* inproc table-weak marshaling */
2530 IStream_Seek(pStream, llZero, STREAM_SEEK_SET, NULL);
2531 hr = IMarshal_MarshalInterface(pFTMarshal, pStream, &IID_IClassFactory,
2532 (IUnknown*)&Test_ClassFactory, MSHCTX_INPROC, (void *)0xdeadbeef,
2533 MSHLFLAGS_TABLEWEAK);
2534 ok_ole_success(hr, IMarshal_MarshalInterface);
2536 ok_no_locks();
2538 test_freethreadedmarshaldata(pStream, MSHCTX_INPROC, &Test_ClassFactory, MSHLFLAGS_TABLEWEAK);
2540 IStream_Seek(pStream, llZero, STREAM_SEEK_SET, NULL);
2541 hr = IMarshal_UnmarshalInterface(pFTMarshal, pStream, &IID_IUnknown, (void **)&pProxy);
2542 ok_ole_success(hr, IMarshal_UnmarshalInterface);
2544 ok_more_than_one_lock();
2546 IUnknown_Release(pProxy);
2548 ok_no_locks();
2550 /* inproc normal marshaling (for extraordinary cases) */
2552 IStream_Seek(pStream, llZero, STREAM_SEEK_SET, NULL);
2553 hr = IMarshal_MarshalInterface(pFTMarshal, pStream, &IID_IClassFactory,
2554 &Test_ClassFactory, MSHCTX_INPROC, NULL, MSHLFLAGS_NORMAL);
2555 ok_ole_success(hr, IMarshal_MarshalInterface);
2557 ok_more_than_one_lock();
2559 /* this call shows that DisconnectObject does nothing */
2560 hr = IMarshal_DisconnectObject(pFTMarshal, 0);
2561 ok_ole_success(hr, IMarshal_DisconnectObject);
2563 ok_more_than_one_lock();
2565 IStream_Seek(pStream, llZero, STREAM_SEEK_SET, NULL);
2566 hr = IMarshal_ReleaseMarshalData(pFTMarshal, pStream);
2567 ok_ole_success(hr, IMarshal_ReleaseMarshalData);
2569 ok_no_locks();
2571 /* doesn't enforce marshaling rules here and allows us to unmarshal the
2572 * interface, even though it was freed above */
2573 IStream_Seek(pStream, llZero, STREAM_SEEK_SET, NULL);
2574 hr = IMarshal_UnmarshalInterface(pFTMarshal, pStream, &IID_IUnknown, (void **)&pProxy);
2575 ok_ole_success(hr, IMarshal_UnmarshalInterface);
2577 ok_no_locks();
2579 IStream_Release(pStream);
2580 IMarshal_Release(pFTMarshal);
2583 static HRESULT reg_unreg_wine_test_class(BOOL Register)
2585 HRESULT hr;
2586 char buffer[256];
2587 LPOLESTR pszClsid;
2588 HKEY hkey;
2589 DWORD dwDisposition;
2590 DWORD error;
2592 hr = StringFromCLSID(&CLSID_WineTest, &pszClsid);
2593 ok_ole_success(hr, "StringFromCLSID");
2594 strcpy(buffer, "CLSID\\");
2595 WideCharToMultiByte(CP_ACP, 0, pszClsid, -1, buffer + strlen(buffer), sizeof(buffer) - strlen(buffer), NULL, NULL);
2596 CoTaskMemFree(pszClsid);
2597 strcat(buffer, "\\InprocHandler32");
2598 if (Register)
2600 error = RegCreateKeyExA(HKEY_CLASSES_ROOT, buffer, 0, NULL, 0, KEY_SET_VALUE, NULL, &hkey, &dwDisposition);
2601 if (error == ERROR_ACCESS_DENIED)
2603 skip("Not authorized to modify the Classes key\n");
2604 return E_FAIL;
2606 ok(error == ERROR_SUCCESS, "RegCreateKeyEx failed with error %d\n", error);
2607 if (error != ERROR_SUCCESS) hr = E_FAIL;
2608 error = RegSetValueExA(hkey, NULL, 0, REG_SZ, (const unsigned char *)"\"ole32.dll\"", strlen("\"ole32.dll\"") + 1);
2609 ok(error == ERROR_SUCCESS, "RegSetValueEx failed with error %d\n", error);
2610 if (error != ERROR_SUCCESS) hr = E_FAIL;
2611 RegCloseKey(hkey);
2613 else
2615 RegDeleteKeyA(HKEY_CLASSES_ROOT, buffer);
2616 *strrchr(buffer, '\\') = '\0';
2617 RegDeleteKeyA(HKEY_CLASSES_ROOT, buffer);
2619 return hr;
2622 static void test_inproc_handler(void)
2624 HRESULT hr;
2625 IUnknown *pObject;
2626 IUnknown *pObject2;
2628 if (FAILED(reg_unreg_wine_test_class(TRUE)))
2629 return;
2631 hr = CoCreateInstance(&CLSID_WineTest, NULL, CLSCTX_INPROC_HANDLER, &IID_IUnknown, (void **)&pObject);
2632 ok_ole_success(hr, "CoCreateInstance");
2634 if (SUCCEEDED(hr))
2636 hr = IUnknown_QueryInterface(pObject, &IID_IWineTest, (void **)&pObject2);
2637 ok(hr == E_NOINTERFACE, "IUnknown_QueryInterface on handler for invalid interface returned 0x%08x instead of E_NOINTERFACE\n", hr);
2639 /* it's a handler as it supports IOleObject */
2640 hr = IUnknown_QueryInterface(pObject, &IID_IOleObject, (void **)&pObject2);
2641 ok_ole_success(hr, "IUnknown_QueryInterface(&IID_IOleObject)");
2642 IUnknown_Release(pObject2);
2644 IUnknown_Release(pObject);
2647 reg_unreg_wine_test_class(FALSE);
2650 static HRESULT WINAPI Test_SMI_QueryInterface(
2651 IStdMarshalInfo *iface,
2652 REFIID riid,
2653 LPVOID *ppvObj)
2655 if (ppvObj == NULL) return E_POINTER;
2657 if (IsEqualGUID(riid, &IID_IUnknown) ||
2658 IsEqualGUID(riid, &IID_IStdMarshalInfo))
2660 *ppvObj = iface;
2661 IStdMarshalInfo_AddRef(iface);
2662 return S_OK;
2665 return E_NOINTERFACE;
2668 static ULONG WINAPI Test_SMI_AddRef(IStdMarshalInfo *iface)
2670 LockModule();
2671 return 2; /* non-heap-based object */
2674 static ULONG WINAPI Test_SMI_Release(IStdMarshalInfo *iface)
2676 UnlockModule();
2677 return 1; /* non-heap-based object */
2680 static HRESULT WINAPI Test_SMI_GetClassForHandler(
2681 IStdMarshalInfo *iface,
2682 DWORD dwDestContext,
2683 void *pvDestContext,
2684 CLSID *pClsid)
2686 *pClsid = CLSID_WineTest;
2687 return S_OK;
2690 static const IStdMarshalInfoVtbl Test_SMI_Vtbl =
2692 Test_SMI_QueryInterface,
2693 Test_SMI_AddRef,
2694 Test_SMI_Release,
2695 Test_SMI_GetClassForHandler
2698 static IStdMarshalInfo Test_SMI = {&Test_SMI_Vtbl};
2700 static void test_handler_marshaling(void)
2702 HRESULT hr;
2703 IStream *pStream = NULL;
2704 IUnknown *pProxy = NULL;
2705 IUnknown *pObject;
2706 DWORD tid;
2707 HANDLE thread;
2708 static const LARGE_INTEGER ullZero;
2710 if (FAILED(reg_unreg_wine_test_class(TRUE)))
2711 return;
2712 cLocks = 0;
2714 hr = CreateStreamOnHGlobal(NULL, TRUE, &pStream);
2715 ok_ole_success(hr, "CreateStreamOnHGlobal");
2716 tid = start_host_object(pStream, &IID_IUnknown, (IUnknown*)&Test_SMI, MSHLFLAGS_NORMAL, &thread);
2718 ok_more_than_one_lock();
2720 IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
2721 hr = CoUnmarshalInterface(pStream, &IID_IUnknown, (void **)&pProxy);
2722 ok_ole_success(hr, "CoUnmarshalInterface");
2723 IStream_Release(pStream);
2725 if(hr == S_OK)
2727 ok_more_than_one_lock();
2729 hr = IUnknown_QueryInterface(pProxy, &IID_IWineTest, (void **)&pObject);
2730 ok(hr == E_NOINTERFACE, "IUnknown_QueryInterface with unknown IID should have returned E_NOINTERFACE instead of 0x%08x\n", hr);
2732 /* it's a handler as it supports IOleObject */
2733 hr = IUnknown_QueryInterface(pProxy, &IID_IOleObject, (void **)&pObject);
2734 todo_wine
2735 ok_ole_success(hr, "IUnknown_QueryInterface(&IID_IOleObject)");
2736 if (SUCCEEDED(hr)) IUnknown_Release(pObject);
2738 IUnknown_Release(pProxy);
2740 ok_no_locks();
2743 end_host_object(tid, thread);
2744 reg_unreg_wine_test_class(FALSE);
2746 /* FIXME: test IPersist interface has the same effect as IStdMarshalInfo */
2750 static void test_client_security(void)
2752 HRESULT hr;
2753 IStream *pStream = NULL;
2754 IClassFactory *pProxy = NULL;
2755 IUnknown *pProxy2 = NULL;
2756 IUnknown *pUnknown1 = NULL;
2757 IUnknown *pUnknown2 = NULL;
2758 IClientSecurity *pCliSec = NULL;
2759 IMarshal *pMarshal;
2760 DWORD tid;
2761 HANDLE thread;
2762 static const LARGE_INTEGER ullZero;
2763 DWORD dwAuthnSvc;
2764 DWORD dwAuthzSvc;
2765 OLECHAR *pServerPrincName;
2766 DWORD dwAuthnLevel;
2767 DWORD dwImpLevel;
2768 void *pAuthInfo;
2769 DWORD dwCapabilities;
2770 void *pv;
2772 cLocks = 0;
2774 hr = CreateStreamOnHGlobal(NULL, TRUE, &pStream);
2775 ok_ole_success(hr, "CreateStreamOnHGlobal");
2776 tid = start_host_object(pStream, &IID_IClassFactory, (IUnknown*)&Test_ClassFactory, MSHLFLAGS_NORMAL, &thread);
2778 IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
2779 hr = CoUnmarshalInterface(pStream, &IID_IClassFactory, (void **)&pProxy);
2780 ok_ole_success(hr, "CoUnmarshalInterface");
2781 IStream_Release(pStream);
2783 hr = IClassFactory_QueryInterface(pProxy, &IID_IUnknown, (LPVOID*)&pUnknown1);
2784 ok_ole_success(hr, "IUnknown_QueryInterface IID_IUnknown");
2786 hr = IClassFactory_QueryInterface(pProxy, &IID_IRemUnknown, (LPVOID*)&pProxy2);
2787 ok_ole_success(hr, "IUnknown_QueryInterface IID_IStream");
2789 hr = IUnknown_QueryInterface(pProxy2, &IID_IUnknown, (LPVOID*)&pUnknown2);
2790 ok_ole_success(hr, "IUnknown_QueryInterface IID_IUnknown");
2792 ok(pUnknown1 == pUnknown2, "both proxy's IUnknowns should be the same - %p, %p\n", pUnknown1, pUnknown2);
2794 hr = IClassFactory_QueryInterface(pProxy, &IID_IMarshal, (LPVOID*)&pMarshal);
2795 ok_ole_success(hr, "IUnknown_QueryInterface IID_IMarshal");
2797 hr = IClassFactory_QueryInterface(pProxy, &IID_IClientSecurity, (LPVOID*)&pCliSec);
2798 ok_ole_success(hr, "IUnknown_QueryInterface IID_IClientSecurity");
2800 hr = IClientSecurity_QueryBlanket(pCliSec, (IUnknown *)pProxy, NULL, NULL, NULL, NULL, NULL, NULL, NULL);
2801 todo_wine ok_ole_success(hr, "IClientSecurity_QueryBlanket (all NULLs)");
2803 hr = IClientSecurity_QueryBlanket(pCliSec, (IUnknown *)pMarshal, NULL, NULL, NULL, NULL, NULL, NULL, NULL);
2804 todo_wine ok(hr == E_NOINTERFACE, "IClientSecurity_QueryBlanket with local interface should have returned E_NOINTERFACE instead of 0x%08x\n", hr);
2806 hr = IClientSecurity_QueryBlanket(pCliSec, (IUnknown *)pProxy, &dwAuthnSvc, &dwAuthzSvc, &pServerPrincName, &dwAuthnLevel, &dwImpLevel, &pAuthInfo, &dwCapabilities);
2807 todo_wine ok_ole_success(hr, "IClientSecurity_QueryBlanket");
2809 hr = IClientSecurity_SetBlanket(pCliSec, (IUnknown *)pProxy, dwAuthnSvc, dwAuthzSvc, pServerPrincName, dwAuthnLevel, RPC_C_IMP_LEVEL_IMPERSONATE, pAuthInfo, dwCapabilities);
2810 todo_wine ok_ole_success(hr, "IClientSecurity_SetBlanket");
2812 hr = IClassFactory_CreateInstance(pProxy, NULL, &IID_IWineTest, &pv);
2813 ok(hr == E_NOINTERFACE, "COM call should have succeeded instead of returning 0x%08x\n", hr);
2815 hr = IClientSecurity_SetBlanket(pCliSec, (IUnknown *)pMarshal, dwAuthnSvc, dwAuthzSvc, pServerPrincName, dwAuthnLevel, dwImpLevel, pAuthInfo, dwCapabilities);
2816 todo_wine ok(hr == E_NOINTERFACE, "IClientSecurity_SetBlanket with local interface should have returned E_NOINTERFACE instead of 0x%08x\n", hr);
2818 hr = IClientSecurity_SetBlanket(pCliSec, (IUnknown *)pProxy, 0xdeadbeef, dwAuthzSvc, pServerPrincName, dwAuthnLevel, dwImpLevel, pAuthInfo, dwCapabilities);
2819 todo_wine ok(hr == E_INVALIDARG, "IClientSecurity_SetBlanke with invalid dwAuthnSvc should have returned E_INVALIDARG instead of 0x%08x\n", hr);
2821 CoTaskMemFree(pServerPrincName);
2823 hr = IClientSecurity_QueryBlanket(pCliSec, pUnknown1, &dwAuthnSvc, &dwAuthzSvc, &pServerPrincName, &dwAuthnLevel, &dwImpLevel, &pAuthInfo, &dwCapabilities);
2824 todo_wine ok_ole_success(hr, "IClientSecurity_QueryBlanket(IUnknown)");
2826 CoTaskMemFree(pServerPrincName);
2828 IClassFactory_Release(pProxy);
2829 IUnknown_Release(pProxy2);
2830 IUnknown_Release(pUnknown1);
2831 IUnknown_Release(pUnknown2);
2832 IMarshal_Release(pMarshal);
2833 IClientSecurity_Release(pCliSec);
2835 end_host_object(tid, thread);
2838 static HANDLE heventShutdown;
2840 static void LockModuleOOP(void)
2842 InterlockedIncrement(&cLocks); /* for test purposes only */
2843 CoAddRefServerProcess();
2846 static void UnlockModuleOOP(void)
2848 InterlockedDecrement(&cLocks); /* for test purposes only */
2849 if (!CoReleaseServerProcess())
2850 SetEvent(heventShutdown);
2853 static HWND hwnd_app;
2855 static HRESULT WINAPI TestOOP_IClassFactory_QueryInterface(
2856 LPCLASSFACTORY iface,
2857 REFIID riid,
2858 LPVOID *ppvObj)
2860 if (ppvObj == NULL) return E_POINTER;
2862 if (IsEqualGUID(riid, &IID_IUnknown) ||
2863 IsEqualGUID(riid, &IID_IClassFactory))
2865 *ppvObj = iface;
2866 IClassFactory_AddRef(iface);
2867 return S_OK;
2870 return E_NOINTERFACE;
2873 static ULONG WINAPI TestOOP_IClassFactory_AddRef(LPCLASSFACTORY iface)
2875 return 2; /* non-heap-based object */
2878 static ULONG WINAPI TestOOP_IClassFactory_Release(LPCLASSFACTORY iface)
2880 return 1; /* non-heap-based object */
2883 static HRESULT WINAPI TestOOP_IClassFactory_CreateInstance(
2884 LPCLASSFACTORY iface,
2885 LPUNKNOWN pUnkOuter,
2886 REFIID riid,
2887 LPVOID *ppvObj)
2889 if (IsEqualIID(riid, &IID_IClassFactory) || IsEqualIID(riid, &IID_IUnknown))
2891 *ppvObj = iface;
2892 return S_OK;
2894 return CLASS_E_CLASSNOTAVAILABLE;
2897 static HRESULT WINAPI TestOOP_IClassFactory_LockServer(
2898 LPCLASSFACTORY iface,
2899 BOOL fLock)
2901 if (fLock)
2902 LockModuleOOP();
2903 else
2904 UnlockModuleOOP();
2905 return S_OK;
2908 static const IClassFactoryVtbl TestClassFactoryOOP_Vtbl =
2910 TestOOP_IClassFactory_QueryInterface,
2911 TestOOP_IClassFactory_AddRef,
2912 TestOOP_IClassFactory_Release,
2913 TestOOP_IClassFactory_CreateInstance,
2914 TestOOP_IClassFactory_LockServer
2917 static IClassFactory TestOOP_ClassFactory = { &TestClassFactoryOOP_Vtbl };
2919 static void test_register_local_server(void)
2921 DWORD cookie;
2922 HRESULT hr;
2923 HANDLE ready_event;
2924 HANDLE quit_event;
2925 DWORD wait;
2927 heventShutdown = CreateEventA(NULL, TRUE, FALSE, NULL);
2929 hr = CoRegisterClassObject(&CLSID_WineOOPTest, (IUnknown *)&TestOOP_ClassFactory,
2930 CLSCTX_LOCAL_SERVER, REGCLS_SINGLEUSE, &cookie);
2931 ok_ole_success(hr, CoRegisterClassObject);
2933 ready_event = CreateEventA(NULL, FALSE, FALSE, "Wine COM Test Ready Event");
2934 SetEvent(ready_event);
2936 quit_event = CreateEventA(NULL, FALSE, FALSE, "Wine COM Test Quit Event");
2940 wait = MsgWaitForMultipleObjects(1, &quit_event, FALSE, 30000, QS_ALLINPUT);
2941 if (wait == WAIT_OBJECT_0+1)
2943 MSG msg;
2945 if (PeekMessageA(&msg, NULL, 0, 0, PM_REMOVE))
2947 trace("Message 0x%x\n", msg.message);
2948 TranslateMessage(&msg);
2949 DispatchMessageA(&msg);
2953 while (wait == WAIT_OBJECT_0+1);
2955 ok( wait == WAIT_OBJECT_0, "quit event wait timed out\n" );
2956 hr = CoRevokeClassObject(cookie);
2957 ok_ole_success(hr, CoRevokeClassObject);
2960 static HANDLE create_target_process(const char *arg)
2962 char **argv;
2963 char cmdline[MAX_PATH];
2964 BOOL ret;
2965 PROCESS_INFORMATION pi;
2966 STARTUPINFOA si = { 0 };
2967 si.cb = sizeof(si);
2969 pi.hThread = NULL;
2970 pi.hProcess = NULL;
2971 winetest_get_mainargs( &argv );
2972 sprintf(cmdline, "%s %s %s", argv[0], argv[1], arg);
2973 ret = CreateProcessA(argv[0], cmdline, NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi);
2974 ok(ret, "CreateProcess failed with error: %u\n", GetLastError());
2975 if (pi.hThread) CloseHandle(pi.hThread);
2976 return pi.hProcess;
2979 /* tests functions commonly used by out of process COM servers */
2980 static void test_local_server(void)
2982 DWORD cookie;
2983 HRESULT hr;
2984 IClassFactory * cf;
2985 DWORD ret;
2986 HANDLE process;
2987 HANDLE quit_event;
2988 HANDLE ready_event;
2990 heventShutdown = CreateEventA(NULL, TRUE, FALSE, NULL);
2992 cLocks = 0;
2994 /* Start the object suspended */
2995 hr = CoRegisterClassObject(&CLSID_WineOOPTest, (IUnknown *)&TestOOP_ClassFactory,
2996 CLSCTX_LOCAL_SERVER, REGCLS_MULTIPLEUSE | REGCLS_SUSPENDED, &cookie);
2997 ok_ole_success(hr, CoRegisterClassObject);
2999 /* ... and CoGetClassObject does not find it and fails when it looks for the
3000 * class in the registry */
3001 hr = CoGetClassObject(&CLSID_WineOOPTest, CLSCTX_INPROC_SERVER,
3002 NULL, &IID_IClassFactory, (LPVOID*)&cf);
3003 ok(hr == REGDB_E_CLASSNOTREG || /* NT */
3004 hr == S_OK /* Win9x */,
3005 "CoGetClassObject should have returned REGDB_E_CLASSNOTREG instead of 0x%08x\n", hr);
3007 /* Resume the object suspended above ... */
3008 hr = CoResumeClassObjects();
3009 ok_ole_success(hr, CoResumeClassObjects);
3011 /* ... and now it should succeed */
3012 hr = CoGetClassObject(&CLSID_WineOOPTest, CLSCTX_INPROC_SERVER,
3013 NULL, &IID_IClassFactory, (LPVOID*)&cf);
3014 ok_ole_success(hr, CoGetClassObject);
3016 /* Now check the locking is working */
3017 /* NOTE: we are accessing the class directly, not through a proxy */
3019 ok_no_locks();
3021 hr = IClassFactory_LockServer(cf, TRUE);
3022 ok_ole_success(hr, IClassFactory_LockServer);
3024 ok_more_than_one_lock();
3026 IClassFactory_LockServer(cf, FALSE);
3027 ok_ole_success(hr, IClassFactory_LockServer);
3029 ok_no_locks();
3031 IClassFactory_Release(cf);
3033 /* wait for shutdown signal */
3034 ret = WaitForSingleObject(heventShutdown, 0);
3035 ok(ret != WAIT_TIMEOUT, "Server didn't shut down\n");
3037 /* try to connect again after SCM has suspended registered class objects */
3038 hr = CoGetClassObject(&CLSID_WineOOPTest, CLSCTX_INPROC_SERVER | CLSCTX_LOCAL_SERVER, NULL,
3039 &IID_IClassFactory, (LPVOID*)&cf);
3040 ok(hr == CO_E_SERVER_STOPPING || /* NT */
3041 hr == REGDB_E_CLASSNOTREG || /* win2k */
3042 hr == S_OK /* Win9x */,
3043 "CoGetClassObject should have returned CO_E_SERVER_STOPPING or REGDB_E_CLASSNOTREG instead of 0x%08x\n", hr);
3045 hr = CoRevokeClassObject(cookie);
3046 ok_ole_success(hr, CoRevokeClassObject);
3048 CloseHandle(heventShutdown);
3050 process = create_target_process("-Embedding");
3051 ok(process != NULL, "couldn't start local server process, error was %d\n", GetLastError());
3053 ready_event = CreateEventA(NULL, FALSE, FALSE, "Wine COM Test Ready Event");
3054 ok( !WaitForSingleObject(ready_event, 10000), "wait timed out\n" );
3055 CloseHandle(ready_event);
3057 hr = CoCreateInstance(&CLSID_WineOOPTest, NULL, CLSCTX_LOCAL_SERVER, &IID_IClassFactory, (void **)&cf);
3058 ok_ole_success(hr, CoCreateInstance);
3060 IClassFactory_Release(cf);
3062 hr = CoCreateInstance(&CLSID_WineOOPTest, NULL, CLSCTX_LOCAL_SERVER, &IID_IClassFactory, (void **)&cf);
3063 ok(hr == REGDB_E_CLASSNOTREG, "Second CoCreateInstance on REGCLS_SINGLEUSE object should have failed\n");
3065 quit_event = CreateEventA(NULL, FALSE, FALSE, "Wine COM Test Quit Event");
3066 SetEvent(quit_event);
3068 winetest_wait_child_process( process );
3069 CloseHandle(quit_event);
3070 CloseHandle(process);
3073 struct git_params
3075 DWORD cookie;
3076 IGlobalInterfaceTable *git;
3079 static DWORD CALLBACK get_global_interface_proc(LPVOID pv)
3081 HRESULT hr;
3082 struct git_params *params = pv;
3083 IClassFactory *cf;
3085 hr = IGlobalInterfaceTable_GetInterfaceFromGlobal(params->git, params->cookie, &IID_IClassFactory, (void **)&cf);
3086 ok(hr == CO_E_NOTINITIALIZED ||
3087 broken(hr == E_UNEXPECTED) /* win2k */ ||
3088 broken(hr == S_OK) /* NT 4 */,
3089 "IGlobalInterfaceTable_GetInterfaceFromGlobal should have failed with error CO_E_NOTINITIALIZED or E_UNEXPECTED instead of 0x%08x\n",
3090 hr);
3091 if (hr == S_OK)
3092 IClassFactory_Release(cf);
3094 CoInitialize(NULL);
3096 hr = IGlobalInterfaceTable_GetInterfaceFromGlobal(params->git, params->cookie, &IID_IClassFactory, (void **)&cf);
3097 ok_ole_success(hr, IGlobalInterfaceTable_GetInterfaceFromGlobal);
3099 IClassFactory_Release(cf);
3101 CoUninitialize();
3103 return hr;
3106 static void test_globalinterfacetable(void)
3108 HRESULT hr;
3109 IGlobalInterfaceTable *git;
3110 DWORD cookie;
3111 HANDLE thread;
3112 DWORD tid;
3113 struct git_params params;
3114 DWORD ret;
3115 IUnknown *object;
3116 IClassFactory *cf;
3117 ULONG ref;
3119 trace("test_globalinterfacetable\n");
3120 cLocks = 0;
3122 hr = pDllGetClassObject(&CLSID_StdGlobalInterfaceTable, &IID_IClassFactory, (void**)&cf);
3123 ok(hr == S_OK, "got 0x%08x\n", hr);
3125 hr = IClassFactory_QueryInterface(cf, &IID_IGlobalInterfaceTable, (void**)&object);
3126 ok(hr == E_NOINTERFACE, "got 0x%08x\n", hr);
3128 IClassFactory_Release(cf);
3130 hr = CoCreateInstance(&CLSID_StdGlobalInterfaceTable, NULL, CLSCTX_INPROC_SERVER, &IID_IGlobalInterfaceTable, (void **)&git);
3131 ok_ole_success(hr, CoCreateInstance);
3133 ref = IGlobalInterfaceTable_AddRef(git);
3134 ok(ref == 1, "ref=%d\n", ref);
3135 ref = IGlobalInterfaceTable_AddRef(git);
3136 ok(ref == 1, "ref=%d\n", ref);
3138 ref = IGlobalInterfaceTable_Release(git);
3139 ok(ref == 1, "ref=%d\n", ref);
3140 ref = IGlobalInterfaceTable_Release(git);
3141 ok(ref == 1, "ref=%d\n", ref);
3143 hr = IGlobalInterfaceTable_RegisterInterfaceInGlobal(git, (IUnknown *)&Test_ClassFactory, &IID_IClassFactory, &cookie);
3144 ok_ole_success(hr, IGlobalInterfaceTable_RegisterInterfaceInGlobal);
3146 ok_more_than_one_lock();
3148 params.cookie = cookie;
3149 params.git = git;
3150 /* note: params is on stack so we MUST wait for get_global_interface_proc
3151 * to exit before we can return */
3152 thread = CreateThread(NULL, 0, get_global_interface_proc, &params, 0, &tid);
3154 ret = MsgWaitForMultipleObjects(1, &thread, FALSE, 10000, QS_ALLINPUT);
3155 while (ret == WAIT_OBJECT_0 + 1)
3157 MSG msg;
3158 while (PeekMessageA(&msg, NULL, 0, 0, PM_REMOVE))
3159 DispatchMessageA(&msg);
3160 ret = MsgWaitForMultipleObjects(1, &thread, FALSE, 10000, QS_ALLINPUT);
3163 CloseHandle(thread);
3165 /* test getting interface from global with different iid */
3166 hr = IGlobalInterfaceTable_GetInterfaceFromGlobal(git, cookie, &IID_IUnknown, (void **)&object);
3167 ok_ole_success(hr, IGlobalInterfaceTable_GetInterfaceFromGlobal);
3168 IUnknown_Release(object);
3170 /* test getting interface from global with same iid */
3171 hr = IGlobalInterfaceTable_GetInterfaceFromGlobal(git, cookie, &IID_IClassFactory, (void **)&object);
3172 ok_ole_success(hr, IGlobalInterfaceTable_GetInterfaceFromGlobal);
3173 IUnknown_Release(object);
3175 hr = IGlobalInterfaceTable_RevokeInterfaceFromGlobal(git, cookie);
3176 ok_ole_success(hr, IGlobalInterfaceTable_RevokeInterfaceFromGlobal);
3178 ok_no_locks();
3180 IGlobalInterfaceTable_Release(git);
3183 static void test_manualresetevent(void)
3185 ISynchronizeHandle *sync_handle;
3186 ISynchronize *psync1, *psync2;
3187 IUnknown *punk;
3188 HANDLE handle;
3189 LONG ref;
3190 HRESULT hr;
3192 hr = CoCreateInstance(&CLSID_ManualResetEvent, NULL, CLSCTX_INPROC_SERVER, &IID_IUnknown, (void**)&punk);
3193 ok(hr == S_OK, "Got 0x%08x\n", hr);
3194 ok(!!punk, "Got NULL.\n");
3195 IUnknown_Release(punk);
3197 hr = CoCreateInstance(&CLSID_ManualResetEvent, NULL, CLSCTX_INPROC_SERVER, &IID_ISynchronize, (void**)&psync1);
3198 ok(hr == S_OK, "Got 0x%08x\n", hr);
3199 ok(!!psync1, "Got NULL.\n");
3201 hr = ISynchronize_Wait(psync1, 0, 5);
3202 ok(hr == RPC_S_CALLPENDING, "Got 0x%08x\n", hr);
3204 hr = ISynchronize_Reset(psync1);
3205 ok(hr == S_OK, "Got 0x%08x\n", hr);
3206 hr = ISynchronize_Signal(psync1);
3207 ok(hr == S_OK, "Got 0x%08x\n", hr);
3208 hr = ISynchronize_Wait(psync1, 0, 5);
3209 ok(hr == S_OK, "Got 0x%08x\n", hr);
3210 hr = ISynchronize_Wait(psync1, 0, 5);
3211 ok(hr == S_OK, "Got 0x%08x\n", hr);
3212 hr = ISynchronize_Reset(psync1);
3213 ok(hr == S_OK, "Got 0x%08x\n", hr);
3214 hr = ISynchronize_Wait(psync1, 0, 5);
3215 ok(hr == RPC_S_CALLPENDING, "Got 0x%08x\n", hr);
3217 hr = CoCreateInstance(&CLSID_ManualResetEvent, NULL, CLSCTX_INPROC_SERVER, &IID_ISynchronize, (void**)&psync2);
3218 ok(hr == S_OK, "Got 0x%08x\n", hr);
3219 ok(!!psync2, "Got NULL.\n");
3220 ok(psync1 != psync2, "psync1 == psync2.\n");
3222 hr = ISynchronize_QueryInterface(psync2, &IID_ISynchronizeHandle, (void**)&sync_handle);
3223 ok(hr == S_OK, "QueryInterface(IID_ISynchronizeHandle) failed: %08x\n", hr);
3225 handle = NULL;
3226 hr = ISynchronizeHandle_GetHandle(sync_handle, &handle);
3227 ok(hr == S_OK, "GetHandle failed: %08x\n", hr);
3228 ok(handle != NULL && handle != INVALID_HANDLE_VALUE, "handle = %p\n", handle);
3230 ISynchronizeHandle_Release(sync_handle);
3232 hr = ISynchronize_Wait(psync2, 0, 5);
3233 ok(hr == RPC_S_CALLPENDING, "Got 0x%08x\n", hr);
3235 hr = ISynchronize_Reset(psync1);
3236 ok(hr == S_OK, "Got 0x%08x\n", hr);
3237 hr = ISynchronize_Reset(psync2);
3238 ok(hr == S_OK, "Got 0x%08x\n", hr);
3239 hr = ISynchronize_Signal(psync1);
3240 ok(hr == S_OK, "Got 0x%08x\n", hr);
3241 hr = ISynchronize_Wait(psync2, 0, 5);
3242 ok(hr == RPC_S_CALLPENDING, "Got 0x%08x\n", hr);
3244 ref = ISynchronize_AddRef(psync1);
3245 ok(ref == 2, "Got ref: %d\n", ref);
3246 ref = ISynchronize_AddRef(psync1);
3247 ok(ref == 3, "Got ref: %d\n", ref);
3248 ref = ISynchronize_Release(psync1);
3249 ok(ref == 2, "Got nonzero ref: %d\n", ref);
3250 ref = ISynchronize_Release(psync2);
3251 ok(!ref, "Got nonzero ref: %d\n", ref);
3252 ref = ISynchronize_Release(psync1);
3253 ok(ref == 1, "Got nonzero ref: %d\n", ref);
3254 ref = ISynchronize_Release(psync1);
3255 ok(!ref, "Got nonzero ref: %d\n", ref);
3258 static const char *debugstr_iid(REFIID riid)
3260 static char name[256];
3261 HKEY hkeyInterface;
3262 WCHAR bufferW[39];
3263 char buffer[39];
3264 LONG name_size = sizeof(name);
3265 StringFromGUID2(riid, bufferW, sizeof(bufferW)/sizeof(bufferW[0]));
3266 WideCharToMultiByte(CP_ACP, 0, bufferW, sizeof(bufferW)/sizeof(bufferW[0]), buffer, sizeof(buffer), NULL, NULL);
3267 if (RegOpenKeyExA(HKEY_CLASSES_ROOT, "Interface", 0, KEY_QUERY_VALUE, &hkeyInterface) != ERROR_SUCCESS)
3269 memcpy(name, buffer, sizeof(buffer));
3270 goto done;
3272 if (RegQueryValueA(hkeyInterface, buffer, name, &name_size) != ERROR_SUCCESS)
3274 memcpy(name, buffer, sizeof(buffer));
3275 goto done;
3277 RegCloseKey(hkeyInterface);
3278 done:
3279 return name;
3282 static HRESULT WINAPI TestChannelHook_QueryInterface(IChannelHook *iface, REFIID riid, void **ppv)
3284 if (IsEqualIID(riid, &IID_IUnknown) || IsEqualIID(riid, &IID_IChannelHook))
3286 *ppv = iface;
3287 IChannelHook_AddRef(iface);
3288 return S_OK;
3291 *ppv = NULL;
3292 return E_NOINTERFACE;
3295 static ULONG WINAPI TestChannelHook_AddRef(IChannelHook *iface)
3297 return 2;
3300 static ULONG WINAPI TestChannelHook_Release(IChannelHook *iface)
3302 return 1;
3305 static void WINAPI TestChannelHook_ClientGetSize(
3306 IChannelHook *iface,
3307 REFGUID uExtent,
3308 REFIID riid,
3309 ULONG *pDataSize )
3311 SChannelHookCallInfo *info = (SChannelHookCallInfo *)riid;
3312 trace("TestChannelHook_ClientGetBuffer\n");
3313 trace("\t%s method %d\n", debugstr_iid(riid), info->iMethod);
3314 trace("\tcid: %s\n", debugstr_iid(&info->uCausality));
3315 ok(info->cbSize == sizeof(*info), "info->cbSize was %d instead of %d\n", info->cbSize, (int)sizeof(*info));
3316 ok(info->dwServerPid == GetCurrentProcessId(), "info->dwServerPid was 0x%x instead of 0x%x\n", info->dwServerPid, GetCurrentProcessId());
3317 ok(!info->pObject, "info->pObject should be NULL\n");
3318 ok(IsEqualGUID(uExtent, &EXTENTID_WineTest), "uExtent wasn't correct\n");
3320 *pDataSize = 1;
3323 static void WINAPI TestChannelHook_ClientFillBuffer(
3324 IChannelHook *iface,
3325 REFGUID uExtent,
3326 REFIID riid,
3327 ULONG *pDataSize,
3328 void *pDataBuffer )
3330 SChannelHookCallInfo *info = (SChannelHookCallInfo *)riid;
3331 trace("TestChannelHook_ClientFillBuffer\n");
3332 ok(info->cbSize == sizeof(*info), "info->cbSize was %d instead of %d\n", info->cbSize, (int)sizeof(*info));
3333 ok(info->dwServerPid == GetCurrentProcessId(), "info->dwServerPid was 0x%x instead of 0x%x\n", info->dwServerPid, GetCurrentProcessId());
3334 ok(!info->pObject, "info->pObject should be NULL\n");
3335 ok(IsEqualGUID(uExtent, &EXTENTID_WineTest), "uExtent wasn't correct\n");
3337 *(unsigned char *)pDataBuffer = 0xcc;
3338 *pDataSize = 1;
3341 static void WINAPI TestChannelHook_ClientNotify(
3342 IChannelHook *iface,
3343 REFGUID uExtent,
3344 REFIID riid,
3345 ULONG cbDataSize,
3346 void *pDataBuffer,
3347 DWORD lDataRep,
3348 HRESULT hrFault )
3350 SChannelHookCallInfo *info = (SChannelHookCallInfo *)riid;
3351 trace("TestChannelHook_ClientNotify hrFault = 0x%08x\n", hrFault);
3352 ok(info->cbSize == sizeof(*info), "info->cbSize was %d instead of %d\n", info->cbSize, (int)sizeof(*info));
3353 ok(info->dwServerPid == GetCurrentProcessId(), "info->dwServerPid was 0x%x instead of 0x%x\n", info->dwServerPid, GetCurrentProcessId());
3354 todo_wine {
3355 ok(info->pObject != NULL, "info->pObject shouldn't be NULL\n");
3357 ok(IsEqualGUID(uExtent, &EXTENTID_WineTest), "uExtent wasn't correct\n");
3360 static void WINAPI TestChannelHook_ServerNotify(
3361 IChannelHook *iface,
3362 REFGUID uExtent,
3363 REFIID riid,
3364 ULONG cbDataSize,
3365 void *pDataBuffer,
3366 DWORD lDataRep )
3368 SChannelHookCallInfo *info = (SChannelHookCallInfo *)riid;
3369 trace("TestChannelHook_ServerNotify\n");
3370 ok(info->cbSize == sizeof(*info), "info->cbSize was %d instead of %d\n", info->cbSize, (int)sizeof(*info));
3371 ok(info->dwServerPid == GetCurrentProcessId(), "info->dwServerPid was 0x%x instead of 0x%x\n", info->dwServerPid, GetCurrentProcessId());
3372 ok(info->pObject != NULL, "info->pObject shouldn't be NULL\n");
3373 ok(cbDataSize == 1, "cbDataSize should have been 1 instead of %d\n", cbDataSize);
3374 ok(*(unsigned char *)pDataBuffer == 0xcc, "pDataBuffer should have contained 0xcc instead of 0x%x\n", *(unsigned char *)pDataBuffer);
3375 ok(IsEqualGUID(uExtent, &EXTENTID_WineTest), "uExtent wasn't correct\n");
3378 static void WINAPI TestChannelHook_ServerGetSize(
3379 IChannelHook *iface,
3380 REFGUID uExtent,
3381 REFIID riid,
3382 HRESULT hrFault,
3383 ULONG *pDataSize )
3385 SChannelHookCallInfo *info = (SChannelHookCallInfo *)riid;
3386 trace("TestChannelHook_ServerGetSize\n");
3387 trace("\t%s method %d\n", debugstr_iid(riid), info->iMethod);
3388 ok(info->cbSize == sizeof(*info), "info->cbSize was %d instead of %d\n", info->cbSize, (int)sizeof(*info));
3389 ok(info->dwServerPid == GetCurrentProcessId(), "info->dwServerPid was 0x%x instead of 0x%x\n", info->dwServerPid, GetCurrentProcessId());
3390 ok(info->pObject != NULL, "info->pObject shouldn't be NULL\n");
3391 ok(IsEqualGUID(uExtent, &EXTENTID_WineTest), "uExtent wasn't correct\n");
3392 if (hrFault != S_OK)
3393 trace("\thrFault = 0x%08x\n", hrFault);
3395 *pDataSize = 0;
3398 static void WINAPI TestChannelHook_ServerFillBuffer(
3399 IChannelHook *iface,
3400 REFGUID uExtent,
3401 REFIID riid,
3402 ULONG *pDataSize,
3403 void *pDataBuffer,
3404 HRESULT hrFault )
3406 trace("TestChannelHook_ServerFillBuffer\n");
3407 ok(0, "TestChannelHook_ServerFillBuffer shouldn't be called\n");
3410 static const IChannelHookVtbl TestChannelHookVtbl =
3412 TestChannelHook_QueryInterface,
3413 TestChannelHook_AddRef,
3414 TestChannelHook_Release,
3415 TestChannelHook_ClientGetSize,
3416 TestChannelHook_ClientFillBuffer,
3417 TestChannelHook_ClientNotify,
3418 TestChannelHook_ServerNotify,
3419 TestChannelHook_ServerGetSize,
3420 TestChannelHook_ServerFillBuffer,
3423 static IChannelHook TestChannelHook = { &TestChannelHookVtbl };
3425 static void test_channel_hook(void)
3427 IStream *pStream = NULL;
3428 IClassFactory *cf = NULL;
3429 DWORD tid;
3430 IUnknown *proxy = NULL;
3431 HANDLE thread;
3432 HRESULT hr;
3434 hr = CoRegisterChannelHook(&EXTENTID_WineTest, &TestChannelHook);
3435 ok_ole_success(hr, CoRegisterChannelHook);
3437 hr = CoRegisterMessageFilter(&MessageFilter, NULL);
3438 ok_ole_success(hr, CoRegisterMessageFilter);
3440 cLocks = 0;
3442 hr = CreateStreamOnHGlobal(NULL, TRUE, &pStream);
3443 ok_ole_success(hr, CreateStreamOnHGlobal);
3444 tid = start_host_object2(pStream, &IID_IClassFactory, (IUnknown*)&Test_ClassFactory, MSHLFLAGS_NORMAL, &MessageFilter, &thread);
3446 ok_more_than_one_lock();
3448 IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
3449 hr = CoUnmarshalInterface(pStream, &IID_IClassFactory, (void **)&cf);
3450 ok_ole_success(hr, CoUnmarshalInterface);
3451 IStream_Release(pStream);
3453 ok_more_than_one_lock();
3455 hr = IClassFactory_CreateInstance(cf, NULL, &IID_IUnknown, (LPVOID*)&proxy);
3456 ok_ole_success(hr, IClassFactory_CreateInstance);
3457 IUnknown_Release(proxy);
3459 IClassFactory_Release(cf);
3461 ok_no_locks();
3463 end_host_object(tid, thread);
3465 hr = CoRegisterMessageFilter(NULL, NULL);
3466 ok_ole_success(hr, CoRegisterMessageFilter);
3469 START_TEST(marshal)
3471 HMODULE hOle32 = GetModuleHandleA("ole32");
3472 int argc;
3473 char **argv;
3475 if (!GetProcAddress(hOle32, "CoRegisterSurrogateEx")) {
3476 win_skip("skipping test on win9x\n");
3477 return;
3480 pCoInitializeEx = (void*)GetProcAddress(hOle32, "CoInitializeEx");
3481 pDllGetClassObject = (void*)GetProcAddress(hOle32, "DllGetClassObject");
3483 argc = winetest_get_mainargs( &argv );
3484 if (argc > 2 && (!strcmp(argv[2], "-Embedding")))
3486 pCoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
3487 test_register_local_server();
3488 CoUninitialize();
3490 return;
3493 register_test_window();
3495 test_cocreateinstance_proxy();
3497 pCoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
3499 /* FIXME: test CoCreateInstanceEx */
3501 /* lifecycle management and marshaling tests */
3504 test_no_marshaler();
3505 test_normal_marshal_and_release();
3506 test_normal_marshal_and_unmarshal();
3507 test_marshal_and_unmarshal_invalid();
3508 test_same_apartment_unmarshal_failure();
3509 test_interthread_marshal_and_unmarshal();
3510 test_proxy_marshal_and_unmarshal();
3511 test_proxy_marshal_and_unmarshal2();
3512 test_proxy_marshal_and_unmarshal_weak();
3513 test_proxy_marshal_and_unmarshal_strong();
3514 test_marshal_stub_apartment_shutdown();
3515 test_marshal_proxy_apartment_shutdown();
3516 test_marshal_proxy_mta_apartment_shutdown();
3517 test_no_couninitialize_server();
3518 test_no_couninitialize_client();
3519 test_tableweak_marshal_and_unmarshal_twice();
3520 test_tableweak_marshal_releasedata1();
3521 test_tableweak_marshal_releasedata2();
3522 test_tableweak_and_normal_marshal_and_unmarshal();
3523 test_tableweak_and_normal_marshal_and_releasedata();
3524 test_two_tableweak_marshal_and_releasedata();
3525 test_tablestrong_marshal_and_unmarshal_twice();
3526 test_lock_object_external();
3527 test_disconnect_stub();
3528 test_normal_marshal_and_unmarshal_twice();
3530 with_external_conn = !with_external_conn;
3531 } while (with_external_conn);
3533 test_hresult_marshaling();
3534 test_proxy_used_in_wrong_thread();
3535 test_message_filter();
3536 test_bad_marshal_stream();
3537 test_proxy_interfaces();
3538 test_stubbuffer(&IID_IClassFactory);
3539 test_proxybuffer(&IID_IClassFactory);
3540 test_message_reentrancy();
3541 test_call_from_message();
3542 test_WM_QUIT_handling();
3543 test_freethreadedmarshaler();
3544 test_inproc_handler();
3545 test_handler_marshaling();
3546 test_client_security();
3548 test_local_server();
3550 test_globalinterfacetable();
3551 test_manualresetevent();
3553 /* must be last test as channel hooks can't be unregistered */
3554 test_channel_hook();
3556 CoUninitialize();