4 * Copyright 2004 Robert Shearman
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
21 #define WIN32_NO_STATUS
23 #define COM_NO_WINDOWS_H
37 //#include "objbase.h"
40 //#include "shobjidl.h"
41 //#include "initguid.h"
43 #include <wine/test.h>
45 DEFINE_GUID(CLSID_StdGlobalInterfaceTable
,0x00000323,0x0000,0x0000,0xc0,0x00,0x00,0x00,0x00,0x00,0x00,0x46);
46 DEFINE_GUID(CLSID_ManualResetEvent
, 0x0000032c,0x0000,0x0000,0xc0,0x00,0x00,0x00,0x00,0x00,0x00,0x46);
48 /* functions that are not present on all versions of Windows */
49 static HRESULT (WINAPI
* pCoInitializeEx
)(LPVOID lpReserved
, DWORD dwCoInit
);
50 static HRESULT (WINAPI
*pDllGetClassObject
)(REFCLSID
,REFIID
,LPVOID
);
52 /* helper macros to make tests a bit leaner */
53 #define ok_more_than_one_lock() ok(cLocks > 0, "Number of locks should be > 0, but actually is %d\n", cLocks)
54 #define ok_no_locks() ok(cLocks == 0, "Number of locks should be 0, but actually is %d\n", cLocks)
55 #define ok_ole_success(hr, func) ok(hr == S_OK, #func " failed with error 0x%08x\n", hr)
56 #define ok_non_zero_external_conn() do {if (with_external_conn) ok(external_connections, "got no external connections\n");} while(0);
57 #define ok_zero_external_conn() do {if (with_external_conn) ok(!external_connections, "got %d external connections\n", external_connections);} while(0);
58 #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);
60 static const IID IID_IWineTest
=
65 {0xa1, 0xa2, 0x5d, 0x5a, 0x36, 0x54, 0xd3, 0xbd}
66 }; /* 5201163f-8164-4fd0-a1a2-5d5a3654d3bd */
68 static const IID IID_IRemUnknown
=
73 {0xc0,0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46}
76 #define EXTENTID_WineTest IID_IWineTest
77 #define CLSID_WineTest IID_IWineTest
79 static const CLSID CLSID_WineOOPTest
=
84 {0xa1, 0xa2, 0x5d, 0x5a, 0x36, 0x54, 0xd3, 0xbd}
85 }; /* 5201163f-8164-4fd0-a1a2-5d5a3654d3bd */
87 static void test_cocreateinstance_proxy(void)
93 pCoInitializeEx(NULL
, COINIT_MULTITHREADED
);
95 hr
= CoCreateInstance(&CLSID_ShellDesktop
, NULL
, CLSCTX_INPROC
, &IID_IUnknown
, (void **)&pProxy
);
96 ok_ole_success(hr
, CoCreateInstance
);
97 hr
= IUnknown_QueryInterface(pProxy
, &IID_IMultiQI
, (void **)&pMQI
);
98 ok(hr
== S_OK
, "created object is not a proxy, so was created in the wrong apartment\n");
100 IMultiQI_Release(pMQI
);
101 IUnknown_Release(pProxy
);
106 static const LARGE_INTEGER ullZero
;
109 static void LockModule(void)
111 InterlockedIncrement(&cLocks
);
114 static void UnlockModule(void)
116 InterlockedDecrement(&cLocks
);
119 static BOOL with_external_conn
;
120 static DWORD external_connections
;
121 static BOOL last_release_closes
;
123 static HRESULT WINAPI
ExternalConnection_QueryInterface(IExternalConnection
*iface
, REFIID riid
, void **ppv
)
125 ok(0, "unexpected call\n");
127 return E_NOINTERFACE
;
130 static ULONG WINAPI
ExternalConnection_AddRef(IExternalConnection
*iface
)
135 static ULONG WINAPI
ExternalConnection_Release(IExternalConnection
*iface
)
140 static DWORD WINAPI
ExternalConnection_AddConnection(IExternalConnection
*iface
, DWORD extconn
, DWORD reserved
)
142 trace("add connection\n");
143 return ++external_connections
;
147 static DWORD WINAPI
ExternalConnection_ReleaseConnection(IExternalConnection
*iface
, DWORD extconn
,
148 DWORD reserved
, BOOL fLastReleaseCloses
)
150 trace("release connection %d\n", fLastReleaseCloses
);
151 last_release_closes
= fLastReleaseCloses
;
152 return --external_connections
;
155 static const IExternalConnectionVtbl ExternalConnectionVtbl
= {
156 ExternalConnection_QueryInterface
,
157 ExternalConnection_AddRef
,
158 ExternalConnection_Release
,
159 ExternalConnection_AddConnection
,
160 ExternalConnection_ReleaseConnection
163 static IExternalConnection ExternalConnection
= { &ExternalConnectionVtbl
};
166 static HRESULT WINAPI
Test_IUnknown_QueryInterface(
171 if (ppvObj
== NULL
) return E_POINTER
;
173 if (IsEqualGUID(riid
, &IID_IUnknown
))
176 IUnknown_AddRef(iface
);
181 return E_NOINTERFACE
;
184 static ULONG WINAPI
Test_IUnknown_AddRef(LPUNKNOWN iface
)
187 return 2; /* non-heap-based object */
190 static ULONG WINAPI
Test_IUnknown_Release(LPUNKNOWN iface
)
193 return 1; /* non-heap-based object */
196 static const IUnknownVtbl TestUnknown_Vtbl
=
198 Test_IUnknown_QueryInterface
,
199 Test_IUnknown_AddRef
,
200 Test_IUnknown_Release
,
203 static IUnknown Test_Unknown
= { &TestUnknown_Vtbl
};
205 static ULONG WINAPI
TestCrash_IUnknown_Release(LPUNKNOWN iface
)
209 trace("crashing...\n");
212 return 1; /* non-heap-based object */
215 static const IUnknownVtbl TestCrashUnknown_Vtbl
=
217 Test_IUnknown_QueryInterface
,
218 Test_IUnknown_AddRef
,
219 TestCrash_IUnknown_Release
,
222 static IUnknown TestCrash_Unknown
= { &TestCrashUnknown_Vtbl
};
224 static HRESULT WINAPI
Test_IClassFactory_QueryInterface(
225 LPCLASSFACTORY iface
,
229 if (ppvObj
== NULL
) return E_POINTER
;
231 if (IsEqualGUID(riid
, &IID_IUnknown
) ||
232 IsEqualGUID(riid
, &IID_IClassFactory
) ||
233 /* the only other interface Wine is currently able to marshal (for testing two proxies) */
234 IsEqualGUID(riid
, &IID_IRemUnknown
))
237 IClassFactory_AddRef(iface
);
241 if (with_external_conn
&& IsEqualGUID(riid
, &IID_IExternalConnection
))
243 *ppvObj
= &ExternalConnection
;
248 return E_NOINTERFACE
;
251 static ULONG WINAPI
Test_IClassFactory_AddRef(LPCLASSFACTORY iface
)
254 return 2; /* non-heap-based object */
257 static ULONG WINAPI
Test_IClassFactory_Release(LPCLASSFACTORY iface
)
260 return 1; /* non-heap-based object */
263 static HRESULT WINAPI
Test_IClassFactory_CreateInstance(
264 LPCLASSFACTORY iface
,
269 if (pUnkOuter
) return CLASS_E_NOAGGREGATION
;
270 return IUnknown_QueryInterface((IUnknown
*)&Test_Unknown
, riid
, ppvObj
);
273 static HRESULT WINAPI
Test_IClassFactory_LockServer(
274 LPCLASSFACTORY iface
,
280 static const IClassFactoryVtbl TestClassFactory_Vtbl
=
282 Test_IClassFactory_QueryInterface
,
283 Test_IClassFactory_AddRef
,
284 Test_IClassFactory_Release
,
285 Test_IClassFactory_CreateInstance
,
286 Test_IClassFactory_LockServer
289 static IClassFactory Test_ClassFactory
= { &TestClassFactory_Vtbl
};
291 #define RELEASEMARSHALDATA WM_USER
293 struct host_object_data
298 MSHLFLAGS marshal_flags
;
299 HANDLE marshal_event
;
300 IMessageFilter
*filter
;
303 static DWORD CALLBACK
host_object_proc(LPVOID p
)
305 struct host_object_data
*data
= p
;
309 pCoInitializeEx(NULL
, COINIT_APARTMENTTHREADED
);
313 IMessageFilter
* prev_filter
= NULL
;
314 hr
= CoRegisterMessageFilter(data
->filter
, &prev_filter
);
315 if (prev_filter
) IMessageFilter_Release(prev_filter
);
316 ok_ole_success(hr
, CoRegisterMessageFilter
);
319 hr
= CoMarshalInterface(data
->stream
, &data
->iid
, data
->object
, MSHCTX_INPROC
, NULL
, data
->marshal_flags
);
320 ok_ole_success(hr
, CoMarshalInterface
);
322 /* force the message queue to be created before signaling parent thread */
323 PeekMessageA(&msg
, NULL
, WM_USER
, WM_USER
, PM_NOREMOVE
);
325 SetEvent(data
->marshal_event
);
327 while (GetMessageA(&msg
, NULL
, 0, 0))
329 if (msg
.hwnd
== NULL
&& msg
.message
== RELEASEMARSHALDATA
)
331 CoReleaseMarshalData(data
->stream
);
332 SetEvent((HANDLE
)msg
.lParam
);
335 DispatchMessageA(&msg
);
338 HeapFree(GetProcessHeap(), 0, data
);
345 static DWORD
start_host_object2(IStream
*stream
, REFIID riid
, IUnknown
*object
, MSHLFLAGS marshal_flags
, IMessageFilter
*filter
, HANDLE
*thread
)
348 HANDLE marshal_event
= CreateEventA(NULL
, FALSE
, FALSE
, NULL
);
349 struct host_object_data
*data
= HeapAlloc(GetProcessHeap(), 0, sizeof(*data
));
351 data
->stream
= stream
;
353 data
->object
= object
;
354 data
->marshal_flags
= marshal_flags
;
355 data
->marshal_event
= marshal_event
;
356 data
->filter
= filter
;
358 *thread
= CreateThread(NULL
, 0, host_object_proc
, data
, 0, &tid
);
360 /* wait for marshaling to complete before returning */
361 ok( !WaitForSingleObject(marshal_event
, 10000), "wait timed out\n" );
362 CloseHandle(marshal_event
);
367 static DWORD
start_host_object(IStream
*stream
, REFIID riid
, IUnknown
*object
, MSHLFLAGS marshal_flags
, HANDLE
*thread
)
369 return start_host_object2(stream
, riid
, object
, marshal_flags
, NULL
, thread
);
372 /* asks thread to release the marshal data because it has to be done by the
373 * same thread that marshaled the interface in the first place. */
374 static void release_host_object(DWORD tid
, WPARAM wp
)
376 HANDLE event
= CreateEventA(NULL
, FALSE
, FALSE
, NULL
);
377 PostThreadMessageA(tid
, RELEASEMARSHALDATA
, wp
, (LPARAM
)event
);
378 ok( !WaitForSingleObject(event
, 10000), "wait timed out\n" );
382 static void end_host_object(DWORD tid
, HANDLE thread
)
384 BOOL ret
= PostThreadMessageA(tid
, WM_QUIT
, 0, 0);
385 ok(ret
, "PostThreadMessage failed with error %d\n", GetLastError());
386 /* be careful of races - don't return until hosting thread has terminated */
387 ok( !WaitForSingleObject(thread
, 10000), "wait timed out\n" );
391 /* tests failure case of interface not having a marshaler specified in the
393 static void test_no_marshaler(void)
398 hr
= CreateStreamOnHGlobal(NULL
, TRUE
, &pStream
);
399 ok_ole_success(hr
, CreateStreamOnHGlobal
);
400 hr
= CoMarshalInterface(pStream
, &IID_IWineTest
, (IUnknown
*)&Test_ClassFactory
, MSHCTX_INPROC
, NULL
, MSHLFLAGS_NORMAL
);
401 ok(hr
== E_NOINTERFACE
, "CoMarshalInterface should have returned E_NOINTERFACE instead of 0x%08x\n", hr
);
403 IStream_Release(pStream
);
406 /* tests normal marshal and then release without unmarshaling */
407 static void test_normal_marshal_and_release(void)
410 IStream
*pStream
= NULL
;
413 external_connections
= 0;
415 hr
= CreateStreamOnHGlobal(NULL
, TRUE
, &pStream
);
416 ok_ole_success(hr
, CreateStreamOnHGlobal
);
417 hr
= CoMarshalInterface(pStream
, &IID_IClassFactory
, (IUnknown
*)&Test_ClassFactory
, MSHCTX_INPROC
, NULL
, MSHLFLAGS_NORMAL
);
418 ok_ole_success(hr
, CoMarshalInterface
);
420 ok_more_than_one_lock();
421 ok_non_zero_external_conn();
423 IStream_Seek(pStream
, ullZero
, STREAM_SEEK_SET
, NULL
);
424 hr
= CoReleaseMarshalData(pStream
);
425 ok_ole_success(hr
, CoReleaseMarshalData
);
426 IStream_Release(pStream
);
429 ok_zero_external_conn();
430 ok_last_release_closes(TRUE
);
433 /* tests success case of a same-thread marshal and unmarshal */
434 static void test_normal_marshal_and_unmarshal(void)
437 IStream
*pStream
= NULL
;
438 IUnknown
*pProxy
= NULL
;
441 external_connections
= 0;
443 hr
= CreateStreamOnHGlobal(NULL
, TRUE
, &pStream
);
444 ok_ole_success(hr
, CreateStreamOnHGlobal
);
445 hr
= CoMarshalInterface(pStream
, &IID_IClassFactory
, (IUnknown
*)&Test_ClassFactory
, MSHCTX_INPROC
, NULL
, MSHLFLAGS_NORMAL
);
446 ok_ole_success(hr
, CoMarshalInterface
);
448 ok_more_than_one_lock();
449 ok_non_zero_external_conn();
451 IStream_Seek(pStream
, ullZero
, STREAM_SEEK_SET
, NULL
);
452 hr
= CoUnmarshalInterface(pStream
, &IID_IClassFactory
, (void **)&pProxy
);
453 ok_ole_success(hr
, CoUnmarshalInterface
);
454 IStream_Release(pStream
);
456 ok_more_than_one_lock();
457 ok_zero_external_conn();
458 ok_last_release_closes(FALSE
);
460 IUnknown_Release(pProxy
);
465 /* tests failure case of unmarshaling a freed object */
466 static void test_marshal_and_unmarshal_invalid(void)
469 IStream
*pStream
= NULL
;
470 IClassFactory
*pProxy
= NULL
;
476 external_connections
= 0;
478 hr
= CreateStreamOnHGlobal(NULL
, TRUE
, &pStream
);
479 ok_ole_success(hr
, CreateStreamOnHGlobal
);
480 tid
= start_host_object(pStream
, &IID_IClassFactory
, (IUnknown
*)&Test_ClassFactory
, MSHLFLAGS_NORMAL
, &thread
);
482 ok_more_than_one_lock();
483 ok_non_zero_external_conn();
485 IStream_Seek(pStream
, ullZero
, STREAM_SEEK_SET
, NULL
);
486 hr
= CoReleaseMarshalData(pStream
);
487 ok_ole_success(hr
, CoReleaseMarshalData
);
490 ok_zero_external_conn();
491 ok_last_release_closes(TRUE
);
493 IStream_Seek(pStream
, ullZero
, STREAM_SEEK_SET
, NULL
);
494 hr
= CoUnmarshalInterface(pStream
, &IID_IClassFactory
, (void **)&pProxy
);
495 todo_wine
{ ok_ole_success(hr
, CoUnmarshalInterface
); }
501 hr
= IClassFactory_CreateInstance(pProxy
, NULL
, &IID_IUnknown
, &dummy
);
502 ok(hr
== RPC_E_DISCONNECTED
, "Remote call should have returned RPC_E_DISCONNECTED, instead of 0x%08x\n", hr
);
504 IClassFactory_Release(pProxy
);
507 IStream_Release(pStream
);
509 end_host_object(tid
, thread
);
512 static void test_same_apartment_unmarshal_failure(void)
517 static const LARGE_INTEGER llZero
;
520 external_connections
= 0;
522 hr
= CreateStreamOnHGlobal(NULL
, TRUE
, &pStream
);
523 ok_ole_success(hr
, CreateStreamOnHGlobal
);
525 hr
= CoMarshalInterface(pStream
, &IID_IUnknown
, (IUnknown
*)&Test_ClassFactory
, MSHCTX_INPROC
, NULL
, MSHLFLAGS_NORMAL
);
526 ok_ole_success(hr
, CoMarshalInterface
);
528 ok_more_than_one_lock();
529 ok_non_zero_external_conn();
531 hr
= IStream_Seek(pStream
, llZero
, STREAM_SEEK_SET
, NULL
);
532 ok_ole_success(hr
, IStream_Seek
);
534 hr
= CoUnmarshalInterface(pStream
, &IID_IParseDisplayName
, (void **)&pProxy
);
535 ok(hr
== E_NOINTERFACE
, "CoUnmarshalInterface should have returned E_NOINTERFACE instead of 0x%08x\n", hr
);
538 ok_zero_external_conn();
539 ok_last_release_closes(FALSE
);
541 IStream_Release(pStream
);
544 /* tests success case of an interthread marshal */
545 static void test_interthread_marshal_and_unmarshal(void)
548 IStream
*pStream
= NULL
;
549 IUnknown
*pProxy
= NULL
;
554 external_connections
= 0;
556 hr
= CreateStreamOnHGlobal(NULL
, TRUE
, &pStream
);
557 ok_ole_success(hr
, CreateStreamOnHGlobal
);
558 tid
= start_host_object(pStream
, &IID_IClassFactory
, (IUnknown
*)&Test_ClassFactory
, MSHLFLAGS_NORMAL
, &thread
);
560 ok_more_than_one_lock();
561 ok_non_zero_external_conn();
563 IStream_Seek(pStream
, ullZero
, STREAM_SEEK_SET
, NULL
);
564 hr
= CoUnmarshalInterface(pStream
, &IID_IClassFactory
, (void **)&pProxy
);
565 ok_ole_success(hr
, CoUnmarshalInterface
);
566 IStream_Release(pStream
);
568 ok_more_than_one_lock();
569 ok_non_zero_external_conn();
571 IUnknown_Release(pProxy
);
574 ok_zero_external_conn();
575 ok_last_release_closes(TRUE
);
577 end_host_object(tid
, thread
);
580 /* the number of external references that Wine's proxy manager normally gives
581 * out, so we can test the border case of running out of references */
582 #define NORMALEXTREFS 5
584 /* tests success case of an interthread marshal and then marshaling the proxy */
585 static void test_proxy_marshal_and_unmarshal(void)
588 IStream
*pStream
= NULL
;
589 IUnknown
*pProxy
= NULL
;
590 IUnknown
*pProxy2
= NULL
;
596 external_connections
= 0;
598 hr
= CreateStreamOnHGlobal(NULL
, TRUE
, &pStream
);
599 ok_ole_success(hr
, CreateStreamOnHGlobal
);
600 tid
= start_host_object(pStream
, &IID_IClassFactory
, (IUnknown
*)&Test_ClassFactory
, MSHLFLAGS_NORMAL
, &thread
);
602 ok_more_than_one_lock();
603 ok_non_zero_external_conn();
605 IStream_Seek(pStream
, ullZero
, STREAM_SEEK_SET
, NULL
);
606 hr
= CoUnmarshalInterface(pStream
, &IID_IClassFactory
, (void **)&pProxy
);
607 ok_ole_success(hr
, CoUnmarshalInterface
);
609 ok_more_than_one_lock();
611 IStream_Seek(pStream
, ullZero
, STREAM_SEEK_SET
, NULL
);
612 /* marshal the proxy */
613 hr
= CoMarshalInterface(pStream
, &IID_IClassFactory
, pProxy
, MSHCTX_INPROC
, NULL
, MSHLFLAGS_NORMAL
);
614 ok_ole_success(hr
, CoMarshalInterface
);
616 ok_more_than_one_lock();
618 /* marshal 5 more times to exhaust the normal external references of 5 */
619 for (i
= 0; i
< NORMALEXTREFS
; i
++)
621 hr
= CoMarshalInterface(pStream
, &IID_IClassFactory
, pProxy
, MSHCTX_INPROC
, NULL
, MSHLFLAGS_NORMAL
);
622 ok_ole_success(hr
, CoMarshalInterface
);
625 ok_more_than_one_lock();
627 /* release the original proxy to test that we successfully keep the
628 * original object alive */
629 IUnknown_Release(pProxy
);
631 IStream_Seek(pStream
, ullZero
, STREAM_SEEK_SET
, NULL
);
632 hr
= CoUnmarshalInterface(pStream
, &IID_IClassFactory
, (void **)&pProxy2
);
633 ok_ole_success(hr
, CoUnmarshalInterface
);
635 ok_more_than_one_lock();
636 ok_non_zero_external_conn();
638 IUnknown_Release(pProxy2
);
640 /* unmarshal all of the proxies to check that the object stub still exists */
641 for (i
= 0; i
< NORMALEXTREFS
; i
++)
643 hr
= CoUnmarshalInterface(pStream
, &IID_IClassFactory
, (void **)&pProxy2
);
644 ok_ole_success(hr
, CoUnmarshalInterface
);
646 IUnknown_Release(pProxy2
);
650 ok_zero_external_conn();
651 ok_last_release_closes(TRUE
);
653 IStream_Release(pStream
);
655 end_host_object(tid
, thread
);
658 /* tests success case of an interthread marshal and then marshaling the proxy
659 * using an iid that hasn't previously been unmarshaled */
660 static void test_proxy_marshal_and_unmarshal2(void)
663 IStream
*pStream
= NULL
;
664 IUnknown
*pProxy
= NULL
;
665 IUnknown
*pProxy2
= NULL
;
670 external_connections
= 0;
672 hr
= CreateStreamOnHGlobal(NULL
, TRUE
, &pStream
);
673 ok_ole_success(hr
, CreateStreamOnHGlobal
);
674 tid
= start_host_object(pStream
, &IID_IUnknown
, (IUnknown
*)&Test_ClassFactory
, MSHLFLAGS_NORMAL
, &thread
);
676 ok_more_than_one_lock();
677 ok_non_zero_external_conn();
679 IStream_Seek(pStream
, ullZero
, STREAM_SEEK_SET
, NULL
);
680 hr
= CoUnmarshalInterface(pStream
, &IID_IUnknown
, (void **)&pProxy
);
681 ok_ole_success(hr
, CoUnmarshalInterface
);
683 ok_more_than_one_lock();
685 IStream_Seek(pStream
, ullZero
, STREAM_SEEK_SET
, NULL
);
686 /* marshal the proxy */
687 hr
= CoMarshalInterface(pStream
, &IID_IClassFactory
, pProxy
, MSHCTX_INPROC
, NULL
, MSHLFLAGS_NORMAL
);
688 ok_ole_success(hr
, CoMarshalInterface
);
690 ok_more_than_one_lock();
692 IStream_Seek(pStream
, ullZero
, STREAM_SEEK_SET
, NULL
);
693 /* unmarshal the second proxy to the object */
694 hr
= CoUnmarshalInterface(pStream
, &IID_IClassFactory
, (void **)&pProxy2
);
695 ok_ole_success(hr
, CoUnmarshalInterface
);
696 IStream_Release(pStream
);
698 /* now the proxies should be as follows:
699 * pProxy -> &Test_ClassFactory
700 * pProxy2 -> &Test_ClassFactory
701 * they should NOT be as follows:
702 * pProxy -> &Test_ClassFactory
704 * the above can only really be tested by looking in +ole traces
707 ok_more_than_one_lock();
709 IUnknown_Release(pProxy
);
711 ok_more_than_one_lock();
712 ok_non_zero_external_conn();
714 IUnknown_Release(pProxy2
);
717 ok_zero_external_conn();
718 ok_last_release_closes(TRUE
);
720 end_host_object(tid
, thread
);
723 /* tests success case of an interthread marshal and then table-weak-marshaling the proxy */
724 static void test_proxy_marshal_and_unmarshal_weak(void)
727 IStream
*pStream
= NULL
;
728 IUnknown
*pProxy
= NULL
;
729 IUnknown
*pProxy2
= NULL
;
734 external_connections
= 0;
736 hr
= CreateStreamOnHGlobal(NULL
, TRUE
, &pStream
);
737 ok_ole_success(hr
, CreateStreamOnHGlobal
);
738 tid
= start_host_object(pStream
, &IID_IClassFactory
, (IUnknown
*)&Test_ClassFactory
, MSHLFLAGS_NORMAL
, &thread
);
740 ok_more_than_one_lock();
741 ok_non_zero_external_conn();
743 IStream_Seek(pStream
, ullZero
, STREAM_SEEK_SET
, NULL
);
744 hr
= CoUnmarshalInterface(pStream
, &IID_IClassFactory
, (void **)&pProxy
);
745 ok_ole_success(hr
, CoUnmarshalInterface
);
747 ok_more_than_one_lock();
748 ok_non_zero_external_conn();
750 IStream_Seek(pStream
, ullZero
, STREAM_SEEK_SET
, NULL
);
751 /* marshal the proxy */
752 hr
= CoMarshalInterface(pStream
, &IID_IClassFactory
, pProxy
, MSHCTX_INPROC
, NULL
, MSHLFLAGS_TABLEWEAK
);
753 ok_ole_success(hr
, CoMarshalInterface
);
755 ok_more_than_one_lock();
756 ok_non_zero_external_conn();
758 /* release the original proxy to test that we successfully keep the
759 * original object alive */
760 IUnknown_Release(pProxy
);
762 IStream_Seek(pStream
, ullZero
, STREAM_SEEK_SET
, NULL
);
763 hr
= CoUnmarshalInterface(pStream
, &IID_IClassFactory
, (void **)&pProxy2
);
765 ok(hr
== CO_E_OBJNOTREG
, "CoUnmarshalInterface should return CO_E_OBJNOTREG instead of 0x%08x\n", hr
);
768 ok_zero_external_conn();
769 ok_last_release_closes(TRUE
);
771 IStream_Release(pStream
);
773 end_host_object(tid
, thread
);
776 /* tests success case of an interthread marshal and then table-strong-marshaling the proxy */
777 static void test_proxy_marshal_and_unmarshal_strong(void)
780 IStream
*pStream
= NULL
;
781 IUnknown
*pProxy
= NULL
;
782 IUnknown
*pProxy2
= NULL
;
787 external_connections
= 0;
789 hr
= CreateStreamOnHGlobal(NULL
, TRUE
, &pStream
);
790 ok_ole_success(hr
, CreateStreamOnHGlobal
);
791 tid
= start_host_object(pStream
, &IID_IClassFactory
, (IUnknown
*)&Test_ClassFactory
, MSHLFLAGS_NORMAL
, &thread
);
793 ok_more_than_one_lock();
794 ok_non_zero_external_conn();
796 IStream_Seek(pStream
, ullZero
, STREAM_SEEK_SET
, NULL
);
797 hr
= CoUnmarshalInterface(pStream
, &IID_IClassFactory
, (void **)&pProxy
);
798 ok_ole_success(hr
, CoUnmarshalInterface
);
800 ok_more_than_one_lock();
801 ok_non_zero_external_conn();
803 IStream_Seek(pStream
, ullZero
, STREAM_SEEK_SET
, NULL
);
804 /* marshal the proxy */
805 hr
= CoMarshalInterface(pStream
, &IID_IClassFactory
, pProxy
, MSHCTX_INPROC
, NULL
, MSHLFLAGS_TABLESTRONG
);
806 ok(hr
== S_OK
/* WinNT */ || hr
== E_INVALIDARG
/* Win9x */,
807 "CoMarshalInterface should have return S_OK or E_INVALIDARG instead of 0x%08x\n", hr
);
810 IUnknown_Release(pProxy
);
814 ok_more_than_one_lock();
815 ok_non_zero_external_conn();
817 /* release the original proxy to test that we successfully keep the
818 * original object alive */
819 IUnknown_Release(pProxy
);
821 IStream_Seek(pStream
, ullZero
, STREAM_SEEK_SET
, NULL
);
822 hr
= CoUnmarshalInterface(pStream
, &IID_IClassFactory
, (void **)&pProxy2
);
823 ok_ole_success(hr
, CoUnmarshalInterface
);
825 ok_more_than_one_lock();
826 ok_non_zero_external_conn();
828 IUnknown_Release(pProxy2
);
830 ok_more_than_one_lock();
831 ok_non_zero_external_conn();
834 IStream_Release(pStream
);
836 end_host_object(tid
, thread
);
840 ok_zero_external_conn();
841 ok_last_release_closes(FALSE
);
845 /* tests that stubs are released when the containing apartment is destroyed */
846 static void test_marshal_stub_apartment_shutdown(void)
849 IStream
*pStream
= NULL
;
850 IUnknown
*pProxy
= NULL
;
855 external_connections
= 0;
857 hr
= CreateStreamOnHGlobal(NULL
, TRUE
, &pStream
);
858 ok_ole_success(hr
, CreateStreamOnHGlobal
);
859 tid
= start_host_object(pStream
, &IID_IClassFactory
, (IUnknown
*)&Test_ClassFactory
, MSHLFLAGS_NORMAL
, &thread
);
861 ok_more_than_one_lock();
862 ok_non_zero_external_conn();
864 IStream_Seek(pStream
, ullZero
, STREAM_SEEK_SET
, NULL
);
865 hr
= CoUnmarshalInterface(pStream
, &IID_IClassFactory
, (void **)&pProxy
);
866 ok_ole_success(hr
, CoUnmarshalInterface
);
867 IStream_Release(pStream
);
869 ok_more_than_one_lock();
870 ok_non_zero_external_conn();
872 end_host_object(tid
, thread
);
876 ok_zero_external_conn();
877 ok_last_release_closes(FALSE
);
880 IUnknown_Release(pProxy
);
885 /* tests that proxies are released when the containing apartment is destroyed */
886 static void test_marshal_proxy_apartment_shutdown(void)
889 IStream
*pStream
= NULL
;
890 IUnknown
*pProxy
= NULL
;
895 external_connections
= 0;
897 hr
= CreateStreamOnHGlobal(NULL
, TRUE
, &pStream
);
898 ok_ole_success(hr
, CreateStreamOnHGlobal
);
899 tid
= start_host_object(pStream
, &IID_IClassFactory
, (IUnknown
*)&Test_ClassFactory
, MSHLFLAGS_NORMAL
, &thread
);
901 ok_more_than_one_lock();
902 ok_non_zero_external_conn();
904 IStream_Seek(pStream
, ullZero
, STREAM_SEEK_SET
, NULL
);
905 hr
= CoUnmarshalInterface(pStream
, &IID_IClassFactory
, (void **)&pProxy
);
906 ok_ole_success(hr
, CoUnmarshalInterface
);
907 IStream_Release(pStream
);
909 ok_more_than_one_lock();
910 ok_non_zero_external_conn();
915 ok_zero_external_conn();
916 ok_last_release_closes(TRUE
);
918 IUnknown_Release(pProxy
);
922 end_host_object(tid
, thread
);
924 pCoInitializeEx(NULL
, COINIT_APARTMENTTHREADED
);
927 /* tests that proxies are released when the containing mta apartment is destroyed */
928 static void test_marshal_proxy_mta_apartment_shutdown(void)
931 IStream
*pStream
= NULL
;
932 IUnknown
*pProxy
= NULL
;
937 pCoInitializeEx(NULL
, COINIT_MULTITHREADED
);
940 external_connections
= 0;
942 hr
= CreateStreamOnHGlobal(NULL
, TRUE
, &pStream
);
943 ok_ole_success(hr
, CreateStreamOnHGlobal
);
944 tid
= start_host_object(pStream
, &IID_IClassFactory
, (IUnknown
*)&Test_ClassFactory
, MSHLFLAGS_NORMAL
, &thread
);
946 ok_more_than_one_lock();
947 ok_non_zero_external_conn();
949 IStream_Seek(pStream
, ullZero
, STREAM_SEEK_SET
, NULL
);
950 hr
= CoUnmarshalInterface(pStream
, &IID_IClassFactory
, (void **)&pProxy
);
951 ok_ole_success(hr
, CoUnmarshalInterface
);
952 IStream_Release(pStream
);
954 ok_more_than_one_lock();
955 ok_non_zero_external_conn();
960 ok_zero_external_conn();
961 ok_last_release_closes(TRUE
);
963 IUnknown_Release(pProxy
);
967 end_host_object(tid
, thread
);
969 pCoInitializeEx(NULL
, COINIT_APARTMENTTHREADED
);
975 HANDLE marshal_event
;
976 HANDLE unmarshal_event
;
979 /* helper for test_no_couninitialize_server */
980 static DWORD CALLBACK
no_couninitialize_server_proc(LPVOID p
)
982 struct ncu_params
*ncu_params
= p
;
985 pCoInitializeEx(NULL
, COINIT_MULTITHREADED
);
987 hr
= CoMarshalInterface(ncu_params
->stream
, &IID_IClassFactory
, (IUnknown
*)&Test_ClassFactory
, MSHCTX_INPROC
, NULL
, MSHLFLAGS_NORMAL
);
988 ok_ole_success(hr
, CoMarshalInterface
);
990 SetEvent(ncu_params
->marshal_event
);
992 ok( !WaitForSingleObject(ncu_params
->unmarshal_event
, 10000), "wait timed out\n" );
994 /* die without calling CoUninitialize */
999 /* tests apartment that an apartment with a stub is released without deadlock
1000 * if the owning thread exits */
1001 static void test_no_couninitialize_server(void)
1004 IStream
*pStream
= NULL
;
1005 IUnknown
*pProxy
= NULL
;
1008 struct ncu_params ncu_params
;
1011 external_connections
= 0;
1013 ncu_params
.marshal_event
= CreateEventA(NULL
, TRUE
, FALSE
, NULL
);
1014 ncu_params
.unmarshal_event
= CreateEventA(NULL
, TRUE
, FALSE
, NULL
);
1016 hr
= CreateStreamOnHGlobal(NULL
, TRUE
, &pStream
);
1017 ok_ole_success(hr
, CreateStreamOnHGlobal
);
1018 ncu_params
.stream
= pStream
;
1020 thread
= CreateThread(NULL
, 0, no_couninitialize_server_proc
, &ncu_params
, 0, &tid
);
1022 ok( !WaitForSingleObject(ncu_params
.marshal_event
, 10000), "wait timed out\n" );
1023 ok_more_than_one_lock();
1024 ok_non_zero_external_conn();
1026 IStream_Seek(pStream
, ullZero
, STREAM_SEEK_SET
, NULL
);
1027 hr
= CoUnmarshalInterface(pStream
, &IID_IClassFactory
, (void **)&pProxy
);
1028 ok_ole_success(hr
, CoUnmarshalInterface
);
1029 IStream_Release(pStream
);
1031 ok_more_than_one_lock();
1032 ok_non_zero_external_conn();
1034 SetEvent(ncu_params
.unmarshal_event
);
1035 ok( !WaitForSingleObject(thread
, 10000), "wait timed out\n" );
1039 ok_zero_external_conn();
1040 ok_last_release_closes(FALSE
);
1043 CloseHandle(thread
);
1044 CloseHandle(ncu_params
.marshal_event
);
1045 CloseHandle(ncu_params
.unmarshal_event
);
1047 IUnknown_Release(pProxy
);
1052 /* STA -> STA call during DLL_THREAD_DETACH */
1053 static DWORD CALLBACK
no_couninitialize_client_proc(LPVOID p
)
1055 struct ncu_params
*ncu_params
= p
;
1057 IUnknown
*pProxy
= NULL
;
1059 pCoInitializeEx(NULL
, COINIT_APARTMENTTHREADED
);
1061 hr
= CoUnmarshalInterface(ncu_params
->stream
, &IID_IClassFactory
, (void **)&pProxy
);
1062 ok_ole_success(hr
, CoUnmarshalInterface
);
1063 IStream_Release(ncu_params
->stream
);
1065 ok_more_than_one_lock();
1067 /* die without calling CoUninitialize */
1072 /* tests STA -> STA call during DLL_THREAD_DETACH doesn't deadlock */
1073 static void test_no_couninitialize_client(void)
1076 IStream
*pStream
= NULL
;
1081 struct ncu_params ncu_params
;
1084 external_connections
= 0;
1086 hr
= CreateStreamOnHGlobal(NULL
, TRUE
, &pStream
);
1087 ok_ole_success(hr
, CreateStreamOnHGlobal
);
1088 ncu_params
.stream
= pStream
;
1090 /* NOTE: assumes start_host_object uses an STA to host the object, as MTAs
1091 * always deadlock when called from within DllMain */
1092 host_tid
= start_host_object(pStream
, &IID_IClassFactory
, (IUnknown
*)&Test_ClassFactory
, MSHLFLAGS_NORMAL
, &host_thread
);
1093 IStream_Seek(pStream
, ullZero
, STREAM_SEEK_SET
, NULL
);
1095 ok_more_than_one_lock();
1096 ok_non_zero_external_conn();
1098 thread
= CreateThread(NULL
, 0, no_couninitialize_client_proc
, &ncu_params
, 0, &tid
);
1100 ok( !WaitForSingleObject(thread
, 10000), "wait timed out\n" );
1101 CloseHandle(thread
);
1104 ok_zero_external_conn();
1105 ok_last_release_closes(TRUE
);
1107 end_host_object(host_tid
, host_thread
);
1110 static BOOL crash_thread_success
;
1112 static DWORD CALLBACK
crash_couninitialize_proc(void *p
)
1121 hr
= CreateStreamOnHGlobal(NULL
, TRUE
, &stream
);
1122 ok_ole_success(hr
, CreateStreamOnHGlobal
);
1124 hr
= CoMarshalInterface(stream
, &IID_IUnknown
, &TestCrash_Unknown
, MSHCTX_INPROC
, NULL
, MSHLFLAGS_NORMAL
);
1125 ok_ole_success(hr
, CoMarshalInterface
);
1127 IStream_Seek(stream
, ullZero
, STREAM_SEEK_SET
, NULL
);
1129 hr
= CoReleaseMarshalData(stream
);
1130 ok_ole_success(hr
, CoReleaseMarshalData
);
1134 hr
= CoMarshalInterface(stream
, &IID_IUnknown
, &TestCrash_Unknown
, MSHCTX_INPROC
, NULL
, MSHLFLAGS_NORMAL
);
1135 ok_ole_success(hr
, CoMarshalInterface
);
1137 ok_more_than_one_lock();
1139 trace("CoUninitialize >>>\n");
1141 trace("CoUninitialize <<<\n");
1145 IStream_Release(stream
);
1146 crash_thread_success
= TRUE
;
1150 static void test_crash_couninitialize(void)
1155 if(!GetProcAddress(GetModuleHandleA("kernel32.dll"), "CreateActCtxW")) {
1156 win_skip("Skipping crash tests on win2k.\n");
1160 crash_thread_success
= FALSE
;
1161 thread
= CreateThread(NULL
, 0, crash_couninitialize_proc
, NULL
, 0, &tid
);
1162 ok(!WaitForSingleObject(thread
, 10000), "wait timed out\n");
1163 CloseHandle(thread
);
1164 ok(crash_thread_success
, "Crash thread failed\n");
1167 /* tests success case of a same-thread table-weak marshal, unmarshal, unmarshal */
1168 static void test_tableweak_marshal_and_unmarshal_twice(void)
1171 IStream
*pStream
= NULL
;
1172 IUnknown
*pProxy1
= NULL
;
1173 IUnknown
*pProxy2
= NULL
;
1178 external_connections
= 0;
1180 hr
= CreateStreamOnHGlobal(NULL
, TRUE
, &pStream
);
1181 ok_ole_success(hr
, CreateStreamOnHGlobal
);
1182 tid
= start_host_object(pStream
, &IID_IClassFactory
, (IUnknown
*)&Test_ClassFactory
, MSHLFLAGS_TABLEWEAK
, &thread
);
1184 ok_more_than_one_lock();
1185 ok_zero_external_conn();
1187 IStream_Seek(pStream
, ullZero
, STREAM_SEEK_SET
, NULL
);
1188 hr
= CoUnmarshalInterface(pStream
, &IID_IClassFactory
, (void **)&pProxy1
);
1189 ok_ole_success(hr
, CoUnmarshalInterface
);
1191 ok_more_than_one_lock();
1192 ok_non_zero_external_conn();
1194 IStream_Seek(pStream
, ullZero
, STREAM_SEEK_SET
, NULL
);
1195 hr
= CoUnmarshalInterface(pStream
, &IID_IClassFactory
, (void **)&pProxy2
);
1196 ok_ole_success(hr
, CoUnmarshalInterface
);
1198 ok_more_than_one_lock();
1200 IUnknown_Release(pProxy1
);
1201 ok_non_zero_external_conn();
1202 IUnknown_Release(pProxy2
);
1203 ok_zero_external_conn();
1204 ok_last_release_closes(TRUE
);
1206 /* When IExternalConnection is present COM's lifetime management
1207 * behaviour is altered; the remaining weak ref prevents stub shutdown. */
1208 if (with_external_conn
)
1210 ok_more_than_one_lock();
1211 IStream_Seek(pStream
, ullZero
, STREAM_SEEK_SET
, NULL
);
1212 release_host_object(tid
, 0);
1215 /* Without IExternalConnection this line is shows the difference between weak and strong table marshaling
1216 * weak has cLocks == 0, strong has cLocks > 0. */
1219 IStream_Release(pStream
);
1220 end_host_object(tid
, thread
);
1223 /* tests releasing after unmarshaling one object */
1224 static void test_tableweak_marshal_releasedata1(void)
1227 IStream
*pStream
= NULL
;
1228 IUnknown
*pProxy1
= NULL
;
1229 IUnknown
*pProxy2
= NULL
;
1234 external_connections
= 0;
1236 hr
= CreateStreamOnHGlobal(NULL
, TRUE
, &pStream
);
1237 ok_ole_success(hr
, CreateStreamOnHGlobal
);
1238 tid
= start_host_object(pStream
, &IID_IClassFactory
, (IUnknown
*)&Test_ClassFactory
, MSHLFLAGS_TABLEWEAK
, &thread
);
1240 ok_more_than_one_lock();
1241 ok_zero_external_conn();
1243 IStream_Seek(pStream
, ullZero
, STREAM_SEEK_SET
, NULL
);
1244 hr
= CoUnmarshalInterface(pStream
, &IID_IClassFactory
, (void **)&pProxy1
);
1245 ok_ole_success(hr
, CoUnmarshalInterface
);
1247 ok_more_than_one_lock();
1248 ok_non_zero_external_conn();
1250 /* release the remaining reference on the object by calling
1251 * CoReleaseMarshalData in the hosting thread */
1252 IStream_Seek(pStream
, ullZero
, STREAM_SEEK_SET
, NULL
);
1253 release_host_object(tid
, 0);
1255 ok_more_than_one_lock();
1256 ok_non_zero_external_conn();
1258 IStream_Seek(pStream
, ullZero
, STREAM_SEEK_SET
, NULL
);
1259 hr
= CoUnmarshalInterface(pStream
, &IID_IClassFactory
, (void **)&pProxy2
);
1260 ok_ole_success(hr
, CoUnmarshalInterface
);
1261 IStream_Release(pStream
);
1263 ok_more_than_one_lock();
1264 ok_non_zero_external_conn();
1266 IUnknown_Release(pProxy1
);
1270 ok_non_zero_external_conn();
1271 IUnknown_Release(pProxy2
);
1274 /* this line is shows the difference between weak and strong table marshaling:
1275 * weak has cLocks == 0
1276 * strong has cLocks > 0 */
1278 ok_zero_external_conn();
1279 ok_last_release_closes(TRUE
);
1281 end_host_object(tid
, thread
);
1284 /* tests releasing after unmarshaling one object */
1285 static void test_tableweak_marshal_releasedata2(void)
1288 IStream
*pStream
= NULL
;
1289 IUnknown
*pProxy
= NULL
;
1294 external_connections
= 0;
1296 hr
= CreateStreamOnHGlobal(NULL
, TRUE
, &pStream
);
1297 ok_ole_success(hr
, CreateStreamOnHGlobal
);
1298 tid
= start_host_object(pStream
, &IID_IClassFactory
, (IUnknown
*)&Test_ClassFactory
, MSHLFLAGS_TABLEWEAK
, &thread
);
1300 ok_more_than_one_lock();
1301 ok_zero_external_conn();
1303 /* release the remaining reference on the object by calling
1304 * CoReleaseMarshalData in the hosting thread */
1305 IStream_Seek(pStream
, ullZero
, STREAM_SEEK_SET
, NULL
);
1306 release_host_object(tid
, 0);
1310 IStream_Seek(pStream
, ullZero
, STREAM_SEEK_SET
, NULL
);
1311 hr
= CoUnmarshalInterface(pStream
, &IID_IClassFactory
, (void **)&pProxy
);
1314 ok(hr
== CO_E_OBJNOTREG
,
1315 "CoUnmarshalInterface should have failed with CO_E_OBJNOTREG, but returned 0x%08x instead\n",
1318 IStream_Release(pStream
);
1321 ok_zero_external_conn();
1323 end_host_object(tid
, thread
);
1326 struct duo_marshal_data
1328 MSHLFLAGS marshal_flags1
, marshal_flags2
;
1329 IStream
*pStream1
, *pStream2
;
1334 static DWORD CALLBACK
duo_marshal_thread_proc(void *p
)
1337 struct duo_marshal_data
*data
= p
;
1338 HANDLE hQuitEvent
= data
->hQuitEvent
;
1341 pCoInitializeEx(NULL
, COINIT_APARTMENTTHREADED
);
1343 hr
= CoMarshalInterface(data
->pStream1
, &IID_IClassFactory
, (IUnknown
*)&Test_ClassFactory
, MSHCTX_INPROC
, NULL
, data
->marshal_flags1
);
1344 ok_ole_success(hr
, "CoMarshalInterface");
1346 hr
= CoMarshalInterface(data
->pStream2
, &IID_IClassFactory
, (IUnknown
*)&Test_ClassFactory
, MSHCTX_INPROC
, NULL
, data
->marshal_flags2
);
1347 ok_ole_success(hr
, "CoMarshalInterface");
1349 /* force the message queue to be created before signaling parent thread */
1350 PeekMessageA(&msg
, NULL
, WM_USER
, WM_USER
, PM_NOREMOVE
);
1352 SetEvent(data
->hReadyEvent
);
1354 while (WAIT_OBJECT_0
+ 1 == MsgWaitForMultipleObjects(1, &hQuitEvent
, FALSE
, 10000, QS_ALLINPUT
))
1356 while (PeekMessageA(&msg
, NULL
, 0, 0, PM_REMOVE
))
1358 if (msg
.hwnd
== NULL
&& msg
.message
== RELEASEMARSHALDATA
)
1360 CoReleaseMarshalData(msg
.wParam
== 1 ? data
->pStream1
: data
->pStream2
);
1361 SetEvent((HANDLE
)msg
.lParam
);
1364 DispatchMessageA(&msg
);
1367 CloseHandle(hQuitEvent
);
1374 /* tests interaction between table-weak and normal marshalling of an object */
1375 static void test_tableweak_and_normal_marshal_and_unmarshal(void)
1378 IUnknown
*pProxyWeak
= NULL
;
1379 IUnknown
*pProxyNormal
= NULL
;
1382 struct duo_marshal_data data
;
1385 external_connections
= 0;
1387 data
.hReadyEvent
= CreateEventA(NULL
, FALSE
, FALSE
, NULL
);
1388 data
.hQuitEvent
= CreateEventA(NULL
, FALSE
, FALSE
, NULL
);
1389 data
.marshal_flags1
= MSHLFLAGS_TABLEWEAK
;
1390 data
.marshal_flags2
= MSHLFLAGS_NORMAL
;
1391 hr
= CreateStreamOnHGlobal(NULL
, TRUE
, &data
.pStream1
);
1392 ok_ole_success(hr
, CreateStreamOnHGlobal
);
1393 hr
= CreateStreamOnHGlobal(NULL
, TRUE
, &data
.pStream2
);
1394 ok_ole_success(hr
, CreateStreamOnHGlobal
);
1396 thread
= CreateThread(NULL
, 0, duo_marshal_thread_proc
, &data
, 0, &tid
);
1397 ok( !WaitForSingleObject(data
.hReadyEvent
, 10000), "wait timed out\n" );
1398 CloseHandle(data
.hReadyEvent
);
1400 ok_more_than_one_lock();
1401 ok_non_zero_external_conn();
1404 IStream_Seek(data
.pStream1
, ullZero
, STREAM_SEEK_SET
, NULL
);
1405 hr
= CoUnmarshalInterface(data
.pStream1
, &IID_IClassFactory
, (void **)&pProxyWeak
);
1406 ok_ole_success(hr
, CoUnmarshalInterface
);
1408 ok_more_than_one_lock();
1411 IStream_Seek(data
.pStream2
, ullZero
, STREAM_SEEK_SET
, NULL
);
1412 hr
= CoUnmarshalInterface(data
.pStream2
, &IID_IClassFactory
, (void **)&pProxyNormal
);
1413 ok_ole_success(hr
, CoUnmarshalInterface
);
1415 ok_more_than_one_lock();
1417 IUnknown_Release(pProxyNormal
);
1419 ok_more_than_one_lock();
1420 ok_non_zero_external_conn();
1422 IUnknown_Release(pProxyWeak
);
1424 ok_zero_external_conn();
1425 ok_last_release_closes(TRUE
);
1427 /* When IExternalConnection is present COM's lifetime management
1428 * behaviour is altered; the remaining weak ref prevents stub shutdown. */
1429 if (with_external_conn
)
1431 ok_more_than_one_lock();
1432 IStream_Seek(data
.pStream1
, ullZero
, STREAM_SEEK_SET
, NULL
);
1433 release_host_object(tid
, 1);
1437 IStream_Release(data
.pStream1
);
1438 IStream_Release(data
.pStream2
);
1440 SetEvent(data
.hQuitEvent
);
1441 ok( !WaitForSingleObject(thread
, 10000), "wait timed out\n" );
1442 CloseHandle(thread
);
1445 static void test_tableweak_and_normal_marshal_and_releasedata(void)
1450 struct duo_marshal_data data
;
1453 external_connections
= 0;
1455 data
.hReadyEvent
= CreateEventA(NULL
, FALSE
, FALSE
, NULL
);
1456 data
.hQuitEvent
= CreateEventA(NULL
, FALSE
, FALSE
, NULL
);
1457 data
.marshal_flags1
= MSHLFLAGS_TABLEWEAK
;
1458 data
.marshal_flags2
= MSHLFLAGS_NORMAL
;
1459 hr
= CreateStreamOnHGlobal(NULL
, TRUE
, &data
.pStream1
);
1460 ok_ole_success(hr
, CreateStreamOnHGlobal
);
1461 hr
= CreateStreamOnHGlobal(NULL
, TRUE
, &data
.pStream2
);
1462 ok_ole_success(hr
, CreateStreamOnHGlobal
);
1464 thread
= CreateThread(NULL
, 0, duo_marshal_thread_proc
, &data
, 0, &tid
);
1465 ok( !WaitForSingleObject(data
.hReadyEvent
, 10000), "wait timed out\n" );
1466 CloseHandle(data
.hReadyEvent
);
1468 ok_more_than_one_lock();
1469 ok_non_zero_external_conn();
1471 /* release normal - which in the non-external conn case will free the object despite the weak ref. */
1472 IStream_Seek(data
.pStream2
, ullZero
, STREAM_SEEK_SET
, NULL
);
1473 release_host_object(tid
, 2);
1475 ok_zero_external_conn();
1476 ok_last_release_closes(TRUE
);
1478 if (with_external_conn
)
1480 ok_more_than_one_lock();
1481 IStream_Seek(data
.pStream1
, ullZero
, STREAM_SEEK_SET
, NULL
);
1482 release_host_object(tid
, 1);
1487 IStream_Release(data
.pStream1
);
1488 IStream_Release(data
.pStream2
);
1490 SetEvent(data
.hQuitEvent
);
1491 ok( !WaitForSingleObject(thread
, 10000), "wait timed out\n" );
1492 CloseHandle(thread
);
1495 static void test_two_tableweak_marshal_and_releasedata(void)
1500 struct duo_marshal_data data
;
1503 external_connections
= 0;
1505 data
.hReadyEvent
= CreateEventA(NULL
, FALSE
, FALSE
, NULL
);
1506 data
.hQuitEvent
= CreateEventA(NULL
, FALSE
, FALSE
, NULL
);
1507 data
.marshal_flags1
= MSHLFLAGS_TABLEWEAK
;
1508 data
.marshal_flags2
= MSHLFLAGS_TABLEWEAK
;
1509 hr
= CreateStreamOnHGlobal(NULL
, TRUE
, &data
.pStream1
);
1510 ok_ole_success(hr
, CreateStreamOnHGlobal
);
1511 hr
= CreateStreamOnHGlobal(NULL
, TRUE
, &data
.pStream2
);
1512 ok_ole_success(hr
, CreateStreamOnHGlobal
);
1514 thread
= CreateThread(NULL
, 0, duo_marshal_thread_proc
, &data
, 0, &tid
);
1515 ok( !WaitForSingleObject(data
.hReadyEvent
, 10000), "wait timed out\n" );
1516 CloseHandle(data
.hReadyEvent
);
1518 ok_more_than_one_lock();
1519 ok_zero_external_conn();
1521 /* release one weak ref - the remaining weak ref will keep the obj alive */
1522 IStream_Seek(data
.pStream1
, ullZero
, STREAM_SEEK_SET
, NULL
);
1523 release_host_object(tid
, 1);
1525 ok_more_than_one_lock();
1527 IStream_Seek(data
.pStream2
, ullZero
, STREAM_SEEK_SET
, NULL
);
1528 release_host_object(tid
, 2);
1532 IStream_Release(data
.pStream1
);
1533 IStream_Release(data
.pStream2
);
1535 SetEvent(data
.hQuitEvent
);
1536 ok( !WaitForSingleObject(thread
, 10000), "wait timed out\n" );
1537 CloseHandle(thread
);
1540 /* tests success case of a same-thread table-strong marshal, unmarshal, unmarshal */
1541 static void test_tablestrong_marshal_and_unmarshal_twice(void)
1544 IStream
*pStream
= NULL
;
1545 IUnknown
*pProxy1
= NULL
;
1546 IUnknown
*pProxy2
= NULL
;
1551 external_connections
= 0;
1553 hr
= CreateStreamOnHGlobal(NULL
, TRUE
, &pStream
);
1554 ok_ole_success(hr
, CreateStreamOnHGlobal
);
1555 tid
= start_host_object(pStream
, &IID_IClassFactory
, (IUnknown
*)&Test_ClassFactory
, MSHLFLAGS_TABLESTRONG
, &thread
);
1557 ok_more_than_one_lock();
1558 ok_non_zero_external_conn();
1560 IStream_Seek(pStream
, ullZero
, STREAM_SEEK_SET
, NULL
);
1561 hr
= CoUnmarshalInterface(pStream
, &IID_IClassFactory
, (void **)&pProxy1
);
1562 ok_ole_success(hr
, CoUnmarshalInterface
);
1564 ok_more_than_one_lock();
1566 IStream_Seek(pStream
, ullZero
, STREAM_SEEK_SET
, NULL
);
1567 hr
= CoUnmarshalInterface(pStream
, &IID_IClassFactory
, (void **)&pProxy2
);
1568 ok_ole_success(hr
, CoUnmarshalInterface
);
1570 ok_more_than_one_lock();
1572 if (pProxy1
) IUnknown_Release(pProxy1
);
1573 if (pProxy2
) IUnknown_Release(pProxy2
);
1575 /* this line is shows the difference between weak and strong table marshaling:
1576 * weak has cLocks == 0
1577 * strong has cLocks > 0 */
1578 ok_more_than_one_lock();
1580 /* release the remaining reference on the object by calling
1581 * CoReleaseMarshalData in the hosting thread */
1582 IStream_Seek(pStream
, ullZero
, STREAM_SEEK_SET
, NULL
);
1583 release_host_object(tid
, 0);
1584 IStream_Release(pStream
);
1587 ok_zero_external_conn();
1588 ok_last_release_closes(TRUE
);
1590 end_host_object(tid
, thread
);
1593 /* tests CoLockObjectExternal */
1594 static void test_lock_object_external(void)
1597 IStream
*pStream
= NULL
;
1600 external_connections
= 0;
1602 /* test the stub manager creation aspect of CoLockObjectExternal when the
1603 * object hasn't been marshaled yet */
1604 CoLockObjectExternal((IUnknown
*)&Test_ClassFactory
, TRUE
, TRUE
);
1606 ok_more_than_one_lock();
1607 ok_non_zero_external_conn();
1609 CoDisconnectObject((IUnknown
*)&Test_ClassFactory
, 0);
1612 ok_non_zero_external_conn();
1613 external_connections
= 0;
1615 /* test our empty stub manager being handled correctly in
1616 * CoMarshalInterface */
1617 CoLockObjectExternal((IUnknown
*)&Test_ClassFactory
, TRUE
, TRUE
);
1619 hr
= CreateStreamOnHGlobal(NULL
, TRUE
, &pStream
);
1620 ok_ole_success(hr
, CreateStreamOnHGlobal
);
1621 hr
= CoMarshalInterface(pStream
, &IID_IClassFactory
, (IUnknown
*)&Test_ClassFactory
, MSHCTX_INPROC
, NULL
, MSHLFLAGS_NORMAL
);
1622 ok_ole_success(hr
, CoMarshalInterface
);
1624 CoLockObjectExternal((IUnknown
*)&Test_ClassFactory
, TRUE
, TRUE
);
1626 ok_more_than_one_lock();
1627 ok_non_zero_external_conn();
1629 IStream_Seek(pStream
, ullZero
, STREAM_SEEK_SET
, NULL
);
1630 hr
= CoReleaseMarshalData(pStream
);
1631 ok_ole_success(hr
, CoReleaseMarshalData
);
1632 IStream_Seek(pStream
, ullZero
, STREAM_SEEK_SET
, NULL
);
1634 ok_more_than_one_lock();
1635 ok_non_zero_external_conn();
1636 ok_last_release_closes(TRUE
);
1638 CoLockObjectExternal((IUnknown
*)&Test_ClassFactory
, FALSE
, TRUE
);
1640 ok_more_than_one_lock();
1641 ok_non_zero_external_conn();
1642 ok_last_release_closes(TRUE
);
1644 CoLockObjectExternal((IUnknown
*)&Test_ClassFactory
, FALSE
, TRUE
);
1647 ok_zero_external_conn();
1648 ok_last_release_closes(TRUE
);
1650 /* test CoLockObjectExternal releases reference to object with
1651 * fLastUnlockReleases as TRUE and there are only strong references on
1653 CoLockObjectExternal((IUnknown
*)&Test_ClassFactory
, TRUE
, FALSE
);
1655 ok_more_than_one_lock();
1656 ok_non_zero_external_conn();
1658 CoLockObjectExternal((IUnknown
*)&Test_ClassFactory
, FALSE
, FALSE
);
1661 ok_zero_external_conn();
1662 ok_last_release_closes(FALSE
);
1664 /* test CoLockObjectExternal doesn't release the last reference to an
1665 * object with fLastUnlockReleases as TRUE and there is a weak reference
1667 hr
= CoMarshalInterface(pStream
, &IID_IClassFactory
, (IUnknown
*)&Test_ClassFactory
, MSHCTX_INPROC
, NULL
, MSHLFLAGS_TABLEWEAK
);
1668 ok_ole_success(hr
, CoMarshalInterface
);
1670 ok_more_than_one_lock();
1671 ok_zero_external_conn();
1673 CoLockObjectExternal((IUnknown
*)&Test_ClassFactory
, TRUE
, FALSE
);
1675 ok_more_than_one_lock();
1676 ok_non_zero_external_conn();
1678 CoLockObjectExternal((IUnknown
*)&Test_ClassFactory
, FALSE
, FALSE
);
1680 ok_more_than_one_lock();
1681 ok_zero_external_conn();
1682 ok_last_release_closes(FALSE
);
1684 CoDisconnectObject((IUnknown
*)&Test_ClassFactory
, 0);
1688 IStream_Release(pStream
);
1691 /* tests disconnecting stubs */
1692 static void test_disconnect_stub(void)
1695 IStream
*pStream
= NULL
;
1698 external_connections
= 0;
1700 hr
= CreateStreamOnHGlobal(NULL
, TRUE
, &pStream
);
1701 ok_ole_success(hr
, CreateStreamOnHGlobal
);
1702 hr
= CoMarshalInterface(pStream
, &IID_IClassFactory
, (IUnknown
*)&Test_ClassFactory
, MSHCTX_INPROC
, NULL
, MSHLFLAGS_NORMAL
);
1703 ok_ole_success(hr
, CoMarshalInterface
);
1705 ok_non_zero_external_conn();
1707 CoLockObjectExternal((IUnknown
*)&Test_ClassFactory
, TRUE
, TRUE
);
1709 ok_more_than_one_lock();
1710 ok_non_zero_external_conn();
1712 IStream_Seek(pStream
, ullZero
, STREAM_SEEK_SET
, NULL
);
1713 hr
= CoReleaseMarshalData(pStream
);
1714 ok_ole_success(hr
, CoReleaseMarshalData
);
1715 IStream_Release(pStream
);
1717 ok_more_than_one_lock();
1718 ok_non_zero_external_conn();
1720 CoDisconnectObject((IUnknown
*)&Test_ClassFactory
, 0);
1723 ok_non_zero_external_conn();
1725 hr
= CoDisconnectObject(NULL
, 0);
1726 ok( hr
== E_INVALIDARG
, "wrong status %x\n", hr
);
1729 /* tests failure case of a same-thread marshal and unmarshal twice */
1730 static void test_normal_marshal_and_unmarshal_twice(void)
1733 IStream
*pStream
= NULL
;
1734 IUnknown
*pProxy1
= NULL
;
1735 IUnknown
*pProxy2
= NULL
;
1738 external_connections
= 0;
1740 hr
= CreateStreamOnHGlobal(NULL
, TRUE
, &pStream
);
1741 ok_ole_success(hr
, CreateStreamOnHGlobal
);
1742 hr
= CoMarshalInterface(pStream
, &IID_IClassFactory
, (IUnknown
*)&Test_ClassFactory
, MSHCTX_INPROC
, NULL
, MSHLFLAGS_NORMAL
);
1743 ok_ole_success(hr
, CoMarshalInterface
);
1745 ok_more_than_one_lock();
1746 ok_non_zero_external_conn();
1748 IStream_Seek(pStream
, ullZero
, STREAM_SEEK_SET
, NULL
);
1749 hr
= CoUnmarshalInterface(pStream
, &IID_IClassFactory
, (void **)&pProxy1
);
1750 ok_ole_success(hr
, CoUnmarshalInterface
);
1752 ok_more_than_one_lock();
1753 ok_zero_external_conn();
1754 ok_last_release_closes(FALSE
);
1756 IStream_Seek(pStream
, ullZero
, STREAM_SEEK_SET
, NULL
);
1757 hr
= CoUnmarshalInterface(pStream
, &IID_IClassFactory
, (void **)&pProxy2
);
1758 ok(hr
== CO_E_OBJNOTCONNECTED
,
1759 "CoUnmarshalInterface should have failed with error CO_E_OBJNOTCONNECTED for double unmarshal, instead of 0x%08x\n", hr
);
1761 IStream_Release(pStream
);
1763 ok_more_than_one_lock();
1765 IUnknown_Release(pProxy1
);
1770 /* tests success case of marshaling and unmarshaling an HRESULT */
1771 static void test_hresult_marshaling(void)
1774 HRESULT hr_marshaled
= 0;
1775 IStream
*pStream
= NULL
;
1776 static const HRESULT E_DEADBEEF
= 0xdeadbeef;
1778 hr
= CreateStreamOnHGlobal(NULL
, TRUE
, &pStream
);
1779 ok_ole_success(hr
, CreateStreamOnHGlobal
);
1781 hr
= CoMarshalHresult(pStream
, E_DEADBEEF
);
1782 ok_ole_success(hr
, CoMarshalHresult
);
1784 IStream_Seek(pStream
, ullZero
, STREAM_SEEK_SET
, NULL
);
1785 hr
= IStream_Read(pStream
, &hr_marshaled
, sizeof(HRESULT
), NULL
);
1786 ok_ole_success(hr
, IStream_Read
);
1788 ok(hr_marshaled
== E_DEADBEEF
, "Didn't marshal HRESULT as expected: got value 0x%08x instead\n", hr_marshaled
);
1791 IStream_Seek(pStream
, ullZero
, STREAM_SEEK_SET
, NULL
);
1792 hr
= CoUnmarshalHresult(pStream
, &hr_marshaled
);
1793 ok_ole_success(hr
, CoUnmarshalHresult
);
1795 ok(hr_marshaled
== E_DEADBEEF
, "Didn't marshal HRESULT as expected: got value 0x%08x instead\n", hr_marshaled
);
1797 IStream_Release(pStream
);
1801 /* helper for test_proxy_used_in_wrong_thread */
1802 static DWORD CALLBACK
bad_thread_proc(LPVOID p
)
1804 IClassFactory
* cf
= p
;
1806 IUnknown
* proxy
= NULL
;
1808 hr
= IClassFactory_CreateInstance(cf
, NULL
, &IID_IUnknown
, (LPVOID
*)&proxy
);
1810 ok(hr
== CO_E_NOTINITIALIZED
,
1811 "COM should have failed with CO_E_NOTINITIALIZED on using proxy without apartment, but instead returned 0x%08x\n",
1814 hr
= IClassFactory_QueryInterface(cf
, &IID_IMultiQI
, (LPVOID
*)&proxy
);
1815 /* Win9x returns S_OK, whilst NT returns RPC_E_WRONG_THREAD */
1816 trace("call to proxy's QueryInterface for local interface without apartment returned 0x%08x\n", hr
);
1818 IUnknown_Release(proxy
);
1820 hr
= IClassFactory_QueryInterface(cf
, &IID_IStream
, (LPVOID
*)&proxy
);
1821 /* Win9x returns E_NOINTERFACE, whilst NT returns RPC_E_WRONG_THREAD */
1822 trace("call to proxy's QueryInterface without apartment returned 0x%08x\n", hr
);
1824 IUnknown_Release(proxy
);
1826 pCoInitializeEx(NULL
, COINIT_MULTITHREADED
);
1828 hr
= IClassFactory_CreateInstance(cf
, NULL
, &IID_IUnknown
, (LPVOID
*)&proxy
);
1829 if (proxy
) IUnknown_Release(proxy
);
1830 ok(hr
== RPC_E_WRONG_THREAD
,
1831 "COM should have failed with RPC_E_WRONG_THREAD on using proxy from wrong apartment, but instead returned 0x%08x\n",
1834 hr
= IClassFactory_QueryInterface(cf
, &IID_IStream
, (LPVOID
*)&proxy
);
1835 /* Win9x returns E_NOINTERFACE, whilst NT returns RPC_E_WRONG_THREAD */
1836 trace("call to proxy's QueryInterface from wrong apartment returned 0x%08x\n", hr
);
1838 /* now be really bad and release the proxy from the wrong apartment */
1839 IClassFactory_Release(cf
);
1846 /* tests failure case of a using a proxy in the wrong apartment */
1847 static void test_proxy_used_in_wrong_thread(void)
1850 IStream
*pStream
= NULL
;
1851 IUnknown
*pProxy
= NULL
;
1858 hr
= CreateStreamOnHGlobal(NULL
, TRUE
, &pStream
);
1859 ok_ole_success(hr
, CreateStreamOnHGlobal
);
1860 tid
= start_host_object(pStream
, &IID_IClassFactory
, (IUnknown
*)&Test_ClassFactory
, MSHLFLAGS_NORMAL
, &host_thread
);
1862 ok_more_than_one_lock();
1864 IStream_Seek(pStream
, ullZero
, STREAM_SEEK_SET
, NULL
);
1865 hr
= CoUnmarshalInterface(pStream
, &IID_IClassFactory
, (void **)&pProxy
);
1866 ok_ole_success(hr
, CoUnmarshalInterface
);
1867 IStream_Release(pStream
);
1869 ok_more_than_one_lock();
1871 /* do a call that will fail, but result in IRemUnknown being used by the proxy */
1872 IUnknown_QueryInterface(pProxy
, &IID_IStream
, (LPVOID
*)&pStream
);
1874 /* create a thread that we can misbehave in */
1875 thread
= CreateThread(NULL
, 0, bad_thread_proc
, pProxy
, 0, &tid2
);
1877 ok( !WaitForSingleObject(thread
, 10000), "wait timed out\n" );
1878 CloseHandle(thread
);
1880 /* do release statement on Win9x that we should have done above */
1881 if (!GetProcAddress(GetModuleHandleA("ole32"), "CoRegisterSurrogateEx"))
1882 IUnknown_Release(pProxy
);
1886 end_host_object(tid
, host_thread
);
1889 static HRESULT WINAPI
MessageFilter_QueryInterface(IMessageFilter
*iface
, REFIID riid
, void ** ppvObj
)
1891 if (ppvObj
== NULL
) return E_POINTER
;
1893 if (IsEqualGUID(riid
, &IID_IUnknown
) ||
1894 IsEqualGUID(riid
, &IID_IClassFactory
))
1897 IMessageFilter_AddRef(iface
);
1901 return E_NOINTERFACE
;
1904 static ULONG WINAPI
MessageFilter_AddRef(IMessageFilter
*iface
)
1906 return 2; /* non-heap object */
1909 static ULONG WINAPI
MessageFilter_Release(IMessageFilter
*iface
)
1911 return 1; /* non-heap object */
1914 static DWORD WINAPI
MessageFilter_HandleInComingCall(
1915 IMessageFilter
*iface
,
1917 HTASK threadIDCaller
,
1919 LPINTERFACEINFO lpInterfaceInfo
)
1921 static int callcount
= 0;
1923 trace("HandleInComingCall\n");
1927 ret
= SERVERCALL_REJECTED
;
1930 ret
= SERVERCALL_RETRYLATER
;
1933 ret
= SERVERCALL_ISHANDLED
;
1940 static DWORD WINAPI
MessageFilter_RetryRejectedCall(
1941 IMessageFilter
*iface
,
1942 HTASK threadIDCallee
,
1946 trace("RetryRejectedCall\n");
1950 static DWORD WINAPI
MessageFilter_MessagePending(
1951 IMessageFilter
*iface
,
1952 HTASK threadIDCallee
,
1954 DWORD dwPendingType
)
1956 trace("MessagePending\n");
1957 return PENDINGMSG_WAITNOPROCESS
;
1960 static const IMessageFilterVtbl MessageFilter_Vtbl
=
1962 MessageFilter_QueryInterface
,
1963 MessageFilter_AddRef
,
1964 MessageFilter_Release
,
1965 MessageFilter_HandleInComingCall
,
1966 MessageFilter_RetryRejectedCall
,
1967 MessageFilter_MessagePending
1970 static IMessageFilter MessageFilter
= { &MessageFilter_Vtbl
};
1972 static void test_message_filter(void)
1975 IStream
*pStream
= NULL
;
1976 IClassFactory
*cf
= NULL
;
1978 IUnknown
*proxy
= NULL
;
1979 IMessageFilter
*prev_filter
= NULL
;
1984 hr
= CreateStreamOnHGlobal(NULL
, TRUE
, &pStream
);
1985 ok_ole_success(hr
, CreateStreamOnHGlobal
);
1986 tid
= start_host_object2(pStream
, &IID_IClassFactory
, (IUnknown
*)&Test_ClassFactory
, MSHLFLAGS_NORMAL
, &MessageFilter
, &thread
);
1988 ok_more_than_one_lock();
1990 IStream_Seek(pStream
, ullZero
, STREAM_SEEK_SET
, NULL
);
1991 hr
= CoUnmarshalInterface(pStream
, &IID_IClassFactory
, (void **)&cf
);
1992 ok_ole_success(hr
, CoUnmarshalInterface
);
1993 IStream_Release(pStream
);
1995 ok_more_than_one_lock();
1997 hr
= IClassFactory_CreateInstance(cf
, NULL
, &IID_IUnknown
, (LPVOID
*)&proxy
);
1998 ok(hr
== RPC_E_CALL_REJECTED
, "Call should have returned RPC_E_CALL_REJECTED, but return 0x%08x instead\n", hr
);
1999 if (proxy
) IUnknown_Release(proxy
);
2002 hr
= CoRegisterMessageFilter(&MessageFilter
, &prev_filter
);
2003 ok_ole_success(hr
, CoRegisterMessageFilter
);
2005 hr
= IClassFactory_CreateInstance(cf
, NULL
, &IID_IUnknown
, (LPVOID
*)&proxy
);
2006 ok_ole_success(hr
, IClassFactory_CreateInstance
);
2008 IUnknown_Release(proxy
);
2010 IClassFactory_Release(cf
);
2014 end_host_object(tid
, thread
);
2016 hr
= CoRegisterMessageFilter(prev_filter
, NULL
);
2017 ok_ole_success(hr
, CoRegisterMessageFilter
);
2020 /* test failure case of trying to unmarshal from bad stream */
2021 static void test_bad_marshal_stream(void)
2024 IStream
*pStream
= NULL
;
2026 hr
= CreateStreamOnHGlobal(NULL
, TRUE
, &pStream
);
2027 ok_ole_success(hr
, CreateStreamOnHGlobal
);
2028 hr
= CoMarshalInterface(pStream
, &IID_IClassFactory
, (IUnknown
*)&Test_ClassFactory
, MSHCTX_INPROC
, NULL
, MSHLFLAGS_NORMAL
);
2029 ok_ole_success(hr
, CoMarshalInterface
);
2031 ok_more_than_one_lock();
2033 /* try to read beyond end of stream */
2034 hr
= CoReleaseMarshalData(pStream
);
2035 ok(hr
== STG_E_READFAULT
, "Should have failed with STG_E_READFAULT, but returned 0x%08x instead\n", hr
);
2037 /* now release for real */
2038 IStream_Seek(pStream
, ullZero
, STREAM_SEEK_SET
, NULL
);
2039 hr
= CoReleaseMarshalData(pStream
);
2040 ok_ole_success(hr
, CoReleaseMarshalData
);
2042 IStream_Release(pStream
);
2045 /* tests that proxies implement certain interfaces */
2046 static void test_proxy_interfaces(void)
2049 IStream
*pStream
= NULL
;
2050 IUnknown
*pProxy
= NULL
;
2051 IUnknown
*pOtherUnknown
= NULL
;
2057 hr
= CreateStreamOnHGlobal(NULL
, TRUE
, &pStream
);
2058 ok_ole_success(hr
, CreateStreamOnHGlobal
);
2059 tid
= start_host_object(pStream
, &IID_IClassFactory
, (IUnknown
*)&Test_ClassFactory
, MSHLFLAGS_NORMAL
, &thread
);
2061 ok_more_than_one_lock();
2063 IStream_Seek(pStream
, ullZero
, STREAM_SEEK_SET
, NULL
);
2064 hr
= CoUnmarshalInterface(pStream
, &IID_IUnknown
, (void **)&pProxy
);
2065 ok_ole_success(hr
, CoUnmarshalInterface
);
2066 IStream_Release(pStream
);
2068 ok_more_than_one_lock();
2070 hr
= IUnknown_QueryInterface(pProxy
, &IID_IUnknown
, (LPVOID
*)&pOtherUnknown
);
2071 ok_ole_success(hr
, IUnknown_QueryInterface IID_IUnknown
);
2072 if (hr
== S_OK
) IUnknown_Release(pOtherUnknown
);
2074 hr
= IUnknown_QueryInterface(pProxy
, &IID_IClientSecurity
, (LPVOID
*)&pOtherUnknown
);
2075 ok_ole_success(hr
, IUnknown_QueryInterface IID_IClientSecurity
);
2076 if (hr
== S_OK
) IUnknown_Release(pOtherUnknown
);
2078 hr
= IUnknown_QueryInterface(pProxy
, &IID_IMultiQI
, (LPVOID
*)&pOtherUnknown
);
2079 ok_ole_success(hr
, IUnknown_QueryInterface IID_IMultiQI
);
2080 if (hr
== S_OK
) IUnknown_Release(pOtherUnknown
);
2082 hr
= IUnknown_QueryInterface(pProxy
, &IID_IMarshal
, (LPVOID
*)&pOtherUnknown
);
2083 ok_ole_success(hr
, IUnknown_QueryInterface IID_IMarshal
);
2084 if (hr
== S_OK
) IUnknown_Release(pOtherUnknown
);
2086 /* IMarshal2 is also supported on NT-based systems, but is pretty much
2087 * useless as it has no more methods over IMarshal that it inherits from. */
2089 IUnknown_Release(pProxy
);
2093 end_host_object(tid
, thread
);
2098 IUnknown IUnknown_iface
;
2102 static inline HeapUnknown
*impl_from_IUnknown(IUnknown
*iface
)
2104 return CONTAINING_RECORD(iface
, HeapUnknown
, IUnknown_iface
);
2107 static HRESULT WINAPI
HeapUnknown_QueryInterface(IUnknown
*iface
, REFIID riid
, void **ppv
)
2109 if (IsEqualIID(riid
, &IID_IUnknown
))
2111 IUnknown_AddRef(iface
);
2116 return E_NOINTERFACE
;
2119 static ULONG WINAPI
HeapUnknown_AddRef(IUnknown
*iface
)
2121 HeapUnknown
*This
= impl_from_IUnknown(iface
);
2122 return InterlockedIncrement((LONG
*)&This
->refs
);
2125 static ULONG WINAPI
HeapUnknown_Release(IUnknown
*iface
)
2127 HeapUnknown
*This
= impl_from_IUnknown(iface
);
2128 ULONG refs
= InterlockedDecrement((LONG
*)&This
->refs
);
2129 if (!refs
) HeapFree(GetProcessHeap(), 0, This
);
2133 static const IUnknownVtbl HeapUnknown_Vtbl
=
2135 HeapUnknown_QueryInterface
,
2140 static void test_proxybuffer(REFIID riid
)
2143 IPSFactoryBuffer
*psfb
;
2144 IRpcProxyBuffer
*proxy
;
2148 HeapUnknown
*pUnkOuter
= HeapAlloc(GetProcessHeap(), 0, sizeof(*pUnkOuter
));
2150 pUnkOuter
->IUnknown_iface
.lpVtbl
= &HeapUnknown_Vtbl
;
2151 pUnkOuter
->refs
= 1;
2153 hr
= CoGetPSClsid(riid
, &clsid
);
2154 ok_ole_success(hr
, CoGetPSClsid
);
2156 hr
= CoGetClassObject(&clsid
, CLSCTX_INPROC_SERVER
, NULL
, &IID_IPSFactoryBuffer
, (LPVOID
*)&psfb
);
2157 ok_ole_success(hr
, CoGetClassObject
);
2159 hr
= IPSFactoryBuffer_CreateProxy(psfb
, &pUnkOuter
->IUnknown_iface
, riid
, &proxy
, &lpvtbl
);
2160 ok_ole_success(hr
, IPSFactoryBuffer_CreateProxy
);
2161 ok(lpvtbl
!= NULL
, "IPSFactoryBuffer_CreateProxy succeeded, but returned a NULL vtable!\n");
2163 /* release our reference to the outer unknown object - the PS factory
2164 * buffer will have AddRef's it in the CreateProxy call */
2165 refs
= IUnknown_Release(&pUnkOuter
->IUnknown_iface
);
2166 ok(refs
== 1, "Ref count of outer unknown should have been 1 instead of %d\n", refs
);
2168 /* Not checking return, unreliable on native. Maybe it leaks references? */
2169 IPSFactoryBuffer_Release(psfb
);
2171 refs
= IUnknown_Release((IUnknown
*)lpvtbl
);
2172 ok(refs
== 0, "Ref-count leak of %d on IRpcProxyBuffer\n", refs
);
2174 refs
= IRpcProxyBuffer_Release(proxy
);
2175 ok(refs
== 0, "Ref-count leak of %d on IRpcProxyBuffer\n", refs
);
2178 static void test_stubbuffer(REFIID riid
)
2181 IPSFactoryBuffer
*psfb
;
2182 IRpcStubBuffer
*stub
;
2188 hr
= CoGetPSClsid(riid
, &clsid
);
2189 ok_ole_success(hr
, CoGetPSClsid
);
2191 hr
= CoGetClassObject(&clsid
, CLSCTX_INPROC_SERVER
, NULL
, &IID_IPSFactoryBuffer
, (LPVOID
*)&psfb
);
2192 ok_ole_success(hr
, CoGetClassObject
);
2194 hr
= IPSFactoryBuffer_CreateStub(psfb
, riid
, (IUnknown
*)&Test_ClassFactory
, &stub
);
2195 ok_ole_success(hr
, IPSFactoryBuffer_CreateStub
);
2197 /* Not checking return, unreliable on native. Maybe it leaks references? */
2198 IPSFactoryBuffer_Release(psfb
);
2200 ok_more_than_one_lock();
2202 IRpcStubBuffer_Disconnect(stub
);
2206 refs
= IRpcStubBuffer_Release(stub
);
2207 ok(refs
== 0, "Ref-count leak of %d on IRpcProxyBuffer\n", refs
);
2210 static HWND hwnd_app
;
2212 static HRESULT WINAPI
TestRE_IClassFactory_CreateInstance(
2213 LPCLASSFACTORY iface
,
2214 LPUNKNOWN pUnkOuter
,
2219 if (IsEqualIID(riid
, &IID_IWineTest
))
2221 BOOL ret
= SendMessageTimeoutA(hwnd_app
, WM_NULL
, 0, 0, SMTO_BLOCK
, 5000, &res
);
2222 ok(ret
, "Timed out sending a message to originating window during RPC call\n");
2228 static const IClassFactoryVtbl TestREClassFactory_Vtbl
=
2230 Test_IClassFactory_QueryInterface
,
2231 Test_IClassFactory_AddRef
,
2232 Test_IClassFactory_Release
,
2233 TestRE_IClassFactory_CreateInstance
,
2234 Test_IClassFactory_LockServer
2237 static IClassFactory TestRE_ClassFactory
= { &TestREClassFactory_Vtbl
};
2239 static LRESULT CALLBACK
window_proc(HWND hwnd
, UINT msg
, WPARAM wparam
, LPARAM lparam
)
2246 IStream
*pStream
= NULL
;
2247 IClassFactory
*proxy
= NULL
;
2254 hr
= CreateStreamOnHGlobal(NULL
, TRUE
, &pStream
);
2255 ok_ole_success(hr
, CreateStreamOnHGlobal
);
2256 tid
= start_host_object(pStream
, &IID_IClassFactory
, (IUnknown
*)&TestRE_ClassFactory
, MSHLFLAGS_NORMAL
, &thread
);
2258 ok_more_than_one_lock();
2260 IStream_Seek(pStream
, ullZero
, STREAM_SEEK_SET
, NULL
);
2261 hr
= CoUnmarshalInterface(pStream
, &IID_IClassFactory
, (void **)&proxy
);
2262 ok_ole_success(hr
, CoReleaseMarshalData
);
2263 IStream_Release(pStream
);
2265 ok_more_than_one_lock();
2267 /* note the use of the magic IID_IWineTest value to tell remote thread
2268 * to try to send a message back to us */
2269 hr
= IClassFactory_CreateInstance(proxy
, NULL
, &IID_IWineTest
, (void **)&object
);
2270 ok(hr
== S_FALSE
, "expected S_FALSE, got %d\n", hr
);
2272 IClassFactory_Release(proxy
);
2276 end_host_object(tid
, thread
);
2278 PostMessageA(hwnd
, WM_QUIT
, 0, 0);
2285 IStream
*pStream
= NULL
;
2286 IClassFactory
*proxy
= NULL
;
2293 hr
= CreateStreamOnHGlobal(NULL
, TRUE
, &pStream
);
2294 ok_ole_success(hr
, CreateStreamOnHGlobal
);
2295 tid
= start_host_object(pStream
, &IID_IClassFactory
, (IUnknown
*)&TestRE_ClassFactory
, MSHLFLAGS_NORMAL
, &thread
);
2297 ok_more_than_one_lock();
2299 IStream_Seek(pStream
, ullZero
, STREAM_SEEK_SET
, NULL
);
2300 hr
= CoUnmarshalInterface(pStream
, &IID_IClassFactory
, (void **)&proxy
);
2301 ok_ole_success(hr
, CoReleaseMarshalData
);
2302 IStream_Release(pStream
);
2304 ok_more_than_one_lock();
2306 /* post quit message before a doing a COM call to show that a pending
2307 * WM_QUIT message doesn't stop the call from succeeding */
2308 PostMessageA(hwnd
, WM_QUIT
, 0, 0);
2309 hr
= IClassFactory_CreateInstance(proxy
, NULL
, &IID_IUnknown
, (void **)&object
);
2310 ok(hr
== S_FALSE
, "IClassFactory_CreateInstance returned 0x%08x, expected S_FALSE\n", hr
);
2312 IClassFactory_Release(proxy
);
2316 end_host_object(tid
, thread
);
2323 IStream
*pStream
= NULL
;
2324 IClassFactory
*proxy
= NULL
;
2329 hr
= CreateStreamOnHGlobal(NULL
, TRUE
, &pStream
);
2330 ok_ole_success(hr
, CreateStreamOnHGlobal
);
2331 tid
= start_host_object(pStream
, &IID_IClassFactory
, (IUnknown
*)&Test_ClassFactory
, MSHLFLAGS_NORMAL
, &thread
);
2333 IStream_Seek(pStream
, ullZero
, STREAM_SEEK_SET
, NULL
);
2334 hr
= CoUnmarshalInterface(pStream
, &IID_IClassFactory
, (void **)&proxy
);
2335 ok_ole_success(hr
, CoReleaseMarshalData
);
2336 IStream_Release(pStream
);
2338 /* shows that COM calls executed during the processing of sent
2339 * messages should fail */
2340 hr
= IClassFactory_CreateInstance(proxy
, NULL
, &IID_IUnknown
, (void **)&object
);
2341 ok(hr
== RPC_E_CANTCALLOUT_ININPUTSYNCCALL
,
2342 "COM call during processing of sent message should return RPC_E_CANTCALLOUT_ININPUTSYNCCALL instead of 0x%08x\n", hr
);
2344 IClassFactory_Release(proxy
);
2346 end_host_object(tid
, thread
);
2353 return DefWindowProcA(hwnd
, msg
, wparam
, lparam
);
2357 static void register_test_window(void)
2361 memset(&wndclass
, 0, sizeof(wndclass
));
2362 wndclass
.lpfnWndProc
= window_proc
;
2363 wndclass
.lpszClassName
= "WineCOMTest";
2364 RegisterClassA(&wndclass
);
2367 static void test_message_reentrancy(void)
2371 hwnd_app
= CreateWindowA("WineCOMTest", NULL
, 0, CW_USEDEFAULT
, CW_USEDEFAULT
, CW_USEDEFAULT
, CW_USEDEFAULT
, NULL
, NULL
, NULL
, 0);
2372 ok(hwnd_app
!= NULL
, "Window creation failed\n");
2374 /* start message re-entrancy test */
2375 PostMessageA(hwnd_app
, WM_USER
, 0, 0);
2377 while (GetMessageA(&msg
, NULL
, 0, 0))
2379 TranslateMessage(&msg
);
2380 DispatchMessageA(&msg
);
2382 DestroyWindow(hwnd_app
);
2385 static HRESULT WINAPI
TestMsg_IClassFactory_CreateInstance(
2386 LPCLASSFACTORY iface
,
2387 LPUNKNOWN pUnkOuter
,
2392 SendMessageA(hwnd_app
, WM_USER
+2, 0, 0);
2396 static IClassFactoryVtbl TestMsgClassFactory_Vtbl
=
2398 Test_IClassFactory_QueryInterface
,
2399 Test_IClassFactory_AddRef
,
2400 Test_IClassFactory_Release
,
2401 TestMsg_IClassFactory_CreateInstance
,
2402 Test_IClassFactory_LockServer
2405 static IClassFactory TestMsg_ClassFactory
= { &TestMsgClassFactory_Vtbl
};
2407 static void test_call_from_message(void)
2412 IClassFactory
*proxy
;
2417 hwnd_app
= CreateWindowA("WineCOMTest", NULL
, 0, CW_USEDEFAULT
, CW_USEDEFAULT
, CW_USEDEFAULT
, CW_USEDEFAULT
, NULL
, NULL
, NULL
, 0);
2418 ok(hwnd_app
!= NULL
, "Window creation failed\n");
2420 hr
= CreateStreamOnHGlobal(NULL
, TRUE
, &pStream
);
2421 ok_ole_success(hr
, CreateStreamOnHGlobal
);
2422 tid
= start_host_object(pStream
, &IID_IClassFactory
, (IUnknown
*)&TestMsg_ClassFactory
, MSHLFLAGS_NORMAL
, &thread
);
2424 ok_more_than_one_lock();
2426 IStream_Seek(pStream
, ullZero
, STREAM_SEEK_SET
, NULL
);
2427 hr
= CoUnmarshalInterface(pStream
, &IID_IClassFactory
, (void **)&proxy
);
2428 ok_ole_success(hr
, CoReleaseMarshalData
);
2429 IStream_Release(pStream
);
2431 ok_more_than_one_lock();
2433 /* start message re-entrancy test */
2434 hr
= IClassFactory_CreateInstance(proxy
, NULL
, &IID_IUnknown
, (void **)&object
);
2435 ok_ole_success(hr
, IClassFactory_CreateInstance
);
2437 IClassFactory_Release(proxy
);
2441 end_host_object(tid
, thread
);
2443 while (GetMessageA(&msg
, NULL
, 0, 0))
2445 TranslateMessage(&msg
);
2446 DispatchMessageA(&msg
);
2448 DestroyWindow(hwnd_app
);
2451 static void test_WM_QUIT_handling(void)
2455 hwnd_app
= CreateWindowA("WineCOMTest", NULL
, 0, CW_USEDEFAULT
, CW_USEDEFAULT
, CW_USEDEFAULT
, CW_USEDEFAULT
, NULL
, NULL
, NULL
, 0);
2456 ok(hwnd_app
!= NULL
, "Window creation failed\n");
2458 /* start WM_QUIT handling test */
2459 PostMessageA(hwnd_app
, WM_USER
+1, 0, 0);
2461 while (GetMessageA(&msg
, NULL
, 0, 0))
2463 TranslateMessage(&msg
);
2464 DispatchMessageA(&msg
);
2468 static SIZE_T
round_global_size(SIZE_T size
)
2470 static SIZE_T global_size_alignment
= -1;
2471 if (global_size_alignment
== -1)
2473 void *p
= GlobalAlloc(GMEM_FIXED
, 1);
2474 global_size_alignment
= GlobalSize(p
);
2478 return ((size
+ global_size_alignment
- 1) & ~(global_size_alignment
- 1));
2481 static void test_freethreadedmarshaldata(IStream
*pStream
, MSHCTX mshctx
, void *ptr
, DWORD mshlflags
)
2488 hr
= GetHGlobalFromStream(pStream
, &hglobal
);
2489 ok_ole_success(hr
, GetHGlobalFromStream
);
2491 size
= GlobalSize(hglobal
);
2493 marshal_data
= GlobalLock(hglobal
);
2495 if (mshctx
== MSHCTX_INPROC
)
2497 DWORD expected_size
= round_global_size(3*sizeof(DWORD
) + sizeof(GUID
));
2498 ok(size
== expected_size
||
2499 broken(size
== (2*sizeof(DWORD
))) /* Win9x & NT4 */,
2500 "size should have been %d instead of %d\n", expected_size
, size
);
2502 ok(*(DWORD
*)marshal_data
== mshlflags
, "expected 0x%x, but got 0x%x for mshctx\n", mshlflags
, *(DWORD
*)marshal_data
);
2503 marshal_data
+= sizeof(DWORD
);
2504 ok(*(void **)marshal_data
== ptr
, "expected %p, but got %p for mshctx\n", ptr
, *(void **)marshal_data
);
2505 marshal_data
+= sizeof(void *);
2506 if (sizeof(void*) == 4 && size
>= 3*sizeof(DWORD
))
2508 ok(*(DWORD
*)marshal_data
== 0, "expected 0x0, but got 0x%x\n", *(DWORD
*)marshal_data
);
2509 marshal_data
+= sizeof(DWORD
);
2511 if (size
>= 3*sizeof(DWORD
) + sizeof(GUID
))
2513 trace("got guid data: %s\n", wine_dbgstr_guid((GUID
*)marshal_data
));
2518 ok(size
> sizeof(DWORD
), "size should have been > sizeof(DWORD), not %d\n", size
);
2519 ok(*(DWORD
*)marshal_data
== 0x574f454d /* MEOW */,
2520 "marshal data should be filled by standard marshal and start with MEOW signature\n");
2523 GlobalUnlock(hglobal
);
2526 static void test_freethreadedmarshaler(void)
2529 IUnknown
*pFTUnknown
;
2530 IMarshal
*pFTMarshal
;
2533 static const LARGE_INTEGER llZero
;
2536 hr
= CoCreateFreeThreadedMarshaler(NULL
, &pFTUnknown
);
2537 ok_ole_success(hr
, CoCreateFreeThreadedMarshaler
);
2538 hr
= IUnknown_QueryInterface(pFTUnknown
, &IID_IMarshal
, (void **)&pFTMarshal
);
2539 ok_ole_success(hr
, IUnknown_QueryInterface
);
2540 IUnknown_Release(pFTUnknown
);
2542 hr
= CreateStreamOnHGlobal(NULL
, TRUE
, &pStream
);
2543 ok_ole_success(hr
, CreateStreamOnHGlobal
);
2545 /* inproc normal marshaling */
2547 hr
= IMarshal_MarshalInterface(pFTMarshal
, pStream
, &IID_IClassFactory
,
2548 &Test_ClassFactory
, MSHCTX_INPROC
, NULL
, MSHLFLAGS_NORMAL
);
2549 ok_ole_success(hr
, IMarshal_MarshalInterface
);
2551 ok_more_than_one_lock();
2553 test_freethreadedmarshaldata(pStream
, MSHCTX_INPROC
, &Test_ClassFactory
, MSHLFLAGS_NORMAL
);
2555 IStream_Seek(pStream
, llZero
, STREAM_SEEK_SET
, NULL
);
2556 hr
= IMarshal_UnmarshalInterface(pFTMarshal
, pStream
, &IID_IUnknown
, (void **)&pProxy
);
2557 ok_ole_success(hr
, IMarshal_UnmarshalInterface
);
2559 IUnknown_Release(pProxy
);
2563 /* native doesn't allow us to unmarshal or release the stream data,
2564 * presumably because it wants us to call CoMarshalInterface instead */
2567 /* local normal marshaling */
2569 IStream_Seek(pStream
, llZero
, STREAM_SEEK_SET
, NULL
);
2570 hr
= IMarshal_MarshalInterface(pFTMarshal
, pStream
, &IID_IClassFactory
, &Test_ClassFactory
, MSHCTX_LOCAL
, NULL
, MSHLFLAGS_NORMAL
);
2571 ok_ole_success(hr
, IMarshal_MarshalInterface
);
2573 ok_more_than_one_lock();
2575 test_freethreadedmarshaldata(pStream
, MSHCTX_LOCAL
, &Test_ClassFactory
, MSHLFLAGS_NORMAL
);
2577 IStream_Seek(pStream
, llZero
, STREAM_SEEK_SET
, NULL
);
2578 hr
= IMarshal_ReleaseMarshalData(pFTMarshal
, pStream
);
2579 ok_ole_success(hr
, IMarshal_ReleaseMarshalData
);
2584 /* inproc table-strong marshaling */
2586 IStream_Seek(pStream
, llZero
, STREAM_SEEK_SET
, NULL
);
2587 hr
= IMarshal_MarshalInterface(pFTMarshal
, pStream
, &IID_IClassFactory
,
2588 (IUnknown
*)&Test_ClassFactory
, MSHCTX_INPROC
, (void *)0xdeadbeef,
2589 MSHLFLAGS_TABLESTRONG
);
2590 ok_ole_success(hr
, IMarshal_MarshalInterface
);
2592 ok_more_than_one_lock();
2594 test_freethreadedmarshaldata(pStream
, MSHCTX_INPROC
, &Test_ClassFactory
, MSHLFLAGS_TABLESTRONG
);
2596 IStream_Seek(pStream
, llZero
, STREAM_SEEK_SET
, NULL
);
2597 hr
= IMarshal_UnmarshalInterface(pFTMarshal
, pStream
, &IID_IUnknown
, (void **)&pProxy
);
2598 ok_ole_success(hr
, IMarshal_UnmarshalInterface
);
2600 IUnknown_Release(pProxy
);
2602 ok_more_than_one_lock();
2604 IStream_Seek(pStream
, llZero
, STREAM_SEEK_SET
, NULL
);
2605 hr
= IMarshal_ReleaseMarshalData(pFTMarshal
, pStream
);
2606 ok_ole_success(hr
, IMarshal_ReleaseMarshalData
);
2610 /* inproc table-weak marshaling */
2612 IStream_Seek(pStream
, llZero
, STREAM_SEEK_SET
, NULL
);
2613 hr
= IMarshal_MarshalInterface(pFTMarshal
, pStream
, &IID_IClassFactory
,
2614 (IUnknown
*)&Test_ClassFactory
, MSHCTX_INPROC
, (void *)0xdeadbeef,
2615 MSHLFLAGS_TABLEWEAK
);
2616 ok_ole_success(hr
, IMarshal_MarshalInterface
);
2620 test_freethreadedmarshaldata(pStream
, MSHCTX_INPROC
, &Test_ClassFactory
, MSHLFLAGS_TABLEWEAK
);
2622 IStream_Seek(pStream
, llZero
, STREAM_SEEK_SET
, NULL
);
2623 hr
= IMarshal_UnmarshalInterface(pFTMarshal
, pStream
, &IID_IUnknown
, (void **)&pProxy
);
2624 ok_ole_success(hr
, IMarshal_UnmarshalInterface
);
2626 ok_more_than_one_lock();
2628 IUnknown_Release(pProxy
);
2632 /* inproc normal marshaling (for extraordinary cases) */
2634 IStream_Seek(pStream
, llZero
, STREAM_SEEK_SET
, NULL
);
2635 hr
= IMarshal_MarshalInterface(pFTMarshal
, pStream
, &IID_IClassFactory
,
2636 &Test_ClassFactory
, MSHCTX_INPROC
, NULL
, MSHLFLAGS_NORMAL
);
2637 ok_ole_success(hr
, IMarshal_MarshalInterface
);
2639 ok_more_than_one_lock();
2641 /* this call shows that DisconnectObject does nothing */
2642 hr
= IMarshal_DisconnectObject(pFTMarshal
, 0);
2643 ok_ole_success(hr
, IMarshal_DisconnectObject
);
2645 ok_more_than_one_lock();
2647 IStream_Seek(pStream
, llZero
, STREAM_SEEK_SET
, NULL
);
2648 hr
= IMarshal_ReleaseMarshalData(pFTMarshal
, pStream
);
2649 ok_ole_success(hr
, IMarshal_ReleaseMarshalData
);
2653 /* doesn't enforce marshaling rules here and allows us to unmarshal the
2654 * interface, even though it was freed above */
2655 IStream_Seek(pStream
, llZero
, STREAM_SEEK_SET
, NULL
);
2656 hr
= IMarshal_UnmarshalInterface(pFTMarshal
, pStream
, &IID_IUnknown
, (void **)&pProxy
);
2657 ok_ole_success(hr
, IMarshal_UnmarshalInterface
);
2661 IStream_Release(pStream
);
2662 IMarshal_Release(pFTMarshal
);
2665 static HRESULT
reg_unreg_wine_test_class(BOOL Register
)
2671 DWORD dwDisposition
;
2674 hr
= StringFromCLSID(&CLSID_WineTest
, &pszClsid
);
2675 ok_ole_success(hr
, "StringFromCLSID");
2676 strcpy(buffer
, "CLSID\\");
2677 WideCharToMultiByte(CP_ACP
, 0, pszClsid
, -1, buffer
+ strlen(buffer
), sizeof(buffer
) - strlen(buffer
), NULL
, NULL
);
2678 CoTaskMemFree(pszClsid
);
2679 strcat(buffer
, "\\InprocHandler32");
2682 error
= RegCreateKeyExA(HKEY_CLASSES_ROOT
, buffer
, 0, NULL
, 0, KEY_SET_VALUE
, NULL
, &hkey
, &dwDisposition
);
2683 if (error
== ERROR_ACCESS_DENIED
)
2685 skip("Not authorized to modify the Classes key\n");
2688 ok(error
== ERROR_SUCCESS
, "RegCreateKeyEx failed with error %d\n", error
);
2689 if (error
!= ERROR_SUCCESS
) hr
= E_FAIL
;
2690 error
= RegSetValueExA(hkey
, NULL
, 0, REG_SZ
, (const unsigned char *)"\"ole32.dll\"", strlen("\"ole32.dll\"") + 1);
2691 ok(error
== ERROR_SUCCESS
, "RegSetValueEx failed with error %d\n", error
);
2692 if (error
!= ERROR_SUCCESS
) hr
= E_FAIL
;
2697 RegDeleteKeyA(HKEY_CLASSES_ROOT
, buffer
);
2698 *strrchr(buffer
, '\\') = '\0';
2699 RegDeleteKeyA(HKEY_CLASSES_ROOT
, buffer
);
2704 static void test_inproc_handler(void)
2710 if (FAILED(reg_unreg_wine_test_class(TRUE
)))
2713 hr
= CoCreateInstance(&CLSID_WineTest
, NULL
, CLSCTX_INPROC_HANDLER
, &IID_IUnknown
, (void **)&pObject
);
2714 ok_ole_success(hr
, "CoCreateInstance");
2718 hr
= IUnknown_QueryInterface(pObject
, &IID_IWineTest
, (void **)&pObject2
);
2719 ok(hr
== E_NOINTERFACE
, "IUnknown_QueryInterface on handler for invalid interface returned 0x%08x instead of E_NOINTERFACE\n", hr
);
2721 /* it's a handler as it supports IOleObject */
2722 hr
= IUnknown_QueryInterface(pObject
, &IID_IOleObject
, (void **)&pObject2
);
2723 ok_ole_success(hr
, "IUnknown_QueryInterface(&IID_IOleObject)");
2724 IUnknown_Release(pObject2
);
2726 IUnknown_Release(pObject
);
2729 reg_unreg_wine_test_class(FALSE
);
2732 static HRESULT WINAPI
Test_SMI_QueryInterface(
2733 IStdMarshalInfo
*iface
,
2737 if (ppvObj
== NULL
) return E_POINTER
;
2739 if (IsEqualGUID(riid
, &IID_IUnknown
) ||
2740 IsEqualGUID(riid
, &IID_IStdMarshalInfo
))
2743 IStdMarshalInfo_AddRef(iface
);
2747 return E_NOINTERFACE
;
2750 static ULONG WINAPI
Test_SMI_AddRef(IStdMarshalInfo
*iface
)
2753 return 2; /* non-heap-based object */
2756 static ULONG WINAPI
Test_SMI_Release(IStdMarshalInfo
*iface
)
2759 return 1; /* non-heap-based object */
2762 static HRESULT WINAPI
Test_SMI_GetClassForHandler(
2763 IStdMarshalInfo
*iface
,
2764 DWORD dwDestContext
,
2765 void *pvDestContext
,
2768 *pClsid
= CLSID_WineTest
;
2772 static const IStdMarshalInfoVtbl Test_SMI_Vtbl
=
2774 Test_SMI_QueryInterface
,
2777 Test_SMI_GetClassForHandler
2780 static IStdMarshalInfo Test_SMI
= {&Test_SMI_Vtbl
};
2782 static void test_handler_marshaling(void)
2785 IStream
*pStream
= NULL
;
2786 IUnknown
*pProxy
= NULL
;
2790 static const LARGE_INTEGER ullZero
;
2792 if (FAILED(reg_unreg_wine_test_class(TRUE
)))
2796 hr
= CreateStreamOnHGlobal(NULL
, TRUE
, &pStream
);
2797 ok_ole_success(hr
, "CreateStreamOnHGlobal");
2798 tid
= start_host_object(pStream
, &IID_IUnknown
, (IUnknown
*)&Test_SMI
, MSHLFLAGS_NORMAL
, &thread
);
2800 ok_more_than_one_lock();
2802 IStream_Seek(pStream
, ullZero
, STREAM_SEEK_SET
, NULL
);
2803 hr
= CoUnmarshalInterface(pStream
, &IID_IUnknown
, (void **)&pProxy
);
2804 ok_ole_success(hr
, "CoUnmarshalInterface");
2805 IStream_Release(pStream
);
2809 ok_more_than_one_lock();
2811 hr
= IUnknown_QueryInterface(pProxy
, &IID_IWineTest
, (void **)&pObject
);
2812 ok(hr
== E_NOINTERFACE
, "IUnknown_QueryInterface with unknown IID should have returned E_NOINTERFACE instead of 0x%08x\n", hr
);
2814 /* it's a handler as it supports IOleObject */
2815 hr
= IUnknown_QueryInterface(pProxy
, &IID_IOleObject
, (void **)&pObject
);
2817 ok_ole_success(hr
, "IUnknown_QueryInterface(&IID_IOleObject)");
2818 if (SUCCEEDED(hr
)) IUnknown_Release(pObject
);
2820 IUnknown_Release(pProxy
);
2825 end_host_object(tid
, thread
);
2826 reg_unreg_wine_test_class(FALSE
);
2828 /* FIXME: test IPersist interface has the same effect as IStdMarshalInfo */
2832 static void test_client_security(void)
2835 IStream
*pStream
= NULL
;
2836 IClassFactory
*pProxy
= NULL
;
2837 IUnknown
*pProxy2
= NULL
;
2838 IUnknown
*pUnknown1
= NULL
;
2839 IUnknown
*pUnknown2
= NULL
;
2840 IClientSecurity
*pCliSec
= NULL
;
2844 static const LARGE_INTEGER ullZero
;
2847 OLECHAR
*pServerPrincName
;
2851 DWORD dwCapabilities
;
2856 hr
= CreateStreamOnHGlobal(NULL
, TRUE
, &pStream
);
2857 ok_ole_success(hr
, "CreateStreamOnHGlobal");
2858 tid
= start_host_object(pStream
, &IID_IClassFactory
, (IUnknown
*)&Test_ClassFactory
, MSHLFLAGS_NORMAL
, &thread
);
2860 IStream_Seek(pStream
, ullZero
, STREAM_SEEK_SET
, NULL
);
2861 hr
= CoUnmarshalInterface(pStream
, &IID_IClassFactory
, (void **)&pProxy
);
2862 ok_ole_success(hr
, "CoUnmarshalInterface");
2863 IStream_Release(pStream
);
2865 hr
= IClassFactory_QueryInterface(pProxy
, &IID_IUnknown
, (LPVOID
*)&pUnknown1
);
2866 ok_ole_success(hr
, "IUnknown_QueryInterface IID_IUnknown");
2868 hr
= IClassFactory_QueryInterface(pProxy
, &IID_IRemUnknown
, (LPVOID
*)&pProxy2
);
2869 ok_ole_success(hr
, "IUnknown_QueryInterface IID_IStream");
2871 hr
= IUnknown_QueryInterface(pProxy2
, &IID_IUnknown
, (LPVOID
*)&pUnknown2
);
2872 ok_ole_success(hr
, "IUnknown_QueryInterface IID_IUnknown");
2874 ok(pUnknown1
== pUnknown2
, "both proxy's IUnknowns should be the same - %p, %p\n", pUnknown1
, pUnknown2
);
2876 hr
= IClassFactory_QueryInterface(pProxy
, &IID_IMarshal
, (LPVOID
*)&pMarshal
);
2877 ok_ole_success(hr
, "IUnknown_QueryInterface IID_IMarshal");
2879 hr
= IClassFactory_QueryInterface(pProxy
, &IID_IClientSecurity
, (LPVOID
*)&pCliSec
);
2880 ok_ole_success(hr
, "IUnknown_QueryInterface IID_IClientSecurity");
2882 hr
= IClientSecurity_QueryBlanket(pCliSec
, (IUnknown
*)pProxy
, NULL
, NULL
, NULL
, NULL
, NULL
, NULL
, NULL
);
2883 todo_wine
ok_ole_success(hr
, "IClientSecurity_QueryBlanket (all NULLs)");
2885 hr
= IClientSecurity_QueryBlanket(pCliSec
, (IUnknown
*)pMarshal
, NULL
, NULL
, NULL
, NULL
, NULL
, NULL
, NULL
);
2886 todo_wine
ok(hr
== E_NOINTERFACE
, "IClientSecurity_QueryBlanket with local interface should have returned E_NOINTERFACE instead of 0x%08x\n", hr
);
2888 hr
= IClientSecurity_QueryBlanket(pCliSec
, (IUnknown
*)pProxy
, &dwAuthnSvc
, &dwAuthzSvc
, &pServerPrincName
, &dwAuthnLevel
, &dwImpLevel
, &pAuthInfo
, &dwCapabilities
);
2889 todo_wine
ok_ole_success(hr
, "IClientSecurity_QueryBlanket");
2891 hr
= IClientSecurity_SetBlanket(pCliSec
, (IUnknown
*)pProxy
, dwAuthnSvc
, dwAuthzSvc
, pServerPrincName
, dwAuthnLevel
, RPC_C_IMP_LEVEL_IMPERSONATE
, pAuthInfo
, dwCapabilities
);
2892 todo_wine
ok_ole_success(hr
, "IClientSecurity_SetBlanket");
2894 hr
= IClassFactory_CreateInstance(pProxy
, NULL
, &IID_IWineTest
, &pv
);
2895 ok(hr
== E_NOINTERFACE
, "COM call should have succeeded instead of returning 0x%08x\n", hr
);
2897 hr
= IClientSecurity_SetBlanket(pCliSec
, (IUnknown
*)pMarshal
, dwAuthnSvc
, dwAuthzSvc
, pServerPrincName
, dwAuthnLevel
, dwImpLevel
, pAuthInfo
, dwCapabilities
);
2898 todo_wine
ok(hr
== E_NOINTERFACE
, "IClientSecurity_SetBlanket with local interface should have returned E_NOINTERFACE instead of 0x%08x\n", hr
);
2900 hr
= IClientSecurity_SetBlanket(pCliSec
, (IUnknown
*)pProxy
, 0xdeadbeef, dwAuthzSvc
, pServerPrincName
, dwAuthnLevel
, dwImpLevel
, pAuthInfo
, dwCapabilities
);
2901 todo_wine
ok(hr
== E_INVALIDARG
, "IClientSecurity_SetBlanke with invalid dwAuthnSvc should have returned E_INVALIDARG instead of 0x%08x\n", hr
);
2903 CoTaskMemFree(pServerPrincName
);
2905 hr
= IClientSecurity_QueryBlanket(pCliSec
, pUnknown1
, &dwAuthnSvc
, &dwAuthzSvc
, &pServerPrincName
, &dwAuthnLevel
, &dwImpLevel
, &pAuthInfo
, &dwCapabilities
);
2906 todo_wine
ok_ole_success(hr
, "IClientSecurity_QueryBlanket(IUnknown)");
2908 CoTaskMemFree(pServerPrincName
);
2910 IClassFactory_Release(pProxy
);
2911 IUnknown_Release(pProxy2
);
2912 IUnknown_Release(pUnknown1
);
2913 IUnknown_Release(pUnknown2
);
2914 IMarshal_Release(pMarshal
);
2915 IClientSecurity_Release(pCliSec
);
2917 end_host_object(tid
, thread
);
2920 static HANDLE heventShutdown
;
2922 static void LockModuleOOP(void)
2924 InterlockedIncrement(&cLocks
); /* for test purposes only */
2925 CoAddRefServerProcess();
2928 static void UnlockModuleOOP(void)
2930 InterlockedDecrement(&cLocks
); /* for test purposes only */
2931 if (!CoReleaseServerProcess())
2932 SetEvent(heventShutdown
);
2935 static HWND hwnd_app
;
2939 IPersist IPersist_iface
; /* a nice short interface */
2942 static HRESULT WINAPI
local_server_QueryInterface(IPersist
*iface
, REFIID iid
, void **obj
)
2946 if (IsEqualGUID(iid
, &IID_IUnknown
) ||
2947 IsEqualGUID(iid
, &IID_IPersist
))
2952 IPersist_AddRef(iface
);
2955 return E_NOINTERFACE
;
2958 static ULONG WINAPI
local_server_AddRef(IPersist
*iface
)
2963 static ULONG WINAPI
local_server_Release(IPersist
*iface
)
2968 static HRESULT WINAPI
local_server_GetClassID(IPersist
*iface
, CLSID
*clsid
)
2972 *clsid
= IID_IUnknown
;
2974 /* Test calling CoDisconnectObject within a COM call */
2975 hr
= CoDisconnectObject((IUnknown
*)iface
, 0);
2976 ok(hr
== S_OK
, "got %08x\n", hr
);
2981 static const IPersistVtbl local_server_persist_vtbl
=
2983 local_server_QueryInterface
,
2984 local_server_AddRef
,
2985 local_server_Release
,
2986 local_server_GetClassID
2989 struct local_server local_server_class
=
2991 {&local_server_persist_vtbl
}
2994 static HRESULT WINAPI
TestOOP_IClassFactory_QueryInterface(
2995 LPCLASSFACTORY iface
,
2999 if (ppvObj
== NULL
) return E_POINTER
;
3001 if (IsEqualGUID(riid
, &IID_IUnknown
) ||
3002 IsEqualGUID(riid
, &IID_IClassFactory
))
3005 IClassFactory_AddRef(iface
);
3009 return E_NOINTERFACE
;
3012 static ULONG WINAPI
TestOOP_IClassFactory_AddRef(LPCLASSFACTORY iface
)
3014 return 2; /* non-heap-based object */
3017 static ULONG WINAPI
TestOOP_IClassFactory_Release(LPCLASSFACTORY iface
)
3019 return 1; /* non-heap-based object */
3022 static HRESULT WINAPI
TestOOP_IClassFactory_CreateInstance(
3023 LPCLASSFACTORY iface
,
3024 LPUNKNOWN pUnkOuter
,
3028 IPersist
*persist
= &local_server_class
.IPersist_iface
;
3030 IPersist_AddRef( persist
);
3031 hr
= IPersist_QueryInterface( persist
, riid
, ppvObj
);
3032 IPersist_Release( persist
);
3036 static HRESULT WINAPI
TestOOP_IClassFactory_LockServer(
3037 LPCLASSFACTORY iface
,
3047 static const IClassFactoryVtbl TestClassFactoryOOP_Vtbl
=
3049 TestOOP_IClassFactory_QueryInterface
,
3050 TestOOP_IClassFactory_AddRef
,
3051 TestOOP_IClassFactory_Release
,
3052 TestOOP_IClassFactory_CreateInstance
,
3053 TestOOP_IClassFactory_LockServer
3056 static IClassFactory TestOOP_ClassFactory
= { &TestClassFactoryOOP_Vtbl
};
3058 static void test_register_local_server(void)
3066 heventShutdown
= CreateEventA(NULL
, TRUE
, FALSE
, NULL
);
3067 ready_event
= CreateEventA(NULL
, FALSE
, FALSE
, "Wine COM Test Ready Event");
3068 handles
[0] = CreateEventA(NULL
, FALSE
, FALSE
, "Wine COM Test Quit Event");
3069 handles
[1] = CreateEventA(NULL
, FALSE
, FALSE
, "Wine COM Test Repeat Event");
3072 hr
= CoRegisterClassObject(&CLSID_WineOOPTest
, (IUnknown
*)&TestOOP_ClassFactory
,
3073 CLSCTX_LOCAL_SERVER
, REGCLS_SINGLEUSE
, &cookie
);
3074 ok_ole_success(hr
, CoRegisterClassObject
);
3076 SetEvent(ready_event
);
3080 wait
= MsgWaitForMultipleObjects(2, handles
, FALSE
, 30000, QS_ALLINPUT
);
3081 if (wait
== WAIT_OBJECT_0
+2)
3085 if (PeekMessageA(&msg
, NULL
, 0, 0, PM_REMOVE
))
3087 trace("Message 0x%x\n", msg
.message
);
3088 TranslateMessage(&msg
);
3089 DispatchMessageA(&msg
);
3092 else if (wait
== WAIT_OBJECT_0
+1)
3094 hr
= CoRevokeClassObject(cookie
);
3095 ok_ole_success(hr
, CoRevokeClassObject
);
3099 while (wait
== WAIT_OBJECT_0
+2);
3101 ok( wait
== WAIT_OBJECT_0
, "quit event wait timed out\n" );
3102 hr
= CoRevokeClassObject(cookie
);
3103 ok_ole_success(hr
, CoRevokeClassObject
);
3104 CloseHandle(handles
[0]);
3105 CloseHandle(handles
[1]);
3108 static HANDLE
create_target_process(const char *arg
)
3111 char cmdline
[MAX_PATH
];
3113 PROCESS_INFORMATION pi
;
3114 STARTUPINFOA si
= { 0 };
3119 winetest_get_mainargs( &argv
);
3120 sprintf(cmdline
, "\"%s\" %s %s", argv
[0], argv
[1], arg
);
3121 ret
= CreateProcessA(argv
[0], cmdline
, NULL
, NULL
, FALSE
, 0, NULL
, NULL
, &si
, &pi
);
3122 ok(ret
, "CreateProcess failed with error: %u\n", GetLastError());
3123 if (pi
.hThread
) CloseHandle(pi
.hThread
);
3127 /* tests functions commonly used by out of process COM servers */
3128 static void test_local_server(void)
3138 HANDLE repeat_event
;
3141 heventShutdown
= CreateEventA(NULL
, TRUE
, FALSE
, NULL
);
3145 /* Start the object suspended */
3146 hr
= CoRegisterClassObject(&CLSID_WineOOPTest
, (IUnknown
*)&TestOOP_ClassFactory
,
3147 CLSCTX_LOCAL_SERVER
, REGCLS_MULTIPLEUSE
| REGCLS_SUSPENDED
, &cookie
);
3148 ok_ole_success(hr
, CoRegisterClassObject
);
3150 /* ... and CoGetClassObject does not find it and fails when it looks for the
3151 * class in the registry */
3152 hr
= CoGetClassObject(&CLSID_WineOOPTest
, CLSCTX_INPROC_SERVER
,
3153 NULL
, &IID_IClassFactory
, (LPVOID
*)&cf
);
3154 ok(hr
== REGDB_E_CLASSNOTREG
|| /* NT */
3155 hr
== S_OK
/* Win9x */,
3156 "CoGetClassObject should have returned REGDB_E_CLASSNOTREG instead of 0x%08x\n", hr
);
3158 /* Resume the object suspended above ... */
3159 hr
= CoResumeClassObjects();
3160 ok_ole_success(hr
, CoResumeClassObjects
);
3162 /* ... and now it should succeed */
3163 hr
= CoGetClassObject(&CLSID_WineOOPTest
, CLSCTX_INPROC_SERVER
,
3164 NULL
, &IID_IClassFactory
, (LPVOID
*)&cf
);
3165 ok_ole_success(hr
, CoGetClassObject
);
3167 /* Now check the locking is working */
3168 /* NOTE: we are accessing the class directly, not through a proxy */
3172 hr
= IClassFactory_LockServer(cf
, TRUE
);
3173 ok_ole_success(hr
, IClassFactory_LockServer
);
3175 ok_more_than_one_lock();
3177 IClassFactory_LockServer(cf
, FALSE
);
3178 ok_ole_success(hr
, IClassFactory_LockServer
);
3182 IClassFactory_Release(cf
);
3184 /* wait for shutdown signal */
3185 ret
= WaitForSingleObject(heventShutdown
, 0);
3186 ok(ret
!= WAIT_TIMEOUT
, "Server didn't shut down\n");
3188 /* try to connect again after SCM has suspended registered class objects */
3189 hr
= CoGetClassObject(&CLSID_WineOOPTest
, CLSCTX_INPROC_SERVER
| CLSCTX_LOCAL_SERVER
, NULL
,
3190 &IID_IClassFactory
, (LPVOID
*)&cf
);
3191 ok(hr
== CO_E_SERVER_STOPPING
|| /* NT */
3192 hr
== REGDB_E_CLASSNOTREG
|| /* win2k */
3193 hr
== S_OK
/* Win9x */,
3194 "CoGetClassObject should have returned CO_E_SERVER_STOPPING or REGDB_E_CLASSNOTREG instead of 0x%08x\n", hr
);
3196 hr
= CoRevokeClassObject(cookie
);
3197 ok_ole_success(hr
, CoRevokeClassObject
);
3199 CloseHandle(heventShutdown
);
3201 process
= create_target_process("-Embedding");
3202 ok(process
!= NULL
, "couldn't start local server process, error was %d\n", GetLastError());
3204 ready_event
= CreateEventA(NULL
, FALSE
, FALSE
, "Wine COM Test Ready Event");
3205 ok( !WaitForSingleObject(ready_event
, 10000), "wait timed out\n" );
3207 hr
= CoCreateInstance(&CLSID_WineOOPTest
, NULL
, CLSCTX_LOCAL_SERVER
, &IID_IPersist
, (void **)&persist
);
3208 ok_ole_success(hr
, CoCreateInstance
);
3210 IPersist_Release(persist
);
3212 hr
= CoCreateInstance(&CLSID_WineOOPTest
, NULL
, CLSCTX_LOCAL_SERVER
, &IID_IPersist
, (void **)&persist
);
3213 ok(hr
== REGDB_E_CLASSNOTREG
, "Second CoCreateInstance on REGCLS_SINGLEUSE object should have failed\n");
3215 /* Re-register the class and try calling CoDisconnectObject from within a call to that object */
3216 repeat_event
= CreateEventA(NULL
, FALSE
, FALSE
, "Wine COM Test Repeat Event");
3217 SetEvent(repeat_event
);
3218 CloseHandle(repeat_event
);
3220 ok( !WaitForSingleObject(ready_event
, 10000), "wait timed out\n" );
3221 CloseHandle(ready_event
);
3223 hr
= CoCreateInstance(&CLSID_WineOOPTest
, NULL
, CLSCTX_LOCAL_SERVER
, &IID_IPersist
, (void **)&persist
);
3224 ok_ole_success(hr
, CoCreateInstance
);
3226 /* GetClassID will call CoDisconnectObject */
3227 IPersist_GetClassID(persist
, &clsid
);
3228 IPersist_Release(persist
);
3230 quit_event
= CreateEventA(NULL
, FALSE
, FALSE
, "Wine COM Test Quit Event");
3231 SetEvent(quit_event
);
3233 winetest_wait_child_process( process
);
3234 CloseHandle(quit_event
);
3235 CloseHandle(process
);
3241 IGlobalInterfaceTable
*git
;
3244 static DWORD CALLBACK
get_global_interface_proc(LPVOID pv
)
3247 struct git_params
*params
= pv
;
3250 hr
= IGlobalInterfaceTable_GetInterfaceFromGlobal(params
->git
, params
->cookie
, &IID_IClassFactory
, (void **)&cf
);
3251 ok(hr
== CO_E_NOTINITIALIZED
||
3252 broken(hr
== E_UNEXPECTED
) /* win2k */ ||
3253 broken(hr
== S_OK
) /* NT 4 */,
3254 "IGlobalInterfaceTable_GetInterfaceFromGlobal should have failed with error CO_E_NOTINITIALIZED or E_UNEXPECTED instead of 0x%08x\n",
3257 IClassFactory_Release(cf
);
3261 hr
= IGlobalInterfaceTable_GetInterfaceFromGlobal(params
->git
, params
->cookie
, &IID_IClassFactory
, (void **)&cf
);
3262 ok_ole_success(hr
, IGlobalInterfaceTable_GetInterfaceFromGlobal
);
3264 IClassFactory_Release(cf
);
3271 static void test_globalinterfacetable(void)
3274 IGlobalInterfaceTable
*git
;
3278 struct git_params params
;
3284 trace("test_globalinterfacetable\n");
3287 hr
= pDllGetClassObject(&CLSID_StdGlobalInterfaceTable
, &IID_IClassFactory
, (void**)&cf
);
3288 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
3290 hr
= IClassFactory_QueryInterface(cf
, &IID_IGlobalInterfaceTable
, (void**)&object
);
3291 ok(hr
== E_NOINTERFACE
, "got 0x%08x\n", hr
);
3293 IClassFactory_Release(cf
);
3295 hr
= CoCreateInstance(&CLSID_StdGlobalInterfaceTable
, NULL
, CLSCTX_INPROC_SERVER
, &IID_IGlobalInterfaceTable
, (void **)&git
);
3296 ok_ole_success(hr
, CoCreateInstance
);
3298 ref
= IGlobalInterfaceTable_AddRef(git
);
3299 ok(ref
== 1, "ref=%d\n", ref
);
3300 ref
= IGlobalInterfaceTable_AddRef(git
);
3301 ok(ref
== 1, "ref=%d\n", ref
);
3303 ref
= IGlobalInterfaceTable_Release(git
);
3304 ok(ref
== 1, "ref=%d\n", ref
);
3305 ref
= IGlobalInterfaceTable_Release(git
);
3306 ok(ref
== 1, "ref=%d\n", ref
);
3308 hr
= IGlobalInterfaceTable_RegisterInterfaceInGlobal(git
, (IUnknown
*)&Test_ClassFactory
, &IID_IClassFactory
, &cookie
);
3309 ok_ole_success(hr
, IGlobalInterfaceTable_RegisterInterfaceInGlobal
);
3311 ok_more_than_one_lock();
3313 params
.cookie
= cookie
;
3315 /* note: params is on stack so we MUST wait for get_global_interface_proc
3316 * to exit before we can return */
3317 thread
= CreateThread(NULL
, 0, get_global_interface_proc
, ¶ms
, 0, &tid
);
3319 ret
= MsgWaitForMultipleObjects(1, &thread
, FALSE
, 10000, QS_ALLINPUT
);
3320 while (ret
== WAIT_OBJECT_0
+ 1)
3323 while (PeekMessageA(&msg
, NULL
, 0, 0, PM_REMOVE
))
3324 DispatchMessageA(&msg
);
3325 ret
= MsgWaitForMultipleObjects(1, &thread
, FALSE
, 10000, QS_ALLINPUT
);
3328 CloseHandle(thread
);
3330 /* test getting interface from global with different iid */
3331 hr
= IGlobalInterfaceTable_GetInterfaceFromGlobal(git
, cookie
, &IID_IUnknown
, (void **)&object
);
3332 ok_ole_success(hr
, IGlobalInterfaceTable_GetInterfaceFromGlobal
);
3333 IUnknown_Release(object
);
3335 /* test getting interface from global with same iid */
3336 hr
= IGlobalInterfaceTable_GetInterfaceFromGlobal(git
, cookie
, &IID_IClassFactory
, (void **)&object
);
3337 ok_ole_success(hr
, IGlobalInterfaceTable_GetInterfaceFromGlobal
);
3338 IUnknown_Release(object
);
3340 hr
= IGlobalInterfaceTable_RevokeInterfaceFromGlobal(git
, cookie
);
3341 ok_ole_success(hr
, IGlobalInterfaceTable_RevokeInterfaceFromGlobal
);
3345 IGlobalInterfaceTable_Release(git
);
3348 static void test_manualresetevent(void)
3350 ISynchronizeHandle
*sync_handle
;
3351 ISynchronize
*psync1
, *psync2
;
3357 hr
= CoCreateInstance(&CLSID_ManualResetEvent
, NULL
, CLSCTX_INPROC_SERVER
, &IID_IUnknown
, (void**)&punk
);
3358 ok(hr
== S_OK
, "Got 0x%08x\n", hr
);
3359 ok(!!punk
, "Got NULL.\n");
3360 IUnknown_Release(punk
);
3362 hr
= CoCreateInstance(&CLSID_ManualResetEvent
, NULL
, CLSCTX_INPROC_SERVER
, &IID_ISynchronize
, (void**)&psync1
);
3363 ok(hr
== S_OK
, "Got 0x%08x\n", hr
);
3364 ok(!!psync1
, "Got NULL.\n");
3366 hr
= ISynchronize_Wait(psync1
, 0, 5);
3367 ok(hr
== RPC_S_CALLPENDING
, "Got 0x%08x\n", hr
);
3369 hr
= ISynchronize_Reset(psync1
);
3370 ok(hr
== S_OK
, "Got 0x%08x\n", hr
);
3371 hr
= ISynchronize_Signal(psync1
);
3372 ok(hr
== S_OK
, "Got 0x%08x\n", hr
);
3373 hr
= ISynchronize_Wait(psync1
, 0, 5);
3374 ok(hr
== S_OK
, "Got 0x%08x\n", hr
);
3375 hr
= ISynchronize_Wait(psync1
, 0, 5);
3376 ok(hr
== S_OK
, "Got 0x%08x\n", hr
);
3377 hr
= ISynchronize_Reset(psync1
);
3378 ok(hr
== S_OK
, "Got 0x%08x\n", hr
);
3379 hr
= ISynchronize_Wait(psync1
, 0, 5);
3380 ok(hr
== RPC_S_CALLPENDING
, "Got 0x%08x\n", hr
);
3382 hr
= CoCreateInstance(&CLSID_ManualResetEvent
, NULL
, CLSCTX_INPROC_SERVER
, &IID_ISynchronize
, (void**)&psync2
);
3383 ok(hr
== S_OK
, "Got 0x%08x\n", hr
);
3384 ok(!!psync2
, "Got NULL.\n");
3385 ok(psync1
!= psync2
, "psync1 == psync2.\n");
3387 hr
= ISynchronize_QueryInterface(psync2
, &IID_ISynchronizeHandle
, (void**)&sync_handle
);
3388 ok(hr
== S_OK
, "QueryInterface(IID_ISynchronizeHandle) failed: %08x\n", hr
);
3391 hr
= ISynchronizeHandle_GetHandle(sync_handle
, &handle
);
3392 ok(hr
== S_OK
, "GetHandle failed: %08x\n", hr
);
3393 ok(handle
!= NULL
&& handle
!= INVALID_HANDLE_VALUE
, "handle = %p\n", handle
);
3395 ISynchronizeHandle_Release(sync_handle
);
3397 hr
= ISynchronize_Wait(psync2
, 0, 5);
3398 ok(hr
== RPC_S_CALLPENDING
, "Got 0x%08x\n", hr
);
3400 hr
= ISynchronize_Reset(psync1
);
3401 ok(hr
== S_OK
, "Got 0x%08x\n", hr
);
3402 hr
= ISynchronize_Reset(psync2
);
3403 ok(hr
== S_OK
, "Got 0x%08x\n", hr
);
3404 hr
= ISynchronize_Signal(psync1
);
3405 ok(hr
== S_OK
, "Got 0x%08x\n", hr
);
3406 hr
= ISynchronize_Wait(psync2
, 0, 5);
3407 ok(hr
== RPC_S_CALLPENDING
, "Got 0x%08x\n", hr
);
3409 ref
= ISynchronize_AddRef(psync1
);
3410 ok(ref
== 2, "Got ref: %d\n", ref
);
3411 ref
= ISynchronize_AddRef(psync1
);
3412 ok(ref
== 3, "Got ref: %d\n", ref
);
3413 ref
= ISynchronize_Release(psync1
);
3414 ok(ref
== 2, "Got nonzero ref: %d\n", ref
);
3415 ref
= ISynchronize_Release(psync2
);
3416 ok(!ref
, "Got nonzero ref: %d\n", ref
);
3417 ref
= ISynchronize_Release(psync1
);
3418 ok(ref
== 1, "Got nonzero ref: %d\n", ref
);
3419 ref
= ISynchronize_Release(psync1
);
3420 ok(!ref
, "Got nonzero ref: %d\n", ref
);
3423 static const char *debugstr_iid(REFIID riid
)
3425 static char name
[256];
3429 LONG name_size
= sizeof(name
);
3430 StringFromGUID2(riid
, bufferW
, sizeof(bufferW
)/sizeof(bufferW
[0]));
3431 WideCharToMultiByte(CP_ACP
, 0, bufferW
, sizeof(bufferW
)/sizeof(bufferW
[0]), buffer
, sizeof(buffer
), NULL
, NULL
);
3432 if (RegOpenKeyExA(HKEY_CLASSES_ROOT
, "Interface", 0, KEY_QUERY_VALUE
, &hkeyInterface
) != ERROR_SUCCESS
)
3434 memcpy(name
, buffer
, sizeof(buffer
));
3437 if (RegQueryValueA(hkeyInterface
, buffer
, name
, &name_size
) != ERROR_SUCCESS
)
3439 memcpy(name
, buffer
, sizeof(buffer
));
3442 RegCloseKey(hkeyInterface
);
3447 static HRESULT WINAPI
TestChannelHook_QueryInterface(IChannelHook
*iface
, REFIID riid
, void **ppv
)
3449 if (IsEqualIID(riid
, &IID_IUnknown
) || IsEqualIID(riid
, &IID_IChannelHook
))
3452 IChannelHook_AddRef(iface
);
3457 return E_NOINTERFACE
;
3460 static ULONG WINAPI
TestChannelHook_AddRef(IChannelHook
*iface
)
3465 static ULONG WINAPI
TestChannelHook_Release(IChannelHook
*iface
)
3470 static void WINAPI
TestChannelHook_ClientGetSize(
3471 IChannelHook
*iface
,
3476 SChannelHookCallInfo
*info
= (SChannelHookCallInfo
*)riid
;
3477 trace("TestChannelHook_ClientGetBuffer\n");
3478 trace("\t%s method %d\n", debugstr_iid(riid
), info
->iMethod
);
3479 trace("\tcid: %s\n", debugstr_iid(&info
->uCausality
));
3480 ok(info
->cbSize
== sizeof(*info
), "info->cbSize was %d instead of %d\n", info
->cbSize
, (int)sizeof(*info
));
3481 ok(info
->dwServerPid
== GetCurrentProcessId(), "info->dwServerPid was 0x%x instead of 0x%x\n", info
->dwServerPid
, GetCurrentProcessId());
3482 ok(!info
->pObject
, "info->pObject should be NULL\n");
3483 ok(IsEqualGUID(uExtent
, &EXTENTID_WineTest
), "uExtent wasn't correct\n");
3488 static void WINAPI
TestChannelHook_ClientFillBuffer(
3489 IChannelHook
*iface
,
3495 SChannelHookCallInfo
*info
= (SChannelHookCallInfo
*)riid
;
3496 trace("TestChannelHook_ClientFillBuffer\n");
3497 ok(info
->cbSize
== sizeof(*info
), "info->cbSize was %d instead of %d\n", info
->cbSize
, (int)sizeof(*info
));
3498 ok(info
->dwServerPid
== GetCurrentProcessId(), "info->dwServerPid was 0x%x instead of 0x%x\n", info
->dwServerPid
, GetCurrentProcessId());
3499 ok(!info
->pObject
, "info->pObject should be NULL\n");
3500 ok(IsEqualGUID(uExtent
, &EXTENTID_WineTest
), "uExtent wasn't correct\n");
3502 *(unsigned char *)pDataBuffer
= 0xcc;
3506 static void WINAPI
TestChannelHook_ClientNotify(
3507 IChannelHook
*iface
,
3515 SChannelHookCallInfo
*info
= (SChannelHookCallInfo
*)riid
;
3516 trace("TestChannelHook_ClientNotify hrFault = 0x%08x\n", hrFault
);
3517 ok(info
->cbSize
== sizeof(*info
), "info->cbSize was %d instead of %d\n", info
->cbSize
, (int)sizeof(*info
));
3518 ok(info
->dwServerPid
== GetCurrentProcessId(), "info->dwServerPid was 0x%x instead of 0x%x\n", info
->dwServerPid
, GetCurrentProcessId());
3520 ok(info
->pObject
!= NULL
, "info->pObject shouldn't be NULL\n");
3522 ok(IsEqualGUID(uExtent
, &EXTENTID_WineTest
), "uExtent wasn't correct\n");
3525 static void WINAPI
TestChannelHook_ServerNotify(
3526 IChannelHook
*iface
,
3533 SChannelHookCallInfo
*info
= (SChannelHookCallInfo
*)riid
;
3534 trace("TestChannelHook_ServerNotify\n");
3535 ok(info
->cbSize
== sizeof(*info
), "info->cbSize was %d instead of %d\n", info
->cbSize
, (int)sizeof(*info
));
3536 ok(info
->dwServerPid
== GetCurrentProcessId(), "info->dwServerPid was 0x%x instead of 0x%x\n", info
->dwServerPid
, GetCurrentProcessId());
3537 ok(info
->pObject
!= NULL
, "info->pObject shouldn't be NULL\n");
3538 ok(cbDataSize
== 1, "cbDataSize should have been 1 instead of %d\n", cbDataSize
);
3539 ok(*(unsigned char *)pDataBuffer
== 0xcc, "pDataBuffer should have contained 0xcc instead of 0x%x\n", *(unsigned char *)pDataBuffer
);
3540 ok(IsEqualGUID(uExtent
, &EXTENTID_WineTest
), "uExtent wasn't correct\n");
3543 static void WINAPI
TestChannelHook_ServerGetSize(
3544 IChannelHook
*iface
,
3550 SChannelHookCallInfo
*info
= (SChannelHookCallInfo
*)riid
;
3551 trace("TestChannelHook_ServerGetSize\n");
3552 trace("\t%s method %d\n", debugstr_iid(riid
), info
->iMethod
);
3553 ok(info
->cbSize
== sizeof(*info
), "info->cbSize was %d instead of %d\n", info
->cbSize
, (int)sizeof(*info
));
3554 ok(info
->dwServerPid
== GetCurrentProcessId(), "info->dwServerPid was 0x%x instead of 0x%x\n", info
->dwServerPid
, GetCurrentProcessId());
3555 ok(info
->pObject
!= NULL
, "info->pObject shouldn't be NULL\n");
3556 ok(IsEqualGUID(uExtent
, &EXTENTID_WineTest
), "uExtent wasn't correct\n");
3557 if (hrFault
!= S_OK
)
3558 trace("\thrFault = 0x%08x\n", hrFault
);
3563 static void WINAPI
TestChannelHook_ServerFillBuffer(
3564 IChannelHook
*iface
,
3571 trace("TestChannelHook_ServerFillBuffer\n");
3572 ok(0, "TestChannelHook_ServerFillBuffer shouldn't be called\n");
3575 static const IChannelHookVtbl TestChannelHookVtbl
=
3577 TestChannelHook_QueryInterface
,
3578 TestChannelHook_AddRef
,
3579 TestChannelHook_Release
,
3580 TestChannelHook_ClientGetSize
,
3581 TestChannelHook_ClientFillBuffer
,
3582 TestChannelHook_ClientNotify
,
3583 TestChannelHook_ServerNotify
,
3584 TestChannelHook_ServerGetSize
,
3585 TestChannelHook_ServerFillBuffer
,
3588 static IChannelHook TestChannelHook
= { &TestChannelHookVtbl
};
3590 static void test_channel_hook(void)
3592 IStream
*pStream
= NULL
;
3593 IClassFactory
*cf
= NULL
;
3595 IUnknown
*proxy
= NULL
;
3599 hr
= CoRegisterChannelHook(&EXTENTID_WineTest
, &TestChannelHook
);
3600 ok_ole_success(hr
, CoRegisterChannelHook
);
3602 hr
= CoRegisterMessageFilter(&MessageFilter
, NULL
);
3603 ok_ole_success(hr
, CoRegisterMessageFilter
);
3607 hr
= CreateStreamOnHGlobal(NULL
, TRUE
, &pStream
);
3608 ok_ole_success(hr
, CreateStreamOnHGlobal
);
3609 tid
= start_host_object2(pStream
, &IID_IClassFactory
, (IUnknown
*)&Test_ClassFactory
, MSHLFLAGS_NORMAL
, &MessageFilter
, &thread
);
3611 ok_more_than_one_lock();
3613 IStream_Seek(pStream
, ullZero
, STREAM_SEEK_SET
, NULL
);
3614 hr
= CoUnmarshalInterface(pStream
, &IID_IClassFactory
, (void **)&cf
);
3615 ok_ole_success(hr
, CoUnmarshalInterface
);
3616 IStream_Release(pStream
);
3618 ok_more_than_one_lock();
3620 hr
= IClassFactory_CreateInstance(cf
, NULL
, &IID_IUnknown
, (LPVOID
*)&proxy
);
3621 ok_ole_success(hr
, IClassFactory_CreateInstance
);
3622 IUnknown_Release(proxy
);
3624 IClassFactory_Release(cf
);
3628 end_host_object(tid
, thread
);
3630 hr
= CoRegisterMessageFilter(NULL
, NULL
);
3631 ok_ole_success(hr
, CoRegisterMessageFilter
);
3636 HMODULE hOle32
= GetModuleHandleA("ole32");
3640 if (!GetProcAddress(hOle32
, "CoRegisterSurrogateEx")) {
3641 win_skip("skipping test on win9x\n");
3645 pCoInitializeEx
= (void*)GetProcAddress(hOle32
, "CoInitializeEx");
3646 pDllGetClassObject
= (void*)GetProcAddress(hOle32
, "DllGetClassObject");
3648 argc
= winetest_get_mainargs( &argv
);
3649 if (argc
> 2 && (!strcmp(argv
[2], "-Embedding")))
3651 pCoInitializeEx(NULL
, COINIT_APARTMENTTHREADED
);
3652 test_register_local_server();
3658 register_test_window();
3660 test_cocreateinstance_proxy();
3662 pCoInitializeEx(NULL
, COINIT_APARTMENTTHREADED
);
3664 /* FIXME: test CoCreateInstanceEx */
3666 /* lifecycle management and marshaling tests */
3669 test_no_marshaler();
3670 test_normal_marshal_and_release();
3671 test_normal_marshal_and_unmarshal();
3672 test_marshal_and_unmarshal_invalid();
3673 test_same_apartment_unmarshal_failure();
3674 test_interthread_marshal_and_unmarshal();
3675 test_proxy_marshal_and_unmarshal();
3676 test_proxy_marshal_and_unmarshal2();
3677 test_proxy_marshal_and_unmarshal_weak();
3678 test_proxy_marshal_and_unmarshal_strong();
3679 test_marshal_stub_apartment_shutdown();
3680 test_marshal_proxy_apartment_shutdown();
3681 test_marshal_proxy_mta_apartment_shutdown();
3682 test_no_couninitialize_server();
3683 test_no_couninitialize_client();
3684 test_tableweak_marshal_and_unmarshal_twice();
3685 test_tableweak_marshal_releasedata1();
3686 test_tableweak_marshal_releasedata2();
3687 test_tableweak_and_normal_marshal_and_unmarshal();
3688 test_tableweak_and_normal_marshal_and_releasedata();
3689 test_two_tableweak_marshal_and_releasedata();
3690 test_tablestrong_marshal_and_unmarshal_twice();
3691 test_lock_object_external();
3692 test_disconnect_stub();
3693 test_normal_marshal_and_unmarshal_twice();
3695 with_external_conn
= !with_external_conn
;
3696 } while (with_external_conn
);
3698 test_hresult_marshaling();
3699 test_proxy_used_in_wrong_thread();
3700 test_message_filter();
3701 test_bad_marshal_stream();
3702 test_proxy_interfaces();
3703 test_stubbuffer(&IID_IClassFactory
);
3704 test_proxybuffer(&IID_IClassFactory
);
3705 test_message_reentrancy();
3706 test_call_from_message();
3707 test_WM_QUIT_handling();
3708 test_freethreadedmarshaler();
3709 test_inproc_handler();
3710 test_handler_marshaling();
3711 test_client_security();
3713 test_local_server();
3715 test_globalinterfacetable();
3716 test_manualresetevent();
3717 test_crash_couninitialize();
3719 /* must be last test as channel hooks can't be unregistered */
3720 test_channel_hook();