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
33 #include "wine/test.h"
35 /* functions that are not present on all versions of Windows */
36 HRESULT (WINAPI
* pCoInitializeEx
)(LPVOID lpReserved
, DWORD dwCoInit
);
38 /* helper macros to make tests a bit leaner */
39 #define ok_more_than_one_lock() ok(cLocks > 0, "Number of locks should be > 0, but actually is %d\n", cLocks)
40 #define ok_no_locks() ok(cLocks == 0, "Number of locks should be 0, but actually is %d\n", cLocks)
41 #define ok_ole_success(hr, func) ok(hr == S_OK, #func " failed with error 0x%08x\n", hr)
43 static const IID IID_IWineTest
=
48 {0xa1, 0xa2, 0x5d, 0x5a, 0x36, 0x54, 0xd3, 0xbd}
49 }; /* 5201163f-8164-4fd0-a1a2-5d5a3654d3bd */
51 static const IID IID_IRemUnknown
=
56 {0xc0,0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46}
59 #define EXTENTID_WineTest IID_IWineTest
60 #define CLSID_WineTest IID_IWineTest
62 static const CLSID CLSID_WineOOPTest
=
67 {0xa1, 0xa2, 0x5d, 0x5a, 0x36, 0x54, 0xd3, 0xbd}
68 }; /* 5201163f-8164-4fd0-a1a2-5d5a3654d3bd */
70 static void test_cocreateinstance_proxy(void)
76 pCoInitializeEx(NULL
, COINIT_MULTITHREADED
);
78 hr
= CoCreateInstance(&CLSID_ShellDesktop
, NULL
, CLSCTX_INPROC
, &IID_IUnknown
, (void **)&pProxy
);
79 ok_ole_success(hr
, CoCreateInstance
);
80 hr
= IUnknown_QueryInterface(pProxy
, &IID_IMultiQI
, (void **)&pMQI
);
81 ok(hr
== S_OK
, "created object is not a proxy, so was created in the wrong apartment\n");
83 IMultiQI_Release(pMQI
);
84 IUnknown_Release(pProxy
);
89 static const LARGE_INTEGER ullZero
;
92 static void LockModule(void)
94 InterlockedIncrement(&cLocks
);
97 static void UnlockModule(void)
99 InterlockedDecrement(&cLocks
);
103 static HRESULT WINAPI
Test_IUnknown_QueryInterface(
108 if (ppvObj
== NULL
) return E_POINTER
;
110 if (IsEqualGUID(riid
, &IID_IUnknown
))
112 *ppvObj
= (LPVOID
)iface
;
113 IUnknown_AddRef(iface
);
118 return E_NOINTERFACE
;
121 static ULONG WINAPI
Test_IUnknown_AddRef(LPUNKNOWN iface
)
124 return 2; /* non-heap-based object */
127 static ULONG WINAPI
Test_IUnknown_Release(LPUNKNOWN iface
)
130 return 1; /* non-heap-based object */
133 static const IUnknownVtbl TestUnknown_Vtbl
=
135 Test_IUnknown_QueryInterface
,
136 Test_IUnknown_AddRef
,
137 Test_IUnknown_Release
,
140 static IUnknown Test_Unknown
= { &TestUnknown_Vtbl
};
143 static HRESULT WINAPI
Test_IClassFactory_QueryInterface(
144 LPCLASSFACTORY iface
,
148 if (ppvObj
== NULL
) return E_POINTER
;
150 if (IsEqualGUID(riid
, &IID_IUnknown
) ||
151 IsEqualGUID(riid
, &IID_IClassFactory
) ||
152 /* the only other interface Wine is currently able to marshal (for testing two proxies) */
153 IsEqualGUID(riid
, &IID_IRemUnknown
))
155 *ppvObj
= (LPVOID
)iface
;
156 IClassFactory_AddRef(iface
);
161 return E_NOINTERFACE
;
164 static ULONG WINAPI
Test_IClassFactory_AddRef(LPCLASSFACTORY iface
)
167 return 2; /* non-heap-based object */
170 static ULONG WINAPI
Test_IClassFactory_Release(LPCLASSFACTORY iface
)
173 return 1; /* non-heap-based object */
176 static HRESULT WINAPI
Test_IClassFactory_CreateInstance(
177 LPCLASSFACTORY iface
,
182 if (pUnkOuter
) return CLASS_E_NOAGGREGATION
;
183 return IUnknown_QueryInterface((IUnknown
*)&Test_Unknown
, riid
, ppvObj
);
186 static HRESULT WINAPI
Test_IClassFactory_LockServer(
187 LPCLASSFACTORY iface
,
193 static const IClassFactoryVtbl TestClassFactory_Vtbl
=
195 Test_IClassFactory_QueryInterface
,
196 Test_IClassFactory_AddRef
,
197 Test_IClassFactory_Release
,
198 Test_IClassFactory_CreateInstance
,
199 Test_IClassFactory_LockServer
202 static IClassFactory Test_ClassFactory
= { &TestClassFactory_Vtbl
};
204 #define RELEASEMARSHALDATA WM_USER
206 struct host_object_data
211 MSHLFLAGS marshal_flags
;
212 HANDLE marshal_event
;
213 IMessageFilter
*filter
;
216 static DWORD CALLBACK
host_object_proc(LPVOID p
)
218 struct host_object_data
*data
= (struct host_object_data
*)p
;
222 pCoInitializeEx(NULL
, COINIT_APARTMENTTHREADED
);
226 IMessageFilter
* prev_filter
= NULL
;
227 hr
= CoRegisterMessageFilter(data
->filter
, &prev_filter
);
228 if (prev_filter
) IMessageFilter_Release(prev_filter
);
229 ok_ole_success(hr
, CoRegisterMessageFilter
);
232 hr
= CoMarshalInterface(data
->stream
, &data
->iid
, data
->object
, MSHCTX_INPROC
, NULL
, data
->marshal_flags
);
233 ok_ole_success(hr
, CoMarshalInterface
);
235 /* force the message queue to be created before signaling parent thread */
236 PeekMessage(&msg
, NULL
, WM_USER
, WM_USER
, PM_NOREMOVE
);
238 SetEvent(data
->marshal_event
);
240 while (GetMessage(&msg
, NULL
, 0, 0))
242 if (msg
.hwnd
== NULL
&& msg
.message
== RELEASEMARSHALDATA
)
244 CoReleaseMarshalData(data
->stream
);
245 SetEvent((HANDLE
)msg
.lParam
);
248 DispatchMessage(&msg
);
251 HeapFree(GetProcessHeap(), 0, data
);
258 static DWORD
start_host_object2(IStream
*stream
, REFIID riid
, IUnknown
*object
, MSHLFLAGS marshal_flags
, IMessageFilter
*filter
, HANDLE
*thread
)
261 HANDLE marshal_event
= CreateEvent(NULL
, FALSE
, FALSE
, NULL
);
262 struct host_object_data
*data
= HeapAlloc(GetProcessHeap(), 0, sizeof(*data
));
264 data
->stream
= stream
;
266 data
->object
= object
;
267 data
->marshal_flags
= marshal_flags
;
268 data
->marshal_event
= marshal_event
;
269 data
->filter
= filter
;
271 *thread
= CreateThread(NULL
, 0, host_object_proc
, data
, 0, &tid
);
273 /* wait for marshaling to complete before returning */
274 WaitForSingleObject(marshal_event
, INFINITE
);
275 CloseHandle(marshal_event
);
280 static DWORD
start_host_object(IStream
*stream
, REFIID riid
, IUnknown
*object
, MSHLFLAGS marshal_flags
, HANDLE
*thread
)
282 return start_host_object2(stream
, riid
, object
, marshal_flags
, NULL
, thread
);
285 /* asks thread to release the marshal data because it has to be done by the
286 * same thread that marshaled the interface in the first place. */
287 static void release_host_object(DWORD tid
)
289 HANDLE event
= CreateEvent(NULL
, FALSE
, FALSE
, NULL
);
290 PostThreadMessage(tid
, RELEASEMARSHALDATA
, 0, (LPARAM
)event
);
291 WaitForSingleObject(event
, INFINITE
);
295 static void end_host_object(DWORD tid
, HANDLE thread
)
297 BOOL ret
= PostThreadMessage(tid
, WM_QUIT
, 0, 0);
298 ok(ret
, "PostThreadMessage failed with error %d\n", GetLastError());
299 /* be careful of races - don't return until hosting thread has terminated */
300 WaitForSingleObject(thread
, INFINITE
);
304 /* tests failure case of interface not having a marshaler specified in the
306 static void test_no_marshaler(void)
311 hr
= CreateStreamOnHGlobal(NULL
, TRUE
, &pStream
);
312 ok_ole_success(hr
, CreateStreamOnHGlobal
);
313 hr
= CoMarshalInterface(pStream
, &IID_IWineTest
, (IUnknown
*)&Test_ClassFactory
, MSHCTX_INPROC
, NULL
, MSHLFLAGS_NORMAL
);
314 ok(hr
== E_NOINTERFACE
, "CoMarshalInterface should have returned E_NOINTERFACE instead of 0x%08x\n", hr
);
316 IStream_Release(pStream
);
319 /* tests normal marshal and then release without unmarshaling */
320 static void test_normal_marshal_and_release(void)
323 IStream
*pStream
= NULL
;
327 hr
= CreateStreamOnHGlobal(NULL
, TRUE
, &pStream
);
328 ok_ole_success(hr
, CreateStreamOnHGlobal
);
329 hr
= CoMarshalInterface(pStream
, &IID_IClassFactory
, (IUnknown
*)&Test_ClassFactory
, MSHCTX_INPROC
, NULL
, MSHLFLAGS_NORMAL
);
330 ok_ole_success(hr
, CoMarshalInterface
);
332 ok_more_than_one_lock();
334 IStream_Seek(pStream
, ullZero
, STREAM_SEEK_SET
, NULL
);
335 hr
= CoReleaseMarshalData(pStream
);
336 ok_ole_success(hr
, CoReleaseMarshalData
);
337 IStream_Release(pStream
);
342 /* tests success case of a same-thread marshal and unmarshal */
343 static void test_normal_marshal_and_unmarshal(void)
346 IStream
*pStream
= NULL
;
347 IUnknown
*pProxy
= NULL
;
351 hr
= CreateStreamOnHGlobal(NULL
, TRUE
, &pStream
);
352 ok_ole_success(hr
, CreateStreamOnHGlobal
);
353 hr
= CoMarshalInterface(pStream
, &IID_IClassFactory
, (IUnknown
*)&Test_ClassFactory
, MSHCTX_INPROC
, NULL
, MSHLFLAGS_NORMAL
);
354 ok_ole_success(hr
, CoMarshalInterface
);
356 ok_more_than_one_lock();
358 IStream_Seek(pStream
, ullZero
, STREAM_SEEK_SET
, NULL
);
359 hr
= CoUnmarshalInterface(pStream
, &IID_IClassFactory
, (void **)&pProxy
);
360 ok_ole_success(hr
, CoUnmarshalInterface
);
361 IStream_Release(pStream
);
363 ok_more_than_one_lock();
365 IUnknown_Release(pProxy
);
370 /* tests failure case of unmarshaling a freed object */
371 static void test_marshal_and_unmarshal_invalid(void)
374 IStream
*pStream
= NULL
;
375 IClassFactory
*pProxy
= NULL
;
382 hr
= CreateStreamOnHGlobal(NULL
, TRUE
, &pStream
);
383 ok_ole_success(hr
, CreateStreamOnHGlobal
);
384 tid
= start_host_object(pStream
, &IID_IClassFactory
, (IUnknown
*)&Test_ClassFactory
, MSHLFLAGS_NORMAL
, &thread
);
386 ok_more_than_one_lock();
388 IStream_Seek(pStream
, ullZero
, STREAM_SEEK_SET
, NULL
);
389 hr
= CoReleaseMarshalData(pStream
);
390 ok_ole_success(hr
, CoReleaseMarshalData
);
394 IStream_Seek(pStream
, ullZero
, STREAM_SEEK_SET
, NULL
);
395 hr
= CoUnmarshalInterface(pStream
, &IID_IClassFactory
, (void **)&pProxy
);
396 todo_wine
{ ok_ole_success(hr
, CoUnmarshalInterface
); }
402 hr
= IClassFactory_CreateInstance(pProxy
, NULL
, &IID_IUnknown
, &dummy
);
403 ok(hr
== RPC_E_DISCONNECTED
, "Remote call should have returned RPC_E_DISCONNECTED, instead of 0x%08x\n", hr
);
405 IClassFactory_Release(pProxy
);
408 IStream_Release(pStream
);
410 end_host_object(tid
, thread
);
413 static void test_same_apartment_unmarshal_failure(void)
418 static const LARGE_INTEGER llZero
;
422 hr
= CreateStreamOnHGlobal(NULL
, TRUE
, &pStream
);
423 ok_ole_success(hr
, CreateStreamOnHGlobal
);
425 hr
= CoMarshalInterface(pStream
, &IID_IUnknown
, (IUnknown
*)&Test_ClassFactory
, MSHCTX_INPROC
, NULL
, MSHLFLAGS_NORMAL
);
426 ok_ole_success(hr
, CoMarshalInterface
);
428 ok_more_than_one_lock();
430 hr
= IStream_Seek(pStream
, llZero
, STREAM_SEEK_SET
, NULL
);
431 ok_ole_success(hr
, IStream_Seek
);
433 hr
= CoUnmarshalInterface(pStream
, &IID_IParseDisplayName
, (void **)&pProxy
);
434 ok(hr
== E_NOINTERFACE
, "CoUnmarshalInterface should have returned E_NOINTERFACE instead of 0x%08x\n", hr
);
439 /* tests success case of an interthread marshal */
440 static void test_interthread_marshal_and_unmarshal(void)
443 IStream
*pStream
= NULL
;
444 IUnknown
*pProxy
= NULL
;
450 hr
= CreateStreamOnHGlobal(NULL
, TRUE
, &pStream
);
451 ok_ole_success(hr
, CreateStreamOnHGlobal
);
452 tid
= start_host_object(pStream
, &IID_IClassFactory
, (IUnknown
*)&Test_ClassFactory
, MSHLFLAGS_NORMAL
, &thread
);
454 ok_more_than_one_lock();
456 IStream_Seek(pStream
, ullZero
, STREAM_SEEK_SET
, NULL
);
457 hr
= CoUnmarshalInterface(pStream
, &IID_IClassFactory
, (void **)&pProxy
);
458 ok_ole_success(hr
, CoUnmarshalInterface
);
459 IStream_Release(pStream
);
461 ok_more_than_one_lock();
463 IUnknown_Release(pProxy
);
467 end_host_object(tid
, thread
);
470 /* the number of external references that Wine's proxy manager normally gives
471 * out, so we can test the border case of running out of references */
472 #define NORMALEXTREFS 5
474 /* tests success case of an interthread marshal and then marshaling the proxy */
475 static void test_proxy_marshal_and_unmarshal(void)
478 IStream
*pStream
= NULL
;
479 IUnknown
*pProxy
= NULL
;
480 IUnknown
*pProxy2
= NULL
;
487 hr
= CreateStreamOnHGlobal(NULL
, TRUE
, &pStream
);
488 ok_ole_success(hr
, CreateStreamOnHGlobal
);
489 tid
= start_host_object(pStream
, &IID_IClassFactory
, (IUnknown
*)&Test_ClassFactory
, MSHLFLAGS_NORMAL
, &thread
);
491 ok_more_than_one_lock();
493 IStream_Seek(pStream
, ullZero
, STREAM_SEEK_SET
, NULL
);
494 hr
= CoUnmarshalInterface(pStream
, &IID_IClassFactory
, (void **)&pProxy
);
495 ok_ole_success(hr
, CoUnmarshalInterface
);
497 ok_more_than_one_lock();
499 IStream_Seek(pStream
, ullZero
, STREAM_SEEK_SET
, NULL
);
500 /* marshal the proxy */
501 hr
= CoMarshalInterface(pStream
, &IID_IClassFactory
, pProxy
, MSHCTX_INPROC
, NULL
, MSHLFLAGS_NORMAL
);
502 ok_ole_success(hr
, CoMarshalInterface
);
504 ok_more_than_one_lock();
506 /* marshal 5 more times to exhaust the normal external references of 5 */
507 for (i
= 0; i
< NORMALEXTREFS
; i
++)
509 hr
= CoMarshalInterface(pStream
, &IID_IClassFactory
, pProxy
, MSHCTX_INPROC
, NULL
, MSHLFLAGS_NORMAL
);
510 ok_ole_success(hr
, CoMarshalInterface
);
513 ok_more_than_one_lock();
515 /* release the original proxy to test that we successfully keep the
516 * original object alive */
517 IUnknown_Release(pProxy
);
519 IStream_Seek(pStream
, ullZero
, STREAM_SEEK_SET
, NULL
);
520 hr
= CoUnmarshalInterface(pStream
, &IID_IClassFactory
, (void **)&pProxy2
);
521 ok_ole_success(hr
, CoUnmarshalInterface
);
523 ok_more_than_one_lock();
525 IUnknown_Release(pProxy2
);
527 /* unmarshal all of the proxies to check that the object stub still exists */
528 for (i
= 0; i
< NORMALEXTREFS
; i
++)
530 hr
= CoUnmarshalInterface(pStream
, &IID_IClassFactory
, (void **)&pProxy2
);
531 ok_ole_success(hr
, CoUnmarshalInterface
);
533 IUnknown_Release(pProxy2
);
538 IStream_Release(pStream
);
540 end_host_object(tid
, thread
);
543 /* tests success case of an interthread marshal and then marshaling the proxy
544 * using an iid that hasn't previously been unmarshaled */
545 static void test_proxy_marshal_and_unmarshal2(void)
548 IStream
*pStream
= NULL
;
549 IUnknown
*pProxy
= NULL
;
550 IUnknown
*pProxy2
= NULL
;
556 hr
= CreateStreamOnHGlobal(NULL
, TRUE
, &pStream
);
557 ok_ole_success(hr
, CreateStreamOnHGlobal
);
558 tid
= start_host_object(pStream
, &IID_IUnknown
, (IUnknown
*)&Test_ClassFactory
, MSHLFLAGS_NORMAL
, &thread
);
560 ok_more_than_one_lock();
562 IStream_Seek(pStream
, ullZero
, STREAM_SEEK_SET
, NULL
);
563 hr
= CoUnmarshalInterface(pStream
, &IID_IUnknown
, (void **)&pProxy
);
564 ok_ole_success(hr
, CoUnmarshalInterface
);
566 ok_more_than_one_lock();
568 IStream_Seek(pStream
, ullZero
, STREAM_SEEK_SET
, NULL
);
569 /* marshal the proxy */
570 hr
= CoMarshalInterface(pStream
, &IID_IClassFactory
, pProxy
, MSHCTX_INPROC
, NULL
, MSHLFLAGS_NORMAL
);
571 ok_ole_success(hr
, CoMarshalInterface
);
573 ok_more_than_one_lock();
575 IStream_Seek(pStream
, ullZero
, STREAM_SEEK_SET
, NULL
);
576 /* unmarshal the second proxy to the object */
577 hr
= CoUnmarshalInterface(pStream
, &IID_IClassFactory
, (void **)&pProxy2
);
578 ok_ole_success(hr
, CoUnmarshalInterface
);
579 IStream_Release(pStream
);
581 /* now the proxies should be as follows:
582 * pProxy -> &Test_ClassFactory
583 * pProxy2 -> &Test_ClassFactory
584 * they should NOT be as follows:
585 * pProxy -> &Test_ClassFactory
587 * the above can only really be tested by looking in +ole traces
590 ok_more_than_one_lock();
592 IUnknown_Release(pProxy
);
594 ok_more_than_one_lock();
596 IUnknown_Release(pProxy2
);
600 end_host_object(tid
, thread
);
603 /* tests success case of an interthread marshal and then table-weak-marshaling the proxy */
604 static void test_proxy_marshal_and_unmarshal_weak(void)
607 IStream
*pStream
= NULL
;
608 IUnknown
*pProxy
= NULL
;
609 IUnknown
*pProxy2
= NULL
;
615 hr
= CreateStreamOnHGlobal(NULL
, TRUE
, &pStream
);
616 ok_ole_success(hr
, CreateStreamOnHGlobal
);
617 tid
= start_host_object(pStream
, &IID_IClassFactory
, (IUnknown
*)&Test_ClassFactory
, MSHLFLAGS_NORMAL
, &thread
);
619 ok_more_than_one_lock();
621 IStream_Seek(pStream
, ullZero
, STREAM_SEEK_SET
, NULL
);
622 hr
= CoUnmarshalInterface(pStream
, &IID_IClassFactory
, (void **)&pProxy
);
623 ok_ole_success(hr
, CoUnmarshalInterface
);
625 ok_more_than_one_lock();
627 IStream_Seek(pStream
, ullZero
, STREAM_SEEK_SET
, NULL
);
628 /* marshal the proxy */
629 hr
= CoMarshalInterface(pStream
, &IID_IClassFactory
, pProxy
, MSHCTX_INPROC
, NULL
, MSHLFLAGS_TABLEWEAK
);
630 ok_ole_success(hr
, CoMarshalInterface
);
632 ok_more_than_one_lock();
634 /* release the original proxy to test that we successfully keep the
635 * original object alive */
636 IUnknown_Release(pProxy
);
638 IStream_Seek(pStream
, ullZero
, STREAM_SEEK_SET
, NULL
);
639 hr
= CoUnmarshalInterface(pStream
, &IID_IClassFactory
, (void **)&pProxy2
);
641 ok(hr
== CO_E_OBJNOTREG
, "CoUnmarshalInterface should return CO_E_OBJNOTREG instead of 0x%08x\n", hr
);
645 IStream_Release(pStream
);
647 end_host_object(tid
, thread
);
650 /* tests success case of an interthread marshal and then table-strong-marshaling the proxy */
651 static void test_proxy_marshal_and_unmarshal_strong(void)
654 IStream
*pStream
= NULL
;
655 IUnknown
*pProxy
= NULL
;
656 IUnknown
*pProxy2
= NULL
;
662 hr
= CreateStreamOnHGlobal(NULL
, TRUE
, &pStream
);
663 ok_ole_success(hr
, CreateStreamOnHGlobal
);
664 tid
= start_host_object(pStream
, &IID_IClassFactory
, (IUnknown
*)&Test_ClassFactory
, MSHLFLAGS_NORMAL
, &thread
);
666 ok_more_than_one_lock();
668 IStream_Seek(pStream
, ullZero
, STREAM_SEEK_SET
, NULL
);
669 hr
= CoUnmarshalInterface(pStream
, &IID_IClassFactory
, (void **)&pProxy
);
670 ok_ole_success(hr
, CoUnmarshalInterface
);
672 ok_more_than_one_lock();
674 IStream_Seek(pStream
, ullZero
, STREAM_SEEK_SET
, NULL
);
675 /* marshal the proxy */
676 hr
= CoMarshalInterface(pStream
, &IID_IClassFactory
, pProxy
, MSHCTX_INPROC
, NULL
, MSHLFLAGS_TABLESTRONG
);
677 ok(hr
== S_OK
/* WinNT */ || hr
== E_INVALIDARG
/* Win9x */,
678 "CoMarshalInterface should have return S_OK or E_INVALIDARG instead of 0x%08x\n", hr
);
681 IUnknown_Release(pProxy
);
685 ok_more_than_one_lock();
687 /* release the original proxy to test that we successfully keep the
688 * original object alive */
689 IUnknown_Release(pProxy
);
691 IStream_Seek(pStream
, ullZero
, STREAM_SEEK_SET
, NULL
);
692 hr
= CoUnmarshalInterface(pStream
, &IID_IClassFactory
, (void **)&pProxy2
);
693 ok_ole_success(hr
, CoUnmarshalInterface
);
695 ok_more_than_one_lock();
697 IUnknown_Release(pProxy2
);
699 ok_more_than_one_lock();
702 IStream_Release(pStream
);
704 end_host_object(tid
, thread
);
709 /* tests that stubs are released when the containing apartment is destroyed */
710 static void test_marshal_stub_apartment_shutdown(void)
713 IStream
*pStream
= NULL
;
714 IUnknown
*pProxy
= NULL
;
720 hr
= CreateStreamOnHGlobal(NULL
, TRUE
, &pStream
);
721 ok_ole_success(hr
, CreateStreamOnHGlobal
);
722 tid
= start_host_object(pStream
, &IID_IClassFactory
, (IUnknown
*)&Test_ClassFactory
, MSHLFLAGS_NORMAL
, &thread
);
724 ok_more_than_one_lock();
726 IStream_Seek(pStream
, ullZero
, STREAM_SEEK_SET
, NULL
);
727 hr
= CoUnmarshalInterface(pStream
, &IID_IClassFactory
, (void **)&pProxy
);
728 ok_ole_success(hr
, CoUnmarshalInterface
);
729 IStream_Release(pStream
);
731 ok_more_than_one_lock();
733 end_host_object(tid
, thread
);
737 IUnknown_Release(pProxy
);
742 /* tests that proxies are released when the containing apartment is destroyed */
743 static void test_marshal_proxy_apartment_shutdown(void)
746 IStream
*pStream
= NULL
;
747 IUnknown
*pProxy
= NULL
;
753 hr
= CreateStreamOnHGlobal(NULL
, TRUE
, &pStream
);
754 ok_ole_success(hr
, CreateStreamOnHGlobal
);
755 tid
= start_host_object(pStream
, &IID_IClassFactory
, (IUnknown
*)&Test_ClassFactory
, MSHLFLAGS_NORMAL
, &thread
);
757 ok_more_than_one_lock();
759 IStream_Seek(pStream
, ullZero
, STREAM_SEEK_SET
, NULL
);
760 hr
= CoUnmarshalInterface(pStream
, &IID_IClassFactory
, (void **)&pProxy
);
761 ok_ole_success(hr
, CoUnmarshalInterface
);
762 IStream_Release(pStream
);
764 ok_more_than_one_lock();
770 IUnknown_Release(pProxy
);
774 end_host_object(tid
, thread
);
776 pCoInitializeEx(NULL
, COINIT_APARTMENTTHREADED
);
779 /* tests that proxies are released when the containing mta apartment is destroyed */
780 static void test_marshal_proxy_mta_apartment_shutdown(void)
783 IStream
*pStream
= NULL
;
784 IUnknown
*pProxy
= NULL
;
789 pCoInitializeEx(NULL
, COINIT_MULTITHREADED
);
793 hr
= CreateStreamOnHGlobal(NULL
, TRUE
, &pStream
);
794 ok_ole_success(hr
, CreateStreamOnHGlobal
);
795 tid
= start_host_object(pStream
, &IID_IClassFactory
, (IUnknown
*)&Test_ClassFactory
, MSHLFLAGS_NORMAL
, &thread
);
797 ok_more_than_one_lock();
799 IStream_Seek(pStream
, ullZero
, STREAM_SEEK_SET
, NULL
);
800 hr
= CoUnmarshalInterface(pStream
, &IID_IClassFactory
, (void **)&pProxy
);
801 ok_ole_success(hr
, CoUnmarshalInterface
);
802 IStream_Release(pStream
);
804 ok_more_than_one_lock();
810 IUnknown_Release(pProxy
);
814 end_host_object(tid
, thread
);
816 pCoInitializeEx(NULL
, COINIT_APARTMENTTHREADED
);
822 HANDLE marshal_event
;
823 HANDLE unmarshal_event
;
826 /* helper for test_no_couninitialize_server */
827 static DWORD CALLBACK
no_couninitialize_server_proc(LPVOID p
)
829 struct ncu_params
*ncu_params
= (struct ncu_params
*)p
;
832 pCoInitializeEx(NULL
, COINIT_MULTITHREADED
);
834 hr
= CoMarshalInterface(ncu_params
->stream
, &IID_IClassFactory
, (IUnknown
*)&Test_ClassFactory
, MSHCTX_INPROC
, NULL
, MSHLFLAGS_NORMAL
);
835 ok_ole_success(hr
, CoMarshalInterface
);
837 SetEvent(ncu_params
->marshal_event
);
839 WaitForSingleObject(ncu_params
->unmarshal_event
, INFINITE
);
841 /* die without calling CoUninitialize */
846 /* tests apartment that an apartment with a stub is released without deadlock
847 * if the owning thread exits */
848 static void test_no_couninitialize_server(void)
851 IStream
*pStream
= NULL
;
852 IUnknown
*pProxy
= NULL
;
855 struct ncu_params ncu_params
;
859 ncu_params
.marshal_event
= CreateEvent(NULL
, TRUE
, FALSE
, NULL
);
860 ncu_params
.unmarshal_event
= CreateEvent(NULL
, TRUE
, FALSE
, NULL
);
862 hr
= CreateStreamOnHGlobal(NULL
, TRUE
, &pStream
);
863 ok_ole_success(hr
, CreateStreamOnHGlobal
);
864 ncu_params
.stream
= pStream
;
866 thread
= CreateThread(NULL
, 0, no_couninitialize_server_proc
, &ncu_params
, 0, &tid
);
868 WaitForSingleObject(ncu_params
.marshal_event
, INFINITE
);
869 ok_more_than_one_lock();
871 IStream_Seek(pStream
, ullZero
, STREAM_SEEK_SET
, NULL
);
872 hr
= CoUnmarshalInterface(pStream
, &IID_IClassFactory
, (void **)&pProxy
);
873 ok_ole_success(hr
, CoUnmarshalInterface
);
874 IStream_Release(pStream
);
876 ok_more_than_one_lock();
878 SetEvent(ncu_params
.unmarshal_event
);
879 WaitForSingleObject(thread
, INFINITE
);
884 CloseHandle(ncu_params
.marshal_event
);
885 CloseHandle(ncu_params
.unmarshal_event
);
887 IUnknown_Release(pProxy
);
892 /* STA -> STA call during DLL_THREAD_DETACH */
893 static DWORD CALLBACK
no_couninitialize_client_proc(LPVOID p
)
895 struct ncu_params
*ncu_params
= (struct ncu_params
*)p
;
897 IUnknown
*pProxy
= NULL
;
899 pCoInitializeEx(NULL
, COINIT_APARTMENTTHREADED
);
901 hr
= CoUnmarshalInterface(ncu_params
->stream
, &IID_IClassFactory
, (void **)&pProxy
);
902 ok_ole_success(hr
, CoUnmarshalInterface
);
903 IStream_Release(ncu_params
->stream
);
905 ok_more_than_one_lock();
907 /* die without calling CoUninitialize */
912 /* tests STA -> STA call during DLL_THREAD_DETACH doesn't deadlock */
913 static void test_no_couninitialize_client(void)
916 IStream
*pStream
= NULL
;
921 struct ncu_params ncu_params
;
925 hr
= CreateStreamOnHGlobal(NULL
, TRUE
, &pStream
);
926 ok_ole_success(hr
, CreateStreamOnHGlobal
);
927 ncu_params
.stream
= pStream
;
929 /* NOTE: assumes start_host_object uses an STA to host the object, as MTAs
930 * always deadlock when called from within DllMain */
931 host_tid
= start_host_object(pStream
, &IID_IClassFactory
, (IUnknown
*)&Test_ClassFactory
, MSHLFLAGS_NORMAL
, &host_thread
);
932 IStream_Seek(pStream
, ullZero
, STREAM_SEEK_SET
, NULL
);
934 ok_more_than_one_lock();
936 thread
= CreateThread(NULL
, 0, no_couninitialize_client_proc
, &ncu_params
, 0, &tid
);
938 WaitForSingleObject(thread
, INFINITE
);
943 end_host_object(host_tid
, host_thread
);
946 /* tests success case of a same-thread table-weak marshal, unmarshal, unmarshal */
947 static void test_tableweak_marshal_and_unmarshal_twice(void)
950 IStream
*pStream
= NULL
;
951 IUnknown
*pProxy1
= NULL
;
952 IUnknown
*pProxy2
= NULL
;
958 hr
= CreateStreamOnHGlobal(NULL
, TRUE
, &pStream
);
959 ok_ole_success(hr
, CreateStreamOnHGlobal
);
960 tid
= start_host_object(pStream
, &IID_IClassFactory
, (IUnknown
*)&Test_ClassFactory
, MSHLFLAGS_TABLEWEAK
, &thread
);
962 ok_more_than_one_lock();
964 IStream_Seek(pStream
, ullZero
, STREAM_SEEK_SET
, NULL
);
965 hr
= CoUnmarshalInterface(pStream
, &IID_IClassFactory
, (void **)&pProxy1
);
966 ok_ole_success(hr
, CoUnmarshalInterface
);
968 ok_more_than_one_lock();
970 IStream_Seek(pStream
, ullZero
, STREAM_SEEK_SET
, NULL
);
971 hr
= CoUnmarshalInterface(pStream
, &IID_IClassFactory
, (void **)&pProxy2
);
972 IStream_Release(pStream
);
973 ok_ole_success(hr
, CoUnmarshalInterface
);
975 ok_more_than_one_lock();
977 IUnknown_Release(pProxy1
);
978 IUnknown_Release(pProxy2
);
980 /* this line is shows the difference between weak and strong table marshaling:
981 * weak has cLocks == 0
982 * strong has cLocks > 0 */
985 end_host_object(tid
, thread
);
988 /* tests releasing after unmarshaling one object */
989 static void test_tableweak_marshal_releasedata1(void)
992 IStream
*pStream
= NULL
;
993 IUnknown
*pProxy1
= NULL
;
994 IUnknown
*pProxy2
= NULL
;
1000 hr
= CreateStreamOnHGlobal(NULL
, TRUE
, &pStream
);
1001 ok_ole_success(hr
, CreateStreamOnHGlobal
);
1002 tid
= start_host_object(pStream
, &IID_IClassFactory
, (IUnknown
*)&Test_ClassFactory
, MSHLFLAGS_TABLEWEAK
, &thread
);
1004 ok_more_than_one_lock();
1006 IStream_Seek(pStream
, ullZero
, STREAM_SEEK_SET
, NULL
);
1007 hr
= CoUnmarshalInterface(pStream
, &IID_IClassFactory
, (void **)&pProxy1
);
1008 ok_ole_success(hr
, CoUnmarshalInterface
);
1010 ok_more_than_one_lock();
1012 /* release the remaining reference on the object by calling
1013 * CoReleaseMarshalData in the hosting thread */
1014 IStream_Seek(pStream
, ullZero
, STREAM_SEEK_SET
, NULL
);
1015 release_host_object(tid
);
1017 ok_more_than_one_lock();
1019 IStream_Seek(pStream
, ullZero
, STREAM_SEEK_SET
, NULL
);
1020 hr
= CoUnmarshalInterface(pStream
, &IID_IClassFactory
, (void **)&pProxy2
);
1021 ok_ole_success(hr
, CoUnmarshalInterface
);
1022 IStream_Release(pStream
);
1024 ok_more_than_one_lock();
1026 IUnknown_Release(pProxy1
);
1028 IUnknown_Release(pProxy2
);
1030 /* this line is shows the difference between weak and strong table marshaling:
1031 * weak has cLocks == 0
1032 * strong has cLocks > 0 */
1035 end_host_object(tid
, thread
);
1038 /* tests releasing after unmarshaling one object */
1039 static void test_tableweak_marshal_releasedata2(void)
1042 IStream
*pStream
= NULL
;
1043 IUnknown
*pProxy
= NULL
;
1049 hr
= CreateStreamOnHGlobal(NULL
, TRUE
, &pStream
);
1050 ok_ole_success(hr
, CreateStreamOnHGlobal
);
1051 tid
= start_host_object(pStream
, &IID_IClassFactory
, (IUnknown
*)&Test_ClassFactory
, MSHLFLAGS_TABLEWEAK
, &thread
);
1053 ok_more_than_one_lock();
1055 /* release the remaining reference on the object by calling
1056 * CoReleaseMarshalData in the hosting thread */
1057 IStream_Seek(pStream
, ullZero
, STREAM_SEEK_SET
, NULL
);
1058 release_host_object(tid
);
1062 IStream_Seek(pStream
, ullZero
, STREAM_SEEK_SET
, NULL
);
1063 hr
= CoUnmarshalInterface(pStream
, &IID_IClassFactory
, (void **)&pProxy
);
1066 ok(hr
== CO_E_OBJNOTREG
,
1067 "CoUnmarshalInterface should have failed with CO_E_OBJNOTREG, but returned 0x%08x instead\n",
1070 IStream_Release(pStream
);
1074 end_host_object(tid
, thread
);
1077 /* tests success case of a same-thread table-strong marshal, unmarshal, unmarshal */
1078 static void test_tablestrong_marshal_and_unmarshal_twice(void)
1081 IStream
*pStream
= NULL
;
1082 IUnknown
*pProxy1
= NULL
;
1083 IUnknown
*pProxy2
= NULL
;
1089 hr
= CreateStreamOnHGlobal(NULL
, TRUE
, &pStream
);
1090 ok_ole_success(hr
, CreateStreamOnHGlobal
);
1091 tid
= start_host_object(pStream
, &IID_IClassFactory
, (IUnknown
*)&Test_ClassFactory
, MSHLFLAGS_TABLESTRONG
, &thread
);
1093 ok_more_than_one_lock();
1095 IStream_Seek(pStream
, ullZero
, STREAM_SEEK_SET
, NULL
);
1096 hr
= CoUnmarshalInterface(pStream
, &IID_IClassFactory
, (void **)&pProxy1
);
1097 ok_ole_success(hr
, CoUnmarshalInterface
);
1099 ok_more_than_one_lock();
1101 IStream_Seek(pStream
, ullZero
, STREAM_SEEK_SET
, NULL
);
1102 hr
= CoUnmarshalInterface(pStream
, &IID_IClassFactory
, (void **)&pProxy2
);
1103 ok_ole_success(hr
, CoUnmarshalInterface
);
1105 ok_more_than_one_lock();
1107 if (pProxy1
) IUnknown_Release(pProxy1
);
1108 if (pProxy2
) IUnknown_Release(pProxy2
);
1110 /* this line is shows the difference between weak and strong table marshaling:
1111 * weak has cLocks == 0
1112 * strong has cLocks > 0 */
1113 ok_more_than_one_lock();
1115 /* release the remaining reference on the object by calling
1116 * CoReleaseMarshalData in the hosting thread */
1117 IStream_Seek(pStream
, ullZero
, STREAM_SEEK_SET
, NULL
);
1118 release_host_object(tid
);
1119 IStream_Release(pStream
);
1123 end_host_object(tid
, thread
);
1126 /* tests CoLockObjectExternal */
1127 static void test_lock_object_external(void)
1130 IStream
*pStream
= NULL
;
1134 /* test the stub manager creation aspect of CoLockObjectExternal when the
1135 * object hasn't been marshaled yet */
1136 CoLockObjectExternal((IUnknown
*)&Test_ClassFactory
, TRUE
, TRUE
);
1138 ok_more_than_one_lock();
1140 CoDisconnectObject((IUnknown
*)&Test_ClassFactory
, 0);
1144 /* test our empty stub manager being handled correctly in
1145 * CoMarshalInterface */
1146 CoLockObjectExternal((IUnknown
*)&Test_ClassFactory
, TRUE
, TRUE
);
1148 hr
= CreateStreamOnHGlobal(NULL
, TRUE
, &pStream
);
1149 ok_ole_success(hr
, CreateStreamOnHGlobal
);
1150 hr
= CoMarshalInterface(pStream
, &IID_IClassFactory
, (IUnknown
*)&Test_ClassFactory
, MSHCTX_INPROC
, NULL
, MSHLFLAGS_NORMAL
);
1151 ok_ole_success(hr
, CoMarshalInterface
);
1153 CoLockObjectExternal((IUnknown
*)&Test_ClassFactory
, TRUE
, TRUE
);
1155 ok_more_than_one_lock();
1157 IStream_Seek(pStream
, ullZero
, STREAM_SEEK_SET
, NULL
);
1158 hr
= CoReleaseMarshalData(pStream
);
1159 ok_ole_success(hr
, CoReleaseMarshalData
);
1160 IStream_Release(pStream
);
1162 ok_more_than_one_lock();
1164 CoLockObjectExternal((IUnknown
*)&Test_ClassFactory
, FALSE
, TRUE
);
1166 ok_more_than_one_lock();
1168 CoLockObjectExternal((IUnknown
*)&Test_ClassFactory
, FALSE
, TRUE
);
1173 /* tests disconnecting stubs */
1174 static void test_disconnect_stub(void)
1177 IStream
*pStream
= NULL
;
1181 hr
= CreateStreamOnHGlobal(NULL
, TRUE
, &pStream
);
1182 ok_ole_success(hr
, CreateStreamOnHGlobal
);
1183 hr
= CoMarshalInterface(pStream
, &IID_IClassFactory
, (IUnknown
*)&Test_ClassFactory
, MSHCTX_INPROC
, NULL
, MSHLFLAGS_NORMAL
);
1184 ok_ole_success(hr
, CoMarshalInterface
);
1186 CoLockObjectExternal((IUnknown
*)&Test_ClassFactory
, TRUE
, TRUE
);
1188 ok_more_than_one_lock();
1190 IStream_Seek(pStream
, ullZero
, STREAM_SEEK_SET
, NULL
);
1191 hr
= CoReleaseMarshalData(pStream
);
1192 ok_ole_success(hr
, CoReleaseMarshalData
);
1193 IStream_Release(pStream
);
1195 ok_more_than_one_lock();
1197 CoDisconnectObject((IUnknown
*)&Test_ClassFactory
, 0);
1202 /* tests failure case of a same-thread marshal and unmarshal twice */
1203 static void test_normal_marshal_and_unmarshal_twice(void)
1206 IStream
*pStream
= NULL
;
1207 IUnknown
*pProxy1
= NULL
;
1208 IUnknown
*pProxy2
= NULL
;
1212 hr
= CreateStreamOnHGlobal(NULL
, TRUE
, &pStream
);
1213 ok_ole_success(hr
, CreateStreamOnHGlobal
);
1214 hr
= CoMarshalInterface(pStream
, &IID_IClassFactory
, (IUnknown
*)&Test_ClassFactory
, MSHCTX_INPROC
, NULL
, MSHLFLAGS_NORMAL
);
1215 ok_ole_success(hr
, CoMarshalInterface
);
1217 ok_more_than_one_lock();
1219 IStream_Seek(pStream
, ullZero
, STREAM_SEEK_SET
, NULL
);
1220 hr
= CoUnmarshalInterface(pStream
, &IID_IClassFactory
, (void **)&pProxy1
);
1221 ok_ole_success(hr
, CoUnmarshalInterface
);
1223 ok_more_than_one_lock();
1225 IStream_Seek(pStream
, ullZero
, STREAM_SEEK_SET
, NULL
);
1226 hr
= CoUnmarshalInterface(pStream
, &IID_IClassFactory
, (void **)&pProxy2
);
1227 ok(hr
== CO_E_OBJNOTCONNECTED
,
1228 "CoUnmarshalInterface should have failed with error CO_E_OBJNOTCONNECTED for double unmarshal, instead of 0x%08x\n", hr
);
1230 IStream_Release(pStream
);
1232 ok_more_than_one_lock();
1234 IUnknown_Release(pProxy1
);
1239 /* tests success case of marshaling and unmarshaling an HRESULT */
1240 static void test_hresult_marshaling(void)
1243 HRESULT hr_marshaled
= 0;
1244 IStream
*pStream
= NULL
;
1245 static const HRESULT E_DEADBEEF
= 0xdeadbeef;
1247 hr
= CreateStreamOnHGlobal(NULL
, TRUE
, &pStream
);
1248 ok_ole_success(hr
, CreateStreamOnHGlobal
);
1250 hr
= CoMarshalHresult(pStream
, E_DEADBEEF
);
1251 ok_ole_success(hr
, CoMarshalHresult
);
1253 IStream_Seek(pStream
, ullZero
, STREAM_SEEK_SET
, NULL
);
1254 hr
= IStream_Read(pStream
, &hr_marshaled
, sizeof(HRESULT
), NULL
);
1255 ok_ole_success(hr
, IStream_Read
);
1257 ok(hr_marshaled
== E_DEADBEEF
, "Didn't marshal HRESULT as expected: got value 0x%08x instead\n", hr_marshaled
);
1260 IStream_Seek(pStream
, ullZero
, STREAM_SEEK_SET
, NULL
);
1261 hr
= CoUnmarshalHresult(pStream
, &hr_marshaled
);
1262 ok_ole_success(hr
, CoUnmarshalHresult
);
1264 ok(hr_marshaled
== E_DEADBEEF
, "Didn't marshal HRESULT as expected: got value 0x%08x instead\n", hr_marshaled
);
1266 IStream_Release(pStream
);
1270 /* helper for test_proxy_used_in_wrong_thread */
1271 static DWORD CALLBACK
bad_thread_proc(LPVOID p
)
1273 IClassFactory
* cf
= (IClassFactory
*)p
;
1275 IUnknown
* proxy
= NULL
;
1277 hr
= IClassFactory_CreateInstance(cf
, NULL
, &IID_IUnknown
, (LPVOID
*)&proxy
);
1279 ok(hr
== CO_E_NOTINITIALIZED
,
1280 "COM should have failed with CO_E_NOTINITIALIZED on using proxy without apartment, but instead returned 0x%08x\n",
1283 hr
= IClassFactory_QueryInterface(cf
, &IID_IMultiQI
, (LPVOID
*)&proxy
);
1284 /* Win9x returns S_OK, whilst NT returns RPC_E_WRONG_THREAD */
1285 trace("call to proxy's QueryInterface for local interface without apartment returned 0x%08x\n", hr
);
1287 IUnknown_Release(proxy
);
1289 hr
= IClassFactory_QueryInterface(cf
, &IID_IStream
, (LPVOID
*)&proxy
);
1290 /* Win9x returns E_NOINTERFACE, whilst NT returns RPC_E_WRONG_THREAD */
1291 trace("call to proxy's QueryInterface without apartment returned 0x%08x\n", hr
);
1293 IUnknown_Release(proxy
);
1295 pCoInitializeEx(NULL
, COINIT_MULTITHREADED
);
1297 hr
= IClassFactory_CreateInstance(cf
, NULL
, &IID_IUnknown
, (LPVOID
*)&proxy
);
1298 if (proxy
) IUnknown_Release(proxy
);
1299 ok(hr
== RPC_E_WRONG_THREAD
,
1300 "COM should have failed with RPC_E_WRONG_THREAD on using proxy from wrong apartment, but instead returned 0x%08x\n",
1303 hr
= IClassFactory_QueryInterface(cf
, &IID_IStream
, (LPVOID
*)&proxy
);
1304 /* Win9x returns E_NOINTERFACE, whilst NT returns RPC_E_WRONG_THREAD */
1305 trace("call to proxy's QueryInterface from wrong apartment returned 0x%08x\n", hr
);
1307 /* this statement causes Win9x DCOM to crash during CoUninitialize of
1308 * other apartment, so don't test this on Win9x (signified by NT-only
1309 * export of CoRegisterSurrogateEx) */
1310 if (GetProcAddress(GetModuleHandle("ole32"), "CoRegisterSurrogateEx"))
1311 /* now be really bad and release the proxy from the wrong apartment */
1312 IUnknown_Release(cf
);
1314 skip("skipping test for releasing proxy from wrong apartment that will succeed, but cause a crash during CoUninitialize\n");
1321 /* tests failure case of a using a proxy in the wrong apartment */
1322 static void test_proxy_used_in_wrong_thread(void)
1325 IStream
*pStream
= NULL
;
1326 IUnknown
*pProxy
= NULL
;
1333 hr
= CreateStreamOnHGlobal(NULL
, TRUE
, &pStream
);
1334 ok_ole_success(hr
, CreateStreamOnHGlobal
);
1335 tid
= start_host_object(pStream
, &IID_IClassFactory
, (IUnknown
*)&Test_ClassFactory
, MSHLFLAGS_NORMAL
, &host_thread
);
1337 ok_more_than_one_lock();
1339 IStream_Seek(pStream
, ullZero
, STREAM_SEEK_SET
, NULL
);
1340 hr
= CoUnmarshalInterface(pStream
, &IID_IClassFactory
, (void **)&pProxy
);
1341 ok_ole_success(hr
, CoUnmarshalInterface
);
1342 IStream_Release(pStream
);
1344 ok_more_than_one_lock();
1346 /* do a call that will fail, but result in IRemUnknown being used by the proxy */
1347 IClassFactory_QueryInterface(pProxy
, &IID_IStream
, (LPVOID
*)&pStream
);
1349 /* create a thread that we can misbehave in */
1350 thread
= CreateThread(NULL
, 0, bad_thread_proc
, (LPVOID
)pProxy
, 0, &tid2
);
1352 WaitForSingleObject(thread
, INFINITE
);
1353 CloseHandle(thread
);
1355 /* do release statement on Win9x that we should have done above */
1356 if (!GetProcAddress(GetModuleHandle("ole32"), "CoRegisterSurrogateEx"))
1357 IUnknown_Release(pProxy
);
1361 end_host_object(tid
, host_thread
);
1364 static HRESULT WINAPI
MessageFilter_QueryInterface(IMessageFilter
*iface
, REFIID riid
, void ** ppvObj
)
1366 if (ppvObj
== NULL
) return E_POINTER
;
1368 if (IsEqualGUID(riid
, &IID_IUnknown
) ||
1369 IsEqualGUID(riid
, &IID_IClassFactory
))
1371 *ppvObj
= (LPVOID
)iface
;
1372 IClassFactory_AddRef(iface
);
1376 return E_NOINTERFACE
;
1379 static ULONG WINAPI
MessageFilter_AddRef(IMessageFilter
*iface
)
1381 return 2; /* non-heap object */
1384 static ULONG WINAPI
MessageFilter_Release(IMessageFilter
*iface
)
1386 return 1; /* non-heap object */
1389 static DWORD WINAPI
MessageFilter_HandleInComingCall(
1390 IMessageFilter
*iface
,
1392 HTASK threadIDCaller
,
1394 LPINTERFACEINFO lpInterfaceInfo
)
1396 static int callcount
= 0;
1398 trace("HandleInComingCall\n");
1402 ret
= SERVERCALL_REJECTED
;
1405 ret
= SERVERCALL_RETRYLATER
;
1408 ret
= SERVERCALL_ISHANDLED
;
1415 static DWORD WINAPI
MessageFilter_RetryRejectedCall(
1416 IMessageFilter
*iface
,
1417 HTASK threadIDCallee
,
1421 trace("RetryRejectedCall\n");
1425 static DWORD WINAPI
MessageFilter_MessagePending(
1426 IMessageFilter
*iface
,
1427 HTASK threadIDCallee
,
1429 DWORD dwPendingType
)
1431 trace("MessagePending\n");
1432 return PENDINGMSG_WAITNOPROCESS
;
1435 static const IMessageFilterVtbl MessageFilter_Vtbl
=
1437 MessageFilter_QueryInterface
,
1438 MessageFilter_AddRef
,
1439 MessageFilter_Release
,
1440 MessageFilter_HandleInComingCall
,
1441 MessageFilter_RetryRejectedCall
,
1442 MessageFilter_MessagePending
1445 static IMessageFilter MessageFilter
= { &MessageFilter_Vtbl
};
1447 static void test_message_filter(void)
1450 IStream
*pStream
= NULL
;
1451 IClassFactory
*cf
= NULL
;
1453 IUnknown
*proxy
= NULL
;
1454 IMessageFilter
*prev_filter
= NULL
;
1459 hr
= CreateStreamOnHGlobal(NULL
, TRUE
, &pStream
);
1460 ok_ole_success(hr
, CreateStreamOnHGlobal
);
1461 tid
= start_host_object2(pStream
, &IID_IClassFactory
, (IUnknown
*)&Test_ClassFactory
, MSHLFLAGS_NORMAL
, &MessageFilter
, &thread
);
1463 ok_more_than_one_lock();
1465 IStream_Seek(pStream
, ullZero
, STREAM_SEEK_SET
, NULL
);
1466 hr
= CoUnmarshalInterface(pStream
, &IID_IClassFactory
, (void **)&cf
);
1467 ok_ole_success(hr
, CoUnmarshalInterface
);
1468 IStream_Release(pStream
);
1470 ok_more_than_one_lock();
1472 hr
= IClassFactory_CreateInstance(cf
, NULL
, &IID_IUnknown
, (LPVOID
*)&proxy
);
1473 ok(hr
== RPC_E_CALL_REJECTED
, "Call should have returned RPC_E_CALL_REJECTED, but return 0x%08x instead\n", hr
);
1474 if (proxy
) IUnknown_Release(proxy
);
1477 hr
= CoRegisterMessageFilter(&MessageFilter
, &prev_filter
);
1478 ok_ole_success(hr
, CoRegisterMessageFilter
);
1480 hr
= IClassFactory_CreateInstance(cf
, NULL
, &IID_IUnknown
, (LPVOID
*)&proxy
);
1481 ok_ole_success(hr
, IClassFactory_CreateInstance
);
1483 IUnknown_Release(proxy
);
1485 IClassFactory_Release(cf
);
1489 end_host_object(tid
, thread
);
1491 hr
= CoRegisterMessageFilter(prev_filter
, NULL
);
1492 ok_ole_success(hr
, CoRegisterMessageFilter
);
1495 /* test failure case of trying to unmarshal from bad stream */
1496 static void test_bad_marshal_stream(void)
1499 IStream
*pStream
= NULL
;
1501 hr
= CreateStreamOnHGlobal(NULL
, TRUE
, &pStream
);
1502 ok_ole_success(hr
, CreateStreamOnHGlobal
);
1503 hr
= CoMarshalInterface(pStream
, &IID_IClassFactory
, (IUnknown
*)&Test_ClassFactory
, MSHCTX_INPROC
, NULL
, MSHLFLAGS_NORMAL
);
1504 ok_ole_success(hr
, CoMarshalInterface
);
1506 ok_more_than_one_lock();
1508 /* try to read beyond end of stream */
1509 hr
= CoReleaseMarshalData(pStream
);
1510 ok(hr
== STG_E_READFAULT
, "Should have failed with STG_E_READFAULT, but returned 0x%08x instead\n", hr
);
1512 /* now release for real */
1513 IStream_Seek(pStream
, ullZero
, STREAM_SEEK_SET
, NULL
);
1514 hr
= CoReleaseMarshalData(pStream
);
1515 ok_ole_success(hr
, CoReleaseMarshalData
);
1517 IStream_Release(pStream
);
1520 /* tests that proxies implement certain interfaces */
1521 static void test_proxy_interfaces(void)
1524 IStream
*pStream
= NULL
;
1525 IUnknown
*pProxy
= NULL
;
1526 IUnknown
*pOtherUnknown
= NULL
;
1532 hr
= CreateStreamOnHGlobal(NULL
, TRUE
, &pStream
);
1533 ok_ole_success(hr
, CreateStreamOnHGlobal
);
1534 tid
= start_host_object(pStream
, &IID_IClassFactory
, (IUnknown
*)&Test_ClassFactory
, MSHLFLAGS_NORMAL
, &thread
);
1536 ok_more_than_one_lock();
1538 IStream_Seek(pStream
, ullZero
, STREAM_SEEK_SET
, NULL
);
1539 hr
= CoUnmarshalInterface(pStream
, &IID_IUnknown
, (void **)&pProxy
);
1540 ok_ole_success(hr
, CoUnmarshalInterface
);
1541 IStream_Release(pStream
);
1543 ok_more_than_one_lock();
1545 hr
= IUnknown_QueryInterface(pProxy
, &IID_IUnknown
, (LPVOID
*)&pOtherUnknown
);
1546 ok_ole_success(hr
, IUnknown_QueryInterface IID_IUnknown
);
1547 if (hr
== S_OK
) IUnknown_Release(pOtherUnknown
);
1549 hr
= IUnknown_QueryInterface(pProxy
, &IID_IClientSecurity
, (LPVOID
*)&pOtherUnknown
);
1550 ok_ole_success(hr
, IUnknown_QueryInterface IID_IClientSecurity
);
1551 if (hr
== S_OK
) IUnknown_Release(pOtherUnknown
);
1553 hr
= IUnknown_QueryInterface(pProxy
, &IID_IMultiQI
, (LPVOID
*)&pOtherUnknown
);
1554 ok_ole_success(hr
, IUnknown_QueryInterface IID_IMultiQI
);
1555 if (hr
== S_OK
) IUnknown_Release(pOtherUnknown
);
1557 hr
= IUnknown_QueryInterface(pProxy
, &IID_IMarshal
, (LPVOID
*)&pOtherUnknown
);
1558 ok_ole_success(hr
, IUnknown_QueryInterface IID_IMarshal
);
1559 if (hr
== S_OK
) IUnknown_Release(pOtherUnknown
);
1561 /* IMarshal2 is also supported on NT-based systems, but is pretty much
1562 * useless as it has no more methods over IMarshal that it inherits from. */
1564 IUnknown_Release(pProxy
);
1568 end_host_object(tid
, thread
);
1573 const IUnknownVtbl
*lpVtbl
;
1577 static HRESULT WINAPI
HeapUnknown_QueryInterface(IUnknown
*iface
, REFIID riid
, void **ppv
)
1579 if (IsEqualIID(riid
, &IID_IUnknown
))
1581 IUnknown_AddRef(iface
);
1582 *ppv
= (LPVOID
)iface
;
1586 return E_NOINTERFACE
;
1589 static ULONG WINAPI
HeapUnknown_AddRef(IUnknown
*iface
)
1591 HeapUnknown
*This
= (HeapUnknown
*)iface
;
1592 return InterlockedIncrement((LONG
*)&This
->refs
);
1595 static ULONG WINAPI
HeapUnknown_Release(IUnknown
*iface
)
1597 HeapUnknown
*This
= (HeapUnknown
*)iface
;
1598 ULONG refs
= InterlockedDecrement((LONG
*)&This
->refs
);
1599 if (!refs
) HeapFree(GetProcessHeap(), 0, This
);
1603 static const IUnknownVtbl HeapUnknown_Vtbl
=
1605 HeapUnknown_QueryInterface
,
1610 static void test_proxybuffer(REFIID riid
)
1613 IPSFactoryBuffer
*psfb
;
1614 IRpcProxyBuffer
*proxy
;
1618 HeapUnknown
*pUnkOuter
= (HeapUnknown
*)HeapAlloc(GetProcessHeap(), 0, sizeof(*pUnkOuter
));
1620 pUnkOuter
->lpVtbl
= &HeapUnknown_Vtbl
;
1621 pUnkOuter
->refs
= 1;
1623 hr
= CoGetPSClsid(riid
, &clsid
);
1624 ok_ole_success(hr
, CoGetPSClsid
);
1626 hr
= CoGetClassObject(&clsid
, CLSCTX_INPROC_SERVER
, NULL
, &IID_IPSFactoryBuffer
, (LPVOID
*)&psfb
);
1627 ok_ole_success(hr
, CoGetClassObject
);
1629 hr
= IPSFactoryBuffer_CreateProxy(psfb
, (IUnknown
*)pUnkOuter
, riid
, &proxy
, &lpvtbl
);
1630 ok_ole_success(hr
, IPSFactoryBuffer_CreateProxy
);
1631 ok(lpvtbl
!= NULL
, "IPSFactoryBuffer_CreateProxy succeeded, but returned a NULL vtable!\n");
1633 /* release our reference to the outer unknown object - the PS factory
1634 * buffer will have AddRef's it in the CreateProxy call */
1635 refs
= IUnknown_Release((IUnknown
*)pUnkOuter
);
1636 ok(refs
== 1, "Ref count of outer unknown should have been 1 instead of %d\n", refs
);
1638 refs
= IPSFactoryBuffer_Release(psfb
);
1641 /* not reliable on native. maybe it leaks references! */
1642 ok(refs
== 0, "Ref-count leak of %d on IPSFactoryBuffer\n", refs
);
1645 refs
= IUnknown_Release((IUnknown
*)lpvtbl
);
1646 ok(refs
== 0, "Ref-count leak of %d on IRpcProxyBuffer\n", refs
);
1648 refs
= IRpcProxyBuffer_Release(proxy
);
1649 ok(refs
== 0, "Ref-count leak of %d on IRpcProxyBuffer\n", refs
);
1652 static void test_stubbuffer(REFIID riid
)
1655 IPSFactoryBuffer
*psfb
;
1656 IRpcStubBuffer
*stub
;
1662 hr
= CoGetPSClsid(riid
, &clsid
);
1663 ok_ole_success(hr
, CoGetPSClsid
);
1665 hr
= CoGetClassObject(&clsid
, CLSCTX_INPROC_SERVER
, NULL
, &IID_IPSFactoryBuffer
, (LPVOID
*)&psfb
);
1666 ok_ole_success(hr
, CoGetClassObject
);
1668 hr
= IPSFactoryBuffer_CreateStub(psfb
, riid
, (IUnknown
*)&Test_ClassFactory
, &stub
);
1669 ok_ole_success(hr
, IPSFactoryBuffer_CreateStub
);
1671 refs
= IPSFactoryBuffer_Release(psfb
);
1674 /* not reliable on native. maybe it leaks references */
1675 ok(refs
== 0, "Ref-count leak of %d on IPSFactoryBuffer\n", refs
);
1678 ok_more_than_one_lock();
1680 IRpcStubBuffer_Disconnect(stub
);
1684 refs
= IRpcStubBuffer_Release(stub
);
1685 ok(refs
== 0, "Ref-count leak of %d on IRpcProxyBuffer\n", refs
);
1688 static HWND hwnd_app
;
1690 static HRESULT WINAPI
TestRE_IClassFactory_CreateInstance(
1691 LPCLASSFACTORY iface
,
1692 LPUNKNOWN pUnkOuter
,
1697 if (IsEqualIID(riid
, &IID_IWineTest
))
1699 BOOL ret
= SendMessageTimeout(hwnd_app
, WM_NULL
, 0, 0, SMTO_BLOCK
, 5000, &res
);
1700 ok(ret
, "Timed out sending a message to originating window during RPC call\n");
1705 static const IClassFactoryVtbl TestREClassFactory_Vtbl
=
1707 Test_IClassFactory_QueryInterface
,
1708 Test_IClassFactory_AddRef
,
1709 Test_IClassFactory_Release
,
1710 TestRE_IClassFactory_CreateInstance
,
1711 Test_IClassFactory_LockServer
1714 IClassFactory TestRE_ClassFactory
= { &TestREClassFactory_Vtbl
};
1716 static LRESULT CALLBACK
window_proc(HWND hwnd
, UINT msg
, WPARAM wparam
, LPARAM lparam
)
1723 IStream
*pStream
= NULL
;
1724 IClassFactory
*proxy
= NULL
;
1731 hr
= CreateStreamOnHGlobal(NULL
, TRUE
, &pStream
);
1732 ok_ole_success(hr
, CreateStreamOnHGlobal
);
1733 tid
= start_host_object(pStream
, &IID_IClassFactory
, (IUnknown
*)&TestRE_ClassFactory
, MSHLFLAGS_NORMAL
, &thread
);
1735 ok_more_than_one_lock();
1737 IStream_Seek(pStream
, ullZero
, STREAM_SEEK_SET
, NULL
);
1738 hr
= CoUnmarshalInterface(pStream
, &IID_IClassFactory
, (void **)&proxy
);
1739 ok_ole_success(hr
, CoReleaseMarshalData
);
1740 IStream_Release(pStream
);
1742 ok_more_than_one_lock();
1744 /* note the use of the magic IID_IWineTest value to tell remote thread
1745 * to try to send a message back to us */
1746 hr
= IClassFactory_CreateInstance(proxy
, NULL
, &IID_IWineTest
, (void **)&object
);
1748 IClassFactory_Release(proxy
);
1752 end_host_object(tid
, thread
);
1754 PostMessage(hwnd
, WM_QUIT
, 0, 0);
1761 IStream
*pStream
= NULL
;
1762 IClassFactory
*proxy
= NULL
;
1769 hr
= CreateStreamOnHGlobal(NULL
, TRUE
, &pStream
);
1770 ok_ole_success(hr
, CreateStreamOnHGlobal
);
1771 tid
= start_host_object(pStream
, &IID_IClassFactory
, (IUnknown
*)&TestRE_ClassFactory
, MSHLFLAGS_NORMAL
, &thread
);
1773 ok_more_than_one_lock();
1775 IStream_Seek(pStream
, ullZero
, STREAM_SEEK_SET
, NULL
);
1776 hr
= CoUnmarshalInterface(pStream
, &IID_IClassFactory
, (void **)&proxy
);
1777 ok_ole_success(hr
, CoReleaseMarshalData
);
1778 IStream_Release(pStream
);
1780 ok_more_than_one_lock();
1782 /* post quit message before a doing a COM call to show that a pending
1783 * WM_QUIT message doesn't stop the call from succeeding */
1784 PostMessage(hwnd
, WM_QUIT
, 0, 0);
1785 hr
= IClassFactory_CreateInstance(proxy
, NULL
, &IID_IUnknown
, (void **)&object
);
1787 IClassFactory_Release(proxy
);
1791 end_host_object(tid
, thread
);
1798 IStream
*pStream
= NULL
;
1799 IClassFactory
*proxy
= NULL
;
1804 hr
= CreateStreamOnHGlobal(NULL
, TRUE
, &pStream
);
1805 ok_ole_success(hr
, CreateStreamOnHGlobal
);
1806 tid
= start_host_object(pStream
, &IID_IClassFactory
, (IUnknown
*)&Test_ClassFactory
, MSHLFLAGS_NORMAL
, &thread
);
1808 IStream_Seek(pStream
, ullZero
, STREAM_SEEK_SET
, NULL
);
1809 hr
= CoUnmarshalInterface(pStream
, &IID_IClassFactory
, (void **)&proxy
);
1810 ok_ole_success(hr
, CoReleaseMarshalData
);
1811 IStream_Release(pStream
);
1813 /* shows that COM calls executed during the processing of sent
1814 * messages should fail */
1815 hr
= IClassFactory_CreateInstance(proxy
, NULL
, &IID_IUnknown
, (void **)&object
);
1816 ok(hr
== RPC_E_CANTCALLOUT_ININPUTSYNCCALL
,
1817 "COM call during processing of sent message should return RPC_E_CANTCALLOUT_ININPUTSYNCCALL instead of 0x%08x\n", hr
);
1819 IClassFactory_Release(proxy
);
1821 end_host_object(tid
, thread
);
1828 return DefWindowProc(hwnd
, msg
, wparam
, lparam
);
1832 static void test_message_reentrancy(void)
1837 memset(&wndclass
, 0, sizeof(wndclass
));
1838 wndclass
.lpfnWndProc
= window_proc
;
1839 wndclass
.lpszClassName
= "WineCOMTest";
1840 RegisterClass(&wndclass
);
1842 hwnd_app
= CreateWindow("WineCOMTest", NULL
, 0, CW_USEDEFAULT
, CW_USEDEFAULT
, CW_USEDEFAULT
, CW_USEDEFAULT
, NULL
, NULL
, NULL
, 0);
1843 ok(hwnd_app
!= NULL
, "Window creation failed\n");
1845 /* start message re-entrancy test */
1846 PostMessage(hwnd_app
, WM_USER
, 0, 0);
1848 while (GetMessage(&msg
, NULL
, 0, 0))
1850 TranslateMessage(&msg
);
1851 DispatchMessage(&msg
);
1855 static HRESULT WINAPI
TestMsg_IClassFactory_CreateInstance(
1856 LPCLASSFACTORY iface
,
1857 LPUNKNOWN pUnkOuter
,
1862 SendMessage(hwnd_app
, WM_USER
+2, 0, 0);
1866 static IClassFactoryVtbl TestMsgClassFactory_Vtbl
=
1868 Test_IClassFactory_QueryInterface
,
1869 Test_IClassFactory_AddRef
,
1870 Test_IClassFactory_Release
,
1871 TestMsg_IClassFactory_CreateInstance
,
1872 Test_IClassFactory_LockServer
1875 IClassFactory TestMsg_ClassFactory
= { &TestMsgClassFactory_Vtbl
};
1877 static void test_call_from_message(void)
1882 IClassFactory
*proxy
;
1887 hwnd_app
= CreateWindow("WineCOMTest", NULL
, 0, CW_USEDEFAULT
, CW_USEDEFAULT
, CW_USEDEFAULT
, CW_USEDEFAULT
, NULL
, NULL
, NULL
, 0);
1888 ok(hwnd_app
!= NULL
, "Window creation failed\n");
1890 hr
= CreateStreamOnHGlobal(NULL
, TRUE
, &pStream
);
1891 ok_ole_success(hr
, CreateStreamOnHGlobal
);
1892 tid
= start_host_object(pStream
, &IID_IClassFactory
, (IUnknown
*)&TestMsg_ClassFactory
, MSHLFLAGS_NORMAL
, &thread
);
1894 ok_more_than_one_lock();
1896 IStream_Seek(pStream
, ullZero
, STREAM_SEEK_SET
, NULL
);
1897 hr
= CoUnmarshalInterface(pStream
, &IID_IClassFactory
, (void **)&proxy
);
1898 ok_ole_success(hr
, CoReleaseMarshalData
);
1899 IStream_Release(pStream
);
1901 ok_more_than_one_lock();
1903 /* start message re-entrancy test */
1904 hr
= IClassFactory_CreateInstance(proxy
, NULL
, &IID_IUnknown
, (void **)&object
);
1905 ok_ole_success(hr
, IClassFactory_CreateInstance
);
1907 IClassFactory_Release(proxy
);
1911 end_host_object(tid
, thread
);
1913 while (GetMessage(&msg
, NULL
, 0, 0))
1915 TranslateMessage(&msg
);
1916 DispatchMessage(&msg
);
1920 static void test_WM_QUIT_handling(void)
1924 hwnd_app
= CreateWindow("WineCOMTest", NULL
, 0, CW_USEDEFAULT
, CW_USEDEFAULT
, CW_USEDEFAULT
, CW_USEDEFAULT
, NULL
, NULL
, NULL
, 0);
1925 ok(hwnd_app
!= NULL
, "Window creation failed\n");
1927 /* start WM_QUIT handling test */
1928 PostMessage(hwnd_app
, WM_USER
+1, 0, 0);
1930 while (GetMessage(&msg
, NULL
, 0, 0))
1932 TranslateMessage(&msg
);
1933 DispatchMessage(&msg
);
1937 static void test_freethreadedmarshaldata(IStream
*pStream
, MSHCTX mshctx
, void *ptr
, DWORD mshlflags
)
1944 hr
= GetHGlobalFromStream(pStream
, &hglobal
);
1945 ok_ole_success(hr
, GetHGlobalFromStream
);
1947 size
= GlobalSize(hglobal
);
1949 marshal_data
= (char *)GlobalLock(hglobal
);
1951 if (mshctx
== MSHCTX_INPROC
)
1953 DWORD expected_size
= sizeof(DWORD
) + sizeof(void *) + sizeof(DWORD
) + sizeof(GUID
);
1954 ok(size
== expected_size
, "size should have been %d instead of %d\n", expected_size
, size
);
1956 ok(*(DWORD
*)marshal_data
== mshlflags
, "expected 0x%x, but got 0x%x for mshctx\n", mshlflags
, *(DWORD
*)marshal_data
);
1957 marshal_data
+= sizeof(DWORD
);
1958 ok(*(void **)marshal_data
== ptr
, "expected %p, but got %p for mshctx\n", ptr
, *(void **)marshal_data
);
1959 marshal_data
+= sizeof(void *);
1960 ok(*(DWORD
*)marshal_data
== 0, "expected 0x0, but got 0x%x\n", *(DWORD
*)marshal_data
);
1961 marshal_data
+= sizeof(DWORD
);
1962 trace("got guid data: {%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x}\n",
1963 ((GUID
*)marshal_data
)->Data1
, ((GUID
*)marshal_data
)->Data2
, ((GUID
*)marshal_data
)->Data3
,
1964 ((GUID
*)marshal_data
)->Data4
[0], ((GUID
*)marshal_data
)->Data4
[1], ((GUID
*)marshal_data
)->Data4
[2], ((GUID
*)marshal_data
)->Data4
[3],
1965 ((GUID
*)marshal_data
)->Data4
[4], ((GUID
*)marshal_data
)->Data4
[5], ((GUID
*)marshal_data
)->Data4
[6], ((GUID
*)marshal_data
)->Data4
[7]);
1969 ok(size
> sizeof(DWORD
), "size should have been > sizeof(DWORD), not %d\n", size
);
1970 ok(*(DWORD
*)marshal_data
== 0x574f454d /* MEOW */,
1971 "marshal data should be filled by standard marshal and start with MEOW signature\n");
1974 GlobalUnlock(hglobal
);
1977 static void test_freethreadedmarshaler(void)
1980 IUnknown
*pFTUnknown
;
1981 IMarshal
*pFTMarshal
;
1984 static const LARGE_INTEGER llZero
;
1987 hr
= CoCreateFreeThreadedMarshaler(NULL
, &pFTUnknown
);
1988 ok_ole_success(hr
, CoCreateFreeThreadedMarshaler
);
1989 hr
= IUnknown_QueryInterface(pFTUnknown
, &IID_IMarshal
, (void **)&pFTMarshal
);
1990 ok_ole_success(hr
, IUnknown_QueryInterface
);
1991 IUnknown_Release(pFTUnknown
);
1993 hr
= CreateStreamOnHGlobal(NULL
, TRUE
, &pStream
);
1994 ok_ole_success(hr
, CreateStreamOnHGlobal
);
1996 /* inproc normal marshaling */
1998 hr
= IMarshal_MarshalInterface(pFTMarshal
, pStream
, &IID_IClassFactory
,
1999 (IUnknown
*)&Test_ClassFactory
, MSHCTX_INPROC
, NULL
, MSHLFLAGS_NORMAL
);
2000 ok_ole_success(hr
, IMarshal_MarshalInterface
);
2002 ok_more_than_one_lock();
2004 test_freethreadedmarshaldata(pStream
, MSHCTX_INPROC
, &Test_ClassFactory
, MSHLFLAGS_NORMAL
);
2006 IStream_Seek(pStream
, llZero
, STREAM_SEEK_SET
, NULL
);
2007 hr
= IMarshal_UnmarshalInterface(pFTMarshal
, pStream
, &IID_IUnknown
, (void **)&pProxy
);
2008 ok_ole_success(hr
, IMarshal_UnmarshalInterface
);
2010 IUnknown_Release(pProxy
);
2014 /* native doesn't allow us to unmarshal or release the stream data,
2015 * presumably because it wants us to call CoMarshalInterface instead */
2018 /* local normal marshaling */
2020 IStream_Seek(pStream
, llZero
, STREAM_SEEK_SET
, NULL
);
2021 hr
= IMarshal_MarshalInterface(pFTMarshal
, pStream
, &IID_IClassFactory
, (IUnknown
*)&Test_ClassFactory
, MSHCTX_LOCAL
, NULL
, MSHLFLAGS_NORMAL
);
2022 ok_ole_success(hr
, IMarshal_MarshalInterface
);
2024 ok_more_than_one_lock();
2026 test_freethreadedmarshaldata(pStream
, MSHCTX_LOCAL
, &Test_ClassFactory
, MSHLFLAGS_NORMAL
);
2028 IStream_Seek(pStream
, llZero
, STREAM_SEEK_SET
, NULL
);
2029 hr
= IMarshal_ReleaseMarshalData(pFTMarshal
, pStream
);
2030 ok_ole_success(hr
, IMarshal_ReleaseMarshalData
);
2035 /* inproc table-strong marshaling */
2037 IStream_Seek(pStream
, llZero
, STREAM_SEEK_SET
, NULL
);
2038 hr
= IMarshal_MarshalInterface(pFTMarshal
, pStream
, &IID_IClassFactory
,
2039 (IUnknown
*)&Test_ClassFactory
, MSHCTX_INPROC
, (void *)0xdeadbeef,
2040 MSHLFLAGS_TABLESTRONG
);
2041 ok_ole_success(hr
, IMarshal_MarshalInterface
);
2043 ok_more_than_one_lock();
2045 test_freethreadedmarshaldata(pStream
, MSHCTX_INPROC
, &Test_ClassFactory
, MSHLFLAGS_TABLESTRONG
);
2047 IStream_Seek(pStream
, llZero
, STREAM_SEEK_SET
, NULL
);
2048 hr
= IMarshal_UnmarshalInterface(pFTMarshal
, pStream
, &IID_IUnknown
, (void **)&pProxy
);
2049 ok_ole_success(hr
, IMarshal_UnmarshalInterface
);
2051 IUnknown_Release(pProxy
);
2053 ok_more_than_one_lock();
2055 IStream_Seek(pStream
, llZero
, STREAM_SEEK_SET
, NULL
);
2056 hr
= IMarshal_ReleaseMarshalData(pFTMarshal
, pStream
);
2057 ok_ole_success(hr
, IMarshal_ReleaseMarshalData
);
2061 /* inproc table-weak marshaling */
2063 IStream_Seek(pStream
, llZero
, STREAM_SEEK_SET
, NULL
);
2064 hr
= IMarshal_MarshalInterface(pFTMarshal
, pStream
, &IID_IClassFactory
,
2065 (IUnknown
*)&Test_ClassFactory
, MSHCTX_INPROC
, (void *)0xdeadbeef,
2066 MSHLFLAGS_TABLEWEAK
);
2067 ok_ole_success(hr
, IMarshal_MarshalInterface
);
2071 test_freethreadedmarshaldata(pStream
, MSHCTX_INPROC
, &Test_ClassFactory
, MSHLFLAGS_TABLEWEAK
);
2073 IStream_Seek(pStream
, llZero
, STREAM_SEEK_SET
, NULL
);
2074 hr
= IMarshal_UnmarshalInterface(pFTMarshal
, pStream
, &IID_IUnknown
, (void **)&pProxy
);
2075 ok_ole_success(hr
, IMarshal_UnmarshalInterface
);
2077 ok_more_than_one_lock();
2079 IUnknown_Release(pProxy
);
2083 /* inproc normal marshaling (for extraordinary cases) */
2085 IStream_Seek(pStream
, llZero
, STREAM_SEEK_SET
, NULL
);
2086 hr
= IMarshal_MarshalInterface(pFTMarshal
, pStream
, &IID_IClassFactory
,
2087 (IUnknown
*)&Test_ClassFactory
, MSHCTX_INPROC
, NULL
, MSHLFLAGS_NORMAL
);
2088 ok_ole_success(hr
, IMarshal_MarshalInterface
);
2090 ok_more_than_one_lock();
2092 /* this call shows that DisconnectObject does nothing */
2093 hr
= IMarshal_DisconnectObject(pFTMarshal
, 0);
2094 ok_ole_success(hr
, IMarshal_DisconnectObject
);
2096 ok_more_than_one_lock();
2098 IStream_Seek(pStream
, llZero
, STREAM_SEEK_SET
, NULL
);
2099 hr
= IMarshal_ReleaseMarshalData(pFTMarshal
, pStream
);
2100 ok_ole_success(hr
, IMarshal_ReleaseMarshalData
);
2104 /* doesn't enforce marshaling rules here and allows us to unmarshal the
2105 * interface, even though it was freed above */
2106 IStream_Seek(pStream
, llZero
, STREAM_SEEK_SET
, NULL
);
2107 hr
= IMarshal_UnmarshalInterface(pFTMarshal
, pStream
, &IID_IUnknown
, (void **)&pProxy
);
2108 ok_ole_success(hr
, IMarshal_UnmarshalInterface
);
2112 IStream_Release(pStream
);
2113 IMarshal_Release(pFTMarshal
);
2116 static void test_inproc_handler(void)
2124 DWORD dwDisposition
;
2127 hr
= StringFromCLSID(&CLSID_WineTest
, &pszClsid
);
2128 ok_ole_success(hr
, "StringFromCLSID");
2129 strcpy(buffer
, "CLSID\\");
2130 WideCharToMultiByte(CP_ACP
, 0, pszClsid
, -1, buffer
+ strlen(buffer
), sizeof(buffer
) - strlen(buffer
), NULL
, NULL
);
2131 CoTaskMemFree(pszClsid
);
2132 strcat(buffer
, "\\InprocHandler32");
2133 error
= RegCreateKeyEx(HKEY_CLASSES_ROOT
, buffer
, 0, NULL
, 0, KEY_SET_VALUE
, NULL
, &hkey
, &dwDisposition
);
2134 ok(error
== ERROR_SUCCESS
, "RegCreateKeyEx failed with error %d\n", error
);
2135 error
= RegSetValueEx(hkey
, NULL
, 0, REG_SZ
, (const unsigned char *)"ole32.dll", strlen("ole32.dll") + 1);
2136 ok(error
== ERROR_SUCCESS
, "RegSetValueEx failed with error %d\n", error
);
2139 hr
= CoCreateInstance(&CLSID_WineTest
, NULL
, CLSCTX_INPROC_HANDLER
, &IID_IUnknown
, (void **)&pObject
);
2141 ok_ole_success(hr
, "CoCreateInstance");
2145 hr
= IUnknown_QueryInterface(pObject
, &IID_IWineTest
, (void **)&pObject2
);
2146 ok(hr
== E_NOINTERFACE
, "IUnknown_QueryInterface on handler for invalid interface returned 0x%08x instead of E_NOINTERFACE\n", hr
);
2148 /* it's a handler as it supports IOleObject */
2149 hr
= IUnknown_QueryInterface(pObject
, &IID_IOleObject
, (void **)&pObject2
);
2150 ok_ole_success(hr
, "IUnknown_QueryInterface(&IID_IOleObject)");
2151 IUnknown_Release(pObject2
);
2153 IUnknown_Release(pObject
);
2156 RegDeleteKey(HKEY_CLASSES_ROOT
, buffer
);
2157 *strrchr(buffer
, '\\') = '\0';
2158 RegDeleteKey(HKEY_CLASSES_ROOT
, buffer
);
2161 static HRESULT WINAPI
Test_SMI_QueryInterface(
2162 IStdMarshalInfo
*iface
,
2166 if (ppvObj
== NULL
) return E_POINTER
;
2168 if (IsEqualGUID(riid
, &IID_IUnknown
) ||
2169 IsEqualGUID(riid
, &IID_IStdMarshalInfo
))
2171 *ppvObj
= (LPVOID
)iface
;
2172 IClassFactory_AddRef(iface
);
2176 return E_NOINTERFACE
;
2179 static ULONG WINAPI
Test_SMI_AddRef(IStdMarshalInfo
*iface
)
2182 return 2; /* non-heap-based object */
2185 static ULONG WINAPI
Test_SMI_Release(IStdMarshalInfo
*iface
)
2188 return 1; /* non-heap-based object */
2191 static HRESULT WINAPI
Test_SMI_GetClassForHandler(
2192 IStdMarshalInfo
*iface
,
2193 DWORD dwDestContext
,
2194 void *pvDestContext
,
2197 *pClsid
= CLSID_WineTest
;
2201 static const IStdMarshalInfoVtbl Test_SMI_Vtbl
=
2203 Test_SMI_QueryInterface
,
2206 Test_SMI_GetClassForHandler
2209 static IStdMarshalInfo Test_SMI
= {&Test_SMI_Vtbl
};
2211 static void test_handler_marshaling(void)
2214 IStream
*pStream
= NULL
;
2215 IUnknown
*pProxy
= NULL
;
2219 static const LARGE_INTEGER ullZero
;
2223 hr
= CreateStreamOnHGlobal(NULL
, TRUE
, &pStream
);
2224 ok_ole_success(hr
, "CreateStreamOnHGlobal");
2225 tid
= start_host_object(pStream
, &IID_IUnknown
, (IUnknown
*)&Test_SMI
, MSHLFLAGS_NORMAL
, &thread
);
2227 ok_more_than_one_lock();
2229 IStream_Seek(pStream
, ullZero
, STREAM_SEEK_SET
, NULL
);
2230 hr
= CoUnmarshalInterface(pStream
, &IID_IUnknown
, (void **)&pProxy
);
2231 ok_ole_success(hr
, "CoUnmarshalInterface");
2232 IStream_Release(pStream
);
2234 ok_more_than_one_lock();
2236 hr
= IUnknown_QueryInterface(pProxy
, &IID_IWineTest
, (void **)&pObject
);
2237 ok(hr
== E_NOINTERFACE
, "IUnknown_QueryInterface with unknown IID should have returned E_NOINTERFACE instead of 0x%08x\n", hr
);
2239 /* it's a handler as it supports IOleObject */
2240 hr
= IUnknown_QueryInterface(pProxy
, &IID_IOleObject
, (void **)&pObject
);
2242 ok_ole_success(hr
, "IUnknown_QueryInterface(&IID_IOleObject)");
2243 if (SUCCEEDED(hr
)) IUnknown_Release(pObject
);
2245 IUnknown_Release(pProxy
);
2249 end_host_object(tid
, thread
);
2251 /* FIXME: test IPersist interface has the same effect as IStdMarshalInfo */
2255 static void test_client_security(void)
2258 IStream
*pStream
= NULL
;
2259 IClassFactory
*pProxy
= NULL
;
2260 IUnknown
*pProxy2
= NULL
;
2261 IUnknown
*pUnknown1
= NULL
;
2262 IUnknown
*pUnknown2
= NULL
;
2263 IClientSecurity
*pCliSec
= NULL
;
2267 static const LARGE_INTEGER ullZero
;
2270 OLECHAR
*pServerPrincName
;
2274 DWORD dwCapabilities
;
2279 hr
= CreateStreamOnHGlobal(NULL
, TRUE
, &pStream
);
2280 ok_ole_success(hr
, "CreateStreamOnHGlobal");
2281 tid
= start_host_object(pStream
, &IID_IClassFactory
, (IUnknown
*)&Test_ClassFactory
, MSHLFLAGS_NORMAL
, &thread
);
2283 IStream_Seek(pStream
, ullZero
, STREAM_SEEK_SET
, NULL
);
2284 hr
= CoUnmarshalInterface(pStream
, &IID_IClassFactory
, (void **)&pProxy
);
2285 ok_ole_success(hr
, "CoUnmarshalInterface");
2286 IStream_Release(pStream
);
2288 hr
= IUnknown_QueryInterface(pProxy
, &IID_IUnknown
, (LPVOID
*)&pUnknown1
);
2289 ok_ole_success(hr
, "IUnknown_QueryInterface IID_IUnknown");
2291 hr
= IUnknown_QueryInterface(pProxy
, &IID_IRemUnknown
, (LPVOID
*)&pProxy2
);
2292 ok_ole_success(hr
, "IUnknown_QueryInterface IID_IStream");
2294 hr
= IUnknown_QueryInterface(pProxy2
, &IID_IUnknown
, (LPVOID
*)&pUnknown2
);
2295 ok_ole_success(hr
, "IUnknown_QueryInterface IID_IUnknown");
2297 ok(pUnknown1
== pUnknown2
, "both proxy's IUnknowns should be the same - %p, %p\n", pUnknown1
, pUnknown2
);
2299 hr
= IUnknown_QueryInterface(pProxy
, &IID_IMarshal
, (LPVOID
*)&pMarshal
);
2300 ok_ole_success(hr
, "IUnknown_QueryInterface IID_IMarshal");
2302 hr
= IUnknown_QueryInterface(pProxy
, &IID_IClientSecurity
, (LPVOID
*)&pCliSec
);
2303 ok_ole_success(hr
, "IUnknown_QueryInterface IID_IClientSecurity");
2305 hr
= IClientSecurity_QueryBlanket(pCliSec
, (IUnknown
*)pProxy
, NULL
, NULL
, NULL
, NULL
, NULL
, NULL
, NULL
);
2306 todo_wine
ok_ole_success(hr
, "IClientSecurity_QueryBlanket (all NULLs)");
2308 hr
= IClientSecurity_QueryBlanket(pCliSec
, (IUnknown
*)pMarshal
, NULL
, NULL
, NULL
, NULL
, NULL
, NULL
, NULL
);
2309 todo_wine
ok(hr
== E_NOINTERFACE
, "IClientSecurity_QueryBlanket with local interface should have returned E_NOINTERFACE instead of 0x%08x\n", hr
);
2311 hr
= IClientSecurity_QueryBlanket(pCliSec
, (IUnknown
*)pProxy
, &dwAuthnSvc
, &dwAuthzSvc
, &pServerPrincName
, &dwAuthnLevel
, &dwImpLevel
, &pAuthInfo
, &dwCapabilities
);
2312 todo_wine
ok_ole_success(hr
, "IClientSecurity_QueryBlanket");
2314 hr
= IClientSecurity_SetBlanket(pCliSec
, (IUnknown
*)pProxy
, dwAuthnSvc
, dwAuthzSvc
, pServerPrincName
, dwAuthnLevel
, RPC_C_IMP_LEVEL_IMPERSONATE
, pAuthInfo
, dwCapabilities
);
2315 todo_wine
ok_ole_success(hr
, "IClientSecurity_SetBlanket");
2317 hr
= IClassFactory_CreateInstance(pProxy
, NULL
, &IID_IWineTest
, &pv
);
2318 ok(hr
== E_NOINTERFACE
, "COM call should have succeeded instead of returning 0x%08x\n", hr
);
2320 hr
= IClientSecurity_SetBlanket(pCliSec
, (IUnknown
*)pMarshal
, dwAuthnSvc
, dwAuthzSvc
, pServerPrincName
, dwAuthnLevel
, dwImpLevel
, pAuthInfo
, dwCapabilities
);
2321 todo_wine
ok(hr
== E_NOINTERFACE
, "IClientSecurity_SetBlanket with local interface should have returned E_NOINTERFACE instead of 0x%08x\n", hr
);
2323 hr
= IClientSecurity_SetBlanket(pCliSec
, (IUnknown
*)pProxy
, 0xdeadbeef, dwAuthzSvc
, pServerPrincName
, dwAuthnLevel
, dwImpLevel
, pAuthInfo
, dwCapabilities
);
2324 todo_wine
ok(hr
== E_INVALIDARG
, "IClientSecurity_SetBlanke with invalid dwAuthnSvc should have returned E_INVALIDARG instead of 0x%08x\n", hr
);
2326 CoTaskMemFree(pServerPrincName
);
2328 hr
= IClientSecurity_QueryBlanket(pCliSec
, (IUnknown
*)pUnknown1
, &dwAuthnSvc
, &dwAuthzSvc
, &pServerPrincName
, &dwAuthnLevel
, &dwImpLevel
, &pAuthInfo
, &dwCapabilities
);
2329 todo_wine
ok_ole_success(hr
, "IClientSecurity_QueryBlanket(IUnknown)");
2331 CoTaskMemFree(pServerPrincName
);
2333 IClassFactory_Release(pProxy
);
2334 IUnknown_Release(pProxy2
);
2335 IUnknown_Release(pUnknown1
);
2336 IUnknown_Release(pUnknown2
);
2337 IMarshal_Release(pMarshal
);
2338 IClientSecurity_Release(pCliSec
);
2340 end_host_object(tid
, thread
);
2343 static HANDLE heventShutdown
;
2345 static void LockModuleOOP(void)
2347 InterlockedIncrement(&cLocks
); /* for test purposes only */
2348 CoAddRefServerProcess();
2351 static void UnlockModuleOOP(void)
2353 InterlockedDecrement(&cLocks
); /* for test purposes only */
2354 if (!CoReleaseServerProcess())
2355 SetEvent(heventShutdown
);
2358 static HWND hwnd_app
;
2360 static HRESULT WINAPI
TestOOP_IClassFactory_QueryInterface(
2361 LPCLASSFACTORY iface
,
2365 if (ppvObj
== NULL
) return E_POINTER
;
2367 if (IsEqualGUID(riid
, &IID_IUnknown
) ||
2368 IsEqualGUID(riid
, &IID_IClassFactory
))
2370 *ppvObj
= (LPVOID
)iface
;
2371 IClassFactory_AddRef(iface
);
2375 return E_NOINTERFACE
;
2378 static ULONG WINAPI
TestOOP_IClassFactory_AddRef(LPCLASSFACTORY iface
)
2380 return 2; /* non-heap-based object */
2383 static ULONG WINAPI
TestOOP_IClassFactory_Release(LPCLASSFACTORY iface
)
2385 return 1; /* non-heap-based object */
2388 static HRESULT WINAPI
TestOOP_IClassFactory_CreateInstance(
2389 LPCLASSFACTORY iface
,
2390 LPUNKNOWN pUnkOuter
,
2394 if (IsEqualIID(riid
, &IID_IClassFactory
) || IsEqualIID(riid
, &IID_IUnknown
))
2399 return CLASS_E_CLASSNOTAVAILABLE
;
2402 static HRESULT WINAPI
TestOOP_IClassFactory_LockServer(
2403 LPCLASSFACTORY iface
,
2413 static const IClassFactoryVtbl TestClassFactoryOOP_Vtbl
=
2415 TestOOP_IClassFactory_QueryInterface
,
2416 TestOOP_IClassFactory_AddRef
,
2417 TestOOP_IClassFactory_Release
,
2418 TestOOP_IClassFactory_CreateInstance
,
2419 TestOOP_IClassFactory_LockServer
2422 static IClassFactory TestOOP_ClassFactory
= { &TestClassFactoryOOP_Vtbl
};
2424 static void test_register_local_server(void)
2432 heventShutdown
= CreateEvent(NULL
, TRUE
, FALSE
, NULL
);
2434 hr
= CoRegisterClassObject(&CLSID_WineOOPTest
, (IUnknown
*)&TestOOP_ClassFactory
,
2435 CLSCTX_LOCAL_SERVER
, REGCLS_SINGLEUSE
, &cookie
);
2436 ok_ole_success(hr
, CoRegisterClassObject
);
2438 ready_event
= CreateEvent(NULL
, FALSE
, FALSE
, "Wine COM Test Ready Event");
2439 SetEvent(ready_event
);
2441 quit_event
= CreateEvent(NULL
, FALSE
, FALSE
, "Wine COM Test Quit Event");
2445 wait
= MsgWaitForMultipleObjects(1, &quit_event
, FALSE
, INFINITE
, QS_ALLINPUT
);
2446 if (wait
== WAIT_OBJECT_0
+1)
2449 BOOL ret
= PeekMessage(&msg
, NULL
, 0, 0, PM_REMOVE
);
2452 trace("Message 0x%x\n", msg
.message
);
2453 TranslateMessage(&msg
);
2454 DispatchMessage(&msg
);
2458 while (wait
== WAIT_OBJECT_0
+1);
2460 hr
= CoRevokeClassObject(cookie
);
2461 ok_ole_success(hr
, CoRevokeClassObject
);
2464 static HANDLE
create_target_process(const char *arg
)
2467 char cmdline
[MAX_PATH
];
2468 PROCESS_INFORMATION pi
;
2469 STARTUPINFO si
= { 0 };
2472 winetest_get_mainargs( &argv
);
2473 sprintf(cmdline
, "%s %s %s", argv
[0], argv
[1], arg
);
2474 ok(CreateProcess(argv
[0], cmdline
, NULL
, NULL
, FALSE
, 0, NULL
, NULL
,
2475 &si
, &pi
) != 0, "error: %u\n", GetLastError());
2476 ok(CloseHandle(pi
.hThread
) != 0, "error %u\n", GetLastError());
2480 /* tests functions commonly used by out of process COM servers */
2481 static void test_local_server(void)
2491 heventShutdown
= CreateEvent(NULL
, TRUE
, FALSE
, NULL
);
2495 /* Start the object suspended */
2496 hr
= CoRegisterClassObject(&CLSID_WineOOPTest
, (IUnknown
*)&TestOOP_ClassFactory
,
2497 CLSCTX_LOCAL_SERVER
, REGCLS_MULTIPLEUSE
| REGCLS_SUSPENDED
, &cookie
);
2498 ok_ole_success(hr
, CoRegisterClassObject
);
2500 /* ... and CoGetClassObject does not find it and fails when it looks for the
2501 * class in the registry */
2502 hr
= CoGetClassObject(&CLSID_WineOOPTest
, CLSCTX_INPROC_SERVER
,
2503 NULL
, &IID_IClassFactory
, (LPVOID
*)&cf
);
2504 ok(hr
== REGDB_E_CLASSNOTREG
|| /* NT */
2505 hr
== S_OK
/* Win9x */,
2506 "CoGetClassObject should have returned REGDB_E_CLASSNOTREG instead of 0x%08x\n", hr
);
2508 /* Resume the object suspended above ... */
2509 hr
= CoResumeClassObjects();
2510 ok_ole_success(hr
, CoResumeClassObjects
);
2512 /* ... and now it should succeed */
2513 hr
= CoGetClassObject(&CLSID_WineOOPTest
, CLSCTX_INPROC_SERVER
,
2514 NULL
, &IID_IClassFactory
, (LPVOID
*)&cf
);
2515 ok_ole_success(hr
, CoGetClassObject
);
2517 /* Now check the locking is working */
2518 /* NOTE: we are accessing the class directly, not through a proxy */
2522 hr
= IClassFactory_LockServer(cf
, TRUE
);
2523 ok_ole_success(hr
, IClassFactory_LockServer
);
2525 ok_more_than_one_lock();
2527 IClassFactory_LockServer(cf
, FALSE
);
2528 ok_ole_success(hr
, IClassFactory_LockServer
);
2532 IClassFactory_Release(cf
);
2534 /* wait for shutdown signal */
2535 ret
= WaitForSingleObject(heventShutdown
, 0);
2536 ok(ret
!= WAIT_TIMEOUT
, "Server didn't shut down\n");
2538 /* try to connect again after SCM has suspended registered class objects */
2539 hr
= CoGetClassObject(&CLSID_WineOOPTest
, CLSCTX_INPROC_SERVER
| CLSCTX_LOCAL_SERVER
, NULL
,
2540 &IID_IClassFactory
, (LPVOID
*)&cf
);
2541 ok(hr
== CO_E_SERVER_STOPPING
|| /* NT */
2542 hr
== S_OK
/* Win9x */,
2543 "CoGetClassObject should have returned CO_E_SERVER_STOPPING instead of 0x%08x\n", hr
);
2545 hr
= CoRevokeClassObject(cookie
);
2546 ok_ole_success(hr
, CoRevokeClassObject
);
2548 CloseHandle(heventShutdown
);
2550 process
= create_target_process("-Embedding");
2551 ok(process
!= NULL
, "couldn't start local server process, error was %d\n", GetLastError());
2553 ready_event
= CreateEvent(NULL
, FALSE
, FALSE
, "Wine COM Test Ready Event");
2554 WaitForSingleObject(ready_event
, 1000);
2555 CloseHandle(ready_event
);
2557 hr
= CoCreateInstance(&CLSID_WineOOPTest
, NULL
, CLSCTX_LOCAL_SERVER
, &IID_IClassFactory
, (void **)&cf
);
2558 ok_ole_success(hr
, CoCreateInstance
);
2560 IClassFactory_Release(cf
);
2562 hr
= CoCreateInstance(&CLSID_WineOOPTest
, NULL
, CLSCTX_LOCAL_SERVER
, &IID_IClassFactory
, (void **)&cf
);
2563 ok(hr
== REGDB_E_CLASSNOTREG
, "Second CoCreateInstance on REGCLS_SINGLEUSE object should have failed\n");
2565 quit_event
= CreateEvent(NULL
, FALSE
, FALSE
, "Wine COM Test Quit Event");
2566 SetEvent(quit_event
);
2568 WaitForSingleObject(process
, INFINITE
);
2569 CloseHandle(quit_event
);
2570 CloseHandle(process
);
2576 IGlobalInterfaceTable
*git
;
2579 static DWORD CALLBACK
get_global_interface_proc(LPVOID pv
)
2582 struct git_params
*params
= (struct git_params
*)pv
;
2585 hr
= IGlobalInterfaceTable_GetInterfaceFromGlobal(params
->git
, params
->cookie
, &IID_IClassFactory
, (void **)&cf
);
2586 ok(hr
== CO_E_NOTINITIALIZED
,
2587 "IGlobalInterfaceTable_GetInterfaceFromGlobal should have failed with error CO_E_NOTINITIALIZED instead of 0x%08x\n",
2592 hr
= IGlobalInterfaceTable_GetInterfaceFromGlobal(params
->git
, params
->cookie
, &IID_IClassFactory
, (void **)&cf
);
2593 ok_ole_success(hr
, IGlobalInterfaceTable_GetInterfaceFromGlobal
);
2595 IClassFactory_Release(cf
);
2602 static void test_globalinterfacetable(void)
2605 IGlobalInterfaceTable
*git
;
2609 struct git_params params
;
2613 trace("test_globalinterfacetable\n");
2616 hr
= CoCreateInstance(&CLSID_StdGlobalInterfaceTable
, NULL
, CLSCTX_INPROC_SERVER
, &IID_IGlobalInterfaceTable
, (void **)&git
);
2617 ok_ole_success(hr
, CoCreateInstance
);
2619 hr
= IGlobalInterfaceTable_RegisterInterfaceInGlobal(git
, (IUnknown
*)&Test_ClassFactory
, &IID_IClassFactory
, &cookie
);
2620 ok_ole_success(hr
, IGlobalInterfaceTable_RegisterInterfaceInGlobal
);
2622 ok_more_than_one_lock();
2624 params
.cookie
= cookie
;
2626 /* note: params is on stack so we MUST wait for get_global_interface_proc
2627 * to exit before we can return */
2628 thread
= CreateThread(NULL
, 0, get_global_interface_proc
, ¶ms
, 0, &tid
);
2630 ret
= MsgWaitForMultipleObjects(1, &thread
, FALSE
, INFINITE
, QS_ALLINPUT
);
2631 while (ret
== WAIT_OBJECT_0
+ 1)
2634 while (PeekMessage(&msg
, NULL
, 0, 0, PM_REMOVE
))
2635 DispatchMessage(&msg
);
2636 ret
= MsgWaitForMultipleObjects(1, &thread
, FALSE
, INFINITE
, QS_ALLINPUT
);
2639 CloseHandle(thread
);
2641 /* test getting interface from global with different iid */
2642 hr
= IGlobalInterfaceTable_GetInterfaceFromGlobal(git
, cookie
, &IID_IUnknown
, (void **)&object
);
2643 ok_ole_success(hr
, IGlobalInterfaceTable_GetInterfaceFromGlobal
);
2644 IUnknown_Release(object
);
2646 /* test getting interface from global with same iid */
2647 hr
= IGlobalInterfaceTable_GetInterfaceFromGlobal(git
, cookie
, &IID_IClassFactory
, (void **)&object
);
2648 ok_ole_success(hr
, IGlobalInterfaceTable_GetInterfaceFromGlobal
);
2649 IUnknown_Release(object
);
2651 hr
= IGlobalInterfaceTable_RevokeInterfaceFromGlobal(git
, cookie
);
2652 ok_ole_success(hr
, IGlobalInterfaceTable_RevokeInterfaceFromGlobal
);
2656 IGlobalInterfaceTable_Release(git
);
2659 static const char *debugstr_iid(REFIID riid
)
2661 static char name
[256];
2665 LONG name_size
= sizeof(name
);
2666 StringFromGUID2(riid
, bufferW
, sizeof(bufferW
)/sizeof(bufferW
[0]));
2667 WideCharToMultiByte(CP_ACP
, 0, bufferW
, sizeof(bufferW
)/sizeof(bufferW
[0]), buffer
, sizeof(buffer
), NULL
, NULL
);
2668 if (RegOpenKeyEx(HKEY_CLASSES_ROOT
, "Interface", 0, KEY_QUERY_VALUE
, &hkeyInterface
) != ERROR_SUCCESS
)
2670 memcpy(name
, buffer
, sizeof(buffer
));
2673 if (RegQueryValue(hkeyInterface
, buffer
, name
, &name_size
) != ERROR_SUCCESS
)
2675 memcpy(name
, buffer
, sizeof(buffer
));
2678 RegCloseKey(hkeyInterface
);
2683 static HRESULT WINAPI
TestChannelHook_QueryInterface(IChannelHook
*iface
, REFIID riid
, void **ppv
)
2685 if (IsEqualIID(riid
, &IID_IUnknown
) || IsEqualIID(riid
, &IID_IChannelHook
))
2688 IUnknown_AddRef(iface
);
2693 return E_NOINTERFACE
;
2696 static ULONG WINAPI
TestChannelHook_AddRef(IChannelHook
*iface
)
2701 static ULONG WINAPI
TestChannelHook_Release(IChannelHook
*iface
)
2706 static void WINAPI
TestChannelHook_ClientGetSize(
2707 IChannelHook
*iface
,
2712 SChannelHookCallInfo
*info
= (SChannelHookCallInfo
*)riid
;
2713 trace("TestChannelHook_ClientGetBuffer\n");
2714 trace("\t%s method %d\n", debugstr_iid(riid
), info
->iMethod
);
2715 trace("\tcid: %s\n", debugstr_iid(&info
->uCausality
));
2716 ok(info
->cbSize
== sizeof(*info
), "info->cbSize was %d instead of %d\n", info
->cbSize
, (int)sizeof(*info
));
2717 ok(info
->dwServerPid
== GetCurrentProcessId(), "info->dwServerPid was 0x%x instead of 0x%x\n", info
->dwServerPid
, GetCurrentProcessId());
2718 ok(!info
->pObject
, "info->pObject should be NULL\n");
2719 ok(IsEqualGUID(uExtent
, &EXTENTID_WineTest
), "uExtent wasn't correct\n");
2724 static void WINAPI
TestChannelHook_ClientFillBuffer(
2725 IChannelHook
*iface
,
2731 SChannelHookCallInfo
*info
= (SChannelHookCallInfo
*)riid
;
2732 trace("TestChannelHook_ClientFillBuffer\n");
2733 ok(info
->cbSize
== sizeof(*info
), "info->cbSize was %d instead of %d\n", info
->cbSize
, (int)sizeof(*info
));
2734 ok(info
->dwServerPid
== GetCurrentProcessId(), "info->dwServerPid was 0x%x instead of 0x%x\n", info
->dwServerPid
, GetCurrentProcessId());
2735 ok(!info
->pObject
, "info->pObject should be NULL\n");
2736 ok(IsEqualGUID(uExtent
, &EXTENTID_WineTest
), "uExtent wasn't correct\n");
2738 *(unsigned char *)pDataBuffer
= 0xcc;
2742 static void WINAPI
TestChannelHook_ClientNotify(
2743 IChannelHook
*iface
,
2751 SChannelHookCallInfo
*info
= (SChannelHookCallInfo
*)riid
;
2752 trace("TestChannelHook_ClientNotify hrFault = 0x%08x\n", hrFault
);
2753 ok(info
->cbSize
== sizeof(*info
), "info->cbSize was %d instead of %d\n", info
->cbSize
, (int)sizeof(*info
));
2754 ok(info
->dwServerPid
== GetCurrentProcessId(), "info->dwServerPid was 0x%x instead of 0x%x\n", info
->dwServerPid
, GetCurrentProcessId());
2756 ok(info
->pObject
!= NULL
, "info->pObject shouldn't be NULL\n");
2758 ok(IsEqualGUID(uExtent
, &EXTENTID_WineTest
), "uExtent wasn't correct\n");
2761 static void WINAPI
TestChannelHook_ServerNotify(
2762 IChannelHook
*iface
,
2769 SChannelHookCallInfo
*info
= (SChannelHookCallInfo
*)riid
;
2770 trace("TestChannelHook_ServerNotify\n");
2771 ok(info
->cbSize
== sizeof(*info
), "info->cbSize was %d instead of %d\n", info
->cbSize
, (int)sizeof(*info
));
2772 ok(info
->dwServerPid
== GetCurrentProcessId(), "info->dwServerPid was 0x%x instead of 0x%x\n", info
->dwServerPid
, GetCurrentProcessId());
2773 ok(info
->pObject
!= NULL
, "info->pObject shouldn't be NULL\n");
2774 ok(cbDataSize
== 1, "cbDataSize should have been 1 instead of %d\n", cbDataSize
);
2775 ok(*(unsigned char *)pDataBuffer
== 0xcc, "pDataBuffer should have contained 0xcc instead of 0x%x\n", *(unsigned char *)pDataBuffer
);
2776 ok(IsEqualGUID(uExtent
, &EXTENTID_WineTest
), "uExtent wasn't correct\n");
2779 static void WINAPI
TestChannelHook_ServerGetSize(
2780 IChannelHook
*iface
,
2786 SChannelHookCallInfo
*info
= (SChannelHookCallInfo
*)riid
;
2787 trace("TestChannelHook_ServerGetSize\n");
2788 trace("\t%s method %d\n", debugstr_iid(riid
), info
->iMethod
);
2789 ok(info
->cbSize
== sizeof(*info
), "info->cbSize was %d instead of %d\n", info
->cbSize
, (int)sizeof(*info
));
2790 ok(info
->dwServerPid
== GetCurrentProcessId(), "info->dwServerPid was 0x%x instead of 0x%x\n", info
->dwServerPid
, GetCurrentProcessId());
2791 ok(info
->pObject
!= NULL
, "info->pObject shouldn't be NULL\n");
2792 ok(IsEqualGUID(uExtent
, &EXTENTID_WineTest
), "uExtent wasn't correct\n");
2793 if (hrFault
!= S_OK
)
2794 trace("\thrFault = 0x%08x\n", hrFault
);
2799 static void WINAPI
TestChannelHook_ServerFillBuffer(
2800 IChannelHook
*iface
,
2807 trace("TestChannelHook_ServerFillBuffer\n");
2808 ok(0, "TestChannelHook_ServerFillBuffer shouldn't be called\n");
2811 static const IChannelHookVtbl TestChannelHookVtbl
=
2813 TestChannelHook_QueryInterface
,
2814 TestChannelHook_AddRef
,
2815 TestChannelHook_Release
,
2816 TestChannelHook_ClientGetSize
,
2817 TestChannelHook_ClientFillBuffer
,
2818 TestChannelHook_ClientNotify
,
2819 TestChannelHook_ServerNotify
,
2820 TestChannelHook_ServerGetSize
,
2821 TestChannelHook_ServerFillBuffer
,
2824 static IChannelHook TestChannelHook
= { &TestChannelHookVtbl
};
2826 static void test_channel_hook(void)
2828 IStream
*pStream
= NULL
;
2829 IClassFactory
*cf
= NULL
;
2831 IUnknown
*proxy
= NULL
;
2835 hr
= CoRegisterChannelHook(&EXTENTID_WineTest
, &TestChannelHook
);
2836 ok_ole_success(hr
, CoRegisterChannelHook
);
2838 hr
= CoRegisterMessageFilter(&MessageFilter
, NULL
);
2839 ok_ole_success(hr
, CoRegisterMessageFilter
);
2843 hr
= CreateStreamOnHGlobal(NULL
, TRUE
, &pStream
);
2844 ok_ole_success(hr
, CreateStreamOnHGlobal
);
2845 tid
= start_host_object2(pStream
, &IID_IClassFactory
, (IUnknown
*)&Test_ClassFactory
, MSHLFLAGS_NORMAL
, &MessageFilter
, &thread
);
2847 ok_more_than_one_lock();
2849 IStream_Seek(pStream
, ullZero
, STREAM_SEEK_SET
, NULL
);
2850 hr
= CoUnmarshalInterface(pStream
, &IID_IClassFactory
, (void **)&cf
);
2851 ok_ole_success(hr
, CoUnmarshalInterface
);
2852 IStream_Release(pStream
);
2854 ok_more_than_one_lock();
2856 hr
= IClassFactory_CreateInstance(cf
, NULL
, &IID_IUnknown
, (LPVOID
*)&proxy
);
2857 ok_ole_success(hr
, IClassFactory_CreateInstance
);
2858 IUnknown_Release(proxy
);
2860 IClassFactory_Release(cf
);
2864 end_host_object(tid
, thread
);
2866 hr
= CoRegisterMessageFilter(NULL
, NULL
);
2867 ok_ole_success(hr
, CoRegisterMessageFilter
);
2873 HMODULE hOle32
= GetModuleHandle("ole32");
2877 if (!(pCoInitializeEx
= (void*)GetProcAddress(hOle32
, "CoInitializeEx"))) goto no_test
;
2879 argc
= winetest_get_mainargs( &argv
);
2880 if (argc
> 2 && (!strcmp(argv
[2], "-Embedding")))
2882 pCoInitializeEx(NULL
, COINIT_APARTMENTTHREADED
);
2883 test_register_local_server();
2889 /* register a window class used in several tests */
2890 memset(&wndclass
, 0, sizeof(wndclass
));
2891 wndclass
.lpfnWndProc
= window_proc
;
2892 wndclass
.lpszClassName
= "WineCOMTest";
2893 RegisterClass(&wndclass
);
2895 test_cocreateinstance_proxy();
2897 pCoInitializeEx(NULL
, COINIT_APARTMENTTHREADED
);
2899 /* FIXME: test CoCreateInstanceEx */
2901 /* lifecycle management and marshaling tests */
2902 test_no_marshaler();
2903 test_normal_marshal_and_release();
2904 test_normal_marshal_and_unmarshal();
2905 test_marshal_and_unmarshal_invalid();
2906 test_same_apartment_unmarshal_failure();
2907 test_interthread_marshal_and_unmarshal();
2908 test_proxy_marshal_and_unmarshal();
2909 test_proxy_marshal_and_unmarshal2();
2910 test_proxy_marshal_and_unmarshal_weak();
2911 test_proxy_marshal_and_unmarshal_strong();
2912 test_marshal_stub_apartment_shutdown();
2913 test_marshal_proxy_apartment_shutdown();
2914 test_marshal_proxy_mta_apartment_shutdown();
2915 test_no_couninitialize_server();
2916 test_no_couninitialize_client();
2917 test_tableweak_marshal_and_unmarshal_twice();
2918 test_tableweak_marshal_releasedata1();
2919 test_tableweak_marshal_releasedata2();
2920 test_tablestrong_marshal_and_unmarshal_twice();
2921 test_lock_object_external();
2922 test_disconnect_stub();
2923 test_normal_marshal_and_unmarshal_twice();
2924 test_hresult_marshaling();
2925 test_proxy_used_in_wrong_thread();
2926 test_message_filter();
2927 test_bad_marshal_stream();
2928 test_proxy_interfaces();
2929 test_stubbuffer(&IID_IClassFactory
);
2930 test_proxybuffer(&IID_IClassFactory
);
2931 test_message_reentrancy();
2932 test_call_from_message();
2933 test_WM_QUIT_handling();
2934 test_freethreadedmarshaler();
2935 test_inproc_handler();
2936 test_handler_marshaling();
2937 test_client_security();
2939 test_local_server();
2941 test_globalinterfacetable();
2943 /* must be last test as channel hooks can't be unregistered */
2944 test_channel_hook();
2950 trace("You need DCOM95 installed to run this test\n");