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
25 DEFINE_GUID(CLSID_StdGlobalInterfaceTable
,0x00000323,0x0000,0x0000,0xc0,0x00,0x00,0x00,0x00,0x00,0x00,0x46);
26 DEFINE_GUID(CLSID_ManualResetEvent
, 0x0000032c,0x0000,0x0000,0xc0,0x00,0x00,0x00,0x00,0x00,0x00,0x46);
28 /* functions that are not present on all versions of Windows */
29 static HRESULT (WINAPI
* pCoInitializeEx
)(LPVOID lpReserved
, DWORD dwCoInit
);
30 static HRESULT (WINAPI
*pDllGetClassObject
)(REFCLSID
,REFIID
,LPVOID
);
32 /* helper macros to make tests a bit leaner */
33 #define ok_more_than_one_lock() ok(cLocks > 0, "Number of locks should be > 0, but actually is %d\n", cLocks)
34 #define ok_no_locks() ok(cLocks == 0, "Number of locks should be 0, but actually is %d\n", cLocks)
35 #define ok_ole_success(hr, func) ok(hr == S_OK, #func " failed with error 0x%08x\n", hr)
36 #define ok_non_zero_external_conn() do {if (with_external_conn) ok(external_connections, "got no external connections\n");} while(0);
37 #define ok_zero_external_conn() do {if (with_external_conn) ok(!external_connections, "got %d external connections\n", external_connections);} while(0);
38 #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);
40 static const IID IID_IWineTest
=
45 {0xa1, 0xa2, 0x5d, 0x5a, 0x36, 0x54, 0xd3, 0xbd}
46 }; /* 5201163f-8164-4fd0-a1a2-5d5a3654d3bd */
48 static const IID IID_IRemUnknown
=
53 {0xc0,0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46}
56 #define EXTENTID_WineTest IID_IWineTest
57 #define CLSID_WineTest IID_IWineTest
59 static const CLSID CLSID_WineOOPTest
=
64 {0xa1, 0xa2, 0x5d, 0x5a, 0x36, 0x54, 0xd3, 0xbd}
65 }; /* 5201163f-8164-4fd0-a1a2-5d5a3654d3bd */
67 static void test_cocreateinstance_proxy(void)
73 pCoInitializeEx(NULL
, COINIT_MULTITHREADED
);
75 hr
= CoCreateInstance(&CLSID_ShellDesktop
, NULL
, CLSCTX_INPROC
, &IID_IUnknown
, (void **)&pProxy
);
76 ok_ole_success(hr
, CoCreateInstance
);
77 hr
= IUnknown_QueryInterface(pProxy
, &IID_IMultiQI
, (void **)&pMQI
);
78 ok(hr
== S_OK
, "created object is not a proxy, so was created in the wrong apartment\n");
80 IMultiQI_Release(pMQI
);
81 IUnknown_Release(pProxy
);
86 static const LARGE_INTEGER ullZero
;
89 static void LockModule(void)
91 InterlockedIncrement(&cLocks
);
94 static void UnlockModule(void)
96 InterlockedDecrement(&cLocks
);
99 static BOOL with_external_conn
;
100 static DWORD external_connections
;
101 static BOOL last_release_closes
;
103 static HRESULT WINAPI
ExternalConnection_QueryInterface(IExternalConnection
*iface
, REFIID riid
, void **ppv
)
105 ok(0, "unexpected call\n");
107 return E_NOINTERFACE
;
110 static ULONG WINAPI
ExternalConnection_AddRef(IExternalConnection
*iface
)
115 static ULONG WINAPI
ExternalConnection_Release(IExternalConnection
*iface
)
120 static DWORD WINAPI
ExternalConnection_AddConnection(IExternalConnection
*iface
, DWORD extconn
, DWORD reserved
)
122 trace("add connection\n");
123 return ++external_connections
;
127 static DWORD WINAPI
ExternalConnection_ReleaseConnection(IExternalConnection
*iface
, DWORD extconn
,
128 DWORD reserved
, BOOL fLastReleaseCloses
)
130 trace("release connection %d\n", fLastReleaseCloses
);
131 last_release_closes
= fLastReleaseCloses
;
132 return --external_connections
;
135 static const IExternalConnectionVtbl ExternalConnectionVtbl
= {
136 ExternalConnection_QueryInterface
,
137 ExternalConnection_AddRef
,
138 ExternalConnection_Release
,
139 ExternalConnection_AddConnection
,
140 ExternalConnection_ReleaseConnection
143 static IExternalConnection ExternalConnection
= { &ExternalConnectionVtbl
};
146 static HRESULT WINAPI
Test_IUnknown_QueryInterface(
151 if (ppvObj
== NULL
) return E_POINTER
;
153 if (IsEqualGUID(riid
, &IID_IUnknown
))
156 IUnknown_AddRef(iface
);
161 return E_NOINTERFACE
;
164 static ULONG WINAPI
Test_IUnknown_AddRef(LPUNKNOWN iface
)
167 return 2; /* non-heap-based object */
170 static ULONG WINAPI
Test_IUnknown_Release(LPUNKNOWN iface
)
173 return 1; /* non-heap-based object */
176 static const IUnknownVtbl TestUnknown_Vtbl
=
178 Test_IUnknown_QueryInterface
,
179 Test_IUnknown_AddRef
,
180 Test_IUnknown_Release
,
183 static IUnknown Test_Unknown
= { &TestUnknown_Vtbl
};
185 static ULONG WINAPI
TestCrash_IUnknown_Release(LPUNKNOWN iface
)
189 trace("crashing...\n");
192 return 1; /* non-heap-based object */
195 static const IUnknownVtbl TestCrashUnknown_Vtbl
=
197 Test_IUnknown_QueryInterface
,
198 Test_IUnknown_AddRef
,
199 TestCrash_IUnknown_Release
,
202 static IUnknown TestCrash_Unknown
= { &TestCrashUnknown_Vtbl
};
204 static HRESULT WINAPI
Test_IClassFactory_QueryInterface(
205 LPCLASSFACTORY iface
,
209 if (ppvObj
== NULL
) return E_POINTER
;
211 if (IsEqualGUID(riid
, &IID_IUnknown
) ||
212 IsEqualGUID(riid
, &IID_IClassFactory
) ||
213 /* the only other interface Wine is currently able to marshal (for testing two proxies) */
214 IsEqualGUID(riid
, &IID_IRemUnknown
))
217 IClassFactory_AddRef(iface
);
221 if (with_external_conn
&& IsEqualGUID(riid
, &IID_IExternalConnection
))
223 *ppvObj
= &ExternalConnection
;
228 return E_NOINTERFACE
;
231 static ULONG WINAPI
Test_IClassFactory_AddRef(LPCLASSFACTORY iface
)
234 return 2; /* non-heap-based object */
237 static ULONG WINAPI
Test_IClassFactory_Release(LPCLASSFACTORY iface
)
240 return 1; /* non-heap-based object */
243 static HRESULT WINAPI
Test_IClassFactory_CreateInstance(
244 LPCLASSFACTORY iface
,
249 if (pUnkOuter
) return CLASS_E_NOAGGREGATION
;
250 return IUnknown_QueryInterface((IUnknown
*)&Test_Unknown
, riid
, ppvObj
);
253 static HRESULT WINAPI
Test_IClassFactory_LockServer(
254 LPCLASSFACTORY iface
,
260 static const IClassFactoryVtbl TestClassFactory_Vtbl
=
262 Test_IClassFactory_QueryInterface
,
263 Test_IClassFactory_AddRef
,
264 Test_IClassFactory_Release
,
265 Test_IClassFactory_CreateInstance
,
266 Test_IClassFactory_LockServer
269 static IClassFactory Test_ClassFactory
= { &TestClassFactory_Vtbl
};
271 #define RELEASEMARSHALDATA WM_USER
273 struct host_object_data
278 MSHLFLAGS marshal_flags
;
279 HANDLE marshal_event
;
280 IMessageFilter
*filter
;
283 static DWORD CALLBACK
host_object_proc(LPVOID p
)
285 struct host_object_data
*data
= p
;
289 pCoInitializeEx(NULL
, COINIT_APARTMENTTHREADED
);
293 IMessageFilter
* prev_filter
= NULL
;
294 hr
= CoRegisterMessageFilter(data
->filter
, &prev_filter
);
295 if (prev_filter
) IMessageFilter_Release(prev_filter
);
296 ok_ole_success(hr
, CoRegisterMessageFilter
);
299 hr
= CoMarshalInterface(data
->stream
, &data
->iid
, data
->object
, MSHCTX_INPROC
, NULL
, data
->marshal_flags
);
300 ok_ole_success(hr
, CoMarshalInterface
);
302 /* force the message queue to be created before signaling parent thread */
303 PeekMessageA(&msg
, NULL
, WM_USER
, WM_USER
, PM_NOREMOVE
);
305 SetEvent(data
->marshal_event
);
307 while (GetMessageA(&msg
, NULL
, 0, 0))
309 if (msg
.hwnd
== NULL
&& msg
.message
== RELEASEMARSHALDATA
)
311 CoReleaseMarshalData(data
->stream
);
312 SetEvent((HANDLE
)msg
.lParam
);
315 DispatchMessageA(&msg
);
318 HeapFree(GetProcessHeap(), 0, data
);
325 static DWORD
start_host_object2(IStream
*stream
, REFIID riid
, IUnknown
*object
, MSHLFLAGS marshal_flags
, IMessageFilter
*filter
, HANDLE
*thread
)
328 HANDLE marshal_event
= CreateEventA(NULL
, FALSE
, FALSE
, NULL
);
329 struct host_object_data
*data
= HeapAlloc(GetProcessHeap(), 0, sizeof(*data
));
331 data
->stream
= stream
;
333 data
->object
= object
;
334 data
->marshal_flags
= marshal_flags
;
335 data
->marshal_event
= marshal_event
;
336 data
->filter
= filter
;
338 *thread
= CreateThread(NULL
, 0, host_object_proc
, data
, 0, &tid
);
340 /* wait for marshaling to complete before returning */
341 ok( !WaitForSingleObject(marshal_event
, 10000), "wait timed out\n" );
342 CloseHandle(marshal_event
);
347 static DWORD
start_host_object(IStream
*stream
, REFIID riid
, IUnknown
*object
, MSHLFLAGS marshal_flags
, HANDLE
*thread
)
349 return start_host_object2(stream
, riid
, object
, marshal_flags
, NULL
, thread
);
352 /* asks thread to release the marshal data because it has to be done by the
353 * same thread that marshaled the interface in the first place. */
354 static void release_host_object(DWORD tid
, WPARAM wp
)
356 HANDLE event
= CreateEventA(NULL
, FALSE
, FALSE
, NULL
);
357 PostThreadMessageA(tid
, RELEASEMARSHALDATA
, wp
, (LPARAM
)event
);
358 ok( !WaitForSingleObject(event
, 10000), "wait timed out\n" );
362 static void end_host_object(DWORD tid
, HANDLE thread
)
364 BOOL ret
= PostThreadMessageA(tid
, WM_QUIT
, 0, 0);
365 ok(ret
, "PostThreadMessage failed with error %d\n", GetLastError());
366 /* be careful of races - don't return until hosting thread has terminated */
367 ok( !WaitForSingleObject(thread
, 10000), "wait timed out\n" );
371 /* tests failure case of interface not having a marshaler specified in the
373 static void test_no_marshaler(void)
378 hr
= CreateStreamOnHGlobal(NULL
, TRUE
, &pStream
);
379 ok_ole_success(hr
, CreateStreamOnHGlobal
);
380 hr
= CoMarshalInterface(pStream
, &IID_IWineTest
, (IUnknown
*)&Test_ClassFactory
, MSHCTX_INPROC
, NULL
, MSHLFLAGS_NORMAL
);
381 ok(hr
== E_NOINTERFACE
, "CoMarshalInterface should have returned E_NOINTERFACE instead of 0x%08x\n", hr
);
383 IStream_Release(pStream
);
386 /* tests normal marshal and then release without unmarshaling */
387 static void test_normal_marshal_and_release(void)
390 IStream
*pStream
= NULL
;
393 external_connections
= 0;
395 hr
= CreateStreamOnHGlobal(NULL
, TRUE
, &pStream
);
396 ok_ole_success(hr
, CreateStreamOnHGlobal
);
397 hr
= CoMarshalInterface(pStream
, &IID_IClassFactory
, (IUnknown
*)&Test_ClassFactory
, MSHCTX_INPROC
, NULL
, MSHLFLAGS_NORMAL
);
398 ok_ole_success(hr
, CoMarshalInterface
);
400 ok_more_than_one_lock();
401 ok_non_zero_external_conn();
403 IStream_Seek(pStream
, ullZero
, STREAM_SEEK_SET
, NULL
);
404 hr
= CoReleaseMarshalData(pStream
);
405 ok_ole_success(hr
, CoReleaseMarshalData
);
406 IStream_Release(pStream
);
409 ok_zero_external_conn();
410 ok_last_release_closes(TRUE
);
413 /* tests success case of a same-thread marshal and unmarshal */
414 static void test_normal_marshal_and_unmarshal(void)
417 IStream
*pStream
= NULL
;
418 IUnknown
*pProxy
= NULL
;
421 external_connections
= 0;
423 hr
= CreateStreamOnHGlobal(NULL
, TRUE
, &pStream
);
424 ok_ole_success(hr
, CreateStreamOnHGlobal
);
425 hr
= CoMarshalInterface(pStream
, &IID_IClassFactory
, (IUnknown
*)&Test_ClassFactory
, MSHCTX_INPROC
, NULL
, MSHLFLAGS_NORMAL
);
426 ok_ole_success(hr
, CoMarshalInterface
);
428 ok_more_than_one_lock();
429 ok_non_zero_external_conn();
431 IStream_Seek(pStream
, ullZero
, STREAM_SEEK_SET
, NULL
);
432 hr
= CoUnmarshalInterface(pStream
, &IID_IClassFactory
, (void **)&pProxy
);
433 ok_ole_success(hr
, CoUnmarshalInterface
);
434 IStream_Release(pStream
);
436 ok_more_than_one_lock();
437 ok_zero_external_conn();
438 ok_last_release_closes(FALSE
);
440 IUnknown_Release(pProxy
);
445 /* tests failure case of unmarshaling a freed object */
446 static void test_marshal_and_unmarshal_invalid(void)
449 IStream
*pStream
= NULL
;
450 IClassFactory
*pProxy
= NULL
;
456 external_connections
= 0;
458 hr
= CreateStreamOnHGlobal(NULL
, TRUE
, &pStream
);
459 ok_ole_success(hr
, CreateStreamOnHGlobal
);
460 tid
= start_host_object(pStream
, &IID_IClassFactory
, (IUnknown
*)&Test_ClassFactory
, MSHLFLAGS_NORMAL
, &thread
);
462 ok_more_than_one_lock();
463 ok_non_zero_external_conn();
465 IStream_Seek(pStream
, ullZero
, STREAM_SEEK_SET
, NULL
);
466 hr
= CoReleaseMarshalData(pStream
);
467 ok_ole_success(hr
, CoReleaseMarshalData
);
470 ok_zero_external_conn();
471 ok_last_release_closes(TRUE
);
473 IStream_Seek(pStream
, ullZero
, STREAM_SEEK_SET
, NULL
);
474 hr
= CoUnmarshalInterface(pStream
, &IID_IClassFactory
, (void **)&pProxy
);
475 todo_wine
{ ok_ole_success(hr
, CoUnmarshalInterface
); }
481 hr
= IClassFactory_CreateInstance(pProxy
, NULL
, &IID_IUnknown
, &dummy
);
482 ok(hr
== RPC_E_DISCONNECTED
, "Remote call should have returned RPC_E_DISCONNECTED, instead of 0x%08x\n", hr
);
484 IClassFactory_Release(pProxy
);
487 IStream_Release(pStream
);
489 end_host_object(tid
, thread
);
492 static void test_same_apartment_unmarshal_failure(void)
497 static const LARGE_INTEGER llZero
;
500 external_connections
= 0;
502 hr
= CreateStreamOnHGlobal(NULL
, TRUE
, &pStream
);
503 ok_ole_success(hr
, CreateStreamOnHGlobal
);
505 hr
= CoMarshalInterface(pStream
, &IID_IUnknown
, (IUnknown
*)&Test_ClassFactory
, MSHCTX_INPROC
, NULL
, MSHLFLAGS_NORMAL
);
506 ok_ole_success(hr
, CoMarshalInterface
);
508 ok_more_than_one_lock();
509 ok_non_zero_external_conn();
511 hr
= IStream_Seek(pStream
, llZero
, STREAM_SEEK_SET
, NULL
);
512 ok_ole_success(hr
, IStream_Seek
);
514 hr
= CoUnmarshalInterface(pStream
, &IID_IParseDisplayName
, (void **)&pProxy
);
515 ok(hr
== E_NOINTERFACE
, "CoUnmarshalInterface should have returned E_NOINTERFACE instead of 0x%08x\n", hr
);
518 ok_zero_external_conn();
519 ok_last_release_closes(FALSE
);
521 IStream_Release(pStream
);
524 /* tests success case of an interthread marshal */
525 static void test_interthread_marshal_and_unmarshal(void)
528 IStream
*pStream
= NULL
;
529 IUnknown
*pProxy
= NULL
;
534 external_connections
= 0;
536 hr
= CreateStreamOnHGlobal(NULL
, TRUE
, &pStream
);
537 ok_ole_success(hr
, CreateStreamOnHGlobal
);
538 tid
= start_host_object(pStream
, &IID_IClassFactory
, (IUnknown
*)&Test_ClassFactory
, MSHLFLAGS_NORMAL
, &thread
);
540 ok_more_than_one_lock();
541 ok_non_zero_external_conn();
543 IStream_Seek(pStream
, ullZero
, STREAM_SEEK_SET
, NULL
);
544 hr
= CoUnmarshalInterface(pStream
, &IID_IClassFactory
, (void **)&pProxy
);
545 ok_ole_success(hr
, CoUnmarshalInterface
);
546 IStream_Release(pStream
);
548 ok_more_than_one_lock();
549 ok_non_zero_external_conn();
551 IUnknown_Release(pProxy
);
554 ok_zero_external_conn();
555 ok_last_release_closes(TRUE
);
557 end_host_object(tid
, thread
);
560 /* the number of external references that Wine's proxy manager normally gives
561 * out, so we can test the border case of running out of references */
562 #define NORMALEXTREFS 5
564 /* tests success case of an interthread marshal and then marshaling the proxy */
565 static void test_proxy_marshal_and_unmarshal(void)
568 IStream
*pStream
= NULL
;
569 IUnknown
*pProxy
= NULL
;
570 IUnknown
*pProxy2
= NULL
;
576 external_connections
= 0;
578 hr
= CreateStreamOnHGlobal(NULL
, TRUE
, &pStream
);
579 ok_ole_success(hr
, CreateStreamOnHGlobal
);
580 tid
= start_host_object(pStream
, &IID_IClassFactory
, (IUnknown
*)&Test_ClassFactory
, MSHLFLAGS_NORMAL
, &thread
);
582 ok_more_than_one_lock();
583 ok_non_zero_external_conn();
585 IStream_Seek(pStream
, ullZero
, STREAM_SEEK_SET
, NULL
);
586 hr
= CoUnmarshalInterface(pStream
, &IID_IClassFactory
, (void **)&pProxy
);
587 ok_ole_success(hr
, CoUnmarshalInterface
);
589 ok_more_than_one_lock();
591 IStream_Seek(pStream
, ullZero
, STREAM_SEEK_SET
, NULL
);
592 /* marshal the proxy */
593 hr
= CoMarshalInterface(pStream
, &IID_IClassFactory
, pProxy
, MSHCTX_INPROC
, NULL
, MSHLFLAGS_NORMAL
);
594 ok_ole_success(hr
, CoMarshalInterface
);
596 ok_more_than_one_lock();
598 /* marshal 5 more times to exhaust the normal external references of 5 */
599 for (i
= 0; i
< NORMALEXTREFS
; i
++)
601 hr
= CoMarshalInterface(pStream
, &IID_IClassFactory
, pProxy
, MSHCTX_INPROC
, NULL
, MSHLFLAGS_NORMAL
);
602 ok_ole_success(hr
, CoMarshalInterface
);
605 ok_more_than_one_lock();
607 /* release the original proxy to test that we successfully keep the
608 * original object alive */
609 IUnknown_Release(pProxy
);
611 IStream_Seek(pStream
, ullZero
, STREAM_SEEK_SET
, NULL
);
612 hr
= CoUnmarshalInterface(pStream
, &IID_IClassFactory
, (void **)&pProxy2
);
613 ok_ole_success(hr
, CoUnmarshalInterface
);
615 ok_more_than_one_lock();
616 ok_non_zero_external_conn();
618 IUnknown_Release(pProxy2
);
620 /* unmarshal all of the proxies to check that the object stub still exists */
621 for (i
= 0; i
< NORMALEXTREFS
; i
++)
623 hr
= CoUnmarshalInterface(pStream
, &IID_IClassFactory
, (void **)&pProxy2
);
624 ok_ole_success(hr
, CoUnmarshalInterface
);
626 IUnknown_Release(pProxy2
);
630 ok_zero_external_conn();
631 ok_last_release_closes(TRUE
);
633 IStream_Release(pStream
);
635 end_host_object(tid
, thread
);
638 /* tests success case of an interthread marshal and then marshaling the proxy
639 * using an iid that hasn't previously been unmarshaled */
640 static void test_proxy_marshal_and_unmarshal2(void)
643 IStream
*pStream
= NULL
;
644 IUnknown
*pProxy
= NULL
;
645 IUnknown
*pProxy2
= NULL
;
650 external_connections
= 0;
652 hr
= CreateStreamOnHGlobal(NULL
, TRUE
, &pStream
);
653 ok_ole_success(hr
, CreateStreamOnHGlobal
);
654 tid
= start_host_object(pStream
, &IID_IUnknown
, (IUnknown
*)&Test_ClassFactory
, MSHLFLAGS_NORMAL
, &thread
);
656 ok_more_than_one_lock();
657 ok_non_zero_external_conn();
659 IStream_Seek(pStream
, ullZero
, STREAM_SEEK_SET
, NULL
);
660 hr
= CoUnmarshalInterface(pStream
, &IID_IUnknown
, (void **)&pProxy
);
661 ok_ole_success(hr
, CoUnmarshalInterface
);
663 ok_more_than_one_lock();
665 IStream_Seek(pStream
, ullZero
, STREAM_SEEK_SET
, NULL
);
666 /* marshal the proxy */
667 hr
= CoMarshalInterface(pStream
, &IID_IClassFactory
, pProxy
, MSHCTX_INPROC
, NULL
, MSHLFLAGS_NORMAL
);
668 ok_ole_success(hr
, CoMarshalInterface
);
670 ok_more_than_one_lock();
672 IStream_Seek(pStream
, ullZero
, STREAM_SEEK_SET
, NULL
);
673 /* unmarshal the second proxy to the object */
674 hr
= CoUnmarshalInterface(pStream
, &IID_IClassFactory
, (void **)&pProxy2
);
675 ok_ole_success(hr
, CoUnmarshalInterface
);
676 IStream_Release(pStream
);
678 /* now the proxies should be as follows:
679 * pProxy -> &Test_ClassFactory
680 * pProxy2 -> &Test_ClassFactory
681 * they should NOT be as follows:
682 * pProxy -> &Test_ClassFactory
684 * the above can only really be tested by looking in +ole traces
687 ok_more_than_one_lock();
689 IUnknown_Release(pProxy
);
691 ok_more_than_one_lock();
692 ok_non_zero_external_conn();
694 IUnknown_Release(pProxy2
);
697 ok_zero_external_conn();
698 ok_last_release_closes(TRUE
);
700 end_host_object(tid
, thread
);
703 /* tests success case of an interthread marshal and then table-weak-marshaling the proxy */
704 static void test_proxy_marshal_and_unmarshal_weak(void)
707 IStream
*pStream
= NULL
;
708 IUnknown
*pProxy
= NULL
;
709 IUnknown
*pProxy2
= NULL
;
714 external_connections
= 0;
716 hr
= CreateStreamOnHGlobal(NULL
, TRUE
, &pStream
);
717 ok_ole_success(hr
, CreateStreamOnHGlobal
);
718 tid
= start_host_object(pStream
, &IID_IClassFactory
, (IUnknown
*)&Test_ClassFactory
, MSHLFLAGS_NORMAL
, &thread
);
720 ok_more_than_one_lock();
721 ok_non_zero_external_conn();
723 IStream_Seek(pStream
, ullZero
, STREAM_SEEK_SET
, NULL
);
724 hr
= CoUnmarshalInterface(pStream
, &IID_IClassFactory
, (void **)&pProxy
);
725 ok_ole_success(hr
, CoUnmarshalInterface
);
727 ok_more_than_one_lock();
728 ok_non_zero_external_conn();
730 IStream_Seek(pStream
, ullZero
, STREAM_SEEK_SET
, NULL
);
731 /* marshal the proxy */
732 hr
= CoMarshalInterface(pStream
, &IID_IClassFactory
, pProxy
, MSHCTX_INPROC
, NULL
, MSHLFLAGS_TABLEWEAK
);
733 ok_ole_success(hr
, CoMarshalInterface
);
735 ok_more_than_one_lock();
736 ok_non_zero_external_conn();
738 /* release the original proxy to test that we successfully keep the
739 * original object alive */
740 IUnknown_Release(pProxy
);
742 IStream_Seek(pStream
, ullZero
, STREAM_SEEK_SET
, NULL
);
743 hr
= CoUnmarshalInterface(pStream
, &IID_IClassFactory
, (void **)&pProxy2
);
745 ok(hr
== CO_E_OBJNOTREG
, "CoUnmarshalInterface should return CO_E_OBJNOTREG instead of 0x%08x\n", hr
);
748 ok_zero_external_conn();
749 ok_last_release_closes(TRUE
);
751 IStream_Release(pStream
);
753 end_host_object(tid
, thread
);
756 /* tests success case of an interthread marshal and then table-strong-marshaling the proxy */
757 static void test_proxy_marshal_and_unmarshal_strong(void)
760 IStream
*pStream
= NULL
;
761 IUnknown
*pProxy
= NULL
;
762 IUnknown
*pProxy2
= NULL
;
767 external_connections
= 0;
769 hr
= CreateStreamOnHGlobal(NULL
, TRUE
, &pStream
);
770 ok_ole_success(hr
, CreateStreamOnHGlobal
);
771 tid
= start_host_object(pStream
, &IID_IClassFactory
, (IUnknown
*)&Test_ClassFactory
, MSHLFLAGS_NORMAL
, &thread
);
773 ok_more_than_one_lock();
774 ok_non_zero_external_conn();
776 IStream_Seek(pStream
, ullZero
, STREAM_SEEK_SET
, NULL
);
777 hr
= CoUnmarshalInterface(pStream
, &IID_IClassFactory
, (void **)&pProxy
);
778 ok_ole_success(hr
, CoUnmarshalInterface
);
780 ok_more_than_one_lock();
781 ok_non_zero_external_conn();
783 IStream_Seek(pStream
, ullZero
, STREAM_SEEK_SET
, NULL
);
784 /* marshal the proxy */
785 hr
= CoMarshalInterface(pStream
, &IID_IClassFactory
, pProxy
, MSHCTX_INPROC
, NULL
, MSHLFLAGS_TABLESTRONG
);
786 ok(hr
== S_OK
/* WinNT */ || hr
== E_INVALIDARG
/* Win9x */,
787 "CoMarshalInterface should have return S_OK or E_INVALIDARG instead of 0x%08x\n", hr
);
790 IUnknown_Release(pProxy
);
794 ok_more_than_one_lock();
795 ok_non_zero_external_conn();
797 /* release the original proxy to test that we successfully keep the
798 * original object alive */
799 IUnknown_Release(pProxy
);
801 IStream_Seek(pStream
, ullZero
, STREAM_SEEK_SET
, NULL
);
802 hr
= CoUnmarshalInterface(pStream
, &IID_IClassFactory
, (void **)&pProxy2
);
803 ok_ole_success(hr
, CoUnmarshalInterface
);
805 ok_more_than_one_lock();
806 ok_non_zero_external_conn();
808 IUnknown_Release(pProxy2
);
810 ok_more_than_one_lock();
811 ok_non_zero_external_conn();
814 IStream_Release(pStream
);
816 end_host_object(tid
, thread
);
820 ok_zero_external_conn();
821 ok_last_release_closes(FALSE
);
825 /* tests that stubs are released when the containing apartment is destroyed */
826 static void test_marshal_stub_apartment_shutdown(void)
829 IStream
*pStream
= NULL
;
830 IUnknown
*pProxy
= NULL
;
835 external_connections
= 0;
837 hr
= CreateStreamOnHGlobal(NULL
, TRUE
, &pStream
);
838 ok_ole_success(hr
, CreateStreamOnHGlobal
);
839 tid
= start_host_object(pStream
, &IID_IClassFactory
, (IUnknown
*)&Test_ClassFactory
, MSHLFLAGS_NORMAL
, &thread
);
841 ok_more_than_one_lock();
842 ok_non_zero_external_conn();
844 IStream_Seek(pStream
, ullZero
, STREAM_SEEK_SET
, NULL
);
845 hr
= CoUnmarshalInterface(pStream
, &IID_IClassFactory
, (void **)&pProxy
);
846 ok_ole_success(hr
, CoUnmarshalInterface
);
847 IStream_Release(pStream
);
849 ok_more_than_one_lock();
850 ok_non_zero_external_conn();
852 end_host_object(tid
, thread
);
856 ok_zero_external_conn();
857 ok_last_release_closes(FALSE
);
860 IUnknown_Release(pProxy
);
865 /* tests that proxies are released when the containing apartment is destroyed */
866 static void test_marshal_proxy_apartment_shutdown(void)
869 IStream
*pStream
= NULL
;
870 IUnknown
*pProxy
= NULL
;
875 external_connections
= 0;
877 hr
= CreateStreamOnHGlobal(NULL
, TRUE
, &pStream
);
878 ok_ole_success(hr
, CreateStreamOnHGlobal
);
879 tid
= start_host_object(pStream
, &IID_IClassFactory
, (IUnknown
*)&Test_ClassFactory
, MSHLFLAGS_NORMAL
, &thread
);
881 ok_more_than_one_lock();
882 ok_non_zero_external_conn();
884 IStream_Seek(pStream
, ullZero
, STREAM_SEEK_SET
, NULL
);
885 hr
= CoUnmarshalInterface(pStream
, &IID_IClassFactory
, (void **)&pProxy
);
886 ok_ole_success(hr
, CoUnmarshalInterface
);
887 IStream_Release(pStream
);
889 ok_more_than_one_lock();
890 ok_non_zero_external_conn();
895 ok_zero_external_conn();
896 ok_last_release_closes(TRUE
);
898 IUnknown_Release(pProxy
);
902 end_host_object(tid
, thread
);
904 pCoInitializeEx(NULL
, COINIT_APARTMENTTHREADED
);
907 /* tests that proxies are released when the containing mta apartment is destroyed */
908 static void test_marshal_proxy_mta_apartment_shutdown(void)
911 IStream
*pStream
= NULL
;
912 IUnknown
*pProxy
= NULL
;
917 pCoInitializeEx(NULL
, COINIT_MULTITHREADED
);
920 external_connections
= 0;
922 hr
= CreateStreamOnHGlobal(NULL
, TRUE
, &pStream
);
923 ok_ole_success(hr
, CreateStreamOnHGlobal
);
924 tid
= start_host_object(pStream
, &IID_IClassFactory
, (IUnknown
*)&Test_ClassFactory
, MSHLFLAGS_NORMAL
, &thread
);
926 ok_more_than_one_lock();
927 ok_non_zero_external_conn();
929 IStream_Seek(pStream
, ullZero
, STREAM_SEEK_SET
, NULL
);
930 hr
= CoUnmarshalInterface(pStream
, &IID_IClassFactory
, (void **)&pProxy
);
931 ok_ole_success(hr
, CoUnmarshalInterface
);
932 IStream_Release(pStream
);
934 ok_more_than_one_lock();
935 ok_non_zero_external_conn();
940 ok_zero_external_conn();
941 ok_last_release_closes(TRUE
);
943 IUnknown_Release(pProxy
);
947 end_host_object(tid
, thread
);
949 pCoInitializeEx(NULL
, COINIT_APARTMENTTHREADED
);
955 HANDLE marshal_event
;
956 HANDLE unmarshal_event
;
959 /* helper for test_no_couninitialize_server */
960 static DWORD CALLBACK
no_couninitialize_server_proc(LPVOID p
)
962 struct ncu_params
*ncu_params
= p
;
965 pCoInitializeEx(NULL
, COINIT_MULTITHREADED
);
967 hr
= CoMarshalInterface(ncu_params
->stream
, &IID_IClassFactory
, (IUnknown
*)&Test_ClassFactory
, MSHCTX_INPROC
, NULL
, MSHLFLAGS_NORMAL
);
968 ok_ole_success(hr
, CoMarshalInterface
);
970 SetEvent(ncu_params
->marshal_event
);
972 ok( !WaitForSingleObject(ncu_params
->unmarshal_event
, 10000), "wait timed out\n" );
974 /* die without calling CoUninitialize */
979 /* tests apartment that an apartment with a stub is released without deadlock
980 * if the owning thread exits */
981 static void test_no_couninitialize_server(void)
984 IStream
*pStream
= NULL
;
985 IUnknown
*pProxy
= NULL
;
988 struct ncu_params ncu_params
;
991 external_connections
= 0;
993 ncu_params
.marshal_event
= CreateEventA(NULL
, TRUE
, FALSE
, NULL
);
994 ncu_params
.unmarshal_event
= CreateEventA(NULL
, TRUE
, FALSE
, NULL
);
996 hr
= CreateStreamOnHGlobal(NULL
, TRUE
, &pStream
);
997 ok_ole_success(hr
, CreateStreamOnHGlobal
);
998 ncu_params
.stream
= pStream
;
1000 thread
= CreateThread(NULL
, 0, no_couninitialize_server_proc
, &ncu_params
, 0, &tid
);
1002 ok( !WaitForSingleObject(ncu_params
.marshal_event
, 10000), "wait timed out\n" );
1003 ok_more_than_one_lock();
1004 ok_non_zero_external_conn();
1006 IStream_Seek(pStream
, ullZero
, STREAM_SEEK_SET
, NULL
);
1007 hr
= CoUnmarshalInterface(pStream
, &IID_IClassFactory
, (void **)&pProxy
);
1008 ok_ole_success(hr
, CoUnmarshalInterface
);
1009 IStream_Release(pStream
);
1011 ok_more_than_one_lock();
1012 ok_non_zero_external_conn();
1014 SetEvent(ncu_params
.unmarshal_event
);
1015 ok( !WaitForSingleObject(thread
, 10000), "wait timed out\n" );
1019 ok_zero_external_conn();
1020 ok_last_release_closes(FALSE
);
1023 CloseHandle(thread
);
1024 CloseHandle(ncu_params
.marshal_event
);
1025 CloseHandle(ncu_params
.unmarshal_event
);
1027 IUnknown_Release(pProxy
);
1032 /* STA -> STA call during DLL_THREAD_DETACH */
1033 static DWORD CALLBACK
no_couninitialize_client_proc(LPVOID p
)
1035 struct ncu_params
*ncu_params
= p
;
1037 IUnknown
*pProxy
= NULL
;
1039 pCoInitializeEx(NULL
, COINIT_APARTMENTTHREADED
);
1041 hr
= CoUnmarshalInterface(ncu_params
->stream
, &IID_IClassFactory
, (void **)&pProxy
);
1042 ok_ole_success(hr
, CoUnmarshalInterface
);
1043 IStream_Release(ncu_params
->stream
);
1045 ok_more_than_one_lock();
1047 /* die without calling CoUninitialize */
1052 /* tests STA -> STA call during DLL_THREAD_DETACH doesn't deadlock */
1053 static void test_no_couninitialize_client(void)
1056 IStream
*pStream
= NULL
;
1061 struct ncu_params ncu_params
;
1064 external_connections
= 0;
1066 hr
= CreateStreamOnHGlobal(NULL
, TRUE
, &pStream
);
1067 ok_ole_success(hr
, CreateStreamOnHGlobal
);
1068 ncu_params
.stream
= pStream
;
1070 /* NOTE: assumes start_host_object uses an STA to host the object, as MTAs
1071 * always deadlock when called from within DllMain */
1072 host_tid
= start_host_object(pStream
, &IID_IClassFactory
, (IUnknown
*)&Test_ClassFactory
, MSHLFLAGS_NORMAL
, &host_thread
);
1073 IStream_Seek(pStream
, ullZero
, STREAM_SEEK_SET
, NULL
);
1075 ok_more_than_one_lock();
1076 ok_non_zero_external_conn();
1078 thread
= CreateThread(NULL
, 0, no_couninitialize_client_proc
, &ncu_params
, 0, &tid
);
1080 ok( !WaitForSingleObject(thread
, 10000), "wait timed out\n" );
1081 CloseHandle(thread
);
1084 ok_zero_external_conn();
1085 ok_last_release_closes(TRUE
);
1087 end_host_object(host_tid
, host_thread
);
1090 static BOOL crash_thread_success
;
1092 static DWORD CALLBACK
crash_couninitialize_proc(void *p
)
1101 hr
= CreateStreamOnHGlobal(NULL
, TRUE
, &stream
);
1102 ok_ole_success(hr
, CreateStreamOnHGlobal
);
1104 hr
= CoMarshalInterface(stream
, &IID_IUnknown
, &TestCrash_Unknown
, MSHCTX_INPROC
, NULL
, MSHLFLAGS_NORMAL
);
1105 ok_ole_success(hr
, CoMarshalInterface
);
1107 IStream_Seek(stream
, ullZero
, STREAM_SEEK_SET
, NULL
);
1109 hr
= CoReleaseMarshalData(stream
);
1110 ok_ole_success(hr
, CoReleaseMarshalData
);
1114 hr
= CoMarshalInterface(stream
, &IID_IUnknown
, &TestCrash_Unknown
, MSHCTX_INPROC
, NULL
, MSHLFLAGS_NORMAL
);
1115 ok_ole_success(hr
, CoMarshalInterface
);
1117 ok_more_than_one_lock();
1119 trace("CoUninitialize >>>\n");
1121 trace("CoUninitialize <<<\n");
1125 IStream_Release(stream
);
1126 crash_thread_success
= TRUE
;
1130 static void test_crash_couninitialize(void)
1135 if(!GetProcAddress(GetModuleHandleA("kernel32.dll"), "CreateActCtxW")) {
1136 win_skip("Skipping crash tests on win2k.\n");
1140 crash_thread_success
= FALSE
;
1141 thread
= CreateThread(NULL
, 0, crash_couninitialize_proc
, NULL
, 0, &tid
);
1142 ok(!WaitForSingleObject(thread
, 10000), "wait timed out\n");
1143 CloseHandle(thread
);
1144 ok(crash_thread_success
, "Crash thread failed\n");
1147 /* tests success case of a same-thread table-weak marshal, unmarshal, unmarshal */
1148 static void test_tableweak_marshal_and_unmarshal_twice(void)
1151 IStream
*pStream
= NULL
;
1152 IUnknown
*pProxy1
= NULL
;
1153 IUnknown
*pProxy2
= NULL
;
1158 external_connections
= 0;
1160 hr
= CreateStreamOnHGlobal(NULL
, TRUE
, &pStream
);
1161 ok_ole_success(hr
, CreateStreamOnHGlobal
);
1162 tid
= start_host_object(pStream
, &IID_IClassFactory
, (IUnknown
*)&Test_ClassFactory
, MSHLFLAGS_TABLEWEAK
, &thread
);
1164 ok_more_than_one_lock();
1165 ok_zero_external_conn();
1167 IStream_Seek(pStream
, ullZero
, STREAM_SEEK_SET
, NULL
);
1168 hr
= CoUnmarshalInterface(pStream
, &IID_IClassFactory
, (void **)&pProxy1
);
1169 ok_ole_success(hr
, CoUnmarshalInterface
);
1171 ok_more_than_one_lock();
1172 ok_non_zero_external_conn();
1174 IStream_Seek(pStream
, ullZero
, STREAM_SEEK_SET
, NULL
);
1175 hr
= CoUnmarshalInterface(pStream
, &IID_IClassFactory
, (void **)&pProxy2
);
1176 ok_ole_success(hr
, CoUnmarshalInterface
);
1178 ok_more_than_one_lock();
1180 IUnknown_Release(pProxy1
);
1181 ok_non_zero_external_conn();
1182 IUnknown_Release(pProxy2
);
1183 ok_zero_external_conn();
1184 ok_last_release_closes(TRUE
);
1186 /* When IExternalConnection is present COM's lifetime management
1187 * behaviour is altered; the remaining weak ref prevents stub shutdown. */
1188 if (with_external_conn
)
1190 ok_more_than_one_lock();
1191 IStream_Seek(pStream
, ullZero
, STREAM_SEEK_SET
, NULL
);
1192 release_host_object(tid
, 0);
1195 /* Without IExternalConnection this line is shows the difference between weak and strong table marshaling
1196 * weak has cLocks == 0, strong has cLocks > 0. */
1199 IStream_Release(pStream
);
1200 end_host_object(tid
, thread
);
1203 /* tests releasing after unmarshaling one object */
1204 static void test_tableweak_marshal_releasedata1(void)
1207 IStream
*pStream
= NULL
;
1208 IUnknown
*pProxy1
= NULL
;
1209 IUnknown
*pProxy2
= NULL
;
1214 external_connections
= 0;
1216 hr
= CreateStreamOnHGlobal(NULL
, TRUE
, &pStream
);
1217 ok_ole_success(hr
, CreateStreamOnHGlobal
);
1218 tid
= start_host_object(pStream
, &IID_IClassFactory
, (IUnknown
*)&Test_ClassFactory
, MSHLFLAGS_TABLEWEAK
, &thread
);
1220 ok_more_than_one_lock();
1221 ok_zero_external_conn();
1223 IStream_Seek(pStream
, ullZero
, STREAM_SEEK_SET
, NULL
);
1224 hr
= CoUnmarshalInterface(pStream
, &IID_IClassFactory
, (void **)&pProxy1
);
1225 ok_ole_success(hr
, CoUnmarshalInterface
);
1227 ok_more_than_one_lock();
1228 ok_non_zero_external_conn();
1230 /* release the remaining reference on the object by calling
1231 * CoReleaseMarshalData in the hosting thread */
1232 IStream_Seek(pStream
, ullZero
, STREAM_SEEK_SET
, NULL
);
1233 release_host_object(tid
, 0);
1235 ok_more_than_one_lock();
1236 ok_non_zero_external_conn();
1238 IStream_Seek(pStream
, ullZero
, STREAM_SEEK_SET
, NULL
);
1239 hr
= CoUnmarshalInterface(pStream
, &IID_IClassFactory
, (void **)&pProxy2
);
1240 ok_ole_success(hr
, CoUnmarshalInterface
);
1241 IStream_Release(pStream
);
1243 ok_more_than_one_lock();
1244 ok_non_zero_external_conn();
1246 IUnknown_Release(pProxy1
);
1250 ok_non_zero_external_conn();
1251 IUnknown_Release(pProxy2
);
1254 /* this line is shows the difference between weak and strong table marshaling:
1255 * weak has cLocks == 0
1256 * strong has cLocks > 0 */
1258 ok_zero_external_conn();
1259 ok_last_release_closes(TRUE
);
1261 end_host_object(tid
, thread
);
1264 /* tests releasing after unmarshaling one object */
1265 static void test_tableweak_marshal_releasedata2(void)
1268 IStream
*pStream
= NULL
;
1269 IUnknown
*pProxy
= NULL
;
1274 external_connections
= 0;
1276 hr
= CreateStreamOnHGlobal(NULL
, TRUE
, &pStream
);
1277 ok_ole_success(hr
, CreateStreamOnHGlobal
);
1278 tid
= start_host_object(pStream
, &IID_IClassFactory
, (IUnknown
*)&Test_ClassFactory
, MSHLFLAGS_TABLEWEAK
, &thread
);
1280 ok_more_than_one_lock();
1281 ok_zero_external_conn();
1283 /* release the remaining reference on the object by calling
1284 * CoReleaseMarshalData in the hosting thread */
1285 IStream_Seek(pStream
, ullZero
, STREAM_SEEK_SET
, NULL
);
1286 release_host_object(tid
, 0);
1290 IStream_Seek(pStream
, ullZero
, STREAM_SEEK_SET
, NULL
);
1291 hr
= CoUnmarshalInterface(pStream
, &IID_IClassFactory
, (void **)&pProxy
);
1294 ok(hr
== CO_E_OBJNOTREG
,
1295 "CoUnmarshalInterface should have failed with CO_E_OBJNOTREG, but returned 0x%08x instead\n",
1298 IStream_Release(pStream
);
1301 ok_zero_external_conn();
1303 end_host_object(tid
, thread
);
1306 struct duo_marshal_data
1308 MSHLFLAGS marshal_flags1
, marshal_flags2
;
1309 IStream
*pStream1
, *pStream2
;
1314 static DWORD CALLBACK
duo_marshal_thread_proc(void *p
)
1317 struct duo_marshal_data
*data
= p
;
1318 HANDLE hQuitEvent
= data
->hQuitEvent
;
1321 pCoInitializeEx(NULL
, COINIT_APARTMENTTHREADED
);
1323 hr
= CoMarshalInterface(data
->pStream1
, &IID_IClassFactory
, (IUnknown
*)&Test_ClassFactory
, MSHCTX_INPROC
, NULL
, data
->marshal_flags1
);
1324 ok_ole_success(hr
, "CoMarshalInterface");
1326 hr
= CoMarshalInterface(data
->pStream2
, &IID_IClassFactory
, (IUnknown
*)&Test_ClassFactory
, MSHCTX_INPROC
, NULL
, data
->marshal_flags2
);
1327 ok_ole_success(hr
, "CoMarshalInterface");
1329 /* force the message queue to be created before signaling parent thread */
1330 PeekMessageA(&msg
, NULL
, WM_USER
, WM_USER
, PM_NOREMOVE
);
1332 SetEvent(data
->hReadyEvent
);
1334 while (WAIT_OBJECT_0
+ 1 == MsgWaitForMultipleObjects(1, &hQuitEvent
, FALSE
, 10000, QS_ALLINPUT
))
1336 while (PeekMessageA(&msg
, NULL
, 0, 0, PM_REMOVE
))
1338 if (msg
.hwnd
== NULL
&& msg
.message
== RELEASEMARSHALDATA
)
1340 CoReleaseMarshalData(msg
.wParam
== 1 ? data
->pStream1
: data
->pStream2
);
1341 SetEvent((HANDLE
)msg
.lParam
);
1344 DispatchMessageA(&msg
);
1347 CloseHandle(hQuitEvent
);
1354 /* tests interaction between table-weak and normal marshalling of an object */
1355 static void test_tableweak_and_normal_marshal_and_unmarshal(void)
1358 IUnknown
*pProxyWeak
= NULL
;
1359 IUnknown
*pProxyNormal
= NULL
;
1362 struct duo_marshal_data data
;
1365 external_connections
= 0;
1367 data
.hReadyEvent
= CreateEventA(NULL
, FALSE
, FALSE
, NULL
);
1368 data
.hQuitEvent
= CreateEventA(NULL
, FALSE
, FALSE
, NULL
);
1369 data
.marshal_flags1
= MSHLFLAGS_TABLEWEAK
;
1370 data
.marshal_flags2
= MSHLFLAGS_NORMAL
;
1371 hr
= CreateStreamOnHGlobal(NULL
, TRUE
, &data
.pStream1
);
1372 ok_ole_success(hr
, CreateStreamOnHGlobal
);
1373 hr
= CreateStreamOnHGlobal(NULL
, TRUE
, &data
.pStream2
);
1374 ok_ole_success(hr
, CreateStreamOnHGlobal
);
1376 thread
= CreateThread(NULL
, 0, duo_marshal_thread_proc
, &data
, 0, &tid
);
1377 ok( !WaitForSingleObject(data
.hReadyEvent
, 10000), "wait timed out\n" );
1378 CloseHandle(data
.hReadyEvent
);
1380 ok_more_than_one_lock();
1381 ok_non_zero_external_conn();
1384 IStream_Seek(data
.pStream1
, ullZero
, STREAM_SEEK_SET
, NULL
);
1385 hr
= CoUnmarshalInterface(data
.pStream1
, &IID_IClassFactory
, (void **)&pProxyWeak
);
1386 ok_ole_success(hr
, CoUnmarshalInterface
);
1388 ok_more_than_one_lock();
1391 IStream_Seek(data
.pStream2
, ullZero
, STREAM_SEEK_SET
, NULL
);
1392 hr
= CoUnmarshalInterface(data
.pStream2
, &IID_IClassFactory
, (void **)&pProxyNormal
);
1393 ok_ole_success(hr
, CoUnmarshalInterface
);
1395 ok_more_than_one_lock();
1397 IUnknown_Release(pProxyNormal
);
1399 ok_more_than_one_lock();
1400 ok_non_zero_external_conn();
1402 IUnknown_Release(pProxyWeak
);
1404 ok_zero_external_conn();
1405 ok_last_release_closes(TRUE
);
1407 /* When IExternalConnection is present COM's lifetime management
1408 * behaviour is altered; the remaining weak ref prevents stub shutdown. */
1409 if (with_external_conn
)
1411 ok_more_than_one_lock();
1412 IStream_Seek(data
.pStream1
, ullZero
, STREAM_SEEK_SET
, NULL
);
1413 release_host_object(tid
, 1);
1417 IStream_Release(data
.pStream1
);
1418 IStream_Release(data
.pStream2
);
1420 SetEvent(data
.hQuitEvent
);
1421 ok( !WaitForSingleObject(thread
, 10000), "wait timed out\n" );
1422 CloseHandle(thread
);
1425 static void test_tableweak_and_normal_marshal_and_releasedata(void)
1430 struct duo_marshal_data data
;
1433 external_connections
= 0;
1435 data
.hReadyEvent
= CreateEventA(NULL
, FALSE
, FALSE
, NULL
);
1436 data
.hQuitEvent
= CreateEventA(NULL
, FALSE
, FALSE
, NULL
);
1437 data
.marshal_flags1
= MSHLFLAGS_TABLEWEAK
;
1438 data
.marshal_flags2
= MSHLFLAGS_NORMAL
;
1439 hr
= CreateStreamOnHGlobal(NULL
, TRUE
, &data
.pStream1
);
1440 ok_ole_success(hr
, CreateStreamOnHGlobal
);
1441 hr
= CreateStreamOnHGlobal(NULL
, TRUE
, &data
.pStream2
);
1442 ok_ole_success(hr
, CreateStreamOnHGlobal
);
1444 thread
= CreateThread(NULL
, 0, duo_marshal_thread_proc
, &data
, 0, &tid
);
1445 ok( !WaitForSingleObject(data
.hReadyEvent
, 10000), "wait timed out\n" );
1446 CloseHandle(data
.hReadyEvent
);
1448 ok_more_than_one_lock();
1449 ok_non_zero_external_conn();
1451 /* release normal - which in the non-external conn case will free the object despite the weak ref. */
1452 IStream_Seek(data
.pStream2
, ullZero
, STREAM_SEEK_SET
, NULL
);
1453 release_host_object(tid
, 2);
1455 ok_zero_external_conn();
1456 ok_last_release_closes(TRUE
);
1458 if (with_external_conn
)
1460 ok_more_than_one_lock();
1461 IStream_Seek(data
.pStream1
, ullZero
, STREAM_SEEK_SET
, NULL
);
1462 release_host_object(tid
, 1);
1467 IStream_Release(data
.pStream1
);
1468 IStream_Release(data
.pStream2
);
1470 SetEvent(data
.hQuitEvent
);
1471 ok( !WaitForSingleObject(thread
, 10000), "wait timed out\n" );
1472 CloseHandle(thread
);
1475 static void test_two_tableweak_marshal_and_releasedata(void)
1480 struct duo_marshal_data data
;
1483 external_connections
= 0;
1485 data
.hReadyEvent
= CreateEventA(NULL
, FALSE
, FALSE
, NULL
);
1486 data
.hQuitEvent
= CreateEventA(NULL
, FALSE
, FALSE
, NULL
);
1487 data
.marshal_flags1
= MSHLFLAGS_TABLEWEAK
;
1488 data
.marshal_flags2
= MSHLFLAGS_TABLEWEAK
;
1489 hr
= CreateStreamOnHGlobal(NULL
, TRUE
, &data
.pStream1
);
1490 ok_ole_success(hr
, CreateStreamOnHGlobal
);
1491 hr
= CreateStreamOnHGlobal(NULL
, TRUE
, &data
.pStream2
);
1492 ok_ole_success(hr
, CreateStreamOnHGlobal
);
1494 thread
= CreateThread(NULL
, 0, duo_marshal_thread_proc
, &data
, 0, &tid
);
1495 ok( !WaitForSingleObject(data
.hReadyEvent
, 10000), "wait timed out\n" );
1496 CloseHandle(data
.hReadyEvent
);
1498 ok_more_than_one_lock();
1499 ok_zero_external_conn();
1501 /* release one weak ref - the remaining weak ref will keep the obj alive */
1502 IStream_Seek(data
.pStream1
, ullZero
, STREAM_SEEK_SET
, NULL
);
1503 release_host_object(tid
, 1);
1505 ok_more_than_one_lock();
1507 IStream_Seek(data
.pStream2
, ullZero
, STREAM_SEEK_SET
, NULL
);
1508 release_host_object(tid
, 2);
1512 IStream_Release(data
.pStream1
);
1513 IStream_Release(data
.pStream2
);
1515 SetEvent(data
.hQuitEvent
);
1516 ok( !WaitForSingleObject(thread
, 10000), "wait timed out\n" );
1517 CloseHandle(thread
);
1520 /* tests success case of a same-thread table-strong marshal, unmarshal, unmarshal */
1521 static void test_tablestrong_marshal_and_unmarshal_twice(void)
1524 IStream
*pStream
= NULL
;
1525 IUnknown
*pProxy1
= NULL
;
1526 IUnknown
*pProxy2
= NULL
;
1531 external_connections
= 0;
1533 hr
= CreateStreamOnHGlobal(NULL
, TRUE
, &pStream
);
1534 ok_ole_success(hr
, CreateStreamOnHGlobal
);
1535 tid
= start_host_object(pStream
, &IID_IClassFactory
, (IUnknown
*)&Test_ClassFactory
, MSHLFLAGS_TABLESTRONG
, &thread
);
1537 ok_more_than_one_lock();
1538 ok_non_zero_external_conn();
1540 IStream_Seek(pStream
, ullZero
, STREAM_SEEK_SET
, NULL
);
1541 hr
= CoUnmarshalInterface(pStream
, &IID_IClassFactory
, (void **)&pProxy1
);
1542 ok_ole_success(hr
, CoUnmarshalInterface
);
1544 ok_more_than_one_lock();
1546 IStream_Seek(pStream
, ullZero
, STREAM_SEEK_SET
, NULL
);
1547 hr
= CoUnmarshalInterface(pStream
, &IID_IClassFactory
, (void **)&pProxy2
);
1548 ok_ole_success(hr
, CoUnmarshalInterface
);
1550 ok_more_than_one_lock();
1552 if (pProxy1
) IUnknown_Release(pProxy1
);
1553 if (pProxy2
) IUnknown_Release(pProxy2
);
1555 /* this line is shows the difference between weak and strong table marshaling:
1556 * weak has cLocks == 0
1557 * strong has cLocks > 0 */
1558 ok_more_than_one_lock();
1560 /* release the remaining reference on the object by calling
1561 * CoReleaseMarshalData in the hosting thread */
1562 IStream_Seek(pStream
, ullZero
, STREAM_SEEK_SET
, NULL
);
1563 release_host_object(tid
, 0);
1564 IStream_Release(pStream
);
1567 ok_zero_external_conn();
1568 ok_last_release_closes(TRUE
);
1570 end_host_object(tid
, thread
);
1573 /* tests CoLockObjectExternal */
1574 static void test_lock_object_external(void)
1577 IStream
*pStream
= NULL
;
1580 external_connections
= 0;
1582 /* test the stub manager creation aspect of CoLockObjectExternal when the
1583 * object hasn't been marshaled yet */
1584 CoLockObjectExternal((IUnknown
*)&Test_ClassFactory
, TRUE
, TRUE
);
1586 ok_more_than_one_lock();
1587 ok_non_zero_external_conn();
1589 CoDisconnectObject((IUnknown
*)&Test_ClassFactory
, 0);
1592 ok_non_zero_external_conn();
1593 external_connections
= 0;
1595 /* test our empty stub manager being handled correctly in
1596 * CoMarshalInterface */
1597 CoLockObjectExternal((IUnknown
*)&Test_ClassFactory
, TRUE
, TRUE
);
1599 hr
= CreateStreamOnHGlobal(NULL
, TRUE
, &pStream
);
1600 ok_ole_success(hr
, CreateStreamOnHGlobal
);
1601 hr
= CoMarshalInterface(pStream
, &IID_IClassFactory
, (IUnknown
*)&Test_ClassFactory
, MSHCTX_INPROC
, NULL
, MSHLFLAGS_NORMAL
);
1602 ok_ole_success(hr
, CoMarshalInterface
);
1604 CoLockObjectExternal((IUnknown
*)&Test_ClassFactory
, TRUE
, TRUE
);
1606 ok_more_than_one_lock();
1607 ok_non_zero_external_conn();
1609 IStream_Seek(pStream
, ullZero
, STREAM_SEEK_SET
, NULL
);
1610 hr
= CoReleaseMarshalData(pStream
);
1611 ok_ole_success(hr
, CoReleaseMarshalData
);
1612 IStream_Seek(pStream
, ullZero
, STREAM_SEEK_SET
, NULL
);
1614 ok_more_than_one_lock();
1615 ok_non_zero_external_conn();
1616 ok_last_release_closes(TRUE
);
1618 CoLockObjectExternal((IUnknown
*)&Test_ClassFactory
, FALSE
, TRUE
);
1620 ok_more_than_one_lock();
1621 ok_non_zero_external_conn();
1622 ok_last_release_closes(TRUE
);
1624 CoLockObjectExternal((IUnknown
*)&Test_ClassFactory
, FALSE
, TRUE
);
1627 ok_zero_external_conn();
1628 ok_last_release_closes(TRUE
);
1630 /* test CoLockObjectExternal releases reference to object with
1631 * fLastUnlockReleases as TRUE and there are only strong references on
1633 CoLockObjectExternal((IUnknown
*)&Test_ClassFactory
, TRUE
, FALSE
);
1635 ok_more_than_one_lock();
1636 ok_non_zero_external_conn();
1638 CoLockObjectExternal((IUnknown
*)&Test_ClassFactory
, FALSE
, FALSE
);
1641 ok_zero_external_conn();
1642 ok_last_release_closes(FALSE
);
1644 /* test CoLockObjectExternal doesn't release the last reference to an
1645 * object with fLastUnlockReleases as TRUE and there is a weak reference
1647 hr
= CoMarshalInterface(pStream
, &IID_IClassFactory
, (IUnknown
*)&Test_ClassFactory
, MSHCTX_INPROC
, NULL
, MSHLFLAGS_TABLEWEAK
);
1648 ok_ole_success(hr
, CoMarshalInterface
);
1650 ok_more_than_one_lock();
1651 ok_zero_external_conn();
1653 CoLockObjectExternal((IUnknown
*)&Test_ClassFactory
, TRUE
, FALSE
);
1655 ok_more_than_one_lock();
1656 ok_non_zero_external_conn();
1658 CoLockObjectExternal((IUnknown
*)&Test_ClassFactory
, FALSE
, FALSE
);
1660 ok_more_than_one_lock();
1661 ok_zero_external_conn();
1662 ok_last_release_closes(FALSE
);
1664 CoDisconnectObject((IUnknown
*)&Test_ClassFactory
, 0);
1668 IStream_Release(pStream
);
1671 /* tests disconnecting stubs */
1672 static void test_disconnect_stub(void)
1675 IStream
*pStream
= NULL
;
1678 external_connections
= 0;
1680 hr
= CreateStreamOnHGlobal(NULL
, TRUE
, &pStream
);
1681 ok_ole_success(hr
, CreateStreamOnHGlobal
);
1682 hr
= CoMarshalInterface(pStream
, &IID_IClassFactory
, (IUnknown
*)&Test_ClassFactory
, MSHCTX_INPROC
, NULL
, MSHLFLAGS_NORMAL
);
1683 ok_ole_success(hr
, CoMarshalInterface
);
1685 ok_non_zero_external_conn();
1687 CoLockObjectExternal((IUnknown
*)&Test_ClassFactory
, TRUE
, TRUE
);
1689 ok_more_than_one_lock();
1690 ok_non_zero_external_conn();
1692 IStream_Seek(pStream
, ullZero
, STREAM_SEEK_SET
, NULL
);
1693 hr
= CoReleaseMarshalData(pStream
);
1694 ok_ole_success(hr
, CoReleaseMarshalData
);
1695 IStream_Release(pStream
);
1697 ok_more_than_one_lock();
1698 ok_non_zero_external_conn();
1700 CoDisconnectObject((IUnknown
*)&Test_ClassFactory
, 0);
1703 ok_non_zero_external_conn();
1705 hr
= CoDisconnectObject(NULL
, 0);
1706 ok( hr
== E_INVALIDARG
, "wrong status %x\n", hr
);
1709 /* tests failure case of a same-thread marshal and unmarshal twice */
1710 static void test_normal_marshal_and_unmarshal_twice(void)
1713 IStream
*pStream
= NULL
;
1714 IUnknown
*pProxy1
= NULL
;
1715 IUnknown
*pProxy2
= NULL
;
1718 external_connections
= 0;
1720 hr
= CreateStreamOnHGlobal(NULL
, TRUE
, &pStream
);
1721 ok_ole_success(hr
, CreateStreamOnHGlobal
);
1722 hr
= CoMarshalInterface(pStream
, &IID_IClassFactory
, (IUnknown
*)&Test_ClassFactory
, MSHCTX_INPROC
, NULL
, MSHLFLAGS_NORMAL
);
1723 ok_ole_success(hr
, CoMarshalInterface
);
1725 ok_more_than_one_lock();
1726 ok_non_zero_external_conn();
1728 IStream_Seek(pStream
, ullZero
, STREAM_SEEK_SET
, NULL
);
1729 hr
= CoUnmarshalInterface(pStream
, &IID_IClassFactory
, (void **)&pProxy1
);
1730 ok_ole_success(hr
, CoUnmarshalInterface
);
1732 ok_more_than_one_lock();
1733 ok_zero_external_conn();
1734 ok_last_release_closes(FALSE
);
1736 IStream_Seek(pStream
, ullZero
, STREAM_SEEK_SET
, NULL
);
1737 hr
= CoUnmarshalInterface(pStream
, &IID_IClassFactory
, (void **)&pProxy2
);
1738 ok(hr
== CO_E_OBJNOTCONNECTED
,
1739 "CoUnmarshalInterface should have failed with error CO_E_OBJNOTCONNECTED for double unmarshal, instead of 0x%08x\n", hr
);
1741 IStream_Release(pStream
);
1743 ok_more_than_one_lock();
1745 IUnknown_Release(pProxy1
);
1750 /* tests success case of marshaling and unmarshaling an HRESULT */
1751 static void test_hresult_marshaling(void)
1754 HRESULT hr_marshaled
= 0;
1755 IStream
*pStream
= NULL
;
1756 static const HRESULT E_DEADBEEF
= 0xdeadbeef;
1758 hr
= CreateStreamOnHGlobal(NULL
, TRUE
, &pStream
);
1759 ok_ole_success(hr
, CreateStreamOnHGlobal
);
1761 hr
= CoMarshalHresult(pStream
, E_DEADBEEF
);
1762 ok_ole_success(hr
, CoMarshalHresult
);
1764 IStream_Seek(pStream
, ullZero
, STREAM_SEEK_SET
, NULL
);
1765 hr
= IStream_Read(pStream
, &hr_marshaled
, sizeof(HRESULT
), NULL
);
1766 ok_ole_success(hr
, IStream_Read
);
1768 ok(hr_marshaled
== E_DEADBEEF
, "Didn't marshal HRESULT as expected: got value 0x%08x instead\n", hr_marshaled
);
1771 IStream_Seek(pStream
, ullZero
, STREAM_SEEK_SET
, NULL
);
1772 hr
= CoUnmarshalHresult(pStream
, &hr_marshaled
);
1773 ok_ole_success(hr
, CoUnmarshalHresult
);
1775 ok(hr_marshaled
== E_DEADBEEF
, "Didn't marshal HRESULT as expected: got value 0x%08x instead\n", hr_marshaled
);
1777 IStream_Release(pStream
);
1781 /* helper for test_proxy_used_in_wrong_thread */
1782 static DWORD CALLBACK
bad_thread_proc(LPVOID p
)
1784 IClassFactory
* cf
= p
;
1786 IUnknown
* proxy
= NULL
;
1788 hr
= IClassFactory_CreateInstance(cf
, NULL
, &IID_IUnknown
, (LPVOID
*)&proxy
);
1790 ok(hr
== CO_E_NOTINITIALIZED
,
1791 "COM should have failed with CO_E_NOTINITIALIZED on using proxy without apartment, but instead returned 0x%08x\n",
1794 hr
= IClassFactory_QueryInterface(cf
, &IID_IMultiQI
, (LPVOID
*)&proxy
);
1795 /* Win9x returns S_OK, whilst NT returns RPC_E_WRONG_THREAD */
1796 trace("call to proxy's QueryInterface for local interface without apartment returned 0x%08x\n", hr
);
1798 IUnknown_Release(proxy
);
1800 hr
= IClassFactory_QueryInterface(cf
, &IID_IStream
, (LPVOID
*)&proxy
);
1801 /* Win9x returns E_NOINTERFACE, whilst NT returns RPC_E_WRONG_THREAD */
1802 trace("call to proxy's QueryInterface without apartment returned 0x%08x\n", hr
);
1804 IUnknown_Release(proxy
);
1806 pCoInitializeEx(NULL
, COINIT_MULTITHREADED
);
1808 hr
= IClassFactory_CreateInstance(cf
, NULL
, &IID_IUnknown
, (LPVOID
*)&proxy
);
1809 if (proxy
) IUnknown_Release(proxy
);
1810 ok(hr
== RPC_E_WRONG_THREAD
,
1811 "COM should have failed with RPC_E_WRONG_THREAD on using proxy from wrong apartment, but instead returned 0x%08x\n",
1814 hr
= IClassFactory_QueryInterface(cf
, &IID_IStream
, (LPVOID
*)&proxy
);
1815 /* Win9x returns E_NOINTERFACE, whilst NT returns RPC_E_WRONG_THREAD */
1816 trace("call to proxy's QueryInterface from wrong apartment returned 0x%08x\n", hr
);
1818 /* now be really bad and release the proxy from the wrong apartment */
1819 IClassFactory_Release(cf
);
1826 /* tests failure case of a using a proxy in the wrong apartment */
1827 static void test_proxy_used_in_wrong_thread(void)
1830 IStream
*pStream
= NULL
;
1831 IUnknown
*pProxy
= NULL
;
1838 hr
= CreateStreamOnHGlobal(NULL
, TRUE
, &pStream
);
1839 ok_ole_success(hr
, CreateStreamOnHGlobal
);
1840 tid
= start_host_object(pStream
, &IID_IClassFactory
, (IUnknown
*)&Test_ClassFactory
, MSHLFLAGS_NORMAL
, &host_thread
);
1842 ok_more_than_one_lock();
1844 IStream_Seek(pStream
, ullZero
, STREAM_SEEK_SET
, NULL
);
1845 hr
= CoUnmarshalInterface(pStream
, &IID_IClassFactory
, (void **)&pProxy
);
1846 ok_ole_success(hr
, CoUnmarshalInterface
);
1847 IStream_Release(pStream
);
1849 ok_more_than_one_lock();
1851 /* do a call that will fail, but result in IRemUnknown being used by the proxy */
1852 IUnknown_QueryInterface(pProxy
, &IID_IStream
, (LPVOID
*)&pStream
);
1854 /* create a thread that we can misbehave in */
1855 thread
= CreateThread(NULL
, 0, bad_thread_proc
, pProxy
, 0, &tid2
);
1857 ok( !WaitForSingleObject(thread
, 10000), "wait timed out\n" );
1858 CloseHandle(thread
);
1860 /* do release statement on Win9x that we should have done above */
1861 if (!GetProcAddress(GetModuleHandleA("ole32"), "CoRegisterSurrogateEx"))
1862 IUnknown_Release(pProxy
);
1866 end_host_object(tid
, host_thread
);
1869 static HRESULT WINAPI
MessageFilter_QueryInterface(IMessageFilter
*iface
, REFIID riid
, void ** ppvObj
)
1871 if (ppvObj
== NULL
) return E_POINTER
;
1873 if (IsEqualGUID(riid
, &IID_IUnknown
) ||
1874 IsEqualGUID(riid
, &IID_IClassFactory
))
1877 IMessageFilter_AddRef(iface
);
1881 return E_NOINTERFACE
;
1884 static ULONG WINAPI
MessageFilter_AddRef(IMessageFilter
*iface
)
1886 return 2; /* non-heap object */
1889 static ULONG WINAPI
MessageFilter_Release(IMessageFilter
*iface
)
1891 return 1; /* non-heap object */
1894 static DWORD WINAPI
MessageFilter_HandleInComingCall(
1895 IMessageFilter
*iface
,
1897 HTASK threadIDCaller
,
1899 LPINTERFACEINFO lpInterfaceInfo
)
1901 static int callcount
= 0;
1903 trace("HandleInComingCall\n");
1907 ret
= SERVERCALL_REJECTED
;
1910 ret
= SERVERCALL_RETRYLATER
;
1913 ret
= SERVERCALL_ISHANDLED
;
1920 static DWORD WINAPI
MessageFilter_RetryRejectedCall(
1921 IMessageFilter
*iface
,
1922 HTASK threadIDCallee
,
1926 trace("RetryRejectedCall\n");
1930 static DWORD WINAPI
MessageFilter_MessagePending(
1931 IMessageFilter
*iface
,
1932 HTASK threadIDCallee
,
1934 DWORD dwPendingType
)
1936 trace("MessagePending\n");
1937 return PENDINGMSG_WAITNOPROCESS
;
1940 static const IMessageFilterVtbl MessageFilter_Vtbl
=
1942 MessageFilter_QueryInterface
,
1943 MessageFilter_AddRef
,
1944 MessageFilter_Release
,
1945 MessageFilter_HandleInComingCall
,
1946 MessageFilter_RetryRejectedCall
,
1947 MessageFilter_MessagePending
1950 static IMessageFilter MessageFilter
= { &MessageFilter_Vtbl
};
1952 static void test_message_filter(void)
1955 IStream
*pStream
= NULL
;
1956 IClassFactory
*cf
= NULL
;
1958 IUnknown
*proxy
= NULL
;
1959 IMessageFilter
*prev_filter
= NULL
;
1964 hr
= CreateStreamOnHGlobal(NULL
, TRUE
, &pStream
);
1965 ok_ole_success(hr
, CreateStreamOnHGlobal
);
1966 tid
= start_host_object2(pStream
, &IID_IClassFactory
, (IUnknown
*)&Test_ClassFactory
, MSHLFLAGS_NORMAL
, &MessageFilter
, &thread
);
1968 ok_more_than_one_lock();
1970 IStream_Seek(pStream
, ullZero
, STREAM_SEEK_SET
, NULL
);
1971 hr
= CoUnmarshalInterface(pStream
, &IID_IClassFactory
, (void **)&cf
);
1972 ok_ole_success(hr
, CoUnmarshalInterface
);
1973 IStream_Release(pStream
);
1975 ok_more_than_one_lock();
1977 hr
= IClassFactory_CreateInstance(cf
, NULL
, &IID_IUnknown
, (LPVOID
*)&proxy
);
1978 ok(hr
== RPC_E_CALL_REJECTED
, "Call should have returned RPC_E_CALL_REJECTED, but return 0x%08x instead\n", hr
);
1979 if (proxy
) IUnknown_Release(proxy
);
1982 hr
= CoRegisterMessageFilter(&MessageFilter
, &prev_filter
);
1983 ok_ole_success(hr
, CoRegisterMessageFilter
);
1985 hr
= IClassFactory_CreateInstance(cf
, NULL
, &IID_IUnknown
, (LPVOID
*)&proxy
);
1986 ok_ole_success(hr
, IClassFactory_CreateInstance
);
1988 IUnknown_Release(proxy
);
1990 IClassFactory_Release(cf
);
1994 end_host_object(tid
, thread
);
1996 hr
= CoRegisterMessageFilter(prev_filter
, NULL
);
1997 ok_ole_success(hr
, CoRegisterMessageFilter
);
2000 /* test failure case of trying to unmarshal from bad stream */
2001 static void test_bad_marshal_stream(void)
2004 IStream
*pStream
= NULL
;
2006 hr
= CreateStreamOnHGlobal(NULL
, TRUE
, &pStream
);
2007 ok_ole_success(hr
, CreateStreamOnHGlobal
);
2008 hr
= CoMarshalInterface(pStream
, &IID_IClassFactory
, (IUnknown
*)&Test_ClassFactory
, MSHCTX_INPROC
, NULL
, MSHLFLAGS_NORMAL
);
2009 ok_ole_success(hr
, CoMarshalInterface
);
2011 ok_more_than_one_lock();
2013 /* try to read beyond end of stream */
2014 hr
= CoReleaseMarshalData(pStream
);
2015 ok(hr
== STG_E_READFAULT
, "Should have failed with STG_E_READFAULT, but returned 0x%08x instead\n", hr
);
2017 /* now release for real */
2018 IStream_Seek(pStream
, ullZero
, STREAM_SEEK_SET
, NULL
);
2019 hr
= CoReleaseMarshalData(pStream
);
2020 ok_ole_success(hr
, CoReleaseMarshalData
);
2022 IStream_Release(pStream
);
2025 /* tests that proxies implement certain interfaces */
2026 static void test_proxy_interfaces(void)
2029 IStream
*pStream
= NULL
;
2030 IUnknown
*pProxy
= NULL
;
2031 IUnknown
*pOtherUnknown
= NULL
;
2037 hr
= CreateStreamOnHGlobal(NULL
, TRUE
, &pStream
);
2038 ok_ole_success(hr
, CreateStreamOnHGlobal
);
2039 tid
= start_host_object(pStream
, &IID_IClassFactory
, (IUnknown
*)&Test_ClassFactory
, MSHLFLAGS_NORMAL
, &thread
);
2041 ok_more_than_one_lock();
2043 IStream_Seek(pStream
, ullZero
, STREAM_SEEK_SET
, NULL
);
2044 hr
= CoUnmarshalInterface(pStream
, &IID_IUnknown
, (void **)&pProxy
);
2045 ok_ole_success(hr
, CoUnmarshalInterface
);
2046 IStream_Release(pStream
);
2048 ok_more_than_one_lock();
2050 hr
= IUnknown_QueryInterface(pProxy
, &IID_IUnknown
, (LPVOID
*)&pOtherUnknown
);
2051 ok_ole_success(hr
, IUnknown_QueryInterface IID_IUnknown
);
2052 if (hr
== S_OK
) IUnknown_Release(pOtherUnknown
);
2054 hr
= IUnknown_QueryInterface(pProxy
, &IID_IClientSecurity
, (LPVOID
*)&pOtherUnknown
);
2055 ok_ole_success(hr
, IUnknown_QueryInterface IID_IClientSecurity
);
2056 if (hr
== S_OK
) IUnknown_Release(pOtherUnknown
);
2058 hr
= IUnknown_QueryInterface(pProxy
, &IID_IMultiQI
, (LPVOID
*)&pOtherUnknown
);
2059 ok_ole_success(hr
, IUnknown_QueryInterface IID_IMultiQI
);
2060 if (hr
== S_OK
) IUnknown_Release(pOtherUnknown
);
2062 hr
= IUnknown_QueryInterface(pProxy
, &IID_IMarshal
, (LPVOID
*)&pOtherUnknown
);
2063 ok_ole_success(hr
, IUnknown_QueryInterface IID_IMarshal
);
2064 if (hr
== S_OK
) IUnknown_Release(pOtherUnknown
);
2066 /* IMarshal2 is also supported on NT-based systems, but is pretty much
2067 * useless as it has no more methods over IMarshal that it inherits from. */
2069 IUnknown_Release(pProxy
);
2073 end_host_object(tid
, thread
);
2078 IUnknown IUnknown_iface
;
2082 static inline HeapUnknown
*impl_from_IUnknown(IUnknown
*iface
)
2084 return CONTAINING_RECORD(iface
, HeapUnknown
, IUnknown_iface
);
2087 static HRESULT WINAPI
HeapUnknown_QueryInterface(IUnknown
*iface
, REFIID riid
, void **ppv
)
2089 if (IsEqualIID(riid
, &IID_IUnknown
))
2091 IUnknown_AddRef(iface
);
2096 return E_NOINTERFACE
;
2099 static ULONG WINAPI
HeapUnknown_AddRef(IUnknown
*iface
)
2101 HeapUnknown
*This
= impl_from_IUnknown(iface
);
2102 return InterlockedIncrement((LONG
*)&This
->refs
);
2105 static ULONG WINAPI
HeapUnknown_Release(IUnknown
*iface
)
2107 HeapUnknown
*This
= impl_from_IUnknown(iface
);
2108 ULONG refs
= InterlockedDecrement((LONG
*)&This
->refs
);
2109 if (!refs
) HeapFree(GetProcessHeap(), 0, This
);
2113 static const IUnknownVtbl HeapUnknown_Vtbl
=
2115 HeapUnknown_QueryInterface
,
2120 static void test_proxybuffer(REFIID riid
)
2123 IPSFactoryBuffer
*psfb
;
2124 IRpcProxyBuffer
*proxy
;
2128 HeapUnknown
*pUnkOuter
= HeapAlloc(GetProcessHeap(), 0, sizeof(*pUnkOuter
));
2130 pUnkOuter
->IUnknown_iface
.lpVtbl
= &HeapUnknown_Vtbl
;
2131 pUnkOuter
->refs
= 1;
2133 hr
= CoGetPSClsid(riid
, &clsid
);
2134 ok_ole_success(hr
, CoGetPSClsid
);
2136 hr
= CoGetClassObject(&clsid
, CLSCTX_INPROC_SERVER
, NULL
, &IID_IPSFactoryBuffer
, (LPVOID
*)&psfb
);
2137 ok_ole_success(hr
, CoGetClassObject
);
2139 hr
= IPSFactoryBuffer_CreateProxy(psfb
, &pUnkOuter
->IUnknown_iface
, riid
, &proxy
, &lpvtbl
);
2140 ok_ole_success(hr
, IPSFactoryBuffer_CreateProxy
);
2141 ok(lpvtbl
!= NULL
, "IPSFactoryBuffer_CreateProxy succeeded, but returned a NULL vtable!\n");
2143 /* release our reference to the outer unknown object - the PS factory
2144 * buffer will have AddRef's it in the CreateProxy call */
2145 refs
= IUnknown_Release(&pUnkOuter
->IUnknown_iface
);
2146 ok(refs
== 1, "Ref count of outer unknown should have been 1 instead of %d\n", refs
);
2148 /* Not checking return, unreliable on native. Maybe it leaks references? */
2149 IPSFactoryBuffer_Release(psfb
);
2151 refs
= IUnknown_Release((IUnknown
*)lpvtbl
);
2152 ok(refs
== 0, "Ref-count leak of %d on IRpcProxyBuffer\n", refs
);
2154 refs
= IRpcProxyBuffer_Release(proxy
);
2155 ok(refs
== 0, "Ref-count leak of %d on IRpcProxyBuffer\n", refs
);
2158 static void test_stubbuffer(REFIID riid
)
2161 IPSFactoryBuffer
*psfb
;
2162 IRpcStubBuffer
*stub
;
2168 hr
= CoGetPSClsid(riid
, &clsid
);
2169 ok_ole_success(hr
, CoGetPSClsid
);
2171 hr
= CoGetClassObject(&clsid
, CLSCTX_INPROC_SERVER
, NULL
, &IID_IPSFactoryBuffer
, (LPVOID
*)&psfb
);
2172 ok_ole_success(hr
, CoGetClassObject
);
2174 hr
= IPSFactoryBuffer_CreateStub(psfb
, riid
, (IUnknown
*)&Test_ClassFactory
, &stub
);
2175 ok_ole_success(hr
, IPSFactoryBuffer_CreateStub
);
2177 /* Not checking return, unreliable on native. Maybe it leaks references? */
2178 IPSFactoryBuffer_Release(psfb
);
2180 ok_more_than_one_lock();
2182 IRpcStubBuffer_Disconnect(stub
);
2186 refs
= IRpcStubBuffer_Release(stub
);
2187 ok(refs
== 0, "Ref-count leak of %d on IRpcProxyBuffer\n", refs
);
2190 static HWND hwnd_app
;
2192 static HRESULT WINAPI
TestRE_IClassFactory_CreateInstance(
2193 LPCLASSFACTORY iface
,
2194 LPUNKNOWN pUnkOuter
,
2199 if (IsEqualIID(riid
, &IID_IWineTest
))
2201 BOOL ret
= SendMessageTimeoutA(hwnd_app
, WM_NULL
, 0, 0, SMTO_BLOCK
, 5000, &res
);
2202 ok(ret
, "Timed out sending a message to originating window during RPC call\n");
2208 static const IClassFactoryVtbl TestREClassFactory_Vtbl
=
2210 Test_IClassFactory_QueryInterface
,
2211 Test_IClassFactory_AddRef
,
2212 Test_IClassFactory_Release
,
2213 TestRE_IClassFactory_CreateInstance
,
2214 Test_IClassFactory_LockServer
2217 static IClassFactory TestRE_ClassFactory
= { &TestREClassFactory_Vtbl
};
2219 static LRESULT CALLBACK
window_proc(HWND hwnd
, UINT msg
, WPARAM wparam
, LPARAM lparam
)
2226 IStream
*pStream
= NULL
;
2227 IClassFactory
*proxy
= NULL
;
2234 hr
= CreateStreamOnHGlobal(NULL
, TRUE
, &pStream
);
2235 ok_ole_success(hr
, CreateStreamOnHGlobal
);
2236 tid
= start_host_object(pStream
, &IID_IClassFactory
, (IUnknown
*)&TestRE_ClassFactory
, MSHLFLAGS_NORMAL
, &thread
);
2238 ok_more_than_one_lock();
2240 IStream_Seek(pStream
, ullZero
, STREAM_SEEK_SET
, NULL
);
2241 hr
= CoUnmarshalInterface(pStream
, &IID_IClassFactory
, (void **)&proxy
);
2242 ok_ole_success(hr
, CoReleaseMarshalData
);
2243 IStream_Release(pStream
);
2245 ok_more_than_one_lock();
2247 /* note the use of the magic IID_IWineTest value to tell remote thread
2248 * to try to send a message back to us */
2249 hr
= IClassFactory_CreateInstance(proxy
, NULL
, &IID_IWineTest
, (void **)&object
);
2250 ok(hr
== S_FALSE
, "expected S_FALSE, got %d\n", hr
);
2252 IClassFactory_Release(proxy
);
2256 end_host_object(tid
, thread
);
2258 PostMessageA(hwnd
, WM_QUIT
, 0, 0);
2265 IStream
*pStream
= NULL
;
2266 IClassFactory
*proxy
= NULL
;
2273 hr
= CreateStreamOnHGlobal(NULL
, TRUE
, &pStream
);
2274 ok_ole_success(hr
, CreateStreamOnHGlobal
);
2275 tid
= start_host_object(pStream
, &IID_IClassFactory
, (IUnknown
*)&TestRE_ClassFactory
, MSHLFLAGS_NORMAL
, &thread
);
2277 ok_more_than_one_lock();
2279 IStream_Seek(pStream
, ullZero
, STREAM_SEEK_SET
, NULL
);
2280 hr
= CoUnmarshalInterface(pStream
, &IID_IClassFactory
, (void **)&proxy
);
2281 ok_ole_success(hr
, CoReleaseMarshalData
);
2282 IStream_Release(pStream
);
2284 ok_more_than_one_lock();
2286 /* post quit message before a doing a COM call to show that a pending
2287 * WM_QUIT message doesn't stop the call from succeeding */
2288 PostMessageA(hwnd
, WM_QUIT
, 0, 0);
2289 hr
= IClassFactory_CreateInstance(proxy
, NULL
, &IID_IUnknown
, (void **)&object
);
2290 ok(hr
== S_FALSE
, "IClassFactory_CreateInstance returned 0x%08x, expected S_FALSE\n", hr
);
2292 IClassFactory_Release(proxy
);
2296 end_host_object(tid
, thread
);
2303 IStream
*pStream
= NULL
;
2304 IClassFactory
*proxy
= NULL
;
2309 hr
= CreateStreamOnHGlobal(NULL
, TRUE
, &pStream
);
2310 ok_ole_success(hr
, CreateStreamOnHGlobal
);
2311 tid
= start_host_object(pStream
, &IID_IClassFactory
, (IUnknown
*)&Test_ClassFactory
, MSHLFLAGS_NORMAL
, &thread
);
2313 IStream_Seek(pStream
, ullZero
, STREAM_SEEK_SET
, NULL
);
2314 hr
= CoUnmarshalInterface(pStream
, &IID_IClassFactory
, (void **)&proxy
);
2315 ok_ole_success(hr
, CoReleaseMarshalData
);
2316 IStream_Release(pStream
);
2318 /* shows that COM calls executed during the processing of sent
2319 * messages should fail */
2320 hr
= IClassFactory_CreateInstance(proxy
, NULL
, &IID_IUnknown
, (void **)&object
);
2321 ok(hr
== RPC_E_CANTCALLOUT_ININPUTSYNCCALL
,
2322 "COM call during processing of sent message should return RPC_E_CANTCALLOUT_ININPUTSYNCCALL instead of 0x%08x\n", hr
);
2324 IClassFactory_Release(proxy
);
2326 end_host_object(tid
, thread
);
2333 return DefWindowProcA(hwnd
, msg
, wparam
, lparam
);
2337 static void register_test_window(void)
2341 memset(&wndclass
, 0, sizeof(wndclass
));
2342 wndclass
.lpfnWndProc
= window_proc
;
2343 wndclass
.lpszClassName
= "WineCOMTest";
2344 RegisterClassA(&wndclass
);
2347 static void test_message_reentrancy(void)
2351 hwnd_app
= CreateWindowA("WineCOMTest", NULL
, 0, CW_USEDEFAULT
, CW_USEDEFAULT
, CW_USEDEFAULT
, CW_USEDEFAULT
, NULL
, NULL
, NULL
, 0);
2352 ok(hwnd_app
!= NULL
, "Window creation failed\n");
2354 /* start message re-entrancy test */
2355 PostMessageA(hwnd_app
, WM_USER
, 0, 0);
2357 while (GetMessageA(&msg
, NULL
, 0, 0))
2359 TranslateMessage(&msg
);
2360 DispatchMessageA(&msg
);
2362 DestroyWindow(hwnd_app
);
2365 static HRESULT WINAPI
TestMsg_IClassFactory_CreateInstance(
2366 LPCLASSFACTORY iface
,
2367 LPUNKNOWN pUnkOuter
,
2372 SendMessageA(hwnd_app
, WM_USER
+2, 0, 0);
2376 static IClassFactoryVtbl TestMsgClassFactory_Vtbl
=
2378 Test_IClassFactory_QueryInterface
,
2379 Test_IClassFactory_AddRef
,
2380 Test_IClassFactory_Release
,
2381 TestMsg_IClassFactory_CreateInstance
,
2382 Test_IClassFactory_LockServer
2385 static IClassFactory TestMsg_ClassFactory
= { &TestMsgClassFactory_Vtbl
};
2387 static void test_call_from_message(void)
2392 IClassFactory
*proxy
;
2397 hwnd_app
= CreateWindowA("WineCOMTest", NULL
, 0, CW_USEDEFAULT
, CW_USEDEFAULT
, CW_USEDEFAULT
, CW_USEDEFAULT
, NULL
, NULL
, NULL
, 0);
2398 ok(hwnd_app
!= NULL
, "Window creation failed\n");
2400 hr
= CreateStreamOnHGlobal(NULL
, TRUE
, &pStream
);
2401 ok_ole_success(hr
, CreateStreamOnHGlobal
);
2402 tid
= start_host_object(pStream
, &IID_IClassFactory
, (IUnknown
*)&TestMsg_ClassFactory
, MSHLFLAGS_NORMAL
, &thread
);
2404 ok_more_than_one_lock();
2406 IStream_Seek(pStream
, ullZero
, STREAM_SEEK_SET
, NULL
);
2407 hr
= CoUnmarshalInterface(pStream
, &IID_IClassFactory
, (void **)&proxy
);
2408 ok_ole_success(hr
, CoReleaseMarshalData
);
2409 IStream_Release(pStream
);
2411 ok_more_than_one_lock();
2413 /* start message re-entrancy test */
2414 hr
= IClassFactory_CreateInstance(proxy
, NULL
, &IID_IUnknown
, (void **)&object
);
2415 ok_ole_success(hr
, IClassFactory_CreateInstance
);
2417 IClassFactory_Release(proxy
);
2421 end_host_object(tid
, thread
);
2423 while (GetMessageA(&msg
, NULL
, 0, 0))
2425 TranslateMessage(&msg
);
2426 DispatchMessageA(&msg
);
2428 DestroyWindow(hwnd_app
);
2431 static void test_WM_QUIT_handling(void)
2435 hwnd_app
= CreateWindowA("WineCOMTest", NULL
, 0, CW_USEDEFAULT
, CW_USEDEFAULT
, CW_USEDEFAULT
, CW_USEDEFAULT
, NULL
, NULL
, NULL
, 0);
2436 ok(hwnd_app
!= NULL
, "Window creation failed\n");
2438 /* start WM_QUIT handling test */
2439 PostMessageA(hwnd_app
, WM_USER
+1, 0, 0);
2441 while (GetMessageA(&msg
, NULL
, 0, 0))
2443 TranslateMessage(&msg
);
2444 DispatchMessageA(&msg
);
2448 static SIZE_T
round_global_size(SIZE_T size
)
2450 static SIZE_T global_size_alignment
= -1;
2451 if (global_size_alignment
== -1)
2453 void *p
= GlobalAlloc(GMEM_FIXED
, 1);
2454 global_size_alignment
= GlobalSize(p
);
2458 return ((size
+ global_size_alignment
- 1) & ~(global_size_alignment
- 1));
2461 static void test_freethreadedmarshaldata(IStream
*pStream
, MSHCTX mshctx
, void *ptr
, DWORD mshlflags
)
2468 hr
= GetHGlobalFromStream(pStream
, &hglobal
);
2469 ok_ole_success(hr
, GetHGlobalFromStream
);
2471 size
= GlobalSize(hglobal
);
2473 marshal_data
= GlobalLock(hglobal
);
2475 if (mshctx
== MSHCTX_INPROC
)
2477 DWORD expected_size
= round_global_size(3*sizeof(DWORD
) + sizeof(GUID
));
2478 ok(size
== expected_size
||
2479 broken(size
== (2*sizeof(DWORD
))) /* Win9x & NT4 */,
2480 "size should have been %d instead of %d\n", expected_size
, size
);
2482 ok(*(DWORD
*)marshal_data
== mshlflags
, "expected 0x%x, but got 0x%x for mshctx\n", mshlflags
, *(DWORD
*)marshal_data
);
2483 marshal_data
+= sizeof(DWORD
);
2484 ok(*(void **)marshal_data
== ptr
, "expected %p, but got %p for mshctx\n", ptr
, *(void **)marshal_data
);
2485 marshal_data
+= sizeof(void *);
2486 if (sizeof(void*) == 4 && size
>= 3*sizeof(DWORD
))
2488 ok(*(DWORD
*)marshal_data
== 0, "expected 0x0, but got 0x%x\n", *(DWORD
*)marshal_data
);
2489 marshal_data
+= sizeof(DWORD
);
2491 if (size
>= 3*sizeof(DWORD
) + sizeof(GUID
))
2493 trace("got guid data: %s\n", wine_dbgstr_guid((GUID
*)marshal_data
));
2498 ok(size
> sizeof(DWORD
), "size should have been > sizeof(DWORD), not %d\n", size
);
2499 ok(*(DWORD
*)marshal_data
== 0x574f454d /* MEOW */,
2500 "marshal data should be filled by standard marshal and start with MEOW signature\n");
2503 GlobalUnlock(hglobal
);
2506 static void test_freethreadedmarshaler(void)
2509 IUnknown
*pFTUnknown
;
2510 IMarshal
*pFTMarshal
;
2513 static const LARGE_INTEGER llZero
;
2516 hr
= CoCreateFreeThreadedMarshaler(NULL
, &pFTUnknown
);
2517 ok_ole_success(hr
, CoCreateFreeThreadedMarshaler
);
2518 hr
= IUnknown_QueryInterface(pFTUnknown
, &IID_IMarshal
, (void **)&pFTMarshal
);
2519 ok_ole_success(hr
, IUnknown_QueryInterface
);
2520 IUnknown_Release(pFTUnknown
);
2522 hr
= CreateStreamOnHGlobal(NULL
, TRUE
, &pStream
);
2523 ok_ole_success(hr
, CreateStreamOnHGlobal
);
2525 /* inproc normal marshaling */
2527 hr
= IMarshal_MarshalInterface(pFTMarshal
, pStream
, &IID_IClassFactory
,
2528 &Test_ClassFactory
, MSHCTX_INPROC
, NULL
, MSHLFLAGS_NORMAL
);
2529 ok_ole_success(hr
, IMarshal_MarshalInterface
);
2531 ok_more_than_one_lock();
2533 test_freethreadedmarshaldata(pStream
, MSHCTX_INPROC
, &Test_ClassFactory
, MSHLFLAGS_NORMAL
);
2535 IStream_Seek(pStream
, llZero
, STREAM_SEEK_SET
, NULL
);
2536 hr
= IMarshal_UnmarshalInterface(pFTMarshal
, pStream
, &IID_IUnknown
, (void **)&pProxy
);
2537 ok_ole_success(hr
, IMarshal_UnmarshalInterface
);
2539 IUnknown_Release(pProxy
);
2543 /* native doesn't allow us to unmarshal or release the stream data,
2544 * presumably because it wants us to call CoMarshalInterface instead */
2547 /* local normal marshaling */
2549 IStream_Seek(pStream
, llZero
, STREAM_SEEK_SET
, NULL
);
2550 hr
= IMarshal_MarshalInterface(pFTMarshal
, pStream
, &IID_IClassFactory
, &Test_ClassFactory
, MSHCTX_LOCAL
, NULL
, MSHLFLAGS_NORMAL
);
2551 ok_ole_success(hr
, IMarshal_MarshalInterface
);
2553 ok_more_than_one_lock();
2555 test_freethreadedmarshaldata(pStream
, MSHCTX_LOCAL
, &Test_ClassFactory
, MSHLFLAGS_NORMAL
);
2557 IStream_Seek(pStream
, llZero
, STREAM_SEEK_SET
, NULL
);
2558 hr
= IMarshal_ReleaseMarshalData(pFTMarshal
, pStream
);
2559 ok_ole_success(hr
, IMarshal_ReleaseMarshalData
);
2564 /* inproc table-strong marshaling */
2566 IStream_Seek(pStream
, llZero
, STREAM_SEEK_SET
, NULL
);
2567 hr
= IMarshal_MarshalInterface(pFTMarshal
, pStream
, &IID_IClassFactory
,
2568 (IUnknown
*)&Test_ClassFactory
, MSHCTX_INPROC
, (void *)0xdeadbeef,
2569 MSHLFLAGS_TABLESTRONG
);
2570 ok_ole_success(hr
, IMarshal_MarshalInterface
);
2572 ok_more_than_one_lock();
2574 test_freethreadedmarshaldata(pStream
, MSHCTX_INPROC
, &Test_ClassFactory
, MSHLFLAGS_TABLESTRONG
);
2576 IStream_Seek(pStream
, llZero
, STREAM_SEEK_SET
, NULL
);
2577 hr
= IMarshal_UnmarshalInterface(pFTMarshal
, pStream
, &IID_IUnknown
, (void **)&pProxy
);
2578 ok_ole_success(hr
, IMarshal_UnmarshalInterface
);
2580 IUnknown_Release(pProxy
);
2582 ok_more_than_one_lock();
2584 IStream_Seek(pStream
, llZero
, STREAM_SEEK_SET
, NULL
);
2585 hr
= IMarshal_ReleaseMarshalData(pFTMarshal
, pStream
);
2586 ok_ole_success(hr
, IMarshal_ReleaseMarshalData
);
2590 /* inproc table-weak marshaling */
2592 IStream_Seek(pStream
, llZero
, STREAM_SEEK_SET
, NULL
);
2593 hr
= IMarshal_MarshalInterface(pFTMarshal
, pStream
, &IID_IClassFactory
,
2594 (IUnknown
*)&Test_ClassFactory
, MSHCTX_INPROC
, (void *)0xdeadbeef,
2595 MSHLFLAGS_TABLEWEAK
);
2596 ok_ole_success(hr
, IMarshal_MarshalInterface
);
2600 test_freethreadedmarshaldata(pStream
, MSHCTX_INPROC
, &Test_ClassFactory
, MSHLFLAGS_TABLEWEAK
);
2602 IStream_Seek(pStream
, llZero
, STREAM_SEEK_SET
, NULL
);
2603 hr
= IMarshal_UnmarshalInterface(pFTMarshal
, pStream
, &IID_IUnknown
, (void **)&pProxy
);
2604 ok_ole_success(hr
, IMarshal_UnmarshalInterface
);
2606 ok_more_than_one_lock();
2608 IUnknown_Release(pProxy
);
2612 /* inproc normal marshaling (for extraordinary cases) */
2614 IStream_Seek(pStream
, llZero
, STREAM_SEEK_SET
, NULL
);
2615 hr
= IMarshal_MarshalInterface(pFTMarshal
, pStream
, &IID_IClassFactory
,
2616 &Test_ClassFactory
, MSHCTX_INPROC
, NULL
, MSHLFLAGS_NORMAL
);
2617 ok_ole_success(hr
, IMarshal_MarshalInterface
);
2619 ok_more_than_one_lock();
2621 /* this call shows that DisconnectObject does nothing */
2622 hr
= IMarshal_DisconnectObject(pFTMarshal
, 0);
2623 ok_ole_success(hr
, IMarshal_DisconnectObject
);
2625 ok_more_than_one_lock();
2627 IStream_Seek(pStream
, llZero
, STREAM_SEEK_SET
, NULL
);
2628 hr
= IMarshal_ReleaseMarshalData(pFTMarshal
, pStream
);
2629 ok_ole_success(hr
, IMarshal_ReleaseMarshalData
);
2633 /* doesn't enforce marshaling rules here and allows us to unmarshal the
2634 * interface, even though it was freed above */
2635 IStream_Seek(pStream
, llZero
, STREAM_SEEK_SET
, NULL
);
2636 hr
= IMarshal_UnmarshalInterface(pFTMarshal
, pStream
, &IID_IUnknown
, (void **)&pProxy
);
2637 ok_ole_success(hr
, IMarshal_UnmarshalInterface
);
2641 IStream_Release(pStream
);
2642 IMarshal_Release(pFTMarshal
);
2645 static HRESULT
reg_unreg_wine_test_class(BOOL Register
)
2651 DWORD dwDisposition
;
2654 hr
= StringFromCLSID(&CLSID_WineTest
, &pszClsid
);
2655 ok_ole_success(hr
, "StringFromCLSID");
2656 strcpy(buffer
, "CLSID\\");
2657 WideCharToMultiByte(CP_ACP
, 0, pszClsid
, -1, buffer
+ strlen(buffer
), sizeof(buffer
) - strlen(buffer
), NULL
, NULL
);
2658 CoTaskMemFree(pszClsid
);
2659 strcat(buffer
, "\\InprocHandler32");
2662 error
= RegCreateKeyExA(HKEY_CLASSES_ROOT
, buffer
, 0, NULL
, 0, KEY_SET_VALUE
, NULL
, &hkey
, &dwDisposition
);
2663 if (error
== ERROR_ACCESS_DENIED
)
2665 skip("Not authorized to modify the Classes key\n");
2668 ok(error
== ERROR_SUCCESS
, "RegCreateKeyEx failed with error %d\n", error
);
2669 if (error
!= ERROR_SUCCESS
) hr
= E_FAIL
;
2670 error
= RegSetValueExA(hkey
, NULL
, 0, REG_SZ
, (const unsigned char *)"\"ole32.dll\"", strlen("\"ole32.dll\"") + 1);
2671 ok(error
== ERROR_SUCCESS
, "RegSetValueEx failed with error %d\n", error
);
2672 if (error
!= ERROR_SUCCESS
) hr
= E_FAIL
;
2677 RegDeleteKeyA(HKEY_CLASSES_ROOT
, buffer
);
2678 *strrchr(buffer
, '\\') = '\0';
2679 RegDeleteKeyA(HKEY_CLASSES_ROOT
, buffer
);
2684 static void test_inproc_handler(void)
2690 if (FAILED(reg_unreg_wine_test_class(TRUE
)))
2693 hr
= CoCreateInstance(&CLSID_WineTest
, NULL
, CLSCTX_INPROC_HANDLER
, &IID_IUnknown
, (void **)&pObject
);
2694 ok_ole_success(hr
, "CoCreateInstance");
2698 hr
= IUnknown_QueryInterface(pObject
, &IID_IWineTest
, (void **)&pObject2
);
2699 ok(hr
== E_NOINTERFACE
, "IUnknown_QueryInterface on handler for invalid interface returned 0x%08x instead of E_NOINTERFACE\n", hr
);
2701 /* it's a handler as it supports IOleObject */
2702 hr
= IUnknown_QueryInterface(pObject
, &IID_IOleObject
, (void **)&pObject2
);
2703 ok_ole_success(hr
, "IUnknown_QueryInterface(&IID_IOleObject)");
2704 IUnknown_Release(pObject2
);
2706 IUnknown_Release(pObject
);
2709 reg_unreg_wine_test_class(FALSE
);
2712 static HRESULT WINAPI
Test_SMI_QueryInterface(
2713 IStdMarshalInfo
*iface
,
2717 if (ppvObj
== NULL
) return E_POINTER
;
2719 if (IsEqualGUID(riid
, &IID_IUnknown
) ||
2720 IsEqualGUID(riid
, &IID_IStdMarshalInfo
))
2723 IStdMarshalInfo_AddRef(iface
);
2727 return E_NOINTERFACE
;
2730 static ULONG WINAPI
Test_SMI_AddRef(IStdMarshalInfo
*iface
)
2733 return 2; /* non-heap-based object */
2736 static ULONG WINAPI
Test_SMI_Release(IStdMarshalInfo
*iface
)
2739 return 1; /* non-heap-based object */
2742 static HRESULT WINAPI
Test_SMI_GetClassForHandler(
2743 IStdMarshalInfo
*iface
,
2744 DWORD dwDestContext
,
2745 void *pvDestContext
,
2748 *pClsid
= CLSID_WineTest
;
2752 static const IStdMarshalInfoVtbl Test_SMI_Vtbl
=
2754 Test_SMI_QueryInterface
,
2757 Test_SMI_GetClassForHandler
2760 static IStdMarshalInfo Test_SMI
= {&Test_SMI_Vtbl
};
2762 static void test_handler_marshaling(void)
2765 IStream
*pStream
= NULL
;
2766 IUnknown
*pProxy
= NULL
;
2770 static const LARGE_INTEGER ullZero
;
2772 if (FAILED(reg_unreg_wine_test_class(TRUE
)))
2776 hr
= CreateStreamOnHGlobal(NULL
, TRUE
, &pStream
);
2777 ok_ole_success(hr
, "CreateStreamOnHGlobal");
2778 tid
= start_host_object(pStream
, &IID_IUnknown
, (IUnknown
*)&Test_SMI
, MSHLFLAGS_NORMAL
, &thread
);
2780 ok_more_than_one_lock();
2782 IStream_Seek(pStream
, ullZero
, STREAM_SEEK_SET
, NULL
);
2783 hr
= CoUnmarshalInterface(pStream
, &IID_IUnknown
, (void **)&pProxy
);
2784 ok_ole_success(hr
, "CoUnmarshalInterface");
2785 IStream_Release(pStream
);
2789 ok_more_than_one_lock();
2791 hr
= IUnknown_QueryInterface(pProxy
, &IID_IWineTest
, (void **)&pObject
);
2792 ok(hr
== E_NOINTERFACE
, "IUnknown_QueryInterface with unknown IID should have returned E_NOINTERFACE instead of 0x%08x\n", hr
);
2794 /* it's a handler as it supports IOleObject */
2795 hr
= IUnknown_QueryInterface(pProxy
, &IID_IOleObject
, (void **)&pObject
);
2797 ok_ole_success(hr
, "IUnknown_QueryInterface(&IID_IOleObject)");
2798 if (SUCCEEDED(hr
)) IUnknown_Release(pObject
);
2800 IUnknown_Release(pProxy
);
2805 end_host_object(tid
, thread
);
2806 reg_unreg_wine_test_class(FALSE
);
2808 /* FIXME: test IPersist interface has the same effect as IStdMarshalInfo */
2812 static void test_client_security(void)
2815 IStream
*pStream
= NULL
;
2816 IClassFactory
*pProxy
= NULL
;
2817 IUnknown
*pProxy2
= NULL
;
2818 IUnknown
*pUnknown1
= NULL
;
2819 IUnknown
*pUnknown2
= NULL
;
2820 IClientSecurity
*pCliSec
= NULL
;
2824 static const LARGE_INTEGER ullZero
;
2827 OLECHAR
*pServerPrincName
;
2831 DWORD dwCapabilities
;
2836 hr
= CreateStreamOnHGlobal(NULL
, TRUE
, &pStream
);
2837 ok_ole_success(hr
, "CreateStreamOnHGlobal");
2838 tid
= start_host_object(pStream
, &IID_IClassFactory
, (IUnknown
*)&Test_ClassFactory
, MSHLFLAGS_NORMAL
, &thread
);
2840 IStream_Seek(pStream
, ullZero
, STREAM_SEEK_SET
, NULL
);
2841 hr
= CoUnmarshalInterface(pStream
, &IID_IClassFactory
, (void **)&pProxy
);
2842 ok_ole_success(hr
, "CoUnmarshalInterface");
2843 IStream_Release(pStream
);
2845 hr
= IClassFactory_QueryInterface(pProxy
, &IID_IUnknown
, (LPVOID
*)&pUnknown1
);
2846 ok_ole_success(hr
, "IUnknown_QueryInterface IID_IUnknown");
2848 hr
= IClassFactory_QueryInterface(pProxy
, &IID_IRemUnknown
, (LPVOID
*)&pProxy2
);
2849 ok_ole_success(hr
, "IUnknown_QueryInterface IID_IStream");
2851 hr
= IUnknown_QueryInterface(pProxy2
, &IID_IUnknown
, (LPVOID
*)&pUnknown2
);
2852 ok_ole_success(hr
, "IUnknown_QueryInterface IID_IUnknown");
2854 ok(pUnknown1
== pUnknown2
, "both proxy's IUnknowns should be the same - %p, %p\n", pUnknown1
, pUnknown2
);
2856 hr
= IClassFactory_QueryInterface(pProxy
, &IID_IMarshal
, (LPVOID
*)&pMarshal
);
2857 ok_ole_success(hr
, "IUnknown_QueryInterface IID_IMarshal");
2859 hr
= IClassFactory_QueryInterface(pProxy
, &IID_IClientSecurity
, (LPVOID
*)&pCliSec
);
2860 ok_ole_success(hr
, "IUnknown_QueryInterface IID_IClientSecurity");
2862 hr
= IClientSecurity_QueryBlanket(pCliSec
, (IUnknown
*)pProxy
, NULL
, NULL
, NULL
, NULL
, NULL
, NULL
, NULL
);
2863 todo_wine
ok_ole_success(hr
, "IClientSecurity_QueryBlanket (all NULLs)");
2865 hr
= IClientSecurity_QueryBlanket(pCliSec
, (IUnknown
*)pMarshal
, NULL
, NULL
, NULL
, NULL
, NULL
, NULL
, NULL
);
2866 todo_wine
ok(hr
== E_NOINTERFACE
, "IClientSecurity_QueryBlanket with local interface should have returned E_NOINTERFACE instead of 0x%08x\n", hr
);
2868 hr
= IClientSecurity_QueryBlanket(pCliSec
, (IUnknown
*)pProxy
, &dwAuthnSvc
, &dwAuthzSvc
, &pServerPrincName
, &dwAuthnLevel
, &dwImpLevel
, &pAuthInfo
, &dwCapabilities
);
2869 todo_wine
ok_ole_success(hr
, "IClientSecurity_QueryBlanket");
2871 hr
= IClientSecurity_SetBlanket(pCliSec
, (IUnknown
*)pProxy
, dwAuthnSvc
, dwAuthzSvc
, pServerPrincName
, dwAuthnLevel
, RPC_C_IMP_LEVEL_IMPERSONATE
, pAuthInfo
, dwCapabilities
);
2872 todo_wine
ok_ole_success(hr
, "IClientSecurity_SetBlanket");
2874 hr
= IClassFactory_CreateInstance(pProxy
, NULL
, &IID_IWineTest
, &pv
);
2875 ok(hr
== E_NOINTERFACE
, "COM call should have succeeded instead of returning 0x%08x\n", hr
);
2877 hr
= IClientSecurity_SetBlanket(pCliSec
, (IUnknown
*)pMarshal
, dwAuthnSvc
, dwAuthzSvc
, pServerPrincName
, dwAuthnLevel
, dwImpLevel
, pAuthInfo
, dwCapabilities
);
2878 todo_wine
ok(hr
== E_NOINTERFACE
, "IClientSecurity_SetBlanket with local interface should have returned E_NOINTERFACE instead of 0x%08x\n", hr
);
2880 hr
= IClientSecurity_SetBlanket(pCliSec
, (IUnknown
*)pProxy
, 0xdeadbeef, dwAuthzSvc
, pServerPrincName
, dwAuthnLevel
, dwImpLevel
, pAuthInfo
, dwCapabilities
);
2881 todo_wine
ok(hr
== E_INVALIDARG
, "IClientSecurity_SetBlanke with invalid dwAuthnSvc should have returned E_INVALIDARG instead of 0x%08x\n", hr
);
2883 CoTaskMemFree(pServerPrincName
);
2885 hr
= IClientSecurity_QueryBlanket(pCliSec
, pUnknown1
, &dwAuthnSvc
, &dwAuthzSvc
, &pServerPrincName
, &dwAuthnLevel
, &dwImpLevel
, &pAuthInfo
, &dwCapabilities
);
2886 todo_wine
ok_ole_success(hr
, "IClientSecurity_QueryBlanket(IUnknown)");
2888 CoTaskMemFree(pServerPrincName
);
2890 IClassFactory_Release(pProxy
);
2891 IUnknown_Release(pProxy2
);
2892 IUnknown_Release(pUnknown1
);
2893 IUnknown_Release(pUnknown2
);
2894 IMarshal_Release(pMarshal
);
2895 IClientSecurity_Release(pCliSec
);
2897 end_host_object(tid
, thread
);
2900 static HANDLE heventShutdown
;
2902 static void LockModuleOOP(void)
2904 InterlockedIncrement(&cLocks
); /* for test purposes only */
2905 CoAddRefServerProcess();
2908 static void UnlockModuleOOP(void)
2910 InterlockedDecrement(&cLocks
); /* for test purposes only */
2911 if (!CoReleaseServerProcess())
2912 SetEvent(heventShutdown
);
2915 static HWND hwnd_app
;
2919 IPersist IPersist_iface
; /* a nice short interface */
2922 static HRESULT WINAPI
local_server_QueryInterface(IPersist
*iface
, REFIID iid
, void **obj
)
2926 if (IsEqualGUID(iid
, &IID_IUnknown
) ||
2927 IsEqualGUID(iid
, &IID_IPersist
))
2932 IPersist_AddRef(iface
);
2935 return E_NOINTERFACE
;
2938 static ULONG WINAPI
local_server_AddRef(IPersist
*iface
)
2943 static ULONG WINAPI
local_server_Release(IPersist
*iface
)
2948 static HRESULT WINAPI
local_server_GetClassID(IPersist
*iface
, CLSID
*clsid
)
2952 *clsid
= IID_IUnknown
;
2954 /* Test calling CoDisconnectObject within a COM call */
2955 hr
= CoDisconnectObject((IUnknown
*)iface
, 0);
2956 ok(hr
== S_OK
, "got %08x\n", hr
);
2958 /* Initialize and uninitialize the apartment to show that we
2959 * remain in the autojoined mta */
2960 hr
= pCoInitializeEx( NULL
, COINIT_MULTITHREADED
);
2961 ok( hr
== S_FALSE
, "got %08x\n", hr
);
2967 static const IPersistVtbl local_server_persist_vtbl
=
2969 local_server_QueryInterface
,
2970 local_server_AddRef
,
2971 local_server_Release
,
2972 local_server_GetClassID
2975 struct local_server local_server_class
=
2977 {&local_server_persist_vtbl
}
2980 static HRESULT WINAPI
TestOOP_IClassFactory_QueryInterface(
2981 LPCLASSFACTORY iface
,
2985 if (ppvObj
== NULL
) return E_POINTER
;
2987 if (IsEqualGUID(riid
, &IID_IUnknown
) ||
2988 IsEqualGUID(riid
, &IID_IClassFactory
))
2991 IClassFactory_AddRef(iface
);
2995 return E_NOINTERFACE
;
2998 static ULONG WINAPI
TestOOP_IClassFactory_AddRef(LPCLASSFACTORY iface
)
3000 return 2; /* non-heap-based object */
3003 static ULONG WINAPI
TestOOP_IClassFactory_Release(LPCLASSFACTORY iface
)
3005 return 1; /* non-heap-based object */
3008 static HRESULT WINAPI
TestOOP_IClassFactory_CreateInstance(
3009 LPCLASSFACTORY iface
,
3010 LPUNKNOWN pUnkOuter
,
3014 IPersist
*persist
= &local_server_class
.IPersist_iface
;
3016 IPersist_AddRef( persist
);
3017 hr
= IPersist_QueryInterface( persist
, riid
, ppvObj
);
3018 IPersist_Release( persist
);
3022 static HRESULT WINAPI
TestOOP_IClassFactory_LockServer(
3023 LPCLASSFACTORY iface
,
3033 static const IClassFactoryVtbl TestClassFactoryOOP_Vtbl
=
3035 TestOOP_IClassFactory_QueryInterface
,
3036 TestOOP_IClassFactory_AddRef
,
3037 TestOOP_IClassFactory_Release
,
3038 TestOOP_IClassFactory_CreateInstance
,
3039 TestOOP_IClassFactory_LockServer
3042 static IClassFactory TestOOP_ClassFactory
= { &TestClassFactoryOOP_Vtbl
};
3044 static void test_register_local_server(void)
3052 heventShutdown
= CreateEventA(NULL
, TRUE
, FALSE
, NULL
);
3053 ready_event
= CreateEventA(NULL
, FALSE
, FALSE
, "Wine COM Test Ready Event");
3054 handles
[0] = CreateEventA(NULL
, FALSE
, FALSE
, "Wine COM Test Quit Event");
3055 handles
[1] = CreateEventA(NULL
, FALSE
, FALSE
, "Wine COM Test Repeat Event");
3058 hr
= CoRegisterClassObject(&CLSID_WineOOPTest
, (IUnknown
*)&TestOOP_ClassFactory
,
3059 CLSCTX_LOCAL_SERVER
, REGCLS_SINGLEUSE
, &cookie
);
3060 ok_ole_success(hr
, CoRegisterClassObject
);
3062 SetEvent(ready_event
);
3066 wait
= MsgWaitForMultipleObjects(2, handles
, FALSE
, 30000, QS_ALLINPUT
);
3067 if (wait
== WAIT_OBJECT_0
+2)
3071 if (PeekMessageA(&msg
, NULL
, 0, 0, PM_REMOVE
))
3073 trace("Message 0x%x\n", msg
.message
);
3074 TranslateMessage(&msg
);
3075 DispatchMessageA(&msg
);
3078 else if (wait
== WAIT_OBJECT_0
+1)
3080 hr
= CoRevokeClassObject(cookie
);
3081 ok_ole_success(hr
, CoRevokeClassObject
);
3085 while (wait
== WAIT_OBJECT_0
+2);
3087 ok( wait
== WAIT_OBJECT_0
, "quit event wait timed out\n" );
3088 hr
= CoRevokeClassObject(cookie
);
3089 ok_ole_success(hr
, CoRevokeClassObject
);
3090 CloseHandle(handles
[0]);
3091 CloseHandle(handles
[1]);
3094 static HANDLE
create_target_process(const char *arg
)
3097 char cmdline
[MAX_PATH
];
3099 PROCESS_INFORMATION pi
;
3100 STARTUPINFOA si
= { 0 };
3105 winetest_get_mainargs( &argv
);
3106 sprintf(cmdline
, "\"%s\" %s %s", argv
[0], argv
[1], arg
);
3107 ret
= CreateProcessA(argv
[0], cmdline
, NULL
, NULL
, FALSE
, 0, NULL
, NULL
, &si
, &pi
);
3108 ok(ret
, "CreateProcess failed with error: %u\n", GetLastError());
3109 if (pi
.hThread
) CloseHandle(pi
.hThread
);
3113 /* tests functions commonly used by out of process COM servers */
3114 static void test_local_server(void)
3124 HANDLE repeat_event
;
3127 heventShutdown
= CreateEventA(NULL
, TRUE
, FALSE
, NULL
);
3131 /* Start the object suspended */
3132 hr
= CoRegisterClassObject(&CLSID_WineOOPTest
, (IUnknown
*)&TestOOP_ClassFactory
,
3133 CLSCTX_LOCAL_SERVER
, REGCLS_MULTIPLEUSE
| REGCLS_SUSPENDED
, &cookie
);
3134 ok_ole_success(hr
, CoRegisterClassObject
);
3136 /* ... and CoGetClassObject does not find it and fails when it looks for the
3137 * class in the registry */
3138 hr
= CoGetClassObject(&CLSID_WineOOPTest
, CLSCTX_INPROC_SERVER
,
3139 NULL
, &IID_IClassFactory
, (LPVOID
*)&cf
);
3140 ok(hr
== REGDB_E_CLASSNOTREG
|| /* NT */
3141 hr
== S_OK
/* Win9x */,
3142 "CoGetClassObject should have returned REGDB_E_CLASSNOTREG instead of 0x%08x\n", hr
);
3144 /* Resume the object suspended above ... */
3145 hr
= CoResumeClassObjects();
3146 ok_ole_success(hr
, CoResumeClassObjects
);
3148 /* ... and now it should succeed */
3149 hr
= CoGetClassObject(&CLSID_WineOOPTest
, CLSCTX_INPROC_SERVER
,
3150 NULL
, &IID_IClassFactory
, (LPVOID
*)&cf
);
3151 ok_ole_success(hr
, CoGetClassObject
);
3153 /* Now check the locking is working */
3154 /* NOTE: we are accessing the class directly, not through a proxy */
3158 hr
= IClassFactory_LockServer(cf
, TRUE
);
3159 ok_ole_success(hr
, IClassFactory_LockServer
);
3161 ok_more_than_one_lock();
3163 IClassFactory_LockServer(cf
, FALSE
);
3164 ok_ole_success(hr
, IClassFactory_LockServer
);
3168 IClassFactory_Release(cf
);
3170 /* wait for shutdown signal */
3171 ret
= WaitForSingleObject(heventShutdown
, 0);
3172 ok(ret
!= WAIT_TIMEOUT
, "Server didn't shut down\n");
3174 /* try to connect again after SCM has suspended registered class objects */
3175 hr
= CoGetClassObject(&CLSID_WineOOPTest
, CLSCTX_INPROC_SERVER
| CLSCTX_LOCAL_SERVER
, NULL
,
3176 &IID_IClassFactory
, (LPVOID
*)&cf
);
3177 ok(hr
== CO_E_SERVER_STOPPING
|| /* NT */
3178 hr
== REGDB_E_CLASSNOTREG
|| /* win2k */
3179 hr
== S_OK
/* Win9x */,
3180 "CoGetClassObject should have returned CO_E_SERVER_STOPPING or REGDB_E_CLASSNOTREG instead of 0x%08x\n", hr
);
3182 hr
= CoRevokeClassObject(cookie
);
3183 ok_ole_success(hr
, CoRevokeClassObject
);
3185 CloseHandle(heventShutdown
);
3187 process
= create_target_process("-Embedding");
3188 ok(process
!= NULL
, "couldn't start local server process, error was %d\n", GetLastError());
3190 ready_event
= CreateEventA(NULL
, FALSE
, FALSE
, "Wine COM Test Ready Event");
3191 ok( !WaitForSingleObject(ready_event
, 10000), "wait timed out\n" );
3193 hr
= CoCreateInstance(&CLSID_WineOOPTest
, NULL
, CLSCTX_LOCAL_SERVER
, &IID_IPersist
, (void **)&persist
);
3194 ok_ole_success(hr
, CoCreateInstance
);
3196 IPersist_Release(persist
);
3198 hr
= CoCreateInstance(&CLSID_WineOOPTest
, NULL
, CLSCTX_LOCAL_SERVER
, &IID_IPersist
, (void **)&persist
);
3199 ok(hr
== REGDB_E_CLASSNOTREG
, "Second CoCreateInstance on REGCLS_SINGLEUSE object should have failed\n");
3201 /* Re-register the class and try calling CoDisconnectObject from within a call to that object */
3202 repeat_event
= CreateEventA(NULL
, FALSE
, FALSE
, "Wine COM Test Repeat Event");
3203 SetEvent(repeat_event
);
3204 CloseHandle(repeat_event
);
3206 ok( !WaitForSingleObject(ready_event
, 10000), "wait timed out\n" );
3207 CloseHandle(ready_event
);
3209 hr
= CoCreateInstance(&CLSID_WineOOPTest
, NULL
, CLSCTX_LOCAL_SERVER
, &IID_IPersist
, (void **)&persist
);
3210 ok_ole_success(hr
, CoCreateInstance
);
3212 /* GetClassID will call CoDisconnectObject */
3213 IPersist_GetClassID(persist
, &clsid
);
3214 IPersist_Release(persist
);
3216 quit_event
= CreateEventA(NULL
, FALSE
, FALSE
, "Wine COM Test Quit Event");
3217 SetEvent(quit_event
);
3219 winetest_wait_child_process( process
);
3220 CloseHandle(quit_event
);
3221 CloseHandle(process
);
3227 IGlobalInterfaceTable
*git
;
3230 static DWORD CALLBACK
get_global_interface_proc(LPVOID pv
)
3233 struct git_params
*params
= pv
;
3236 hr
= IGlobalInterfaceTable_GetInterfaceFromGlobal(params
->git
, params
->cookie
, &IID_IClassFactory
, (void **)&cf
);
3237 ok(hr
== CO_E_NOTINITIALIZED
||
3238 broken(hr
== E_UNEXPECTED
) /* win2k */ ||
3239 broken(hr
== S_OK
) /* NT 4 */,
3240 "IGlobalInterfaceTable_GetInterfaceFromGlobal should have failed with error CO_E_NOTINITIALIZED or E_UNEXPECTED instead of 0x%08x\n",
3243 IClassFactory_Release(cf
);
3247 hr
= IGlobalInterfaceTable_GetInterfaceFromGlobal(params
->git
, params
->cookie
, &IID_IClassFactory
, (void **)&cf
);
3248 ok_ole_success(hr
, IGlobalInterfaceTable_GetInterfaceFromGlobal
);
3250 IClassFactory_Release(cf
);
3257 static void test_globalinterfacetable(void)
3260 IGlobalInterfaceTable
*git
;
3264 struct git_params params
;
3270 trace("test_globalinterfacetable\n");
3273 hr
= pDllGetClassObject(&CLSID_StdGlobalInterfaceTable
, &IID_IClassFactory
, (void**)&cf
);
3274 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3276 hr
= IClassFactory_QueryInterface(cf
, &IID_IGlobalInterfaceTable
, (void**)&object
);
3277 ok(hr
== E_NOINTERFACE
, "got 0x%08x\n", hr
);
3279 IClassFactory_Release(cf
);
3281 hr
= CoCreateInstance(&CLSID_StdGlobalInterfaceTable
, NULL
, CLSCTX_INPROC_SERVER
, &IID_IGlobalInterfaceTable
, (void **)&git
);
3282 ok_ole_success(hr
, CoCreateInstance
);
3284 ref
= IGlobalInterfaceTable_AddRef(git
);
3285 ok(ref
== 1, "ref=%d\n", ref
);
3286 ref
= IGlobalInterfaceTable_AddRef(git
);
3287 ok(ref
== 1, "ref=%d\n", ref
);
3289 ref
= IGlobalInterfaceTable_Release(git
);
3290 ok(ref
== 1, "ref=%d\n", ref
);
3291 ref
= IGlobalInterfaceTable_Release(git
);
3292 ok(ref
== 1, "ref=%d\n", ref
);
3294 hr
= IGlobalInterfaceTable_RegisterInterfaceInGlobal(git
, (IUnknown
*)&Test_ClassFactory
, &IID_IClassFactory
, &cookie
);
3295 ok_ole_success(hr
, IGlobalInterfaceTable_RegisterInterfaceInGlobal
);
3297 ok_more_than_one_lock();
3299 params
.cookie
= cookie
;
3301 /* note: params is on stack so we MUST wait for get_global_interface_proc
3302 * to exit before we can return */
3303 thread
= CreateThread(NULL
, 0, get_global_interface_proc
, ¶ms
, 0, &tid
);
3305 ret
= MsgWaitForMultipleObjects(1, &thread
, FALSE
, 10000, QS_ALLINPUT
);
3306 while (ret
== WAIT_OBJECT_0
+ 1)
3309 while (PeekMessageA(&msg
, NULL
, 0, 0, PM_REMOVE
))
3310 DispatchMessageA(&msg
);
3311 ret
= MsgWaitForMultipleObjects(1, &thread
, FALSE
, 10000, QS_ALLINPUT
);
3314 CloseHandle(thread
);
3316 /* test getting interface from global with different iid */
3317 hr
= IGlobalInterfaceTable_GetInterfaceFromGlobal(git
, cookie
, &IID_IUnknown
, (void **)&object
);
3318 ok_ole_success(hr
, IGlobalInterfaceTable_GetInterfaceFromGlobal
);
3319 IUnknown_Release(object
);
3321 /* test getting interface from global with same iid */
3322 hr
= IGlobalInterfaceTable_GetInterfaceFromGlobal(git
, cookie
, &IID_IClassFactory
, (void **)&object
);
3323 ok_ole_success(hr
, IGlobalInterfaceTable_GetInterfaceFromGlobal
);
3324 IUnknown_Release(object
);
3326 hr
= IGlobalInterfaceTable_RevokeInterfaceFromGlobal(git
, cookie
);
3327 ok_ole_success(hr
, IGlobalInterfaceTable_RevokeInterfaceFromGlobal
);
3331 IGlobalInterfaceTable_Release(git
);
3334 static void test_manualresetevent(void)
3336 ISynchronizeHandle
*sync_handle
;
3337 ISynchronize
*psync1
, *psync2
;
3343 hr
= CoCreateInstance(&CLSID_ManualResetEvent
, NULL
, CLSCTX_INPROC_SERVER
, &IID_IUnknown
, (void**)&punk
);
3344 ok(hr
== S_OK
, "Got 0x%08x\n", hr
);
3345 ok(!!punk
, "Got NULL.\n");
3346 IUnknown_Release(punk
);
3348 hr
= CoCreateInstance(&CLSID_ManualResetEvent
, NULL
, CLSCTX_INPROC_SERVER
, &IID_ISynchronize
, (void**)&psync1
);
3349 ok(hr
== S_OK
, "Got 0x%08x\n", hr
);
3350 ok(!!psync1
, "Got NULL.\n");
3352 hr
= ISynchronize_Wait(psync1
, 0, 5);
3353 ok(hr
== RPC_S_CALLPENDING
, "Got 0x%08x\n", hr
);
3355 hr
= ISynchronize_Reset(psync1
);
3356 ok(hr
== S_OK
, "Got 0x%08x\n", hr
);
3357 hr
= ISynchronize_Signal(psync1
);
3358 ok(hr
== S_OK
, "Got 0x%08x\n", hr
);
3359 hr
= ISynchronize_Wait(psync1
, 0, 5);
3360 ok(hr
== S_OK
, "Got 0x%08x\n", hr
);
3361 hr
= ISynchronize_Wait(psync1
, 0, 5);
3362 ok(hr
== S_OK
, "Got 0x%08x\n", hr
);
3363 hr
= ISynchronize_Reset(psync1
);
3364 ok(hr
== S_OK
, "Got 0x%08x\n", hr
);
3365 hr
= ISynchronize_Wait(psync1
, 0, 5);
3366 ok(hr
== RPC_S_CALLPENDING
, "Got 0x%08x\n", hr
);
3368 hr
= CoCreateInstance(&CLSID_ManualResetEvent
, NULL
, CLSCTX_INPROC_SERVER
, &IID_ISynchronize
, (void**)&psync2
);
3369 ok(hr
== S_OK
, "Got 0x%08x\n", hr
);
3370 ok(!!psync2
, "Got NULL.\n");
3371 ok(psync1
!= psync2
, "psync1 == psync2.\n");
3373 hr
= ISynchronize_QueryInterface(psync2
, &IID_ISynchronizeHandle
, (void**)&sync_handle
);
3374 ok(hr
== S_OK
, "QueryInterface(IID_ISynchronizeHandle) failed: %08x\n", hr
);
3377 hr
= ISynchronizeHandle_GetHandle(sync_handle
, &handle
);
3378 ok(hr
== S_OK
, "GetHandle failed: %08x\n", hr
);
3379 ok(handle
!= NULL
&& handle
!= INVALID_HANDLE_VALUE
, "handle = %p\n", handle
);
3381 ISynchronizeHandle_Release(sync_handle
);
3383 hr
= ISynchronize_Wait(psync2
, 0, 5);
3384 ok(hr
== RPC_S_CALLPENDING
, "Got 0x%08x\n", hr
);
3386 hr
= ISynchronize_Reset(psync1
);
3387 ok(hr
== S_OK
, "Got 0x%08x\n", hr
);
3388 hr
= ISynchronize_Reset(psync2
);
3389 ok(hr
== S_OK
, "Got 0x%08x\n", hr
);
3390 hr
= ISynchronize_Signal(psync1
);
3391 ok(hr
== S_OK
, "Got 0x%08x\n", hr
);
3392 hr
= ISynchronize_Wait(psync2
, 0, 5);
3393 ok(hr
== RPC_S_CALLPENDING
, "Got 0x%08x\n", hr
);
3395 ref
= ISynchronize_AddRef(psync1
);
3396 ok(ref
== 2, "Got ref: %d\n", ref
);
3397 ref
= ISynchronize_AddRef(psync1
);
3398 ok(ref
== 3, "Got ref: %d\n", ref
);
3399 ref
= ISynchronize_Release(psync1
);
3400 ok(ref
== 2, "Got nonzero ref: %d\n", ref
);
3401 ref
= ISynchronize_Release(psync2
);
3402 ok(!ref
, "Got nonzero ref: %d\n", ref
);
3403 ref
= ISynchronize_Release(psync1
);
3404 ok(ref
== 1, "Got nonzero ref: %d\n", ref
);
3405 ref
= ISynchronize_Release(psync1
);
3406 ok(!ref
, "Got nonzero ref: %d\n", ref
);
3409 static const char *debugstr_iid(REFIID riid
)
3411 static char name
[256];
3415 LONG name_size
= sizeof(name
);
3416 StringFromGUID2(riid
, bufferW
, sizeof(bufferW
)/sizeof(bufferW
[0]));
3417 WideCharToMultiByte(CP_ACP
, 0, bufferW
, sizeof(bufferW
)/sizeof(bufferW
[0]), buffer
, sizeof(buffer
), NULL
, NULL
);
3418 if (RegOpenKeyExA(HKEY_CLASSES_ROOT
, "Interface", 0, KEY_QUERY_VALUE
, &hkeyInterface
) != ERROR_SUCCESS
)
3420 memcpy(name
, buffer
, sizeof(buffer
));
3423 if (RegQueryValueA(hkeyInterface
, buffer
, name
, &name_size
) != ERROR_SUCCESS
)
3425 memcpy(name
, buffer
, sizeof(buffer
));
3428 RegCloseKey(hkeyInterface
);
3433 static HRESULT WINAPI
TestChannelHook_QueryInterface(IChannelHook
*iface
, REFIID riid
, void **ppv
)
3435 if (IsEqualIID(riid
, &IID_IUnknown
) || IsEqualIID(riid
, &IID_IChannelHook
))
3438 IChannelHook_AddRef(iface
);
3443 return E_NOINTERFACE
;
3446 static ULONG WINAPI
TestChannelHook_AddRef(IChannelHook
*iface
)
3451 static ULONG WINAPI
TestChannelHook_Release(IChannelHook
*iface
)
3456 static BOOL new_hook_struct
;
3457 static int method
, server_tid
;
3458 static GUID causality
;
3460 struct new_hook_info
3469 static void WINAPI
TestChannelHook_ClientGetSize(
3470 IChannelHook
*iface
,
3475 SChannelHookCallInfo
*info
= (SChannelHookCallInfo
*)riid
;
3476 trace("TestChannelHook_ClientGetSize\n");
3477 trace("\t%s\n", debugstr_iid(riid
));
3478 if (info
->cbSize
!= sizeof(*info
))
3479 new_hook_struct
= TRUE
;
3481 if (!new_hook_struct
)
3483 ok(info
->cbSize
== sizeof(*info
), "cbSize was %d instead of %d\n", info
->cbSize
, (int)sizeof(*info
));
3484 ok(info
->dwServerPid
== GetCurrentProcessId(), "dwServerPid was 0x%x instead of 0x%x\n", info
->dwServerPid
, GetCurrentProcessId());
3485 ok(info
->iMethod
== method
, "iMethod was %d should be %d\n", info
->iMethod
, method
);
3486 ok(!info
->pObject
, "pObject should be NULL\n");
3488 causality
= info
->uCausality
;
3490 ok(IsEqualGUID(&info
->uCausality
, &causality
), "causality wasn't correct\n");
3494 struct new_hook_info
*new_info
= (struct new_hook_info
*)riid
;
3495 ok(new_info
->server_pid
== GetCurrentProcessId(), "server pid was 0x%x instead of 0x%x\n", new_info
->server_pid
,
3496 GetCurrentProcessId());
3497 ok(new_info
->server_tid
== server_tid
, "server tid was 0x%x instead of 0x%x\n", new_info
->server_tid
,
3499 ok(new_info
->method
== method
, "method was %d instead of %d\n", new_info
->method
, method
);
3501 causality
= new_info
->causality
;
3503 ok(IsEqualGUID(&new_info
->causality
, &causality
), "causality wasn't correct\n");
3506 ok(IsEqualGUID(uExtent
, &EXTENTID_WineTest
), "uExtent wasn't correct\n");
3511 static void WINAPI
TestChannelHook_ClientFillBuffer(
3512 IChannelHook
*iface
,
3518 SChannelHookCallInfo
*info
= (SChannelHookCallInfo
*)riid
;
3519 trace("TestChannelHook_ClientFillBuffer\n");
3521 if (!new_hook_struct
)
3523 ok(info
->cbSize
== sizeof(*info
), "cbSize was %d instead of %d\n", info
->cbSize
, (int)sizeof(*info
));
3524 ok(info
->dwServerPid
== GetCurrentProcessId(), "dwServerPid was 0x%x instead of 0x%x\n", info
->dwServerPid
, GetCurrentProcessId());
3525 ok(info
->iMethod
== method
, "iMethod was %d should be %d\n", info
->iMethod
, method
);
3526 ok(!info
->pObject
, "pObject should be NULL\n");
3527 ok(IsEqualGUID(&info
->uCausality
, &causality
), "causality wasn't correct\n");
3531 struct new_hook_info
*new_info
= (struct new_hook_info
*)riid
;
3532 ok(new_info
->server_pid
== GetCurrentProcessId(), "server pid was 0x%x instead of 0x%x\n", new_info
->server_pid
,
3533 GetCurrentProcessId());
3534 ok(new_info
->server_tid
== server_tid
, "server tid was 0x%x instead of 0x%x\n", new_info
->server_tid
,
3536 ok(new_info
->method
== method
, "method was %d instead of %d\n", new_info
->method
, method
);
3537 ok(IsEqualGUID(&new_info
->causality
, &causality
), "causality wasn't correct\n");
3540 ok(IsEqualGUID(uExtent
, &EXTENTID_WineTest
), "uExtent wasn't correct\n");
3542 *(unsigned char *)pDataBuffer
= 0xcc;
3546 static void WINAPI
TestChannelHook_ClientNotify(
3547 IChannelHook
*iface
,
3555 SChannelHookCallInfo
*info
= (SChannelHookCallInfo
*)riid
;
3556 trace("TestChannelHook_ClientNotify hrFault = 0x%08x\n", hrFault
);
3558 if (!new_hook_struct
)
3560 ok(info
->cbSize
== sizeof(*info
), "cbSize was %d instead of %d\n", info
->cbSize
, (int)sizeof(*info
));
3561 ok(info
->dwServerPid
== GetCurrentProcessId(), "dwServerPid was 0x%x instead of 0x%x\n", info
->dwServerPid
, GetCurrentProcessId());
3562 ok(info
->iMethod
== method
, "iMethod was %d should be %d\n", info
->iMethod
, method
);
3564 ok(info
->pObject
!= NULL
, "pObject shouldn't be NULL\n");
3566 ok(IsEqualGUID(&info
->uCausality
, &causality
), "causality wasn't correct\n");
3570 struct new_hook_info
*new_info
= (struct new_hook_info
*)riid
;
3571 ok(new_info
->server_pid
== GetCurrentProcessId(), "server pid was 0x%x instead of 0x%x\n", new_info
->server_pid
,
3572 GetCurrentProcessId());
3573 ok(new_info
->server_tid
== server_tid
, "server tid was 0x%x instead of 0x%x\n", new_info
->server_tid
,
3575 ok(new_info
->method
== method
, "method was %d instead of %d\n", new_info
->method
, method
);
3576 ok(IsEqualGUID(&new_info
->causality
, &causality
), "causality wasn't correct\n");
3579 ok(IsEqualGUID(uExtent
, &EXTENTID_WineTest
), "uExtent wasn't correct\n");
3582 static void WINAPI
TestChannelHook_ServerNotify(
3583 IChannelHook
*iface
,
3590 SChannelHookCallInfo
*info
= (SChannelHookCallInfo
*)riid
;
3591 trace("TestChannelHook_ServerNotify\n");
3593 if (!new_hook_struct
)
3595 ok(info
->cbSize
== sizeof(*info
), "cbSize was %d instead of %d\n", info
->cbSize
, (int)sizeof(*info
));
3596 ok(info
->dwServerPid
== GetCurrentProcessId(), "dwServerPid was 0x%x instead of 0x%x\n", info
->dwServerPid
, GetCurrentProcessId());
3597 ok(info
->iMethod
== method
, "iMethod was %d should be %d\n", info
->iMethod
, method
);
3598 ok(info
->pObject
!= NULL
, "pObject shouldn't be NULL\n");
3599 ok(IsEqualGUID(&info
->uCausality
, &causality
), "causality wasn't correct\n");
3603 struct new_hook_info
*new_info
= (struct new_hook_info
*)riid
;
3604 ok(new_info
->server_pid
== GetCurrentProcessId(), "server pid was 0x%x instead of 0x%x\n", new_info
->server_pid
,
3605 GetCurrentProcessId());
3606 ok(new_info
->server_tid
== server_tid
, "server tid was 0x%x instead of 0x%x\n", new_info
->server_tid
,
3608 ok(new_info
->method
== method
, "method was %d instead of %d\n", new_info
->method
, method
);
3609 ok(IsEqualGUID(&new_info
->causality
, &causality
), "causality wasn't correct\n");
3612 ok(cbDataSize
== 1, "cbDataSize should have been 1 instead of %d\n", cbDataSize
);
3613 ok(*(unsigned char *)pDataBuffer
== 0xcc, "pDataBuffer should have contained 0xcc instead of 0x%x\n", *(unsigned char *)pDataBuffer
);
3614 ok(IsEqualGUID(uExtent
, &EXTENTID_WineTest
), "uExtent wasn't correct\n");
3617 static void WINAPI
TestChannelHook_ServerGetSize(
3618 IChannelHook
*iface
,
3624 SChannelHookCallInfo
*info
= (SChannelHookCallInfo
*)riid
;
3625 trace("TestChannelHook_ServerGetSize\n");
3626 trace("\t%s\n", debugstr_iid(riid
));
3627 if (!new_hook_struct
)
3629 ok(info
->cbSize
== sizeof(*info
), "cbSize was %d instead of %d\n", info
->cbSize
, (int)sizeof(*info
));
3630 ok(info
->dwServerPid
== GetCurrentProcessId(), "dwServerPid was 0x%x instead of 0x%x\n", info
->dwServerPid
, GetCurrentProcessId());
3631 ok(info
->iMethod
== method
, "iMethod was %d should be %d\n", info
->iMethod
, method
);
3632 ok(info
->pObject
!= NULL
, "pObject shouldn't be NULL\n");
3633 ok(IsEqualGUID(&info
->uCausality
, &causality
), "causality wasn't correct\n");
3637 struct new_hook_info
*new_info
= (struct new_hook_info
*)riid
;
3638 ok(new_info
->server_pid
== GetCurrentProcessId(), "server pid was 0x%x instead of 0x%x\n", new_info
->server_pid
,
3639 GetCurrentProcessId());
3640 ok(new_info
->server_tid
== server_tid
, "server tid was 0x%x instead of 0x%x\n", new_info
->server_tid
,
3642 ok(new_info
->method
== method
, "method was %d instead of %d\n", new_info
->method
, method
);
3643 ok(IsEqualGUID(&new_info
->causality
, &causality
), "causality wasn't correct\n");
3646 ok(IsEqualGUID(uExtent
, &EXTENTID_WineTest
), "uExtent wasn't correct\n");
3647 if (hrFault
!= S_OK
)
3648 trace("\thrFault = 0x%08x\n", hrFault
);
3653 static void WINAPI
TestChannelHook_ServerFillBuffer(
3654 IChannelHook
*iface
,
3661 trace("TestChannelHook_ServerFillBuffer\n");
3662 ok(0, "TestChannelHook_ServerFillBuffer shouldn't be called\n");
3665 static const IChannelHookVtbl TestChannelHookVtbl
=
3667 TestChannelHook_QueryInterface
,
3668 TestChannelHook_AddRef
,
3669 TestChannelHook_Release
,
3670 TestChannelHook_ClientGetSize
,
3671 TestChannelHook_ClientFillBuffer
,
3672 TestChannelHook_ClientNotify
,
3673 TestChannelHook_ServerNotify
,
3674 TestChannelHook_ServerGetSize
,
3675 TestChannelHook_ServerFillBuffer
,
3678 static IChannelHook TestChannelHook
= { &TestChannelHookVtbl
};
3680 static void test_channel_hook(void)
3682 IStream
*pStream
= NULL
;
3683 IClassFactory
*cf
= NULL
;
3685 IUnknown
*proxy
= NULL
;
3689 hr
= CoRegisterChannelHook(&EXTENTID_WineTest
, &TestChannelHook
);
3690 ok_ole_success(hr
, CoRegisterChannelHook
);
3692 hr
= CoRegisterMessageFilter(&MessageFilter
, NULL
);
3693 ok_ole_success(hr
, CoRegisterMessageFilter
);
3697 hr
= CreateStreamOnHGlobal(NULL
, TRUE
, &pStream
);
3698 ok_ole_success(hr
, CreateStreamOnHGlobal
);
3699 tid
= start_host_object2(pStream
, &IID_IClassFactory
, (IUnknown
*)&Test_ClassFactory
, MSHLFLAGS_NORMAL
, &MessageFilter
, &thread
);
3702 ok_more_than_one_lock();
3704 IStream_Seek(pStream
, ullZero
, STREAM_SEEK_SET
, NULL
);
3705 hr
= CoUnmarshalInterface(pStream
, &IID_IClassFactory
, (void **)&cf
);
3706 ok_ole_success(hr
, CoUnmarshalInterface
);
3707 IStream_Release(pStream
);
3709 ok_more_than_one_lock();
3712 hr
= IClassFactory_CreateInstance(cf
, NULL
, &IID_IUnknown
, (LPVOID
*)&proxy
);
3713 ok_ole_success(hr
, IClassFactory_CreateInstance
);
3716 IUnknown_Release(proxy
);
3718 IClassFactory_Release(cf
);
3722 end_host_object(tid
, thread
);
3724 hr
= CoRegisterMessageFilter(NULL
, NULL
);
3725 ok_ole_success(hr
, CoRegisterMessageFilter
);
3730 HMODULE hOle32
= GetModuleHandleA("ole32");
3734 if (!GetProcAddress(hOle32
, "CoRegisterSurrogateEx")) {
3735 win_skip("skipping test on win9x\n");
3739 pCoInitializeEx
= (void*)GetProcAddress(hOle32
, "CoInitializeEx");
3740 pDllGetClassObject
= (void*)GetProcAddress(hOle32
, "DllGetClassObject");
3742 argc
= winetest_get_mainargs( &argv
);
3743 if (argc
> 2 && (!strcmp(argv
[2], "-Embedding")))
3745 pCoInitializeEx(NULL
, COINIT_MULTITHREADED
);
3746 test_register_local_server();
3752 register_test_window();
3754 test_cocreateinstance_proxy();
3756 pCoInitializeEx(NULL
, COINIT_APARTMENTTHREADED
);
3758 /* FIXME: test CoCreateInstanceEx */
3760 /* lifecycle management and marshaling tests */
3763 test_no_marshaler();
3764 test_normal_marshal_and_release();
3765 test_normal_marshal_and_unmarshal();
3766 test_marshal_and_unmarshal_invalid();
3767 test_same_apartment_unmarshal_failure();
3768 test_interthread_marshal_and_unmarshal();
3769 test_proxy_marshal_and_unmarshal();
3770 test_proxy_marshal_and_unmarshal2();
3771 test_proxy_marshal_and_unmarshal_weak();
3772 test_proxy_marshal_and_unmarshal_strong();
3773 test_marshal_stub_apartment_shutdown();
3774 test_marshal_proxy_apartment_shutdown();
3775 test_marshal_proxy_mta_apartment_shutdown();
3776 test_no_couninitialize_server();
3777 test_no_couninitialize_client();
3778 test_tableweak_marshal_and_unmarshal_twice();
3779 test_tableweak_marshal_releasedata1();
3780 test_tableweak_marshal_releasedata2();
3781 test_tableweak_and_normal_marshal_and_unmarshal();
3782 test_tableweak_and_normal_marshal_and_releasedata();
3783 test_two_tableweak_marshal_and_releasedata();
3784 test_tablestrong_marshal_and_unmarshal_twice();
3785 test_lock_object_external();
3786 test_disconnect_stub();
3787 test_normal_marshal_and_unmarshal_twice();
3789 with_external_conn
= !with_external_conn
;
3790 } while (with_external_conn
);
3792 test_hresult_marshaling();
3793 test_proxy_used_in_wrong_thread();
3794 test_message_filter();
3795 test_bad_marshal_stream();
3796 test_proxy_interfaces();
3797 test_stubbuffer(&IID_IClassFactory
);
3798 test_proxybuffer(&IID_IClassFactory
);
3799 test_message_reentrancy();
3800 test_call_from_message();
3801 test_WM_QUIT_handling();
3802 test_freethreadedmarshaler();
3803 test_inproc_handler();
3804 test_handler_marshaling();
3805 test_client_security();
3807 test_local_server();
3809 test_globalinterfacetable();
3810 test_manualresetevent();
3811 test_crash_couninitialize();
3813 /* must be last test as channel hooks can't be unregistered */
3814 test_channel_hook();