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
36 #include "wine/test.h"
38 DEFINE_GUID(CLSID_StdGlobalInterfaceTable
,0x00000323,0x0000,0x0000,0xc0,0x00,0x00,0x00,0x00,0x00,0x00,0x46);
39 DEFINE_GUID(CLSID_ManualResetEvent
, 0x0000032c,0x0000,0x0000,0xc0,0x00,0x00,0x00,0x00,0x00,0x00,0x46);
41 /* functions that are not present on all versions of Windows */
42 static HRESULT (WINAPI
* pCoInitializeEx
)(LPVOID lpReserved
, DWORD dwCoInit
);
43 static HRESULT (WINAPI
*pDllGetClassObject
)(REFCLSID
,REFIID
,LPVOID
);
45 /* helper macros to make tests a bit leaner */
46 #define ok_more_than_one_lock() ok(cLocks > 0, "Number of locks should be > 0, but actually is %d\n", cLocks)
47 #define ok_no_locks() ok(cLocks == 0, "Number of locks should be 0, but actually is %d\n", cLocks)
48 #define ok_ole_success(hr, func) ok(hr == S_OK, #func " failed with error 0x%08x\n", hr)
49 #define ok_non_zero_external_conn() do {if (with_external_conn) ok(external_connections, "got no external connections\n");} while(0);
50 #define ok_zero_external_conn() do {if (with_external_conn) ok(!external_connections, "got %d external connections\n", external_connections);} while(0);
51 #define ok_last_release_closes(b) do {if (with_external_conn) ok(last_release_closes == b, "got %d expected %d\n", last_release_closes, b);} while(0);
53 static const IID IID_IWineTest
=
58 {0xa1, 0xa2, 0x5d, 0x5a, 0x36, 0x54, 0xd3, 0xbd}
59 }; /* 5201163f-8164-4fd0-a1a2-5d5a3654d3bd */
61 static const IID IID_IRemUnknown
=
66 {0xc0,0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46}
69 #define EXTENTID_WineTest IID_IWineTest
70 #define CLSID_WineTest IID_IWineTest
72 static const CLSID CLSID_WineOOPTest
=
77 {0xa1, 0xa2, 0x5d, 0x5a, 0x36, 0x54, 0xd3, 0xbd}
78 }; /* 5201163f-8164-4fd0-a1a2-5d5a3654d3bd */
80 static void test_cocreateinstance_proxy(void)
86 pCoInitializeEx(NULL
, COINIT_MULTITHREADED
);
88 hr
= CoCreateInstance(&CLSID_ShellDesktop
, NULL
, CLSCTX_INPROC
, &IID_IUnknown
, (void **)&pProxy
);
89 ok_ole_success(hr
, CoCreateInstance
);
90 hr
= IUnknown_QueryInterface(pProxy
, &IID_IMultiQI
, (void **)&pMQI
);
91 ok(hr
== S_OK
, "created object is not a proxy, so was created in the wrong apartment\n");
93 IMultiQI_Release(pMQI
);
94 IUnknown_Release(pProxy
);
99 static const LARGE_INTEGER ullZero
;
102 static void LockModule(void)
104 InterlockedIncrement(&cLocks
);
107 static void UnlockModule(void)
109 InterlockedDecrement(&cLocks
);
112 static BOOL with_external_conn
;
113 static DWORD external_connections
;
114 static BOOL last_release_closes
;
116 static HRESULT WINAPI
ExternalConnection_QueryInterface(IExternalConnection
*iface
, REFIID riid
, void **ppv
)
118 ok(0, "unexpected call\n");
120 return E_NOINTERFACE
;
123 static ULONG WINAPI
ExternalConnection_AddRef(IExternalConnection
*iface
)
128 static ULONG WINAPI
ExternalConnection_Release(IExternalConnection
*iface
)
133 static DWORD WINAPI
ExternalConnection_AddConnection(IExternalConnection
*iface
, DWORD extconn
, DWORD reserved
)
135 trace("add connection\n");
136 return ++external_connections
;
140 static DWORD WINAPI
ExternalConnection_ReleaseConnection(IExternalConnection
*iface
, DWORD extconn
,
141 DWORD reserved
, BOOL fLastReleaseCloses
)
143 trace("release connection %d\n", fLastReleaseCloses
);
144 last_release_closes
= fLastReleaseCloses
;
145 return --external_connections
;
148 static const IExternalConnectionVtbl ExternalConnectionVtbl
= {
149 ExternalConnection_QueryInterface
,
150 ExternalConnection_AddRef
,
151 ExternalConnection_Release
,
152 ExternalConnection_AddConnection
,
153 ExternalConnection_ReleaseConnection
156 static IExternalConnection ExternalConnection
= { &ExternalConnectionVtbl
};
159 static HRESULT WINAPI
Test_IUnknown_QueryInterface(
164 if (ppvObj
== NULL
) return E_POINTER
;
166 if (IsEqualGUID(riid
, &IID_IUnknown
))
169 IUnknown_AddRef(iface
);
174 return E_NOINTERFACE
;
177 static ULONG WINAPI
Test_IUnknown_AddRef(LPUNKNOWN iface
)
180 return 2; /* non-heap-based object */
183 static ULONG WINAPI
Test_IUnknown_Release(LPUNKNOWN iface
)
186 return 1; /* non-heap-based object */
189 static const IUnknownVtbl TestUnknown_Vtbl
=
191 Test_IUnknown_QueryInterface
,
192 Test_IUnknown_AddRef
,
193 Test_IUnknown_Release
,
196 static IUnknown Test_Unknown
= { &TestUnknown_Vtbl
};
198 static ULONG WINAPI
TestCrash_IUnknown_Release(LPUNKNOWN iface
)
202 trace("crashing...\n");
205 return 1; /* non-heap-based object */
208 static const IUnknownVtbl TestCrashUnknown_Vtbl
=
210 Test_IUnknown_QueryInterface
,
211 Test_IUnknown_AddRef
,
212 TestCrash_IUnknown_Release
,
215 static IUnknown TestCrash_Unknown
= { &TestCrashUnknown_Vtbl
};
217 static HRESULT WINAPI
Test_IClassFactory_QueryInterface(
218 LPCLASSFACTORY iface
,
222 if (ppvObj
== NULL
) return E_POINTER
;
224 if (IsEqualGUID(riid
, &IID_IUnknown
) ||
225 IsEqualGUID(riid
, &IID_IClassFactory
) ||
226 /* the only other interface Wine is currently able to marshal (for testing two proxies) */
227 IsEqualGUID(riid
, &IID_IRemUnknown
))
230 IClassFactory_AddRef(iface
);
234 if (with_external_conn
&& IsEqualGUID(riid
, &IID_IExternalConnection
))
236 *ppvObj
= &ExternalConnection
;
241 return E_NOINTERFACE
;
244 static ULONG WINAPI
Test_IClassFactory_AddRef(LPCLASSFACTORY iface
)
247 return 2; /* non-heap-based object */
250 static ULONG WINAPI
Test_IClassFactory_Release(LPCLASSFACTORY iface
)
253 return 1; /* non-heap-based object */
256 static HRESULT WINAPI
Test_IClassFactory_CreateInstance(
257 LPCLASSFACTORY iface
,
262 if (pUnkOuter
) return CLASS_E_NOAGGREGATION
;
263 return IUnknown_QueryInterface((IUnknown
*)&Test_Unknown
, riid
, ppvObj
);
266 static HRESULT WINAPI
Test_IClassFactory_LockServer(
267 LPCLASSFACTORY iface
,
273 static const IClassFactoryVtbl TestClassFactory_Vtbl
=
275 Test_IClassFactory_QueryInterface
,
276 Test_IClassFactory_AddRef
,
277 Test_IClassFactory_Release
,
278 Test_IClassFactory_CreateInstance
,
279 Test_IClassFactory_LockServer
282 static IClassFactory Test_ClassFactory
= { &TestClassFactory_Vtbl
};
284 #define RELEASEMARSHALDATA WM_USER
286 struct host_object_data
291 MSHLFLAGS marshal_flags
;
292 HANDLE marshal_event
;
293 IMessageFilter
*filter
;
296 static DWORD CALLBACK
host_object_proc(LPVOID p
)
298 struct host_object_data
*data
= p
;
302 pCoInitializeEx(NULL
, COINIT_APARTMENTTHREADED
);
306 IMessageFilter
* prev_filter
= NULL
;
307 hr
= CoRegisterMessageFilter(data
->filter
, &prev_filter
);
308 if (prev_filter
) IMessageFilter_Release(prev_filter
);
309 ok_ole_success(hr
, CoRegisterMessageFilter
);
312 hr
= CoMarshalInterface(data
->stream
, &data
->iid
, data
->object
, MSHCTX_INPROC
, NULL
, data
->marshal_flags
);
313 ok_ole_success(hr
, CoMarshalInterface
);
315 /* force the message queue to be created before signaling parent thread */
316 PeekMessageA(&msg
, NULL
, WM_USER
, WM_USER
, PM_NOREMOVE
);
318 SetEvent(data
->marshal_event
);
320 while (GetMessageA(&msg
, NULL
, 0, 0))
322 if (msg
.hwnd
== NULL
&& msg
.message
== RELEASEMARSHALDATA
)
324 CoReleaseMarshalData(data
->stream
);
325 SetEvent((HANDLE
)msg
.lParam
);
328 DispatchMessageA(&msg
);
331 HeapFree(GetProcessHeap(), 0, data
);
338 static DWORD
start_host_object2(IStream
*stream
, REFIID riid
, IUnknown
*object
, MSHLFLAGS marshal_flags
, IMessageFilter
*filter
, HANDLE
*thread
)
341 HANDLE marshal_event
= CreateEventA(NULL
, FALSE
, FALSE
, NULL
);
342 struct host_object_data
*data
= HeapAlloc(GetProcessHeap(), 0, sizeof(*data
));
344 data
->stream
= stream
;
346 data
->object
= object
;
347 data
->marshal_flags
= marshal_flags
;
348 data
->marshal_event
= marshal_event
;
349 data
->filter
= filter
;
351 *thread
= CreateThread(NULL
, 0, host_object_proc
, data
, 0, &tid
);
353 /* wait for marshaling to complete before returning */
354 ok( !WaitForSingleObject(marshal_event
, 10000), "wait timed out\n" );
355 CloseHandle(marshal_event
);
360 static DWORD
start_host_object(IStream
*stream
, REFIID riid
, IUnknown
*object
, MSHLFLAGS marshal_flags
, HANDLE
*thread
)
362 return start_host_object2(stream
, riid
, object
, marshal_flags
, NULL
, thread
);
365 /* asks thread to release the marshal data because it has to be done by the
366 * same thread that marshaled the interface in the first place. */
367 static void release_host_object(DWORD tid
, WPARAM wp
)
369 HANDLE event
= CreateEventA(NULL
, FALSE
, FALSE
, NULL
);
370 PostThreadMessageA(tid
, RELEASEMARSHALDATA
, wp
, (LPARAM
)event
);
371 ok( !WaitForSingleObject(event
, 10000), "wait timed out\n" );
375 static void end_host_object(DWORD tid
, HANDLE thread
)
377 BOOL ret
= PostThreadMessageA(tid
, WM_QUIT
, 0, 0);
378 ok(ret
, "PostThreadMessage failed with error %d\n", GetLastError());
379 /* be careful of races - don't return until hosting thread has terminated */
380 ok( !WaitForSingleObject(thread
, 10000), "wait timed out\n" );
384 /* tests failure case of interface not having a marshaler specified in the
386 static void test_no_marshaler(void)
391 hr
= CreateStreamOnHGlobal(NULL
, TRUE
, &pStream
);
392 ok_ole_success(hr
, CreateStreamOnHGlobal
);
393 hr
= CoMarshalInterface(pStream
, &IID_IWineTest
, (IUnknown
*)&Test_ClassFactory
, MSHCTX_INPROC
, NULL
, MSHLFLAGS_NORMAL
);
394 ok(hr
== E_NOINTERFACE
, "CoMarshalInterface should have returned E_NOINTERFACE instead of 0x%08x\n", hr
);
396 IStream_Release(pStream
);
399 /* tests normal marshal and then release without unmarshaling */
400 static void test_normal_marshal_and_release(void)
403 IStream
*pStream
= NULL
;
406 external_connections
= 0;
408 hr
= CreateStreamOnHGlobal(NULL
, TRUE
, &pStream
);
409 ok_ole_success(hr
, CreateStreamOnHGlobal
);
410 hr
= CoMarshalInterface(pStream
, &IID_IClassFactory
, (IUnknown
*)&Test_ClassFactory
, MSHCTX_INPROC
, NULL
, MSHLFLAGS_NORMAL
);
411 ok_ole_success(hr
, CoMarshalInterface
);
413 ok_more_than_one_lock();
414 ok_non_zero_external_conn();
416 IStream_Seek(pStream
, ullZero
, STREAM_SEEK_SET
, NULL
);
417 hr
= CoReleaseMarshalData(pStream
);
418 ok_ole_success(hr
, CoReleaseMarshalData
);
419 IStream_Release(pStream
);
422 ok_zero_external_conn();
423 ok_last_release_closes(TRUE
);
426 /* tests success case of a same-thread marshal and unmarshal */
427 static void test_normal_marshal_and_unmarshal(void)
430 IStream
*pStream
= NULL
;
431 IUnknown
*pProxy
= NULL
;
434 external_connections
= 0;
436 hr
= CreateStreamOnHGlobal(NULL
, TRUE
, &pStream
);
437 ok_ole_success(hr
, CreateStreamOnHGlobal
);
438 hr
= CoMarshalInterface(pStream
, &IID_IClassFactory
, (IUnknown
*)&Test_ClassFactory
, MSHCTX_INPROC
, NULL
, MSHLFLAGS_NORMAL
);
439 ok_ole_success(hr
, CoMarshalInterface
);
441 ok_more_than_one_lock();
442 ok_non_zero_external_conn();
444 IStream_Seek(pStream
, ullZero
, STREAM_SEEK_SET
, NULL
);
445 hr
= CoUnmarshalInterface(pStream
, &IID_IClassFactory
, (void **)&pProxy
);
446 ok_ole_success(hr
, CoUnmarshalInterface
);
447 IStream_Release(pStream
);
449 ok_more_than_one_lock();
450 ok_zero_external_conn();
451 ok_last_release_closes(FALSE
);
453 IUnknown_Release(pProxy
);
458 /* tests failure case of unmarshaling a freed object */
459 static void test_marshal_and_unmarshal_invalid(void)
462 IStream
*pStream
= NULL
;
463 IClassFactory
*pProxy
= NULL
;
469 external_connections
= 0;
471 hr
= CreateStreamOnHGlobal(NULL
, TRUE
, &pStream
);
472 ok_ole_success(hr
, CreateStreamOnHGlobal
);
473 tid
= start_host_object(pStream
, &IID_IClassFactory
, (IUnknown
*)&Test_ClassFactory
, MSHLFLAGS_NORMAL
, &thread
);
475 ok_more_than_one_lock();
476 ok_non_zero_external_conn();
478 IStream_Seek(pStream
, ullZero
, STREAM_SEEK_SET
, NULL
);
479 hr
= CoReleaseMarshalData(pStream
);
480 ok_ole_success(hr
, CoReleaseMarshalData
);
483 ok_zero_external_conn();
484 ok_last_release_closes(TRUE
);
486 IStream_Seek(pStream
, ullZero
, STREAM_SEEK_SET
, NULL
);
487 hr
= CoUnmarshalInterface(pStream
, &IID_IClassFactory
, (void **)&pProxy
);
488 todo_wine
{ ok_ole_success(hr
, CoUnmarshalInterface
); }
494 hr
= IClassFactory_CreateInstance(pProxy
, NULL
, &IID_IUnknown
, &dummy
);
495 ok(hr
== RPC_E_DISCONNECTED
, "Remote call should have returned RPC_E_DISCONNECTED, instead of 0x%08x\n", hr
);
497 IClassFactory_Release(pProxy
);
500 IStream_Release(pStream
);
502 end_host_object(tid
, thread
);
505 static void test_same_apartment_unmarshal_failure(void)
510 static const LARGE_INTEGER llZero
;
513 external_connections
= 0;
515 hr
= CreateStreamOnHGlobal(NULL
, TRUE
, &pStream
);
516 ok_ole_success(hr
, CreateStreamOnHGlobal
);
518 hr
= CoMarshalInterface(pStream
, &IID_IUnknown
, (IUnknown
*)&Test_ClassFactory
, MSHCTX_INPROC
, NULL
, MSHLFLAGS_NORMAL
);
519 ok_ole_success(hr
, CoMarshalInterface
);
521 ok_more_than_one_lock();
522 ok_non_zero_external_conn();
524 hr
= IStream_Seek(pStream
, llZero
, STREAM_SEEK_SET
, NULL
);
525 ok_ole_success(hr
, IStream_Seek
);
527 hr
= CoUnmarshalInterface(pStream
, &IID_IParseDisplayName
, (void **)&pProxy
);
528 ok(hr
== E_NOINTERFACE
, "CoUnmarshalInterface should have returned E_NOINTERFACE instead of 0x%08x\n", hr
);
531 ok_zero_external_conn();
532 ok_last_release_closes(FALSE
);
534 IStream_Release(pStream
);
537 /* tests success case of an interthread marshal */
538 static void test_interthread_marshal_and_unmarshal(void)
541 IStream
*pStream
= NULL
;
542 IUnknown
*pProxy
= NULL
;
547 external_connections
= 0;
549 hr
= CreateStreamOnHGlobal(NULL
, TRUE
, &pStream
);
550 ok_ole_success(hr
, CreateStreamOnHGlobal
);
551 tid
= start_host_object(pStream
, &IID_IClassFactory
, (IUnknown
*)&Test_ClassFactory
, MSHLFLAGS_NORMAL
, &thread
);
553 ok_more_than_one_lock();
554 ok_non_zero_external_conn();
556 IStream_Seek(pStream
, ullZero
, STREAM_SEEK_SET
, NULL
);
557 hr
= CoUnmarshalInterface(pStream
, &IID_IClassFactory
, (void **)&pProxy
);
558 ok_ole_success(hr
, CoUnmarshalInterface
);
559 IStream_Release(pStream
);
561 ok_more_than_one_lock();
562 ok_non_zero_external_conn();
564 IUnknown_Release(pProxy
);
567 ok_zero_external_conn();
568 ok_last_release_closes(TRUE
);
570 end_host_object(tid
, thread
);
573 /* the number of external references that Wine's proxy manager normally gives
574 * out, so we can test the border case of running out of references */
575 #define NORMALEXTREFS 5
577 /* tests success case of an interthread marshal and then marshaling the proxy */
578 static void test_proxy_marshal_and_unmarshal(void)
581 IStream
*pStream
= NULL
;
582 IUnknown
*pProxy
= NULL
;
583 IUnknown
*pProxy2
= NULL
;
589 external_connections
= 0;
591 hr
= CreateStreamOnHGlobal(NULL
, TRUE
, &pStream
);
592 ok_ole_success(hr
, CreateStreamOnHGlobal
);
593 tid
= start_host_object(pStream
, &IID_IClassFactory
, (IUnknown
*)&Test_ClassFactory
, MSHLFLAGS_NORMAL
, &thread
);
595 ok_more_than_one_lock();
596 ok_non_zero_external_conn();
598 IStream_Seek(pStream
, ullZero
, STREAM_SEEK_SET
, NULL
);
599 hr
= CoUnmarshalInterface(pStream
, &IID_IClassFactory
, (void **)&pProxy
);
600 ok_ole_success(hr
, CoUnmarshalInterface
);
602 ok_more_than_one_lock();
604 IStream_Seek(pStream
, ullZero
, STREAM_SEEK_SET
, NULL
);
605 /* marshal the proxy */
606 hr
= CoMarshalInterface(pStream
, &IID_IClassFactory
, pProxy
, MSHCTX_INPROC
, NULL
, MSHLFLAGS_NORMAL
);
607 ok_ole_success(hr
, CoMarshalInterface
);
609 ok_more_than_one_lock();
611 /* marshal 5 more times to exhaust the normal external references of 5 */
612 for (i
= 0; i
< NORMALEXTREFS
; i
++)
614 hr
= CoMarshalInterface(pStream
, &IID_IClassFactory
, pProxy
, MSHCTX_INPROC
, NULL
, MSHLFLAGS_NORMAL
);
615 ok_ole_success(hr
, CoMarshalInterface
);
618 ok_more_than_one_lock();
620 /* release the original proxy to test that we successfully keep the
621 * original object alive */
622 IUnknown_Release(pProxy
);
624 IStream_Seek(pStream
, ullZero
, STREAM_SEEK_SET
, NULL
);
625 hr
= CoUnmarshalInterface(pStream
, &IID_IClassFactory
, (void **)&pProxy2
);
626 ok_ole_success(hr
, CoUnmarshalInterface
);
628 ok_more_than_one_lock();
629 ok_non_zero_external_conn();
631 IUnknown_Release(pProxy2
);
633 /* unmarshal all of the proxies to check that the object stub still exists */
634 for (i
= 0; i
< NORMALEXTREFS
; i
++)
636 hr
= CoUnmarshalInterface(pStream
, &IID_IClassFactory
, (void **)&pProxy2
);
637 ok_ole_success(hr
, CoUnmarshalInterface
);
639 IUnknown_Release(pProxy2
);
643 ok_zero_external_conn();
644 ok_last_release_closes(TRUE
);
646 IStream_Release(pStream
);
648 end_host_object(tid
, thread
);
651 /* tests success case of an interthread marshal and then marshaling the proxy
652 * using an iid that hasn't previously been unmarshaled */
653 static void test_proxy_marshal_and_unmarshal2(void)
656 IStream
*pStream
= NULL
;
657 IUnknown
*pProxy
= NULL
;
658 IUnknown
*pProxy2
= NULL
;
663 external_connections
= 0;
665 hr
= CreateStreamOnHGlobal(NULL
, TRUE
, &pStream
);
666 ok_ole_success(hr
, CreateStreamOnHGlobal
);
667 tid
= start_host_object(pStream
, &IID_IUnknown
, (IUnknown
*)&Test_ClassFactory
, MSHLFLAGS_NORMAL
, &thread
);
669 ok_more_than_one_lock();
670 ok_non_zero_external_conn();
672 IStream_Seek(pStream
, ullZero
, STREAM_SEEK_SET
, NULL
);
673 hr
= CoUnmarshalInterface(pStream
, &IID_IUnknown
, (void **)&pProxy
);
674 ok_ole_success(hr
, CoUnmarshalInterface
);
676 ok_more_than_one_lock();
678 IStream_Seek(pStream
, ullZero
, STREAM_SEEK_SET
, NULL
);
679 /* marshal the proxy */
680 hr
= CoMarshalInterface(pStream
, &IID_IClassFactory
, pProxy
, MSHCTX_INPROC
, NULL
, MSHLFLAGS_NORMAL
);
681 ok_ole_success(hr
, CoMarshalInterface
);
683 ok_more_than_one_lock();
685 IStream_Seek(pStream
, ullZero
, STREAM_SEEK_SET
, NULL
);
686 /* unmarshal the second proxy to the object */
687 hr
= CoUnmarshalInterface(pStream
, &IID_IClassFactory
, (void **)&pProxy2
);
688 ok_ole_success(hr
, CoUnmarshalInterface
);
689 IStream_Release(pStream
);
691 /* now the proxies should be as follows:
692 * pProxy -> &Test_ClassFactory
693 * pProxy2 -> &Test_ClassFactory
694 * they should NOT be as follows:
695 * pProxy -> &Test_ClassFactory
697 * the above can only really be tested by looking in +ole traces
700 ok_more_than_one_lock();
702 IUnknown_Release(pProxy
);
704 ok_more_than_one_lock();
705 ok_non_zero_external_conn();
707 IUnknown_Release(pProxy2
);
710 ok_zero_external_conn();
711 ok_last_release_closes(TRUE
);
713 end_host_object(tid
, thread
);
716 /* tests success case of an interthread marshal and then table-weak-marshaling the proxy */
717 static void test_proxy_marshal_and_unmarshal_weak(void)
720 IStream
*pStream
= NULL
;
721 IUnknown
*pProxy
= NULL
;
722 IUnknown
*pProxy2
= NULL
;
727 external_connections
= 0;
729 hr
= CreateStreamOnHGlobal(NULL
, TRUE
, &pStream
);
730 ok_ole_success(hr
, CreateStreamOnHGlobal
);
731 tid
= start_host_object(pStream
, &IID_IClassFactory
, (IUnknown
*)&Test_ClassFactory
, MSHLFLAGS_NORMAL
, &thread
);
733 ok_more_than_one_lock();
734 ok_non_zero_external_conn();
736 IStream_Seek(pStream
, ullZero
, STREAM_SEEK_SET
, NULL
);
737 hr
= CoUnmarshalInterface(pStream
, &IID_IClassFactory
, (void **)&pProxy
);
738 ok_ole_success(hr
, CoUnmarshalInterface
);
740 ok_more_than_one_lock();
741 ok_non_zero_external_conn();
743 IStream_Seek(pStream
, ullZero
, STREAM_SEEK_SET
, NULL
);
744 /* marshal the proxy */
745 hr
= CoMarshalInterface(pStream
, &IID_IClassFactory
, pProxy
, MSHCTX_INPROC
, NULL
, MSHLFLAGS_TABLEWEAK
);
746 ok_ole_success(hr
, CoMarshalInterface
);
748 ok_more_than_one_lock();
749 ok_non_zero_external_conn();
751 /* release the original proxy to test that we successfully keep the
752 * original object alive */
753 IUnknown_Release(pProxy
);
755 IStream_Seek(pStream
, ullZero
, STREAM_SEEK_SET
, NULL
);
756 hr
= CoUnmarshalInterface(pStream
, &IID_IClassFactory
, (void **)&pProxy2
);
758 ok(hr
== CO_E_OBJNOTREG
, "CoUnmarshalInterface should return CO_E_OBJNOTREG instead of 0x%08x\n", hr
);
761 ok_zero_external_conn();
762 ok_last_release_closes(TRUE
);
764 IStream_Release(pStream
);
766 end_host_object(tid
, thread
);
769 /* tests success case of an interthread marshal and then table-strong-marshaling the proxy */
770 static void test_proxy_marshal_and_unmarshal_strong(void)
773 IStream
*pStream
= NULL
;
774 IUnknown
*pProxy
= NULL
;
775 IUnknown
*pProxy2
= NULL
;
780 external_connections
= 0;
782 hr
= CreateStreamOnHGlobal(NULL
, TRUE
, &pStream
);
783 ok_ole_success(hr
, CreateStreamOnHGlobal
);
784 tid
= start_host_object(pStream
, &IID_IClassFactory
, (IUnknown
*)&Test_ClassFactory
, MSHLFLAGS_NORMAL
, &thread
);
786 ok_more_than_one_lock();
787 ok_non_zero_external_conn();
789 IStream_Seek(pStream
, ullZero
, STREAM_SEEK_SET
, NULL
);
790 hr
= CoUnmarshalInterface(pStream
, &IID_IClassFactory
, (void **)&pProxy
);
791 ok_ole_success(hr
, CoUnmarshalInterface
);
793 ok_more_than_one_lock();
794 ok_non_zero_external_conn();
796 IStream_Seek(pStream
, ullZero
, STREAM_SEEK_SET
, NULL
);
797 /* marshal the proxy */
798 hr
= CoMarshalInterface(pStream
, &IID_IClassFactory
, pProxy
, MSHCTX_INPROC
, NULL
, MSHLFLAGS_TABLESTRONG
);
799 ok(hr
== S_OK
/* WinNT */ || hr
== E_INVALIDARG
/* Win9x */,
800 "CoMarshalInterface should have return S_OK or E_INVALIDARG instead of 0x%08x\n", hr
);
803 IUnknown_Release(pProxy
);
807 ok_more_than_one_lock();
808 ok_non_zero_external_conn();
810 /* release the original proxy to test that we successfully keep the
811 * original object alive */
812 IUnknown_Release(pProxy
);
814 IStream_Seek(pStream
, ullZero
, STREAM_SEEK_SET
, NULL
);
815 hr
= CoUnmarshalInterface(pStream
, &IID_IClassFactory
, (void **)&pProxy2
);
816 ok_ole_success(hr
, CoUnmarshalInterface
);
818 ok_more_than_one_lock();
819 ok_non_zero_external_conn();
821 IUnknown_Release(pProxy2
);
823 ok_more_than_one_lock();
824 ok_non_zero_external_conn();
827 IStream_Release(pStream
);
829 end_host_object(tid
, thread
);
833 ok_zero_external_conn();
834 ok_last_release_closes(FALSE
);
838 /* tests that stubs are released when the containing apartment is destroyed */
839 static void test_marshal_stub_apartment_shutdown(void)
842 IStream
*pStream
= NULL
;
843 IUnknown
*pProxy
= NULL
;
848 external_connections
= 0;
850 hr
= CreateStreamOnHGlobal(NULL
, TRUE
, &pStream
);
851 ok_ole_success(hr
, CreateStreamOnHGlobal
);
852 tid
= start_host_object(pStream
, &IID_IClassFactory
, (IUnknown
*)&Test_ClassFactory
, MSHLFLAGS_NORMAL
, &thread
);
854 ok_more_than_one_lock();
855 ok_non_zero_external_conn();
857 IStream_Seek(pStream
, ullZero
, STREAM_SEEK_SET
, NULL
);
858 hr
= CoUnmarshalInterface(pStream
, &IID_IClassFactory
, (void **)&pProxy
);
859 ok_ole_success(hr
, CoUnmarshalInterface
);
860 IStream_Release(pStream
);
862 ok_more_than_one_lock();
863 ok_non_zero_external_conn();
865 end_host_object(tid
, thread
);
869 ok_zero_external_conn();
870 ok_last_release_closes(FALSE
);
873 IUnknown_Release(pProxy
);
878 /* tests that proxies are released when the containing apartment is destroyed */
879 static void test_marshal_proxy_apartment_shutdown(void)
882 IStream
*pStream
= NULL
;
883 IUnknown
*pProxy
= NULL
;
888 external_connections
= 0;
890 hr
= CreateStreamOnHGlobal(NULL
, TRUE
, &pStream
);
891 ok_ole_success(hr
, CreateStreamOnHGlobal
);
892 tid
= start_host_object(pStream
, &IID_IClassFactory
, (IUnknown
*)&Test_ClassFactory
, MSHLFLAGS_NORMAL
, &thread
);
894 ok_more_than_one_lock();
895 ok_non_zero_external_conn();
897 IStream_Seek(pStream
, ullZero
, STREAM_SEEK_SET
, NULL
);
898 hr
= CoUnmarshalInterface(pStream
, &IID_IClassFactory
, (void **)&pProxy
);
899 ok_ole_success(hr
, CoUnmarshalInterface
);
900 IStream_Release(pStream
);
902 ok_more_than_one_lock();
903 ok_non_zero_external_conn();
908 ok_zero_external_conn();
909 ok_last_release_closes(TRUE
);
911 IUnknown_Release(pProxy
);
915 end_host_object(tid
, thread
);
917 pCoInitializeEx(NULL
, COINIT_APARTMENTTHREADED
);
920 /* tests that proxies are released when the containing mta apartment is destroyed */
921 static void test_marshal_proxy_mta_apartment_shutdown(void)
924 IStream
*pStream
= NULL
;
925 IUnknown
*pProxy
= NULL
;
930 pCoInitializeEx(NULL
, COINIT_MULTITHREADED
);
933 external_connections
= 0;
935 hr
= CreateStreamOnHGlobal(NULL
, TRUE
, &pStream
);
936 ok_ole_success(hr
, CreateStreamOnHGlobal
);
937 tid
= start_host_object(pStream
, &IID_IClassFactory
, (IUnknown
*)&Test_ClassFactory
, MSHLFLAGS_NORMAL
, &thread
);
939 ok_more_than_one_lock();
940 ok_non_zero_external_conn();
942 IStream_Seek(pStream
, ullZero
, STREAM_SEEK_SET
, NULL
);
943 hr
= CoUnmarshalInterface(pStream
, &IID_IClassFactory
, (void **)&pProxy
);
944 ok_ole_success(hr
, CoUnmarshalInterface
);
945 IStream_Release(pStream
);
947 ok_more_than_one_lock();
948 ok_non_zero_external_conn();
953 ok_zero_external_conn();
954 ok_last_release_closes(TRUE
);
956 IUnknown_Release(pProxy
);
960 end_host_object(tid
, thread
);
962 pCoInitializeEx(NULL
, COINIT_APARTMENTTHREADED
);
968 HANDLE marshal_event
;
969 HANDLE unmarshal_event
;
972 /* helper for test_no_couninitialize_server */
973 static DWORD CALLBACK
no_couninitialize_server_proc(LPVOID p
)
975 struct ncu_params
*ncu_params
= p
;
978 pCoInitializeEx(NULL
, COINIT_MULTITHREADED
);
980 hr
= CoMarshalInterface(ncu_params
->stream
, &IID_IClassFactory
, (IUnknown
*)&Test_ClassFactory
, MSHCTX_INPROC
, NULL
, MSHLFLAGS_NORMAL
);
981 ok_ole_success(hr
, CoMarshalInterface
);
983 SetEvent(ncu_params
->marshal_event
);
985 ok( !WaitForSingleObject(ncu_params
->unmarshal_event
, 10000), "wait timed out\n" );
987 /* die without calling CoUninitialize */
992 /* tests apartment that an apartment with a stub is released without deadlock
993 * if the owning thread exits */
994 static void test_no_couninitialize_server(void)
997 IStream
*pStream
= NULL
;
998 IUnknown
*pProxy
= NULL
;
1001 struct ncu_params ncu_params
;
1004 external_connections
= 0;
1006 ncu_params
.marshal_event
= CreateEventA(NULL
, TRUE
, FALSE
, NULL
);
1007 ncu_params
.unmarshal_event
= CreateEventA(NULL
, TRUE
, FALSE
, NULL
);
1009 hr
= CreateStreamOnHGlobal(NULL
, TRUE
, &pStream
);
1010 ok_ole_success(hr
, CreateStreamOnHGlobal
);
1011 ncu_params
.stream
= pStream
;
1013 thread
= CreateThread(NULL
, 0, no_couninitialize_server_proc
, &ncu_params
, 0, &tid
);
1015 ok( !WaitForSingleObject(ncu_params
.marshal_event
, 10000), "wait timed out\n" );
1016 ok_more_than_one_lock();
1017 ok_non_zero_external_conn();
1019 IStream_Seek(pStream
, ullZero
, STREAM_SEEK_SET
, NULL
);
1020 hr
= CoUnmarshalInterface(pStream
, &IID_IClassFactory
, (void **)&pProxy
);
1021 ok_ole_success(hr
, CoUnmarshalInterface
);
1022 IStream_Release(pStream
);
1024 ok_more_than_one_lock();
1025 ok_non_zero_external_conn();
1027 SetEvent(ncu_params
.unmarshal_event
);
1028 ok( !WaitForSingleObject(thread
, 10000), "wait timed out\n" );
1032 ok_zero_external_conn();
1033 ok_last_release_closes(FALSE
);
1036 CloseHandle(thread
);
1037 CloseHandle(ncu_params
.marshal_event
);
1038 CloseHandle(ncu_params
.unmarshal_event
);
1040 IUnknown_Release(pProxy
);
1045 /* STA -> STA call during DLL_THREAD_DETACH */
1046 static DWORD CALLBACK
no_couninitialize_client_proc(LPVOID p
)
1048 struct ncu_params
*ncu_params
= p
;
1050 IUnknown
*pProxy
= NULL
;
1052 pCoInitializeEx(NULL
, COINIT_APARTMENTTHREADED
);
1054 hr
= CoUnmarshalInterface(ncu_params
->stream
, &IID_IClassFactory
, (void **)&pProxy
);
1055 ok_ole_success(hr
, CoUnmarshalInterface
);
1056 IStream_Release(ncu_params
->stream
);
1058 ok_more_than_one_lock();
1060 /* die without calling CoUninitialize */
1065 /* tests STA -> STA call during DLL_THREAD_DETACH doesn't deadlock */
1066 static void test_no_couninitialize_client(void)
1069 IStream
*pStream
= NULL
;
1074 struct ncu_params ncu_params
;
1077 external_connections
= 0;
1079 hr
= CreateStreamOnHGlobal(NULL
, TRUE
, &pStream
);
1080 ok_ole_success(hr
, CreateStreamOnHGlobal
);
1081 ncu_params
.stream
= pStream
;
1083 /* NOTE: assumes start_host_object uses an STA to host the object, as MTAs
1084 * always deadlock when called from within DllMain */
1085 host_tid
= start_host_object(pStream
, &IID_IClassFactory
, (IUnknown
*)&Test_ClassFactory
, MSHLFLAGS_NORMAL
, &host_thread
);
1086 IStream_Seek(pStream
, ullZero
, STREAM_SEEK_SET
, NULL
);
1088 ok_more_than_one_lock();
1089 ok_non_zero_external_conn();
1091 thread
= CreateThread(NULL
, 0, no_couninitialize_client_proc
, &ncu_params
, 0, &tid
);
1093 ok( !WaitForSingleObject(thread
, 10000), "wait timed out\n" );
1094 CloseHandle(thread
);
1097 ok_zero_external_conn();
1098 ok_last_release_closes(TRUE
);
1100 end_host_object(host_tid
, host_thread
);
1103 static BOOL crash_thread_success
;
1105 static DWORD CALLBACK
crash_couninitialize_proc(void *p
)
1114 hr
= CreateStreamOnHGlobal(NULL
, TRUE
, &stream
);
1115 ok_ole_success(hr
, CreateStreamOnHGlobal
);
1117 hr
= CoMarshalInterface(stream
, &IID_IUnknown
, &TestCrash_Unknown
, MSHCTX_INPROC
, NULL
, MSHLFLAGS_NORMAL
);
1118 ok_ole_success(hr
, CoMarshalInterface
);
1120 IStream_Seek(stream
, ullZero
, STREAM_SEEK_SET
, NULL
);
1122 hr
= CoReleaseMarshalData(stream
);
1123 ok_ole_success(hr
, CoReleaseMarshalData
);
1127 hr
= CoMarshalInterface(stream
, &IID_IUnknown
, &TestCrash_Unknown
, MSHCTX_INPROC
, NULL
, MSHLFLAGS_NORMAL
);
1128 ok_ole_success(hr
, CoMarshalInterface
);
1130 ok_more_than_one_lock();
1132 trace("CoUninitialize >>>\n");
1134 trace("CoUninitialize <<<\n");
1138 IStream_Release(stream
);
1139 crash_thread_success
= TRUE
;
1143 static void test_crash_couninitialize(void)
1148 if(!GetProcAddress(GetModuleHandleA("kernel32.dll"), "CreateActCtxW")) {
1149 win_skip("Skipping crash tests on win2k.\n");
1153 crash_thread_success
= FALSE
;
1154 thread
= CreateThread(NULL
, 0, crash_couninitialize_proc
, NULL
, 0, &tid
);
1155 ok(!WaitForSingleObject(thread
, 10000), "wait timed out\n");
1156 CloseHandle(thread
);
1157 ok(crash_thread_success
, "Crash thread failed\n");
1160 /* tests success case of a same-thread table-weak marshal, unmarshal, unmarshal */
1161 static void test_tableweak_marshal_and_unmarshal_twice(void)
1164 IStream
*pStream
= NULL
;
1165 IUnknown
*pProxy1
= NULL
;
1166 IUnknown
*pProxy2
= NULL
;
1171 external_connections
= 0;
1173 hr
= CreateStreamOnHGlobal(NULL
, TRUE
, &pStream
);
1174 ok_ole_success(hr
, CreateStreamOnHGlobal
);
1175 tid
= start_host_object(pStream
, &IID_IClassFactory
, (IUnknown
*)&Test_ClassFactory
, MSHLFLAGS_TABLEWEAK
, &thread
);
1177 ok_more_than_one_lock();
1178 ok_zero_external_conn();
1180 IStream_Seek(pStream
, ullZero
, STREAM_SEEK_SET
, NULL
);
1181 hr
= CoUnmarshalInterface(pStream
, &IID_IClassFactory
, (void **)&pProxy1
);
1182 ok_ole_success(hr
, CoUnmarshalInterface
);
1184 ok_more_than_one_lock();
1185 ok_non_zero_external_conn();
1187 IStream_Seek(pStream
, ullZero
, STREAM_SEEK_SET
, NULL
);
1188 hr
= CoUnmarshalInterface(pStream
, &IID_IClassFactory
, (void **)&pProxy2
);
1189 ok_ole_success(hr
, CoUnmarshalInterface
);
1191 ok_more_than_one_lock();
1193 IUnknown_Release(pProxy1
);
1194 ok_non_zero_external_conn();
1195 IUnknown_Release(pProxy2
);
1196 ok_zero_external_conn();
1197 ok_last_release_closes(TRUE
);
1199 /* When IExternalConnection is present COM's lifetime management
1200 * behaviour is altered; the remaining weak ref prevents stub shutdown. */
1201 if (with_external_conn
)
1203 ok_more_than_one_lock();
1204 IStream_Seek(pStream
, ullZero
, STREAM_SEEK_SET
, NULL
);
1205 release_host_object(tid
, 0);
1208 /* Without IExternalConnection this line is shows the difference between weak and strong table marshaling
1209 * weak has cLocks == 0, strong has cLocks > 0. */
1212 IStream_Release(pStream
);
1213 end_host_object(tid
, thread
);
1216 /* tests releasing after unmarshaling one object */
1217 static void test_tableweak_marshal_releasedata1(void)
1220 IStream
*pStream
= NULL
;
1221 IUnknown
*pProxy1
= NULL
;
1222 IUnknown
*pProxy2
= NULL
;
1227 external_connections
= 0;
1229 hr
= CreateStreamOnHGlobal(NULL
, TRUE
, &pStream
);
1230 ok_ole_success(hr
, CreateStreamOnHGlobal
);
1231 tid
= start_host_object(pStream
, &IID_IClassFactory
, (IUnknown
*)&Test_ClassFactory
, MSHLFLAGS_TABLEWEAK
, &thread
);
1233 ok_more_than_one_lock();
1234 ok_zero_external_conn();
1236 IStream_Seek(pStream
, ullZero
, STREAM_SEEK_SET
, NULL
);
1237 hr
= CoUnmarshalInterface(pStream
, &IID_IClassFactory
, (void **)&pProxy1
);
1238 ok_ole_success(hr
, CoUnmarshalInterface
);
1240 ok_more_than_one_lock();
1241 ok_non_zero_external_conn();
1243 /* release the remaining reference on the object by calling
1244 * CoReleaseMarshalData in the hosting thread */
1245 IStream_Seek(pStream
, ullZero
, STREAM_SEEK_SET
, NULL
);
1246 release_host_object(tid
, 0);
1248 ok_more_than_one_lock();
1249 ok_non_zero_external_conn();
1251 IStream_Seek(pStream
, ullZero
, STREAM_SEEK_SET
, NULL
);
1252 hr
= CoUnmarshalInterface(pStream
, &IID_IClassFactory
, (void **)&pProxy2
);
1253 ok_ole_success(hr
, CoUnmarshalInterface
);
1254 IStream_Release(pStream
);
1256 ok_more_than_one_lock();
1257 ok_non_zero_external_conn();
1259 IUnknown_Release(pProxy1
);
1263 ok_non_zero_external_conn();
1264 IUnknown_Release(pProxy2
);
1267 /* this line is shows the difference between weak and strong table marshaling:
1268 * weak has cLocks == 0
1269 * strong has cLocks > 0 */
1271 ok_zero_external_conn();
1272 ok_last_release_closes(TRUE
);
1274 end_host_object(tid
, thread
);
1277 /* tests releasing after unmarshaling one object */
1278 static void test_tableweak_marshal_releasedata2(void)
1281 IStream
*pStream
= NULL
;
1282 IUnknown
*pProxy
= NULL
;
1287 external_connections
= 0;
1289 hr
= CreateStreamOnHGlobal(NULL
, TRUE
, &pStream
);
1290 ok_ole_success(hr
, CreateStreamOnHGlobal
);
1291 tid
= start_host_object(pStream
, &IID_IClassFactory
, (IUnknown
*)&Test_ClassFactory
, MSHLFLAGS_TABLEWEAK
, &thread
);
1293 ok_more_than_one_lock();
1294 ok_zero_external_conn();
1296 /* release the remaining reference on the object by calling
1297 * CoReleaseMarshalData in the hosting thread */
1298 IStream_Seek(pStream
, ullZero
, STREAM_SEEK_SET
, NULL
);
1299 release_host_object(tid
, 0);
1303 IStream_Seek(pStream
, ullZero
, STREAM_SEEK_SET
, NULL
);
1304 hr
= CoUnmarshalInterface(pStream
, &IID_IClassFactory
, (void **)&pProxy
);
1307 ok(hr
== CO_E_OBJNOTREG
,
1308 "CoUnmarshalInterface should have failed with CO_E_OBJNOTREG, but returned 0x%08x instead\n",
1311 IStream_Release(pStream
);
1314 ok_zero_external_conn();
1316 end_host_object(tid
, thread
);
1319 struct duo_marshal_data
1321 MSHLFLAGS marshal_flags1
, marshal_flags2
;
1322 IStream
*pStream1
, *pStream2
;
1327 static DWORD CALLBACK
duo_marshal_thread_proc(void *p
)
1330 struct duo_marshal_data
*data
= p
;
1331 HANDLE hQuitEvent
= data
->hQuitEvent
;
1334 pCoInitializeEx(NULL
, COINIT_APARTMENTTHREADED
);
1336 hr
= CoMarshalInterface(data
->pStream1
, &IID_IClassFactory
, (IUnknown
*)&Test_ClassFactory
, MSHCTX_INPROC
, NULL
, data
->marshal_flags1
);
1337 ok_ole_success(hr
, "CoMarshalInterface");
1339 hr
= CoMarshalInterface(data
->pStream2
, &IID_IClassFactory
, (IUnknown
*)&Test_ClassFactory
, MSHCTX_INPROC
, NULL
, data
->marshal_flags2
);
1340 ok_ole_success(hr
, "CoMarshalInterface");
1342 /* force the message queue to be created before signaling parent thread */
1343 PeekMessageA(&msg
, NULL
, WM_USER
, WM_USER
, PM_NOREMOVE
);
1345 SetEvent(data
->hReadyEvent
);
1347 while (WAIT_OBJECT_0
+ 1 == MsgWaitForMultipleObjects(1, &hQuitEvent
, FALSE
, 10000, QS_ALLINPUT
))
1349 while (PeekMessageA(&msg
, NULL
, 0, 0, PM_REMOVE
))
1351 if (msg
.hwnd
== NULL
&& msg
.message
== RELEASEMARSHALDATA
)
1353 CoReleaseMarshalData(msg
.wParam
== 1 ? data
->pStream1
: data
->pStream2
);
1354 SetEvent((HANDLE
)msg
.lParam
);
1357 DispatchMessageA(&msg
);
1360 CloseHandle(hQuitEvent
);
1367 /* tests interaction between table-weak and normal marshalling of an object */
1368 static void test_tableweak_and_normal_marshal_and_unmarshal(void)
1371 IUnknown
*pProxyWeak
= NULL
;
1372 IUnknown
*pProxyNormal
= NULL
;
1375 struct duo_marshal_data data
;
1378 external_connections
= 0;
1380 data
.hReadyEvent
= CreateEventA(NULL
, FALSE
, FALSE
, NULL
);
1381 data
.hQuitEvent
= CreateEventA(NULL
, FALSE
, FALSE
, NULL
);
1382 data
.marshal_flags1
= MSHLFLAGS_TABLEWEAK
;
1383 data
.marshal_flags2
= MSHLFLAGS_NORMAL
;
1384 hr
= CreateStreamOnHGlobal(NULL
, TRUE
, &data
.pStream1
);
1385 ok_ole_success(hr
, CreateStreamOnHGlobal
);
1386 hr
= CreateStreamOnHGlobal(NULL
, TRUE
, &data
.pStream2
);
1387 ok_ole_success(hr
, CreateStreamOnHGlobal
);
1389 thread
= CreateThread(NULL
, 0, duo_marshal_thread_proc
, &data
, 0, &tid
);
1390 ok( !WaitForSingleObject(data
.hReadyEvent
, 10000), "wait timed out\n" );
1391 CloseHandle(data
.hReadyEvent
);
1393 ok_more_than_one_lock();
1394 ok_non_zero_external_conn();
1397 IStream_Seek(data
.pStream1
, ullZero
, STREAM_SEEK_SET
, NULL
);
1398 hr
= CoUnmarshalInterface(data
.pStream1
, &IID_IClassFactory
, (void **)&pProxyWeak
);
1399 ok_ole_success(hr
, CoUnmarshalInterface
);
1401 ok_more_than_one_lock();
1404 IStream_Seek(data
.pStream2
, ullZero
, STREAM_SEEK_SET
, NULL
);
1405 hr
= CoUnmarshalInterface(data
.pStream2
, &IID_IClassFactory
, (void **)&pProxyNormal
);
1406 ok_ole_success(hr
, CoUnmarshalInterface
);
1408 ok_more_than_one_lock();
1410 IUnknown_Release(pProxyNormal
);
1412 ok_more_than_one_lock();
1413 ok_non_zero_external_conn();
1415 IUnknown_Release(pProxyWeak
);
1417 ok_zero_external_conn();
1418 ok_last_release_closes(TRUE
);
1420 /* When IExternalConnection is present COM's lifetime management
1421 * behaviour is altered; the remaining weak ref prevents stub shutdown. */
1422 if (with_external_conn
)
1424 ok_more_than_one_lock();
1425 IStream_Seek(data
.pStream1
, ullZero
, STREAM_SEEK_SET
, NULL
);
1426 release_host_object(tid
, 1);
1430 IStream_Release(data
.pStream1
);
1431 IStream_Release(data
.pStream2
);
1433 SetEvent(data
.hQuitEvent
);
1434 ok( !WaitForSingleObject(thread
, 10000), "wait timed out\n" );
1435 CloseHandle(thread
);
1438 static void test_tableweak_and_normal_marshal_and_releasedata(void)
1443 struct duo_marshal_data data
;
1446 external_connections
= 0;
1448 data
.hReadyEvent
= CreateEventA(NULL
, FALSE
, FALSE
, NULL
);
1449 data
.hQuitEvent
= CreateEventA(NULL
, FALSE
, FALSE
, NULL
);
1450 data
.marshal_flags1
= MSHLFLAGS_TABLEWEAK
;
1451 data
.marshal_flags2
= MSHLFLAGS_NORMAL
;
1452 hr
= CreateStreamOnHGlobal(NULL
, TRUE
, &data
.pStream1
);
1453 ok_ole_success(hr
, CreateStreamOnHGlobal
);
1454 hr
= CreateStreamOnHGlobal(NULL
, TRUE
, &data
.pStream2
);
1455 ok_ole_success(hr
, CreateStreamOnHGlobal
);
1457 thread
= CreateThread(NULL
, 0, duo_marshal_thread_proc
, &data
, 0, &tid
);
1458 ok( !WaitForSingleObject(data
.hReadyEvent
, 10000), "wait timed out\n" );
1459 CloseHandle(data
.hReadyEvent
);
1461 ok_more_than_one_lock();
1462 ok_non_zero_external_conn();
1464 /* release normal - which in the non-external conn case will free the object despite the weak ref. */
1465 IStream_Seek(data
.pStream2
, ullZero
, STREAM_SEEK_SET
, NULL
);
1466 release_host_object(tid
, 2);
1468 ok_zero_external_conn();
1469 ok_last_release_closes(TRUE
);
1471 if (with_external_conn
)
1473 ok_more_than_one_lock();
1474 IStream_Seek(data
.pStream1
, ullZero
, STREAM_SEEK_SET
, NULL
);
1475 release_host_object(tid
, 1);
1480 IStream_Release(data
.pStream1
);
1481 IStream_Release(data
.pStream2
);
1483 SetEvent(data
.hQuitEvent
);
1484 ok( !WaitForSingleObject(thread
, 10000), "wait timed out\n" );
1485 CloseHandle(thread
);
1488 static void test_two_tableweak_marshal_and_releasedata(void)
1493 struct duo_marshal_data data
;
1496 external_connections
= 0;
1498 data
.hReadyEvent
= CreateEventA(NULL
, FALSE
, FALSE
, NULL
);
1499 data
.hQuitEvent
= CreateEventA(NULL
, FALSE
, FALSE
, NULL
);
1500 data
.marshal_flags1
= MSHLFLAGS_TABLEWEAK
;
1501 data
.marshal_flags2
= MSHLFLAGS_TABLEWEAK
;
1502 hr
= CreateStreamOnHGlobal(NULL
, TRUE
, &data
.pStream1
);
1503 ok_ole_success(hr
, CreateStreamOnHGlobal
);
1504 hr
= CreateStreamOnHGlobal(NULL
, TRUE
, &data
.pStream2
);
1505 ok_ole_success(hr
, CreateStreamOnHGlobal
);
1507 thread
= CreateThread(NULL
, 0, duo_marshal_thread_proc
, &data
, 0, &tid
);
1508 ok( !WaitForSingleObject(data
.hReadyEvent
, 10000), "wait timed out\n" );
1509 CloseHandle(data
.hReadyEvent
);
1511 ok_more_than_one_lock();
1512 ok_zero_external_conn();
1514 /* release one weak ref - the remaining weak ref will keep the obj alive */
1515 IStream_Seek(data
.pStream1
, ullZero
, STREAM_SEEK_SET
, NULL
);
1516 release_host_object(tid
, 1);
1518 ok_more_than_one_lock();
1520 IStream_Seek(data
.pStream2
, ullZero
, STREAM_SEEK_SET
, NULL
);
1521 release_host_object(tid
, 2);
1525 IStream_Release(data
.pStream1
);
1526 IStream_Release(data
.pStream2
);
1528 SetEvent(data
.hQuitEvent
);
1529 ok( !WaitForSingleObject(thread
, 10000), "wait timed out\n" );
1530 CloseHandle(thread
);
1533 /* tests success case of a same-thread table-strong marshal, unmarshal, unmarshal */
1534 static void test_tablestrong_marshal_and_unmarshal_twice(void)
1537 IStream
*pStream
= NULL
;
1538 IUnknown
*pProxy1
= NULL
;
1539 IUnknown
*pProxy2
= NULL
;
1544 external_connections
= 0;
1546 hr
= CreateStreamOnHGlobal(NULL
, TRUE
, &pStream
);
1547 ok_ole_success(hr
, CreateStreamOnHGlobal
);
1548 tid
= start_host_object(pStream
, &IID_IClassFactory
, (IUnknown
*)&Test_ClassFactory
, MSHLFLAGS_TABLESTRONG
, &thread
);
1550 ok_more_than_one_lock();
1551 ok_non_zero_external_conn();
1553 IStream_Seek(pStream
, ullZero
, STREAM_SEEK_SET
, NULL
);
1554 hr
= CoUnmarshalInterface(pStream
, &IID_IClassFactory
, (void **)&pProxy1
);
1555 ok_ole_success(hr
, CoUnmarshalInterface
);
1557 ok_more_than_one_lock();
1559 IStream_Seek(pStream
, ullZero
, STREAM_SEEK_SET
, NULL
);
1560 hr
= CoUnmarshalInterface(pStream
, &IID_IClassFactory
, (void **)&pProxy2
);
1561 ok_ole_success(hr
, CoUnmarshalInterface
);
1563 ok_more_than_one_lock();
1565 if (pProxy1
) IUnknown_Release(pProxy1
);
1566 if (pProxy2
) IUnknown_Release(pProxy2
);
1568 /* this line is shows the difference between weak and strong table marshaling:
1569 * weak has cLocks == 0
1570 * strong has cLocks > 0 */
1571 ok_more_than_one_lock();
1573 /* release the remaining reference on the object by calling
1574 * CoReleaseMarshalData in the hosting thread */
1575 IStream_Seek(pStream
, ullZero
, STREAM_SEEK_SET
, NULL
);
1576 release_host_object(tid
, 0);
1577 IStream_Release(pStream
);
1580 ok_zero_external_conn();
1581 ok_last_release_closes(TRUE
);
1583 end_host_object(tid
, thread
);
1586 /* tests CoLockObjectExternal */
1587 static void test_lock_object_external(void)
1590 IStream
*pStream
= NULL
;
1593 external_connections
= 0;
1595 /* test the stub manager creation aspect of CoLockObjectExternal when the
1596 * object hasn't been marshaled yet */
1597 CoLockObjectExternal((IUnknown
*)&Test_ClassFactory
, TRUE
, TRUE
);
1599 ok_more_than_one_lock();
1600 ok_non_zero_external_conn();
1602 CoDisconnectObject((IUnknown
*)&Test_ClassFactory
, 0);
1605 ok_non_zero_external_conn();
1606 external_connections
= 0;
1608 /* test our empty stub manager being handled correctly in
1609 * CoMarshalInterface */
1610 CoLockObjectExternal((IUnknown
*)&Test_ClassFactory
, TRUE
, TRUE
);
1612 hr
= CreateStreamOnHGlobal(NULL
, TRUE
, &pStream
);
1613 ok_ole_success(hr
, CreateStreamOnHGlobal
);
1614 hr
= CoMarshalInterface(pStream
, &IID_IClassFactory
, (IUnknown
*)&Test_ClassFactory
, MSHCTX_INPROC
, NULL
, MSHLFLAGS_NORMAL
);
1615 ok_ole_success(hr
, CoMarshalInterface
);
1617 CoLockObjectExternal((IUnknown
*)&Test_ClassFactory
, TRUE
, TRUE
);
1619 ok_more_than_one_lock();
1620 ok_non_zero_external_conn();
1622 IStream_Seek(pStream
, ullZero
, STREAM_SEEK_SET
, NULL
);
1623 hr
= CoReleaseMarshalData(pStream
);
1624 ok_ole_success(hr
, CoReleaseMarshalData
);
1625 IStream_Seek(pStream
, ullZero
, STREAM_SEEK_SET
, NULL
);
1627 ok_more_than_one_lock();
1628 ok_non_zero_external_conn();
1629 ok_last_release_closes(TRUE
);
1631 CoLockObjectExternal((IUnknown
*)&Test_ClassFactory
, FALSE
, TRUE
);
1633 ok_more_than_one_lock();
1634 ok_non_zero_external_conn();
1635 ok_last_release_closes(TRUE
);
1637 CoLockObjectExternal((IUnknown
*)&Test_ClassFactory
, FALSE
, TRUE
);
1640 ok_zero_external_conn();
1641 ok_last_release_closes(TRUE
);
1643 /* test CoLockObjectExternal releases reference to object with
1644 * fLastUnlockReleases as TRUE and there are only strong references on
1646 CoLockObjectExternal((IUnknown
*)&Test_ClassFactory
, TRUE
, FALSE
);
1648 ok_more_than_one_lock();
1649 ok_non_zero_external_conn();
1651 CoLockObjectExternal((IUnknown
*)&Test_ClassFactory
, FALSE
, FALSE
);
1654 ok_zero_external_conn();
1655 ok_last_release_closes(FALSE
);
1657 /* test CoLockObjectExternal doesn't release the last reference to an
1658 * object with fLastUnlockReleases as TRUE and there is a weak reference
1660 hr
= CoMarshalInterface(pStream
, &IID_IClassFactory
, (IUnknown
*)&Test_ClassFactory
, MSHCTX_INPROC
, NULL
, MSHLFLAGS_TABLEWEAK
);
1661 ok_ole_success(hr
, CoMarshalInterface
);
1663 ok_more_than_one_lock();
1664 ok_zero_external_conn();
1666 CoLockObjectExternal((IUnknown
*)&Test_ClassFactory
, TRUE
, FALSE
);
1668 ok_more_than_one_lock();
1669 ok_non_zero_external_conn();
1671 CoLockObjectExternal((IUnknown
*)&Test_ClassFactory
, FALSE
, FALSE
);
1673 ok_more_than_one_lock();
1674 ok_zero_external_conn();
1675 ok_last_release_closes(FALSE
);
1677 CoDisconnectObject((IUnknown
*)&Test_ClassFactory
, 0);
1681 IStream_Release(pStream
);
1684 /* tests disconnecting stubs */
1685 static void test_disconnect_stub(void)
1688 IStream
*pStream
= NULL
;
1691 external_connections
= 0;
1693 hr
= CreateStreamOnHGlobal(NULL
, TRUE
, &pStream
);
1694 ok_ole_success(hr
, CreateStreamOnHGlobal
);
1695 hr
= CoMarshalInterface(pStream
, &IID_IClassFactory
, (IUnknown
*)&Test_ClassFactory
, MSHCTX_INPROC
, NULL
, MSHLFLAGS_NORMAL
);
1696 ok_ole_success(hr
, CoMarshalInterface
);
1698 ok_non_zero_external_conn();
1700 CoLockObjectExternal((IUnknown
*)&Test_ClassFactory
, TRUE
, TRUE
);
1702 ok_more_than_one_lock();
1703 ok_non_zero_external_conn();
1705 IStream_Seek(pStream
, ullZero
, STREAM_SEEK_SET
, NULL
);
1706 hr
= CoReleaseMarshalData(pStream
);
1707 ok_ole_success(hr
, CoReleaseMarshalData
);
1708 IStream_Release(pStream
);
1710 ok_more_than_one_lock();
1711 ok_non_zero_external_conn();
1713 CoDisconnectObject((IUnknown
*)&Test_ClassFactory
, 0);
1716 ok_non_zero_external_conn();
1718 hr
= CoDisconnectObject(NULL
, 0);
1719 ok( hr
== E_INVALIDARG
, "wrong status %x\n", hr
);
1722 /* tests failure case of a same-thread marshal and unmarshal twice */
1723 static void test_normal_marshal_and_unmarshal_twice(void)
1726 IStream
*pStream
= NULL
;
1727 IUnknown
*pProxy1
= NULL
;
1728 IUnknown
*pProxy2
= NULL
;
1731 external_connections
= 0;
1733 hr
= CreateStreamOnHGlobal(NULL
, TRUE
, &pStream
);
1734 ok_ole_success(hr
, CreateStreamOnHGlobal
);
1735 hr
= CoMarshalInterface(pStream
, &IID_IClassFactory
, (IUnknown
*)&Test_ClassFactory
, MSHCTX_INPROC
, NULL
, MSHLFLAGS_NORMAL
);
1736 ok_ole_success(hr
, CoMarshalInterface
);
1738 ok_more_than_one_lock();
1739 ok_non_zero_external_conn();
1741 IStream_Seek(pStream
, ullZero
, STREAM_SEEK_SET
, NULL
);
1742 hr
= CoUnmarshalInterface(pStream
, &IID_IClassFactory
, (void **)&pProxy1
);
1743 ok_ole_success(hr
, CoUnmarshalInterface
);
1745 ok_more_than_one_lock();
1746 ok_zero_external_conn();
1747 ok_last_release_closes(FALSE
);
1749 IStream_Seek(pStream
, ullZero
, STREAM_SEEK_SET
, NULL
);
1750 hr
= CoUnmarshalInterface(pStream
, &IID_IClassFactory
, (void **)&pProxy2
);
1751 ok(hr
== CO_E_OBJNOTCONNECTED
,
1752 "CoUnmarshalInterface should have failed with error CO_E_OBJNOTCONNECTED for double unmarshal, instead of 0x%08x\n", hr
);
1754 IStream_Release(pStream
);
1756 ok_more_than_one_lock();
1758 IUnknown_Release(pProxy1
);
1763 /* tests success case of marshaling and unmarshaling an HRESULT */
1764 static void test_hresult_marshaling(void)
1767 HRESULT hr_marshaled
= 0;
1768 IStream
*pStream
= NULL
;
1769 static const HRESULT E_DEADBEEF
= 0xdeadbeef;
1771 hr
= CreateStreamOnHGlobal(NULL
, TRUE
, &pStream
);
1772 ok_ole_success(hr
, CreateStreamOnHGlobal
);
1774 hr
= CoMarshalHresult(pStream
, E_DEADBEEF
);
1775 ok_ole_success(hr
, CoMarshalHresult
);
1777 IStream_Seek(pStream
, ullZero
, STREAM_SEEK_SET
, NULL
);
1778 hr
= IStream_Read(pStream
, &hr_marshaled
, sizeof(HRESULT
), NULL
);
1779 ok_ole_success(hr
, IStream_Read
);
1781 ok(hr_marshaled
== E_DEADBEEF
, "Didn't marshal HRESULT as expected: got value 0x%08x instead\n", hr_marshaled
);
1784 IStream_Seek(pStream
, ullZero
, STREAM_SEEK_SET
, NULL
);
1785 hr
= CoUnmarshalHresult(pStream
, &hr_marshaled
);
1786 ok_ole_success(hr
, CoUnmarshalHresult
);
1788 ok(hr_marshaled
== E_DEADBEEF
, "Didn't marshal HRESULT as expected: got value 0x%08x instead\n", hr_marshaled
);
1790 IStream_Release(pStream
);
1794 /* helper for test_proxy_used_in_wrong_thread */
1795 static DWORD CALLBACK
bad_thread_proc(LPVOID p
)
1797 IClassFactory
* cf
= p
;
1799 IUnknown
* proxy
= NULL
;
1801 hr
= IClassFactory_CreateInstance(cf
, NULL
, &IID_IUnknown
, (LPVOID
*)&proxy
);
1803 ok(hr
== CO_E_NOTINITIALIZED
,
1804 "COM should have failed with CO_E_NOTINITIALIZED on using proxy without apartment, but instead returned 0x%08x\n",
1807 hr
= IClassFactory_QueryInterface(cf
, &IID_IMultiQI
, (LPVOID
*)&proxy
);
1808 /* Win9x returns S_OK, whilst NT returns RPC_E_WRONG_THREAD */
1809 trace("call to proxy's QueryInterface for local interface without apartment returned 0x%08x\n", hr
);
1811 IUnknown_Release(proxy
);
1813 hr
= IClassFactory_QueryInterface(cf
, &IID_IStream
, (LPVOID
*)&proxy
);
1814 /* Win9x returns E_NOINTERFACE, whilst NT returns RPC_E_WRONG_THREAD */
1815 trace("call to proxy's QueryInterface without apartment returned 0x%08x\n", hr
);
1817 IUnknown_Release(proxy
);
1819 pCoInitializeEx(NULL
, COINIT_MULTITHREADED
);
1821 hr
= IClassFactory_CreateInstance(cf
, NULL
, &IID_IUnknown
, (LPVOID
*)&proxy
);
1822 if (proxy
) IUnknown_Release(proxy
);
1823 ok(hr
== RPC_E_WRONG_THREAD
,
1824 "COM should have failed with RPC_E_WRONG_THREAD on using proxy from wrong apartment, but instead returned 0x%08x\n",
1827 hr
= IClassFactory_QueryInterface(cf
, &IID_IStream
, (LPVOID
*)&proxy
);
1828 /* Win9x returns E_NOINTERFACE, whilst NT returns RPC_E_WRONG_THREAD */
1829 trace("call to proxy's QueryInterface from wrong apartment returned 0x%08x\n", hr
);
1831 /* now be really bad and release the proxy from the wrong apartment */
1832 IClassFactory_Release(cf
);
1839 /* tests failure case of a using a proxy in the wrong apartment */
1840 static void test_proxy_used_in_wrong_thread(void)
1843 IStream
*pStream
= NULL
;
1844 IUnknown
*pProxy
= NULL
;
1851 hr
= CreateStreamOnHGlobal(NULL
, TRUE
, &pStream
);
1852 ok_ole_success(hr
, CreateStreamOnHGlobal
);
1853 tid
= start_host_object(pStream
, &IID_IClassFactory
, (IUnknown
*)&Test_ClassFactory
, MSHLFLAGS_NORMAL
, &host_thread
);
1855 ok_more_than_one_lock();
1857 IStream_Seek(pStream
, ullZero
, STREAM_SEEK_SET
, NULL
);
1858 hr
= CoUnmarshalInterface(pStream
, &IID_IClassFactory
, (void **)&pProxy
);
1859 ok_ole_success(hr
, CoUnmarshalInterface
);
1860 IStream_Release(pStream
);
1862 ok_more_than_one_lock();
1864 /* do a call that will fail, but result in IRemUnknown being used by the proxy */
1865 IUnknown_QueryInterface(pProxy
, &IID_IStream
, (LPVOID
*)&pStream
);
1867 /* create a thread that we can misbehave in */
1868 thread
= CreateThread(NULL
, 0, bad_thread_proc
, pProxy
, 0, &tid2
);
1870 ok( !WaitForSingleObject(thread
, 10000), "wait timed out\n" );
1871 CloseHandle(thread
);
1873 /* do release statement on Win9x that we should have done above */
1874 if (!GetProcAddress(GetModuleHandleA("ole32"), "CoRegisterSurrogateEx"))
1875 IUnknown_Release(pProxy
);
1879 end_host_object(tid
, host_thread
);
1882 static HRESULT WINAPI
MessageFilter_QueryInterface(IMessageFilter
*iface
, REFIID riid
, void ** ppvObj
)
1884 if (ppvObj
== NULL
) return E_POINTER
;
1886 if (IsEqualGUID(riid
, &IID_IUnknown
) ||
1887 IsEqualGUID(riid
, &IID_IClassFactory
))
1890 IMessageFilter_AddRef(iface
);
1894 return E_NOINTERFACE
;
1897 static ULONG WINAPI
MessageFilter_AddRef(IMessageFilter
*iface
)
1899 return 2; /* non-heap object */
1902 static ULONG WINAPI
MessageFilter_Release(IMessageFilter
*iface
)
1904 return 1; /* non-heap object */
1907 static DWORD WINAPI
MessageFilter_HandleInComingCall(
1908 IMessageFilter
*iface
,
1910 HTASK threadIDCaller
,
1912 LPINTERFACEINFO lpInterfaceInfo
)
1914 static int callcount
= 0;
1916 trace("HandleInComingCall\n");
1920 ret
= SERVERCALL_REJECTED
;
1923 ret
= SERVERCALL_RETRYLATER
;
1926 ret
= SERVERCALL_ISHANDLED
;
1933 static DWORD WINAPI
MessageFilter_RetryRejectedCall(
1934 IMessageFilter
*iface
,
1935 HTASK threadIDCallee
,
1939 trace("RetryRejectedCall\n");
1943 static DWORD WINAPI
MessageFilter_MessagePending(
1944 IMessageFilter
*iface
,
1945 HTASK threadIDCallee
,
1947 DWORD dwPendingType
)
1949 trace("MessagePending\n");
1950 return PENDINGMSG_WAITNOPROCESS
;
1953 static const IMessageFilterVtbl MessageFilter_Vtbl
=
1955 MessageFilter_QueryInterface
,
1956 MessageFilter_AddRef
,
1957 MessageFilter_Release
,
1958 MessageFilter_HandleInComingCall
,
1959 MessageFilter_RetryRejectedCall
,
1960 MessageFilter_MessagePending
1963 static IMessageFilter MessageFilter
= { &MessageFilter_Vtbl
};
1965 static void test_message_filter(void)
1968 IStream
*pStream
= NULL
;
1969 IClassFactory
*cf
= NULL
;
1971 IUnknown
*proxy
= NULL
;
1972 IMessageFilter
*prev_filter
= NULL
;
1977 hr
= CreateStreamOnHGlobal(NULL
, TRUE
, &pStream
);
1978 ok_ole_success(hr
, CreateStreamOnHGlobal
);
1979 tid
= start_host_object2(pStream
, &IID_IClassFactory
, (IUnknown
*)&Test_ClassFactory
, MSHLFLAGS_NORMAL
, &MessageFilter
, &thread
);
1981 ok_more_than_one_lock();
1983 IStream_Seek(pStream
, ullZero
, STREAM_SEEK_SET
, NULL
);
1984 hr
= CoUnmarshalInterface(pStream
, &IID_IClassFactory
, (void **)&cf
);
1985 ok_ole_success(hr
, CoUnmarshalInterface
);
1986 IStream_Release(pStream
);
1988 ok_more_than_one_lock();
1990 hr
= IClassFactory_CreateInstance(cf
, NULL
, &IID_IUnknown
, (LPVOID
*)&proxy
);
1991 ok(hr
== RPC_E_CALL_REJECTED
, "Call should have returned RPC_E_CALL_REJECTED, but return 0x%08x instead\n", hr
);
1992 if (proxy
) IUnknown_Release(proxy
);
1995 hr
= CoRegisterMessageFilter(&MessageFilter
, &prev_filter
);
1996 ok_ole_success(hr
, CoRegisterMessageFilter
);
1998 hr
= IClassFactory_CreateInstance(cf
, NULL
, &IID_IUnknown
, (LPVOID
*)&proxy
);
1999 ok_ole_success(hr
, IClassFactory_CreateInstance
);
2001 IUnknown_Release(proxy
);
2003 IClassFactory_Release(cf
);
2007 end_host_object(tid
, thread
);
2009 hr
= CoRegisterMessageFilter(prev_filter
, NULL
);
2010 ok_ole_success(hr
, CoRegisterMessageFilter
);
2013 /* test failure case of trying to unmarshal from bad stream */
2014 static void test_bad_marshal_stream(void)
2017 IStream
*pStream
= NULL
;
2019 hr
= CreateStreamOnHGlobal(NULL
, TRUE
, &pStream
);
2020 ok_ole_success(hr
, CreateStreamOnHGlobal
);
2021 hr
= CoMarshalInterface(pStream
, &IID_IClassFactory
, (IUnknown
*)&Test_ClassFactory
, MSHCTX_INPROC
, NULL
, MSHLFLAGS_NORMAL
);
2022 ok_ole_success(hr
, CoMarshalInterface
);
2024 ok_more_than_one_lock();
2026 /* try to read beyond end of stream */
2027 hr
= CoReleaseMarshalData(pStream
);
2028 ok(hr
== STG_E_READFAULT
, "Should have failed with STG_E_READFAULT, but returned 0x%08x instead\n", hr
);
2030 /* now release for real */
2031 IStream_Seek(pStream
, ullZero
, STREAM_SEEK_SET
, NULL
);
2032 hr
= CoReleaseMarshalData(pStream
);
2033 ok_ole_success(hr
, CoReleaseMarshalData
);
2035 IStream_Release(pStream
);
2038 /* tests that proxies implement certain interfaces */
2039 static void test_proxy_interfaces(void)
2042 IStream
*pStream
= NULL
;
2043 IUnknown
*pProxy
= NULL
;
2044 IUnknown
*pOtherUnknown
= NULL
;
2050 hr
= CreateStreamOnHGlobal(NULL
, TRUE
, &pStream
);
2051 ok_ole_success(hr
, CreateStreamOnHGlobal
);
2052 tid
= start_host_object(pStream
, &IID_IClassFactory
, (IUnknown
*)&Test_ClassFactory
, MSHLFLAGS_NORMAL
, &thread
);
2054 ok_more_than_one_lock();
2056 IStream_Seek(pStream
, ullZero
, STREAM_SEEK_SET
, NULL
);
2057 hr
= CoUnmarshalInterface(pStream
, &IID_IUnknown
, (void **)&pProxy
);
2058 ok_ole_success(hr
, CoUnmarshalInterface
);
2059 IStream_Release(pStream
);
2061 ok_more_than_one_lock();
2063 hr
= IUnknown_QueryInterface(pProxy
, &IID_IUnknown
, (LPVOID
*)&pOtherUnknown
);
2064 ok_ole_success(hr
, IUnknown_QueryInterface IID_IUnknown
);
2065 if (hr
== S_OK
) IUnknown_Release(pOtherUnknown
);
2067 hr
= IUnknown_QueryInterface(pProxy
, &IID_IClientSecurity
, (LPVOID
*)&pOtherUnknown
);
2068 ok_ole_success(hr
, IUnknown_QueryInterface IID_IClientSecurity
);
2069 if (hr
== S_OK
) IUnknown_Release(pOtherUnknown
);
2071 hr
= IUnknown_QueryInterface(pProxy
, &IID_IMultiQI
, (LPVOID
*)&pOtherUnknown
);
2072 ok_ole_success(hr
, IUnknown_QueryInterface IID_IMultiQI
);
2073 if (hr
== S_OK
) IUnknown_Release(pOtherUnknown
);
2075 hr
= IUnknown_QueryInterface(pProxy
, &IID_IMarshal
, (LPVOID
*)&pOtherUnknown
);
2076 ok_ole_success(hr
, IUnknown_QueryInterface IID_IMarshal
);
2077 if (hr
== S_OK
) IUnknown_Release(pOtherUnknown
);
2079 /* IMarshal2 is also supported on NT-based systems, but is pretty much
2080 * useless as it has no more methods over IMarshal that it inherits from. */
2082 IUnknown_Release(pProxy
);
2086 end_host_object(tid
, thread
);
2091 IUnknown IUnknown_iface
;
2095 static inline HeapUnknown
*impl_from_IUnknown(IUnknown
*iface
)
2097 return CONTAINING_RECORD(iface
, HeapUnknown
, IUnknown_iface
);
2100 static HRESULT WINAPI
HeapUnknown_QueryInterface(IUnknown
*iface
, REFIID riid
, void **ppv
)
2102 if (IsEqualIID(riid
, &IID_IUnknown
))
2104 IUnknown_AddRef(iface
);
2109 return E_NOINTERFACE
;
2112 static ULONG WINAPI
HeapUnknown_AddRef(IUnknown
*iface
)
2114 HeapUnknown
*This
= impl_from_IUnknown(iface
);
2115 return InterlockedIncrement((LONG
*)&This
->refs
);
2118 static ULONG WINAPI
HeapUnknown_Release(IUnknown
*iface
)
2120 HeapUnknown
*This
= impl_from_IUnknown(iface
);
2121 ULONG refs
= InterlockedDecrement((LONG
*)&This
->refs
);
2122 if (!refs
) HeapFree(GetProcessHeap(), 0, This
);
2126 static const IUnknownVtbl HeapUnknown_Vtbl
=
2128 HeapUnknown_QueryInterface
,
2133 static void test_proxybuffer(REFIID riid
)
2136 IPSFactoryBuffer
*psfb
;
2137 IRpcProxyBuffer
*proxy
;
2141 HeapUnknown
*pUnkOuter
= HeapAlloc(GetProcessHeap(), 0, sizeof(*pUnkOuter
));
2143 pUnkOuter
->IUnknown_iface
.lpVtbl
= &HeapUnknown_Vtbl
;
2144 pUnkOuter
->refs
= 1;
2146 hr
= CoGetPSClsid(riid
, &clsid
);
2147 ok_ole_success(hr
, CoGetPSClsid
);
2149 hr
= CoGetClassObject(&clsid
, CLSCTX_INPROC_SERVER
, NULL
, &IID_IPSFactoryBuffer
, (LPVOID
*)&psfb
);
2150 ok_ole_success(hr
, CoGetClassObject
);
2152 hr
= IPSFactoryBuffer_CreateProxy(psfb
, &pUnkOuter
->IUnknown_iface
, riid
, &proxy
, &lpvtbl
);
2153 ok_ole_success(hr
, IPSFactoryBuffer_CreateProxy
);
2154 ok(lpvtbl
!= NULL
, "IPSFactoryBuffer_CreateProxy succeeded, but returned a NULL vtable!\n");
2156 /* release our reference to the outer unknown object - the PS factory
2157 * buffer will have AddRef's it in the CreateProxy call */
2158 refs
= IUnknown_Release(&pUnkOuter
->IUnknown_iface
);
2159 ok(refs
== 1, "Ref count of outer unknown should have been 1 instead of %d\n", refs
);
2161 /* Not checking return, unreliable on native. Maybe it leaks references? */
2162 IPSFactoryBuffer_Release(psfb
);
2164 refs
= IUnknown_Release((IUnknown
*)lpvtbl
);
2165 ok(refs
== 0, "Ref-count leak of %d on IRpcProxyBuffer\n", refs
);
2167 refs
= IRpcProxyBuffer_Release(proxy
);
2168 ok(refs
== 0, "Ref-count leak of %d on IRpcProxyBuffer\n", refs
);
2171 static void test_stubbuffer(REFIID riid
)
2174 IPSFactoryBuffer
*psfb
;
2175 IRpcStubBuffer
*stub
;
2181 hr
= CoGetPSClsid(riid
, &clsid
);
2182 ok_ole_success(hr
, CoGetPSClsid
);
2184 hr
= CoGetClassObject(&clsid
, CLSCTX_INPROC_SERVER
, NULL
, &IID_IPSFactoryBuffer
, (LPVOID
*)&psfb
);
2185 ok_ole_success(hr
, CoGetClassObject
);
2187 hr
= IPSFactoryBuffer_CreateStub(psfb
, riid
, (IUnknown
*)&Test_ClassFactory
, &stub
);
2188 ok_ole_success(hr
, IPSFactoryBuffer_CreateStub
);
2190 /* Not checking return, unreliable on native. Maybe it leaks references? */
2191 IPSFactoryBuffer_Release(psfb
);
2193 ok_more_than_one_lock();
2195 IRpcStubBuffer_Disconnect(stub
);
2199 refs
= IRpcStubBuffer_Release(stub
);
2200 ok(refs
== 0, "Ref-count leak of %d on IRpcProxyBuffer\n", refs
);
2203 static HWND hwnd_app
;
2205 static HRESULT WINAPI
TestRE_IClassFactory_CreateInstance(
2206 LPCLASSFACTORY iface
,
2207 LPUNKNOWN pUnkOuter
,
2212 if (IsEqualIID(riid
, &IID_IWineTest
))
2214 BOOL ret
= SendMessageTimeoutA(hwnd_app
, WM_NULL
, 0, 0, SMTO_BLOCK
, 5000, &res
);
2215 ok(ret
, "Timed out sending a message to originating window during RPC call\n");
2221 static const IClassFactoryVtbl TestREClassFactory_Vtbl
=
2223 Test_IClassFactory_QueryInterface
,
2224 Test_IClassFactory_AddRef
,
2225 Test_IClassFactory_Release
,
2226 TestRE_IClassFactory_CreateInstance
,
2227 Test_IClassFactory_LockServer
2230 static IClassFactory TestRE_ClassFactory
= { &TestREClassFactory_Vtbl
};
2232 static LRESULT CALLBACK
window_proc(HWND hwnd
, UINT msg
, WPARAM wparam
, LPARAM lparam
)
2239 IStream
*pStream
= NULL
;
2240 IClassFactory
*proxy
= NULL
;
2247 hr
= CreateStreamOnHGlobal(NULL
, TRUE
, &pStream
);
2248 ok_ole_success(hr
, CreateStreamOnHGlobal
);
2249 tid
= start_host_object(pStream
, &IID_IClassFactory
, (IUnknown
*)&TestRE_ClassFactory
, MSHLFLAGS_NORMAL
, &thread
);
2251 ok_more_than_one_lock();
2253 IStream_Seek(pStream
, ullZero
, STREAM_SEEK_SET
, NULL
);
2254 hr
= CoUnmarshalInterface(pStream
, &IID_IClassFactory
, (void **)&proxy
);
2255 ok_ole_success(hr
, CoReleaseMarshalData
);
2256 IStream_Release(pStream
);
2258 ok_more_than_one_lock();
2260 /* note the use of the magic IID_IWineTest value to tell remote thread
2261 * to try to send a message back to us */
2262 hr
= IClassFactory_CreateInstance(proxy
, NULL
, &IID_IWineTest
, (void **)&object
);
2263 ok(hr
== S_FALSE
, "expected S_FALSE, got %d\n", hr
);
2265 IClassFactory_Release(proxy
);
2269 end_host_object(tid
, thread
);
2271 PostMessageA(hwnd
, WM_QUIT
, 0, 0);
2278 IStream
*pStream
= NULL
;
2279 IClassFactory
*proxy
= NULL
;
2286 hr
= CreateStreamOnHGlobal(NULL
, TRUE
, &pStream
);
2287 ok_ole_success(hr
, CreateStreamOnHGlobal
);
2288 tid
= start_host_object(pStream
, &IID_IClassFactory
, (IUnknown
*)&TestRE_ClassFactory
, MSHLFLAGS_NORMAL
, &thread
);
2290 ok_more_than_one_lock();
2292 IStream_Seek(pStream
, ullZero
, STREAM_SEEK_SET
, NULL
);
2293 hr
= CoUnmarshalInterface(pStream
, &IID_IClassFactory
, (void **)&proxy
);
2294 ok_ole_success(hr
, CoReleaseMarshalData
);
2295 IStream_Release(pStream
);
2297 ok_more_than_one_lock();
2299 /* post quit message before a doing a COM call to show that a pending
2300 * WM_QUIT message doesn't stop the call from succeeding */
2301 PostMessageA(hwnd
, WM_QUIT
, 0, 0);
2302 hr
= IClassFactory_CreateInstance(proxy
, NULL
, &IID_IUnknown
, (void **)&object
);
2303 ok(hr
== S_FALSE
, "IClassFactory_CreateInstance returned 0x%08x, expected S_FALSE\n", hr
);
2305 IClassFactory_Release(proxy
);
2309 end_host_object(tid
, thread
);
2316 IStream
*pStream
= NULL
;
2317 IClassFactory
*proxy
= NULL
;
2322 hr
= CreateStreamOnHGlobal(NULL
, TRUE
, &pStream
);
2323 ok_ole_success(hr
, CreateStreamOnHGlobal
);
2324 tid
= start_host_object(pStream
, &IID_IClassFactory
, (IUnknown
*)&Test_ClassFactory
, MSHLFLAGS_NORMAL
, &thread
);
2326 IStream_Seek(pStream
, ullZero
, STREAM_SEEK_SET
, NULL
);
2327 hr
= CoUnmarshalInterface(pStream
, &IID_IClassFactory
, (void **)&proxy
);
2328 ok_ole_success(hr
, CoReleaseMarshalData
);
2329 IStream_Release(pStream
);
2331 /* shows that COM calls executed during the processing of sent
2332 * messages should fail */
2333 hr
= IClassFactory_CreateInstance(proxy
, NULL
, &IID_IUnknown
, (void **)&object
);
2334 ok(hr
== RPC_E_CANTCALLOUT_ININPUTSYNCCALL
,
2335 "COM call during processing of sent message should return RPC_E_CANTCALLOUT_ININPUTSYNCCALL instead of 0x%08x\n", hr
);
2337 IClassFactory_Release(proxy
);
2339 end_host_object(tid
, thread
);
2346 return DefWindowProcA(hwnd
, msg
, wparam
, lparam
);
2350 static void register_test_window(void)
2354 memset(&wndclass
, 0, sizeof(wndclass
));
2355 wndclass
.lpfnWndProc
= window_proc
;
2356 wndclass
.lpszClassName
= "WineCOMTest";
2357 RegisterClassA(&wndclass
);
2360 static void test_message_reentrancy(void)
2364 hwnd_app
= CreateWindowA("WineCOMTest", NULL
, 0, CW_USEDEFAULT
, CW_USEDEFAULT
, CW_USEDEFAULT
, CW_USEDEFAULT
, NULL
, NULL
, NULL
, 0);
2365 ok(hwnd_app
!= NULL
, "Window creation failed\n");
2367 /* start message re-entrancy test */
2368 PostMessageA(hwnd_app
, WM_USER
, 0, 0);
2370 while (GetMessageA(&msg
, NULL
, 0, 0))
2372 TranslateMessage(&msg
);
2373 DispatchMessageA(&msg
);
2375 DestroyWindow(hwnd_app
);
2378 static HRESULT WINAPI
TestMsg_IClassFactory_CreateInstance(
2379 LPCLASSFACTORY iface
,
2380 LPUNKNOWN pUnkOuter
,
2385 SendMessageA(hwnd_app
, WM_USER
+2, 0, 0);
2389 static IClassFactoryVtbl TestMsgClassFactory_Vtbl
=
2391 Test_IClassFactory_QueryInterface
,
2392 Test_IClassFactory_AddRef
,
2393 Test_IClassFactory_Release
,
2394 TestMsg_IClassFactory_CreateInstance
,
2395 Test_IClassFactory_LockServer
2398 static IClassFactory TestMsg_ClassFactory
= { &TestMsgClassFactory_Vtbl
};
2400 static void test_call_from_message(void)
2405 IClassFactory
*proxy
;
2410 hwnd_app
= CreateWindowA("WineCOMTest", NULL
, 0, CW_USEDEFAULT
, CW_USEDEFAULT
, CW_USEDEFAULT
, CW_USEDEFAULT
, NULL
, NULL
, NULL
, 0);
2411 ok(hwnd_app
!= NULL
, "Window creation failed\n");
2413 hr
= CreateStreamOnHGlobal(NULL
, TRUE
, &pStream
);
2414 ok_ole_success(hr
, CreateStreamOnHGlobal
);
2415 tid
= start_host_object(pStream
, &IID_IClassFactory
, (IUnknown
*)&TestMsg_ClassFactory
, MSHLFLAGS_NORMAL
, &thread
);
2417 ok_more_than_one_lock();
2419 IStream_Seek(pStream
, ullZero
, STREAM_SEEK_SET
, NULL
);
2420 hr
= CoUnmarshalInterface(pStream
, &IID_IClassFactory
, (void **)&proxy
);
2421 ok_ole_success(hr
, CoReleaseMarshalData
);
2422 IStream_Release(pStream
);
2424 ok_more_than_one_lock();
2426 /* start message re-entrancy test */
2427 hr
= IClassFactory_CreateInstance(proxy
, NULL
, &IID_IUnknown
, (void **)&object
);
2428 ok_ole_success(hr
, IClassFactory_CreateInstance
);
2430 IClassFactory_Release(proxy
);
2434 end_host_object(tid
, thread
);
2436 while (GetMessageA(&msg
, NULL
, 0, 0))
2438 TranslateMessage(&msg
);
2439 DispatchMessageA(&msg
);
2441 DestroyWindow(hwnd_app
);
2444 static void test_WM_QUIT_handling(void)
2448 hwnd_app
= CreateWindowA("WineCOMTest", NULL
, 0, CW_USEDEFAULT
, CW_USEDEFAULT
, CW_USEDEFAULT
, CW_USEDEFAULT
, NULL
, NULL
, NULL
, 0);
2449 ok(hwnd_app
!= NULL
, "Window creation failed\n");
2451 /* start WM_QUIT handling test */
2452 PostMessageA(hwnd_app
, WM_USER
+1, 0, 0);
2454 while (GetMessageA(&msg
, NULL
, 0, 0))
2456 TranslateMessage(&msg
);
2457 DispatchMessageA(&msg
);
2461 static SIZE_T
round_global_size(SIZE_T size
)
2463 static SIZE_T global_size_alignment
= -1;
2464 if (global_size_alignment
== -1)
2466 void *p
= GlobalAlloc(GMEM_FIXED
, 1);
2467 global_size_alignment
= GlobalSize(p
);
2471 return ((size
+ global_size_alignment
- 1) & ~(global_size_alignment
- 1));
2474 static void test_freethreadedmarshaldata(IStream
*pStream
, MSHCTX mshctx
, void *ptr
, DWORD mshlflags
)
2481 hr
= GetHGlobalFromStream(pStream
, &hglobal
);
2482 ok_ole_success(hr
, GetHGlobalFromStream
);
2484 size
= GlobalSize(hglobal
);
2486 marshal_data
= GlobalLock(hglobal
);
2488 if (mshctx
== MSHCTX_INPROC
)
2490 DWORD expected_size
= round_global_size(3*sizeof(DWORD
) + sizeof(GUID
));
2491 ok(size
== expected_size
||
2492 broken(size
== (2*sizeof(DWORD
))) /* Win9x & NT4 */,
2493 "size should have been %d instead of %d\n", expected_size
, size
);
2495 ok(*(DWORD
*)marshal_data
== mshlflags
, "expected 0x%x, but got 0x%x for mshctx\n", mshlflags
, *(DWORD
*)marshal_data
);
2496 marshal_data
+= sizeof(DWORD
);
2497 ok(*(void **)marshal_data
== ptr
, "expected %p, but got %p for mshctx\n", ptr
, *(void **)marshal_data
);
2498 marshal_data
+= sizeof(void *);
2499 if (sizeof(void*) == 4 && size
>= 3*sizeof(DWORD
))
2501 ok(*(DWORD
*)marshal_data
== 0, "expected 0x0, but got 0x%x\n", *(DWORD
*)marshal_data
);
2502 marshal_data
+= sizeof(DWORD
);
2504 if (size
>= 3*sizeof(DWORD
) + sizeof(GUID
))
2506 trace("got guid data: %s\n", wine_dbgstr_guid((GUID
*)marshal_data
));
2511 ok(size
> sizeof(DWORD
), "size should have been > sizeof(DWORD), not %d\n", size
);
2512 ok(*(DWORD
*)marshal_data
== 0x574f454d /* MEOW */,
2513 "marshal data should be filled by standard marshal and start with MEOW signature\n");
2516 GlobalUnlock(hglobal
);
2519 static void test_freethreadedmarshaler(void)
2522 IUnknown
*pFTUnknown
;
2523 IMarshal
*pFTMarshal
;
2526 static const LARGE_INTEGER llZero
;
2529 hr
= CoCreateFreeThreadedMarshaler(NULL
, &pFTUnknown
);
2530 ok_ole_success(hr
, CoCreateFreeThreadedMarshaler
);
2531 hr
= IUnknown_QueryInterface(pFTUnknown
, &IID_IMarshal
, (void **)&pFTMarshal
);
2532 ok_ole_success(hr
, IUnknown_QueryInterface
);
2533 IUnknown_Release(pFTUnknown
);
2535 hr
= CreateStreamOnHGlobal(NULL
, TRUE
, &pStream
);
2536 ok_ole_success(hr
, CreateStreamOnHGlobal
);
2538 /* inproc normal marshaling */
2540 hr
= IMarshal_MarshalInterface(pFTMarshal
, pStream
, &IID_IClassFactory
,
2541 &Test_ClassFactory
, MSHCTX_INPROC
, NULL
, MSHLFLAGS_NORMAL
);
2542 ok_ole_success(hr
, IMarshal_MarshalInterface
);
2544 ok_more_than_one_lock();
2546 test_freethreadedmarshaldata(pStream
, MSHCTX_INPROC
, &Test_ClassFactory
, MSHLFLAGS_NORMAL
);
2548 IStream_Seek(pStream
, llZero
, STREAM_SEEK_SET
, NULL
);
2549 hr
= IMarshal_UnmarshalInterface(pFTMarshal
, pStream
, &IID_IUnknown
, (void **)&pProxy
);
2550 ok_ole_success(hr
, IMarshal_UnmarshalInterface
);
2552 IUnknown_Release(pProxy
);
2556 /* native doesn't allow us to unmarshal or release the stream data,
2557 * presumably because it wants us to call CoMarshalInterface instead */
2560 /* local normal marshaling */
2562 IStream_Seek(pStream
, llZero
, STREAM_SEEK_SET
, NULL
);
2563 hr
= IMarshal_MarshalInterface(pFTMarshal
, pStream
, &IID_IClassFactory
, &Test_ClassFactory
, MSHCTX_LOCAL
, NULL
, MSHLFLAGS_NORMAL
);
2564 ok_ole_success(hr
, IMarshal_MarshalInterface
);
2566 ok_more_than_one_lock();
2568 test_freethreadedmarshaldata(pStream
, MSHCTX_LOCAL
, &Test_ClassFactory
, MSHLFLAGS_NORMAL
);
2570 IStream_Seek(pStream
, llZero
, STREAM_SEEK_SET
, NULL
);
2571 hr
= IMarshal_ReleaseMarshalData(pFTMarshal
, pStream
);
2572 ok_ole_success(hr
, IMarshal_ReleaseMarshalData
);
2577 /* inproc table-strong marshaling */
2579 IStream_Seek(pStream
, llZero
, STREAM_SEEK_SET
, NULL
);
2580 hr
= IMarshal_MarshalInterface(pFTMarshal
, pStream
, &IID_IClassFactory
,
2581 (IUnknown
*)&Test_ClassFactory
, MSHCTX_INPROC
, (void *)0xdeadbeef,
2582 MSHLFLAGS_TABLESTRONG
);
2583 ok_ole_success(hr
, IMarshal_MarshalInterface
);
2585 ok_more_than_one_lock();
2587 test_freethreadedmarshaldata(pStream
, MSHCTX_INPROC
, &Test_ClassFactory
, MSHLFLAGS_TABLESTRONG
);
2589 IStream_Seek(pStream
, llZero
, STREAM_SEEK_SET
, NULL
);
2590 hr
= IMarshal_UnmarshalInterface(pFTMarshal
, pStream
, &IID_IUnknown
, (void **)&pProxy
);
2591 ok_ole_success(hr
, IMarshal_UnmarshalInterface
);
2593 IUnknown_Release(pProxy
);
2595 ok_more_than_one_lock();
2597 IStream_Seek(pStream
, llZero
, STREAM_SEEK_SET
, NULL
);
2598 hr
= IMarshal_ReleaseMarshalData(pFTMarshal
, pStream
);
2599 ok_ole_success(hr
, IMarshal_ReleaseMarshalData
);
2603 /* inproc table-weak marshaling */
2605 IStream_Seek(pStream
, llZero
, STREAM_SEEK_SET
, NULL
);
2606 hr
= IMarshal_MarshalInterface(pFTMarshal
, pStream
, &IID_IClassFactory
,
2607 (IUnknown
*)&Test_ClassFactory
, MSHCTX_INPROC
, (void *)0xdeadbeef,
2608 MSHLFLAGS_TABLEWEAK
);
2609 ok_ole_success(hr
, IMarshal_MarshalInterface
);
2613 test_freethreadedmarshaldata(pStream
, MSHCTX_INPROC
, &Test_ClassFactory
, MSHLFLAGS_TABLEWEAK
);
2615 IStream_Seek(pStream
, llZero
, STREAM_SEEK_SET
, NULL
);
2616 hr
= IMarshal_UnmarshalInterface(pFTMarshal
, pStream
, &IID_IUnknown
, (void **)&pProxy
);
2617 ok_ole_success(hr
, IMarshal_UnmarshalInterface
);
2619 ok_more_than_one_lock();
2621 IUnknown_Release(pProxy
);
2625 /* inproc normal marshaling (for extraordinary cases) */
2627 IStream_Seek(pStream
, llZero
, STREAM_SEEK_SET
, NULL
);
2628 hr
= IMarshal_MarshalInterface(pFTMarshal
, pStream
, &IID_IClassFactory
,
2629 &Test_ClassFactory
, MSHCTX_INPROC
, NULL
, MSHLFLAGS_NORMAL
);
2630 ok_ole_success(hr
, IMarshal_MarshalInterface
);
2632 ok_more_than_one_lock();
2634 /* this call shows that DisconnectObject does nothing */
2635 hr
= IMarshal_DisconnectObject(pFTMarshal
, 0);
2636 ok_ole_success(hr
, IMarshal_DisconnectObject
);
2638 ok_more_than_one_lock();
2640 IStream_Seek(pStream
, llZero
, STREAM_SEEK_SET
, NULL
);
2641 hr
= IMarshal_ReleaseMarshalData(pFTMarshal
, pStream
);
2642 ok_ole_success(hr
, IMarshal_ReleaseMarshalData
);
2646 /* doesn't enforce marshaling rules here and allows us to unmarshal the
2647 * interface, even though it was freed above */
2648 IStream_Seek(pStream
, llZero
, STREAM_SEEK_SET
, NULL
);
2649 hr
= IMarshal_UnmarshalInterface(pFTMarshal
, pStream
, &IID_IUnknown
, (void **)&pProxy
);
2650 ok_ole_success(hr
, IMarshal_UnmarshalInterface
);
2654 IStream_Release(pStream
);
2655 IMarshal_Release(pFTMarshal
);
2658 static HRESULT
reg_unreg_wine_test_class(BOOL Register
)
2664 DWORD dwDisposition
;
2667 hr
= StringFromCLSID(&CLSID_WineTest
, &pszClsid
);
2668 ok_ole_success(hr
, "StringFromCLSID");
2669 strcpy(buffer
, "CLSID\\");
2670 WideCharToMultiByte(CP_ACP
, 0, pszClsid
, -1, buffer
+ strlen(buffer
), sizeof(buffer
) - strlen(buffer
), NULL
, NULL
);
2671 CoTaskMemFree(pszClsid
);
2672 strcat(buffer
, "\\InprocHandler32");
2675 error
= RegCreateKeyExA(HKEY_CLASSES_ROOT
, buffer
, 0, NULL
, 0, KEY_SET_VALUE
, NULL
, &hkey
, &dwDisposition
);
2676 if (error
== ERROR_ACCESS_DENIED
)
2678 skip("Not authorized to modify the Classes key\n");
2681 ok(error
== ERROR_SUCCESS
, "RegCreateKeyEx failed with error %d\n", error
);
2682 if (error
!= ERROR_SUCCESS
) hr
= E_FAIL
;
2683 error
= RegSetValueExA(hkey
, NULL
, 0, REG_SZ
, (const unsigned char *)"\"ole32.dll\"", strlen("\"ole32.dll\"") + 1);
2684 ok(error
== ERROR_SUCCESS
, "RegSetValueEx failed with error %d\n", error
);
2685 if (error
!= ERROR_SUCCESS
) hr
= E_FAIL
;
2690 RegDeleteKeyA(HKEY_CLASSES_ROOT
, buffer
);
2691 *strrchr(buffer
, '\\') = '\0';
2692 RegDeleteKeyA(HKEY_CLASSES_ROOT
, buffer
);
2697 static void test_inproc_handler(void)
2703 if (FAILED(reg_unreg_wine_test_class(TRUE
)))
2706 hr
= CoCreateInstance(&CLSID_WineTest
, NULL
, CLSCTX_INPROC_HANDLER
, &IID_IUnknown
, (void **)&pObject
);
2707 ok_ole_success(hr
, "CoCreateInstance");
2711 hr
= IUnknown_QueryInterface(pObject
, &IID_IWineTest
, (void **)&pObject2
);
2712 ok(hr
== E_NOINTERFACE
, "IUnknown_QueryInterface on handler for invalid interface returned 0x%08x instead of E_NOINTERFACE\n", hr
);
2714 /* it's a handler as it supports IOleObject */
2715 hr
= IUnknown_QueryInterface(pObject
, &IID_IOleObject
, (void **)&pObject2
);
2716 ok_ole_success(hr
, "IUnknown_QueryInterface(&IID_IOleObject)");
2717 IUnknown_Release(pObject2
);
2719 IUnknown_Release(pObject
);
2722 reg_unreg_wine_test_class(FALSE
);
2725 static HRESULT WINAPI
Test_SMI_QueryInterface(
2726 IStdMarshalInfo
*iface
,
2730 if (ppvObj
== NULL
) return E_POINTER
;
2732 if (IsEqualGUID(riid
, &IID_IUnknown
) ||
2733 IsEqualGUID(riid
, &IID_IStdMarshalInfo
))
2736 IStdMarshalInfo_AddRef(iface
);
2740 return E_NOINTERFACE
;
2743 static ULONG WINAPI
Test_SMI_AddRef(IStdMarshalInfo
*iface
)
2746 return 2; /* non-heap-based object */
2749 static ULONG WINAPI
Test_SMI_Release(IStdMarshalInfo
*iface
)
2752 return 1; /* non-heap-based object */
2755 static HRESULT WINAPI
Test_SMI_GetClassForHandler(
2756 IStdMarshalInfo
*iface
,
2757 DWORD dwDestContext
,
2758 void *pvDestContext
,
2761 *pClsid
= CLSID_WineTest
;
2765 static const IStdMarshalInfoVtbl Test_SMI_Vtbl
=
2767 Test_SMI_QueryInterface
,
2770 Test_SMI_GetClassForHandler
2773 static IStdMarshalInfo Test_SMI
= {&Test_SMI_Vtbl
};
2775 static void test_handler_marshaling(void)
2778 IStream
*pStream
= NULL
;
2779 IUnknown
*pProxy
= NULL
;
2783 static const LARGE_INTEGER ullZero
;
2785 if (FAILED(reg_unreg_wine_test_class(TRUE
)))
2789 hr
= CreateStreamOnHGlobal(NULL
, TRUE
, &pStream
);
2790 ok_ole_success(hr
, "CreateStreamOnHGlobal");
2791 tid
= start_host_object(pStream
, &IID_IUnknown
, (IUnknown
*)&Test_SMI
, MSHLFLAGS_NORMAL
, &thread
);
2793 ok_more_than_one_lock();
2795 IStream_Seek(pStream
, ullZero
, STREAM_SEEK_SET
, NULL
);
2796 hr
= CoUnmarshalInterface(pStream
, &IID_IUnknown
, (void **)&pProxy
);
2797 ok_ole_success(hr
, "CoUnmarshalInterface");
2798 IStream_Release(pStream
);
2802 ok_more_than_one_lock();
2804 hr
= IUnknown_QueryInterface(pProxy
, &IID_IWineTest
, (void **)&pObject
);
2805 ok(hr
== E_NOINTERFACE
, "IUnknown_QueryInterface with unknown IID should have returned E_NOINTERFACE instead of 0x%08x\n", hr
);
2807 /* it's a handler as it supports IOleObject */
2808 hr
= IUnknown_QueryInterface(pProxy
, &IID_IOleObject
, (void **)&pObject
);
2810 ok_ole_success(hr
, "IUnknown_QueryInterface(&IID_IOleObject)");
2811 if (SUCCEEDED(hr
)) IUnknown_Release(pObject
);
2813 IUnknown_Release(pProxy
);
2818 end_host_object(tid
, thread
);
2819 reg_unreg_wine_test_class(FALSE
);
2821 /* FIXME: test IPersist interface has the same effect as IStdMarshalInfo */
2825 static void test_client_security(void)
2828 IStream
*pStream
= NULL
;
2829 IClassFactory
*pProxy
= NULL
;
2830 IUnknown
*pProxy2
= NULL
;
2831 IUnknown
*pUnknown1
= NULL
;
2832 IUnknown
*pUnknown2
= NULL
;
2833 IClientSecurity
*pCliSec
= NULL
;
2837 static const LARGE_INTEGER ullZero
;
2840 OLECHAR
*pServerPrincName
;
2844 DWORD dwCapabilities
;
2849 hr
= CreateStreamOnHGlobal(NULL
, TRUE
, &pStream
);
2850 ok_ole_success(hr
, "CreateStreamOnHGlobal");
2851 tid
= start_host_object(pStream
, &IID_IClassFactory
, (IUnknown
*)&Test_ClassFactory
, MSHLFLAGS_NORMAL
, &thread
);
2853 IStream_Seek(pStream
, ullZero
, STREAM_SEEK_SET
, NULL
);
2854 hr
= CoUnmarshalInterface(pStream
, &IID_IClassFactory
, (void **)&pProxy
);
2855 ok_ole_success(hr
, "CoUnmarshalInterface");
2856 IStream_Release(pStream
);
2858 hr
= IClassFactory_QueryInterface(pProxy
, &IID_IUnknown
, (LPVOID
*)&pUnknown1
);
2859 ok_ole_success(hr
, "IUnknown_QueryInterface IID_IUnknown");
2861 hr
= IClassFactory_QueryInterface(pProxy
, &IID_IRemUnknown
, (LPVOID
*)&pProxy2
);
2862 ok_ole_success(hr
, "IUnknown_QueryInterface IID_IStream");
2864 hr
= IUnknown_QueryInterface(pProxy2
, &IID_IUnknown
, (LPVOID
*)&pUnknown2
);
2865 ok_ole_success(hr
, "IUnknown_QueryInterface IID_IUnknown");
2867 ok(pUnknown1
== pUnknown2
, "both proxy's IUnknowns should be the same - %p, %p\n", pUnknown1
, pUnknown2
);
2869 hr
= IClassFactory_QueryInterface(pProxy
, &IID_IMarshal
, (LPVOID
*)&pMarshal
);
2870 ok_ole_success(hr
, "IUnknown_QueryInterface IID_IMarshal");
2872 hr
= IClassFactory_QueryInterface(pProxy
, &IID_IClientSecurity
, (LPVOID
*)&pCliSec
);
2873 ok_ole_success(hr
, "IUnknown_QueryInterface IID_IClientSecurity");
2875 hr
= IClientSecurity_QueryBlanket(pCliSec
, (IUnknown
*)pProxy
, NULL
, NULL
, NULL
, NULL
, NULL
, NULL
, NULL
);
2876 todo_wine
ok_ole_success(hr
, "IClientSecurity_QueryBlanket (all NULLs)");
2878 hr
= IClientSecurity_QueryBlanket(pCliSec
, (IUnknown
*)pMarshal
, NULL
, NULL
, NULL
, NULL
, NULL
, NULL
, NULL
);
2879 todo_wine
ok(hr
== E_NOINTERFACE
, "IClientSecurity_QueryBlanket with local interface should have returned E_NOINTERFACE instead of 0x%08x\n", hr
);
2881 hr
= IClientSecurity_QueryBlanket(pCliSec
, (IUnknown
*)pProxy
, &dwAuthnSvc
, &dwAuthzSvc
, &pServerPrincName
, &dwAuthnLevel
, &dwImpLevel
, &pAuthInfo
, &dwCapabilities
);
2882 todo_wine
ok_ole_success(hr
, "IClientSecurity_QueryBlanket");
2884 hr
= IClientSecurity_SetBlanket(pCliSec
, (IUnknown
*)pProxy
, dwAuthnSvc
, dwAuthzSvc
, pServerPrincName
, dwAuthnLevel
, RPC_C_IMP_LEVEL_IMPERSONATE
, pAuthInfo
, dwCapabilities
);
2885 todo_wine
ok_ole_success(hr
, "IClientSecurity_SetBlanket");
2887 hr
= IClassFactory_CreateInstance(pProxy
, NULL
, &IID_IWineTest
, &pv
);
2888 ok(hr
== E_NOINTERFACE
, "COM call should have succeeded instead of returning 0x%08x\n", hr
);
2890 hr
= IClientSecurity_SetBlanket(pCliSec
, (IUnknown
*)pMarshal
, dwAuthnSvc
, dwAuthzSvc
, pServerPrincName
, dwAuthnLevel
, dwImpLevel
, pAuthInfo
, dwCapabilities
);
2891 todo_wine
ok(hr
== E_NOINTERFACE
, "IClientSecurity_SetBlanket with local interface should have returned E_NOINTERFACE instead of 0x%08x\n", hr
);
2893 hr
= IClientSecurity_SetBlanket(pCliSec
, (IUnknown
*)pProxy
, 0xdeadbeef, dwAuthzSvc
, pServerPrincName
, dwAuthnLevel
, dwImpLevel
, pAuthInfo
, dwCapabilities
);
2894 todo_wine
ok(hr
== E_INVALIDARG
, "IClientSecurity_SetBlanke with invalid dwAuthnSvc should have returned E_INVALIDARG instead of 0x%08x\n", hr
);
2896 CoTaskMemFree(pServerPrincName
);
2898 hr
= IClientSecurity_QueryBlanket(pCliSec
, pUnknown1
, &dwAuthnSvc
, &dwAuthzSvc
, &pServerPrincName
, &dwAuthnLevel
, &dwImpLevel
, &pAuthInfo
, &dwCapabilities
);
2899 todo_wine
ok_ole_success(hr
, "IClientSecurity_QueryBlanket(IUnknown)");
2901 CoTaskMemFree(pServerPrincName
);
2903 IClassFactory_Release(pProxy
);
2904 IUnknown_Release(pProxy2
);
2905 IUnknown_Release(pUnknown1
);
2906 IUnknown_Release(pUnknown2
);
2907 IMarshal_Release(pMarshal
);
2908 IClientSecurity_Release(pCliSec
);
2910 end_host_object(tid
, thread
);
2913 static HANDLE heventShutdown
;
2915 static void LockModuleOOP(void)
2917 InterlockedIncrement(&cLocks
); /* for test purposes only */
2918 CoAddRefServerProcess();
2921 static void UnlockModuleOOP(void)
2923 InterlockedDecrement(&cLocks
); /* for test purposes only */
2924 if (!CoReleaseServerProcess())
2925 SetEvent(heventShutdown
);
2928 static HWND hwnd_app
;
2932 IPersist IPersist_iface
; /* a nice short interface */
2935 static HRESULT WINAPI
local_server_QueryInterface(IPersist
*iface
, REFIID iid
, void **obj
)
2939 if (IsEqualGUID(iid
, &IID_IUnknown
) ||
2940 IsEqualGUID(iid
, &IID_IPersist
))
2945 IPersist_AddRef(iface
);
2948 return E_NOINTERFACE
;
2951 static ULONG WINAPI
local_server_AddRef(IPersist
*iface
)
2956 static ULONG WINAPI
local_server_Release(IPersist
*iface
)
2961 static HRESULT WINAPI
local_server_GetClassID(IPersist
*iface
, CLSID
*clsid
)
2965 *clsid
= IID_IUnknown
;
2967 /* Test calling CoDisconnectObject within a COM call */
2968 hr
= CoDisconnectObject((IUnknown
*)iface
, 0);
2969 ok(hr
== S_OK
, "got %08x\n", hr
);
2971 /* Initialize and uninitialize the apartment to show that we
2972 * remain in the autojoined mta */
2973 hr
= pCoInitializeEx( NULL
, COINIT_MULTITHREADED
);
2974 ok( hr
== S_FALSE
, "got %08x\n", hr
);
2980 static const IPersistVtbl local_server_persist_vtbl
=
2982 local_server_QueryInterface
,
2983 local_server_AddRef
,
2984 local_server_Release
,
2985 local_server_GetClassID
2988 struct local_server local_server_class
=
2990 {&local_server_persist_vtbl
}
2993 static HRESULT WINAPI
TestOOP_IClassFactory_QueryInterface(
2994 LPCLASSFACTORY iface
,
2998 if (ppvObj
== NULL
) return E_POINTER
;
3000 if (IsEqualGUID(riid
, &IID_IUnknown
) ||
3001 IsEqualGUID(riid
, &IID_IClassFactory
))
3004 IClassFactory_AddRef(iface
);
3008 return E_NOINTERFACE
;
3011 static ULONG WINAPI
TestOOP_IClassFactory_AddRef(LPCLASSFACTORY iface
)
3013 return 2; /* non-heap-based object */
3016 static ULONG WINAPI
TestOOP_IClassFactory_Release(LPCLASSFACTORY iface
)
3018 return 1; /* non-heap-based object */
3021 static HRESULT WINAPI
TestOOP_IClassFactory_CreateInstance(
3022 LPCLASSFACTORY iface
,
3023 LPUNKNOWN pUnkOuter
,
3027 IPersist
*persist
= &local_server_class
.IPersist_iface
;
3029 IPersist_AddRef( persist
);
3030 hr
= IPersist_QueryInterface( persist
, riid
, ppvObj
);
3031 IPersist_Release( persist
);
3035 static HRESULT WINAPI
TestOOP_IClassFactory_LockServer(
3036 LPCLASSFACTORY iface
,
3046 static const IClassFactoryVtbl TestClassFactoryOOP_Vtbl
=
3048 TestOOP_IClassFactory_QueryInterface
,
3049 TestOOP_IClassFactory_AddRef
,
3050 TestOOP_IClassFactory_Release
,
3051 TestOOP_IClassFactory_CreateInstance
,
3052 TestOOP_IClassFactory_LockServer
3055 static IClassFactory TestOOP_ClassFactory
= { &TestClassFactoryOOP_Vtbl
};
3057 static void test_register_local_server(void)
3065 heventShutdown
= CreateEventA(NULL
, TRUE
, FALSE
, NULL
);
3066 ready_event
= CreateEventA(NULL
, FALSE
, FALSE
, "Wine COM Test Ready Event");
3067 handles
[0] = CreateEventA(NULL
, FALSE
, FALSE
, "Wine COM Test Quit Event");
3068 handles
[1] = CreateEventA(NULL
, FALSE
, FALSE
, "Wine COM Test Repeat Event");
3071 hr
= CoRegisterClassObject(&CLSID_WineOOPTest
, (IUnknown
*)&TestOOP_ClassFactory
,
3072 CLSCTX_LOCAL_SERVER
, REGCLS_SINGLEUSE
, &cookie
);
3073 ok_ole_success(hr
, CoRegisterClassObject
);
3075 SetEvent(ready_event
);
3079 wait
= MsgWaitForMultipleObjects(2, handles
, FALSE
, 30000, QS_ALLINPUT
);
3080 if (wait
== WAIT_OBJECT_0
+2)
3084 if (PeekMessageA(&msg
, NULL
, 0, 0, PM_REMOVE
))
3086 trace("Message 0x%x\n", msg
.message
);
3087 TranslateMessage(&msg
);
3088 DispatchMessageA(&msg
);
3091 else if (wait
== WAIT_OBJECT_0
+1)
3093 hr
= CoRevokeClassObject(cookie
);
3094 ok_ole_success(hr
, CoRevokeClassObject
);
3098 while (wait
== WAIT_OBJECT_0
+2);
3100 ok( wait
== WAIT_OBJECT_0
, "quit event wait timed out\n" );
3101 hr
= CoRevokeClassObject(cookie
);
3102 ok_ole_success(hr
, CoRevokeClassObject
);
3103 CloseHandle(handles
[0]);
3104 CloseHandle(handles
[1]);
3107 static HANDLE
create_target_process(const char *arg
)
3110 char cmdline
[MAX_PATH
];
3112 PROCESS_INFORMATION pi
;
3113 STARTUPINFOA si
= { 0 };
3118 winetest_get_mainargs( &argv
);
3119 sprintf(cmdline
, "\"%s\" %s %s", argv
[0], argv
[1], arg
);
3120 ret
= CreateProcessA(argv
[0], cmdline
, NULL
, NULL
, FALSE
, 0, NULL
, NULL
, &si
, &pi
);
3121 ok(ret
, "CreateProcess failed with error: %u\n", GetLastError());
3122 if (pi
.hThread
) CloseHandle(pi
.hThread
);
3126 /* tests functions commonly used by out of process COM servers */
3127 static void test_local_server(void)
3137 HANDLE repeat_event
;
3140 heventShutdown
= CreateEventA(NULL
, TRUE
, FALSE
, NULL
);
3144 /* Start the object suspended */
3145 hr
= CoRegisterClassObject(&CLSID_WineOOPTest
, (IUnknown
*)&TestOOP_ClassFactory
,
3146 CLSCTX_LOCAL_SERVER
, REGCLS_MULTIPLEUSE
| REGCLS_SUSPENDED
, &cookie
);
3147 ok_ole_success(hr
, CoRegisterClassObject
);
3149 /* ... and CoGetClassObject does not find it and fails when it looks for the
3150 * class in the registry */
3151 hr
= CoGetClassObject(&CLSID_WineOOPTest
, CLSCTX_INPROC_SERVER
,
3152 NULL
, &IID_IClassFactory
, (LPVOID
*)&cf
);
3153 ok(hr
== REGDB_E_CLASSNOTREG
|| /* NT */
3154 hr
== S_OK
/* Win9x */,
3155 "CoGetClassObject should have returned REGDB_E_CLASSNOTREG instead of 0x%08x\n", hr
);
3157 /* Resume the object suspended above ... */
3158 hr
= CoResumeClassObjects();
3159 ok_ole_success(hr
, CoResumeClassObjects
);
3161 /* ... and now it should succeed */
3162 hr
= CoGetClassObject(&CLSID_WineOOPTest
, CLSCTX_INPROC_SERVER
,
3163 NULL
, &IID_IClassFactory
, (LPVOID
*)&cf
);
3164 ok_ole_success(hr
, CoGetClassObject
);
3166 /* Now check the locking is working */
3167 /* NOTE: we are accessing the class directly, not through a proxy */
3171 hr
= IClassFactory_LockServer(cf
, TRUE
);
3172 ok_ole_success(hr
, IClassFactory_LockServer
);
3174 ok_more_than_one_lock();
3176 IClassFactory_LockServer(cf
, FALSE
);
3177 ok_ole_success(hr
, IClassFactory_LockServer
);
3181 IClassFactory_Release(cf
);
3183 /* wait for shutdown signal */
3184 ret
= WaitForSingleObject(heventShutdown
, 0);
3185 ok(ret
!= WAIT_TIMEOUT
, "Server didn't shut down\n");
3187 /* try to connect again after SCM has suspended registered class objects */
3188 hr
= CoGetClassObject(&CLSID_WineOOPTest
, CLSCTX_INPROC_SERVER
| CLSCTX_LOCAL_SERVER
, NULL
,
3189 &IID_IClassFactory
, (LPVOID
*)&cf
);
3190 ok(hr
== CO_E_SERVER_STOPPING
|| /* NT */
3191 hr
== REGDB_E_CLASSNOTREG
|| /* win2k */
3192 hr
== S_OK
/* Win9x */,
3193 "CoGetClassObject should have returned CO_E_SERVER_STOPPING or REGDB_E_CLASSNOTREG instead of 0x%08x\n", hr
);
3195 hr
= CoRevokeClassObject(cookie
);
3196 ok_ole_success(hr
, CoRevokeClassObject
);
3198 CloseHandle(heventShutdown
);
3200 process
= create_target_process("-Embedding");
3201 ok(process
!= NULL
, "couldn't start local server process, error was %d\n", GetLastError());
3203 ready_event
= CreateEventA(NULL
, FALSE
, FALSE
, "Wine COM Test Ready Event");
3204 ok( !WaitForSingleObject(ready_event
, 10000), "wait timed out\n" );
3206 hr
= CoCreateInstance(&CLSID_WineOOPTest
, NULL
, CLSCTX_LOCAL_SERVER
, &IID_IPersist
, (void **)&persist
);
3207 ok_ole_success(hr
, CoCreateInstance
);
3209 IPersist_Release(persist
);
3211 hr
= CoCreateInstance(&CLSID_WineOOPTest
, NULL
, CLSCTX_LOCAL_SERVER
, &IID_IPersist
, (void **)&persist
);
3212 ok(hr
== REGDB_E_CLASSNOTREG
, "Second CoCreateInstance on REGCLS_SINGLEUSE object should have failed\n");
3214 /* Re-register the class and try calling CoDisconnectObject from within a call to that object */
3215 repeat_event
= CreateEventA(NULL
, FALSE
, FALSE
, "Wine COM Test Repeat Event");
3216 SetEvent(repeat_event
);
3217 CloseHandle(repeat_event
);
3219 ok( !WaitForSingleObject(ready_event
, 10000), "wait timed out\n" );
3220 CloseHandle(ready_event
);
3222 hr
= CoCreateInstance(&CLSID_WineOOPTest
, NULL
, CLSCTX_LOCAL_SERVER
, &IID_IPersist
, (void **)&persist
);
3223 ok_ole_success(hr
, CoCreateInstance
);
3225 /* GetClassID will call CoDisconnectObject */
3226 IPersist_GetClassID(persist
, &clsid
);
3227 IPersist_Release(persist
);
3229 quit_event
= CreateEventA(NULL
, FALSE
, FALSE
, "Wine COM Test Quit Event");
3230 SetEvent(quit_event
);
3232 winetest_wait_child_process( process
);
3233 CloseHandle(quit_event
);
3234 CloseHandle(process
);
3240 IGlobalInterfaceTable
*git
;
3243 static DWORD CALLBACK
get_global_interface_proc(LPVOID pv
)
3246 struct git_params
*params
= pv
;
3249 hr
= IGlobalInterfaceTable_GetInterfaceFromGlobal(params
->git
, params
->cookie
, &IID_IClassFactory
, (void **)&cf
);
3250 ok(hr
== CO_E_NOTINITIALIZED
||
3251 broken(hr
== E_UNEXPECTED
) /* win2k */ ||
3252 broken(hr
== S_OK
) /* NT 4 */,
3253 "IGlobalInterfaceTable_GetInterfaceFromGlobal should have failed with error CO_E_NOTINITIALIZED or E_UNEXPECTED instead of 0x%08x\n",
3256 IClassFactory_Release(cf
);
3260 hr
= IGlobalInterfaceTable_GetInterfaceFromGlobal(params
->git
, params
->cookie
, &IID_IClassFactory
, (void **)&cf
);
3261 ok_ole_success(hr
, IGlobalInterfaceTable_GetInterfaceFromGlobal
);
3263 IClassFactory_Release(cf
);
3270 static void test_globalinterfacetable(void)
3273 IGlobalInterfaceTable
*git
;
3277 struct git_params params
;
3283 trace("test_globalinterfacetable\n");
3286 hr
= pDllGetClassObject(&CLSID_StdGlobalInterfaceTable
, &IID_IClassFactory
, (void**)&cf
);
3287 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3289 hr
= IClassFactory_QueryInterface(cf
, &IID_IGlobalInterfaceTable
, (void**)&object
);
3290 ok(hr
== E_NOINTERFACE
, "got 0x%08x\n", hr
);
3292 IClassFactory_Release(cf
);
3294 hr
= CoCreateInstance(&CLSID_StdGlobalInterfaceTable
, NULL
, CLSCTX_INPROC_SERVER
, &IID_IGlobalInterfaceTable
, (void **)&git
);
3295 ok_ole_success(hr
, CoCreateInstance
);
3297 ref
= IGlobalInterfaceTable_AddRef(git
);
3298 ok(ref
== 1, "ref=%d\n", ref
);
3299 ref
= IGlobalInterfaceTable_AddRef(git
);
3300 ok(ref
== 1, "ref=%d\n", ref
);
3302 ref
= IGlobalInterfaceTable_Release(git
);
3303 ok(ref
== 1, "ref=%d\n", ref
);
3304 ref
= IGlobalInterfaceTable_Release(git
);
3305 ok(ref
== 1, "ref=%d\n", ref
);
3307 hr
= IGlobalInterfaceTable_RegisterInterfaceInGlobal(git
, (IUnknown
*)&Test_ClassFactory
, &IID_IClassFactory
, &cookie
);
3308 ok_ole_success(hr
, IGlobalInterfaceTable_RegisterInterfaceInGlobal
);
3310 ok_more_than_one_lock();
3312 params
.cookie
= cookie
;
3314 /* note: params is on stack so we MUST wait for get_global_interface_proc
3315 * to exit before we can return */
3316 thread
= CreateThread(NULL
, 0, get_global_interface_proc
, ¶ms
, 0, &tid
);
3318 ret
= MsgWaitForMultipleObjects(1, &thread
, FALSE
, 10000, QS_ALLINPUT
);
3319 while (ret
== WAIT_OBJECT_0
+ 1)
3322 while (PeekMessageA(&msg
, NULL
, 0, 0, PM_REMOVE
))
3323 DispatchMessageA(&msg
);
3324 ret
= MsgWaitForMultipleObjects(1, &thread
, FALSE
, 10000, QS_ALLINPUT
);
3327 CloseHandle(thread
);
3329 /* test getting interface from global with different iid */
3330 hr
= IGlobalInterfaceTable_GetInterfaceFromGlobal(git
, cookie
, &IID_IUnknown
, (void **)&object
);
3331 ok_ole_success(hr
, IGlobalInterfaceTable_GetInterfaceFromGlobal
);
3332 IUnknown_Release(object
);
3334 /* test getting interface from global with same iid */
3335 hr
= IGlobalInterfaceTable_GetInterfaceFromGlobal(git
, cookie
, &IID_IClassFactory
, (void **)&object
);
3336 ok_ole_success(hr
, IGlobalInterfaceTable_GetInterfaceFromGlobal
);
3337 IUnknown_Release(object
);
3339 hr
= IGlobalInterfaceTable_RevokeInterfaceFromGlobal(git
, cookie
);
3340 ok_ole_success(hr
, IGlobalInterfaceTable_RevokeInterfaceFromGlobal
);
3344 IGlobalInterfaceTable_Release(git
);
3347 static void test_manualresetevent(void)
3349 ISynchronizeHandle
*sync_handle
;
3350 ISynchronize
*psync1
, *psync2
;
3356 hr
= CoCreateInstance(&CLSID_ManualResetEvent
, NULL
, CLSCTX_INPROC_SERVER
, &IID_IUnknown
, (void**)&punk
);
3357 ok(hr
== S_OK
, "Got 0x%08x\n", hr
);
3358 ok(!!punk
, "Got NULL.\n");
3359 IUnknown_Release(punk
);
3361 hr
= CoCreateInstance(&CLSID_ManualResetEvent
, NULL
, CLSCTX_INPROC_SERVER
, &IID_ISynchronize
, (void**)&psync1
);
3362 ok(hr
== S_OK
, "Got 0x%08x\n", hr
);
3363 ok(!!psync1
, "Got NULL.\n");
3365 hr
= ISynchronize_Wait(psync1
, 0, 5);
3366 ok(hr
== RPC_S_CALLPENDING
, "Got 0x%08x\n", hr
);
3368 hr
= ISynchronize_Reset(psync1
);
3369 ok(hr
== S_OK
, "Got 0x%08x\n", hr
);
3370 hr
= ISynchronize_Signal(psync1
);
3371 ok(hr
== S_OK
, "Got 0x%08x\n", hr
);
3372 hr
= ISynchronize_Wait(psync1
, 0, 5);
3373 ok(hr
== S_OK
, "Got 0x%08x\n", hr
);
3374 hr
= ISynchronize_Wait(psync1
, 0, 5);
3375 ok(hr
== S_OK
, "Got 0x%08x\n", hr
);
3376 hr
= ISynchronize_Reset(psync1
);
3377 ok(hr
== S_OK
, "Got 0x%08x\n", hr
);
3378 hr
= ISynchronize_Wait(psync1
, 0, 5);
3379 ok(hr
== RPC_S_CALLPENDING
, "Got 0x%08x\n", hr
);
3381 hr
= CoCreateInstance(&CLSID_ManualResetEvent
, NULL
, CLSCTX_INPROC_SERVER
, &IID_ISynchronize
, (void**)&psync2
);
3382 ok(hr
== S_OK
, "Got 0x%08x\n", hr
);
3383 ok(!!psync2
, "Got NULL.\n");
3384 ok(psync1
!= psync2
, "psync1 == psync2.\n");
3386 hr
= ISynchronize_QueryInterface(psync2
, &IID_ISynchronizeHandle
, (void**)&sync_handle
);
3387 ok(hr
== S_OK
, "QueryInterface(IID_ISynchronizeHandle) failed: %08x\n", hr
);
3390 hr
= ISynchronizeHandle_GetHandle(sync_handle
, &handle
);
3391 ok(hr
== S_OK
, "GetHandle failed: %08x\n", hr
);
3392 ok(handle
!= NULL
&& handle
!= INVALID_HANDLE_VALUE
, "handle = %p\n", handle
);
3394 ISynchronizeHandle_Release(sync_handle
);
3396 hr
= ISynchronize_Wait(psync2
, 0, 5);
3397 ok(hr
== RPC_S_CALLPENDING
, "Got 0x%08x\n", hr
);
3399 hr
= ISynchronize_Reset(psync1
);
3400 ok(hr
== S_OK
, "Got 0x%08x\n", hr
);
3401 hr
= ISynchronize_Reset(psync2
);
3402 ok(hr
== S_OK
, "Got 0x%08x\n", hr
);
3403 hr
= ISynchronize_Signal(psync1
);
3404 ok(hr
== S_OK
, "Got 0x%08x\n", hr
);
3405 hr
= ISynchronize_Wait(psync2
, 0, 5);
3406 ok(hr
== RPC_S_CALLPENDING
, "Got 0x%08x\n", hr
);
3408 ref
= ISynchronize_AddRef(psync1
);
3409 ok(ref
== 2, "Got ref: %d\n", ref
);
3410 ref
= ISynchronize_AddRef(psync1
);
3411 ok(ref
== 3, "Got ref: %d\n", ref
);
3412 ref
= ISynchronize_Release(psync1
);
3413 ok(ref
== 2, "Got nonzero ref: %d\n", ref
);
3414 ref
= ISynchronize_Release(psync2
);
3415 ok(!ref
, "Got nonzero ref: %d\n", ref
);
3416 ref
= ISynchronize_Release(psync1
);
3417 ok(ref
== 1, "Got nonzero ref: %d\n", ref
);
3418 ref
= ISynchronize_Release(psync1
);
3419 ok(!ref
, "Got nonzero ref: %d\n", ref
);
3422 static DWORD CALLBACK
implicit_mta_unmarshal_proc(void *param
)
3424 IStream
*stream
= param
;
3429 IStream_Seek(stream
, ullZero
, STREAM_SEEK_SET
, NULL
);
3430 hr
= CoUnmarshalInterface(stream
, &IID_IClassFactory
, (void **)&cf
);
3431 ok_ole_success(hr
, CoUnmarshalInterface
);
3433 hr
= IClassFactory_CreateInstance(cf
, NULL
, &IID_IUnknown
, (void **)&proxy
);
3434 ok_ole_success(hr
, IClassFactory_CreateInstance
);
3436 IUnknown_Release(proxy
);
3438 /* But if we initialize an STA in this apartment, it becomes the wrong one. */
3439 CoInitializeEx(NULL
, COINIT_APARTMENTTHREADED
);
3441 hr
= IClassFactory_CreateInstance(cf
, NULL
, &IID_IUnknown
, (void **)&proxy
);
3442 ok(hr
== RPC_E_WRONG_THREAD
, "got %#x\n", hr
);
3446 ok_more_than_one_lock();
3447 ok_non_zero_external_conn();
3449 IClassFactory_Release(cf
);
3452 ok_zero_external_conn();
3453 ok_last_release_closes(TRUE
);
3457 static DWORD CALLBACK
implicit_mta_use_proc(void *param
)
3459 IClassFactory
*cf
= param
;
3463 hr
= IClassFactory_CreateInstance(cf
, NULL
, &IID_IUnknown
, (void **)&proxy
);
3464 ok_ole_success(hr
, IClassFactory_CreateInstance
);
3466 IUnknown_Release(proxy
);
3468 /* But if we initialize an STA in this apartment, it becomes the wrong one. */
3469 CoInitializeEx(NULL
, COINIT_APARTMENTTHREADED
);
3471 hr
= IClassFactory_CreateInstance(cf
, NULL
, &IID_IUnknown
, (void **)&proxy
);
3472 ok(hr
== RPC_E_WRONG_THREAD
, "got %#x\n", hr
);
3478 static void test_implicit_mta(void)
3480 HANDLE host_thread
, thread
;
3487 external_connections
= 0;
3489 CoInitializeEx(NULL
, COINIT_MULTITHREADED
);
3491 /* Firstly: we can unmarshal and use an object while in the implicit MTA. */
3492 hr
= CreateStreamOnHGlobal(NULL
, TRUE
, &stream
);
3493 ok_ole_success(hr
, CreateStreamOnHGlobal
);
3494 tid
= start_host_object(stream
, &IID_IClassFactory
, (IUnknown
*)&Test_ClassFactory
, MSHLFLAGS_NORMAL
, &host_thread
);
3496 ok_more_than_one_lock();
3497 ok_non_zero_external_conn();
3499 thread
= CreateThread(NULL
, 0, implicit_mta_unmarshal_proc
, stream
, 0, NULL
);
3500 ok(!WaitForSingleObject(thread
, 1000), "wait failed\n");
3501 CloseHandle(thread
);
3503 IStream_Release(stream
);
3504 end_host_object(tid
, host_thread
);
3506 /* Secondly: we can unmarshal an object into the real MTA and then use it
3507 * from the implicit MTA. */
3508 hr
= CreateStreamOnHGlobal(NULL
, TRUE
, &stream
);
3509 ok_ole_success(hr
, CreateStreamOnHGlobal
);
3510 tid
= start_host_object(stream
, &IID_IClassFactory
, (IUnknown
*)&Test_ClassFactory
, MSHLFLAGS_NORMAL
, &host_thread
);
3512 ok_more_than_one_lock();
3513 ok_non_zero_external_conn();
3515 IStream_Seek(stream
, ullZero
, STREAM_SEEK_SET
, NULL
);
3516 hr
= CoUnmarshalInterface(stream
, &IID_IClassFactory
, (void **)&cf
);
3517 ok_ole_success(hr
, CoUnmarshalInterface
);
3519 thread
= CreateThread(NULL
, 0, implicit_mta_use_proc
, cf
, 0, NULL
);
3520 ok(!WaitForSingleObject(thread
, 1000), "wait failed\n");
3521 CloseHandle(thread
);
3523 IClassFactory_Release(cf
);
3524 IStream_Release(stream
);
3527 ok_non_zero_external_conn();
3528 ok_last_release_closes(TRUE
);
3530 end_host_object(tid
, host_thread
);
3535 static const char *debugstr_iid(REFIID riid
)
3537 static char name
[256];
3541 LONG name_size
= sizeof(name
);
3542 StringFromGUID2(riid
, bufferW
, sizeof(bufferW
)/sizeof(bufferW
[0]));
3543 WideCharToMultiByte(CP_ACP
, 0, bufferW
, sizeof(bufferW
)/sizeof(bufferW
[0]), buffer
, sizeof(buffer
), NULL
, NULL
);
3544 if (RegOpenKeyExA(HKEY_CLASSES_ROOT
, "Interface", 0, KEY_QUERY_VALUE
, &hkeyInterface
) != ERROR_SUCCESS
)
3546 memcpy(name
, buffer
, sizeof(buffer
));
3549 if (RegQueryValueA(hkeyInterface
, buffer
, name
, &name_size
) != ERROR_SUCCESS
)
3551 memcpy(name
, buffer
, sizeof(buffer
));
3554 RegCloseKey(hkeyInterface
);
3559 static HRESULT WINAPI
TestChannelHook_QueryInterface(IChannelHook
*iface
, REFIID riid
, void **ppv
)
3561 if (IsEqualIID(riid
, &IID_IUnknown
) || IsEqualIID(riid
, &IID_IChannelHook
))
3564 IChannelHook_AddRef(iface
);
3569 return E_NOINTERFACE
;
3572 static ULONG WINAPI
TestChannelHook_AddRef(IChannelHook
*iface
)
3577 static ULONG WINAPI
TestChannelHook_Release(IChannelHook
*iface
)
3582 static BOOL new_hook_struct
;
3583 static int method
, server_tid
;
3584 static GUID causality
;
3586 struct new_hook_info
3595 static void WINAPI
TestChannelHook_ClientGetSize(
3596 IChannelHook
*iface
,
3601 SChannelHookCallInfo
*info
= (SChannelHookCallInfo
*)riid
;
3602 trace("TestChannelHook_ClientGetSize\n");
3603 trace("\t%s\n", debugstr_iid(riid
));
3604 if (info
->cbSize
!= sizeof(*info
))
3605 new_hook_struct
= TRUE
;
3607 if (!new_hook_struct
)
3609 ok(info
->cbSize
== sizeof(*info
), "cbSize was %d instead of %d\n", info
->cbSize
, (int)sizeof(*info
));
3610 ok(info
->dwServerPid
== GetCurrentProcessId(), "dwServerPid was 0x%x instead of 0x%x\n", info
->dwServerPid
, GetCurrentProcessId());
3611 ok(info
->iMethod
== method
, "iMethod was %d should be %d\n", info
->iMethod
, method
);
3612 ok(!info
->pObject
, "pObject should be NULL\n");
3614 causality
= info
->uCausality
;
3616 ok(IsEqualGUID(&info
->uCausality
, &causality
), "causality wasn't correct\n");
3620 struct new_hook_info
*new_info
= (struct new_hook_info
*)riid
;
3621 ok(new_info
->server_pid
== GetCurrentProcessId(), "server pid was 0x%x instead of 0x%x\n", new_info
->server_pid
,
3622 GetCurrentProcessId());
3623 ok(new_info
->server_tid
== server_tid
, "server tid was 0x%x instead of 0x%x\n", new_info
->server_tid
,
3625 ok(new_info
->method
== method
, "method was %d instead of %d\n", new_info
->method
, method
);
3627 causality
= new_info
->causality
;
3629 ok(IsEqualGUID(&new_info
->causality
, &causality
), "causality wasn't correct\n");
3632 ok(IsEqualGUID(uExtent
, &EXTENTID_WineTest
), "uExtent wasn't correct\n");
3637 static void WINAPI
TestChannelHook_ClientFillBuffer(
3638 IChannelHook
*iface
,
3644 SChannelHookCallInfo
*info
= (SChannelHookCallInfo
*)riid
;
3645 trace("TestChannelHook_ClientFillBuffer\n");
3647 if (!new_hook_struct
)
3649 ok(info
->cbSize
== sizeof(*info
), "cbSize was %d instead of %d\n", info
->cbSize
, (int)sizeof(*info
));
3650 ok(info
->dwServerPid
== GetCurrentProcessId(), "dwServerPid was 0x%x instead of 0x%x\n", info
->dwServerPid
, GetCurrentProcessId());
3651 ok(info
->iMethod
== method
, "iMethod was %d should be %d\n", info
->iMethod
, method
);
3652 ok(!info
->pObject
, "pObject should be NULL\n");
3653 ok(IsEqualGUID(&info
->uCausality
, &causality
), "causality wasn't correct\n");
3657 struct new_hook_info
*new_info
= (struct new_hook_info
*)riid
;
3658 ok(new_info
->server_pid
== GetCurrentProcessId(), "server pid was 0x%x instead of 0x%x\n", new_info
->server_pid
,
3659 GetCurrentProcessId());
3660 ok(new_info
->server_tid
== server_tid
, "server tid was 0x%x instead of 0x%x\n", new_info
->server_tid
,
3662 ok(new_info
->method
== method
, "method was %d instead of %d\n", new_info
->method
, method
);
3663 ok(IsEqualGUID(&new_info
->causality
, &causality
), "causality wasn't correct\n");
3666 ok(IsEqualGUID(uExtent
, &EXTENTID_WineTest
), "uExtent wasn't correct\n");
3668 *(unsigned char *)pDataBuffer
= 0xcc;
3672 static void WINAPI
TestChannelHook_ClientNotify(
3673 IChannelHook
*iface
,
3681 SChannelHookCallInfo
*info
= (SChannelHookCallInfo
*)riid
;
3682 trace("TestChannelHook_ClientNotify hrFault = 0x%08x\n", hrFault
);
3684 if (!new_hook_struct
)
3686 ok(info
->cbSize
== sizeof(*info
), "cbSize was %d instead of %d\n", info
->cbSize
, (int)sizeof(*info
));
3687 ok(info
->dwServerPid
== GetCurrentProcessId(), "dwServerPid was 0x%x instead of 0x%x\n", info
->dwServerPid
, GetCurrentProcessId());
3688 ok(info
->iMethod
== method
, "iMethod was %d should be %d\n", info
->iMethod
, method
);
3690 ok(info
->pObject
!= NULL
, "pObject shouldn't be NULL\n");
3692 ok(IsEqualGUID(&info
->uCausality
, &causality
), "causality wasn't correct\n");
3696 struct new_hook_info
*new_info
= (struct new_hook_info
*)riid
;
3697 ok(new_info
->server_pid
== GetCurrentProcessId(), "server pid was 0x%x instead of 0x%x\n", new_info
->server_pid
,
3698 GetCurrentProcessId());
3699 ok(new_info
->server_tid
== server_tid
, "server tid was 0x%x instead of 0x%x\n", new_info
->server_tid
,
3701 ok(new_info
->method
== method
, "method was %d instead of %d\n", new_info
->method
, method
);
3702 ok(IsEqualGUID(&new_info
->causality
, &causality
), "causality wasn't correct\n");
3705 ok(IsEqualGUID(uExtent
, &EXTENTID_WineTest
), "uExtent wasn't correct\n");
3708 static void WINAPI
TestChannelHook_ServerNotify(
3709 IChannelHook
*iface
,
3716 SChannelHookCallInfo
*info
= (SChannelHookCallInfo
*)riid
;
3717 trace("TestChannelHook_ServerNotify\n");
3719 if (!new_hook_struct
)
3721 ok(info
->cbSize
== sizeof(*info
), "cbSize was %d instead of %d\n", info
->cbSize
, (int)sizeof(*info
));
3722 ok(info
->dwServerPid
== GetCurrentProcessId(), "dwServerPid was 0x%x instead of 0x%x\n", info
->dwServerPid
, GetCurrentProcessId());
3723 ok(info
->iMethod
== method
, "iMethod was %d should be %d\n", info
->iMethod
, method
);
3724 ok(info
->pObject
!= NULL
, "pObject shouldn't be NULL\n");
3725 ok(IsEqualGUID(&info
->uCausality
, &causality
), "causality wasn't correct\n");
3729 struct new_hook_info
*new_info
= (struct new_hook_info
*)riid
;
3730 ok(new_info
->server_pid
== GetCurrentProcessId(), "server pid was 0x%x instead of 0x%x\n", new_info
->server_pid
,
3731 GetCurrentProcessId());
3732 ok(new_info
->server_tid
== server_tid
, "server tid was 0x%x instead of 0x%x\n", new_info
->server_tid
,
3734 ok(new_info
->method
== method
, "method was %d instead of %d\n", new_info
->method
, method
);
3735 ok(IsEqualGUID(&new_info
->causality
, &causality
), "causality wasn't correct\n");
3738 ok(cbDataSize
== 1, "cbDataSize should have been 1 instead of %d\n", cbDataSize
);
3739 ok(*(unsigned char *)pDataBuffer
== 0xcc, "pDataBuffer should have contained 0xcc instead of 0x%x\n", *(unsigned char *)pDataBuffer
);
3740 ok(IsEqualGUID(uExtent
, &EXTENTID_WineTest
), "uExtent wasn't correct\n");
3743 static void WINAPI
TestChannelHook_ServerGetSize(
3744 IChannelHook
*iface
,
3750 SChannelHookCallInfo
*info
= (SChannelHookCallInfo
*)riid
;
3751 trace("TestChannelHook_ServerGetSize\n");
3752 trace("\t%s\n", debugstr_iid(riid
));
3753 if (!new_hook_struct
)
3755 ok(info
->cbSize
== sizeof(*info
), "cbSize was %d instead of %d\n", info
->cbSize
, (int)sizeof(*info
));
3756 ok(info
->dwServerPid
== GetCurrentProcessId(), "dwServerPid was 0x%x instead of 0x%x\n", info
->dwServerPid
, GetCurrentProcessId());
3757 ok(info
->iMethod
== method
, "iMethod was %d should be %d\n", info
->iMethod
, method
);
3758 ok(info
->pObject
!= NULL
, "pObject shouldn't be NULL\n");
3759 ok(IsEqualGUID(&info
->uCausality
, &causality
), "causality wasn't correct\n");
3763 struct new_hook_info
*new_info
= (struct new_hook_info
*)riid
;
3764 ok(new_info
->server_pid
== GetCurrentProcessId(), "server pid was 0x%x instead of 0x%x\n", new_info
->server_pid
,
3765 GetCurrentProcessId());
3766 ok(new_info
->server_tid
== server_tid
, "server tid was 0x%x instead of 0x%x\n", new_info
->server_tid
,
3768 ok(new_info
->method
== method
, "method was %d instead of %d\n", new_info
->method
, method
);
3769 ok(IsEqualGUID(&new_info
->causality
, &causality
), "causality wasn't correct\n");
3772 ok(IsEqualGUID(uExtent
, &EXTENTID_WineTest
), "uExtent wasn't correct\n");
3773 if (hrFault
!= S_OK
)
3774 trace("\thrFault = 0x%08x\n", hrFault
);
3779 static void WINAPI
TestChannelHook_ServerFillBuffer(
3780 IChannelHook
*iface
,
3787 trace("TestChannelHook_ServerFillBuffer\n");
3788 ok(0, "TestChannelHook_ServerFillBuffer shouldn't be called\n");
3791 static const IChannelHookVtbl TestChannelHookVtbl
=
3793 TestChannelHook_QueryInterface
,
3794 TestChannelHook_AddRef
,
3795 TestChannelHook_Release
,
3796 TestChannelHook_ClientGetSize
,
3797 TestChannelHook_ClientFillBuffer
,
3798 TestChannelHook_ClientNotify
,
3799 TestChannelHook_ServerNotify
,
3800 TestChannelHook_ServerGetSize
,
3801 TestChannelHook_ServerFillBuffer
,
3804 static IChannelHook TestChannelHook
= { &TestChannelHookVtbl
};
3806 static void test_channel_hook(void)
3808 IStream
*pStream
= NULL
;
3809 IClassFactory
*cf
= NULL
;
3811 IUnknown
*proxy
= NULL
;
3815 hr
= CoRegisterChannelHook(&EXTENTID_WineTest
, &TestChannelHook
);
3816 ok_ole_success(hr
, CoRegisterChannelHook
);
3818 hr
= CoRegisterMessageFilter(&MessageFilter
, NULL
);
3819 ok_ole_success(hr
, CoRegisterMessageFilter
);
3823 hr
= CreateStreamOnHGlobal(NULL
, TRUE
, &pStream
);
3824 ok_ole_success(hr
, CreateStreamOnHGlobal
);
3825 tid
= start_host_object2(pStream
, &IID_IClassFactory
, (IUnknown
*)&Test_ClassFactory
, MSHLFLAGS_NORMAL
, &MessageFilter
, &thread
);
3828 ok_more_than_one_lock();
3830 IStream_Seek(pStream
, ullZero
, STREAM_SEEK_SET
, NULL
);
3831 hr
= CoUnmarshalInterface(pStream
, &IID_IClassFactory
, (void **)&cf
);
3832 ok_ole_success(hr
, CoUnmarshalInterface
);
3833 IStream_Release(pStream
);
3835 ok_more_than_one_lock();
3838 hr
= IClassFactory_CreateInstance(cf
, NULL
, &IID_IUnknown
, (LPVOID
*)&proxy
);
3839 ok_ole_success(hr
, IClassFactory_CreateInstance
);
3842 IUnknown_Release(proxy
);
3844 IClassFactory_Release(cf
);
3848 end_host_object(tid
, thread
);
3850 hr
= CoRegisterMessageFilter(NULL
, NULL
);
3851 ok_ole_success(hr
, CoRegisterMessageFilter
);
3856 HMODULE hOle32
= GetModuleHandleA("ole32");
3860 if (!GetProcAddress(hOle32
, "CoRegisterSurrogateEx")) {
3861 win_skip("skipping test on win9x\n");
3865 pCoInitializeEx
= (void*)GetProcAddress(hOle32
, "CoInitializeEx");
3866 pDllGetClassObject
= (void*)GetProcAddress(hOle32
, "DllGetClassObject");
3868 argc
= winetest_get_mainargs( &argv
);
3869 if (argc
> 2 && (!strcmp(argv
[2], "-Embedding")))
3871 pCoInitializeEx(NULL
, COINIT_MULTITHREADED
);
3872 test_register_local_server();
3878 register_test_window();
3880 test_cocreateinstance_proxy();
3881 test_implicit_mta();
3883 pCoInitializeEx(NULL
, COINIT_APARTMENTTHREADED
);
3885 /* FIXME: test CoCreateInstanceEx */
3887 /* lifecycle management and marshaling tests */
3890 test_no_marshaler();
3891 test_normal_marshal_and_release();
3892 test_normal_marshal_and_unmarshal();
3893 test_marshal_and_unmarshal_invalid();
3894 test_same_apartment_unmarshal_failure();
3895 test_interthread_marshal_and_unmarshal();
3896 test_proxy_marshal_and_unmarshal();
3897 test_proxy_marshal_and_unmarshal2();
3898 test_proxy_marshal_and_unmarshal_weak();
3899 test_proxy_marshal_and_unmarshal_strong();
3900 test_marshal_stub_apartment_shutdown();
3901 test_marshal_proxy_apartment_shutdown();
3902 test_marshal_proxy_mta_apartment_shutdown();
3903 test_no_couninitialize_server();
3904 test_no_couninitialize_client();
3905 test_tableweak_marshal_and_unmarshal_twice();
3906 test_tableweak_marshal_releasedata1();
3907 test_tableweak_marshal_releasedata2();
3908 test_tableweak_and_normal_marshal_and_unmarshal();
3909 test_tableweak_and_normal_marshal_and_releasedata();
3910 test_two_tableweak_marshal_and_releasedata();
3911 test_tablestrong_marshal_and_unmarshal_twice();
3912 test_lock_object_external();
3913 test_disconnect_stub();
3914 test_normal_marshal_and_unmarshal_twice();
3916 with_external_conn
= !with_external_conn
;
3917 } while (with_external_conn
);
3919 test_hresult_marshaling();
3920 test_proxy_used_in_wrong_thread();
3921 test_message_filter();
3922 test_bad_marshal_stream();
3923 test_proxy_interfaces();
3924 test_stubbuffer(&IID_IClassFactory
);
3925 test_proxybuffer(&IID_IClassFactory
);
3926 test_message_reentrancy();
3927 test_call_from_message();
3928 test_WM_QUIT_handling();
3929 test_freethreadedmarshaler();
3930 test_inproc_handler();
3931 test_handler_marshaling();
3932 test_client_security();
3934 test_local_server();
3936 test_globalinterfacetable();
3937 test_manualresetevent();
3938 test_crash_couninitialize();
3940 /* must be last test as channel hooks can't be unregistered */
3941 test_channel_hook();