4 * Copyright 2004 Robert Shearman
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
36 #include "wine/test.h"
38 DEFINE_GUID(CLSID_StdGlobalInterfaceTable
,0x00000323,0x0000,0x0000,0xc0,0x00,0x00,0x00,0x00,0x00,0x00,0x46);
39 DEFINE_GUID(CLSID_ManualResetEvent
, 0x0000032c,0x0000,0x0000,0xc0,0x00,0x00,0x00,0x00,0x00,0x00,0x46);
41 /* functions that are not present on all versions of Windows */
42 static HRESULT (WINAPI
* pCoInitializeEx
)(LPVOID lpReserved
, DWORD dwCoInit
);
43 static HRESULT (WINAPI
*pDllGetClassObject
)(REFCLSID
,REFIID
,LPVOID
);
45 /* helper macros to make tests a bit leaner */
46 #define ok_more_than_one_lock() ok(cLocks > 0, "Number of locks should be > 0, but actually is %d\n", cLocks)
47 #define ok_no_locks() ok(cLocks == 0, "Number of locks should be 0, but actually is %d\n", cLocks)
48 #define ok_ole_success(hr, func) ok(hr == S_OK, #func " failed with error 0x%08x\n", hr)
50 static const IID IID_IWineTest
=
55 {0xa1, 0xa2, 0x5d, 0x5a, 0x36, 0x54, 0xd3, 0xbd}
56 }; /* 5201163f-8164-4fd0-a1a2-5d5a3654d3bd */
58 static const IID IID_IRemUnknown
=
63 {0xc0,0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46}
66 #define EXTENTID_WineTest IID_IWineTest
67 #define CLSID_WineTest IID_IWineTest
69 static const CLSID CLSID_WineOOPTest
=
74 {0xa1, 0xa2, 0x5d, 0x5a, 0x36, 0x54, 0xd3, 0xbd}
75 }; /* 5201163f-8164-4fd0-a1a2-5d5a3654d3bd */
77 static void test_cocreateinstance_proxy(void)
83 pCoInitializeEx(NULL
, COINIT_MULTITHREADED
);
85 hr
= CoCreateInstance(&CLSID_ShellDesktop
, NULL
, CLSCTX_INPROC
, &IID_IUnknown
, (void **)&pProxy
);
86 ok_ole_success(hr
, CoCreateInstance
);
87 hr
= IUnknown_QueryInterface(pProxy
, &IID_IMultiQI
, (void **)&pMQI
);
88 ok(hr
== S_OK
, "created object is not a proxy, so was created in the wrong apartment\n");
90 IMultiQI_Release(pMQI
);
91 IUnknown_Release(pProxy
);
96 static const LARGE_INTEGER ullZero
;
99 static void LockModule(void)
101 InterlockedIncrement(&cLocks
);
104 static void UnlockModule(void)
106 InterlockedDecrement(&cLocks
);
110 static HRESULT WINAPI
Test_IUnknown_QueryInterface(
115 if (ppvObj
== NULL
) return E_POINTER
;
117 if (IsEqualGUID(riid
, &IID_IUnknown
))
120 IUnknown_AddRef(iface
);
125 return E_NOINTERFACE
;
128 static ULONG WINAPI
Test_IUnknown_AddRef(LPUNKNOWN iface
)
131 return 2; /* non-heap-based object */
134 static ULONG WINAPI
Test_IUnknown_Release(LPUNKNOWN iface
)
137 return 1; /* non-heap-based object */
140 static const IUnknownVtbl TestUnknown_Vtbl
=
142 Test_IUnknown_QueryInterface
,
143 Test_IUnknown_AddRef
,
144 Test_IUnknown_Release
,
147 static IUnknown Test_Unknown
= { &TestUnknown_Vtbl
};
150 static HRESULT WINAPI
Test_IClassFactory_QueryInterface(
151 LPCLASSFACTORY iface
,
155 if (ppvObj
== NULL
) return E_POINTER
;
157 if (IsEqualGUID(riid
, &IID_IUnknown
) ||
158 IsEqualGUID(riid
, &IID_IClassFactory
) ||
159 /* the only other interface Wine is currently able to marshal (for testing two proxies) */
160 IsEqualGUID(riid
, &IID_IRemUnknown
))
163 IClassFactory_AddRef(iface
);
168 return E_NOINTERFACE
;
171 static ULONG WINAPI
Test_IClassFactory_AddRef(LPCLASSFACTORY iface
)
174 return 2; /* non-heap-based object */
177 static ULONG WINAPI
Test_IClassFactory_Release(LPCLASSFACTORY iface
)
180 return 1; /* non-heap-based object */
183 static HRESULT WINAPI
Test_IClassFactory_CreateInstance(
184 LPCLASSFACTORY iface
,
189 if (pUnkOuter
) return CLASS_E_NOAGGREGATION
;
190 return IUnknown_QueryInterface((IUnknown
*)&Test_Unknown
, riid
, ppvObj
);
193 static HRESULT WINAPI
Test_IClassFactory_LockServer(
194 LPCLASSFACTORY iface
,
200 static const IClassFactoryVtbl TestClassFactory_Vtbl
=
202 Test_IClassFactory_QueryInterface
,
203 Test_IClassFactory_AddRef
,
204 Test_IClassFactory_Release
,
205 Test_IClassFactory_CreateInstance
,
206 Test_IClassFactory_LockServer
209 static IClassFactory Test_ClassFactory
= { &TestClassFactory_Vtbl
};
211 #define RELEASEMARSHALDATA WM_USER
213 struct host_object_data
218 MSHLFLAGS marshal_flags
;
219 HANDLE marshal_event
;
220 IMessageFilter
*filter
;
223 static DWORD CALLBACK
host_object_proc(LPVOID p
)
225 struct host_object_data
*data
= p
;
229 pCoInitializeEx(NULL
, COINIT_APARTMENTTHREADED
);
233 IMessageFilter
* prev_filter
= NULL
;
234 hr
= CoRegisterMessageFilter(data
->filter
, &prev_filter
);
235 if (prev_filter
) IMessageFilter_Release(prev_filter
);
236 ok_ole_success(hr
, CoRegisterMessageFilter
);
239 hr
= CoMarshalInterface(data
->stream
, &data
->iid
, data
->object
, MSHCTX_INPROC
, NULL
, data
->marshal_flags
);
240 ok_ole_success(hr
, CoMarshalInterface
);
242 /* force the message queue to be created before signaling parent thread */
243 PeekMessageA(&msg
, NULL
, WM_USER
, WM_USER
, PM_NOREMOVE
);
245 SetEvent(data
->marshal_event
);
247 while (GetMessageA(&msg
, NULL
, 0, 0))
249 if (msg
.hwnd
== NULL
&& msg
.message
== RELEASEMARSHALDATA
)
251 CoReleaseMarshalData(data
->stream
);
252 SetEvent((HANDLE
)msg
.lParam
);
255 DispatchMessageA(&msg
);
258 HeapFree(GetProcessHeap(), 0, data
);
265 static DWORD
start_host_object2(IStream
*stream
, REFIID riid
, IUnknown
*object
, MSHLFLAGS marshal_flags
, IMessageFilter
*filter
, HANDLE
*thread
)
268 HANDLE marshal_event
= CreateEventA(NULL
, FALSE
, FALSE
, NULL
);
269 struct host_object_data
*data
= HeapAlloc(GetProcessHeap(), 0, sizeof(*data
));
271 data
->stream
= stream
;
273 data
->object
= object
;
274 data
->marshal_flags
= marshal_flags
;
275 data
->marshal_event
= marshal_event
;
276 data
->filter
= filter
;
278 *thread
= CreateThread(NULL
, 0, host_object_proc
, data
, 0, &tid
);
280 /* wait for marshaling to complete before returning */
281 ok( !WaitForSingleObject(marshal_event
, 10000), "wait timed out\n" );
282 CloseHandle(marshal_event
);
287 static DWORD
start_host_object(IStream
*stream
, REFIID riid
, IUnknown
*object
, MSHLFLAGS marshal_flags
, HANDLE
*thread
)
289 return start_host_object2(stream
, riid
, object
, marshal_flags
, NULL
, thread
);
292 /* asks thread to release the marshal data because it has to be done by the
293 * same thread that marshaled the interface in the first place. */
294 static void release_host_object(DWORD tid
)
296 HANDLE event
= CreateEventA(NULL
, FALSE
, FALSE
, NULL
);
297 PostThreadMessageA(tid
, RELEASEMARSHALDATA
, 0, (LPARAM
)event
);
298 ok( !WaitForSingleObject(event
, 10000), "wait timed out\n" );
302 static void end_host_object(DWORD tid
, HANDLE thread
)
304 BOOL ret
= PostThreadMessageA(tid
, WM_QUIT
, 0, 0);
305 ok(ret
, "PostThreadMessage failed with error %d\n", GetLastError());
306 /* be careful of races - don't return until hosting thread has terminated */
307 ok( !WaitForSingleObject(thread
, 10000), "wait timed out\n" );
311 /* tests failure case of interface not having a marshaler specified in the
313 static void test_no_marshaler(void)
318 hr
= CreateStreamOnHGlobal(NULL
, TRUE
, &pStream
);
319 ok_ole_success(hr
, CreateStreamOnHGlobal
);
320 hr
= CoMarshalInterface(pStream
, &IID_IWineTest
, (IUnknown
*)&Test_ClassFactory
, MSHCTX_INPROC
, NULL
, MSHLFLAGS_NORMAL
);
321 ok(hr
== E_NOINTERFACE
, "CoMarshalInterface should have returned E_NOINTERFACE instead of 0x%08x\n", hr
);
323 IStream_Release(pStream
);
326 /* tests normal marshal and then release without unmarshaling */
327 static void test_normal_marshal_and_release(void)
330 IStream
*pStream
= NULL
;
334 hr
= CreateStreamOnHGlobal(NULL
, TRUE
, &pStream
);
335 ok_ole_success(hr
, CreateStreamOnHGlobal
);
336 hr
= CoMarshalInterface(pStream
, &IID_IClassFactory
, (IUnknown
*)&Test_ClassFactory
, MSHCTX_INPROC
, NULL
, MSHLFLAGS_NORMAL
);
337 ok_ole_success(hr
, CoMarshalInterface
);
339 ok_more_than_one_lock();
341 IStream_Seek(pStream
, ullZero
, STREAM_SEEK_SET
, NULL
);
342 hr
= CoReleaseMarshalData(pStream
);
343 ok_ole_success(hr
, CoReleaseMarshalData
);
344 IStream_Release(pStream
);
349 /* tests success case of a same-thread marshal and unmarshal */
350 static void test_normal_marshal_and_unmarshal(void)
353 IStream
*pStream
= NULL
;
354 IUnknown
*pProxy
= NULL
;
358 hr
= CreateStreamOnHGlobal(NULL
, TRUE
, &pStream
);
359 ok_ole_success(hr
, CreateStreamOnHGlobal
);
360 hr
= CoMarshalInterface(pStream
, &IID_IClassFactory
, (IUnknown
*)&Test_ClassFactory
, MSHCTX_INPROC
, NULL
, MSHLFLAGS_NORMAL
);
361 ok_ole_success(hr
, CoMarshalInterface
);
363 ok_more_than_one_lock();
365 IStream_Seek(pStream
, ullZero
, STREAM_SEEK_SET
, NULL
);
366 hr
= CoUnmarshalInterface(pStream
, &IID_IClassFactory
, (void **)&pProxy
);
367 ok_ole_success(hr
, CoUnmarshalInterface
);
368 IStream_Release(pStream
);
370 ok_more_than_one_lock();
372 IUnknown_Release(pProxy
);
377 /* tests failure case of unmarshaling a freed object */
378 static void test_marshal_and_unmarshal_invalid(void)
381 IStream
*pStream
= NULL
;
382 IClassFactory
*pProxy
= NULL
;
389 hr
= CreateStreamOnHGlobal(NULL
, TRUE
, &pStream
);
390 ok_ole_success(hr
, CreateStreamOnHGlobal
);
391 tid
= start_host_object(pStream
, &IID_IClassFactory
, (IUnknown
*)&Test_ClassFactory
, MSHLFLAGS_NORMAL
, &thread
);
393 ok_more_than_one_lock();
395 IStream_Seek(pStream
, ullZero
, STREAM_SEEK_SET
, NULL
);
396 hr
= CoReleaseMarshalData(pStream
);
397 ok_ole_success(hr
, CoReleaseMarshalData
);
401 IStream_Seek(pStream
, ullZero
, STREAM_SEEK_SET
, NULL
);
402 hr
= CoUnmarshalInterface(pStream
, &IID_IClassFactory
, (void **)&pProxy
);
403 todo_wine
{ ok_ole_success(hr
, CoUnmarshalInterface
); }
409 hr
= IClassFactory_CreateInstance(pProxy
, NULL
, &IID_IUnknown
, &dummy
);
410 ok(hr
== RPC_E_DISCONNECTED
, "Remote call should have returned RPC_E_DISCONNECTED, instead of 0x%08x\n", hr
);
412 IClassFactory_Release(pProxy
);
415 IStream_Release(pStream
);
417 end_host_object(tid
, thread
);
420 static void test_same_apartment_unmarshal_failure(void)
425 static const LARGE_INTEGER llZero
;
429 hr
= CreateStreamOnHGlobal(NULL
, TRUE
, &pStream
);
430 ok_ole_success(hr
, CreateStreamOnHGlobal
);
432 hr
= CoMarshalInterface(pStream
, &IID_IUnknown
, (IUnknown
*)&Test_ClassFactory
, MSHCTX_INPROC
, NULL
, MSHLFLAGS_NORMAL
);
433 ok_ole_success(hr
, CoMarshalInterface
);
435 ok_more_than_one_lock();
437 hr
= IStream_Seek(pStream
, llZero
, STREAM_SEEK_SET
, NULL
);
438 ok_ole_success(hr
, IStream_Seek
);
440 hr
= CoUnmarshalInterface(pStream
, &IID_IParseDisplayName
, (void **)&pProxy
);
441 ok(hr
== E_NOINTERFACE
, "CoUnmarshalInterface should have returned E_NOINTERFACE instead of 0x%08x\n", hr
);
445 IStream_Release(pStream
);
448 /* tests success case of an interthread marshal */
449 static void test_interthread_marshal_and_unmarshal(void)
452 IStream
*pStream
= NULL
;
453 IUnknown
*pProxy
= NULL
;
459 hr
= CreateStreamOnHGlobal(NULL
, TRUE
, &pStream
);
460 ok_ole_success(hr
, CreateStreamOnHGlobal
);
461 tid
= start_host_object(pStream
, &IID_IClassFactory
, (IUnknown
*)&Test_ClassFactory
, MSHLFLAGS_NORMAL
, &thread
);
463 ok_more_than_one_lock();
465 IStream_Seek(pStream
, ullZero
, STREAM_SEEK_SET
, NULL
);
466 hr
= CoUnmarshalInterface(pStream
, &IID_IClassFactory
, (void **)&pProxy
);
467 ok_ole_success(hr
, CoUnmarshalInterface
);
468 IStream_Release(pStream
);
470 ok_more_than_one_lock();
472 IUnknown_Release(pProxy
);
476 end_host_object(tid
, thread
);
479 /* the number of external references that Wine's proxy manager normally gives
480 * out, so we can test the border case of running out of references */
481 #define NORMALEXTREFS 5
483 /* tests success case of an interthread marshal and then marshaling the proxy */
484 static void test_proxy_marshal_and_unmarshal(void)
487 IStream
*pStream
= NULL
;
488 IUnknown
*pProxy
= NULL
;
489 IUnknown
*pProxy2
= NULL
;
496 hr
= CreateStreamOnHGlobal(NULL
, TRUE
, &pStream
);
497 ok_ole_success(hr
, CreateStreamOnHGlobal
);
498 tid
= start_host_object(pStream
, &IID_IClassFactory
, (IUnknown
*)&Test_ClassFactory
, MSHLFLAGS_NORMAL
, &thread
);
500 ok_more_than_one_lock();
502 IStream_Seek(pStream
, ullZero
, STREAM_SEEK_SET
, NULL
);
503 hr
= CoUnmarshalInterface(pStream
, &IID_IClassFactory
, (void **)&pProxy
);
504 ok_ole_success(hr
, CoUnmarshalInterface
);
506 ok_more_than_one_lock();
508 IStream_Seek(pStream
, ullZero
, STREAM_SEEK_SET
, NULL
);
509 /* marshal the proxy */
510 hr
= CoMarshalInterface(pStream
, &IID_IClassFactory
, pProxy
, MSHCTX_INPROC
, NULL
, MSHLFLAGS_NORMAL
);
511 ok_ole_success(hr
, CoMarshalInterface
);
513 ok_more_than_one_lock();
515 /* marshal 5 more times to exhaust the normal external references of 5 */
516 for (i
= 0; i
< NORMALEXTREFS
; i
++)
518 hr
= CoMarshalInterface(pStream
, &IID_IClassFactory
, pProxy
, MSHCTX_INPROC
, NULL
, MSHLFLAGS_NORMAL
);
519 ok_ole_success(hr
, CoMarshalInterface
);
522 ok_more_than_one_lock();
524 /* release the original proxy to test that we successfully keep the
525 * original object alive */
526 IUnknown_Release(pProxy
);
528 IStream_Seek(pStream
, ullZero
, STREAM_SEEK_SET
, NULL
);
529 hr
= CoUnmarshalInterface(pStream
, &IID_IClassFactory
, (void **)&pProxy2
);
530 ok_ole_success(hr
, CoUnmarshalInterface
);
532 ok_more_than_one_lock();
534 IUnknown_Release(pProxy2
);
536 /* unmarshal all of the proxies to check that the object stub still exists */
537 for (i
= 0; i
< NORMALEXTREFS
; i
++)
539 hr
= CoUnmarshalInterface(pStream
, &IID_IClassFactory
, (void **)&pProxy2
);
540 ok_ole_success(hr
, CoUnmarshalInterface
);
542 IUnknown_Release(pProxy2
);
547 IStream_Release(pStream
);
549 end_host_object(tid
, thread
);
552 /* tests success case of an interthread marshal and then marshaling the proxy
553 * using an iid that hasn't previously been unmarshaled */
554 static void test_proxy_marshal_and_unmarshal2(void)
557 IStream
*pStream
= NULL
;
558 IUnknown
*pProxy
= NULL
;
559 IUnknown
*pProxy2
= NULL
;
565 hr
= CreateStreamOnHGlobal(NULL
, TRUE
, &pStream
);
566 ok_ole_success(hr
, CreateStreamOnHGlobal
);
567 tid
= start_host_object(pStream
, &IID_IUnknown
, (IUnknown
*)&Test_ClassFactory
, MSHLFLAGS_NORMAL
, &thread
);
569 ok_more_than_one_lock();
571 IStream_Seek(pStream
, ullZero
, STREAM_SEEK_SET
, NULL
);
572 hr
= CoUnmarshalInterface(pStream
, &IID_IUnknown
, (void **)&pProxy
);
573 ok_ole_success(hr
, CoUnmarshalInterface
);
575 ok_more_than_one_lock();
577 IStream_Seek(pStream
, ullZero
, STREAM_SEEK_SET
, NULL
);
578 /* marshal the proxy */
579 hr
= CoMarshalInterface(pStream
, &IID_IClassFactory
, pProxy
, MSHCTX_INPROC
, NULL
, MSHLFLAGS_NORMAL
);
580 ok_ole_success(hr
, CoMarshalInterface
);
582 ok_more_than_one_lock();
584 IStream_Seek(pStream
, ullZero
, STREAM_SEEK_SET
, NULL
);
585 /* unmarshal the second proxy to the object */
586 hr
= CoUnmarshalInterface(pStream
, &IID_IClassFactory
, (void **)&pProxy2
);
587 ok_ole_success(hr
, CoUnmarshalInterface
);
588 IStream_Release(pStream
);
590 /* now the proxies should be as follows:
591 * pProxy -> &Test_ClassFactory
592 * pProxy2 -> &Test_ClassFactory
593 * they should NOT be as follows:
594 * pProxy -> &Test_ClassFactory
596 * the above can only really be tested by looking in +ole traces
599 ok_more_than_one_lock();
601 IUnknown_Release(pProxy
);
603 ok_more_than_one_lock();
605 IUnknown_Release(pProxy2
);
609 end_host_object(tid
, thread
);
612 /* tests success case of an interthread marshal and then table-weak-marshaling the proxy */
613 static void test_proxy_marshal_and_unmarshal_weak(void)
616 IStream
*pStream
= NULL
;
617 IUnknown
*pProxy
= NULL
;
618 IUnknown
*pProxy2
= NULL
;
624 hr
= CreateStreamOnHGlobal(NULL
, TRUE
, &pStream
);
625 ok_ole_success(hr
, CreateStreamOnHGlobal
);
626 tid
= start_host_object(pStream
, &IID_IClassFactory
, (IUnknown
*)&Test_ClassFactory
, MSHLFLAGS_NORMAL
, &thread
);
628 ok_more_than_one_lock();
630 IStream_Seek(pStream
, ullZero
, STREAM_SEEK_SET
, NULL
);
631 hr
= CoUnmarshalInterface(pStream
, &IID_IClassFactory
, (void **)&pProxy
);
632 ok_ole_success(hr
, CoUnmarshalInterface
);
634 ok_more_than_one_lock();
636 IStream_Seek(pStream
, ullZero
, STREAM_SEEK_SET
, NULL
);
637 /* marshal the proxy */
638 hr
= CoMarshalInterface(pStream
, &IID_IClassFactory
, pProxy
, MSHCTX_INPROC
, NULL
, MSHLFLAGS_TABLEWEAK
);
639 ok_ole_success(hr
, CoMarshalInterface
);
641 ok_more_than_one_lock();
643 /* release the original proxy to test that we successfully keep the
644 * original object alive */
645 IUnknown_Release(pProxy
);
647 IStream_Seek(pStream
, ullZero
, STREAM_SEEK_SET
, NULL
);
648 hr
= CoUnmarshalInterface(pStream
, &IID_IClassFactory
, (void **)&pProxy2
);
650 ok(hr
== CO_E_OBJNOTREG
, "CoUnmarshalInterface should return CO_E_OBJNOTREG instead of 0x%08x\n", hr
);
654 IStream_Release(pStream
);
656 end_host_object(tid
, thread
);
659 /* tests success case of an interthread marshal and then table-strong-marshaling the proxy */
660 static void test_proxy_marshal_and_unmarshal_strong(void)
663 IStream
*pStream
= NULL
;
664 IUnknown
*pProxy
= NULL
;
665 IUnknown
*pProxy2
= NULL
;
671 hr
= CreateStreamOnHGlobal(NULL
, TRUE
, &pStream
);
672 ok_ole_success(hr
, CreateStreamOnHGlobal
);
673 tid
= start_host_object(pStream
, &IID_IClassFactory
, (IUnknown
*)&Test_ClassFactory
, MSHLFLAGS_NORMAL
, &thread
);
675 ok_more_than_one_lock();
677 IStream_Seek(pStream
, ullZero
, STREAM_SEEK_SET
, NULL
);
678 hr
= CoUnmarshalInterface(pStream
, &IID_IClassFactory
, (void **)&pProxy
);
679 ok_ole_success(hr
, CoUnmarshalInterface
);
681 ok_more_than_one_lock();
683 IStream_Seek(pStream
, ullZero
, STREAM_SEEK_SET
, NULL
);
684 /* marshal the proxy */
685 hr
= CoMarshalInterface(pStream
, &IID_IClassFactory
, pProxy
, MSHCTX_INPROC
, NULL
, MSHLFLAGS_TABLESTRONG
);
686 ok(hr
== S_OK
/* WinNT */ || hr
== E_INVALIDARG
/* Win9x */,
687 "CoMarshalInterface should have return S_OK or E_INVALIDARG instead of 0x%08x\n", hr
);
690 IUnknown_Release(pProxy
);
694 ok_more_than_one_lock();
696 /* release the original proxy to test that we successfully keep the
697 * original object alive */
698 IUnknown_Release(pProxy
);
700 IStream_Seek(pStream
, ullZero
, STREAM_SEEK_SET
, NULL
);
701 hr
= CoUnmarshalInterface(pStream
, &IID_IClassFactory
, (void **)&pProxy2
);
702 ok_ole_success(hr
, CoUnmarshalInterface
);
704 ok_more_than_one_lock();
706 IUnknown_Release(pProxy2
);
708 ok_more_than_one_lock();
711 IStream_Release(pStream
);
713 end_host_object(tid
, thread
);
718 /* tests that stubs are released when the containing apartment is destroyed */
719 static void test_marshal_stub_apartment_shutdown(void)
722 IStream
*pStream
= NULL
;
723 IUnknown
*pProxy
= NULL
;
729 hr
= CreateStreamOnHGlobal(NULL
, TRUE
, &pStream
);
730 ok_ole_success(hr
, CreateStreamOnHGlobal
);
731 tid
= start_host_object(pStream
, &IID_IClassFactory
, (IUnknown
*)&Test_ClassFactory
, MSHLFLAGS_NORMAL
, &thread
);
733 ok_more_than_one_lock();
735 IStream_Seek(pStream
, ullZero
, STREAM_SEEK_SET
, NULL
);
736 hr
= CoUnmarshalInterface(pStream
, &IID_IClassFactory
, (void **)&pProxy
);
737 ok_ole_success(hr
, CoUnmarshalInterface
);
738 IStream_Release(pStream
);
740 ok_more_than_one_lock();
742 end_host_object(tid
, thread
);
746 IUnknown_Release(pProxy
);
751 /* tests that proxies are released when the containing apartment is destroyed */
752 static void test_marshal_proxy_apartment_shutdown(void)
755 IStream
*pStream
= NULL
;
756 IUnknown
*pProxy
= NULL
;
762 hr
= CreateStreamOnHGlobal(NULL
, TRUE
, &pStream
);
763 ok_ole_success(hr
, CreateStreamOnHGlobal
);
764 tid
= start_host_object(pStream
, &IID_IClassFactory
, (IUnknown
*)&Test_ClassFactory
, MSHLFLAGS_NORMAL
, &thread
);
766 ok_more_than_one_lock();
768 IStream_Seek(pStream
, ullZero
, STREAM_SEEK_SET
, NULL
);
769 hr
= CoUnmarshalInterface(pStream
, &IID_IClassFactory
, (void **)&pProxy
);
770 ok_ole_success(hr
, CoUnmarshalInterface
);
771 IStream_Release(pStream
);
773 ok_more_than_one_lock();
779 IUnknown_Release(pProxy
);
783 end_host_object(tid
, thread
);
785 pCoInitializeEx(NULL
, COINIT_APARTMENTTHREADED
);
788 /* tests that proxies are released when the containing mta apartment is destroyed */
789 static void test_marshal_proxy_mta_apartment_shutdown(void)
792 IStream
*pStream
= NULL
;
793 IUnknown
*pProxy
= NULL
;
798 pCoInitializeEx(NULL
, COINIT_MULTITHREADED
);
802 hr
= CreateStreamOnHGlobal(NULL
, TRUE
, &pStream
);
803 ok_ole_success(hr
, CreateStreamOnHGlobal
);
804 tid
= start_host_object(pStream
, &IID_IClassFactory
, (IUnknown
*)&Test_ClassFactory
, MSHLFLAGS_NORMAL
, &thread
);
806 ok_more_than_one_lock();
808 IStream_Seek(pStream
, ullZero
, STREAM_SEEK_SET
, NULL
);
809 hr
= CoUnmarshalInterface(pStream
, &IID_IClassFactory
, (void **)&pProxy
);
810 ok_ole_success(hr
, CoUnmarshalInterface
);
811 IStream_Release(pStream
);
813 ok_more_than_one_lock();
819 IUnknown_Release(pProxy
);
823 end_host_object(tid
, thread
);
825 pCoInitializeEx(NULL
, COINIT_APARTMENTTHREADED
);
831 HANDLE marshal_event
;
832 HANDLE unmarshal_event
;
835 /* helper for test_no_couninitialize_server */
836 static DWORD CALLBACK
no_couninitialize_server_proc(LPVOID p
)
838 struct ncu_params
*ncu_params
= p
;
841 pCoInitializeEx(NULL
, COINIT_MULTITHREADED
);
843 hr
= CoMarshalInterface(ncu_params
->stream
, &IID_IClassFactory
, (IUnknown
*)&Test_ClassFactory
, MSHCTX_INPROC
, NULL
, MSHLFLAGS_NORMAL
);
844 ok_ole_success(hr
, CoMarshalInterface
);
846 SetEvent(ncu_params
->marshal_event
);
848 ok( !WaitForSingleObject(ncu_params
->unmarshal_event
, 10000), "wait timed out\n" );
850 /* die without calling CoUninitialize */
855 /* tests apartment that an apartment with a stub is released without deadlock
856 * if the owning thread exits */
857 static void test_no_couninitialize_server(void)
860 IStream
*pStream
= NULL
;
861 IUnknown
*pProxy
= NULL
;
864 struct ncu_params ncu_params
;
868 ncu_params
.marshal_event
= CreateEventA(NULL
, TRUE
, FALSE
, NULL
);
869 ncu_params
.unmarshal_event
= CreateEventA(NULL
, TRUE
, FALSE
, NULL
);
871 hr
= CreateStreamOnHGlobal(NULL
, TRUE
, &pStream
);
872 ok_ole_success(hr
, CreateStreamOnHGlobal
);
873 ncu_params
.stream
= pStream
;
875 thread
= CreateThread(NULL
, 0, no_couninitialize_server_proc
, &ncu_params
, 0, &tid
);
877 ok( !WaitForSingleObject(ncu_params
.marshal_event
, 10000), "wait timed out\n" );
878 ok_more_than_one_lock();
880 IStream_Seek(pStream
, ullZero
, STREAM_SEEK_SET
, NULL
);
881 hr
= CoUnmarshalInterface(pStream
, &IID_IClassFactory
, (void **)&pProxy
);
882 ok_ole_success(hr
, CoUnmarshalInterface
);
883 IStream_Release(pStream
);
885 ok_more_than_one_lock();
887 SetEvent(ncu_params
.unmarshal_event
);
888 ok( !WaitForSingleObject(thread
, 10000), "wait timed out\n" );
893 CloseHandle(ncu_params
.marshal_event
);
894 CloseHandle(ncu_params
.unmarshal_event
);
896 IUnknown_Release(pProxy
);
901 /* STA -> STA call during DLL_THREAD_DETACH */
902 static DWORD CALLBACK
no_couninitialize_client_proc(LPVOID p
)
904 struct ncu_params
*ncu_params
= p
;
906 IUnknown
*pProxy
= NULL
;
908 pCoInitializeEx(NULL
, COINIT_APARTMENTTHREADED
);
910 hr
= CoUnmarshalInterface(ncu_params
->stream
, &IID_IClassFactory
, (void **)&pProxy
);
911 ok_ole_success(hr
, CoUnmarshalInterface
);
912 IStream_Release(ncu_params
->stream
);
914 ok_more_than_one_lock();
916 /* die without calling CoUninitialize */
921 /* tests STA -> STA call during DLL_THREAD_DETACH doesn't deadlock */
922 static void test_no_couninitialize_client(void)
925 IStream
*pStream
= NULL
;
930 struct ncu_params ncu_params
;
934 hr
= CreateStreamOnHGlobal(NULL
, TRUE
, &pStream
);
935 ok_ole_success(hr
, CreateStreamOnHGlobal
);
936 ncu_params
.stream
= pStream
;
938 /* NOTE: assumes start_host_object uses an STA to host the object, as MTAs
939 * always deadlock when called from within DllMain */
940 host_tid
= start_host_object(pStream
, &IID_IClassFactory
, (IUnknown
*)&Test_ClassFactory
, MSHLFLAGS_NORMAL
, &host_thread
);
941 IStream_Seek(pStream
, ullZero
, STREAM_SEEK_SET
, NULL
);
943 ok_more_than_one_lock();
945 thread
= CreateThread(NULL
, 0, no_couninitialize_client_proc
, &ncu_params
, 0, &tid
);
947 ok( !WaitForSingleObject(thread
, 10000), "wait timed out\n" );
952 end_host_object(host_tid
, host_thread
);
955 /* tests success case of a same-thread table-weak marshal, unmarshal, unmarshal */
956 static void test_tableweak_marshal_and_unmarshal_twice(void)
959 IStream
*pStream
= NULL
;
960 IUnknown
*pProxy1
= NULL
;
961 IUnknown
*pProxy2
= NULL
;
967 hr
= CreateStreamOnHGlobal(NULL
, TRUE
, &pStream
);
968 ok_ole_success(hr
, CreateStreamOnHGlobal
);
969 tid
= start_host_object(pStream
, &IID_IClassFactory
, (IUnknown
*)&Test_ClassFactory
, MSHLFLAGS_TABLEWEAK
, &thread
);
971 ok_more_than_one_lock();
973 IStream_Seek(pStream
, ullZero
, STREAM_SEEK_SET
, NULL
);
974 hr
= CoUnmarshalInterface(pStream
, &IID_IClassFactory
, (void **)&pProxy1
);
975 ok_ole_success(hr
, CoUnmarshalInterface
);
977 ok_more_than_one_lock();
979 IStream_Seek(pStream
, ullZero
, STREAM_SEEK_SET
, NULL
);
980 hr
= CoUnmarshalInterface(pStream
, &IID_IClassFactory
, (void **)&pProxy2
);
981 IStream_Release(pStream
);
982 ok_ole_success(hr
, CoUnmarshalInterface
);
984 ok_more_than_one_lock();
986 IUnknown_Release(pProxy1
);
987 IUnknown_Release(pProxy2
);
989 /* this line is shows the difference between weak and strong table marshaling:
990 * weak has cLocks == 0
991 * strong has cLocks > 0 */
994 end_host_object(tid
, thread
);
997 /* tests releasing after unmarshaling one object */
998 static void test_tableweak_marshal_releasedata1(void)
1001 IStream
*pStream
= NULL
;
1002 IUnknown
*pProxy1
= NULL
;
1003 IUnknown
*pProxy2
= NULL
;
1009 hr
= CreateStreamOnHGlobal(NULL
, TRUE
, &pStream
);
1010 ok_ole_success(hr
, CreateStreamOnHGlobal
);
1011 tid
= start_host_object(pStream
, &IID_IClassFactory
, (IUnknown
*)&Test_ClassFactory
, MSHLFLAGS_TABLEWEAK
, &thread
);
1013 ok_more_than_one_lock();
1015 IStream_Seek(pStream
, ullZero
, STREAM_SEEK_SET
, NULL
);
1016 hr
= CoUnmarshalInterface(pStream
, &IID_IClassFactory
, (void **)&pProxy1
);
1017 ok_ole_success(hr
, CoUnmarshalInterface
);
1019 ok_more_than_one_lock();
1021 /* release the remaining reference on the object by calling
1022 * CoReleaseMarshalData in the hosting thread */
1023 IStream_Seek(pStream
, ullZero
, STREAM_SEEK_SET
, NULL
);
1024 release_host_object(tid
);
1026 ok_more_than_one_lock();
1028 IStream_Seek(pStream
, ullZero
, STREAM_SEEK_SET
, NULL
);
1029 hr
= CoUnmarshalInterface(pStream
, &IID_IClassFactory
, (void **)&pProxy2
);
1030 ok_ole_success(hr
, CoUnmarshalInterface
);
1031 IStream_Release(pStream
);
1033 ok_more_than_one_lock();
1035 IUnknown_Release(pProxy1
);
1037 IUnknown_Release(pProxy2
);
1039 /* this line is shows the difference between weak and strong table marshaling:
1040 * weak has cLocks == 0
1041 * strong has cLocks > 0 */
1044 end_host_object(tid
, thread
);
1047 /* tests releasing after unmarshaling one object */
1048 static void test_tableweak_marshal_releasedata2(void)
1051 IStream
*pStream
= NULL
;
1052 IUnknown
*pProxy
= NULL
;
1058 hr
= CreateStreamOnHGlobal(NULL
, TRUE
, &pStream
);
1059 ok_ole_success(hr
, CreateStreamOnHGlobal
);
1060 tid
= start_host_object(pStream
, &IID_IClassFactory
, (IUnknown
*)&Test_ClassFactory
, MSHLFLAGS_TABLEWEAK
, &thread
);
1062 ok_more_than_one_lock();
1064 /* release the remaining reference on the object by calling
1065 * CoReleaseMarshalData in the hosting thread */
1066 IStream_Seek(pStream
, ullZero
, STREAM_SEEK_SET
, NULL
);
1067 release_host_object(tid
);
1071 IStream_Seek(pStream
, ullZero
, STREAM_SEEK_SET
, NULL
);
1072 hr
= CoUnmarshalInterface(pStream
, &IID_IClassFactory
, (void **)&pProxy
);
1075 ok(hr
== CO_E_OBJNOTREG
,
1076 "CoUnmarshalInterface should have failed with CO_E_OBJNOTREG, but returned 0x%08x instead\n",
1079 IStream_Release(pStream
);
1083 end_host_object(tid
, thread
);
1086 struct weak_and_normal_marshal_data
1088 IStream
*pStreamWeak
;
1089 IStream
*pStreamNormal
;
1094 static DWORD CALLBACK
weak_and_normal_marshal_thread_proc(void *p
)
1097 struct weak_and_normal_marshal_data
*data
= p
;
1098 HANDLE hQuitEvent
= data
->hQuitEvent
;
1101 pCoInitializeEx(NULL
, COINIT_APARTMENTTHREADED
);
1103 hr
= CoMarshalInterface(data
->pStreamWeak
, &IID_IClassFactory
, (IUnknown
*)&Test_ClassFactory
, MSHCTX_INPROC
, NULL
, MSHLFLAGS_TABLEWEAK
);
1104 ok_ole_success(hr
, "CoMarshalInterface");
1106 hr
= CoMarshalInterface(data
->pStreamNormal
, &IID_IClassFactory
, (IUnknown
*)&Test_ClassFactory
, MSHCTX_INPROC
, NULL
, MSHLFLAGS_NORMAL
);
1107 ok_ole_success(hr
, "CoMarshalInterface");
1109 /* force the message queue to be created before signaling parent thread */
1110 PeekMessageA(&msg
, NULL
, WM_USER
, WM_USER
, PM_NOREMOVE
);
1112 SetEvent(data
->hReadyEvent
);
1114 while (WAIT_OBJECT_0
+ 1 == MsgWaitForMultipleObjects(1, &hQuitEvent
, FALSE
, 10000, QS_ALLINPUT
))
1116 while (PeekMessageA(&msg
, NULL
, 0, 0, PM_REMOVE
))
1117 DispatchMessageA(&msg
);
1119 CloseHandle(hQuitEvent
);
1126 /* tests interaction between table-weak and normal marshalling of an object */
1127 static void test_tableweak_and_normal_marshal_and_unmarshal(void)
1130 IUnknown
*pProxyWeak
= NULL
;
1131 IUnknown
*pProxyNormal
= NULL
;
1134 struct weak_and_normal_marshal_data data
;
1138 data
.hReadyEvent
= CreateEventA(NULL
, FALSE
, FALSE
, NULL
);
1139 data
.hQuitEvent
= CreateEventA(NULL
, FALSE
, FALSE
, NULL
);
1140 hr
= CreateStreamOnHGlobal(NULL
, TRUE
, &data
.pStreamWeak
);
1141 ok_ole_success(hr
, CreateStreamOnHGlobal
);
1142 hr
= CreateStreamOnHGlobal(NULL
, TRUE
, &data
.pStreamNormal
);
1143 ok_ole_success(hr
, CreateStreamOnHGlobal
);
1145 thread
= CreateThread(NULL
, 0, weak_and_normal_marshal_thread_proc
, &data
, 0, &tid
);
1146 ok( !WaitForSingleObject(data
.hReadyEvent
, 10000), "wait timed out\n" );
1147 CloseHandle(data
.hReadyEvent
);
1149 ok_more_than_one_lock();
1151 IStream_Seek(data
.pStreamWeak
, ullZero
, STREAM_SEEK_SET
, NULL
);
1152 hr
= CoUnmarshalInterface(data
.pStreamWeak
, &IID_IClassFactory
, (void **)&pProxyWeak
);
1153 ok_ole_success(hr
, CoUnmarshalInterface
);
1155 ok_more_than_one_lock();
1157 IStream_Seek(data
.pStreamNormal
, ullZero
, STREAM_SEEK_SET
, NULL
);
1158 hr
= CoUnmarshalInterface(data
.pStreamNormal
, &IID_IClassFactory
, (void **)&pProxyNormal
);
1159 ok_ole_success(hr
, CoUnmarshalInterface
);
1161 ok_more_than_one_lock();
1163 IUnknown_Release(pProxyNormal
);
1165 ok_more_than_one_lock();
1167 IUnknown_Release(pProxyWeak
);
1171 IStream_Release(data
.pStreamWeak
);
1172 IStream_Release(data
.pStreamNormal
);
1174 SetEvent(data
.hQuitEvent
);
1175 ok( !WaitForSingleObject(thread
, 10000), "wait timed out\n" );
1176 CloseHandle(thread
);
1179 /* tests success case of a same-thread table-strong marshal, unmarshal, unmarshal */
1180 static void test_tablestrong_marshal_and_unmarshal_twice(void)
1183 IStream
*pStream
= NULL
;
1184 IUnknown
*pProxy1
= NULL
;
1185 IUnknown
*pProxy2
= NULL
;
1191 hr
= CreateStreamOnHGlobal(NULL
, TRUE
, &pStream
);
1192 ok_ole_success(hr
, CreateStreamOnHGlobal
);
1193 tid
= start_host_object(pStream
, &IID_IClassFactory
, (IUnknown
*)&Test_ClassFactory
, MSHLFLAGS_TABLESTRONG
, &thread
);
1195 ok_more_than_one_lock();
1197 IStream_Seek(pStream
, ullZero
, STREAM_SEEK_SET
, NULL
);
1198 hr
= CoUnmarshalInterface(pStream
, &IID_IClassFactory
, (void **)&pProxy1
);
1199 ok_ole_success(hr
, CoUnmarshalInterface
);
1201 ok_more_than_one_lock();
1203 IStream_Seek(pStream
, ullZero
, STREAM_SEEK_SET
, NULL
);
1204 hr
= CoUnmarshalInterface(pStream
, &IID_IClassFactory
, (void **)&pProxy2
);
1205 ok_ole_success(hr
, CoUnmarshalInterface
);
1207 ok_more_than_one_lock();
1209 if (pProxy1
) IUnknown_Release(pProxy1
);
1210 if (pProxy2
) IUnknown_Release(pProxy2
);
1212 /* this line is shows the difference between weak and strong table marshaling:
1213 * weak has cLocks == 0
1214 * strong has cLocks > 0 */
1215 ok_more_than_one_lock();
1217 /* release the remaining reference on the object by calling
1218 * CoReleaseMarshalData in the hosting thread */
1219 IStream_Seek(pStream
, ullZero
, STREAM_SEEK_SET
, NULL
);
1220 release_host_object(tid
);
1221 IStream_Release(pStream
);
1225 end_host_object(tid
, thread
);
1228 /* tests CoLockObjectExternal */
1229 static void test_lock_object_external(void)
1232 IStream
*pStream
= NULL
;
1236 /* test the stub manager creation aspect of CoLockObjectExternal when the
1237 * object hasn't been marshaled yet */
1238 CoLockObjectExternal((IUnknown
*)&Test_ClassFactory
, TRUE
, TRUE
);
1240 ok_more_than_one_lock();
1242 CoDisconnectObject((IUnknown
*)&Test_ClassFactory
, 0);
1246 /* test our empty stub manager being handled correctly in
1247 * CoMarshalInterface */
1248 CoLockObjectExternal((IUnknown
*)&Test_ClassFactory
, TRUE
, TRUE
);
1250 hr
= CreateStreamOnHGlobal(NULL
, TRUE
, &pStream
);
1251 ok_ole_success(hr
, CreateStreamOnHGlobal
);
1252 hr
= CoMarshalInterface(pStream
, &IID_IClassFactory
, (IUnknown
*)&Test_ClassFactory
, MSHCTX_INPROC
, NULL
, MSHLFLAGS_NORMAL
);
1253 ok_ole_success(hr
, CoMarshalInterface
);
1255 CoLockObjectExternal((IUnknown
*)&Test_ClassFactory
, TRUE
, TRUE
);
1257 ok_more_than_one_lock();
1259 IStream_Seek(pStream
, ullZero
, STREAM_SEEK_SET
, NULL
);
1260 hr
= CoReleaseMarshalData(pStream
);
1261 ok_ole_success(hr
, CoReleaseMarshalData
);
1262 IStream_Seek(pStream
, ullZero
, STREAM_SEEK_SET
, NULL
);
1264 ok_more_than_one_lock();
1266 CoLockObjectExternal((IUnknown
*)&Test_ClassFactory
, FALSE
, TRUE
);
1268 ok_more_than_one_lock();
1270 CoLockObjectExternal((IUnknown
*)&Test_ClassFactory
, FALSE
, TRUE
);
1274 /* test CoLockObjectExternal releases reference to object with
1275 * fLastUnlockReleases as TRUE and there are only strong references on
1277 CoLockObjectExternal((IUnknown
*)&Test_ClassFactory
, TRUE
, FALSE
);
1279 ok_more_than_one_lock();
1281 CoLockObjectExternal((IUnknown
*)&Test_ClassFactory
, FALSE
, FALSE
);
1285 /* test CoLockObjectExternal doesn't release the last reference to an
1286 * object with fLastUnlockReleases as TRUE and there is a weak reference
1288 hr
= CoMarshalInterface(pStream
, &IID_IClassFactory
, (IUnknown
*)&Test_ClassFactory
, MSHCTX_INPROC
, NULL
, MSHLFLAGS_TABLEWEAK
);
1289 ok_ole_success(hr
, CoMarshalInterface
);
1291 ok_more_than_one_lock();
1293 CoLockObjectExternal((IUnknown
*)&Test_ClassFactory
, TRUE
, FALSE
);
1295 ok_more_than_one_lock();
1297 CoLockObjectExternal((IUnknown
*)&Test_ClassFactory
, FALSE
, FALSE
);
1299 ok_more_than_one_lock();
1301 CoDisconnectObject((IUnknown
*)&Test_ClassFactory
, 0);
1305 IStream_Release(pStream
);
1308 /* tests disconnecting stubs */
1309 static void test_disconnect_stub(void)
1312 IStream
*pStream
= NULL
;
1316 hr
= CreateStreamOnHGlobal(NULL
, TRUE
, &pStream
);
1317 ok_ole_success(hr
, CreateStreamOnHGlobal
);
1318 hr
= CoMarshalInterface(pStream
, &IID_IClassFactory
, (IUnknown
*)&Test_ClassFactory
, MSHCTX_INPROC
, NULL
, MSHLFLAGS_NORMAL
);
1319 ok_ole_success(hr
, CoMarshalInterface
);
1321 CoLockObjectExternal((IUnknown
*)&Test_ClassFactory
, TRUE
, TRUE
);
1323 ok_more_than_one_lock();
1325 IStream_Seek(pStream
, ullZero
, STREAM_SEEK_SET
, NULL
);
1326 hr
= CoReleaseMarshalData(pStream
);
1327 ok_ole_success(hr
, CoReleaseMarshalData
);
1328 IStream_Release(pStream
);
1330 ok_more_than_one_lock();
1332 CoDisconnectObject((IUnknown
*)&Test_ClassFactory
, 0);
1336 hr
= CoDisconnectObject(NULL
, 0);
1337 ok( hr
== E_INVALIDARG
, "wrong status %x\n", hr
);
1340 /* tests failure case of a same-thread marshal and unmarshal twice */
1341 static void test_normal_marshal_and_unmarshal_twice(void)
1344 IStream
*pStream
= NULL
;
1345 IUnknown
*pProxy1
= NULL
;
1346 IUnknown
*pProxy2
= NULL
;
1350 hr
= CreateStreamOnHGlobal(NULL
, TRUE
, &pStream
);
1351 ok_ole_success(hr
, CreateStreamOnHGlobal
);
1352 hr
= CoMarshalInterface(pStream
, &IID_IClassFactory
, (IUnknown
*)&Test_ClassFactory
, MSHCTX_INPROC
, NULL
, MSHLFLAGS_NORMAL
);
1353 ok_ole_success(hr
, CoMarshalInterface
);
1355 ok_more_than_one_lock();
1357 IStream_Seek(pStream
, ullZero
, STREAM_SEEK_SET
, NULL
);
1358 hr
= CoUnmarshalInterface(pStream
, &IID_IClassFactory
, (void **)&pProxy1
);
1359 ok_ole_success(hr
, CoUnmarshalInterface
);
1361 ok_more_than_one_lock();
1363 IStream_Seek(pStream
, ullZero
, STREAM_SEEK_SET
, NULL
);
1364 hr
= CoUnmarshalInterface(pStream
, &IID_IClassFactory
, (void **)&pProxy2
);
1365 ok(hr
== CO_E_OBJNOTCONNECTED
,
1366 "CoUnmarshalInterface should have failed with error CO_E_OBJNOTCONNECTED for double unmarshal, instead of 0x%08x\n", hr
);
1368 IStream_Release(pStream
);
1370 ok_more_than_one_lock();
1372 IUnknown_Release(pProxy1
);
1377 /* tests success case of marshaling and unmarshaling an HRESULT */
1378 static void test_hresult_marshaling(void)
1381 HRESULT hr_marshaled
= 0;
1382 IStream
*pStream
= NULL
;
1383 static const HRESULT E_DEADBEEF
= 0xdeadbeef;
1385 hr
= CreateStreamOnHGlobal(NULL
, TRUE
, &pStream
);
1386 ok_ole_success(hr
, CreateStreamOnHGlobal
);
1388 hr
= CoMarshalHresult(pStream
, E_DEADBEEF
);
1389 ok_ole_success(hr
, CoMarshalHresult
);
1391 IStream_Seek(pStream
, ullZero
, STREAM_SEEK_SET
, NULL
);
1392 hr
= IStream_Read(pStream
, &hr_marshaled
, sizeof(HRESULT
), NULL
);
1393 ok_ole_success(hr
, IStream_Read
);
1395 ok(hr_marshaled
== E_DEADBEEF
, "Didn't marshal HRESULT as expected: got value 0x%08x instead\n", hr_marshaled
);
1398 IStream_Seek(pStream
, ullZero
, STREAM_SEEK_SET
, NULL
);
1399 hr
= CoUnmarshalHresult(pStream
, &hr_marshaled
);
1400 ok_ole_success(hr
, CoUnmarshalHresult
);
1402 ok(hr_marshaled
== E_DEADBEEF
, "Didn't marshal HRESULT as expected: got value 0x%08x instead\n", hr_marshaled
);
1404 IStream_Release(pStream
);
1408 /* helper for test_proxy_used_in_wrong_thread */
1409 static DWORD CALLBACK
bad_thread_proc(LPVOID p
)
1411 IClassFactory
* cf
= p
;
1413 IUnknown
* proxy
= NULL
;
1415 hr
= IClassFactory_CreateInstance(cf
, NULL
, &IID_IUnknown
, (LPVOID
*)&proxy
);
1417 ok(hr
== CO_E_NOTINITIALIZED
,
1418 "COM should have failed with CO_E_NOTINITIALIZED on using proxy without apartment, but instead returned 0x%08x\n",
1421 hr
= IClassFactory_QueryInterface(cf
, &IID_IMultiQI
, (LPVOID
*)&proxy
);
1422 /* Win9x returns S_OK, whilst NT returns RPC_E_WRONG_THREAD */
1423 trace("call to proxy's QueryInterface for local interface without apartment returned 0x%08x\n", hr
);
1425 IUnknown_Release(proxy
);
1427 hr
= IClassFactory_QueryInterface(cf
, &IID_IStream
, (LPVOID
*)&proxy
);
1428 /* Win9x returns E_NOINTERFACE, whilst NT returns RPC_E_WRONG_THREAD */
1429 trace("call to proxy's QueryInterface without apartment returned 0x%08x\n", hr
);
1431 IUnknown_Release(proxy
);
1433 pCoInitializeEx(NULL
, COINIT_MULTITHREADED
);
1435 hr
= IClassFactory_CreateInstance(cf
, NULL
, &IID_IUnknown
, (LPVOID
*)&proxy
);
1436 if (proxy
) IUnknown_Release(proxy
);
1437 ok(hr
== RPC_E_WRONG_THREAD
,
1438 "COM should have failed with RPC_E_WRONG_THREAD on using proxy from wrong apartment, but instead returned 0x%08x\n",
1441 hr
= IClassFactory_QueryInterface(cf
, &IID_IStream
, (LPVOID
*)&proxy
);
1442 /* Win9x returns E_NOINTERFACE, whilst NT returns RPC_E_WRONG_THREAD */
1443 trace("call to proxy's QueryInterface from wrong apartment returned 0x%08x\n", hr
);
1445 /* now be really bad and release the proxy from the wrong apartment */
1446 IClassFactory_Release(cf
);
1453 /* tests failure case of a using a proxy in the wrong apartment */
1454 static void test_proxy_used_in_wrong_thread(void)
1457 IStream
*pStream
= NULL
;
1458 IUnknown
*pProxy
= NULL
;
1465 hr
= CreateStreamOnHGlobal(NULL
, TRUE
, &pStream
);
1466 ok_ole_success(hr
, CreateStreamOnHGlobal
);
1467 tid
= start_host_object(pStream
, &IID_IClassFactory
, (IUnknown
*)&Test_ClassFactory
, MSHLFLAGS_NORMAL
, &host_thread
);
1469 ok_more_than_one_lock();
1471 IStream_Seek(pStream
, ullZero
, STREAM_SEEK_SET
, NULL
);
1472 hr
= CoUnmarshalInterface(pStream
, &IID_IClassFactory
, (void **)&pProxy
);
1473 ok_ole_success(hr
, CoUnmarshalInterface
);
1474 IStream_Release(pStream
);
1476 ok_more_than_one_lock();
1478 /* do a call that will fail, but result in IRemUnknown being used by the proxy */
1479 IUnknown_QueryInterface(pProxy
, &IID_IStream
, (LPVOID
*)&pStream
);
1481 /* create a thread that we can misbehave in */
1482 thread
= CreateThread(NULL
, 0, bad_thread_proc
, pProxy
, 0, &tid2
);
1484 ok( !WaitForSingleObject(thread
, 10000), "wait timed out\n" );
1485 CloseHandle(thread
);
1487 /* do release statement on Win9x that we should have done above */
1488 if (!GetProcAddress(GetModuleHandleA("ole32"), "CoRegisterSurrogateEx"))
1489 IUnknown_Release(pProxy
);
1493 end_host_object(tid
, host_thread
);
1496 static HRESULT WINAPI
MessageFilter_QueryInterface(IMessageFilter
*iface
, REFIID riid
, void ** ppvObj
)
1498 if (ppvObj
== NULL
) return E_POINTER
;
1500 if (IsEqualGUID(riid
, &IID_IUnknown
) ||
1501 IsEqualGUID(riid
, &IID_IClassFactory
))
1504 IMessageFilter_AddRef(iface
);
1508 return E_NOINTERFACE
;
1511 static ULONG WINAPI
MessageFilter_AddRef(IMessageFilter
*iface
)
1513 return 2; /* non-heap object */
1516 static ULONG WINAPI
MessageFilter_Release(IMessageFilter
*iface
)
1518 return 1; /* non-heap object */
1521 static DWORD WINAPI
MessageFilter_HandleInComingCall(
1522 IMessageFilter
*iface
,
1524 HTASK threadIDCaller
,
1526 LPINTERFACEINFO lpInterfaceInfo
)
1528 static int callcount
= 0;
1530 trace("HandleInComingCall\n");
1534 ret
= SERVERCALL_REJECTED
;
1537 ret
= SERVERCALL_RETRYLATER
;
1540 ret
= SERVERCALL_ISHANDLED
;
1547 static DWORD WINAPI
MessageFilter_RetryRejectedCall(
1548 IMessageFilter
*iface
,
1549 HTASK threadIDCallee
,
1553 trace("RetryRejectedCall\n");
1557 static DWORD WINAPI
MessageFilter_MessagePending(
1558 IMessageFilter
*iface
,
1559 HTASK threadIDCallee
,
1561 DWORD dwPendingType
)
1563 trace("MessagePending\n");
1564 return PENDINGMSG_WAITNOPROCESS
;
1567 static const IMessageFilterVtbl MessageFilter_Vtbl
=
1569 MessageFilter_QueryInterface
,
1570 MessageFilter_AddRef
,
1571 MessageFilter_Release
,
1572 MessageFilter_HandleInComingCall
,
1573 MessageFilter_RetryRejectedCall
,
1574 MessageFilter_MessagePending
1577 static IMessageFilter MessageFilter
= { &MessageFilter_Vtbl
};
1579 static void test_message_filter(void)
1582 IStream
*pStream
= NULL
;
1583 IClassFactory
*cf
= NULL
;
1585 IUnknown
*proxy
= NULL
;
1586 IMessageFilter
*prev_filter
= NULL
;
1591 hr
= CreateStreamOnHGlobal(NULL
, TRUE
, &pStream
);
1592 ok_ole_success(hr
, CreateStreamOnHGlobal
);
1593 tid
= start_host_object2(pStream
, &IID_IClassFactory
, (IUnknown
*)&Test_ClassFactory
, MSHLFLAGS_NORMAL
, &MessageFilter
, &thread
);
1595 ok_more_than_one_lock();
1597 IStream_Seek(pStream
, ullZero
, STREAM_SEEK_SET
, NULL
);
1598 hr
= CoUnmarshalInterface(pStream
, &IID_IClassFactory
, (void **)&cf
);
1599 ok_ole_success(hr
, CoUnmarshalInterface
);
1600 IStream_Release(pStream
);
1602 ok_more_than_one_lock();
1604 hr
= IClassFactory_CreateInstance(cf
, NULL
, &IID_IUnknown
, (LPVOID
*)&proxy
);
1605 ok(hr
== RPC_E_CALL_REJECTED
, "Call should have returned RPC_E_CALL_REJECTED, but return 0x%08x instead\n", hr
);
1606 if (proxy
) IUnknown_Release(proxy
);
1609 hr
= CoRegisterMessageFilter(&MessageFilter
, &prev_filter
);
1610 ok_ole_success(hr
, CoRegisterMessageFilter
);
1612 hr
= IClassFactory_CreateInstance(cf
, NULL
, &IID_IUnknown
, (LPVOID
*)&proxy
);
1613 ok_ole_success(hr
, IClassFactory_CreateInstance
);
1615 IUnknown_Release(proxy
);
1617 IClassFactory_Release(cf
);
1621 end_host_object(tid
, thread
);
1623 hr
= CoRegisterMessageFilter(prev_filter
, NULL
);
1624 ok_ole_success(hr
, CoRegisterMessageFilter
);
1627 /* test failure case of trying to unmarshal from bad stream */
1628 static void test_bad_marshal_stream(void)
1631 IStream
*pStream
= NULL
;
1633 hr
= CreateStreamOnHGlobal(NULL
, TRUE
, &pStream
);
1634 ok_ole_success(hr
, CreateStreamOnHGlobal
);
1635 hr
= CoMarshalInterface(pStream
, &IID_IClassFactory
, (IUnknown
*)&Test_ClassFactory
, MSHCTX_INPROC
, NULL
, MSHLFLAGS_NORMAL
);
1636 ok_ole_success(hr
, CoMarshalInterface
);
1638 ok_more_than_one_lock();
1640 /* try to read beyond end of stream */
1641 hr
= CoReleaseMarshalData(pStream
);
1642 ok(hr
== STG_E_READFAULT
, "Should have failed with STG_E_READFAULT, but returned 0x%08x instead\n", hr
);
1644 /* now release for real */
1645 IStream_Seek(pStream
, ullZero
, STREAM_SEEK_SET
, NULL
);
1646 hr
= CoReleaseMarshalData(pStream
);
1647 ok_ole_success(hr
, CoReleaseMarshalData
);
1649 IStream_Release(pStream
);
1652 /* tests that proxies implement certain interfaces */
1653 static void test_proxy_interfaces(void)
1656 IStream
*pStream
= NULL
;
1657 IUnknown
*pProxy
= NULL
;
1658 IUnknown
*pOtherUnknown
= NULL
;
1664 hr
= CreateStreamOnHGlobal(NULL
, TRUE
, &pStream
);
1665 ok_ole_success(hr
, CreateStreamOnHGlobal
);
1666 tid
= start_host_object(pStream
, &IID_IClassFactory
, (IUnknown
*)&Test_ClassFactory
, MSHLFLAGS_NORMAL
, &thread
);
1668 ok_more_than_one_lock();
1670 IStream_Seek(pStream
, ullZero
, STREAM_SEEK_SET
, NULL
);
1671 hr
= CoUnmarshalInterface(pStream
, &IID_IUnknown
, (void **)&pProxy
);
1672 ok_ole_success(hr
, CoUnmarshalInterface
);
1673 IStream_Release(pStream
);
1675 ok_more_than_one_lock();
1677 hr
= IUnknown_QueryInterface(pProxy
, &IID_IUnknown
, (LPVOID
*)&pOtherUnknown
);
1678 ok_ole_success(hr
, IUnknown_QueryInterface IID_IUnknown
);
1679 if (hr
== S_OK
) IUnknown_Release(pOtherUnknown
);
1681 hr
= IUnknown_QueryInterface(pProxy
, &IID_IClientSecurity
, (LPVOID
*)&pOtherUnknown
);
1682 ok_ole_success(hr
, IUnknown_QueryInterface IID_IClientSecurity
);
1683 if (hr
== S_OK
) IUnknown_Release(pOtherUnknown
);
1685 hr
= IUnknown_QueryInterface(pProxy
, &IID_IMultiQI
, (LPVOID
*)&pOtherUnknown
);
1686 ok_ole_success(hr
, IUnknown_QueryInterface IID_IMultiQI
);
1687 if (hr
== S_OK
) IUnknown_Release(pOtherUnknown
);
1689 hr
= IUnknown_QueryInterface(pProxy
, &IID_IMarshal
, (LPVOID
*)&pOtherUnknown
);
1690 ok_ole_success(hr
, IUnknown_QueryInterface IID_IMarshal
);
1691 if (hr
== S_OK
) IUnknown_Release(pOtherUnknown
);
1693 /* IMarshal2 is also supported on NT-based systems, but is pretty much
1694 * useless as it has no more methods over IMarshal that it inherits from. */
1696 IUnknown_Release(pProxy
);
1700 end_host_object(tid
, thread
);
1705 IUnknown IUnknown_iface
;
1709 static inline HeapUnknown
*impl_from_IUnknown(IUnknown
*iface
)
1711 return CONTAINING_RECORD(iface
, HeapUnknown
, IUnknown_iface
);
1714 static HRESULT WINAPI
HeapUnknown_QueryInterface(IUnknown
*iface
, REFIID riid
, void **ppv
)
1716 if (IsEqualIID(riid
, &IID_IUnknown
))
1718 IUnknown_AddRef(iface
);
1723 return E_NOINTERFACE
;
1726 static ULONG WINAPI
HeapUnknown_AddRef(IUnknown
*iface
)
1728 HeapUnknown
*This
= impl_from_IUnknown(iface
);
1729 return InterlockedIncrement((LONG
*)&This
->refs
);
1732 static ULONG WINAPI
HeapUnknown_Release(IUnknown
*iface
)
1734 HeapUnknown
*This
= impl_from_IUnknown(iface
);
1735 ULONG refs
= InterlockedDecrement((LONG
*)&This
->refs
);
1736 if (!refs
) HeapFree(GetProcessHeap(), 0, This
);
1740 static const IUnknownVtbl HeapUnknown_Vtbl
=
1742 HeapUnknown_QueryInterface
,
1747 static void test_proxybuffer(REFIID riid
)
1750 IPSFactoryBuffer
*psfb
;
1751 IRpcProxyBuffer
*proxy
;
1755 HeapUnknown
*pUnkOuter
= HeapAlloc(GetProcessHeap(), 0, sizeof(*pUnkOuter
));
1757 pUnkOuter
->IUnknown_iface
.lpVtbl
= &HeapUnknown_Vtbl
;
1758 pUnkOuter
->refs
= 1;
1760 hr
= CoGetPSClsid(riid
, &clsid
);
1761 ok_ole_success(hr
, CoGetPSClsid
);
1763 hr
= CoGetClassObject(&clsid
, CLSCTX_INPROC_SERVER
, NULL
, &IID_IPSFactoryBuffer
, (LPVOID
*)&psfb
);
1764 ok_ole_success(hr
, CoGetClassObject
);
1766 hr
= IPSFactoryBuffer_CreateProxy(psfb
, &pUnkOuter
->IUnknown_iface
, riid
, &proxy
, &lpvtbl
);
1767 ok_ole_success(hr
, IPSFactoryBuffer_CreateProxy
);
1768 ok(lpvtbl
!= NULL
, "IPSFactoryBuffer_CreateProxy succeeded, but returned a NULL vtable!\n");
1770 /* release our reference to the outer unknown object - the PS factory
1771 * buffer will have AddRef's it in the CreateProxy call */
1772 refs
= IUnknown_Release(&pUnkOuter
->IUnknown_iface
);
1773 ok(refs
== 1, "Ref count of outer unknown should have been 1 instead of %d\n", refs
);
1775 /* Not checking return, unreliable on native. Maybe it leaks references? */
1776 IPSFactoryBuffer_Release(psfb
);
1778 refs
= IUnknown_Release((IUnknown
*)lpvtbl
);
1779 ok(refs
== 0, "Ref-count leak of %d on IRpcProxyBuffer\n", refs
);
1781 refs
= IRpcProxyBuffer_Release(proxy
);
1782 ok(refs
== 0, "Ref-count leak of %d on IRpcProxyBuffer\n", refs
);
1785 static void test_stubbuffer(REFIID riid
)
1788 IPSFactoryBuffer
*psfb
;
1789 IRpcStubBuffer
*stub
;
1795 hr
= CoGetPSClsid(riid
, &clsid
);
1796 ok_ole_success(hr
, CoGetPSClsid
);
1798 hr
= CoGetClassObject(&clsid
, CLSCTX_INPROC_SERVER
, NULL
, &IID_IPSFactoryBuffer
, (LPVOID
*)&psfb
);
1799 ok_ole_success(hr
, CoGetClassObject
);
1801 hr
= IPSFactoryBuffer_CreateStub(psfb
, riid
, (IUnknown
*)&Test_ClassFactory
, &stub
);
1802 ok_ole_success(hr
, IPSFactoryBuffer_CreateStub
);
1804 /* Not checking return, unreliable on native. Maybe it leaks references? */
1805 IPSFactoryBuffer_Release(psfb
);
1807 ok_more_than_one_lock();
1809 IRpcStubBuffer_Disconnect(stub
);
1813 refs
= IRpcStubBuffer_Release(stub
);
1814 ok(refs
== 0, "Ref-count leak of %d on IRpcProxyBuffer\n", refs
);
1817 static HWND hwnd_app
;
1819 static HRESULT WINAPI
TestRE_IClassFactory_CreateInstance(
1820 LPCLASSFACTORY iface
,
1821 LPUNKNOWN pUnkOuter
,
1826 if (IsEqualIID(riid
, &IID_IWineTest
))
1828 BOOL ret
= SendMessageTimeoutA(hwnd_app
, WM_NULL
, 0, 0, SMTO_BLOCK
, 5000, &res
);
1829 ok(ret
, "Timed out sending a message to originating window during RPC call\n");
1835 static const IClassFactoryVtbl TestREClassFactory_Vtbl
=
1837 Test_IClassFactory_QueryInterface
,
1838 Test_IClassFactory_AddRef
,
1839 Test_IClassFactory_Release
,
1840 TestRE_IClassFactory_CreateInstance
,
1841 Test_IClassFactory_LockServer
1844 static IClassFactory TestRE_ClassFactory
= { &TestREClassFactory_Vtbl
};
1846 static LRESULT CALLBACK
window_proc(HWND hwnd
, UINT msg
, WPARAM wparam
, LPARAM lparam
)
1853 IStream
*pStream
= NULL
;
1854 IClassFactory
*proxy
= NULL
;
1861 hr
= CreateStreamOnHGlobal(NULL
, TRUE
, &pStream
);
1862 ok_ole_success(hr
, CreateStreamOnHGlobal
);
1863 tid
= start_host_object(pStream
, &IID_IClassFactory
, (IUnknown
*)&TestRE_ClassFactory
, MSHLFLAGS_NORMAL
, &thread
);
1865 ok_more_than_one_lock();
1867 IStream_Seek(pStream
, ullZero
, STREAM_SEEK_SET
, NULL
);
1868 hr
= CoUnmarshalInterface(pStream
, &IID_IClassFactory
, (void **)&proxy
);
1869 ok_ole_success(hr
, CoReleaseMarshalData
);
1870 IStream_Release(pStream
);
1872 ok_more_than_one_lock();
1874 /* note the use of the magic IID_IWineTest value to tell remote thread
1875 * to try to send a message back to us */
1876 hr
= IClassFactory_CreateInstance(proxy
, NULL
, &IID_IWineTest
, (void **)&object
);
1877 ok(hr
== S_FALSE
, "expected S_FALSE, got %d\n", hr
);
1879 IClassFactory_Release(proxy
);
1883 end_host_object(tid
, thread
);
1885 PostMessageA(hwnd
, WM_QUIT
, 0, 0);
1892 IStream
*pStream
= NULL
;
1893 IClassFactory
*proxy
= NULL
;
1900 hr
= CreateStreamOnHGlobal(NULL
, TRUE
, &pStream
);
1901 ok_ole_success(hr
, CreateStreamOnHGlobal
);
1902 tid
= start_host_object(pStream
, &IID_IClassFactory
, (IUnknown
*)&TestRE_ClassFactory
, MSHLFLAGS_NORMAL
, &thread
);
1904 ok_more_than_one_lock();
1906 IStream_Seek(pStream
, ullZero
, STREAM_SEEK_SET
, NULL
);
1907 hr
= CoUnmarshalInterface(pStream
, &IID_IClassFactory
, (void **)&proxy
);
1908 ok_ole_success(hr
, CoReleaseMarshalData
);
1909 IStream_Release(pStream
);
1911 ok_more_than_one_lock();
1913 /* post quit message before a doing a COM call to show that a pending
1914 * WM_QUIT message doesn't stop the call from succeeding */
1915 PostMessageA(hwnd
, WM_QUIT
, 0, 0);
1916 hr
= IClassFactory_CreateInstance(proxy
, NULL
, &IID_IUnknown
, (void **)&object
);
1917 ok(hr
== S_FALSE
, "IClassFactory_CreateInstance returned 0x%08x, expected S_FALSE\n", hr
);
1919 IClassFactory_Release(proxy
);
1923 end_host_object(tid
, thread
);
1930 IStream
*pStream
= NULL
;
1931 IClassFactory
*proxy
= NULL
;
1936 hr
= CreateStreamOnHGlobal(NULL
, TRUE
, &pStream
);
1937 ok_ole_success(hr
, CreateStreamOnHGlobal
);
1938 tid
= start_host_object(pStream
, &IID_IClassFactory
, (IUnknown
*)&Test_ClassFactory
, MSHLFLAGS_NORMAL
, &thread
);
1940 IStream_Seek(pStream
, ullZero
, STREAM_SEEK_SET
, NULL
);
1941 hr
= CoUnmarshalInterface(pStream
, &IID_IClassFactory
, (void **)&proxy
);
1942 ok_ole_success(hr
, CoReleaseMarshalData
);
1943 IStream_Release(pStream
);
1945 /* shows that COM calls executed during the processing of sent
1946 * messages should fail */
1947 hr
= IClassFactory_CreateInstance(proxy
, NULL
, &IID_IUnknown
, (void **)&object
);
1948 ok(hr
== RPC_E_CANTCALLOUT_ININPUTSYNCCALL
,
1949 "COM call during processing of sent message should return RPC_E_CANTCALLOUT_ININPUTSYNCCALL instead of 0x%08x\n", hr
);
1951 IClassFactory_Release(proxy
);
1953 end_host_object(tid
, thread
);
1960 return DefWindowProcA(hwnd
, msg
, wparam
, lparam
);
1964 static void register_test_window(void)
1968 memset(&wndclass
, 0, sizeof(wndclass
));
1969 wndclass
.lpfnWndProc
= window_proc
;
1970 wndclass
.lpszClassName
= "WineCOMTest";
1971 RegisterClassA(&wndclass
);
1974 static void test_message_reentrancy(void)
1978 hwnd_app
= CreateWindowA("WineCOMTest", NULL
, 0, CW_USEDEFAULT
, CW_USEDEFAULT
, CW_USEDEFAULT
, CW_USEDEFAULT
, NULL
, NULL
, NULL
, 0);
1979 ok(hwnd_app
!= NULL
, "Window creation failed\n");
1981 /* start message re-entrancy test */
1982 PostMessageA(hwnd_app
, WM_USER
, 0, 0);
1984 while (GetMessageA(&msg
, NULL
, 0, 0))
1986 TranslateMessage(&msg
);
1987 DispatchMessageA(&msg
);
1989 DestroyWindow(hwnd_app
);
1992 static HRESULT WINAPI
TestMsg_IClassFactory_CreateInstance(
1993 LPCLASSFACTORY iface
,
1994 LPUNKNOWN pUnkOuter
,
1999 SendMessageA(hwnd_app
, WM_USER
+2, 0, 0);
2003 static IClassFactoryVtbl TestMsgClassFactory_Vtbl
=
2005 Test_IClassFactory_QueryInterface
,
2006 Test_IClassFactory_AddRef
,
2007 Test_IClassFactory_Release
,
2008 TestMsg_IClassFactory_CreateInstance
,
2009 Test_IClassFactory_LockServer
2012 static IClassFactory TestMsg_ClassFactory
= { &TestMsgClassFactory_Vtbl
};
2014 static void test_call_from_message(void)
2019 IClassFactory
*proxy
;
2024 hwnd_app
= CreateWindowA("WineCOMTest", NULL
, 0, CW_USEDEFAULT
, CW_USEDEFAULT
, CW_USEDEFAULT
, CW_USEDEFAULT
, NULL
, NULL
, NULL
, 0);
2025 ok(hwnd_app
!= NULL
, "Window creation failed\n");
2027 hr
= CreateStreamOnHGlobal(NULL
, TRUE
, &pStream
);
2028 ok_ole_success(hr
, CreateStreamOnHGlobal
);
2029 tid
= start_host_object(pStream
, &IID_IClassFactory
, (IUnknown
*)&TestMsg_ClassFactory
, MSHLFLAGS_NORMAL
, &thread
);
2031 ok_more_than_one_lock();
2033 IStream_Seek(pStream
, ullZero
, STREAM_SEEK_SET
, NULL
);
2034 hr
= CoUnmarshalInterface(pStream
, &IID_IClassFactory
, (void **)&proxy
);
2035 ok_ole_success(hr
, CoReleaseMarshalData
);
2036 IStream_Release(pStream
);
2038 ok_more_than_one_lock();
2040 /* start message re-entrancy test */
2041 hr
= IClassFactory_CreateInstance(proxy
, NULL
, &IID_IUnknown
, (void **)&object
);
2042 ok_ole_success(hr
, IClassFactory_CreateInstance
);
2044 IClassFactory_Release(proxy
);
2048 end_host_object(tid
, thread
);
2050 while (GetMessageA(&msg
, NULL
, 0, 0))
2052 TranslateMessage(&msg
);
2053 DispatchMessageA(&msg
);
2055 DestroyWindow(hwnd_app
);
2058 static void test_WM_QUIT_handling(void)
2062 hwnd_app
= CreateWindowA("WineCOMTest", NULL
, 0, CW_USEDEFAULT
, CW_USEDEFAULT
, CW_USEDEFAULT
, CW_USEDEFAULT
, NULL
, NULL
, NULL
, 0);
2063 ok(hwnd_app
!= NULL
, "Window creation failed\n");
2065 /* start WM_QUIT handling test */
2066 PostMessageA(hwnd_app
, WM_USER
+1, 0, 0);
2068 while (GetMessageA(&msg
, NULL
, 0, 0))
2070 TranslateMessage(&msg
);
2071 DispatchMessageA(&msg
);
2075 static SIZE_T
round_global_size(SIZE_T size
)
2077 static SIZE_T global_size_alignment
= -1;
2078 if (global_size_alignment
== -1)
2080 void *p
= GlobalAlloc(GMEM_FIXED
, 1);
2081 global_size_alignment
= GlobalSize(p
);
2085 return ((size
+ global_size_alignment
- 1) & ~(global_size_alignment
- 1));
2088 static void test_freethreadedmarshaldata(IStream
*pStream
, MSHCTX mshctx
, void *ptr
, DWORD mshlflags
)
2095 hr
= GetHGlobalFromStream(pStream
, &hglobal
);
2096 ok_ole_success(hr
, GetHGlobalFromStream
);
2098 size
= GlobalSize(hglobal
);
2100 marshal_data
= GlobalLock(hglobal
);
2102 if (mshctx
== MSHCTX_INPROC
)
2104 DWORD expected_size
= round_global_size(3*sizeof(DWORD
) + sizeof(GUID
));
2105 ok(size
== expected_size
||
2106 broken(size
== (2*sizeof(DWORD
))) /* Win9x & NT4 */,
2107 "size should have been %d instead of %d\n", expected_size
, size
);
2109 ok(*(DWORD
*)marshal_data
== mshlflags
, "expected 0x%x, but got 0x%x for mshctx\n", mshlflags
, *(DWORD
*)marshal_data
);
2110 marshal_data
+= sizeof(DWORD
);
2111 ok(*(void **)marshal_data
== ptr
, "expected %p, but got %p for mshctx\n", ptr
, *(void **)marshal_data
);
2112 marshal_data
+= sizeof(void *);
2113 if (sizeof(void*) == 4 && size
>= 3*sizeof(DWORD
))
2115 ok(*(DWORD
*)marshal_data
== 0, "expected 0x0, but got 0x%x\n", *(DWORD
*)marshal_data
);
2116 marshal_data
+= sizeof(DWORD
);
2118 if (size
>= 3*sizeof(DWORD
) + sizeof(GUID
))
2120 trace("got guid data: {%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x}\n",
2121 ((GUID
*)marshal_data
)->Data1
, ((GUID
*)marshal_data
)->Data2
, ((GUID
*)marshal_data
)->Data3
,
2122 ((GUID
*)marshal_data
)->Data4
[0], ((GUID
*)marshal_data
)->Data4
[1], ((GUID
*)marshal_data
)->Data4
[2], ((GUID
*)marshal_data
)->Data4
[3],
2123 ((GUID
*)marshal_data
)->Data4
[4], ((GUID
*)marshal_data
)->Data4
[5], ((GUID
*)marshal_data
)->Data4
[6], ((GUID
*)marshal_data
)->Data4
[7]);
2128 ok(size
> sizeof(DWORD
), "size should have been > sizeof(DWORD), not %d\n", size
);
2129 ok(*(DWORD
*)marshal_data
== 0x574f454d /* MEOW */,
2130 "marshal data should be filled by standard marshal and start with MEOW signature\n");
2133 GlobalUnlock(hglobal
);
2136 static void test_freethreadedmarshaler(void)
2139 IUnknown
*pFTUnknown
;
2140 IMarshal
*pFTMarshal
;
2143 static const LARGE_INTEGER llZero
;
2146 hr
= CoCreateFreeThreadedMarshaler(NULL
, &pFTUnknown
);
2147 ok_ole_success(hr
, CoCreateFreeThreadedMarshaler
);
2148 hr
= IUnknown_QueryInterface(pFTUnknown
, &IID_IMarshal
, (void **)&pFTMarshal
);
2149 ok_ole_success(hr
, IUnknown_QueryInterface
);
2150 IUnknown_Release(pFTUnknown
);
2152 hr
= CreateStreamOnHGlobal(NULL
, TRUE
, &pStream
);
2153 ok_ole_success(hr
, CreateStreamOnHGlobal
);
2155 /* inproc normal marshaling */
2157 hr
= IMarshal_MarshalInterface(pFTMarshal
, pStream
, &IID_IClassFactory
,
2158 &Test_ClassFactory
, MSHCTX_INPROC
, NULL
, MSHLFLAGS_NORMAL
);
2159 ok_ole_success(hr
, IMarshal_MarshalInterface
);
2161 ok_more_than_one_lock();
2163 test_freethreadedmarshaldata(pStream
, MSHCTX_INPROC
, &Test_ClassFactory
, MSHLFLAGS_NORMAL
);
2165 IStream_Seek(pStream
, llZero
, STREAM_SEEK_SET
, NULL
);
2166 hr
= IMarshal_UnmarshalInterface(pFTMarshal
, pStream
, &IID_IUnknown
, (void **)&pProxy
);
2167 ok_ole_success(hr
, IMarshal_UnmarshalInterface
);
2169 IUnknown_Release(pProxy
);
2173 /* native doesn't allow us to unmarshal or release the stream data,
2174 * presumably because it wants us to call CoMarshalInterface instead */
2177 /* local normal marshaling */
2179 IStream_Seek(pStream
, llZero
, STREAM_SEEK_SET
, NULL
);
2180 hr
= IMarshal_MarshalInterface(pFTMarshal
, pStream
, &IID_IClassFactory
, &Test_ClassFactory
, MSHCTX_LOCAL
, NULL
, MSHLFLAGS_NORMAL
);
2181 ok_ole_success(hr
, IMarshal_MarshalInterface
);
2183 ok_more_than_one_lock();
2185 test_freethreadedmarshaldata(pStream
, MSHCTX_LOCAL
, &Test_ClassFactory
, MSHLFLAGS_NORMAL
);
2187 IStream_Seek(pStream
, llZero
, STREAM_SEEK_SET
, NULL
);
2188 hr
= IMarshal_ReleaseMarshalData(pFTMarshal
, pStream
);
2189 ok_ole_success(hr
, IMarshal_ReleaseMarshalData
);
2194 /* inproc table-strong marshaling */
2196 IStream_Seek(pStream
, llZero
, STREAM_SEEK_SET
, NULL
);
2197 hr
= IMarshal_MarshalInterface(pFTMarshal
, pStream
, &IID_IClassFactory
,
2198 (IUnknown
*)&Test_ClassFactory
, MSHCTX_INPROC
, (void *)0xdeadbeef,
2199 MSHLFLAGS_TABLESTRONG
);
2200 ok_ole_success(hr
, IMarshal_MarshalInterface
);
2202 ok_more_than_one_lock();
2204 test_freethreadedmarshaldata(pStream
, MSHCTX_INPROC
, &Test_ClassFactory
, MSHLFLAGS_TABLESTRONG
);
2206 IStream_Seek(pStream
, llZero
, STREAM_SEEK_SET
, NULL
);
2207 hr
= IMarshal_UnmarshalInterface(pFTMarshal
, pStream
, &IID_IUnknown
, (void **)&pProxy
);
2208 ok_ole_success(hr
, IMarshal_UnmarshalInterface
);
2210 IUnknown_Release(pProxy
);
2212 ok_more_than_one_lock();
2214 IStream_Seek(pStream
, llZero
, STREAM_SEEK_SET
, NULL
);
2215 hr
= IMarshal_ReleaseMarshalData(pFTMarshal
, pStream
);
2216 ok_ole_success(hr
, IMarshal_ReleaseMarshalData
);
2220 /* inproc table-weak marshaling */
2222 IStream_Seek(pStream
, llZero
, STREAM_SEEK_SET
, NULL
);
2223 hr
= IMarshal_MarshalInterface(pFTMarshal
, pStream
, &IID_IClassFactory
,
2224 (IUnknown
*)&Test_ClassFactory
, MSHCTX_INPROC
, (void *)0xdeadbeef,
2225 MSHLFLAGS_TABLEWEAK
);
2226 ok_ole_success(hr
, IMarshal_MarshalInterface
);
2230 test_freethreadedmarshaldata(pStream
, MSHCTX_INPROC
, &Test_ClassFactory
, MSHLFLAGS_TABLEWEAK
);
2232 IStream_Seek(pStream
, llZero
, STREAM_SEEK_SET
, NULL
);
2233 hr
= IMarshal_UnmarshalInterface(pFTMarshal
, pStream
, &IID_IUnknown
, (void **)&pProxy
);
2234 ok_ole_success(hr
, IMarshal_UnmarshalInterface
);
2236 ok_more_than_one_lock();
2238 IUnknown_Release(pProxy
);
2242 /* inproc normal marshaling (for extraordinary cases) */
2244 IStream_Seek(pStream
, llZero
, STREAM_SEEK_SET
, NULL
);
2245 hr
= IMarshal_MarshalInterface(pFTMarshal
, pStream
, &IID_IClassFactory
,
2246 &Test_ClassFactory
, MSHCTX_INPROC
, NULL
, MSHLFLAGS_NORMAL
);
2247 ok_ole_success(hr
, IMarshal_MarshalInterface
);
2249 ok_more_than_one_lock();
2251 /* this call shows that DisconnectObject does nothing */
2252 hr
= IMarshal_DisconnectObject(pFTMarshal
, 0);
2253 ok_ole_success(hr
, IMarshal_DisconnectObject
);
2255 ok_more_than_one_lock();
2257 IStream_Seek(pStream
, llZero
, STREAM_SEEK_SET
, NULL
);
2258 hr
= IMarshal_ReleaseMarshalData(pFTMarshal
, pStream
);
2259 ok_ole_success(hr
, IMarshal_ReleaseMarshalData
);
2263 /* doesn't enforce marshaling rules here and allows us to unmarshal the
2264 * interface, even though it was freed above */
2265 IStream_Seek(pStream
, llZero
, STREAM_SEEK_SET
, NULL
);
2266 hr
= IMarshal_UnmarshalInterface(pFTMarshal
, pStream
, &IID_IUnknown
, (void **)&pProxy
);
2267 ok_ole_success(hr
, IMarshal_UnmarshalInterface
);
2271 IStream_Release(pStream
);
2272 IMarshal_Release(pFTMarshal
);
2275 static HRESULT
reg_unreg_wine_test_class(BOOL Register
)
2281 DWORD dwDisposition
;
2284 hr
= StringFromCLSID(&CLSID_WineTest
, &pszClsid
);
2285 ok_ole_success(hr
, "StringFromCLSID");
2286 strcpy(buffer
, "CLSID\\");
2287 WideCharToMultiByte(CP_ACP
, 0, pszClsid
, -1, buffer
+ strlen(buffer
), sizeof(buffer
) - strlen(buffer
), NULL
, NULL
);
2288 CoTaskMemFree(pszClsid
);
2289 strcat(buffer
, "\\InprocHandler32");
2292 error
= RegCreateKeyExA(HKEY_CLASSES_ROOT
, buffer
, 0, NULL
, 0, KEY_SET_VALUE
, NULL
, &hkey
, &dwDisposition
);
2293 if (error
== ERROR_ACCESS_DENIED
)
2295 skip("Not authorized to modify the Classes key\n");
2298 ok(error
== ERROR_SUCCESS
, "RegCreateKeyEx failed with error %d\n", error
);
2299 if (error
!= ERROR_SUCCESS
) hr
= E_FAIL
;
2300 error
= RegSetValueExA(hkey
, NULL
, 0, REG_SZ
, (const unsigned char *)"\"ole32.dll\"", strlen("\"ole32.dll\"") + 1);
2301 ok(error
== ERROR_SUCCESS
, "RegSetValueEx failed with error %d\n", error
);
2302 if (error
!= ERROR_SUCCESS
) hr
= E_FAIL
;
2307 RegDeleteKeyA(HKEY_CLASSES_ROOT
, buffer
);
2308 *strrchr(buffer
, '\\') = '\0';
2309 RegDeleteKeyA(HKEY_CLASSES_ROOT
, buffer
);
2314 static void test_inproc_handler(void)
2320 if (FAILED(reg_unreg_wine_test_class(TRUE
)))
2323 hr
= CoCreateInstance(&CLSID_WineTest
, NULL
, CLSCTX_INPROC_HANDLER
, &IID_IUnknown
, (void **)&pObject
);
2324 ok_ole_success(hr
, "CoCreateInstance");
2328 hr
= IUnknown_QueryInterface(pObject
, &IID_IWineTest
, (void **)&pObject2
);
2329 ok(hr
== E_NOINTERFACE
, "IUnknown_QueryInterface on handler for invalid interface returned 0x%08x instead of E_NOINTERFACE\n", hr
);
2331 /* it's a handler as it supports IOleObject */
2332 hr
= IUnknown_QueryInterface(pObject
, &IID_IOleObject
, (void **)&pObject2
);
2333 ok_ole_success(hr
, "IUnknown_QueryInterface(&IID_IOleObject)");
2334 IUnknown_Release(pObject2
);
2336 IUnknown_Release(pObject
);
2339 reg_unreg_wine_test_class(FALSE
);
2342 static HRESULT WINAPI
Test_SMI_QueryInterface(
2343 IStdMarshalInfo
*iface
,
2347 if (ppvObj
== NULL
) return E_POINTER
;
2349 if (IsEqualGUID(riid
, &IID_IUnknown
) ||
2350 IsEqualGUID(riid
, &IID_IStdMarshalInfo
))
2353 IStdMarshalInfo_AddRef(iface
);
2357 return E_NOINTERFACE
;
2360 static ULONG WINAPI
Test_SMI_AddRef(IStdMarshalInfo
*iface
)
2363 return 2; /* non-heap-based object */
2366 static ULONG WINAPI
Test_SMI_Release(IStdMarshalInfo
*iface
)
2369 return 1; /* non-heap-based object */
2372 static HRESULT WINAPI
Test_SMI_GetClassForHandler(
2373 IStdMarshalInfo
*iface
,
2374 DWORD dwDestContext
,
2375 void *pvDestContext
,
2378 *pClsid
= CLSID_WineTest
;
2382 static const IStdMarshalInfoVtbl Test_SMI_Vtbl
=
2384 Test_SMI_QueryInterface
,
2387 Test_SMI_GetClassForHandler
2390 static IStdMarshalInfo Test_SMI
= {&Test_SMI_Vtbl
};
2392 static void test_handler_marshaling(void)
2395 IStream
*pStream
= NULL
;
2396 IUnknown
*pProxy
= NULL
;
2400 static const LARGE_INTEGER ullZero
;
2402 if (FAILED(reg_unreg_wine_test_class(TRUE
)))
2406 hr
= CreateStreamOnHGlobal(NULL
, TRUE
, &pStream
);
2407 ok_ole_success(hr
, "CreateStreamOnHGlobal");
2408 tid
= start_host_object(pStream
, &IID_IUnknown
, (IUnknown
*)&Test_SMI
, MSHLFLAGS_NORMAL
, &thread
);
2410 ok_more_than_one_lock();
2412 IStream_Seek(pStream
, ullZero
, STREAM_SEEK_SET
, NULL
);
2413 hr
= CoUnmarshalInterface(pStream
, &IID_IUnknown
, (void **)&pProxy
);
2414 ok_ole_success(hr
, "CoUnmarshalInterface");
2415 IStream_Release(pStream
);
2419 ok_more_than_one_lock();
2421 hr
= IUnknown_QueryInterface(pProxy
, &IID_IWineTest
, (void **)&pObject
);
2422 ok(hr
== E_NOINTERFACE
, "IUnknown_QueryInterface with unknown IID should have returned E_NOINTERFACE instead of 0x%08x\n", hr
);
2424 /* it's a handler as it supports IOleObject */
2425 hr
= IUnknown_QueryInterface(pProxy
, &IID_IOleObject
, (void **)&pObject
);
2427 ok_ole_success(hr
, "IUnknown_QueryInterface(&IID_IOleObject)");
2428 if (SUCCEEDED(hr
)) IUnknown_Release(pObject
);
2430 IUnknown_Release(pProxy
);
2435 end_host_object(tid
, thread
);
2436 reg_unreg_wine_test_class(FALSE
);
2438 /* FIXME: test IPersist interface has the same effect as IStdMarshalInfo */
2442 static void test_client_security(void)
2445 IStream
*pStream
= NULL
;
2446 IClassFactory
*pProxy
= NULL
;
2447 IUnknown
*pProxy2
= NULL
;
2448 IUnknown
*pUnknown1
= NULL
;
2449 IUnknown
*pUnknown2
= NULL
;
2450 IClientSecurity
*pCliSec
= NULL
;
2454 static const LARGE_INTEGER ullZero
;
2457 OLECHAR
*pServerPrincName
;
2461 DWORD dwCapabilities
;
2466 hr
= CreateStreamOnHGlobal(NULL
, TRUE
, &pStream
);
2467 ok_ole_success(hr
, "CreateStreamOnHGlobal");
2468 tid
= start_host_object(pStream
, &IID_IClassFactory
, (IUnknown
*)&Test_ClassFactory
, MSHLFLAGS_NORMAL
, &thread
);
2470 IStream_Seek(pStream
, ullZero
, STREAM_SEEK_SET
, NULL
);
2471 hr
= CoUnmarshalInterface(pStream
, &IID_IClassFactory
, (void **)&pProxy
);
2472 ok_ole_success(hr
, "CoUnmarshalInterface");
2473 IStream_Release(pStream
);
2475 hr
= IClassFactory_QueryInterface(pProxy
, &IID_IUnknown
, (LPVOID
*)&pUnknown1
);
2476 ok_ole_success(hr
, "IUnknown_QueryInterface IID_IUnknown");
2478 hr
= IClassFactory_QueryInterface(pProxy
, &IID_IRemUnknown
, (LPVOID
*)&pProxy2
);
2479 ok_ole_success(hr
, "IUnknown_QueryInterface IID_IStream");
2481 hr
= IUnknown_QueryInterface(pProxy2
, &IID_IUnknown
, (LPVOID
*)&pUnknown2
);
2482 ok_ole_success(hr
, "IUnknown_QueryInterface IID_IUnknown");
2484 ok(pUnknown1
== pUnknown2
, "both proxy's IUnknowns should be the same - %p, %p\n", pUnknown1
, pUnknown2
);
2486 hr
= IClassFactory_QueryInterface(pProxy
, &IID_IMarshal
, (LPVOID
*)&pMarshal
);
2487 ok_ole_success(hr
, "IUnknown_QueryInterface IID_IMarshal");
2489 hr
= IClassFactory_QueryInterface(pProxy
, &IID_IClientSecurity
, (LPVOID
*)&pCliSec
);
2490 ok_ole_success(hr
, "IUnknown_QueryInterface IID_IClientSecurity");
2492 hr
= IClientSecurity_QueryBlanket(pCliSec
, (IUnknown
*)pProxy
, NULL
, NULL
, NULL
, NULL
, NULL
, NULL
, NULL
);
2493 todo_wine
ok_ole_success(hr
, "IClientSecurity_QueryBlanket (all NULLs)");
2495 hr
= IClientSecurity_QueryBlanket(pCliSec
, (IUnknown
*)pMarshal
, NULL
, NULL
, NULL
, NULL
, NULL
, NULL
, NULL
);
2496 todo_wine
ok(hr
== E_NOINTERFACE
, "IClientSecurity_QueryBlanket with local interface should have returned E_NOINTERFACE instead of 0x%08x\n", hr
);
2498 hr
= IClientSecurity_QueryBlanket(pCliSec
, (IUnknown
*)pProxy
, &dwAuthnSvc
, &dwAuthzSvc
, &pServerPrincName
, &dwAuthnLevel
, &dwImpLevel
, &pAuthInfo
, &dwCapabilities
);
2499 todo_wine
ok_ole_success(hr
, "IClientSecurity_QueryBlanket");
2501 hr
= IClientSecurity_SetBlanket(pCliSec
, (IUnknown
*)pProxy
, dwAuthnSvc
, dwAuthzSvc
, pServerPrincName
, dwAuthnLevel
, RPC_C_IMP_LEVEL_IMPERSONATE
, pAuthInfo
, dwCapabilities
);
2502 todo_wine
ok_ole_success(hr
, "IClientSecurity_SetBlanket");
2504 hr
= IClassFactory_CreateInstance(pProxy
, NULL
, &IID_IWineTest
, &pv
);
2505 ok(hr
== E_NOINTERFACE
, "COM call should have succeeded instead of returning 0x%08x\n", hr
);
2507 hr
= IClientSecurity_SetBlanket(pCliSec
, (IUnknown
*)pMarshal
, dwAuthnSvc
, dwAuthzSvc
, pServerPrincName
, dwAuthnLevel
, dwImpLevel
, pAuthInfo
, dwCapabilities
);
2508 todo_wine
ok(hr
== E_NOINTERFACE
, "IClientSecurity_SetBlanket with local interface should have returned E_NOINTERFACE instead of 0x%08x\n", hr
);
2510 hr
= IClientSecurity_SetBlanket(pCliSec
, (IUnknown
*)pProxy
, 0xdeadbeef, dwAuthzSvc
, pServerPrincName
, dwAuthnLevel
, dwImpLevel
, pAuthInfo
, dwCapabilities
);
2511 todo_wine
ok(hr
== E_INVALIDARG
, "IClientSecurity_SetBlanke with invalid dwAuthnSvc should have returned E_INVALIDARG instead of 0x%08x\n", hr
);
2513 CoTaskMemFree(pServerPrincName
);
2515 hr
= IClientSecurity_QueryBlanket(pCliSec
, pUnknown1
, &dwAuthnSvc
, &dwAuthzSvc
, &pServerPrincName
, &dwAuthnLevel
, &dwImpLevel
, &pAuthInfo
, &dwCapabilities
);
2516 todo_wine
ok_ole_success(hr
, "IClientSecurity_QueryBlanket(IUnknown)");
2518 CoTaskMemFree(pServerPrincName
);
2520 IClassFactory_Release(pProxy
);
2521 IUnknown_Release(pProxy2
);
2522 IUnknown_Release(pUnknown1
);
2523 IUnknown_Release(pUnknown2
);
2524 IMarshal_Release(pMarshal
);
2525 IClientSecurity_Release(pCliSec
);
2527 end_host_object(tid
, thread
);
2530 static HANDLE heventShutdown
;
2532 static void LockModuleOOP(void)
2534 InterlockedIncrement(&cLocks
); /* for test purposes only */
2535 CoAddRefServerProcess();
2538 static void UnlockModuleOOP(void)
2540 InterlockedDecrement(&cLocks
); /* for test purposes only */
2541 if (!CoReleaseServerProcess())
2542 SetEvent(heventShutdown
);
2545 static HWND hwnd_app
;
2547 static HRESULT WINAPI
TestOOP_IClassFactory_QueryInterface(
2548 LPCLASSFACTORY iface
,
2552 if (ppvObj
== NULL
) return E_POINTER
;
2554 if (IsEqualGUID(riid
, &IID_IUnknown
) ||
2555 IsEqualGUID(riid
, &IID_IClassFactory
))
2558 IClassFactory_AddRef(iface
);
2562 return E_NOINTERFACE
;
2565 static ULONG WINAPI
TestOOP_IClassFactory_AddRef(LPCLASSFACTORY iface
)
2567 return 2; /* non-heap-based object */
2570 static ULONG WINAPI
TestOOP_IClassFactory_Release(LPCLASSFACTORY iface
)
2572 return 1; /* non-heap-based object */
2575 static HRESULT WINAPI
TestOOP_IClassFactory_CreateInstance(
2576 LPCLASSFACTORY iface
,
2577 LPUNKNOWN pUnkOuter
,
2581 if (IsEqualIID(riid
, &IID_IClassFactory
) || IsEqualIID(riid
, &IID_IUnknown
))
2586 return CLASS_E_CLASSNOTAVAILABLE
;
2589 static HRESULT WINAPI
TestOOP_IClassFactory_LockServer(
2590 LPCLASSFACTORY iface
,
2600 static const IClassFactoryVtbl TestClassFactoryOOP_Vtbl
=
2602 TestOOP_IClassFactory_QueryInterface
,
2603 TestOOP_IClassFactory_AddRef
,
2604 TestOOP_IClassFactory_Release
,
2605 TestOOP_IClassFactory_CreateInstance
,
2606 TestOOP_IClassFactory_LockServer
2609 static IClassFactory TestOOP_ClassFactory
= { &TestClassFactoryOOP_Vtbl
};
2611 static void test_register_local_server(void)
2619 heventShutdown
= CreateEventA(NULL
, TRUE
, FALSE
, NULL
);
2621 hr
= CoRegisterClassObject(&CLSID_WineOOPTest
, (IUnknown
*)&TestOOP_ClassFactory
,
2622 CLSCTX_LOCAL_SERVER
, REGCLS_SINGLEUSE
, &cookie
);
2623 ok_ole_success(hr
, CoRegisterClassObject
);
2625 ready_event
= CreateEventA(NULL
, FALSE
, FALSE
, "Wine COM Test Ready Event");
2626 SetEvent(ready_event
);
2628 quit_event
= CreateEventA(NULL
, FALSE
, FALSE
, "Wine COM Test Quit Event");
2632 wait
= MsgWaitForMultipleObjects(1, &quit_event
, FALSE
, 30000, QS_ALLINPUT
);
2633 if (wait
== WAIT_OBJECT_0
+1)
2637 if (PeekMessageA(&msg
, NULL
, 0, 0, PM_REMOVE
))
2639 trace("Message 0x%x\n", msg
.message
);
2640 TranslateMessage(&msg
);
2641 DispatchMessageA(&msg
);
2645 while (wait
== WAIT_OBJECT_0
+1);
2647 ok( wait
== WAIT_OBJECT_0
, "quit event wait timed out\n" );
2648 hr
= CoRevokeClassObject(cookie
);
2649 ok_ole_success(hr
, CoRevokeClassObject
);
2652 static HANDLE
create_target_process(const char *arg
)
2655 char cmdline
[MAX_PATH
];
2657 PROCESS_INFORMATION pi
;
2658 STARTUPINFOA si
= { 0 };
2663 winetest_get_mainargs( &argv
);
2664 sprintf(cmdline
, "%s %s %s", argv
[0], argv
[1], arg
);
2665 ret
= CreateProcessA(argv
[0], cmdline
, NULL
, NULL
, FALSE
, 0, NULL
, NULL
, &si
, &pi
);
2666 ok(ret
, "CreateProcess failed with error: %u\n", GetLastError());
2667 if (pi
.hThread
) CloseHandle(pi
.hThread
);
2671 /* tests functions commonly used by out of process COM servers */
2672 static void test_local_server(void)
2682 heventShutdown
= CreateEventA(NULL
, TRUE
, FALSE
, NULL
);
2686 /* Start the object suspended */
2687 hr
= CoRegisterClassObject(&CLSID_WineOOPTest
, (IUnknown
*)&TestOOP_ClassFactory
,
2688 CLSCTX_LOCAL_SERVER
, REGCLS_MULTIPLEUSE
| REGCLS_SUSPENDED
, &cookie
);
2689 ok_ole_success(hr
, CoRegisterClassObject
);
2691 /* ... and CoGetClassObject does not find it and fails when it looks for the
2692 * class in the registry */
2693 hr
= CoGetClassObject(&CLSID_WineOOPTest
, CLSCTX_INPROC_SERVER
,
2694 NULL
, &IID_IClassFactory
, (LPVOID
*)&cf
);
2695 ok(hr
== REGDB_E_CLASSNOTREG
|| /* NT */
2696 hr
== S_OK
/* Win9x */,
2697 "CoGetClassObject should have returned REGDB_E_CLASSNOTREG instead of 0x%08x\n", hr
);
2699 /* Resume the object suspended above ... */
2700 hr
= CoResumeClassObjects();
2701 ok_ole_success(hr
, CoResumeClassObjects
);
2703 /* ... and now it should succeed */
2704 hr
= CoGetClassObject(&CLSID_WineOOPTest
, CLSCTX_INPROC_SERVER
,
2705 NULL
, &IID_IClassFactory
, (LPVOID
*)&cf
);
2706 ok_ole_success(hr
, CoGetClassObject
);
2708 /* Now check the locking is working */
2709 /* NOTE: we are accessing the class directly, not through a proxy */
2713 hr
= IClassFactory_LockServer(cf
, TRUE
);
2714 ok_ole_success(hr
, IClassFactory_LockServer
);
2716 ok_more_than_one_lock();
2718 IClassFactory_LockServer(cf
, FALSE
);
2719 ok_ole_success(hr
, IClassFactory_LockServer
);
2723 IClassFactory_Release(cf
);
2725 /* wait for shutdown signal */
2726 ret
= WaitForSingleObject(heventShutdown
, 0);
2727 ok(ret
!= WAIT_TIMEOUT
, "Server didn't shut down\n");
2729 /* try to connect again after SCM has suspended registered class objects */
2730 hr
= CoGetClassObject(&CLSID_WineOOPTest
, CLSCTX_INPROC_SERVER
| CLSCTX_LOCAL_SERVER
, NULL
,
2731 &IID_IClassFactory
, (LPVOID
*)&cf
);
2732 ok(hr
== CO_E_SERVER_STOPPING
|| /* NT */
2733 hr
== REGDB_E_CLASSNOTREG
|| /* win2k */
2734 hr
== S_OK
/* Win9x */,
2735 "CoGetClassObject should have returned CO_E_SERVER_STOPPING or REGDB_E_CLASSNOTREG instead of 0x%08x\n", hr
);
2737 hr
= CoRevokeClassObject(cookie
);
2738 ok_ole_success(hr
, CoRevokeClassObject
);
2740 CloseHandle(heventShutdown
);
2742 process
= create_target_process("-Embedding");
2743 ok(process
!= NULL
, "couldn't start local server process, error was %d\n", GetLastError());
2745 ready_event
= CreateEventA(NULL
, FALSE
, FALSE
, "Wine COM Test Ready Event");
2746 ok( !WaitForSingleObject(ready_event
, 10000), "wait timed out\n" );
2747 CloseHandle(ready_event
);
2749 hr
= CoCreateInstance(&CLSID_WineOOPTest
, NULL
, CLSCTX_LOCAL_SERVER
, &IID_IClassFactory
, (void **)&cf
);
2750 ok_ole_success(hr
, CoCreateInstance
);
2752 IClassFactory_Release(cf
);
2754 hr
= CoCreateInstance(&CLSID_WineOOPTest
, NULL
, CLSCTX_LOCAL_SERVER
, &IID_IClassFactory
, (void **)&cf
);
2755 ok(hr
== REGDB_E_CLASSNOTREG
, "Second CoCreateInstance on REGCLS_SINGLEUSE object should have failed\n");
2757 quit_event
= CreateEventA(NULL
, FALSE
, FALSE
, "Wine COM Test Quit Event");
2758 SetEvent(quit_event
);
2760 winetest_wait_child_process( process
);
2761 CloseHandle(quit_event
);
2762 CloseHandle(process
);
2768 IGlobalInterfaceTable
*git
;
2771 static DWORD CALLBACK
get_global_interface_proc(LPVOID pv
)
2774 struct git_params
*params
= pv
;
2777 hr
= IGlobalInterfaceTable_GetInterfaceFromGlobal(params
->git
, params
->cookie
, &IID_IClassFactory
, (void **)&cf
);
2778 ok(hr
== CO_E_NOTINITIALIZED
||
2779 broken(hr
== E_UNEXPECTED
) /* win2k */ ||
2780 broken(hr
== S_OK
) /* NT 4 */,
2781 "IGlobalInterfaceTable_GetInterfaceFromGlobal should have failed with error CO_E_NOTINITIALIZED or E_UNEXPECTED instead of 0x%08x\n",
2784 IClassFactory_Release(cf
);
2788 hr
= IGlobalInterfaceTable_GetInterfaceFromGlobal(params
->git
, params
->cookie
, &IID_IClassFactory
, (void **)&cf
);
2789 ok_ole_success(hr
, IGlobalInterfaceTable_GetInterfaceFromGlobal
);
2791 IClassFactory_Release(cf
);
2798 static void test_globalinterfacetable(void)
2801 IGlobalInterfaceTable
*git
;
2805 struct git_params params
;
2811 trace("test_globalinterfacetable\n");
2814 hr
= pDllGetClassObject(&CLSID_StdGlobalInterfaceTable
, &IID_IClassFactory
, (void**)&cf
);
2815 ok(hr
== S_OK
, "got 0x%08x\n", hr
);
2817 hr
= IClassFactory_QueryInterface(cf
, &IID_IGlobalInterfaceTable
, (void**)&object
);
2818 ok(hr
== E_NOINTERFACE
, "got 0x%08x\n", hr
);
2820 IClassFactory_Release(cf
);
2822 hr
= CoCreateInstance(&CLSID_StdGlobalInterfaceTable
, NULL
, CLSCTX_INPROC_SERVER
, &IID_IGlobalInterfaceTable
, (void **)&git
);
2823 ok_ole_success(hr
, CoCreateInstance
);
2825 ref
= IGlobalInterfaceTable_AddRef(git
);
2826 ok(ref
== 1, "ref=%d\n", ref
);
2827 ref
= IGlobalInterfaceTable_AddRef(git
);
2828 ok(ref
== 1, "ref=%d\n", ref
);
2830 ref
= IGlobalInterfaceTable_Release(git
);
2831 ok(ref
== 1, "ref=%d\n", ref
);
2832 ref
= IGlobalInterfaceTable_Release(git
);
2833 ok(ref
== 1, "ref=%d\n", ref
);
2835 hr
= IGlobalInterfaceTable_RegisterInterfaceInGlobal(git
, (IUnknown
*)&Test_ClassFactory
, &IID_IClassFactory
, &cookie
);
2836 ok_ole_success(hr
, IGlobalInterfaceTable_RegisterInterfaceInGlobal
);
2838 ok_more_than_one_lock();
2840 params
.cookie
= cookie
;
2842 /* note: params is on stack so we MUST wait for get_global_interface_proc
2843 * to exit before we can return */
2844 thread
= CreateThread(NULL
, 0, get_global_interface_proc
, ¶ms
, 0, &tid
);
2846 ret
= MsgWaitForMultipleObjects(1, &thread
, FALSE
, 10000, QS_ALLINPUT
);
2847 while (ret
== WAIT_OBJECT_0
+ 1)
2850 while (PeekMessageA(&msg
, NULL
, 0, 0, PM_REMOVE
))
2851 DispatchMessageA(&msg
);
2852 ret
= MsgWaitForMultipleObjects(1, &thread
, FALSE
, 10000, QS_ALLINPUT
);
2855 CloseHandle(thread
);
2857 /* test getting interface from global with different iid */
2858 hr
= IGlobalInterfaceTable_GetInterfaceFromGlobal(git
, cookie
, &IID_IUnknown
, (void **)&object
);
2859 ok_ole_success(hr
, IGlobalInterfaceTable_GetInterfaceFromGlobal
);
2860 IUnknown_Release(object
);
2862 /* test getting interface from global with same iid */
2863 hr
= IGlobalInterfaceTable_GetInterfaceFromGlobal(git
, cookie
, &IID_IClassFactory
, (void **)&object
);
2864 ok_ole_success(hr
, IGlobalInterfaceTable_GetInterfaceFromGlobal
);
2865 IUnknown_Release(object
);
2867 hr
= IGlobalInterfaceTable_RevokeInterfaceFromGlobal(git
, cookie
);
2868 ok_ole_success(hr
, IGlobalInterfaceTable_RevokeInterfaceFromGlobal
);
2872 IGlobalInterfaceTable_Release(git
);
2875 static void test_manualresetevent(void)
2877 ISynchronizeHandle
*sync_handle
;
2878 ISynchronize
*psync1
, *psync2
;
2884 hr
= CoCreateInstance(&CLSID_ManualResetEvent
, NULL
, CLSCTX_INPROC_SERVER
, &IID_IUnknown
, (void**)&punk
);
2885 ok(hr
== S_OK
, "Got 0x%08x\n", hr
);
2886 ok(!!punk
, "Got NULL.\n");
2887 IUnknown_Release(punk
);
2889 hr
= CoCreateInstance(&CLSID_ManualResetEvent
, NULL
, CLSCTX_INPROC_SERVER
, &IID_ISynchronize
, (void**)&psync1
);
2890 ok(hr
== S_OK
, "Got 0x%08x\n", hr
);
2891 ok(!!psync1
, "Got NULL.\n");
2893 hr
= ISynchronize_Wait(psync1
, 0, 5);
2894 ok(hr
== RPC_S_CALLPENDING
, "Got 0x%08x\n", hr
);
2896 hr
= ISynchronize_Reset(psync1
);
2897 ok(hr
== S_OK
, "Got 0x%08x\n", hr
);
2898 hr
= ISynchronize_Signal(psync1
);
2899 ok(hr
== S_OK
, "Got 0x%08x\n", hr
);
2900 hr
= ISynchronize_Wait(psync1
, 0, 5);
2901 ok(hr
== S_OK
, "Got 0x%08x\n", hr
);
2902 hr
= ISynchronize_Wait(psync1
, 0, 5);
2903 ok(hr
== S_OK
, "Got 0x%08x\n", hr
);
2904 hr
= ISynchronize_Reset(psync1
);
2905 ok(hr
== S_OK
, "Got 0x%08x\n", hr
);
2906 hr
= ISynchronize_Wait(psync1
, 0, 5);
2907 ok(hr
== RPC_S_CALLPENDING
, "Got 0x%08x\n", hr
);
2909 hr
= CoCreateInstance(&CLSID_ManualResetEvent
, NULL
, CLSCTX_INPROC_SERVER
, &IID_ISynchronize
, (void**)&psync2
);
2910 ok(hr
== S_OK
, "Got 0x%08x\n", hr
);
2911 ok(!!psync2
, "Got NULL.\n");
2912 ok(psync1
!= psync2
, "psync1 == psync2.\n");
2914 hr
= ISynchronize_QueryInterface(psync2
, &IID_ISynchronizeHandle
, (void**)&sync_handle
);
2915 ok(hr
== S_OK
, "QueryInterface(IID_ISynchronizeHandle) failed: %08x\n", hr
);
2918 hr
= ISynchronizeHandle_GetHandle(sync_handle
, &handle
);
2919 ok(hr
== S_OK
, "GetHandle failed: %08x\n", hr
);
2920 ok(handle
!= NULL
&& handle
!= INVALID_HANDLE_VALUE
, "handle = %p\n", handle
);
2922 ISynchronizeHandle_Release(sync_handle
);
2924 hr
= ISynchronize_Wait(psync2
, 0, 5);
2925 ok(hr
== RPC_S_CALLPENDING
, "Got 0x%08x\n", hr
);
2927 hr
= ISynchronize_Reset(psync1
);
2928 ok(hr
== S_OK
, "Got 0x%08x\n", hr
);
2929 hr
= ISynchronize_Reset(psync2
);
2930 ok(hr
== S_OK
, "Got 0x%08x\n", hr
);
2931 hr
= ISynchronize_Signal(psync1
);
2932 ok(hr
== S_OK
, "Got 0x%08x\n", hr
);
2933 hr
= ISynchronize_Wait(psync2
, 0, 5);
2934 ok(hr
== RPC_S_CALLPENDING
, "Got 0x%08x\n", hr
);
2936 ref
= ISynchronize_AddRef(psync1
);
2937 ok(ref
== 2, "Got ref: %d\n", ref
);
2938 ref
= ISynchronize_AddRef(psync1
);
2939 ok(ref
== 3, "Got ref: %d\n", ref
);
2940 ref
= ISynchronize_Release(psync1
);
2941 ok(ref
== 2, "Got nonzero ref: %d\n", ref
);
2942 ref
= ISynchronize_Release(psync2
);
2943 ok(!ref
, "Got nonzero ref: %d\n", ref
);
2944 ref
= ISynchronize_Release(psync1
);
2945 ok(ref
== 1, "Got nonzero ref: %d\n", ref
);
2946 ref
= ISynchronize_Release(psync1
);
2947 ok(!ref
, "Got nonzero ref: %d\n", ref
);
2950 static const char *debugstr_iid(REFIID riid
)
2952 static char name
[256];
2956 LONG name_size
= sizeof(name
);
2957 StringFromGUID2(riid
, bufferW
, sizeof(bufferW
)/sizeof(bufferW
[0]));
2958 WideCharToMultiByte(CP_ACP
, 0, bufferW
, sizeof(bufferW
)/sizeof(bufferW
[0]), buffer
, sizeof(buffer
), NULL
, NULL
);
2959 if (RegOpenKeyExA(HKEY_CLASSES_ROOT
, "Interface", 0, KEY_QUERY_VALUE
, &hkeyInterface
) != ERROR_SUCCESS
)
2961 memcpy(name
, buffer
, sizeof(buffer
));
2964 if (RegQueryValueA(hkeyInterface
, buffer
, name
, &name_size
) != ERROR_SUCCESS
)
2966 memcpy(name
, buffer
, sizeof(buffer
));
2969 RegCloseKey(hkeyInterface
);
2974 static HRESULT WINAPI
TestChannelHook_QueryInterface(IChannelHook
*iface
, REFIID riid
, void **ppv
)
2976 if (IsEqualIID(riid
, &IID_IUnknown
) || IsEqualIID(riid
, &IID_IChannelHook
))
2979 IChannelHook_AddRef(iface
);
2984 return E_NOINTERFACE
;
2987 static ULONG WINAPI
TestChannelHook_AddRef(IChannelHook
*iface
)
2992 static ULONG WINAPI
TestChannelHook_Release(IChannelHook
*iface
)
2997 static void WINAPI
TestChannelHook_ClientGetSize(
2998 IChannelHook
*iface
,
3003 SChannelHookCallInfo
*info
= (SChannelHookCallInfo
*)riid
;
3004 trace("TestChannelHook_ClientGetBuffer\n");
3005 trace("\t%s method %d\n", debugstr_iid(riid
), info
->iMethod
);
3006 trace("\tcid: %s\n", debugstr_iid(&info
->uCausality
));
3007 ok(info
->cbSize
== sizeof(*info
), "info->cbSize was %d instead of %d\n", info
->cbSize
, (int)sizeof(*info
));
3008 ok(info
->dwServerPid
== GetCurrentProcessId(), "info->dwServerPid was 0x%x instead of 0x%x\n", info
->dwServerPid
, GetCurrentProcessId());
3009 ok(!info
->pObject
, "info->pObject should be NULL\n");
3010 ok(IsEqualGUID(uExtent
, &EXTENTID_WineTest
), "uExtent wasn't correct\n");
3015 static void WINAPI
TestChannelHook_ClientFillBuffer(
3016 IChannelHook
*iface
,
3022 SChannelHookCallInfo
*info
= (SChannelHookCallInfo
*)riid
;
3023 trace("TestChannelHook_ClientFillBuffer\n");
3024 ok(info
->cbSize
== sizeof(*info
), "info->cbSize was %d instead of %d\n", info
->cbSize
, (int)sizeof(*info
));
3025 ok(info
->dwServerPid
== GetCurrentProcessId(), "info->dwServerPid was 0x%x instead of 0x%x\n", info
->dwServerPid
, GetCurrentProcessId());
3026 ok(!info
->pObject
, "info->pObject should be NULL\n");
3027 ok(IsEqualGUID(uExtent
, &EXTENTID_WineTest
), "uExtent wasn't correct\n");
3029 *(unsigned char *)pDataBuffer
= 0xcc;
3033 static void WINAPI
TestChannelHook_ClientNotify(
3034 IChannelHook
*iface
,
3042 SChannelHookCallInfo
*info
= (SChannelHookCallInfo
*)riid
;
3043 trace("TestChannelHook_ClientNotify hrFault = 0x%08x\n", hrFault
);
3044 ok(info
->cbSize
== sizeof(*info
), "info->cbSize was %d instead of %d\n", info
->cbSize
, (int)sizeof(*info
));
3045 ok(info
->dwServerPid
== GetCurrentProcessId(), "info->dwServerPid was 0x%x instead of 0x%x\n", info
->dwServerPid
, GetCurrentProcessId());
3047 ok(info
->pObject
!= NULL
, "info->pObject shouldn't be NULL\n");
3049 ok(IsEqualGUID(uExtent
, &EXTENTID_WineTest
), "uExtent wasn't correct\n");
3052 static void WINAPI
TestChannelHook_ServerNotify(
3053 IChannelHook
*iface
,
3060 SChannelHookCallInfo
*info
= (SChannelHookCallInfo
*)riid
;
3061 trace("TestChannelHook_ServerNotify\n");
3062 ok(info
->cbSize
== sizeof(*info
), "info->cbSize was %d instead of %d\n", info
->cbSize
, (int)sizeof(*info
));
3063 ok(info
->dwServerPid
== GetCurrentProcessId(), "info->dwServerPid was 0x%x instead of 0x%x\n", info
->dwServerPid
, GetCurrentProcessId());
3064 ok(info
->pObject
!= NULL
, "info->pObject shouldn't be NULL\n");
3065 ok(cbDataSize
== 1, "cbDataSize should have been 1 instead of %d\n", cbDataSize
);
3066 ok(*(unsigned char *)pDataBuffer
== 0xcc, "pDataBuffer should have contained 0xcc instead of 0x%x\n", *(unsigned char *)pDataBuffer
);
3067 ok(IsEqualGUID(uExtent
, &EXTENTID_WineTest
), "uExtent wasn't correct\n");
3070 static void WINAPI
TestChannelHook_ServerGetSize(
3071 IChannelHook
*iface
,
3077 SChannelHookCallInfo
*info
= (SChannelHookCallInfo
*)riid
;
3078 trace("TestChannelHook_ServerGetSize\n");
3079 trace("\t%s method %d\n", debugstr_iid(riid
), info
->iMethod
);
3080 ok(info
->cbSize
== sizeof(*info
), "info->cbSize was %d instead of %d\n", info
->cbSize
, (int)sizeof(*info
));
3081 ok(info
->dwServerPid
== GetCurrentProcessId(), "info->dwServerPid was 0x%x instead of 0x%x\n", info
->dwServerPid
, GetCurrentProcessId());
3082 ok(info
->pObject
!= NULL
, "info->pObject shouldn't be NULL\n");
3083 ok(IsEqualGUID(uExtent
, &EXTENTID_WineTest
), "uExtent wasn't correct\n");
3084 if (hrFault
!= S_OK
)
3085 trace("\thrFault = 0x%08x\n", hrFault
);
3090 static void WINAPI
TestChannelHook_ServerFillBuffer(
3091 IChannelHook
*iface
,
3098 trace("TestChannelHook_ServerFillBuffer\n");
3099 ok(0, "TestChannelHook_ServerFillBuffer shouldn't be called\n");
3102 static const IChannelHookVtbl TestChannelHookVtbl
=
3104 TestChannelHook_QueryInterface
,
3105 TestChannelHook_AddRef
,
3106 TestChannelHook_Release
,
3107 TestChannelHook_ClientGetSize
,
3108 TestChannelHook_ClientFillBuffer
,
3109 TestChannelHook_ClientNotify
,
3110 TestChannelHook_ServerNotify
,
3111 TestChannelHook_ServerGetSize
,
3112 TestChannelHook_ServerFillBuffer
,
3115 static IChannelHook TestChannelHook
= { &TestChannelHookVtbl
};
3117 static void test_channel_hook(void)
3119 IStream
*pStream
= NULL
;
3120 IClassFactory
*cf
= NULL
;
3122 IUnknown
*proxy
= NULL
;
3126 hr
= CoRegisterChannelHook(&EXTENTID_WineTest
, &TestChannelHook
);
3127 ok_ole_success(hr
, CoRegisterChannelHook
);
3129 hr
= CoRegisterMessageFilter(&MessageFilter
, NULL
);
3130 ok_ole_success(hr
, CoRegisterMessageFilter
);
3134 hr
= CreateStreamOnHGlobal(NULL
, TRUE
, &pStream
);
3135 ok_ole_success(hr
, CreateStreamOnHGlobal
);
3136 tid
= start_host_object2(pStream
, &IID_IClassFactory
, (IUnknown
*)&Test_ClassFactory
, MSHLFLAGS_NORMAL
, &MessageFilter
, &thread
);
3138 ok_more_than_one_lock();
3140 IStream_Seek(pStream
, ullZero
, STREAM_SEEK_SET
, NULL
);
3141 hr
= CoUnmarshalInterface(pStream
, &IID_IClassFactory
, (void **)&cf
);
3142 ok_ole_success(hr
, CoUnmarshalInterface
);
3143 IStream_Release(pStream
);
3145 ok_more_than_one_lock();
3147 hr
= IClassFactory_CreateInstance(cf
, NULL
, &IID_IUnknown
, (LPVOID
*)&proxy
);
3148 ok_ole_success(hr
, IClassFactory_CreateInstance
);
3149 IUnknown_Release(proxy
);
3151 IClassFactory_Release(cf
);
3155 end_host_object(tid
, thread
);
3157 hr
= CoRegisterMessageFilter(NULL
, NULL
);
3158 ok_ole_success(hr
, CoRegisterMessageFilter
);
3163 HMODULE hOle32
= GetModuleHandleA("ole32");
3167 if (!GetProcAddress(hOle32
, "CoRegisterSurrogateEx")) {
3168 win_skip("skipping test on win9x\n");
3172 pCoInitializeEx
= (void*)GetProcAddress(hOle32
, "CoInitializeEx");
3173 pDllGetClassObject
= (void*)GetProcAddress(hOle32
, "DllGetClassObject");
3175 argc
= winetest_get_mainargs( &argv
);
3176 if (argc
> 2 && (!strcmp(argv
[2], "-Embedding")))
3178 pCoInitializeEx(NULL
, COINIT_APARTMENTTHREADED
);
3179 test_register_local_server();
3185 register_test_window();
3187 test_cocreateinstance_proxy();
3189 pCoInitializeEx(NULL
, COINIT_APARTMENTTHREADED
);
3191 /* FIXME: test CoCreateInstanceEx */
3193 /* lifecycle management and marshaling tests */
3194 test_no_marshaler();
3195 test_normal_marshal_and_release();
3196 test_normal_marshal_and_unmarshal();
3197 test_marshal_and_unmarshal_invalid();
3198 test_same_apartment_unmarshal_failure();
3199 test_interthread_marshal_and_unmarshal();
3200 test_proxy_marshal_and_unmarshal();
3201 test_proxy_marshal_and_unmarshal2();
3202 test_proxy_marshal_and_unmarshal_weak();
3203 test_proxy_marshal_and_unmarshal_strong();
3204 test_marshal_stub_apartment_shutdown();
3205 test_marshal_proxy_apartment_shutdown();
3206 test_marshal_proxy_mta_apartment_shutdown();
3207 test_no_couninitialize_server();
3208 test_no_couninitialize_client();
3209 test_tableweak_marshal_and_unmarshal_twice();
3210 test_tableweak_marshal_releasedata1();
3211 test_tableweak_marshal_releasedata2();
3212 test_tableweak_and_normal_marshal_and_unmarshal();
3213 test_tablestrong_marshal_and_unmarshal_twice();
3214 test_lock_object_external();
3215 test_disconnect_stub();
3216 test_normal_marshal_and_unmarshal_twice();
3217 test_hresult_marshaling();
3218 test_proxy_used_in_wrong_thread();
3219 test_message_filter();
3220 test_bad_marshal_stream();
3221 test_proxy_interfaces();
3222 test_stubbuffer(&IID_IClassFactory
);
3223 test_proxybuffer(&IID_IClassFactory
);
3224 test_message_reentrancy();
3225 test_call_from_message();
3226 test_WM_QUIT_handling();
3227 test_freethreadedmarshaler();
3228 test_inproc_handler();
3229 test_handler_marshaling();
3230 test_client_security();
3232 test_local_server();
3234 test_globalinterfacetable();
3235 test_manualresetevent();
3237 /* must be last test as channel hooks can't be unregistered */
3238 test_channel_hook();