ReactOS 0.4.15-dev-5893-g1bb4167
marshal.c
Go to the documentation of this file.
1/*
2 * Marshaling Tests
3 *
4 * Copyright 2004 Robert Shearman
5 *
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.
10 *
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.
15 *
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
19 */
20
21#define _WIN32_DCOM
22#define COBJMACROS
23#define CONST_VTABLE
24
25#include <stdarg.h>
26#include <stdio.h>
27
28#include "windef.h"
29#include "winbase.h"
30#include "objbase.h"
31#include "olectl.h"
32#include "shlguid.h"
33#include "shobjidl.h"
34
35#include "wine/test.h"
36#include "wine/heap.h"
37
38#define DEFINE_EXPECT(func) \
39 static BOOL expect_ ## func = FALSE, called_ ## func = FALSE
40
41#define SET_EXPECT(func) \
42 expect_ ## func = TRUE
43
44#define CHECK_EXPECT2(func) \
45 do { \
46 ok(expect_ ##func, "unexpected call " #func "\n"); \
47 called_ ## func = TRUE; \
48 }while(0)
49
50#define CHECK_EXPECT(func) \
51 do { \
52 CHECK_EXPECT2(func); \
53 expect_ ## func = FALSE; \
54 }while(0)
55
56#define CHECK_CALLED(func) \
57 do { \
58 ok(called_ ## func, "expected " #func "\n"); \
59 expect_ ## func = called_ ## func = FALSE; \
60 }while(0)
61
62static const GUID CLSID_WineTestPSFactoryBuffer = { 0x22222222, 0x1234, 0x1234, { 0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0 } };
63static const GUID CLSID_DfMarshal = { 0x0000030b, 0x0000, 0x0000, { 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46 } };
64
65/* functions that are not present on all versions of Windows */
66static HRESULT (WINAPI * pCoInitializeEx)(LPVOID lpReserved, DWORD dwCoInit);
67static HRESULT (WINAPI *pDllGetClassObject)(REFCLSID,REFIID,LPVOID);
68
69/* helper macros to make tests a bit leaner */
70#define ok_more_than_one_lock() ok(cLocks > 0, "Number of locks should be > 0, but actually is %d\n", cLocks)
71#define ok_no_locks() ok(cLocks == 0, "Number of locks should be 0, but actually is %d\n", cLocks)
72#define ok_ole_success(hr, func) ok(hr == S_OK, #func " failed with error 0x%08x\n", hr)
73#define ok_non_zero_external_conn() do {if (with_external_conn) ok(external_connections, "got no external connections\n");} while(0);
74#define ok_zero_external_conn() do {if (with_external_conn) ok(!external_connections, "got %d external connections\n", external_connections);} while(0);
75#define ok_last_release_closes(b) do {if (with_external_conn) ok(last_release_closes == b, "got %d expected %d\n", last_release_closes, b);} while(0);
76
77#define OBJREF_SIGNATURE (0x574f454d)
78#define OBJREF_STANDARD (0x1)
79#define OBJREF_CUSTOM (0x4)
80
81typedef struct tagDUALSTRINGARRAY {
82 unsigned short wNumEntries;
83 unsigned short wSecurityOffset;
84 unsigned short aStringArray[1];
86
87typedef UINT64 OXID;
88typedef UINT64 OID;
89typedef GUID IPID;
90
91typedef struct tagSTDOBJREF {
98
99typedef struct tagOBJREF {
103 union {
104 struct OR_STANDARD {
108 struct OR_HANDLER {
111 DUALSTRINGARRAY saResAddr;
113 struct OR_CUSTOM {
114 CLSID clsid;
117 byte *pData;
121
122static const IID IID_IWineTest =
123{
124 0x5201163f,
125 0x8164,
126 0x4fd0,
127 {0xa1, 0xa2, 0x5d, 0x5a, 0x36, 0x54, 0xd3, 0xbd}
128}; /* 5201163f-8164-4fd0-a1a2-5d5a3654d3bd */
129
130static const IID IID_IRemUnknown =
131{
132 0x00000131,
133 0x0000,
134 0x0000,
135 {0xc0,0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46}
136};
137
138#define EXTENTID_WineTest IID_IWineTest
139#define CLSID_WineTest IID_IWineTest
140
142{
143 0x5201163f,
144 0x8164,
145 0x4fd0,
146 {0xa1, 0xa2, 0x5d, 0x5a, 0x36, 0x54, 0xd3, 0xbd}
147}; /* 5201163f-8164-4fd0-a1a2-5d5a3654d3bd */
148
150{
151 IUnknown *pProxy;
152 IMultiQI *pMQI;
153 HRESULT hr;
154
155 pCoInitializeEx(NULL, COINIT_MULTITHREADED);
156
157 hr = CoCreateInstance(&CLSID_ShellDesktop, NULL, CLSCTX_INPROC, &IID_IUnknown, (void **)&pProxy);
159 hr = IUnknown_QueryInterface(pProxy, &IID_IMultiQI, (void **)&pMQI);
160 ok(hr == S_OK, "created object is not a proxy, so was created in the wrong apartment\n");
161 if (hr == S_OK)
162 IMultiQI_Release(pMQI);
163 IUnknown_Release(pProxy);
164
166}
167
170
171static void LockModule(void)
172{
174}
175
176static void UnlockModule(void)
177{
179}
180
184
186{
187 ok(0, "unexpected call\n");
188 *ppv = NULL;
189 return E_NOINTERFACE;
190}
191
193{
194 return 2;
195}
196
198{
199 return 1;
200}
201
203{
204 trace("add connection\n");
205 return ++external_connections;
206}
207
208
210 DWORD reserved, BOOL fLastReleaseCloses)
211{
212 trace("release connection %d\n", fLastReleaseCloses);
213 last_release_closes = fLastReleaseCloses;
214 return --external_connections;
215}
216
217static const IExternalConnectionVtbl ExternalConnectionVtbl = {
223};
224
226
227
229 LPUNKNOWN iface,
230 REFIID riid,
231 LPVOID *ppvObj)
232{
233 if (ppvObj == NULL) return E_POINTER;
234
236 {
237 *ppvObj = iface;
238 IUnknown_AddRef(iface);
239 return S_OK;
240 }
241
242 *ppvObj = NULL;
243 return E_NOINTERFACE;
244}
245
247{
248 LockModule();
249 return 2; /* non-heap-based object */
250}
251
253{
254 UnlockModule();
255 return 1; /* non-heap-based object */
256}
257
258static const IUnknownVtbl TestUnknown_Vtbl =
259{
263};
264
266
268{
269 UnlockModule();
270 if(!cLocks) {
271 trace("crashing...\n");
272 *(int**)0xc = 0;
273 }
274 return 1; /* non-heap-based object */
275}
276
277static const IUnknownVtbl TestCrashUnknown_Vtbl =
278{
282};
283
285
287 LPCLASSFACTORY iface,
288 REFIID riid,
289 LPVOID *ppvObj)
290{
291 if (ppvObj == NULL) return E_POINTER;
292
295 /* the only other interface Wine is currently able to marshal (for testing two proxies) */
297 {
298 *ppvObj = iface;
299 IClassFactory_AddRef(iface);
300 return S_OK;
301 }
302
303 if (with_external_conn && IsEqualGUID(riid, &IID_IExternalConnection))
304 {
305 *ppvObj = &ExternalConnection;
306 return S_OK;
307 }
308
309 *ppvObj = NULL;
310 return E_NOINTERFACE;
311}
312
313static ULONG WINAPI Test_IClassFactory_AddRef(LPCLASSFACTORY iface)
314{
315 LockModule();
316 return 2; /* non-heap-based object */
317}
318
319static ULONG WINAPI Test_IClassFactory_Release(LPCLASSFACTORY iface)
320{
321 UnlockModule();
322 return 1; /* non-heap-based object */
323}
324
326 LPCLASSFACTORY iface,
327 LPUNKNOWN pUnkOuter,
328 REFIID riid,
329 LPVOID *ppvObj)
330{
331 if (pUnkOuter) return CLASS_E_NOAGGREGATION;
332 return IUnknown_QueryInterface(&Test_Unknown, riid, ppvObj);
333}
334
336 LPCLASSFACTORY iface,
337 BOOL fLock)
338{
339 return S_OK;
340}
341
342static const IClassFactoryVtbl TestClassFactory_Vtbl =
343{
349};
350
352
354DEFINE_EXPECT(CreateStub);
355DEFINE_EXPECT(CreateProxy);
357DEFINE_EXPECT(Disconnect);
358
360{
361 ok(0, "unexpected call %s\n", wine_dbgstr_guid(riid));
362 *ppv = NULL;
363 return E_NOINTERFACE;
364}
365
367{
368 return 2;
369}
370
372{
373 return 1;
374}
375
377{
379 *hwnd = (HWND)0xdeadbeef;
380 return S_OK;
381}
382
383static const IOleWindowVtbl OleWindowVtbl = {
388 /* not needed */
389};
390
392
394{
396 *ppv = iface;
397 else if (IsEqualGUID(riid, &IID_IOleWindow))
399 else
400 {
401 *ppv = NULL;
402 return E_NOINTERFACE;
403 }
404
405 IUnknown_AddRef((IUnknown*)*ppv);
406 return S_OK;
407}
408
410{
411 return 2;
412}
413
415{
416 return 1;
417}
418
419static const IOleClientSiteVtbl OleClientSiteVtbl = {
423 /* we don't need the rest, we never call it */
424};
425
427
428typedef struct {
433
435{
436 return CONTAINING_RECORD(iface, StubBufferWrapper, IRpcStubBuffer_iface);
437}
438
440{
442
443 if(IsEqualGUID(&IID_IUnknown, riid) || IsEqualGUID(&IID_IRpcStubBuffer, riid)) {
444 *ppv = &This->IRpcStubBuffer_iface;
445 }else {
446 *ppv = NULL;
447 return E_NOINTERFACE;
448 }
449
450 IUnknown_AddRef((IUnknown*)*ppv);
451 return S_OK;
452}
453
455{
457 return InterlockedIncrement(&This->ref);
458}
459
461{
464 if(!ref) {
465 IRpcStubBuffer_Release(This->buffer);
467 }
468 return ref;
469}
470
472{
473 ok(0, "unexpected call\n");
474 return E_NOTIMPL;
475}
476
478{
479 CHECK_EXPECT(Disconnect);
480}
481
482static HRESULT WINAPI RpcStubBuffer_Invoke(IRpcStubBuffer *iface, RPCOLEMESSAGE *_prpcmsg,
483 IRpcChannelBuffer *_pRpcChannelBuffer)
484{
486 void *dest_context_data;
487 DWORD dest_context;
488 HRESULT hr;
489
490 CHECK_EXPECT(Invoke);
491
492 hr = IRpcChannelBuffer_GetDestCtx(_pRpcChannelBuffer, &dest_context, &dest_context_data);
493 ok(hr == S_OK, "GetDestCtx failed: %08x\n", hr);
494 ok(dest_context == MSHCTX_INPROC, "desc_context = %x\n", dest_context);
495 ok(!dest_context_data, "desc_context_data = %p\n", dest_context_data);
496
497 return IRpcStubBuffer_Invoke(This->buffer, _prpcmsg, _pRpcChannelBuffer);
498}
499
501{
502 ok(0, "unexpected call\n");
503 return NULL;
504}
505
507{
508 ok(0, "unexpected call\n");
509 return E_NOTIMPL;
510}
511
513{
514 ok(0, "unexpected call\n");
515 return E_NOTIMPL;
516}
517
519{
520 ok(0, "unexpected call\n");
521}
522
523static const IRpcStubBufferVtbl RpcStubBufferVtbl = {
534};
535
537
539{
540 if (IsEqualIID(riid, &IID_IUnknown) || IsEqualIID(riid, &IID_IPSFactoryBuffer))
541 *ppv = iface;
542 else
543 {
544 *ppv = NULL;
545 return E_NOINTERFACE;
546 }
547 IUnknown_AddRef((IUnknown*)*ppv);
548 return S_OK;
549}
550
552{
553 return 2;
554}
555
557{
558 return 1;
559}
560
562 REFIID riid, IRpcProxyBuffer **ppProxy, void **ppv)
563{
564 CHECK_EXPECT(CreateProxy);
565 return IPSFactoryBuffer_CreateProxy(ps_factory_buffer, outer, riid, ppProxy, ppv);
566}
567
569 IUnknown *server, IRpcStubBuffer **ppStub)
570{
572 HRESULT hr;
573
574 CHECK_EXPECT(CreateStub);
575
576 ok(server == (IUnknown*)&Test_OleClientSite, "unexpected server %p\n", server);
577
578 stub = heap_alloc(sizeof(*stub));
579 stub->IRpcStubBuffer_iface.lpVtbl = &RpcStubBufferVtbl;
580 stub->ref = 1;
581
582 hr = IPSFactoryBuffer_CreateStub(ps_factory_buffer, riid, server, &stub->buffer);
583 ok(hr == S_OK, "CreateStub failed: %08x\n", hr);
584
585 *ppStub = &stub->IRpcStubBuffer_iface;
586 return S_OK;
587}
588
589static IPSFactoryBufferVtbl PSFactoryBufferVtbl =
590{
596};
597
599
600#define RELEASEMARSHALDATA WM_USER
601
603{
605 const IID *iid;
607 MSHLFLAGS marshal_flags;
612};
613
614#ifndef __REACTOS__ /* FIXME: Inspect */
616#endif
617
619{
620 struct host_object_data *data = p;
621 DWORD registration_key;
622 HRESULT hr;
623 MSG msg;
624
625 pCoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
626
627 if(data->register_object) {
628 hr = CoRegisterClassObject(data->register_clsid, data->register_object,
629 CLSCTX_INPROC_SERVER, REGCLS_MULTIPLEUSE, &registration_key);
630 ok(hr == S_OK, "CoRegisterClassObject failed: %08x\n", hr);
631 }
632
633 if (data->filter)
634 {
635 IMessageFilter * prev_filter = NULL;
636 hr = CoRegisterMessageFilter(data->filter, &prev_filter);
637 if (prev_filter) IMessageFilter_Release(prev_filter);
639 }
640
641 hr = CoMarshalInterface(data->stream, data->iid, data->object, MSHCTX_INPROC, NULL, data->marshal_flags);
643
644 /* force the message queue to be created before signaling parent thread */
646
647 SetEvent(data->marshal_event);
648
649 while (GetMessageA(&msg, NULL, 0, 0))
650 {
651 if (msg.hwnd == NULL && msg.message == RELEASEMARSHALDATA)
652 {
653 CoReleaseMarshalData(data->stream);
654 SetEvent((HANDLE)msg.lParam);
655 }
656 else
658 }
659
661
663
664 return hr;
665}
666
668{
669 DWORD tid = 0;
670 struct host_object_data *data;
671
672 data = HeapAlloc(GetProcessHeap(), 0, sizeof(*data));
673 *data = *object_data;
676
677 /* wait for marshaling to complete before returning */
678 ok( !WaitForSingleObject(data->marshal_event, 10000), "wait timed out\n" );
679 CloseHandle(data->marshal_event);
680
681 return tid;
682}
683
685{
686 struct host_object_data object_data = { stream, riid, object, marshal_flags };
687 return start_host_object2(&object_data, thread);
688}
689
690/* asks thread to release the marshal data because it has to be done by the
691 * same thread that marshaled the interface in the first place. */
693{
696 ok( !WaitForSingleObject(event, 10000), "wait timed out\n" );
698}
699
701{
703 ok(ret, "PostThreadMessage failed with error %d\n", GetLastError());
704 /* be careful of races - don't return until hosting thread has terminated */
705 ok( !WaitForSingleObject(thread, 10000), "wait timed out\n" );
707}
708
709/* tests failure case of interface not having a marshaler specified in the
710 * registry */
711static void test_no_marshaler(void)
712{
713 IStream *pStream;
714 HRESULT hr;
715
716 hr = CreateStreamOnHGlobal(NULL, TRUE, &pStream);
718 hr = CoMarshalInterface(pStream, &IID_IWineTest, (IUnknown*)&Test_ClassFactory, MSHCTX_INPROC, NULL, MSHLFLAGS_NORMAL);
719 ok(hr == E_NOINTERFACE, "CoMarshalInterface should have returned E_NOINTERFACE instead of 0x%08x\n", hr);
720
721 IStream_Release(pStream);
722}
723
724/* tests normal marshal and then release without unmarshaling */
726{
727 HRESULT hr;
728 IStream *pStream = NULL;
729
730 cLocks = 0;
732
733 hr = CreateStreamOnHGlobal(NULL, TRUE, &pStream);
735 hr = CoMarshalInterface(pStream, &IID_IClassFactory, (IUnknown*)&Test_ClassFactory, MSHCTX_INPROC, NULL, MSHLFLAGS_NORMAL);
737
740
741 IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
742 hr = CoReleaseMarshalData(pStream);
744 IStream_Release(pStream);
745
746 ok_no_locks();
749}
750
751/* tests success case of a same-thread marshal and unmarshal */
753{
754 HRESULT hr;
755 IStream *pStream = NULL;
756 IUnknown *pProxy = NULL;
757
758 cLocks = 0;
760
761 hr = CreateStreamOnHGlobal(NULL, TRUE, &pStream);
763 hr = CoMarshalInterface(pStream, &IID_IClassFactory, (IUnknown*)&Test_ClassFactory, MSHCTX_INPROC, NULL, MSHLFLAGS_NORMAL);
765
768
769 IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
770 hr = CoUnmarshalInterface(pStream, &IID_IClassFactory, (void **)&pProxy);
772 IStream_Release(pStream);
773
777
778 IUnknown_Release(pProxy);
779
780 ok_no_locks();
781}
782
783/* tests failure case of unmarshaling a freed object */
785{
786 HRESULT hr;
787 IStream *pStream = NULL;
788 IClassFactory *pProxy = NULL;
789 DWORD tid;
790 void * dummy;
792
793 cLocks = 0;
795
796 hr = CreateStreamOnHGlobal(NULL, TRUE, &pStream);
798 tid = start_host_object(pStream, &IID_IClassFactory, (IUnknown*)&Test_ClassFactory, MSHLFLAGS_NORMAL, &thread);
799
802
803 IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
804 hr = CoReleaseMarshalData(pStream);
806
807 ok_no_locks();
810
811 IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
812 hr = CoUnmarshalInterface(pStream, &IID_IClassFactory, (void **)&pProxy);
814
815 ok_no_locks();
816
817 if (pProxy)
818 {
819 hr = IClassFactory_CreateInstance(pProxy, NULL, &IID_IUnknown, &dummy);
820 ok(hr == RPC_E_DISCONNECTED, "Remote call should have returned RPC_E_DISCONNECTED, instead of 0x%08x\n", hr);
821
822 IClassFactory_Release(pProxy);
823 }
824
825 IStream_Release(pStream);
826
828}
829
831{
832 HRESULT hr;
833 IStream *pStream;
834 IUnknown *pProxy;
835 static const LARGE_INTEGER llZero;
836
837 cLocks = 0;
839
840 hr = CreateStreamOnHGlobal(NULL, TRUE, &pStream);
842
843 hr = CoMarshalInterface(pStream, &IID_IUnknown, (IUnknown *)&Test_ClassFactory, MSHCTX_INPROC, NULL, MSHLFLAGS_NORMAL);
845
848
849 hr = IStream_Seek(pStream, llZero, STREAM_SEEK_SET, NULL);
850 ok_ole_success(hr, IStream_Seek);
851
852 hr = CoUnmarshalInterface(pStream, &IID_IParseDisplayName, (void **)&pProxy);
853 ok(hr == E_NOINTERFACE, "CoUnmarshalInterface should have returned E_NOINTERFACE instead of 0x%08x\n", hr);
854
855 ok_no_locks();
858
859 IStream_Release(pStream);
860}
861
862/* tests success case of an interthread marshal */
864{
865 HRESULT hr;
866 IStream *pStream = NULL;
867 IUnknown *pProxy = NULL;
868 DWORD tid;
870
871 cLocks = 0;
873
874 hr = CreateStreamOnHGlobal(NULL, TRUE, &pStream);
876 tid = start_host_object(pStream, &IID_IClassFactory, (IUnknown*)&Test_ClassFactory, MSHLFLAGS_NORMAL, &thread);
877
880
881 IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
882 hr = CoUnmarshalInterface(pStream, &IID_IClassFactory, (void **)&pProxy);
884 IStream_Release(pStream);
885
888
889 IUnknown_Release(pProxy);
890
891 ok_no_locks();
894
896}
897
898/* the number of external references that Wine's proxy manager normally gives
899 * out, so we can test the border case of running out of references */
900#define NORMALEXTREFS 5
901
902/* tests success case of an interthread marshal and then marshaling the proxy */
904{
905 HRESULT hr;
906 IStream *pStream = NULL;
907 IUnknown *pProxy = NULL;
908 IUnknown *pProxy2 = NULL;
909 DWORD tid;
911 int i;
912
913 cLocks = 0;
915
916 hr = CreateStreamOnHGlobal(NULL, TRUE, &pStream);
918 tid = start_host_object(pStream, &IID_IClassFactory, (IUnknown*)&Test_ClassFactory, MSHLFLAGS_NORMAL, &thread);
919
922
923 IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
924 hr = CoUnmarshalInterface(pStream, &IID_IClassFactory, (void **)&pProxy);
926
928
929 IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
930 /* marshal the proxy */
931 hr = CoMarshalInterface(pStream, &IID_IClassFactory, pProxy, MSHCTX_INPROC, NULL, MSHLFLAGS_NORMAL);
933
935
936 /* marshal 5 more times to exhaust the normal external references of 5 */
937 for (i = 0; i < NORMALEXTREFS; i++)
938 {
939 hr = CoMarshalInterface(pStream, &IID_IClassFactory, pProxy, MSHCTX_INPROC, NULL, MSHLFLAGS_NORMAL);
941 }
942
944
945 /* release the original proxy to test that we successfully keep the
946 * original object alive */
947 IUnknown_Release(pProxy);
948
949 IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
950 hr = CoUnmarshalInterface(pStream, &IID_IClassFactory, (void **)&pProxy2);
952
955
956 IUnknown_Release(pProxy2);
957
958 /* unmarshal all of the proxies to check that the object stub still exists */
959 for (i = 0; i < NORMALEXTREFS; i++)
960 {
961 hr = CoUnmarshalInterface(pStream, &IID_IClassFactory, (void **)&pProxy2);
963
964 IUnknown_Release(pProxy2);
965 }
966
967 ok_no_locks();
970
971 IStream_Release(pStream);
972
974}
975
976/* tests success case of an interthread marshal and then marshaling the proxy
977 * using an iid that hasn't previously been unmarshaled */
979{
980 HRESULT hr;
981 IStream *pStream = NULL;
982 IUnknown *pProxy = NULL;
983 IUnknown *pProxy2 = NULL;
984 DWORD tid;
986
987 cLocks = 0;
989
990 hr = CreateStreamOnHGlobal(NULL, TRUE, &pStream);
992 tid = start_host_object(pStream, &IID_IUnknown, (IUnknown*)&Test_ClassFactory, MSHLFLAGS_NORMAL, &thread);
993
996
997 IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
998 hr = CoUnmarshalInterface(pStream, &IID_IUnknown, (void **)&pProxy);
1000
1002
1003 IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
1004 /* marshal the proxy */
1005 hr = CoMarshalInterface(pStream, &IID_IClassFactory, pProxy, MSHCTX_INPROC, NULL, MSHLFLAGS_NORMAL);
1007
1009
1010 IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
1011 /* unmarshal the second proxy to the object */
1012 hr = CoUnmarshalInterface(pStream, &IID_IClassFactory, (void **)&pProxy2);
1014 IStream_Release(pStream);
1015
1016 /* now the proxies should be as follows:
1017 * pProxy -> &Test_ClassFactory
1018 * pProxy2 -> &Test_ClassFactory
1019 * they should NOT be as follows:
1020 * pProxy -> &Test_ClassFactory
1021 * pProxy2 -> pProxy
1022 * the above can only really be tested by looking in +ole traces
1023 */
1024
1026
1027 IUnknown_Release(pProxy);
1028
1031
1032 IUnknown_Release(pProxy2);
1033
1034 ok_no_locks();
1037
1039}
1040
1041/* tests success case of an interthread marshal and then table-weak-marshaling the proxy */
1043{
1044 HRESULT hr;
1045 IStream *pStream = NULL;
1046 IUnknown *pProxy = NULL;
1047 IUnknown *pProxy2 = NULL;
1048 DWORD tid;
1049 HANDLE thread;
1050
1051 cLocks = 0;
1053
1054 hr = CreateStreamOnHGlobal(NULL, TRUE, &pStream);
1056 tid = start_host_object(pStream, &IID_IClassFactory, (IUnknown*)&Test_ClassFactory, MSHLFLAGS_NORMAL, &thread);
1057
1060
1061 IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
1062 hr = CoUnmarshalInterface(pStream, &IID_IClassFactory, (void **)&pProxy);
1064
1067
1068 IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
1069 /* marshal the proxy */
1070 hr = CoMarshalInterface(pStream, &IID_IClassFactory, pProxy, MSHCTX_INPROC, NULL, MSHLFLAGS_TABLEWEAK);
1072
1075
1076 /* release the original proxy to test that we successfully keep the
1077 * original object alive */
1078 IUnknown_Release(pProxy);
1079
1080 IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
1081 hr = CoUnmarshalInterface(pStream, &IID_IClassFactory, (void **)&pProxy2);
1082 todo_wine
1083 ok(hr == CO_E_OBJNOTREG, "CoUnmarshalInterface should return CO_E_OBJNOTREG instead of 0x%08x\n", hr);
1084
1085 ok_no_locks();
1088
1089 IStream_Release(pStream);
1090
1092}
1093
1094/* tests success case of an interthread marshal and then table-strong-marshaling the proxy */
1096{
1097 HRESULT hr;
1098 IStream *pStream = NULL;
1099 IUnknown *pProxy = NULL;
1100 IUnknown *pProxy2 = NULL;
1101 DWORD tid;
1102 HANDLE thread;
1103
1104 cLocks = 0;
1106
1107 hr = CreateStreamOnHGlobal(NULL, TRUE, &pStream);
1109 tid = start_host_object(pStream, &IID_IClassFactory, (IUnknown*)&Test_ClassFactory, MSHLFLAGS_NORMAL, &thread);
1110
1113
1114 IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
1115 hr = CoUnmarshalInterface(pStream, &IID_IClassFactory, (void **)&pProxy);
1117
1120
1121 IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
1122 /* marshal the proxy */
1123 hr = CoMarshalInterface(pStream, &IID_IClassFactory, pProxy, MSHCTX_INPROC, NULL, MSHLFLAGS_TABLESTRONG);
1124 ok(hr == S_OK /* WinNT */ || hr == E_INVALIDARG /* Win9x */,
1125 "CoMarshalInterface should have return S_OK or E_INVALIDARG instead of 0x%08x\n", hr);
1126 if (FAILED(hr))
1127 {
1128 IUnknown_Release(pProxy);
1129 goto end;
1130 }
1131
1134
1135 /* release the original proxy to test that we successfully keep the
1136 * original object alive */
1137 IUnknown_Release(pProxy);
1138
1139 IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
1140 hr = CoUnmarshalInterface(pStream, &IID_IClassFactory, (void **)&pProxy2);
1142
1145
1146 IUnknown_Release(pProxy2);
1147
1150
1151end:
1152 IStream_Release(pStream);
1153
1155
1156 ok_no_locks();
1157todo_wine {
1160}
1161}
1162
1163/* tests that stubs are released when the containing apartment is destroyed */
1165{
1166 HRESULT hr;
1167 IStream *pStream = NULL;
1168 IUnknown *pProxy = NULL;
1169 DWORD tid;
1170 HANDLE thread;
1171
1172 cLocks = 0;
1174
1175 hr = CreateStreamOnHGlobal(NULL, TRUE, &pStream);
1177 tid = start_host_object(pStream, &IID_IClassFactory, (IUnknown*)&Test_ClassFactory, MSHLFLAGS_NORMAL, &thread);
1178
1181
1182 IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
1183 hr = CoUnmarshalInterface(pStream, &IID_IClassFactory, (void **)&pProxy);
1185 IStream_Release(pStream);
1186
1189
1191
1192 ok_no_locks();
1193todo_wine {
1196}
1197
1198 IUnknown_Release(pProxy);
1199
1200 ok_no_locks();
1201}
1202
1203/* tests that proxies are released when the containing apartment is destroyed */
1205{
1206 HRESULT hr;
1207 IStream *pStream = NULL;
1209 IUnknown *unk;
1210 ULONG ref;
1211 DWORD tid;
1212 HANDLE thread;
1213
1214 cLocks = 0;
1216
1217 hr = CreateStreamOnHGlobal(NULL, TRUE, &pStream);
1219 tid = start_host_object(pStream, &IID_IClassFactory, (IUnknown*)&Test_ClassFactory, MSHLFLAGS_NORMAL, &thread);
1220
1223
1224 IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
1225 hr = CoUnmarshalInterface(pStream, &IID_IClassFactory, (void **)&proxy);
1227 IStream_Release(pStream);
1228
1231
1233
1234 ok_no_locks();
1237
1238 hr = IClassFactory_CreateInstance(proxy, NULL, &IID_IUnknown, (void **)&unk);
1239 ok(hr == CO_E_OBJNOTCONNECTED, "got %#x\n", hr);
1240
1241 ref = IClassFactory_Release(proxy);
1242 ok(!ref, "got %d refs\n", ref);
1243
1244 ok_no_locks();
1245
1247
1248 pCoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
1249}
1250
1251/* tests that proxies are released when the containing mta apartment is destroyed */
1253{
1254 HRESULT hr;
1255 IStream *pStream = NULL;
1256 IUnknown *pProxy = NULL;
1257 DWORD tid;
1258 HANDLE thread;
1259
1261 pCoInitializeEx(NULL, COINIT_MULTITHREADED);
1262
1263 cLocks = 0;
1265
1266 hr = CreateStreamOnHGlobal(NULL, TRUE, &pStream);
1268 tid = start_host_object(pStream, &IID_IClassFactory, (IUnknown*)&Test_ClassFactory, MSHLFLAGS_NORMAL, &thread);
1269
1272
1273 IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
1274 hr = CoUnmarshalInterface(pStream, &IID_IClassFactory, (void **)&pProxy);
1276 IStream_Release(pStream);
1277
1280
1282
1283 ok_no_locks();
1286
1287 IUnknown_Release(pProxy);
1288
1289 ok_no_locks();
1290
1292
1293 pCoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
1294}
1295
1297{
1298 DWORD registration_key;
1299 IUnknown *proxy = NULL;
1300 IOleWindow *ole_window;
1301 HWND hwnd;
1302 CLSID clsid;
1303 DWORD tid;
1304 HANDLE thread;
1305 HRESULT hr;
1306
1308 MSHLFLAGS_NORMAL, NULL, (IUnknown*)&PSFactoryBuffer,
1310
1311 cLocks = 0;
1313
1315 ok_ole_success(hr, "CoGetPSClsid");
1316
1317 hr = CoGetClassObject(&clsid, CLSCTX_INPROC_SERVER, NULL, &IID_IPSFactoryBuffer,
1318 (void **)&ps_factory_buffer);
1319 ok_ole_success(hr, "CoGetClassObject");
1320
1321 hr = CreateStreamOnHGlobal(NULL, TRUE, &object_data.stream);
1323 tid = start_host_object2(&object_data, &thread);
1324
1325 IStream_Seek(object_data.stream, ullZero, STREAM_SEEK_SET, NULL);
1326 hr = CoUnmarshalInterface(object_data.stream, &IID_IUnknown, (void **)&proxy);
1328 IStream_Release(object_data.stream);
1329
1331 CLSCTX_INPROC_SERVER, REGCLS_MULTIPLEUSE, &registration_key);
1332 ok(hr == S_OK, "CoRegisterClassObject failed: %08x\n", hr);
1333
1335 ok(hr == S_OK, "CoRegisterPSClsid failed: %08x\n", hr);
1336
1337 SET_EXPECT(CreateStub);
1338 SET_EXPECT(CreateProxy);
1339 hr = IUnknown_QueryInterface(proxy, &IID_IOleWindow, (void**)&ole_window);
1340 ok(hr == S_OK, "Could not get IOleWindow iface: %08x\n", hr);
1341 CHECK_CALLED(CreateStub);
1342 CHECK_CALLED(CreateProxy);
1343
1344 SET_EXPECT(Invoke);
1346 hr = IOleWindow_GetWindow(ole_window, &hwnd);
1347 ok(hr == S_OK, "GetWindow failed: %08x\n", hr);
1348 ok((DWORD)(DWORD_PTR)hwnd == 0xdeadbeef, "hwnd = %p\n", hwnd);
1349 CHECK_CALLED(Invoke);
1351
1352 IOleWindow_Release(ole_window);
1353
1354 SET_EXPECT(Disconnect);
1355 IUnknown_Release(proxy);
1357 CHECK_CALLED(Disconnect);
1358
1359 hr = CoRevokeClassObject(registration_key);
1360 ok(hr == S_OK, "CoRevokeClassObject failed: %08x\n", hr);
1361
1363}
1364
1369
1371{
1372 if (IsEqualIID(riid, &IID_IUnknown) || IsEqualIID(riid, &IID_IMarshal)) {
1373 *ppv = iface;
1374 }
1375 else
1376 {
1377 *ppv = NULL;
1378 return E_NOINTERFACE;
1379 }
1380 IUnknown_AddRef((IUnknown*)*ppv);
1381 return S_OK;
1382}
1383
1385{
1386 return 2;
1387}
1388
1390{
1391 return 1;
1392}
1393
1395 void *pv, DWORD dwDestContext, void *pvDestContext, DWORD mshlflags, CLSID *clsid)
1396{
1399 return S_OK;
1400}
1401
1403 void *pv, DWORD dwDestContext, void *pvDestContext, DWORD mshlflags, DWORD *size)
1404{
1406 ok(size != NULL, "size = NULL\n");
1407
1408 *size = 0;
1409 return S_OK;
1410}
1411
1413 REFIID riid, void *pv, DWORD dwDestContext, void *pvDestContext, DWORD mshlflags)
1414{
1415 IMarshal *std_marshal;
1416 STATSTG stat;
1417 HRESULT hr;
1418
1420
1422 return S_OK;
1423
1424 hr = IStream_Stat(stream, &stat, STATFLAG_DEFAULT);
1425 ok_ole_success(hr, IStream_Stat);
1426 ok(U(stat.cbSize).LowPart == 0, "stream is not empty (%d)\n", U(stat.cbSize).LowPart);
1427 ok(U(stat.cbSize).HighPart == 0, "stream is not empty (%d)\n", U(stat.cbSize).HighPart);
1428
1430 dwDestContext, NULL, mshlflags, &std_marshal);
1432 hr = IMarshal_MarshalInterface(std_marshal, stream, riid, pv,
1433 dwDestContext, pvDestContext, mshlflags);
1434 ok_ole_success(hr, IMarshal_MarshalInterface);
1435 IMarshal_Release(std_marshal);
1436
1437 return S_OK;
1438}
1439
1441 IStream *stream, REFIID riid, void **ppv)
1442{
1443 ok(0, "unexpected call\n");
1444 return E_NOTIMPL;
1445}
1446
1448{
1449 ok(0, "unexpected call\n");
1450 return E_NOTIMPL;
1451}
1452
1454{
1455 ok(0, "unexpected call\n");
1456 return E_NOTIMPL;
1457}
1458
1459static IMarshalVtbl CustomMarshalVtbl =
1460{
1470};
1471
1473
1475{
1476 IStream *stream;
1477 IUnknown *unk;
1478 DWORD size;
1479 HRESULT hr;
1480
1483
1488 MSHCTX_INPROC, NULL, MSHLFLAGS_NORMAL);
1492
1493 hr = IStream_Seek(stream, ullZero, STREAM_SEEK_SET, NULL);
1494 ok_ole_success(hr, IStream_Seek);
1495 hr = CoUnmarshalInterface(stream, &IID_IUnknown, (void**)&unk);
1497 ok(unk == (IUnknown*)&CustomMarshal, "unk != &CustomMarshal\n");
1498 IUnknown_Release(unk);
1499 IStream_Release(stream);
1500
1503
1507 MSHCTX_INPROC, NULL, MSHLFLAGS_NORMAL);
1511
1512 hr = IStream_Seek(stream, ullZero, STREAM_SEEK_SET, NULL);
1513 ok_ole_success(hr, IStream_Seek);
1516 IStream_Release(stream);
1517
1520 MSHCTX_INPROC, NULL, MSHLFLAGS_NORMAL);
1523 ok(size == sizeof(OBJREF), "size = %d, expected %d\n", size, (int)sizeof(OBJREF));
1524}
1525
1527{
1528 DWORD size, read;
1529 IStream *stream;
1530 OBJREF objref;
1531 HRESULT hr;
1532
1535
1541 MSHCTX_INPROC, NULL, MSHLFLAGS_NORMAL);
1546
1547 hr = IStream_Seek(stream, ullZero, STREAM_SEEK_SET, NULL);
1548 ok_ole_success(hr, IStream_Seek);
1549 size = FIELD_OFFSET(OBJREF, u_objref.u_custom.pData);
1550 hr = IStream_Read(stream, &objref, size, &read);
1551 ok_ole_success(hr, IStream_Read);
1552 ok(read == size, "read = %d, expected %d\n", read, size);
1553 ok(objref.signature == OBJREF_SIGNATURE, "objref.signature = %x\n",
1554 objref.signature);
1555 ok(objref.flags == OBJREF_CUSTOM, "objref.flags = %x\n", objref.flags);
1556 ok(IsEqualIID(&objref.iid, &IID_IUnknown), "objref.iid = %s\n",
1557 wine_dbgstr_guid(&objref.iid));
1559 "custom.clsid = %s\n", wine_dbgstr_guid(&objref.u_objref.u_custom.clsid));
1560 ok(!objref.u_objref.u_custom.cbExtension, "custom.cbExtension = %d\n",
1561 objref.u_objref.u_custom.cbExtension);
1562 ok(!objref.u_objref.u_custom.size, "custom.size = %d\n",
1563 objref.u_objref.u_custom.size);
1564
1565 IStream_Release(stream);
1566
1569 MSHCTX_INPROC, NULL, MSHLFLAGS_NORMAL);
1572 ok(size == sizeof(OBJREF), "size = %d, expected %d\n", size, (int)sizeof(OBJREF));
1573}
1574
1576{
1577 DUALSTRINGARRAY *dualstringarr;
1578 STDOBJREF *stdobjref;
1579 OBJREF objref;
1580 IMarshal *marshal;
1581 DWORD size, read;
1582 IStream *stream;
1583 IUnknown *unk;
1584 CLSID clsid;
1585 HRESULT hr;
1586
1589
1591 MSHCTX_INPROC, NULL, MSHLFLAGS_NORMAL, &marshal);
1593
1594 hr = IMarshal_GetUnmarshalClass(marshal, &IID_IUnknown, &Test_Unknown,
1595 MSHCTX_INPROC, NULL, MSHLFLAGS_NORMAL, &clsid);
1596 ok_ole_success(hr, IMarshal_GetUnmarshalClass);
1598
1599 hr = IMarshal_GetMarshalSizeMax(marshal, &IID_IUnknown, &Test_Unknown,
1600 MSHCTX_INPROC, NULL, MSHLFLAGS_NORMAL, &size);
1601 ok_ole_success(hr, IMarshal_GetMarshalSizeMax);
1603 MSHCTX_INPROC, NULL, MSHLFLAGS_NORMAL);
1605 ok(size == read, "IMarshal_GetMarshalSizeMax size = %d, expected %d\n", size, read);
1606
1607 hr = IMarshal_MarshalInterface(marshal, stream, &IID_IUnknown,
1608 &Test_Unknown, MSHCTX_INPROC, NULL, MSHLFLAGS_NORMAL);
1609 ok_ole_success(hr, IMarshal_MarshalInterface);
1610
1611 hr = IStream_Seek(stream, ullZero, STREAM_SEEK_SET, NULL);
1612 ok_ole_success(hr, IStream_Seek);
1613 size = FIELD_OFFSET(OBJREF, u_objref.u_standard.saResAddr.aStringArray);
1614 hr = IStream_Read(stream, &objref, size, &read);
1615 ok_ole_success(hr, IStream_Read);
1616 ok(read == size, "read = %d, expected %d\n", read, size);
1617 ok(objref.signature == OBJREF_SIGNATURE, "objref.signature = %x\n",
1618 objref.signature);
1619 ok(objref.flags == OBJREF_STANDARD, "objref.flags = %x\n", objref.flags);
1620 ok(IsEqualIID(&objref.iid, &IID_IUnknown), "objref.iid = %s\n",
1621 wine_dbgstr_guid(&objref.iid));
1622 stdobjref = &objref.u_objref.u_standard.std;
1623 ok(stdobjref->flags == 0, "stdobjref.flags = %d\n", stdobjref->flags);
1624 ok(stdobjref->cPublicRefs == 5, "stdobjref.cPublicRefs = %d\n",
1625 stdobjref->cPublicRefs);
1626 dualstringarr = &objref.u_objref.u_standard.saResAddr;
1627 ok(dualstringarr->wNumEntries == 0, "dualstringarr.wNumEntries = %d\n",
1628 dualstringarr->wNumEntries);
1629 ok(dualstringarr->wSecurityOffset == 0, "dualstringarr.wSecurityOffset = %d\n",
1630 dualstringarr->wSecurityOffset);
1631
1632 hr = IStream_Seek(stream, ullZero, STREAM_SEEK_SET, NULL);
1633 ok_ole_success(hr, IStream_Seek);
1634 hr = IMarshal_UnmarshalInterface(marshal, stream, &IID_IUnknown, (void**)&unk);
1635 ok_ole_success(hr, IMarshal_UnmarshalInterface);
1636 IUnknown_Release(unk);
1637
1638 hr = IStream_Seek(stream, ullZero, STREAM_SEEK_SET, NULL);
1639 ok_ole_success(hr, IStream_Seek);
1640 hr = IMarshal_MarshalInterface(marshal, stream, &IID_IUnknown,
1641 &Test_Unknown, MSHCTX_INPROC, NULL, MSHLFLAGS_NORMAL);
1642 ok_ole_success(hr, IMarshal_MarshalInterface);
1643
1644 hr = IStream_Seek(stream, ullZero, STREAM_SEEK_SET, NULL);
1645 ok_ole_success(hr, IStream_Seek);
1646 hr = IMarshal_ReleaseMarshalData(marshal, stream);
1647 ok_ole_success(hr, IMarshal_ReleaseMarshalData);
1648 IStream_Release(stream);
1649
1650 IMarshal_Release(marshal);
1651}
1653{
1657};
1658
1659/* helper for test_no_couninitialize_server */
1661{
1662 struct ncu_params *ncu_params = p;
1663 HRESULT hr;
1664
1665 pCoInitializeEx(NULL, COINIT_MULTITHREADED);
1666
1667 hr = CoMarshalInterface(ncu_params->stream, &IID_IClassFactory, (IUnknown*)&Test_ClassFactory, MSHCTX_INPROC, NULL, MSHLFLAGS_NORMAL);
1669
1671
1672 ok( !WaitForSingleObject(ncu_params->unmarshal_event, 10000), "wait timed out\n" );
1673
1674 /* die without calling CoUninitialize */
1675
1676 return 0;
1677}
1678
1679/* tests apartment that an apartment with a stub is released without deadlock
1680 * if the owning thread exits */
1682{
1683 HRESULT hr;
1684 IStream *pStream = NULL;
1685 IUnknown *pProxy = NULL;
1686 DWORD tid;
1687 HANDLE thread;
1688 struct ncu_params ncu_params;
1689
1690 cLocks = 0;
1692
1695
1696 hr = CreateStreamOnHGlobal(NULL, TRUE, &pStream);
1698 ncu_params.stream = pStream;
1699
1701
1702 ok( !WaitForSingleObject(ncu_params.marshal_event, 10000), "wait timed out\n" );
1705
1706 IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
1707 hr = CoUnmarshalInterface(pStream, &IID_IClassFactory, (void **)&pProxy);
1709 IStream_Release(pStream);
1710
1713
1715 ok( !WaitForSingleObject(thread, 10000), "wait timed out\n" );
1716
1717 ok_no_locks();
1718todo_wine {
1721}
1722
1726
1727 IUnknown_Release(pProxy);
1728
1729 ok_no_locks();
1730}
1731
1732/* STA -> STA call during DLL_THREAD_DETACH */
1734{
1735 struct ncu_params *ncu_params = p;
1736 HRESULT hr;
1737 IUnknown *pProxy = NULL;
1738
1739 pCoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
1740
1743 IStream_Release(ncu_params->stream);
1744
1746
1747 /* die without calling CoUninitialize */
1748
1749 return 0;
1750}
1751
1752/* tests STA -> STA call during DLL_THREAD_DETACH doesn't deadlock */
1754{
1755 HRESULT hr;
1756 IStream *pStream = NULL;
1757 DWORD tid;
1758 DWORD host_tid;
1759 HANDLE thread;
1760 HANDLE host_thread;
1761 struct ncu_params ncu_params;
1762
1763 cLocks = 0;
1765
1766 hr = CreateStreamOnHGlobal(NULL, TRUE, &pStream);
1768 ncu_params.stream = pStream;
1769
1770 /* NOTE: assumes start_host_object uses an STA to host the object, as MTAs
1771 * always deadlock when called from within DllMain */
1772 host_tid = start_host_object(pStream, &IID_IClassFactory, (IUnknown *)&Test_ClassFactory, MSHLFLAGS_NORMAL, &host_thread);
1773 IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
1774
1777
1779
1780 ok( !WaitForSingleObject(thread, 10000), "wait timed out\n" );
1782
1783 ok_no_locks();
1786
1787 end_host_object(host_tid, host_thread);
1788}
1789
1791
1793{
1794 IStream *stream;
1795 HRESULT hr;
1796
1797 cLocks = 0;
1798
1800
1803
1804 hr = CoMarshalInterface(stream, &IID_IUnknown, &TestCrash_Unknown, MSHCTX_INPROC, NULL, MSHLFLAGS_NORMAL);
1806
1807 IStream_Seek(stream, ullZero, STREAM_SEEK_SET, NULL);
1808
1811
1812 ok_no_locks();
1813
1814 hr = CoMarshalInterface(stream, &IID_IUnknown, &TestCrash_Unknown, MSHCTX_INPROC, NULL, MSHLFLAGS_NORMAL);
1816
1818
1819 trace("CoUninitialize >>>\n");
1821 trace("CoUninitialize <<<\n");
1822
1823 ok_no_locks();
1824
1825 IStream_Release(stream);
1827 return 0;
1828}
1829
1831{
1832 HANDLE thread;
1833 DWORD tid;
1834
1835 if(!GetProcAddress(GetModuleHandleA("kernel32.dll"), "CreateActCtxW")) {
1836 win_skip("Skipping crash tests on win2k.\n");
1837 return;
1838 }
1839
1842 ok(!WaitForSingleObject(thread, 10000), "wait timed out\n");
1844 ok(crash_thread_success, "Crash thread failed\n");
1845}
1846
1847/* tests success case of a same-thread table-weak marshal, unmarshal, unmarshal */
1849{
1850 HRESULT hr;
1851 IStream *pStream = NULL;
1852 IUnknown *pProxy1 = NULL;
1853 IUnknown *pProxy2 = NULL;
1854 DWORD tid;
1855 HANDLE thread;
1856
1857 cLocks = 0;
1859
1860 hr = CreateStreamOnHGlobal(NULL, TRUE, &pStream);
1862 tid = start_host_object(pStream, &IID_IClassFactory, (IUnknown*)&Test_ClassFactory, MSHLFLAGS_TABLEWEAK, &thread);
1863
1866
1867 IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
1868 hr = CoUnmarshalInterface(pStream, &IID_IClassFactory, (void **)&pProxy1);
1870
1873
1874 IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
1875 hr = CoUnmarshalInterface(pStream, &IID_IClassFactory, (void **)&pProxy2);
1877
1879
1880 IUnknown_Release(pProxy1);
1882 IUnknown_Release(pProxy2);
1885
1886 /* When IExternalConnection is present COM's lifetime management
1887 * behaviour is altered; the remaining weak ref prevents stub shutdown. */
1889 {
1891 IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
1893 }
1894
1895 /* Without IExternalConnection this line is shows the difference between weak and strong table marshaling
1896 * weak has cLocks == 0, strong has cLocks > 0. */
1897 ok_no_locks();
1898
1899 IStream_Release(pStream);
1901}
1902
1903/* tests releasing after unmarshaling one object */
1905{
1906 HRESULT hr;
1907 IStream *pStream = NULL;
1908 IUnknown *pProxy1 = NULL;
1909 IUnknown *pProxy2 = NULL;
1910 DWORD tid;
1911 HANDLE thread;
1912
1913 cLocks = 0;
1915
1916 hr = CreateStreamOnHGlobal(NULL, TRUE, &pStream);
1918 tid = start_host_object(pStream, &IID_IClassFactory, (IUnknown*)&Test_ClassFactory, MSHLFLAGS_TABLEWEAK, &thread);
1919
1922
1923 IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
1924 hr = CoUnmarshalInterface(pStream, &IID_IClassFactory, (void **)&pProxy1);
1926
1929
1930 /* release the remaining reference on the object by calling
1931 * CoReleaseMarshalData in the hosting thread */
1932 IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
1934
1937
1938 IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
1939 hr = CoUnmarshalInterface(pStream, &IID_IClassFactory, (void **)&pProxy2);
1941 IStream_Release(pStream);
1942
1945
1946 IUnknown_Release(pProxy1);
1947
1948 if (pProxy2)
1949 {
1951 IUnknown_Release(pProxy2);
1952 }
1953
1954 /* this line is shows the difference between weak and strong table marshaling:
1955 * weak has cLocks == 0
1956 * strong has cLocks > 0 */
1957 ok_no_locks();
1960
1962}
1963
1964/* tests releasing after unmarshaling one object */
1966{
1967 HRESULT hr;
1968 IStream *pStream = NULL;
1969 IUnknown *pProxy = NULL;
1970 DWORD tid;
1971 HANDLE thread;
1972
1973 cLocks = 0;
1975
1976 hr = CreateStreamOnHGlobal(NULL, TRUE, &pStream);
1978 tid = start_host_object(pStream, &IID_IClassFactory, (IUnknown*)&Test_ClassFactory, MSHLFLAGS_TABLEWEAK, &thread);
1979
1982
1983 /* release the remaining reference on the object by calling
1984 * CoReleaseMarshalData in the hosting thread */
1985 IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
1987
1988 ok_no_locks();
1989
1990 IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
1991 hr = CoUnmarshalInterface(pStream, &IID_IClassFactory, (void **)&pProxy);
1992 todo_wine
1993 {
1994 ok(hr == CO_E_OBJNOTREG,
1995 "CoUnmarshalInterface should have failed with CO_E_OBJNOTREG, but returned 0x%08x instead\n",
1996 hr);
1997 }
1998 IStream_Release(pStream);
1999
2000 ok_no_locks();
2002
2004}
2005
2007{
2012};
2013
2015{
2016 HRESULT hr;
2017 struct duo_marshal_data *data = p;
2018 HANDLE hQuitEvent = data->hQuitEvent;
2019 MSG msg;
2020
2021 pCoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
2022
2023 hr = CoMarshalInterface(data->pStream1, &IID_IClassFactory, (IUnknown*)&Test_ClassFactory, MSHCTX_INPROC, NULL, data->marshal_flags1);
2024 ok_ole_success(hr, "CoMarshalInterface");
2025
2026 hr = CoMarshalInterface(data->pStream2, &IID_IClassFactory, (IUnknown*)&Test_ClassFactory, MSHCTX_INPROC, NULL, data->marshal_flags2);
2027 ok_ole_success(hr, "CoMarshalInterface");
2028
2029 /* force the message queue to be created before signaling parent thread */
2031
2032 SetEvent(data->hReadyEvent);
2033
2035 {
2036 while (PeekMessageA(&msg, NULL, 0, 0, PM_REMOVE))
2037 {
2038 if (msg.hwnd == NULL && msg.message == RELEASEMARSHALDATA)
2039 {
2040 CoReleaseMarshalData(msg.wParam == 1 ? data->pStream1 : data->pStream2);
2041 SetEvent((HANDLE)msg.lParam);
2042 }
2043 else
2045 }
2046 }
2048
2050
2051 return 0;
2052}
2053
2054/* tests interaction between table-weak and normal marshalling of an object */
2056{
2057 HRESULT hr;
2058 IUnknown *pProxyWeak = NULL;
2059 IUnknown *pProxyNormal = NULL;
2060 DWORD tid;
2061 HANDLE thread;
2062 struct duo_marshal_data data;
2063
2064 cLocks = 0;
2066
2067 data.hReadyEvent = CreateEventA(NULL, FALSE, FALSE, NULL);
2068 data.hQuitEvent = CreateEventA(NULL, FALSE, FALSE, NULL);
2069 data.marshal_flags1 = MSHLFLAGS_TABLEWEAK;
2070 data.marshal_flags2 = MSHLFLAGS_NORMAL;
2071 hr = CreateStreamOnHGlobal(NULL, TRUE, &data.pStream1);
2073 hr = CreateStreamOnHGlobal(NULL, TRUE, &data.pStream2);
2075
2077 ok( !WaitForSingleObject(data.hReadyEvent, 10000), "wait timed out\n" );
2078 CloseHandle(data.hReadyEvent);
2079
2082
2083 /* weak */
2084 IStream_Seek(data.pStream1, ullZero, STREAM_SEEK_SET, NULL);
2085 hr = CoUnmarshalInterface(data.pStream1, &IID_IClassFactory, (void **)&pProxyWeak);
2087
2089
2090 /* normal */
2091 IStream_Seek(data.pStream2, ullZero, STREAM_SEEK_SET, NULL);
2092 hr = CoUnmarshalInterface(data.pStream2, &IID_IClassFactory, (void **)&pProxyNormal);
2094
2096
2097 IUnknown_Release(pProxyNormal);
2098
2101
2102 IUnknown_Release(pProxyWeak);
2103
2106
2107 /* When IExternalConnection is present COM's lifetime management
2108 * behaviour is altered; the remaining weak ref prevents stub shutdown. */
2110 {
2112 IStream_Seek(data.pStream1, ullZero, STREAM_SEEK_SET, NULL);
2114 }
2115 ok_no_locks();
2116
2117 IStream_Release(data.pStream1);
2118 IStream_Release(data.pStream2);
2119
2120 SetEvent(data.hQuitEvent);
2121 ok( !WaitForSingleObject(thread, 10000), "wait timed out\n" );
2123}
2124
2126{
2127 HRESULT hr;
2128 DWORD tid;
2129 HANDLE thread;
2130 struct duo_marshal_data data;
2131
2132 cLocks = 0;
2134
2135 data.hReadyEvent = CreateEventA(NULL, FALSE, FALSE, NULL);
2136 data.hQuitEvent = CreateEventA(NULL, FALSE, FALSE, NULL);
2137 data.marshal_flags1 = MSHLFLAGS_TABLEWEAK;
2138 data.marshal_flags2 = MSHLFLAGS_NORMAL;
2139 hr = CreateStreamOnHGlobal(NULL, TRUE, &data.pStream1);
2141 hr = CreateStreamOnHGlobal(NULL, TRUE, &data.pStream2);
2143
2145 ok( !WaitForSingleObject(data.hReadyEvent, 10000), "wait timed out\n" );
2146 CloseHandle(data.hReadyEvent);
2147
2150
2151 /* release normal - which in the non-external conn case will free the object despite the weak ref. */
2152 IStream_Seek(data.pStream2, ullZero, STREAM_SEEK_SET, NULL);
2154
2157
2159 {
2161 IStream_Seek(data.pStream1, ullZero, STREAM_SEEK_SET, NULL);
2163 }
2164
2165 ok_no_locks();
2166
2167 IStream_Release(data.pStream1);
2168 IStream_Release(data.pStream2);
2169
2170 SetEvent(data.hQuitEvent);
2171 ok( !WaitForSingleObject(thread, 10000), "wait timed out\n" );
2173}
2174
2176{
2177 HRESULT hr;
2178 DWORD tid;
2179 HANDLE thread;
2180 struct duo_marshal_data data;
2181
2182 cLocks = 0;
2184
2185 data.hReadyEvent = CreateEventA(NULL, FALSE, FALSE, NULL);
2186 data.hQuitEvent = CreateEventA(NULL, FALSE, FALSE, NULL);
2187 data.marshal_flags1 = MSHLFLAGS_TABLEWEAK;
2188 data.marshal_flags2 = MSHLFLAGS_TABLEWEAK;
2189 hr = CreateStreamOnHGlobal(NULL, TRUE, &data.pStream1);
2191 hr = CreateStreamOnHGlobal(NULL, TRUE, &data.pStream2);
2193
2195 ok( !WaitForSingleObject(data.hReadyEvent, 10000), "wait timed out\n" );
2196 CloseHandle(data.hReadyEvent);
2197
2200
2201 /* release one weak ref - the remaining weak ref will keep the obj alive */
2202 IStream_Seek(data.pStream1, ullZero, STREAM_SEEK_SET, NULL);
2204
2206
2207 IStream_Seek(data.pStream2, ullZero, STREAM_SEEK_SET, NULL);
2209
2210 ok_no_locks();
2211
2212 IStream_Release(data.pStream1);
2213 IStream_Release(data.pStream2);
2214
2215 SetEvent(data.hQuitEvent);
2216 ok( !WaitForSingleObject(thread, 10000), "wait timed out\n" );
2218}
2219
2220/* tests success case of a same-thread table-strong marshal, unmarshal, unmarshal */
2222{
2223 HRESULT hr;
2224 IStream *pStream = NULL;
2225 IUnknown *pProxy1 = NULL;
2226 IUnknown *pProxy2 = NULL;
2227 DWORD tid;
2228 HANDLE thread;
2229
2230 cLocks = 0;
2232
2233 hr = CreateStreamOnHGlobal(NULL, TRUE, &pStream);
2235 tid = start_host_object(pStream, &IID_IClassFactory, (IUnknown*)&Test_ClassFactory, MSHLFLAGS_TABLESTRONG, &thread);
2236
2239
2240 IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
2241 hr = CoUnmarshalInterface(pStream, &IID_IClassFactory, (void **)&pProxy1);
2243
2245
2246 IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
2247 hr = CoUnmarshalInterface(pStream, &IID_IClassFactory, (void **)&pProxy2);
2249
2251
2252 if (pProxy1) IUnknown_Release(pProxy1);
2253 if (pProxy2) IUnknown_Release(pProxy2);
2254
2255 /* this line is shows the difference between weak and strong table marshaling:
2256 * weak has cLocks == 0
2257 * strong has cLocks > 0 */
2259
2260 /* release the remaining reference on the object by calling
2261 * CoReleaseMarshalData in the hosting thread */
2262 IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
2264 IStream_Release(pStream);
2265
2266 ok_no_locks();
2269
2271}
2272
2273/* tests CoLockObjectExternal */
2275{
2276 HRESULT hr;
2277 IStream *pStream = NULL;
2278
2279 cLocks = 0;
2281
2282 /* test the stub manager creation aspect of CoLockObjectExternal when the
2283 * object hasn't been marshaled yet */
2285
2288
2290
2291 ok_no_locks();
2294
2295 /* test our empty stub manager being handled correctly in
2296 * CoMarshalInterface */
2298
2299 hr = CreateStreamOnHGlobal(NULL, TRUE, &pStream);
2301 hr = CoMarshalInterface(pStream, &IID_IClassFactory, (IUnknown*)&Test_ClassFactory, MSHCTX_INPROC, NULL, MSHLFLAGS_NORMAL);
2303
2305
2308
2309 IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
2310 hr = CoReleaseMarshalData(pStream);
2312 IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
2313
2317
2319
2323
2325
2326 ok_no_locks();
2329
2330 /* test CoLockObjectExternal releases reference to object with
2331 * fLastUnlockReleases as TRUE and there are only strong references on
2332 * the object */
2334
2337
2339
2340 ok_no_locks();
2343
2344 /* test CoLockObjectExternal doesn't release the last reference to an
2345 * object with fLastUnlockReleases as TRUE and there is a weak reference
2346 * on the object */
2347 hr = CoMarshalInterface(pStream, &IID_IClassFactory, (IUnknown*)&Test_ClassFactory, MSHCTX_INPROC, NULL, MSHLFLAGS_TABLEWEAK);
2349
2352
2354
2357
2359
2363
2365
2366 ok_no_locks();
2367
2368 IStream_Release(pStream);
2369}
2370
2371/* tests disconnecting stubs */
2372static void test_disconnect_stub(void)
2373{
2374 HRESULT hr;
2375 IStream *pStream = NULL;
2376
2377 cLocks = 0;
2379
2380 hr = CreateStreamOnHGlobal(NULL, TRUE, &pStream);
2382 hr = CoMarshalInterface(pStream, &IID_IClassFactory, (IUnknown*)&Test_ClassFactory, MSHCTX_INPROC, NULL, MSHLFLAGS_NORMAL);
2384
2386
2388
2391
2392 IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
2393 hr = CoReleaseMarshalData(pStream);
2395 IStream_Release(pStream);
2396
2399
2401
2402 ok_no_locks();
2404
2406 ok( hr == E_INVALIDARG, "wrong status %x\n", hr );
2407}
2408
2409/* tests failure case of a same-thread marshal and unmarshal twice */
2411{
2412 HRESULT hr;
2413 IStream *pStream = NULL;
2414 IUnknown *pProxy1 = NULL;
2415 IUnknown *pProxy2 = NULL;
2416
2417 cLocks = 0;
2419
2420 hr = CreateStreamOnHGlobal(NULL, TRUE, &pStream);
2422 hr = CoMarshalInterface(pStream, &IID_IClassFactory, (IUnknown*)&Test_ClassFactory, MSHCTX_INPROC, NULL, MSHLFLAGS_NORMAL);
2424
2427
2428 IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
2429 hr = CoUnmarshalInterface(pStream, &IID_IClassFactory, (void **)&pProxy1);
2431
2435
2436 IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
2437 hr = CoUnmarshalInterface(pStream, &IID_IClassFactory, (void **)&pProxy2);
2439 "CoUnmarshalInterface should have failed with error CO_E_OBJNOTCONNECTED for double unmarshal, instead of 0x%08x\n", hr);
2440
2441 IStream_Release(pStream);
2442
2444
2445 IUnknown_Release(pProxy1);
2446
2447 ok_no_locks();
2448}
2449
2450/* tests success case of marshaling and unmarshaling an HRESULT */
2452{
2453 HRESULT hr;
2454 HRESULT hr_marshaled = 0;
2455 IStream *pStream = NULL;
2456 static const HRESULT E_DEADBEEF = 0xdeadbeef;
2457
2458 hr = CreateStreamOnHGlobal(NULL, TRUE, &pStream);
2460
2461 hr = CoMarshalHresult(pStream, E_DEADBEEF);
2463
2464 IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
2465 hr = IStream_Read(pStream, &hr_marshaled, sizeof(HRESULT), NULL);
2466 ok_ole_success(hr, IStream_Read);
2467
2468 ok(hr_marshaled == E_DEADBEEF, "Didn't marshal HRESULT as expected: got value 0x%08x instead\n", hr_marshaled);
2469
2470 hr_marshaled = 0;
2471 IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
2472 hr = CoUnmarshalHresult(pStream, &hr_marshaled);
2474
2475 ok(hr_marshaled == E_DEADBEEF, "Didn't marshal HRESULT as expected: got value 0x%08x instead\n", hr_marshaled);
2476
2477 IStream_Release(pStream);
2478}
2479
2480
2481/* helper for test_proxy_used_in_wrong_thread */
2483{
2484 IClassFactory * cf = p;
2485 HRESULT hr;
2486 IUnknown * proxy = NULL;
2487
2488 hr = IClassFactory_CreateInstance(cf, NULL, &IID_IUnknown, (LPVOID*)&proxy);
2489 todo_wine
2491 "COM should have failed with CO_E_NOTINITIALIZED on using proxy without apartment, but instead returned 0x%08x\n",
2492 hr);
2493
2494 hr = IClassFactory_QueryInterface(cf, &IID_IMultiQI, (LPVOID *)&proxy);
2495 /* Win9x returns S_OK, whilst NT returns RPC_E_WRONG_THREAD */
2496 trace("call to proxy's QueryInterface for local interface without apartment returned 0x%08x\n", hr);
2497 if (SUCCEEDED(hr))
2498 IUnknown_Release(proxy);
2499
2500 hr = IClassFactory_QueryInterface(cf, &IID_IStream, (LPVOID *)&proxy);
2501 /* Win9x returns E_NOINTERFACE, whilst NT returns RPC_E_WRONG_THREAD */
2502 trace("call to proxy's QueryInterface without apartment returned 0x%08x\n", hr);
2503 if (SUCCEEDED(hr))
2504 IUnknown_Release(proxy);
2505
2506 pCoInitializeEx(NULL, COINIT_MULTITHREADED);
2507
2508 hr = IClassFactory_CreateInstance(cf, NULL, &IID_IUnknown, (LPVOID*)&proxy);
2509 if (proxy) IUnknown_Release(proxy);
2511 "COM should have failed with RPC_E_WRONG_THREAD on using proxy from wrong apartment, but instead returned 0x%08x\n",
2512 hr);
2513
2514 hr = IClassFactory_QueryInterface(cf, &IID_IStream, (LPVOID *)&proxy);
2515 /* Win9x returns E_NOINTERFACE, whilst NT returns RPC_E_WRONG_THREAD */
2516 trace("call to proxy's QueryInterface from wrong apartment returned 0x%08x\n", hr);
2517
2518 /* now be really bad and release the proxy from the wrong apartment */
2519 IClassFactory_Release(cf);
2520
2522
2523 return 0;
2524}
2525
2526/* tests failure case of a using a proxy in the wrong apartment */
2528{
2529 HRESULT hr;
2530 IStream *pStream = NULL;
2531 IUnknown *pProxy = NULL;
2532 DWORD tid, tid2;
2533 HANDLE thread;
2534 HANDLE host_thread;
2535
2536 cLocks = 0;
2537
2538 hr = CreateStreamOnHGlobal(NULL, TRUE, &pStream);
2540 tid = start_host_object(pStream, &IID_IClassFactory, (IUnknown*)&Test_ClassFactory, MSHLFLAGS_NORMAL, &host_thread);
2541
2543
2544 IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
2545 hr = CoUnmarshalInterface(pStream, &IID_IClassFactory, (void **)&pProxy);
2547 IStream_Release(pStream);
2548
2550
2551 /* do a call that will fail, but result in IRemUnknown being used by the proxy */
2552 IUnknown_QueryInterface(pProxy, &IID_IStream, (LPVOID *)&pStream);
2553
2554 /* create a thread that we can misbehave in */
2555 thread = CreateThread(NULL, 0, bad_thread_proc, pProxy, 0, &tid2);
2556
2557 ok( !WaitForSingleObject(thread, 10000), "wait timed out\n" );
2559
2560 /* do release statement on Win9x that we should have done above */
2561 if (!GetProcAddress(GetModuleHandleA("ole32"), "CoRegisterSurrogateEx"))
2562 IUnknown_Release(pProxy);
2563
2564 ok_no_locks();
2565
2566 end_host_object(tid, host_thread);
2567}
2568
2570{
2571 if (ppvObj == NULL) return E_POINTER;
2572
2573 if (IsEqualGUID(riid, &IID_IUnknown) ||
2575 {
2576 *ppvObj = iface;
2577 IMessageFilter_AddRef(iface);
2578 return S_OK;
2579 }
2580
2581 return E_NOINTERFACE;
2582}
2583
2585{
2586 return 2; /* non-heap object */
2587}
2588
2590{
2591 return 1; /* non-heap object */
2592}
2593
2595 IMessageFilter *iface,
2596 DWORD dwCallType,
2597 HTASK threadIDCaller,
2598 DWORD dwTickCount,
2599 LPINTERFACEINFO lpInterfaceInfo)
2600{
2601 static int callcount = 0;
2602 DWORD ret;
2603 trace("HandleInComingCall\n");
2604 switch (callcount)
2605 {
2606 case 0:
2607 ret = SERVERCALL_REJECTED;
2608 break;
2609 case 1:
2610 ret = SERVERCALL_RETRYLATER;
2611 break;
2612 default:
2613 ret = SERVERCALL_ISHANDLED;
2614 break;
2615 }
2616 callcount++;
2617 return ret;
2618}
2619
2621 IMessageFilter *iface,
2622 HTASK threadIDCallee,
2623 DWORD dwTickCount,
2624 DWORD dwRejectType)
2625{
2626 trace("RetryRejectedCall\n");
2627 return 0;
2628}
2629
2631 IMessageFilter *iface,
2632 HTASK threadIDCallee,
2633 DWORD dwTickCount,
2634 DWORD dwPendingType)
2635{
2636 trace("MessagePending\n");
2637 return PENDINGMSG_WAITNOPROCESS;
2638}
2639
2640static const IMessageFilterVtbl MessageFilter_Vtbl =
2641{
2648};
2649
2651
2652static void test_message_filter(void)
2653{
2654 HRESULT hr;
2656 DWORD tid;
2657 IUnknown *proxy = NULL;
2658 IMessageFilter *prev_filter = NULL;
2659 HANDLE thread;
2660
2662 MSHLFLAGS_NORMAL, &MessageFilter };
2663
2664 cLocks = 0;
2665
2666 hr = CreateStreamOnHGlobal(NULL, TRUE, &object_data.stream);
2668 tid = start_host_object2(&object_data, &thread);
2669
2671
2672 IStream_Seek(object_data.stream, ullZero, STREAM_SEEK_SET, NULL);
2673 hr = CoUnmarshalInterface(object_data.stream, &IID_IClassFactory, (void **)&cf);
2675 IStream_Release(object_data.stream);
2676
2678
2679 hr = IClassFactory_CreateInstance(cf, NULL, &IID_IUnknown, (LPVOID*)&proxy);
2680 ok(hr == RPC_E_CALL_REJECTED, "Call should have returned RPC_E_CALL_REJECTED, but return 0x%08x instead\n", hr);
2681 if (proxy) IUnknown_Release(proxy);
2682 proxy = NULL;
2683
2684 hr = CoRegisterMessageFilter(&MessageFilter, &prev_filter);
2686
2687 hr = IClassFactory_CreateInstance(cf, NULL, &IID_IUnknown, (LPVOID*)&proxy);
2688 ok_ole_success(hr, IClassFactory_CreateInstance);
2689
2690 IUnknown_Release(proxy);
2691
2692 IClassFactory_Release(cf);
2693
2694 ok_no_locks();
2695
2697
2698 hr = CoRegisterMessageFilter(prev_filter, NULL);
2700}
2701
2702/* test failure case of trying to unmarshal from bad stream */
2704{
2705 HRESULT hr;
2706 IStream *pStream = NULL;
2707
2708 hr = CreateStreamOnHGlobal(NULL, TRUE, &pStream);
2710 hr = CoMarshalInterface(pStream, &IID_IClassFactory, (IUnknown*)&Test_ClassFactory, MSHCTX_INPROC, NULL, MSHLFLAGS_NORMAL);
2712
2714
2715 /* try to read beyond end of stream */
2716 hr = CoReleaseMarshalData(pStream);
2717 ok(hr == STG_E_READFAULT, "Should have failed with STG_E_READFAULT, but returned 0x%08x instead\n", hr);
2718
2719 /* now release for real */
2720 IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
2721 hr = CoReleaseMarshalData(pStream);
2723
2724 IStream_Release(pStream);
2725}
2726
2727/* tests that proxies implement certain interfaces */
2728static void test_proxy_interfaces(void)
2729{
2730 HRESULT hr;
2731 IStream *pStream = NULL;
2732 IUnknown *pProxy = NULL;
2733 IUnknown *pOtherUnknown = NULL;
2734 DWORD tid;
2735 HANDLE thread;
2736
2737 cLocks = 0;
2738
2739 hr = CreateStreamOnHGlobal(NULL, TRUE, &pStream);
2741 tid = start_host_object(pStream, &IID_IClassFactory, (IUnknown*)&Test_ClassFactory, MSHLFLAGS_NORMAL, &thread);
2742
2744
2745 IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
2746 hr = CoUnmarshalInterface(pStream, &IID_IUnknown, (void **)&pProxy);
2748 IStream_Release(pStream);
2749
2751
2752 hr = IUnknown_QueryInterface(pProxy, &IID_IUnknown, (LPVOID*)&pOtherUnknown);
2753 ok_ole_success(hr, IUnknown_QueryInterface IID_IUnknown);
2754 if (hr == S_OK) IUnknown_Release(pOtherUnknown);
2755
2756 hr = IUnknown_QueryInterface(pProxy, &IID_IClientSecurity, (LPVOID*)&pOtherUnknown);
2757 ok_ole_success(hr, IUnknown_QueryInterface IID_IClientSecurity);
2758 if (hr == S_OK) IUnknown_Release(pOtherUnknown);
2759
2760 hr = IUnknown_QueryInterface(pProxy, &IID_IMultiQI, (LPVOID*)&pOtherUnknown);
2761 ok_ole_success(hr, IUnknown_QueryInterface IID_IMultiQI);
2762 if (hr == S_OK) IUnknown_Release(pOtherUnknown);
2763
2764 hr = IUnknown_QueryInterface(pProxy, &IID_IMarshal, (LPVOID*)&pOtherUnknown);
2765 ok_ole_success(hr, IUnknown_QueryInterface IID_IMarshal);
2766 if (hr == S_OK) IUnknown_Release(pOtherUnknown);
2767
2768 /* IMarshal2 is also supported on NT-based systems, but is pretty much
2769 * useless as it has no more methods over IMarshal that it inherits from. */
2770
2771 IUnknown_Release(pProxy);
2772
2773 ok_no_locks();
2774
2776}
2777
2778typedef struct
2779{
2782} HeapUnknown;
2783
2785{
2786 return CONTAINING_RECORD(iface, HeapUnknown, IUnknown_iface);
2787}
2788
2790{
2792 {
2793 IUnknown_AddRef(iface);
2794 *ppv = iface;
2795 return S_OK;
2796 }
2797 *ppv = NULL;
2798 return E_NOINTERFACE;
2799}
2800
2802{
2804 return InterlockedIncrement((LONG*)&This->refs);
2805}
2806
2808{
2810 ULONG refs = InterlockedDecrement((LONG*)&This->refs);
2811 if (!refs) HeapFree(GetProcessHeap(), 0, This);
2812 return refs;
2813}
2814
2815static const IUnknownVtbl HeapUnknown_Vtbl =
2816{
2820};
2821
2823{
2824 HRESULT hr;
2825 IPSFactoryBuffer *psfb;
2827 LPVOID lpvtbl;
2828 ULONG refs;
2829 CLSID clsid;
2830 HeapUnknown *pUnkOuter = HeapAlloc(GetProcessHeap(), 0, sizeof(*pUnkOuter));
2831
2832 pUnkOuter->IUnknown_iface.lpVtbl = &HeapUnknown_Vtbl;
2833 pUnkOuter->refs = 1;
2834
2837
2838 hr = CoGetClassObject(&clsid, CLSCTX_INPROC_SERVER, NULL, &IID_IPSFactoryBuffer, (LPVOID*)&psfb);
2840
2841 hr = IPSFactoryBuffer_CreateProxy(psfb, &pUnkOuter->IUnknown_iface, riid, &proxy, &lpvtbl);
2842 ok_ole_success(hr, IPSFactoryBuffer_CreateProxy);
2843 ok(lpvtbl != NULL, "IPSFactoryBuffer_CreateProxy succeeded, but returned a NULL vtable!\n");
2844
2845 /* release our reference to the outer unknown object - the PS factory
2846 * buffer will have AddRef's it in the CreateProxy call */
2847 refs = IUnknown_Release(&pUnkOuter->IUnknown_iface);
2848 ok(refs == 1, "Ref count of outer unknown should have been 1 instead of %d\n", refs);
2849
2850 /* Not checking return, unreliable on native. Maybe it leaks references? */
2851 IPSFactoryBuffer_Release(psfb);
2852
2853 refs = IUnknown_Release((IUnknown *)lpvtbl);
2854 ok(refs == 0, "Ref-count leak of %d on IRpcProxyBuffer\n", refs);
2855
2856 refs = IRpcProxyBuffer_Release(proxy);
2857 ok(refs == 0, "Ref-count leak of %d on IRpcProxyBuffer\n", refs);
2858}
2859
2861{
2862 HRESULT hr;
2863 IPSFactoryBuffer *psfb;
2865 ULONG refs;
2866 CLSID clsid;
2867
2868 cLocks = 0;
2869
2872
2873 hr = CoGetClassObject(&clsid, CLSCTX_INPROC_SERVER, NULL, &IID_IPSFactoryBuffer, (LPVOID*)&psfb);
2875
2876 hr = IPSFactoryBuffer_CreateStub(psfb, riid, (IUnknown*)&Test_ClassFactory, &stub);
2877 ok_ole_success(hr, IPSFactoryBuffer_CreateStub);
2878
2879 /* Not checking return, unreliable on native. Maybe it leaks references? */
2880 IPSFactoryBuffer_Release(psfb);
2881
2883
2884 IRpcStubBuffer_Disconnect(stub);
2885
2886 ok_no_locks();
2887
2888 refs = IRpcStubBuffer_Release(stub);
2889 ok(refs == 0, "Ref-count leak of %d on IRpcProxyBuffer\n", refs);
2890}
2891
2893
2895 LPCLASSFACTORY iface,
2896 LPUNKNOWN pUnkOuter,
2897 REFIID riid,
2898 LPVOID *ppvObj)
2899{
2900 DWORD_PTR res;
2902 {
2904 ok(ret, "Timed out sending a message to originating window during RPC call\n");
2905 }
2906 *ppvObj = NULL;
2907 return S_FALSE;
2908}
2909
2910static const IClassFactoryVtbl TestREClassFactory_Vtbl =
2911{
2917};
2918
2920
2922{
2923 switch (msg)
2924 {
2925 case WM_USER:
2926 {
2927 HRESULT hr;
2928 IStream *pStream = NULL;
2931 DWORD tid;
2932 HANDLE thread;
2933
2934 cLocks = 0;
2935
2936 hr = CreateStreamOnHGlobal(NULL, TRUE, &pStream);
2938 tid = start_host_object(pStream, &IID_IClassFactory, (IUnknown*)&TestRE_ClassFactory, MSHLFLAGS_NORMAL, &thread);
2939
2941
2942 IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
2943 hr = CoUnmarshalInterface(pStream, &IID_IClassFactory, (void **)&proxy);
2945 IStream_Release(pStream);
2946
2948
2949 /* note the use of the magic IID_IWineTest value to tell remote thread
2950 * to try to send a message back to us */
2951 hr = IClassFactory_CreateInstance(proxy, NULL, &IID_IWineTest, (void **)&object);
2952 ok(hr == S_FALSE, "expected S_FALSE, got %d\n", hr);
2953
2954 IClassFactory_Release(proxy);
2955
2956 ok_no_locks();
2957
2959
2960 PostMessageA(hwnd, WM_QUIT, 0, 0);
2961
2962 return 0;
2963 }
2964 case WM_USER+1:
2965 {
2966 HRESULT hr;
2967 IStream *pStream = NULL;
2970 DWORD tid;
2971 HANDLE thread;
2972
2973 cLocks = 0;
2974
2975 hr = CreateStreamOnHGlobal(NULL, TRUE, &pStream);
2977 tid = start_host_object(pStream, &IID_IClassFactory, (IUnknown*)&TestRE_ClassFactory, MSHLFLAGS_NORMAL, &thread);
2978
2980
2981 IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
2982 hr = CoUnmarshalInterface(pStream, &IID_IClassFactory, (void **)&proxy);
2984 IStream_Release(pStream);
2985
2987
2988 /* post quit message before a doing a COM call to show that a pending
2989 * WM_QUIT message doesn't stop the call from succeeding */
2990 PostMessageA(hwnd, WM_QUIT, 0, 0);
2991 hr = IClassFactory_CreateInstance(proxy, NULL, &IID_IUnknown, (void **)&object);
2992 ok(hr == S_FALSE, "IClassFactory_CreateInstance returned 0x%08x, expected S_FALSE\n", hr);
2993
2994 IClassFactory_Release(proxy);
2995
2996 ok_no_locks();
2997
2999
3000 return 0;
3001 }
3002 case WM_USER+2:
3003 {
3004 HRESULT hr;
3005 IStream *pStream = NULL;
3008 DWORD tid;
3009 HANDLE thread;
3010
3011 hr = CreateStreamOnHGlobal(NULL, TRUE, &pStream);
3013 tid = start_host_object(pStream, &IID_IClassFactory, (IUnknown*)&Test_ClassFactory, MSHLFLAGS_NORMAL, &thread);
3014
3015 IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
3016 hr = CoUnmarshalInterface(pStream, &IID_IClassFactory, (void **)&proxy);
3018 IStream_Release(pStream);
3019
3020 /* shows that COM calls executed during the processing of sent
3021 * messages should fail */
3022 hr = IClassFactory_CreateInstance(proxy, NULL, &IID_IUnknown, (void **)&object);
3024 "COM call during processing of sent message should return RPC_E_CANTCALLOUT_ININPUTSYNCCALL instead of 0x%08x\n", hr);
3025
3026 IClassFactory_Release(proxy);
3027
3029
3030 PostQuitMessage(0);
3031
3032 return 0;
3033 }
3034 default:
3035 return DefWindowProcA(hwnd, msg, wparam, lparam);
3036 }
3037}
3038
3039static void register_test_window(void)
3040{
3041 WNDCLASSA wndclass;
3042
3043 memset(&wndclass, 0, sizeof(wndclass));
3044 wndclass.lpfnWndProc = window_proc;
3045 wndclass.lpszClassName = "WineCOMTest";
3046 RegisterClassA(&wndclass);
3047}
3048
3050{
3051 MSG msg;
3052
3054 ok(hwnd_app != NULL, "Window creation failed\n");
3055
3056 /* start message re-entrancy test */
3058
3059 while (GetMessageA(&msg, NULL, 0, 0))
3060 {
3063 }
3065}
3066
3068 LPCLASSFACTORY iface,
3069 LPUNKNOWN pUnkOuter,
3070 REFIID riid,
3071 LPVOID *ppvObj)
3072{
3073 *ppvObj = NULL;
3074 SendMessageA(hwnd_app, WM_USER+2, 0, 0);
3075 return S_OK;
3076}
3077
3078static IClassFactoryVtbl TestMsgClassFactory_Vtbl =
3079{
3085};
3086
3088
3089static void test_call_from_message(void)
3090{
3091 MSG msg;
3092 IStream *pStream;
3093 HRESULT hr;
3095 DWORD tid;
3096 HANDLE thread;
3098
3100 ok(hwnd_app != NULL, "Window creation failed\n");
3101
3102 hr = CreateStreamOnHGlobal(NULL, TRUE, &pStream);
3104 tid = start_host_object(pStream, &IID_IClassFactory, (IUnknown*)&TestMsg_ClassFactory, MSHLFLAGS_NORMAL, &thread);
3105
3107
3108 IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
3109 hr = CoUnmarshalInterface(pStream, &IID_IClassFactory, (void **)&proxy);
3111 IStream_Release(pStream);
3112
3114
3115 /* start message re-entrancy test */
3116 hr = IClassFactory_CreateInstance(proxy, NULL, &IID_IUnknown, (void **)&object);
3117 ok_ole_success(hr, IClassFactory_CreateInstance);
3118
3119 IClassFactory_Release(proxy);
3120
3121 ok_no_locks();
3122
3124
3125 while (GetMessageA(&msg, NULL, 0, 0))
3126 {
3129 }
3131}
3132
3133static void test_WM_QUIT_handling(void)
3134{
3135 MSG msg;
3136
3138 ok(hwnd_app != NULL, "Window creation failed\n");
3139
3140 /* start WM_QUIT handling test */
3141 PostMessageA(hwnd_app, WM_USER+1, 0, 0);
3142
3143 while (GetMessageA(&msg, NULL, 0, 0))
3144 {
3147 }
3148}
3149
3151{
3152 static SIZE_T global_size_alignment = -1;
3153 if (global_size_alignment == -1)
3154 {
3155 void *p = GlobalAlloc(GMEM_FIXED, 1);
3156 global_size_alignment = GlobalSize(p);
3157 GlobalFree(p);
3158 }
3159
3160 return ((size + global_size_alignment - 1) & ~(global_size_alignment - 1));
3161}
3162
3163static void test_freethreadedmarshaldata(IStream *pStream, MSHCTX mshctx, void *ptr, DWORD mshlflags)
3164{
3165 HGLOBAL hglobal;
3166 DWORD size;
3167 char *marshal_data;
3168 HRESULT hr;
3169
3170 hr = GetHGlobalFromStream(pStream, &hglobal);
3172
3173 size = GlobalSize(hglobal);
3174
3175 marshal_data = GlobalLock(hglobal);
3176
3177 if (mshctx == MSHCTX_INPROC)
3178 {
3179 DWORD expected_size = round_global_size(3*sizeof(DWORD) + sizeof(GUID));
3180 ok(size == expected_size ||
3181 broken(size == (2*sizeof(DWORD))) /* Win9x & NT4 */,
3182 "size should have been %d instead of %d\n", expected_size, size);
3183
3184 ok(*(DWORD *)marshal_data == mshlflags, "expected 0x%x, but got 0x%x for mshctx\n", mshlflags, *(DWORD *)marshal_data);
3185 marshal_data += sizeof(DWORD);
3186 ok(*(void **)marshal_data == ptr, "expected %p, but got %p for mshctx\n", ptr, *(void **)marshal_data);
3187 marshal_data += sizeof(void *);
3188 if (sizeof(void*) == 4 && size >= 3*sizeof(DWORD))
3189 {
3190 ok(*(DWORD *)marshal_data == 0, "expected 0x0, but got 0x%x\n", *(DWORD *)marshal_data);
3191 marshal_data += sizeof(DWORD);
3192 }
3193 if (size >= 3*sizeof(DWORD) + sizeof(GUID))
3194 {
3195 trace("got guid data: %s\n", wine_dbgstr_guid((GUID *)marshal_data));
3196 }
3197 }
3198 else
3199 {
3200 ok(size > sizeof(DWORD), "size should have been > sizeof(DWORD), not %d\n", size);
3201 ok(*(DWORD *)marshal_data == 0x574f454d /* MEOW */,
3202 "marshal data should be filled by standard marshal and start with MEOW signature\n");
3203 }
3204
3205 GlobalUnlock(hglobal);
3206}
3207
3209{
3210 HRESULT hr;
3211 IUnknown *pFTUnknown;
3212 IMarshal *pFTMarshal;
3213 IStream *pStream;
3214 IUnknown *pProxy;
3215 static const LARGE_INTEGER llZero;
3216 CLSID clsid;
3217
3218 cLocks = 0;
3219 hr = CoCreateFreeThreadedMarshaler(NULL, &pFTUnknown);
3221 hr = IUnknown_QueryInterface(pFTUnknown, &IID_IMarshal, (void **)&pFTMarshal);
3222 ok_ole_success(hr, IUnknown_QueryInterface);
3223 IUnknown_Release(pFTUnknown);
3224
3225 hr = CreateStreamOnHGlobal(NULL, TRUE, &pStream);
3227
3228 /* inproc normal marshaling */
3229
3230 hr = IMarshal_GetUnmarshalClass(pFTMarshal, &IID_IClassFactory,
3231 &Test_ClassFactory, MSHCTX_INPROC, NULL, MSHLFLAGS_NORMAL, &clsid);
3232 ok_ole_success(hr, IMarshal_GetUnmarshalClass);
3233 ok(IsEqualIID(&clsid, &CLSID_InProcFreeMarshaler), "clsid = %s\n",
3235
3236 hr = IMarshal_MarshalInterface(pFTMarshal, pStream, &IID_IClassFactory,
3237 &Test_ClassFactory, MSHCTX_INPROC, NULL, MSHLFLAGS_NORMAL);
3238 ok_ole_success(hr, IMarshal_MarshalInterface);
3239
3241
3242 test_freethreadedmarshaldata(pStream, MSHCTX_INPROC, &Test_ClassFactory, MSHLFLAGS_NORMAL);
3243
3244 IStream_Seek(pStream, llZero, STREAM_SEEK_SET, NULL);
3245 hr = IMarshal_UnmarshalInterface(pFTMarshal, pStream, &IID_IUnknown, (void **)&pProxy);
3246 ok_ole_success(hr, IMarshal_UnmarshalInterface);
3247
3248 IUnknown_Release(pProxy);
3249
3250 ok_no_locks();
3251
3252 /* inproc table-strong marshaling */
3253
3254 IStream_Seek(pStream, llZero, STREAM_SEEK_SET, NULL);
3255 hr = IMarshal_MarshalInterface(pFTMarshal, pStream, &IID_IClassFactory,
3256 (IUnknown*)&Test_ClassFactory, MSHCTX_INPROC, (void *)0xdeadbeef,
3257 MSHLFLAGS_TABLESTRONG);
3258 ok_ole_success(hr, IMarshal_MarshalInterface);
3259
3261
3262 test_freethreadedmarshaldata(pStream, MSHCTX_INPROC, &Test_ClassFactory, MSHLFLAGS_TABLESTRONG);
3263
3264 IStream_Seek(pStream, llZero, STREAM_SEEK_SET, NULL);
3265 hr = IMarshal_UnmarshalInterface(pFTMarshal, pStream, &IID_IUnknown, (void **)&pProxy);
3266 ok_ole_success(hr, IMarshal_UnmarshalInterface);
3267
3268 IUnknown_Release(pProxy);
3269
3271
3272 IStream_Seek(pStream, llZero, STREAM_SEEK_SET, NULL);
3273 hr = IMarshal_ReleaseMarshalData(pFTMarshal, pStream);
3274 ok_ole_success(hr, IMarshal_ReleaseMarshalData);
3275
3276 ok_no_locks();
3277
3278 /* inproc table-weak marshaling */
3279
3280 IStream_Seek(pStream, llZero, STREAM_SEEK_SET, NULL);
3281 hr = IMarshal_MarshalInterface(pFTMarshal, pStream, &IID_IClassFactory,
3282 (IUnknown*)&Test_ClassFactory, MSHCTX_INPROC, (void *)0xdeadbeef,
3283 MSHLFLAGS_TABLEWEAK);
3284 ok_ole_success(hr, IMarshal_MarshalInterface);
3285
3286 ok_no_locks();
3287
3288 test_freethreadedmarshaldata(pStream, MSHCTX_INPROC, &Test_ClassFactory, MSHLFLAGS_TABLEWEAK);
3289
3290 IStream_Seek(pStream, llZero, STREAM_SEEK_SET, NULL);
3291 hr = IMarshal_UnmarshalInterface(pFTMarshal, pStream, &IID_IUnknown, (void **)&pProxy);
3292 ok_ole_success(hr, IMarshal_UnmarshalInterface);
3293
3295
3296 IUnknown_Release(pProxy);
3297
3298 ok_no_locks();
3299
3300 /* inproc normal marshaling (for extraordinary cases) */
3301
3302 IStream_Seek(pStream, llZero, STREAM_SEEK_SET, NULL);
3303 hr = IMarshal_MarshalInterface(pFTMarshal, pStream, &IID_IClassFactory,
3304 &Test_ClassFactory, MSHCTX_INPROC, NULL, MSHLFLAGS_NORMAL);
3305 ok_ole_success(hr, IMarshal_MarshalInterface);
3306
3308
3309 /* this call shows that DisconnectObject does nothing */
3310 hr = IMarshal_DisconnectObject(pFTMarshal, 0);
3311 ok_ole_success(hr, IMarshal_DisconnectObject);
3312
3314
3315 IStream_Seek(pStream, llZero, STREAM_SEEK_SET, NULL);
3316 hr = IMarshal_ReleaseMarshalData(pFTMarshal, pStream);
3317 ok_ole_success(hr, IMarshal_ReleaseMarshalData);
3318
3319 ok_no_locks();
3320
3321 /* doesn't enforce marshaling rules here and allows us to unmarshal the
3322 * interface, even though it was freed above */
3323 IStream_Seek(pStream, llZero, STREAM_SEEK_SET, NULL);
3324 hr = IMarshal_UnmarshalInterface(pFTMarshal, pStream, &IID_IUnknown, (void **)&pProxy);
3325 ok_ole_success(hr, IMarshal_UnmarshalInterface);
3326
3327 ok_no_locks();
3328
3329 /* local normal marshaling */
3330
3331 hr = IMarshal_GetUnmarshalClass(pFTMarshal, &IID_IClassFactory,
3332 &Test_ClassFactory, MSHCTX_LOCAL, NULL, MSHLFLAGS_NORMAL, &clsid);
3333 ok_ole_success(hr, IMarshal_GetUnmarshalClass);
3334 ok(IsEqualIID(&clsid, &CLSID_StdMarshal), "clsid = %s\n",
3336
3337 IStream_Seek(pStream, llZero, STREAM_SEEK_SET, NULL);
3338 hr = IMarshal_MarshalInterface(pFTMarshal, pStream, &IID_IClassFactory, &Test_ClassFactory, MSHCTX_LOCAL, NULL, MSHLFLAGS_NORMAL);
3339 ok_ole_success(hr, IMarshal_MarshalInterface);
3340
3342
3343 test_freethreadedmarshaldata(pStream, MSHCTX_LOCAL, &Test_ClassFactory, MSHLFLAGS_NORMAL);
3344
3345 IStream_Seek(pStream, llZero, STREAM_SEEK_SET, NULL);
3346 hr = CoReleaseMarshalData(pStream);
3348
3349 ok_no_locks();
3350
3351 IStream_Release(pStream);
3352 IMarshal_Release(pFTMarshal);
3353}
3354
3356{
3357 HRESULT hr;
3358 char buffer[256];
3359 LPOLESTR pszClsid;
3360 HKEY hkey;
3361 DWORD dwDisposition;
3362 DWORD error;
3363
3364 hr = StringFromCLSID(&CLSID_WineTest, &pszClsid);
3365 ok_ole_success(hr, "StringFromCLSID");
3366 strcpy(buffer, "CLSID\\");
3367 WideCharToMultiByte(CP_ACP, 0, pszClsid, -1, buffer + strlen(buffer), sizeof(buffer) - strlen(buffer), NULL, NULL);
3368 CoTaskMemFree(pszClsid);
3369 strcat(buffer, "\\InprocHandler32");
3370 if (Register)
3371 {
3372 error = RegCreateKeyExA(HKEY_CLASSES_ROOT, buffer, 0, NULL, 0, KEY_SET_VALUE, NULL, &hkey, &dwDisposition);
3374 {
3375 skip("Not authorized to modify the Classes key\n");
3376 return E_FAIL;
3377 }
3378 ok(error == ERROR_SUCCESS, "RegCreateKeyEx failed with error %d\n", error);
3379 if (error != ERROR_SUCCESS) hr = E_FAIL;
3380 error = RegSetValueExA(hkey, NULL, 0, REG_SZ, (const unsigned char *)"\"ole32.dll\"", strlen("\"ole32.dll\"") + 1);
3381 ok(error == ERROR_SUCCESS, "RegSetValueEx failed with error %d\n", error);
3382 if (error != ERROR_SUCCESS) hr = E_FAIL;
3383 RegCloseKey(hkey);
3384 }
3385 else
3386 {
3388 *strrchr(buffer, '\\') = '\0';
3390 }
3391 return hr;
3392}
3393
3394static void test_inproc_handler(void)
3395{
3396 HRESULT hr;
3398 IUnknown *pObject2;
3399
3401 return;
3402
3403 hr = CoCreateInstance(&CLSID_WineTest, NULL, CLSCTX_INPROC_HANDLER, &IID_IUnknown, (void **)&pObject);
3404 ok_ole_success(hr, "CoCreateInstance");
3405
3406 if (SUCCEEDED(hr))
3407 {
3408 hr = IUnknown_QueryInterface(pObject, &IID_IWineTest, (void **)&pObject2);
3409 ok(hr == E_NOINTERFACE, "IUnknown_QueryInterface on handler for invalid interface returned 0x%08x instead of E_NOINTERFACE\n", hr);
3410
3411 /* it's a handler as it supports IOleObject */
3412 hr = IUnknown_QueryInterface(pObject, &IID_IOleObject, (void **)&pObject2);
3413 ok_ole_success(hr, "IUnknown_QueryInterface(&IID_IOleObject)");
3414 IUnknown_Release(pObject2);
3415
3416 IUnknown_Release(pObject);
3417 }
3418
3420}
3421
3423 IStdMarshalInfo *iface,
3424 REFIID riid,
3425 LPVOID *ppvObj)
3426{
3427 if (ppvObj == NULL) return E_POINTER;
3428
3429 if (IsEqualGUID(riid, &IID_IUnknown) ||
3430 IsEqualGUID(riid, &IID_IStdMarshalInfo))
3431 {
3432 *ppvObj = iface;
3433 IStdMarshalInfo_AddRef(iface);
3434 return S_OK;
3435 }
3436
3437 return E_NOINTERFACE;
3438}
3439
3441{
3442 LockModule();
3443 return 2; /* non-heap-based object */
3444}
3445
3447{
3448 UnlockModule();
3449 return 1; /* non-heap-based object */
3450}
3451
3453 IStdMarshalInfo *iface,
3454 DWORD dwDestContext,
3455 void *pvDestContext,
3456 CLSID *pClsid)
3457{
3458 *pClsid = CLSID_WineTest;
3459 return S_OK;
3460}
3461
3462static const IStdMarshalInfoVtbl Test_SMI_Vtbl =
3463{
3468};
3469
3471
3473{
3474 HRESULT hr;
3475 IStream *pStream = NULL;
3476 IUnknown *pProxy = NULL;
3478 DWORD tid;
3479 HANDLE thread;
3480 static const LARGE_INTEGER ullZero;
3481
3483 return;
3484 cLocks = 0;
3485
3486 hr = CreateStreamOnHGlobal(NULL, TRUE, &pStream);
3487 ok_ole_success(hr, "CreateStreamOnHGlobal");
3488 tid = start_host_object(pStream, &IID_IUnknown, (IUnknown*)&Test_SMI, MSHLFLAGS_NORMAL, &thread);
3489
3491
3492 IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
3493 hr = CoUnmarshalInterface(pStream, &IID_IUnknown, (void **)&pProxy);
3494 ok_ole_success(hr, "CoUnmarshalInterface");
3495 IStream_Release(pStream);
3496
3497 if(hr == S_OK)
3498 {
3500
3501 hr = IUnknown_QueryInterface(pProxy, &IID_IWineTest, (void **)&pObject);
3502 ok(hr == E_NOINTERFACE, "IUnknown_QueryInterface with unknown IID should have returned E_NOINTERFACE instead of 0x%08x\n", hr);
3503
3504 /* it's a handler as it supports IOleObject */
3505 hr = IUnknown_QueryInterface(pProxy, &IID_IOleObject, (void **)&pObject);
3506 todo_wine
3507 ok_ole_success(hr, "IUnknown_QueryInterface(&IID_IOleObject)");
3508 if (SUCCEEDED(hr)) IUnknown_Release(pObject);
3509
3510 IUnknown_Release(pProxy);
3511
3512 ok_no_locks();
3513 }
3514
3517
3518 /* FIXME: test IPersist interface has the same effect as IStdMarshalInfo */
3519}
3520
3521
3522static void test_client_security(void)
3523{
3524 HRESULT hr;
3525 IStream *pStream = NULL;
3526 IClassFactory *pProxy = NULL;
3527 IUnknown *pProxy2 = NULL;
3528 IUnknown *pUnknown1 = NULL;
3529 IUnknown *pUnknown2 = NULL;
3530 IClientSecurity *pCliSec = NULL;
3531 IMarshal *pMarshal;
3532 DWORD tid;
3533 HANDLE thread;
3534 static const LARGE_INTEGER ullZero;
3535 DWORD dwAuthnSvc;
3536 DWORD dwAuthzSvc;
3537 OLECHAR *pServerPrincName;
3538 DWORD dwAuthnLevel;
3539 DWORD dwImpLevel;
3540 void *pAuthInfo;
3541 DWORD dwCapabilities;
3542 void *pv;
3543
3544 cLocks = 0;
3545
3546 hr = CreateStreamOnHGlobal(NULL, TRUE, &pStream);
3547 ok_ole_success(hr, "CreateStreamOnHGlobal");
3548 tid = start_host_object(pStream, &IID_IClassFactory, (IUnknown*)&Test_ClassFactory, MSHLFLAGS_NORMAL, &thread);
3549
3550 IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
3551 hr = CoUnmarshalInterface(pStream, &IID_IClassFactory, (void **)&pProxy);
3552 ok_ole_success(hr, "CoUnmarshalInterface");
3553 IStream_Release(pStream);
3554
3555 hr = IClassFactory_QueryInterface(pProxy, &IID_IUnknown, (LPVOID*)&pUnknown1);
3556 ok_ole_success(hr, "IUnknown_QueryInterface IID_IUnknown");
3557
3558 hr = IClassFactory_QueryInterface(pProxy, &IID_IRemUnknown, (LPVOID*)&pProxy2);
3559 ok_ole_success(hr, "IUnknown_QueryInterface IID_IStream");
3560
3561 hr = IUnknown_QueryInterface(pProxy2, &IID_IUnknown, (LPVOID*)&pUnknown2);
3562 ok_ole_success(hr, "IUnknown_QueryInterface IID_IUnknown");
3563
3564 ok(pUnknown1 == pUnknown2, "both proxy's IUnknowns should be the same - %p, %p\n", pUnknown1, pUnknown2);
3565
3566 hr = IClassFactory_QueryInterface(pProxy, &IID_IMarshal, (LPVOID*)&pMarshal);
3567 ok_ole_success(hr, "IUnknown_QueryInterface IID_IMarshal");
3568
3569 hr = IClassFactory_QueryInterface(pProxy, &IID_IClientSecurity, (LPVOID*)&pCliSec);
3570 ok_ole_success(hr, "IUnknown_QueryInterface IID_IClientSecurity");
3571
3572 hr = IClientSecurity_QueryBlanket(pCliSec, (IUnknown *)pProxy, NULL, NULL, NULL, NULL, NULL, NULL, NULL);
3573 todo_wine ok_ole_success(hr, "IClientSecurity_QueryBlanket (all NULLs)");
3574
3575 hr = IClientSecurity_QueryBlanket(pCliSec, (IUnknown *)pMarshal, NULL, NULL, NULL, NULL, NULL, NULL, NULL);
3576 todo_wine ok(hr == E_NOINTERFACE, "IClientSecurity_QueryBlanket with local interface should have returned E_NOINTERFACE instead of 0x%08x\n", hr);
3577
3578 hr = IClientSecurity_QueryBlanket(pCliSec, (IUnknown *)pProxy, &dwAuthnSvc, &dwAuthzSvc, &pServerPrincName, &dwAuthnLevel, &dwImpLevel, &pAuthInfo, &dwCapabilities);
3579 todo_wine ok_ole_success(hr, "IClientSecurity_QueryBlanket");
3580
3581 hr = IClientSecurity_SetBlanket(pCliSec, (IUnknown *)pProxy, dwAuthnSvc, dwAuthzSvc, pServerPrincName, dwAuthnLevel, RPC_C_IMP_LEVEL_IMPERSONATE, pAuthInfo, dwCapabilities);
3582 todo_wine ok_ole_success(hr, "IClientSecurity_SetBlanket");
3583
3584 hr = IClassFactory_CreateInstance(pProxy, NULL, &IID_IWineTest, &pv);
3585 ok(hr == E_NOINTERFACE, "COM call should have succeeded instead of returning 0x%08x\n", hr);
3586
3587 hr = IClientSecurity_SetBlanket(pCliSec, (IUnknown *)pMarshal, dwAuthnSvc, dwAuthzSvc, pServerPrincName, dwAuthnLevel, dwImpLevel, pAuthInfo, dwCapabilities);
3588 todo_wine ok(hr == E_NOINTERFACE, "IClientSecurity_SetBlanket with local interface should have returned E_NOINTERFACE instead of 0x%08x\n", hr);
3589
3590 hr = IClientSecurity_SetBlanket(pCliSec, (IUnknown *)pProxy, 0xdeadbeef, dwAuthzSvc, pServerPrincName, dwAuthnLevel, dwImpLevel, pAuthInfo, dwCapabilities);
3591 todo_wine ok(hr == E_INVALIDARG, "IClientSecurity_SetBlanke with invalid dwAuthnSvc should have returned E_INVALIDARG instead of 0x%08x\n", hr);
3592
3593 CoTaskMemFree(pServerPrincName);
3594
3595 hr = IClientSecurity_QueryBlanket(pCliSec, pUnknown1, &dwAuthnSvc, &dwAuthzSvc, &pServerPrincName, &dwAuthnLevel, &dwImpLevel, &pAuthInfo, &dwCapabilities);
3596 todo_wine ok_ole_success(hr, "IClientSecurity_QueryBlanket(IUnknown)");
3597
3598 CoTaskMemFree(pServerPrincName);
3599
3600 IClassFactory_Release(pProxy);
3601 IUnknown_Release(pProxy2);
3602 IUnknown_Release(pUnknown1);
3603 IUnknown_Release(pUnknown2);
3604 IMarshal_Release(pMarshal);
3605 IClientSecurity_Release(pCliSec);
3606
3608}
3609
3611
3612static void LockModuleOOP(void)
3613{
3614 InterlockedIncrement(&cLocks); /* for test purposes only */
3616}
3617
3618static void UnlockModuleOOP(void)
3619{