2 * Copyright (C) 2005-2006 Robert Shearman for CodeWeavers
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2.1 of the License, or (at your option) any later version.
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with this library; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
29 #include "wine/test.h"
33 static HRESULT (WINAPI
*pVarAdd
)(LPVARIANT
,LPVARIANT
,LPVARIANT
);
36 #define ok_ole_success(hr, func) ok(hr == S_OK, #func " failed with error 0x%08x\n", hr)
37 static inline void release_iface_(unsigned int line
, void *iface
)
39 ULONG ref
= IUnknown_Release((IUnknown
*)iface
);
40 ok_(__FILE__
, line
)(!ref
, "Got outstanding refcount %d.\n", ref
);
41 if (ref
== 1) IUnknown_Release((IUnknown
*)iface
);
43 #define release_iface(a) release_iface_(__LINE__, a)
45 /* ULL suffix is not portable */
46 #define ULL_CONST(dw1, dw2) ((((ULONGLONG)dw1) << 32) | (ULONGLONG)dw2)
48 static const WCHAR test_bstr1
[] = {'f','o','o',0,'b','a','r'};
49 static const WCHAR test_bstr2
[] = {'t','e','s','t',0};
50 static const WCHAR test_bstr3
[] = {'q','u','x',0};
51 static const WCHAR test_bstr4
[] = {'a','b','c',0};
53 static const MYSTRUCT test_mystruct1
= {0x12345678, ULL_CONST(0xdeadbeef, 0x98765432), {0,1,2,3,4,5,6,7}};
54 static const MYSTRUCT test_mystruct2
= {0x91827364, ULL_CONST(0x88776655, 0x44332211), {3,6,1,4,0,1,3,0}};
55 static const MYSTRUCT test_mystruct3
= {0x1a1b1c1d, ULL_CONST(0x1e1f1011, 0x12131415), {9,2,4,5,6,5,1,3}};
56 static const MYSTRUCT test_mystruct4
= {0x2a2b2c2d, ULL_CONST(0x2e2f2021, 0x22232425), {0,4,6,7,3,6,7,4}};
57 static const MYSTRUCT test_mystruct5
= {0x3a3b3c3d, ULL_CONST(0x3e3f3031, 0x32333435), {1,6,7,3,8,4,6,5}};
58 static const MYSTRUCT test_mystruct6
= {0x4a4b4c4d, ULL_CONST(0x4e4f4041, 0x42434445), {3,6,5,3,4,8,0,9}};
59 static const MYSTRUCT test_mystruct7
= {0x5a5b5c5d, ULL_CONST(0x5e5f5051, 0x52535455), {1,8,4,4,4,2,3,1}};
61 static const struct thin test_thin_struct
= {-456, 78};
63 static const RECT test_rect1
= {1,2,3,4};
64 static const RECT test_rect2
= {5,6,7,8};
65 static const RECT test_rect3
= {9,10,11,12};
66 static const RECT test_rect4
= {13,14,15,16};
67 static const RECT test_rect5
= {17,18,19,20};
68 static const RECT test_rect6
= {21,22,23,24};
69 static const RECT test_rect7
= {25,26,27,28};
71 static const array_t test_array1
= {1,2,3,4};
72 static const array_t test_array2
= {5,6,7,8};
73 static const array_t test_array3
= {9,10,11,12};
74 static const array_t test_array4
= {13,14,15,16};
75 static const array_t test_array5
= {17,18,19,20};
76 static const array_t test_array6
= {21,22,23,24};
78 #define RELEASEMARSHALDATA WM_USER
80 struct host_object_data
85 MSHLFLAGS marshal_flags
;
87 IMessageFilter
*filter
;
90 static DWORD CALLBACK
host_object_proc(LPVOID p
)
92 struct host_object_data
*data
= p
;
96 CoInitializeEx(NULL
, COINIT_APARTMENTTHREADED
);
100 IMessageFilter
* prev_filter
= NULL
;
101 hr
= CoRegisterMessageFilter(data
->filter
, &prev_filter
);
102 if (prev_filter
) IMessageFilter_Release(prev_filter
);
103 ok_ole_success(hr
, CoRegisterMessageFilter
);
106 hr
= CoMarshalInterface(data
->stream
, &data
->iid
, data
->object
, MSHCTX_INPROC
, NULL
, data
->marshal_flags
);
107 ok_ole_success(hr
, CoMarshalInterface
);
109 /* force the message queue to be created before signaling parent thread */
110 PeekMessageA(&msg
, NULL
, WM_USER
, WM_USER
, PM_NOREMOVE
);
112 SetEvent(data
->marshal_event
);
114 while (GetMessageA(&msg
, NULL
, 0, 0))
116 if (msg
.hwnd
== NULL
&& msg
.message
== RELEASEMARSHALDATA
)
118 trace("releasing marshal data\n");
119 CoReleaseMarshalData(data
->stream
);
120 SetEvent((HANDLE
)msg
.lParam
);
123 DispatchMessageA(&msg
);
126 HeapFree(GetProcessHeap(), 0, data
);
133 static DWORD
start_host_object2(IStream
*stream
, REFIID riid
, IUnknown
*object
, MSHLFLAGS marshal_flags
, IMessageFilter
*filter
, HANDLE
*thread
)
136 HANDLE marshal_event
= CreateEventA(NULL
, FALSE
, FALSE
, NULL
);
137 struct host_object_data
*data
= HeapAlloc(GetProcessHeap(), 0, sizeof(*data
));
139 data
->stream
= stream
;
141 data
->object
= object
;
142 data
->marshal_flags
= marshal_flags
;
143 data
->marshal_event
= marshal_event
;
144 data
->filter
= filter
;
146 *thread
= CreateThread(NULL
, 0, host_object_proc
, data
, 0, &tid
);
148 /* wait for marshaling to complete before returning */
149 WaitForSingleObject(marshal_event
, INFINITE
);
150 CloseHandle(marshal_event
);
155 static DWORD
start_host_object(IStream
*stream
, REFIID riid
, IUnknown
*object
, MSHLFLAGS marshal_flags
, HANDLE
*thread
)
157 return start_host_object2(stream
, riid
, object
, marshal_flags
, NULL
, thread
);
161 /* asks thread to release the marshal data because it has to be done by the
162 * same thread that marshaled the interface in the first place. */
163 static void release_host_object(DWORD tid
)
165 HANDLE event
= CreateEventA(NULL
, FALSE
, FALSE
, NULL
);
166 PostThreadMessageA(tid
, RELEASEMARSHALDATA
, 0, (LPARAM
)event
);
167 WaitForSingleObject(event
, INFINITE
);
172 static void end_host_object(DWORD tid
, HANDLE thread
)
174 BOOL ret
= PostThreadMessageA(tid
, WM_QUIT
, 0, 0);
175 ok(ret
, "PostThreadMessage failed with error %d\n", GetLastError());
176 /* be careful of races - don't return until hosting thread has terminated */
177 WaitForSingleObject(thread
, INFINITE
);
181 static int external_connections
;
182 static BOOL expect_last_release_closes
;
184 static HRESULT WINAPI
ExternalConnection_QueryInterface(IExternalConnection
*iface
, REFIID riid
, void **ppv
)
186 ok(0, "unexpected call\n");
188 return E_NOINTERFACE
;
191 static ULONG WINAPI
ExternalConnection_AddRef(IExternalConnection
*iface
)
196 static ULONG WINAPI
ExternalConnection_Release(IExternalConnection
*iface
)
201 static DWORD WINAPI
ExternalConnection_AddConnection(IExternalConnection
*iface
, DWORD extconn
, DWORD reserved
)
203 trace("add connection\n");
205 ok(extconn
== EXTCONN_STRONG
, "extconn = %d\n", extconn
);
206 ok(!reserved
, "reserved = %x\n", reserved
);
207 return ++external_connections
;
210 static DWORD WINAPI
ExternalConnection_ReleaseConnection(IExternalConnection
*iface
, DWORD extconn
,
211 DWORD reserved
, BOOL fLastReleaseCloses
)
213 trace("release connection\n");
215 ok(extconn
== EXTCONN_STRONG
, "extconn = %d\n", extconn
);
216 ok(!reserved
, "reserved = %x\n", reserved
);
218 ok(fLastReleaseCloses
== expect_last_release_closes
, "fLastReleaseCloses = %x, expected %x\n",
219 fLastReleaseCloses
, expect_last_release_closes
);
220 return --external_connections
;
223 static const IExternalConnectionVtbl ExternalConnectionVtbl
= {
224 ExternalConnection_QueryInterface
,
225 ExternalConnection_AddRef
,
226 ExternalConnection_Release
,
227 ExternalConnection_AddConnection
,
228 ExternalConnection_ReleaseConnection
231 static IExternalConnection ExternalConnection
= { &ExternalConnectionVtbl
};
233 static ItestDual TestDual
, TestDualDisp
;
235 static HRESULT WINAPI
TestSecondIface_QueryInterface(ITestSecondIface
*iface
, REFIID riid
, void **ppv
)
237 return ItestDual_QueryInterface(&TestDual
, riid
, ppv
);
240 static ULONG WINAPI
TestSecondIface_AddRef(ITestSecondIface
*iface
)
245 static ULONG WINAPI
TestSecondIface_Release(ITestSecondIface
*iface
)
250 static HRESULT WINAPI
TestSecondIface_test(ITestSecondIface
*iface
)
255 static const ITestSecondIfaceVtbl TestSecondIfaceVtbl
= {
256 TestSecondIface_QueryInterface
,
257 TestSecondIface_AddRef
,
258 TestSecondIface_Release
,
262 static ITestSecondIface TestSecondIface
= { &TestSecondIfaceVtbl
};
264 static HRESULT WINAPI
TestSecondDisp_QueryInterface(ITestSecondDisp
*iface
, REFIID riid
, void **ppv
)
266 return ItestDual_QueryInterface(&TestDual
, riid
, ppv
);
269 static ULONG WINAPI
TestSecondDisp_AddRef(ITestSecondDisp
*iface
)
274 static ULONG WINAPI
TestSecondDisp_Release(ITestSecondDisp
*iface
)
279 static HRESULT WINAPI
TestSecondDisp_GetTypeInfoCount(ITestSecondDisp
*iface
, UINT
*pctinfo
)
281 ok(0, "unexpected call\n");
285 static HRESULT WINAPI
TestSecondDisp_GetTypeInfo(ITestSecondDisp
*iface
, UINT iTInfo
, LCID lcid
, ITypeInfo
**ppTInfo
)
287 ok(0, "unexpected call\n");
291 static HRESULT WINAPI
TestSecondDisp_GetIDsOfNames(ITestSecondDisp
*iface
, REFIID riid
, LPOLESTR
*rgszNames
,
292 UINT cNames
, LCID lcid
, DISPID
*rgDispId
)
294 ok(0, "unexpected call\n");
298 static HRESULT WINAPI
TestSecondDisp_Invoke(ITestSecondDisp
*iface
, DISPID dispIdMember
, REFIID riid
, LCID lcid
,
299 WORD wFlags
, DISPPARAMS
*pDispParams
, VARIANT
*pVarResult
, EXCEPINFO
*pExcepInfo
,
302 ok(0, "unexpected call\n");
306 static HRESULT WINAPI
TestSecondDisp_test(ITestSecondDisp
*iface
)
308 ok(0, "unexpected call\n");
312 static ITestSecondDispVtbl TestSecondDispVtbl
= {
313 TestSecondDisp_QueryInterface
,
314 TestSecondDisp_AddRef
,
315 TestSecondDisp_Release
,
316 TestSecondDisp_GetTypeInfoCount
,
317 TestSecondDisp_GetTypeInfo
,
318 TestSecondDisp_GetIDsOfNames
,
319 TestSecondDisp_Invoke
,
323 static ITestSecondDisp TestSecondDisp
= { &TestSecondDispVtbl
};
325 static HRESULT WINAPI
TestDual_QueryInterface(ItestDual
*iface
, REFIID riid
, void **ppvObject
)
327 if (IsEqualIID(riid
, &IID_IUnknown
) || IsEqualIID(riid
, &IID_IDispatch
)) {
328 *ppvObject
= &TestDualDisp
;
330 }else if(IsEqualGUID(riid
, &IID_ItestDual
)) {
331 *ppvObject
= &TestDual
;
333 }else if(IsEqualGUID(riid
, &IID_ITestSecondIface
)) {
334 *ppvObject
= &TestSecondIface
;
336 }else if(IsEqualGUID(riid
, &IID_ITestSecondDisp
)) {
337 *ppvObject
= &TestSecondDisp
;
339 }else if (IsEqualGUID(riid
, &IID_IExternalConnection
)) {
340 trace("QI external connection\n");
341 *ppvObject
= &ExternalConnection
;
346 return E_NOINTERFACE
;
349 static ULONG WINAPI
TestDual_AddRef(ItestDual
*iface
)
354 static ULONG WINAPI
TestDual_Release(ItestDual
*iface
)
359 static HRESULT WINAPI
TestDual_GetTypeInfoCount(ItestDual
*iface
, UINT
*pctinfo
)
361 ok(0, "unexpected call\n");
365 static HRESULT WINAPI
TestDual_GetTypeInfo(ItestDual
*iface
, UINT iTInfo
, LCID lcid
, ITypeInfo
**ppTInfo
)
367 ok(0, "unexpected call\n");
371 static HRESULT WINAPI
TestDual_GetIDsOfNames(ItestDual
*iface
, REFIID riid
, LPOLESTR
*rgszNames
,
372 UINT cNames
, LCID lcid
, DISPID
*rgDispId
)
374 ok(0, "unexpected call\n");
378 static HRESULT WINAPI
TestDual_Invoke(ItestDual
*iface
, DISPID dispIdMember
, REFIID riid
, LCID lcid
,
379 WORD wFlags
, DISPPARAMS
*pDispParams
, VARIANT
*pVarResult
, EXCEPINFO
*pExcepInfo
,
382 ok(0, "unexpected call\n");
386 static ItestDualVtbl TestDualVtbl
= {
387 TestDual_QueryInterface
,
390 TestDual_GetTypeInfoCount
,
391 TestDual_GetTypeInfo
,
392 TestDual_GetIDsOfNames
,
396 static ItestDual TestDual
= { &TestDualVtbl
};
397 static ItestDual TestDualDisp
= { &TestDualVtbl
};
401 ISomethingFromDispatch ISomethingFromDispatch_iface
;
405 static inline struct disp_obj
*impl_from_ISomethingFromDispatch(ISomethingFromDispatch
*iface
)
407 return CONTAINING_RECORD(iface
, struct disp_obj
, ISomethingFromDispatch_iface
);
410 static HRESULT WINAPI
disp_obj_QueryInterface(ISomethingFromDispatch
*iface
, REFIID iid
, void **out
)
412 if (IsEqualGUID(iid
, &IID_IUnknown
) || IsEqualGUID(iid
, &IID_IDispatch
)
413 || IsEqualGUID(iid
, &IID_ISomethingFromDispatch
)
414 || IsEqualGUID(iid
, &DIID_ItestIF4
))
417 ISomethingFromDispatch_AddRef(iface
);
422 return E_NOINTERFACE
;
425 static ULONG WINAPI
disp_obj_AddRef(ISomethingFromDispatch
*iface
)
427 struct disp_obj
*obj
= impl_from_ISomethingFromDispatch(iface
);
431 static ULONG WINAPI
disp_obj_Release(ISomethingFromDispatch
*iface
)
433 struct disp_obj
*obj
= impl_from_ISomethingFromDispatch(iface
);
434 LONG ref
= --obj
->ref
;
440 static HRESULT WINAPI
disp_obj_GetTypeInfoCount(ISomethingFromDispatch
*iface
, UINT
*count
)
442 ok(0, "unexpected call\n");
446 static HRESULT WINAPI
disp_obj_GetTypeInfo(ISomethingFromDispatch
*iface
,
447 UINT index
, LCID lcid
, ITypeInfo
**typeinfo
)
449 ok(index
== 0xdeadbeef, "Got unexpected index %#x.\n", index
);
453 static HRESULT WINAPI
disp_obj_GetIDsOfNames(ISomethingFromDispatch
*iface
,
454 REFIID iid
, LPOLESTR
*names
, UINT count
, LCID lcid
, DISPID
*ids
)
456 ok(0, "unexpected call\n");
460 static HRESULT WINAPI
disp_obj_Invoke(ISomethingFromDispatch
*iface
, DISPID id
, REFIID iid
, LCID lcid
,
461 WORD flags
, DISPPARAMS
*dispparams
, VARIANT
*result
, EXCEPINFO
*excepinfo
, UINT
*errarg
)
463 ok(0, "unexpected call\n");
467 static HRESULT WINAPI
disp_obj_anotherfn(ISomethingFromDispatch
*iface
)
472 static const ISomethingFromDispatchVtbl disp_obj_vtbl
=
474 disp_obj_QueryInterface
,
477 disp_obj_GetTypeInfoCount
,
478 disp_obj_GetTypeInfo
,
479 disp_obj_GetIDsOfNames
,
484 static ISomethingFromDispatch
*create_disp_obj(void)
486 struct disp_obj
*obj
= CoTaskMemAlloc(sizeof(*obj
));
487 obj
->ISomethingFromDispatch_iface
.lpVtbl
= &disp_obj_vtbl
;
489 return &obj
->ISomethingFromDispatch_iface
;
494 ICoclass1 ICoclass1_iface
;
495 ICoclass2 ICoclass2_iface
;
499 static inline struct coclass_obj
*impl_from_ICoclass1(ICoclass1
*iface
)
501 return CONTAINING_RECORD(iface
, struct coclass_obj
, ICoclass1_iface
);
504 static inline struct coclass_obj
*impl_from_ICoclass2(ICoclass2
*iface
)
506 return CONTAINING_RECORD(iface
, struct coclass_obj
, ICoclass2_iface
);
509 static HRESULT WINAPI
coclass1_QueryInterface(ICoclass1
*iface
, REFIID iid
, void **out
)
511 struct coclass_obj
*obj
= impl_from_ICoclass1(iface
);
513 if (IsEqualGUID(iid
, &IID_IUnknown
)
514 || IsEqualGUID(iid
, &IID_IDispatch
)
515 || IsEqualGUID(iid
, &IID_ICoclass1
))
518 ICoclass1_AddRef(iface
);
521 else if (IsEqualGUID(iid
, &IID_ICoclass2
))
523 *out
= &obj
->ICoclass2_iface
;
524 ICoclass2_AddRef(*out
);
529 return E_NOINTERFACE
;
532 static ULONG WINAPI
coclass1_AddRef(ICoclass1
*iface
)
534 struct coclass_obj
*obj
= impl_from_ICoclass1(iface
);
538 static ULONG WINAPI
coclass1_Release(ICoclass1
*iface
)
540 struct coclass_obj
*obj
= impl_from_ICoclass1(iface
);
541 LONG ref
= --obj
->ref
;
547 static HRESULT WINAPI
coclass1_GetTypeInfoCount(ICoclass1
*iface
, UINT
*count
)
549 ok(0, "unexpected call\n");
553 static HRESULT WINAPI
coclass1_GetTypeInfo(ICoclass1
*iface
, UINT index
,
554 LCID lcid
, ITypeInfo
**typeinfo
)
556 ok(index
== 0xdeadbeef, "Got unexpected index %#x.\n", index
);
560 static HRESULT WINAPI
coclass1_GetIDsOfNames(ICoclass1
*iface
, REFIID iid
,
561 LPOLESTR
*names
, UINT count
, LCID lcid
, DISPID
*ids
)
563 ok(0, "unexpected call\n");
567 static HRESULT WINAPI
coclass1_Invoke(ICoclass1
*iface
, DISPID id
, REFIID iid
, LCID lcid
,
568 WORD flags
, DISPPARAMS
*dispparams
, VARIANT
*result
, EXCEPINFO
*excepinfo
, UINT
*errarg
)
570 ok(0, "unexpected call\n");
574 static HRESULT WINAPI
coclass1_test(ICoclass1
*iface
)
579 static HRESULT WINAPI
coclass2_QueryInterface(ICoclass2
*iface
, REFIID iid
, void **out
)
581 struct coclass_obj
*obj
= impl_from_ICoclass2(iface
);
582 return ICoclass1_QueryInterface(&obj
->ICoclass1_iface
, iid
, out
);
585 static ULONG WINAPI
coclass2_AddRef(ICoclass2
*iface
)
587 struct coclass_obj
*obj
= impl_from_ICoclass2(iface
);
588 return ICoclass1_AddRef(&obj
->ICoclass1_iface
);
591 static ULONG WINAPI
coclass2_Release(ICoclass2
*iface
)
593 struct coclass_obj
*obj
= impl_from_ICoclass2(iface
);
594 return ICoclass1_Release(&obj
->ICoclass1_iface
);
597 static HRESULT WINAPI
coclass2_GetTypeInfoCount(ICoclass2
*iface
, UINT
*count
)
599 ok(0, "unexpected call\n");
603 static HRESULT WINAPI
coclass2_GetTypeInfo(ICoclass2
*iface
, UINT index
,
604 LCID lcid
, ITypeInfo
**typeinfo
)
606 ok(index
== 0xdeadbeef, "Got unexpected index %#x.\n", index
);
610 static HRESULT WINAPI
coclass2_GetIDsOfNames(ICoclass2
*iface
, REFIID iid
,
611 LPOLESTR
*names
, UINT count
, LCID lcid
, DISPID
*ids
)
613 ok(0, "unexpected call\n");
617 static HRESULT WINAPI
coclass2_Invoke(ICoclass2
*iface
, DISPID id
, REFIID iid
, LCID lcid
,
618 WORD flags
, DISPPARAMS
*dispparams
, VARIANT
*result
, EXCEPINFO
*excepinfo
, UINT
*errarg
)
620 ok(0, "unexpected call\n");
624 static HRESULT WINAPI
coclass2_test(ICoclass2
*iface
)
629 static const ICoclass1Vtbl coclass1_vtbl
=
631 coclass1_QueryInterface
,
634 coclass1_GetTypeInfoCount
,
635 coclass1_GetTypeInfo
,
636 coclass1_GetIDsOfNames
,
641 static const ICoclass2Vtbl coclass2_vtbl
=
643 coclass2_QueryInterface
,
646 coclass2_GetTypeInfoCount
,
647 coclass2_GetTypeInfo
,
648 coclass2_GetIDsOfNames
,
653 static struct coclass_obj
*create_coclass_obj(void)
655 struct coclass_obj
*obj
= CoTaskMemAlloc(sizeof(*obj
));
656 obj
->ICoclass1_iface
.lpVtbl
= &coclass1_vtbl
;
657 obj
->ICoclass2_iface
.lpVtbl
= &coclass2_vtbl
;
664 typedef struct Widget
666 IWidget IWidget_iface
;
668 IUnknown
*pDispatchUnknown
;
671 static inline Widget
*impl_from_IWidget(IWidget
*iface
)
673 return CONTAINING_RECORD(iface
, Widget
, IWidget_iface
);
676 static HRESULT WINAPI
Widget_QueryInterface(
678 /* [in] */ REFIID riid
,
679 /* [iid_is][out] */ void __RPC_FAR
*__RPC_FAR
*ppvObject
)
681 if (IsEqualIID(riid
, &IID_IWidget
) || IsEqualIID(riid
, &IID_IUnknown
) || IsEqualIID(riid
, &IID_IDispatch
))
683 IWidget_AddRef(iface
);
690 return E_NOINTERFACE
;
694 static ULONG WINAPI
Widget_AddRef(
697 Widget
*This
= impl_from_IWidget(iface
);
699 return InterlockedIncrement(&This
->refs
);
702 static ULONG WINAPI
Widget_Release(
705 Widget
*This
= impl_from_IWidget(iface
);
706 ULONG refs
= InterlockedDecrement(&This
->refs
);
709 IUnknown_Release(This
->pDispatchUnknown
);
710 memset(This
, 0xcc, sizeof(*This
));
711 HeapFree(GetProcessHeap(), 0, This
);
712 trace("Widget destroyed!\n");
718 static HRESULT WINAPI
Widget_GetTypeInfoCount(
720 /* [out] */ UINT __RPC_FAR
*pctinfo
)
722 Widget
*This
= impl_from_IWidget(iface
);
723 IDispatch
*pDispatch
;
724 HRESULT hr
= IUnknown_QueryInterface(This
->pDispatchUnknown
, &IID_IDispatch
, (void **)&pDispatch
);
727 hr
= IDispatch_GetTypeInfoCount(pDispatch
, pctinfo
);
728 IDispatch_Release(pDispatch
);
733 static HRESULT WINAPI
Widget_GetTypeInfo(
734 IWidget __RPC_FAR
* iface
,
735 /* [in] */ UINT iTInfo
,
736 /* [in] */ LCID lcid
,
737 /* [out] */ ITypeInfo __RPC_FAR
*__RPC_FAR
*ppTInfo
)
739 Widget
*This
= impl_from_IWidget(iface
);
740 IDispatch
*pDispatch
;
741 HRESULT hr
= IUnknown_QueryInterface(This
->pDispatchUnknown
, &IID_IDispatch
, (void **)&pDispatch
);
744 hr
= IDispatch_GetTypeInfo(pDispatch
, iTInfo
, lcid
, ppTInfo
);
745 IDispatch_Release(pDispatch
);
750 static HRESULT WINAPI
Widget_GetIDsOfNames(
751 IWidget __RPC_FAR
* iface
,
752 /* [in] */ REFIID riid
,
753 /* [size_is][in] */ LPOLESTR __RPC_FAR
*rgszNames
,
754 /* [in] */ UINT cNames
,
755 /* [in] */ LCID lcid
,
756 /* [size_is][out] */ DISPID __RPC_FAR
*rgDispId
)
758 Widget
*This
= impl_from_IWidget(iface
);
759 IDispatch
*pDispatch
;
760 HRESULT hr
= IUnknown_QueryInterface(This
->pDispatchUnknown
, &IID_IDispatch
, (void **)&pDispatch
);
763 hr
= IDispatch_GetIDsOfNames(pDispatch
, riid
, rgszNames
, cNames
, lcid
, rgDispId
);
764 IDispatch_Release(pDispatch
);
769 static HRESULT WINAPI
Widget_Invoke(
770 IWidget __RPC_FAR
* iface
,
771 /* [in] */ DISPID dispIdMember
,
772 /* [in] */ REFIID riid
,
773 /* [in] */ LCID lcid
,
774 /* [in] */ WORD wFlags
,
775 /* [out][in] */ DISPPARAMS __RPC_FAR
*pDispParams
,
776 /* [out] */ VARIANT __RPC_FAR
*pVarResult
,
777 /* [out] */ EXCEPINFO __RPC_FAR
*pExcepInfo
,
778 /* [out] */ UINT __RPC_FAR
*puArgErr
)
780 Widget
*This
= impl_from_IWidget(iface
);
781 IDispatch
*pDispatch
;
782 HRESULT hr
= IUnknown_QueryInterface(This
->pDispatchUnknown
, &IID_IDispatch
, (void **)&pDispatch
);
785 hr
= IDispatch_Invoke(pDispatch
, dispIdMember
, riid
, lcid
, wFlags
, pDispParams
, pVarResult
, pExcepInfo
, puArgErr
);
786 IDispatch_Release(pDispatch
);
791 static HRESULT WINAPI
Widget_put_Name(
792 IWidget __RPC_FAR
* iface
,
793 /* [in] */ BSTR name
)
795 trace("put_Name(%s)\n", wine_dbgstr_w(name
));
799 static HRESULT WINAPI
Widget_get_Name(
800 IWidget __RPC_FAR
* iface
,
801 /* [out] */ BSTR __RPC_FAR
*name
)
803 static const WCHAR szCat
[] = { 'C','a','t',0 };
804 trace("get_Name()\n");
805 *name
= SysAllocString(szCat
);
809 static HRESULT WINAPI
Widget_DoSomething(
810 IWidget __RPC_FAR
* iface
,
811 /* [in] */ double number
,
812 /* [out] */ BSTR
*str1
,
813 /* [defaultvalue][in] */ BSTR str2
,
814 /* [optional][in] */ VARIANT __RPC_FAR
*opt
)
816 static const WCHAR szString
[] = { 'S','t','r','i','n','g',0 };
817 trace("DoSomething()\n");
819 ok(number
== 3.141, "number(%f) != 3.141\n", number
);
820 ok(*str2
== '\0', "str2(%s) != \"\"\n", wine_dbgstr_w(str2
));
821 ok(V_VT(opt
) == VT_ERROR
, "V_VT(opt) should be VT_ERROR instead of 0x%x\n", V_VT(opt
));
822 ok(V_ERROR(opt
) == DISP_E_PARAMNOTFOUND
, "V_ERROR(opt) should be DISP_E_PARAMNOTFOUND instead of 0x%08x\n", V_ERROR(opt
));
823 *str1
= SysAllocString(szString
);
828 static HRESULT WINAPI
Widget_get_State(
829 IWidget __RPC_FAR
* iface
,
830 /* [retval][out] */ STATE __RPC_FAR
*state
)
832 trace("get_State() = STATE_WIDGETIFIED\n");
833 *state
= STATE_WIDGETIFIED
;
837 static HRESULT WINAPI
Widget_put_State(
838 IWidget __RPC_FAR
* iface
,
839 /* [in] */ STATE state
)
841 trace("put_State(%d)\n", state
);
845 static HRESULT WINAPI
Widget_Map(
850 trace("Map(%s, %p)\n", wine_dbgstr_w(bstrId
), sValue
);
851 *sValue
= SysAllocString(bstrId
);
855 static HRESULT WINAPI
Widget_SetOleColor(
859 trace("SetOleColor(0x%x)\n", val
);
863 static HRESULT WINAPI
Widget_GetOleColor(
867 trace("GetOleColor() = 0x8000000f\n");
872 static HRESULT WINAPI
Widget_Clone(
877 return Widget_QueryInterface(iface
, &IID_IWidget
, (void **)ppVal
);
880 static HRESULT WINAPI
Widget_CloneDispatch(
884 trace("CloneDispatch()\n");
885 return Widget_QueryInterface(iface
, &IID_IWidget
, (void **)ppVal
);
888 static HRESULT WINAPI
Widget_CloneCoclass(
890 ApplicationObject2
**ppVal
)
892 trace("CloneCoclass()\n");
893 return Widget_QueryInterface(iface
, &IID_IWidget
, (void **)ppVal
);
896 static HRESULT WINAPI
Widget_Value(
897 IWidget __RPC_FAR
* iface
,
901 trace("Value(%p, %p)\n", value
, retval
);
902 ok(V_VT(value
) == VT_I2
, "V_VT(value) was %d instead of VT_I2\n", V_VT(value
));
903 ok(V_I2(value
) == 1, "V_I2(value) was %d instead of 1\n", V_I2(value
));
904 V_VT(retval
) = VT_I2
;
909 static HRESULT WINAPI
Widget_VariantArrayPtr(
913 trace("VariantArrayPtr(%p)\n", values
);
917 static HRESULT WINAPI
Widget_VarArg(
922 LONG lbound
, ubound
, i
;
926 trace("VarArg(%p)\n", values
);
928 hr
= SafeArrayGetLBound(values
, 1, &lbound
);
929 ok(hr
== S_OK
, "SafeArrayGetLBound failed with %x\n", hr
);
930 ok(lbound
== 0, "SafeArrayGetLBound returned %d\n", lbound
);
932 hr
= SafeArrayGetUBound(values
, 1, &ubound
);
933 ok(hr
== S_OK
, "SafeArrayGetUBound failed with %x\n", hr
);
934 ok(ubound
== numexpect
-1, "SafeArrayGetUBound returned %d, but expected %d\n", ubound
, numexpect
-1);
936 hr
= SafeArrayAccessData(values
, (LPVOID
)&data
);
937 ok(hr
== S_OK
, "SafeArrayAccessData failed with %x\n", hr
);
939 for (i
=0; i
<=ubound
-lbound
; i
++)
941 ok(V_VT(&data
[i
]) == VT_I4
, "V_VT(&data[%d]) was %d\n", i
, V_VT(&data
[i
]));
942 ok(V_I4(&data
[i
]) == i
, "V_I4(&data[%d]) was %d\n", i
, V_I4(&data
[i
]));
945 hr
= SafeArrayUnaccessData(values
);
946 ok(hr
== S_OK
, "SafeArrayUnaccessData failed with %x\n", hr
);
951 static HRESULT WINAPI
Widget_Error(
952 IWidget __RPC_FAR
* iface
)
958 static HRESULT WINAPI
Widget_CloneInterface(
959 IWidget __RPC_FAR
* iface
,
960 ISomethingFromDispatch
**ppVal
)
962 trace("CloneInterface()\n");
967 static HRESULT WINAPI
Widget_put_prop_with_lcid(
968 IWidget
* iface
, LONG lcid
, INT i
)
970 trace("put_prop_with_lcid(%08x, %x)\n", lcid
, i
);
971 ok(lcid
== MAKELANGID(LANG_ENGLISH
, SUBLANG_ENGLISH_US
), "got lcid %08x\n", lcid
);
972 ok(i
== 0xcafe, "got %08x\n", i
);
976 static HRESULT WINAPI
Widget_get_prop_with_lcid(
977 IWidget
* iface
, LONG lcid
, INT
*i
)
979 trace("get_prop_with_lcid(%08x, %p)\n", lcid
, i
);
980 ok(lcid
== MAKELANGID(LANG_ENGLISH
, SUBLANG_ENGLISH_US
), "got lcid %08x\n", lcid
);
985 static HRESULT WINAPI
Widget_get_prop_int(
986 IWidget
* iface
, INT
*i
)
988 trace("get_prop_int(%p)\n", i
);
993 static HRESULT WINAPI
Widget_get_prop_uint(
994 IWidget
* iface
, UINT
*i
)
996 trace("get_prop_uint(%p)\n", i
);
1001 static HRESULT WINAPI
Widget_ByRefUInt(
1002 IWidget
* iface
, UINT
*i
)
1008 static HRESULT WINAPI
Widget_put_prop_opt_arg(
1009 IWidget
* iface
, INT opt
, INT i
)
1011 trace("put_prop_opt_arg(%08x, %08x)\n", opt
, i
);
1012 todo_wine
ok(opt
== 0, "got opt=%08x\n", opt
);
1013 ok(i
== 0xcafe, "got i=%08x\n", i
);
1017 static HRESULT WINAPI
Widget_put_prop_req_arg(
1018 IWidget
* iface
, INT req
, INT i
)
1020 trace("put_prop_req_arg(%08x, %08x)\n", req
, i
);
1021 ok(req
== 0x5678, "got req=%08x\n", req
);
1022 ok(i
== 0x1234, "got i=%08x\n", i
);
1026 static HRESULT WINAPI
Widget_pos_restrict(IWidget
* iface
, INT
*i
)
1028 trace("restrict\n");
1029 *i
= DISPID_TM_RESTRICTED
;
1033 static HRESULT WINAPI
Widget_neg_restrict(IWidget
* iface
, INT
*i
)
1035 trace("neg_restrict\n");
1036 *i
= DISPID_TM_NEG_RESTRICTED
;
1040 static HRESULT WINAPI
Widget_VarArg_Run(
1041 IWidget
*iface
, BSTR name
, SAFEARRAY
*params
, VARIANT
*result
)
1043 static const WCHAR catW
[] = { 'C','a','t',0 };
1044 static const WCHAR supermanW
[] = { 'S','u','p','e','r','m','a','n',0 };
1050 trace("VarArg_Run(%p,%p,%p)\n", name
, params
, result
);
1052 ok(!lstrcmpW(name
, catW
), "got %s\n", wine_dbgstr_w(name
));
1054 hr
= SafeArrayGetLBound(params
, 1, &bound
);
1055 ok(hr
== S_OK
, "SafeArrayGetLBound error %#x\n", hr
);
1056 ok(bound
== 0, "expected 0, got %d\n", bound
);
1058 hr
= SafeArrayGetUBound(params
, 1, &bound
);
1059 ok(hr
== S_OK
, "SafeArrayGetUBound error %#x\n", hr
);
1060 ok(bound
== 0, "expected 0, got %d\n", bound
);
1062 hr
= SafeArrayAccessData(params
, (void **)&var
);
1063 ok(hr
== S_OK
, "SafeArrayAccessData failed with %x\n", hr
);
1065 ok(V_VT(&var
[0]) == VT_BSTR
, "expected VT_BSTR, got %d\n", V_VT(&var
[0]));
1066 bstr
= V_BSTR(&var
[0]);
1067 ok(!lstrcmpW(bstr
, supermanW
), "got %s\n", wine_dbgstr_w(bstr
));
1069 hr
= SafeArrayUnaccessData(params
);
1070 ok(hr
== S_OK
, "SafeArrayUnaccessData error %#x\n", hr
);
1075 static HRESULT WINAPI
Widget_VarArg_Ref_Run(
1076 IWidget
*iface
, BSTR name
, SAFEARRAY
**params
, VARIANT
*result
)
1078 static const WCHAR catW
[] = { 'C','a','t',0 };
1079 static const WCHAR supermanW
[] = { 'S','u','p','e','r','m','a','n',0 };
1085 trace("VarArg_Ref_Run(%p,%p,%p)\n", name
, params
, result
);
1087 ok(!lstrcmpW(name
, catW
), "got %s\n", wine_dbgstr_w(name
));
1089 hr
= SafeArrayGetLBound(*params
, 1, &bound
);
1090 ok(hr
== S_OK
, "SafeArrayGetLBound error %#x\n", hr
);
1091 ok(bound
== 0, "expected 0, got %d\n", bound
);
1093 hr
= SafeArrayGetUBound(*params
, 1, &bound
);
1094 ok(hr
== S_OK
, "SafeArrayGetUBound error %#x\n", hr
);
1095 ok(bound
== 0, "expected 0, got %d\n", bound
);
1097 hr
= SafeArrayAccessData(*params
, (void **)&var
);
1098 ok(hr
== S_OK
, "SafeArrayAccessData error %#x\n", hr
);
1100 ok(V_VT(&var
[0]) == VT_BSTR
, "expected VT_BSTR, got %d\n", V_VT(&var
[0]));
1101 bstr
= V_BSTR(&var
[0]);
1102 ok(!lstrcmpW(bstr
, supermanW
), "got %s\n", wine_dbgstr_w(bstr
));
1104 hr
= SafeArrayUnaccessData(*params
);
1105 ok(hr
== S_OK
, "SafeArrayUnaccessData error %#x\n", hr
);
1110 static HRESULT WINAPI
Widget_basetypes_in(IWidget
*iface
, signed char c
, short s
, int i
, hyper h
,
1111 unsigned char uc
, unsigned short us
, unsigned int ui
, MIDL_uhyper uh
,
1112 float f
, double d
, STATE st
)
1114 ok(c
== 5, "Got char %d.\n", c
);
1115 ok(s
== -123, "Got short %d.\n", s
);
1116 ok(i
== -100000, "Got int %d.\n", i
);
1117 ok(h
== (LONGLONG
)-100000 * 1000000, "Got hyper %s.\n", wine_dbgstr_longlong(h
));
1118 ok(uc
== 0, "Got unsigned char %u.\n", uc
);
1119 ok(us
== 456, "Got unsigned short %u.\n", us
);
1120 ok(ui
== 0xdeadbeef, "Got unsigned int %i.\n", ui
);
1121 ok(uh
== (ULONGLONG
)1234567890 * 9876543210, "Got unsigned hyper %s.\n", wine_dbgstr_longlong(uh
));
1122 ok(f
== (float)M_PI
, "Got float %f.\n", f
);
1123 ok(d
== M_E
, "Got double %f.\n", d
);
1124 ok(st
== STATE_WIDGETIFIED
, "Got state %u.\n", st
);
1129 static HRESULT WINAPI
Widget_basetypes_out(IWidget
*iface
, signed char *c
, short *s
, int *i
, hyper
*h
,
1130 unsigned char *uc
, unsigned short *us
, unsigned int *ui
, MIDL_uhyper
*uh
,
1131 float *f
, double *d
, STATE
*st
)
1136 *h
= (LONGLONG
)-200000 * 1000000;
1140 *uh
= (((ULONGLONG
)0xabcdef01) << 32) | (ULONGLONG
)0x23456789;
1143 *st
= STATE_UNWIDGETIFIED
;
1148 static HRESULT WINAPI
Widget_float_abi(IWidget
*iface
, float f
, double d
, int i
, float f2
, double d2
)
1150 ok(f
== 1.0f
, "Got float %f.\n", f
);
1151 ok(d
== 2.0, "Got double %f.\n", d
);
1152 ok(i
== 3, "Got int %d.\n", i
);
1153 ok(f2
== 4.0f
, "Got float %f.\n", f2
);
1154 ok(d2
== 5.0, "Got double %f.\n", d2
);
1159 static HRESULT WINAPI
Widget_int_ptr(IWidget
*iface
, int *in
, int *out
, int *in_out
)
1161 ok(*in
== 123, "Got [in] %d.\n", *in
);
1162 if (testmode
== 0) /* Invoke() */
1163 ok(*out
== 456, "Got [out] %d.\n", *out
);
1164 else if (testmode
== 1)
1165 ok(!*out
, "Got [out] %d.\n", *out
);
1166 ok(*in_out
== 789, "Got [in, out] %d.\n", *in_out
);
1175 static HRESULT WINAPI
Widget_int_ptr_ptr(IWidget
*iface
, int **in
, int **out
, int **in_out
)
1177 ok(!*out
, "Got [out] %p.\n", *out
);
1180 ok(!*in
, "Got [in] %p.\n", *in
);
1181 ok(!*in_out
, "Got [in, out] %p.\n", *in_out
);
1183 else if (testmode
== 1)
1185 ok(!*in
, "Got [in] %p.\n", *in
);
1186 ok(!*in_out
, "Got [in, out] %p.\n", *in_out
);
1188 *out
= CoTaskMemAlloc(sizeof(int));
1190 *in_out
= CoTaskMemAlloc(sizeof(int));
1193 else if (testmode
== 2)
1195 ok(**in
== 123, "Got [in] %d.\n", **in
);
1196 ok(**in_out
== 789, "Got [in, out] %d.\n", **in_out
);
1198 *out
= CoTaskMemAlloc(sizeof(int));
1202 else if (testmode
== 3)
1204 ok(**in_out
== 789, "Got [in, out] %d.\n", **in_out
);
1211 /* Call methods to check that we have valid proxies to each interface. */
1212 static void check_iface_marshal(IUnknown
*unk
, IDispatch
*disp
, ISomethingFromDispatch
*sfd
)
1214 ISomethingFromDispatch
*sfd2
;
1215 ITypeInfo
*typeinfo
;
1218 hr
= IUnknown_QueryInterface(unk
, &IID_ISomethingFromDispatch
, (void **)&sfd2
);
1219 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
1220 ISomethingFromDispatch_Release(sfd2
);
1222 hr
= IDispatch_GetTypeInfo(disp
, 0xdeadbeef, 0, &typeinfo
);
1223 ok(hr
== 0xbeefdead, "Got hr %#x.\n", hr
);
1225 hr
= ISomethingFromDispatch_anotherfn(sfd
);
1226 ok(hr
== 0x01234567, "Got hr %#x.\n", hr
);
1229 static HRESULT WINAPI
Widget_iface_in(IWidget
*iface
, IUnknown
*unk
, IDispatch
*disp
, ISomethingFromDispatch
*sfd
)
1232 check_iface_marshal(unk
, disp
, sfd
);
1233 else if (testmode
== 1)
1235 ok(!unk
, "Got iface %p.\n", unk
);
1236 ok(!disp
, "Got iface %p.\n", disp
);
1237 ok(!sfd
, "Got iface %p.\n", sfd
);
1242 static HRESULT WINAPI
Widget_iface_out(IWidget
*iface
, IUnknown
**unk
, IDispatch
**disp
, ISomethingFromDispatch
**sfd
)
1244 ok(!*unk
, "Got iface %p.\n", *unk
);
1245 ok(!*disp
, "Got iface %p.\n", *disp
);
1246 ok(!*sfd
, "Got iface %p.\n", *sfd
);
1250 *unk
= (IUnknown
*)create_disp_obj();
1251 *disp
= (IDispatch
*)create_disp_obj();
1252 *sfd
= create_disp_obj();
1257 static HRESULT WINAPI
Widget_iface_ptr(IWidget
*iface
, ISomethingFromDispatch
**in
,
1258 ISomethingFromDispatch
**out
, ISomethingFromDispatch
**in_out
)
1262 ok(!*out
, "Got [out] %p.\n", *out
);
1263 if (testmode
== 0 || testmode
== 1)
1265 hr
= ISomethingFromDispatch_anotherfn(*in
);
1266 ok(hr
== 0x01234567, "Got hr %#x.\n", hr
);
1267 hr
= ISomethingFromDispatch_anotherfn(*in_out
);
1268 ok(hr
== 0x01234567, "Got hr %#x.\n", hr
);
1273 *out
= create_disp_obj();
1274 ISomethingFromDispatch_Release(*in_out
);
1275 *in_out
= create_disp_obj();
1277 else if (testmode
== 2)
1279 ok(!*in
, "Got [in] %p.\n", *in
);
1280 ok(!*in_out
, "Got [in, out] %p.\n", *in_out
);
1281 *in_out
= create_disp_obj();
1283 else if (testmode
== 3)
1285 hr
= ISomethingFromDispatch_anotherfn(*in_out
);
1286 ok(hr
== 0x01234567, "Got hr %#x.\n", hr
);
1287 ISomethingFromDispatch_Release(*in_out
);
1294 static HRESULT WINAPI
Widget_iface_noptr(IWidget
*iface
, IUnknown unk
, IDispatch disp
, ISomethingFromDispatch sfd
)
1296 check_iface_marshal((IUnknown
*)unk
.lpVtbl
, (IDispatch
*)disp
.lpVtbl
, (ISomethingFromDispatch
*)sfd
.lpVtbl
);
1300 static HRESULT WINAPI
Widget_bstr(IWidget
*iface
, BSTR in
, BSTR
*out
, BSTR
*in_ptr
, BSTR
*in_out
)
1306 len
= SysStringByteLen(in
);
1307 ok(len
== sizeof(test_bstr1
), "Got wrong length %u.\n", len
);
1308 ok(!memcmp(in
, test_bstr1
, len
), "Got string %s.\n", wine_dbgstr_wn(in
, len
/ sizeof(WCHAR
)));
1309 ok(!*out
, "Got unexpected output %p.\n", *out
);
1310 len
= SysStringLen(*in_ptr
);
1311 ok(len
== lstrlenW(test_bstr2
), "Got wrong length %u.\n", len
);
1312 ok(!memcmp(*in_ptr
, test_bstr2
, len
), "Got string %s.\n", wine_dbgstr_w(*in_ptr
));
1313 len
= SysStringLen(*in_out
);
1314 ok(len
== lstrlenW(test_bstr3
), "Got wrong length %u.\n", len
);
1315 ok(!memcmp(*in_out
, test_bstr3
, len
), "Got string %s.\n", wine_dbgstr_w(*in_out
));
1317 *out
= SysAllocString(test_bstr4
);
1318 in
[1] = (*in_ptr
)[1] = (*in_out
)[1] = 'X';
1320 else if (testmode
== 1)
1322 ok(!in
, "Got string %s.\n", wine_dbgstr_w(in
));
1323 ok(!*out
, "Got string %s.\n", wine_dbgstr_w(*out
));
1324 ok(!*in_ptr
, "Got string %s.\n", wine_dbgstr_w(*in_ptr
));
1325 ok(!*in_out
, "Got string %s.\n", wine_dbgstr_w(*in_out
));
1330 static HRESULT WINAPI
Widget_variant(IWidget
*iface
, VARIANT in
, VARIANT
*out
, VARIANT
*in_ptr
, VARIANT
*in_out
)
1332 ok(V_VT(&in
) == VT_CY
, "Got wrong type %#x.\n", V_VT(&in
));
1333 ok(V_CY(&in
).Hi
== 0xdababe && V_CY(&in
).Lo
== 0xdeadbeef,
1334 "Got wrong value %s.\n", wine_dbgstr_longlong(V_CY(&in
).int64
));
1337 ok(V_VT(out
) == VT_I4
, "Got wrong type %u.\n", V_VT(out
));
1338 ok(V_I4(out
) == 1, "Got wrong value %d.\n", V_I4(out
));
1341 ok(V_VT(out
) == VT_EMPTY
, "Got wrong type %u.\n", V_VT(out
));
1342 ok(V_VT(in_ptr
) == VT_I4
, "Got wrong type %u.\n", V_VT(in_ptr
));
1343 ok(V_I4(in_ptr
) == -1, "Got wrong value %d.\n", V_I4(in_ptr
));
1344 ok(V_VT(in_out
) == VT_BSTR
, "Got wrong type %u.\n", V_VT(in_out
));
1345 ok(!lstrcmpW(V_BSTR(in_out
), test_bstr2
), "Got wrong value %s.\n",
1346 wine_dbgstr_w(V_BSTR(in_out
)));
1352 V_VT(in_ptr
) = VT_I2
;
1354 VariantClear(in_out
);
1355 V_VT(in_out
) = VT_I1
;
1360 static SAFEARRAY
*make_safearray(ULONG len
)
1362 SAFEARRAY
*sa
= SafeArrayCreateVector(VT_I4
, 0, len
);
1365 SafeArrayAccessData(sa
, (void **)&data
);
1366 for (i
= 0; i
< len
; ++i
)
1368 SafeArrayUnaccessData(sa
);
1373 static void check_safearray(SAFEARRAY
*sa
, LONG expect
)
1378 hr
= SafeArrayGetUBound(sa
, 1, &len
);
1380 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
1381 ok(len
== expect
, "Expected len %d, got %d.\n", expect
, len
);
1383 hr
= SafeArrayAccessData(sa
, (void **)&data
);
1384 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
1386 for (i
= 0; i
< len
; ++i
)
1387 ok(data
[i
] == len
+ i
, "Expected data %d at %d, got %d.\n", len
+ i
, i
, data
[i
]);
1389 SafeArrayUnaccessData(sa
);
1392 static HRESULT WINAPI
Widget_safearray(IWidget
*iface
, SAFEARRAY
*in
, SAFEARRAY
**out
, SAFEARRAY
**in_ptr
, SAFEARRAY
**in_out
)
1396 check_safearray(in
, 3);
1397 ok(!*out
, "Got array %p.\n", *out
);
1398 check_safearray(*in_ptr
, 7);
1399 check_safearray(*in_out
, 9);
1401 hr
= SafeArrayDestroy(*in_out
);
1402 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
1404 *out
= make_safearray(4);
1405 *in_out
= make_safearray(6);
1410 static HRESULT WINAPI
Widget_mystruct(IWidget
*iface
, MYSTRUCT in
, MYSTRUCT
*out
, MYSTRUCT
*in_ptr
, MYSTRUCT
*in_out
)
1412 static const MYSTRUCT empty
= {0};
1413 ok(!memcmp(&in
, &test_mystruct1
, sizeof(in
)), "Structs didn't match.\n");
1414 ok(!memcmp(out
, &empty
, sizeof(*out
)), "Structs didn't match.\n");
1415 ok(!memcmp(in_ptr
, &test_mystruct3
, sizeof(*in_ptr
)), "Structs didn't match.\n");
1416 ok(!memcmp(in_out
, &test_mystruct4
, sizeof(*in_out
)), "Structs didn't match.\n");
1418 memcpy(out
, &test_mystruct5
, sizeof(*out
));
1419 memcpy(in_ptr
, &test_mystruct6
, sizeof(*in_ptr
));
1420 memcpy(in_out
, &test_mystruct7
, sizeof(*in_out
));
1424 static HRESULT WINAPI
Widget_mystruct_ptr_ptr(IWidget
*iface
, MYSTRUCT
**in
)
1426 ok(!memcmp(*in
, &test_mystruct1
, sizeof(**in
)), "Structs didn't match.\n");
1430 static HRESULT WINAPI
Widget_thin_struct(IWidget
*iface
, struct thin in
)
1432 ok(!memcmp(&in
, &test_thin_struct
, sizeof(in
)), "Structs didn't match.\n");
1436 static HRESULT WINAPI
Widget_rect(IWidget
*iface
, RECT in
, RECT
*out
, RECT
*in_ptr
, RECT
*in_out
)
1438 static const RECT empty
= {0};
1439 ok(EqualRect(&in
, &test_rect1
), "Rects didn't match.\n");
1440 ok(EqualRect(out
, &empty
), "Rects didn't match.\n");
1441 ok(EqualRect(in_ptr
, &test_rect3
), "Rects didn't match.\n");
1442 ok(EqualRect(in_out
, &test_rect4
), "Rects didn't match.\n");
1445 *in_ptr
= test_rect6
;
1446 *in_out
= test_rect7
;
1450 static HRESULT WINAPI
Widget_complex_struct(IWidget
*iface
, struct complex in
)
1454 ok(in
.c
== 98, "Got char %d.\n", in
.c
);
1455 ok(in
.i
== 76543, "Got int %d.\n", in
.i
);
1456 ok(*in
.pi
== 2, "Got int pointer %d.\n", *in
.pi
);
1457 ok(**in
.ppi
== 10, "Got int double pointer %d.\n", **in
.ppi
);
1458 hr
= ISomethingFromDispatch_anotherfn(in
.iface
);
1459 ok(hr
== 0x01234567, "Got wrong hr %#x.\n", hr
);
1460 hr
= ISomethingFromDispatch_anotherfn(*in
.iface_ptr
);
1461 ok(hr
== 0x01234567, "Got wrong hr %#x.\n", hr
);
1462 ok(!lstrcmpW(in
.bstr
, test_bstr2
), "Got string %s.\n", wine_dbgstr_w(in
.bstr
));
1463 ok(V_VT(&in
.var
) == VT_I4
, "Got wrong type %u.\n", V_VT(&in
.var
));
1464 ok(V_I4(&in
.var
) == 123, "Got wrong value %d.\n", V_I4(&in
.var
));
1465 ok(!memcmp(&in
.mystruct
, &test_mystruct1
, sizeof(MYSTRUCT
)), "Structs didn't match.\n");
1466 ok(!memcmp(in
.arr
, test_array1
, sizeof(array_t
)), "Arrays didn't match.\n");
1467 ok(in
.myint
== 456, "Got int %d.\n", in
.myint
);
1472 static HRESULT WINAPI
Widget_array(IWidget
*iface
, array_t in
, array_t out
, array_t in_out
)
1474 static const array_t empty
= {0};
1475 ok(!memcmp(in
, test_array1
, sizeof(array_t
)), "Arrays didn't match.\n");
1476 ok(!memcmp(out
, empty
, sizeof(array_t
)), "Arrays didn't match.\n");
1477 ok(!memcmp(in_out
, test_array3
, sizeof(array_t
)), "Arrays didn't match.\n");
1479 memcpy(in
, test_array4
, sizeof(array_t
));
1480 memcpy(out
, test_array5
, sizeof(array_t
));
1481 memcpy(in_out
, test_array6
, sizeof(array_t
));
1486 static HRESULT WINAPI
Widget_variant_array(IWidget
*iface
, VARIANT in
[2], VARIANT out
[2], VARIANT in_out
[2])
1488 ok(V_VT(&in
[0]) == VT_I4
, "Got wrong type %u.\n", V_VT(&in
[0]));
1489 ok(V_I4(&in
[0]) == 1, "Got wrong value %d.\n", V_I4(&in
[0]));
1490 ok(V_VT(&in
[1]) == (VT_BYREF
|VT_I4
), "Got wrong type %u.\n", V_VT(&in
[1]));
1491 ok(*V_I4REF(&in
[1]) == 2, "Got wrong value %d.\n", *V_I4REF(&in
[1]));
1492 ok(V_VT(&out
[0]) == VT_EMPTY
, "Got wrong type %u.\n", V_VT(&out
[0]));
1493 ok(V_VT(&out
[1]) == VT_EMPTY
, "Got wrong type %u.\n", V_VT(&out
[1]));
1494 ok(V_VT(&in_out
[0]) == VT_I4
, "Got wrong type %u.\n", V_VT(&in_out
[0]));
1495 ok(V_I4(&in_out
[0]) == 5, "Got wrong type %u.\n", V_VT(&in_out
[0]));
1496 ok(V_VT(&in_out
[1]) == VT_BSTR
, "Got wrong type %u.\n", V_VT(&in_out
[1]));
1497 ok(!lstrcmpW(V_BSTR(&in_out
[1]), test_bstr1
), "Got wrong value %s.\n", wine_dbgstr_w(V_BSTR(&in
[1])));
1499 V_VT(&in
[0]) = VT_I1
; V_I1(&in
[0]) = 7;
1500 V_VT(&in
[1]) = VT_I1
; V_I1(&in
[1]) = 8;
1501 V_VT(&out
[0]) = VT_I1
; V_I1(&out
[0]) = 9;
1502 V_VT(&out
[1]) = VT_BSTR
; V_BSTR(&out
[1]) = SysAllocString(test_bstr2
);
1503 V_VT(&in_out
[0]) = VT_I1
; V_I1(&in_out
[0]) = 11;
1504 V_VT(&in_out
[1]) = VT_UNKNOWN
; V_UNKNOWN(&in_out
[1]) = (IUnknown
*)create_disp_obj();
1509 static HRESULT WINAPI
Widget_mystruct_array(IWidget
*iface
, MYSTRUCT in
[2])
1511 ok(!memcmp(&in
[0], &test_mystruct1
, sizeof(MYSTRUCT
)), "Structs didn't match.\n");
1512 ok(!memcmp(&in
[1], &test_mystruct2
, sizeof(MYSTRUCT
)), "Structs didn't match.\n");
1516 static HRESULT WINAPI
Widget_myint(IWidget
*iface
, myint_t val
, myint_t
*ptr
, myint_t
**ptr_ptr
)
1518 ok(val
== 123, "Got value %d.\n", val
);
1519 ok(*ptr
== 456, "Got single ptr ref %d.\n", *ptr
);
1520 ok(**ptr_ptr
== 789, "Got double ptr ref %d.\n", **ptr_ptr
);
1524 static HRESULT WINAPI
Widget_Coclass(IWidget
*iface
, Coclass1
*class1
, Coclass2
*class2
, Coclass3
*class3
)
1528 hr
= ICoclass1_test((ICoclass1
*)class1
);
1529 ok(hr
== 1, "Got hr %#x.\n", hr
);
1531 hr
= ICoclass2_test((ICoclass2
*)class2
);
1532 ok(hr
== 2, "Got hr %#x.\n", hr
);
1534 hr
= ICoclass1_test((ICoclass1
*)class3
);
1535 ok(hr
== 1, "Got hr %#x.\n", hr
);
1540 static HRESULT WINAPI
Widget_Coclass_ptr(IWidget
*iface
, Coclass1
**in
, Coclass1
**out
, Coclass1
**in_out
)
1542 struct coclass_obj
*obj
;
1545 ok(!*out
, "Got [out] %p.\n", *out
);
1546 if (testmode
== 0 || testmode
== 1)
1548 hr
= ICoclass1_test((ICoclass1
*)*in
);
1549 ok(hr
== 1, "Got hr %#x.\n", hr
);
1550 hr
= ICoclass1_test((ICoclass1
*)*in_out
);
1551 ok(hr
== 1, "Got hr %#x.\n", hr
);
1556 obj
= create_coclass_obj();
1557 *out
= (Coclass1
*)&obj
->ICoclass1_iface
;
1559 ICoclass1_Release((ICoclass1
*)*in_out
);
1560 obj
= create_coclass_obj();
1561 *in_out
= (Coclass1
*)&obj
->ICoclass1_iface
;
1563 else if (testmode
== 2)
1565 ok(!*in_out
, "Got [in, out] %p.\n", *in_out
);
1566 obj
= create_coclass_obj();
1567 *in_out
= (Coclass1
*)&obj
->ICoclass1_iface
;
1569 else if (testmode
== 3)
1571 hr
= ICoclass1_test((ICoclass1
*)*in_out
);
1572 ok(hr
== 1, "Got hr %#x.\n", hr
);
1573 ICoclass1_Release((ICoclass1
*)*in_out
);
1580 static HRESULT WINAPI
Widget_Coclass_noptr(IWidget
*iface
, Coclass1 class1
, Coclass2 class2
, Coclass3 class3
)
1584 hr
= ICoclass1_test(class1
.iface
);
1585 ok(hr
== 1, "Got hr %#x.\n", hr
);
1587 hr
= ICoclass2_test(class2
.iface
);
1588 ok(hr
== 2, "Got hr %#x.\n", hr
);
1590 hr
= ICoclass1_test(class3
.iface
);
1591 ok(hr
== 1, "Got hr %#x.\n", hr
);
1596 static HRESULT WINAPI
Widget_no_in_out(IWidget
*iface
, BSTR str
, int i
)
1598 ok(SysStringLen(str
) == 4, "unexpected len\n");
1599 ok(!lstrcmpW(str
, L
"test"), "unexpected str %s\n", wine_dbgstr_w(str
));
1600 ok(i
== 5, "i = %d\n", i
);
1604 static const struct IWidgetVtbl Widget_VTable
=
1606 Widget_QueryInterface
,
1609 Widget_GetTypeInfoCount
,
1611 Widget_GetIDsOfNames
,
1622 Widget_CloneDispatch
,
1623 Widget_CloneCoclass
,
1625 Widget_VariantArrayPtr
,
1628 Widget_CloneInterface
,
1629 Widget_put_prop_with_lcid
,
1630 Widget_get_prop_with_lcid
,
1631 Widget_get_prop_int
,
1632 Widget_get_prop_uint
,
1634 Widget_put_prop_opt_arg
,
1635 Widget_put_prop_req_arg
,
1636 Widget_pos_restrict
,
1637 Widget_neg_restrict
,
1639 Widget_VarArg_Ref_Run
,
1640 Widget_basetypes_in
,
1641 Widget_basetypes_out
,
1653 Widget_mystruct_ptr_ptr
,
1656 Widget_complex_struct
,
1658 Widget_variant_array
,
1659 Widget_mystruct_array
,
1663 Widget_Coclass_noptr
,
1667 static HRESULT WINAPI
StaticWidget_QueryInterface(IStaticWidget
*iface
, REFIID riid
, void **ppvObject
)
1669 if (IsEqualIID(riid
, &IID_IStaticWidget
) || IsEqualIID(riid
, &IID_IUnknown
) || IsEqualIID(riid
, &IID_IDispatch
))
1671 IStaticWidget_AddRef(iface
);
1677 return E_NOINTERFACE
;
1680 static ULONG WINAPI
StaticWidget_AddRef(IStaticWidget
*iface
)
1685 static ULONG WINAPI
StaticWidget_Release(IStaticWidget
*iface
)
1690 static HRESULT WINAPI
StaticWidget_GetTypeInfoCount(IStaticWidget
*iface
, UINT
*pctinfo
)
1692 ok(0, "unexpected call\n");
1696 static HRESULT WINAPI
StaticWidget_GetTypeInfo(IStaticWidget
*iface
, UINT iTInfo
, LCID lcid
,
1697 ITypeInfo
**ppTInfo
)
1699 ok(0, "unexpected call\n");
1703 static HRESULT WINAPI
StaticWidget_GetIDsOfNames(IStaticWidget
*iface
, REFIID riid
, LPOLESTR
*rgszNames
,
1704 UINT cNames
, LCID lcid
, DISPID
*rgDispId
)
1706 ok(0, "unexpected call\n");
1710 static HRESULT WINAPI
StaticWidget_Invoke(IStaticWidget
*iface
, DISPID dispIdMember
, REFIID riid
,
1711 LCID lcid
, WORD wFlags
, DISPPARAMS
*pDispParams
, VARIANT
*pVarResult
, EXCEPINFO
*pExcepInfo
,
1714 ok(0, "unexpected call\n");
1718 static HRESULT WINAPI
StaticWidget_TestDual(IStaticWidget
*iface
, ItestDual
*p
)
1720 trace("TestDual()\n");
1721 ok(p
== &TestDual
, "wrong ItestDual\n");
1725 static HRESULT WINAPI
StaticWidget_TestSecondIface(IStaticWidget
*iface
, ITestSecondIface
*p
)
1727 trace("TestSecondIface()\n");
1728 ok(p
== &TestSecondIface
, "wrong ItestSecondIface\n");
1732 static const IStaticWidgetVtbl StaticWidgetVtbl
= {
1733 StaticWidget_QueryInterface
,
1734 StaticWidget_AddRef
,
1735 StaticWidget_Release
,
1736 StaticWidget_GetTypeInfoCount
,
1737 StaticWidget_GetTypeInfo
,
1738 StaticWidget_GetIDsOfNames
,
1739 StaticWidget_Invoke
,
1740 StaticWidget_TestDual
,
1741 StaticWidget_TestSecondIface
1744 static IStaticWidget StaticWidget
= { &StaticWidgetVtbl
};
1746 typedef struct KindaEnum
1748 IKindaEnumWidget IKindaEnumWidget_iface
;
1752 static inline KindaEnum
*impl_from_IKindaEnumWidget(IKindaEnumWidget
*iface
)
1754 return CONTAINING_RECORD(iface
, KindaEnum
, IKindaEnumWidget_iface
);
1757 static HRESULT
register_current_module_typelib(void)
1759 WCHAR path
[MAX_PATH
];
1760 CHAR pathA
[MAX_PATH
];
1764 GetModuleFileNameA(NULL
, pathA
, MAX_PATH
);
1765 MultiByteToWideChar(CP_ACP
, 0, pathA
, -1, path
, MAX_PATH
);
1767 hr
= LoadTypeLib(path
, &typelib
);
1770 hr
= RegisterTypeLib(typelib
, path
, NULL
);
1771 ITypeLib_Release(typelib
);
1776 static ITypeInfo
*get_type_info(REFIID riid
)
1778 ITypeInfo
*pTypeInfo
;
1782 hr
= LoadRegTypeLib(&LIBID_TestTypelib
, 2, 5, LOCALE_NEUTRAL
, &pTypeLib
);
1783 ok_ole_success(hr
, LoadRegTypeLib
);
1787 hr
= ITypeLib_GetTypeInfoOfGuid(pTypeLib
, riid
, &pTypeInfo
);
1788 ITypeLib_Release(pTypeLib
);
1789 ok_ole_success(hr
, ITypeLib_GetTypeInfoOfGuid
);
1796 static IWidget
*Widget_Create(void)
1799 ITypeInfo
*pTypeInfo
;
1800 HRESULT hr
= E_FAIL
;
1802 pTypeInfo
= get_type_info(&IID_IWidget
);
1806 This
= HeapAlloc(GetProcessHeap(), 0, sizeof(*This
));
1807 This
->IWidget_iface
.lpVtbl
= &Widget_VTable
;
1809 This
->pDispatchUnknown
= NULL
;
1811 hr
= CreateStdDispatch((IUnknown
*)&This
->IWidget_iface
, This
, pTypeInfo
,
1812 &This
->pDispatchUnknown
);
1813 ok_ole_success(hr
, CreateStdDispatch
);
1814 ITypeInfo_Release(pTypeInfo
);
1817 return &This
->IWidget_iface
;
1820 HeapFree(GetProcessHeap(), 0, This
);
1825 static HRESULT WINAPI
KindaEnum_QueryInterface(
1826 IKindaEnumWidget
*iface
,
1827 /* [in] */ REFIID riid
,
1828 /* [iid_is][out] */ void __RPC_FAR
*__RPC_FAR
*ppvObject
)
1830 if (IsEqualIID(riid
, &IID_IKindaEnumWidget
) || IsEqualIID(riid
, &IID_IUnknown
))
1832 IKindaEnumWidget_AddRef(iface
);
1839 return E_NOINTERFACE
;
1843 static ULONG WINAPI
KindaEnum_AddRef(
1844 IKindaEnumWidget
*iface
)
1846 KindaEnum
*This
= impl_from_IKindaEnumWidget(iface
);
1848 return InterlockedIncrement(&This
->refs
);
1851 static ULONG WINAPI
KindaEnum_Release(
1852 IKindaEnumWidget
*iface
)
1854 KindaEnum
*This
= impl_from_IKindaEnumWidget(iface
);
1855 ULONG refs
= InterlockedDecrement(&This
->refs
);
1858 memset(This
, 0xcc, sizeof(*This
));
1859 HeapFree(GetProcessHeap(), 0, This
);
1860 trace("KindaEnumWidget destroyed!\n");
1866 static HRESULT WINAPI
KindaEnum_Next(
1867 IKindaEnumWidget
*iface
,
1868 /* [out] */ IWidget __RPC_FAR
*__RPC_FAR
*widget
)
1870 *widget
= Widget_Create();
1874 return E_OUTOFMEMORY
;
1877 static HRESULT WINAPI
KindaEnum_Count(
1878 IKindaEnumWidget
*iface
,
1879 /* [out] */ ULONG __RPC_FAR
*count
)
1884 static HRESULT WINAPI
KindaEnum_Reset(
1885 IKindaEnumWidget
*iface
)
1890 static HRESULT WINAPI
KindaEnum_Clone(
1891 IKindaEnumWidget
*iface
,
1892 /* [out] */ IKindaEnumWidget __RPC_FAR
*__RPC_FAR
*ppenum
)
1897 static const IKindaEnumWidgetVtbl KindaEnumWidget_VTable
=
1899 KindaEnum_QueryInterface
,
1908 static IKindaEnumWidget
*KindaEnumWidget_Create(void)
1912 This
= HeapAlloc(GetProcessHeap(), 0, sizeof(*This
));
1913 if (!This
) return NULL
;
1914 This
->IKindaEnumWidget_iface
.lpVtbl
= &KindaEnumWidget_VTable
;
1916 return &This
->IKindaEnumWidget_iface
;
1919 static HRESULT WINAPI
NonOleAutomation_QueryInterface(INonOleAutomation
*iface
, REFIID riid
, void **ppv
)
1921 if (IsEqualIID(riid
, &IID_IUnknown
) || IsEqualIID(riid
, &IID_INonOleAutomation
))
1923 *(INonOleAutomation
**)ppv
= iface
;
1927 return E_NOINTERFACE
;
1930 static ULONG WINAPI
NonOleAutomation_AddRef(INonOleAutomation
*iface
)
1935 static ULONG WINAPI
NonOleAutomation_Release(INonOleAutomation
*iface
)
1940 static BSTR WINAPI
NonOleAutomation_BstrRet(INonOleAutomation
*iface
)
1942 static const WCHAR wszTestString
[] = {'T','h','i','s',' ','i','s',' ','a',' ','t','e','s','t',' ','s','t','r','i','n','g',0};
1943 return SysAllocString(wszTestString
);
1946 static HRESULT WINAPI
NonOleAutomation_Error(INonOleAutomation
*iface
)
1951 static INonOleAutomationVtbl NonOleAutomation_VTable
=
1953 NonOleAutomation_QueryInterface
,
1954 NonOleAutomation_AddRef
,
1955 NonOleAutomation_Release
,
1956 NonOleAutomation_BstrRet
,
1957 NonOleAutomation_Error
1960 static INonOleAutomation NonOleAutomation
= { &NonOleAutomation_VTable
};
1962 static ITypeInfo
*NonOleAutomation_GetTypeInfo(void)
1965 HRESULT hr
= LoadRegTypeLib(&LIBID_TestTypelib
, 2, 5, LOCALE_NEUTRAL
, &pTypeLib
);
1966 ok_ole_success(hr
, LoadRegTypeLib
);
1969 ITypeInfo
*pTypeInfo
;
1970 hr
= ITypeLib_GetTypeInfoOfGuid(pTypeLib
, &IID_INonOleAutomation
, &pTypeInfo
);
1971 ok_ole_success(hr
, ITypeLib_GetTypeInfoOfGuid
);
1972 ITypeLib_Release(pTypeLib
);
1978 static void test_marshal_basetypes(IWidget
*widget
, IDispatch
*disp
)
1981 DISPPARAMS dispparams
= {arg
, NULL
, ARRAY_SIZE(arg
), 0};
1996 V_VT(&arg
[10]) = VT_I1
; V_I1(&arg
[10]) = 5;
1997 V_VT(&arg
[9]) = VT_I2
; V_I2(&arg
[9]) = -123;
1998 V_VT(&arg
[8]) = VT_I4
; V_I4(&arg
[8]) = -100000;
1999 V_VT(&arg
[7]) = VT_I8
; V_I8(&arg
[7]) = (LONGLONG
)-100000 * 1000000;
2000 V_VT(&arg
[6]) = VT_UI1
; V_UI1(&arg
[6]) = 0;
2001 V_VT(&arg
[5]) = VT_UI2
; V_UI2(&arg
[5]) = 456;
2002 V_VT(&arg
[4]) = VT_UI4
; V_UI4(&arg
[4]) = 0xdeadbeef;
2003 V_VT(&arg
[3]) = VT_UI8
; V_UI8(&arg
[3]) = (ULONGLONG
)1234567890 * 9876543210;
2004 V_VT(&arg
[2]) = VT_R4
; V_R4(&arg
[2]) = M_PI
;
2005 V_VT(&arg
[1]) = VT_R8
; V_R8(&arg
[1]) = M_E
;
2006 V_VT(&arg
[0]) = VT_I4
; V_I4(&arg
[0]) = STATE_WIDGETIFIED
;
2007 hr
= IDispatch_Invoke(disp
, DISPID_TM_BASETYPES_IN
, &IID_NULL
, LOCALE_NEUTRAL
,
2008 DISPATCH_METHOD
, &dispparams
, NULL
, NULL
, NULL
);
2009 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
2011 hr
= IWidget_basetypes_in(widget
, 5, -123, -100000, (LONGLONG
)-100000 * 1000000, 0, 456,
2012 0xdeadbeef, (ULONGLONG
)1234567890 * 9876543210, M_PI
, M_E
, STATE_WIDGETIFIED
);
2013 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
2015 c
= s
= i
= h
= uc
= us
= ui
= uh
= f
= d
= st
= 0;
2017 V_VT(&arg
[10]) = VT_BYREF
|VT_I1
; V_I1REF(&arg
[10]) = &c
;
2018 V_VT(&arg
[9]) = VT_BYREF
|VT_I2
; V_I2REF(&arg
[9]) = &s
;
2019 V_VT(&arg
[8]) = VT_BYREF
|VT_I4
; V_I4REF(&arg
[8]) = &i
;
2020 V_VT(&arg
[7]) = VT_BYREF
|VT_I8
; V_I8REF(&arg
[7]) = &h
;
2021 V_VT(&arg
[6]) = VT_BYREF
|VT_UI1
; V_UI1REF(&arg
[6]) = &uc
;
2022 V_VT(&arg
[5]) = VT_BYREF
|VT_UI2
; V_UI2REF(&arg
[5]) = &us
;
2023 V_VT(&arg
[4]) = VT_BYREF
|VT_UI4
; V_UI4REF(&arg
[4]) = &ui
;
2024 V_VT(&arg
[3]) = VT_BYREF
|VT_UI8
; V_UI8REF(&arg
[3]) = &uh
;
2025 V_VT(&arg
[2]) = VT_BYREF
|VT_R4
; V_R4REF(&arg
[2]) = &f
;
2026 V_VT(&arg
[1]) = VT_BYREF
|VT_R8
; V_R8REF(&arg
[1]) = &d
;
2027 V_VT(&arg
[0]) = VT_BYREF
|VT_I4
; V_I4REF(&arg
[0]) = (int *)&st
;
2028 hr
= IDispatch_Invoke(disp
, DISPID_TM_BASETYPES_OUT
, &IID_NULL
, LOCALE_NEUTRAL
,
2029 DISPATCH_METHOD
, &dispparams
, NULL
, NULL
, NULL
);
2030 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
2031 ok(c
== 10, "Got char %d.\n", c
);
2032 ok(s
== -321, "Got short %d.\n", s
);
2033 ok(i
== -200000, "Got int %d.\n", i
);
2034 ok(h
== (LONGLONG
)-200000 * 1000000L, "Got hyper %s.\n", wine_dbgstr_longlong(h
));
2035 ok(uc
== 254, "Got unsigned char %u.\n", uc
);
2036 ok(us
== 256, "Got unsigned short %u.\n", us
);
2037 ok(ui
== 0xf00dfade, "Got unsigned int %i.\n", ui
);
2038 ok(uh
== ((((ULONGLONG
)0xabcdef01) << 32) | (ULONGLONG
)0x23456789),
2039 "Got unsigned hyper %s.\n", wine_dbgstr_longlong(uh
));
2040 ok(f
== (float)M_LN2
, "Got float %f.\n", f
);
2041 ok(d
== M_LN10
, "Got double %f.\n", d
);
2042 ok(st
== STATE_UNWIDGETIFIED
, "Got state %u.\n", st
);
2044 c
= s
= i
= h
= uc
= us
= ui
= uh
= f
= d
= st
= 0;
2046 hr
= IWidget_basetypes_out(widget
, &c
, &s
, &i
, &h
, &uc
, &us
, &ui
, &uh
, &f
, &d
, &st
);
2047 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
2048 ok(c
== 10, "Got char %d.\n", c
);
2049 ok(s
== -321, "Got short %d.\n", s
);
2050 ok(i
== -200000, "Got int %d.\n", i
);
2051 ok(h
== (LONGLONG
)-200000 * 1000000L, "Got hyper %s.\n", wine_dbgstr_longlong(h
));
2052 ok(uc
== 254, "Got unsigned char %u.\n", uc
);
2053 ok(us
== 256, "Got unsigned short %u.\n", us
);
2054 ok(ui
== 0xf00dfade, "Got unsigned int %i.\n", ui
);
2055 ok(uh
== ((((ULONGLONG
)0xabcdef01) << 32) | (ULONGLONG
)0x23456789),
2056 "Got unsigned hyper %s.\n", wine_dbgstr_longlong(uh
));
2057 ok(f
== (float)M_LN2
, "Got float %f.\n", f
);
2058 ok(d
== M_LN10
, "Got double %f.\n", d
);
2059 ok(st
== STATE_UNWIDGETIFIED
, "Got state %u.\n", st
);
2061 /* Test marshalling of public typedefs. */
2066 hr
= IWidget_myint(widget
, 123, &i
, &pi
);
2067 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
2069 /* Test that different float ABIs are correctly handled. */
2071 hr
= IWidget_float_abi(widget
, 1.0f
, 2.0, 3, 4.0f
, 5.0);
2072 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
2075 static void test_marshal_pointer(IWidget
*widget
, IDispatch
*disp
)
2078 DISPPARAMS dispparams
= {arg
, NULL
, ARRAY_SIZE(arg
), 0};
2079 int in
, out
, in_out
, *in_ptr
, *out_ptr
, *in_out_ptr
;
2087 V_VT(&arg
[2]) = VT_BYREF
|VT_I4
; V_I4REF(&arg
[2]) = &in
;
2088 V_VT(&arg
[1]) = VT_BYREF
|VT_I4
; V_I4REF(&arg
[1]) = &out
;
2089 V_VT(&arg
[0]) = VT_BYREF
|VT_I4
; V_I4REF(&arg
[0]) = &in_out
;
2090 hr
= IDispatch_Invoke(disp
, DISPID_TM_INT_PTR
, &IID_NULL
, LOCALE_NEUTRAL
,
2091 DISPATCH_METHOD
, &dispparams
, NULL
, NULL
, NULL
);
2092 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
2093 ok(in
== 987, "Got [in] %d.\n", in
);
2094 ok(out
== 654, "Got [out] %d.\n", out
);
2095 ok(in_out
== 321, "Got [in, out] %d.\n", in_out
);
2102 hr
= IWidget_int_ptr(widget
, &in
, &out
, &in_out
);
2103 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
2104 ok(in
== 123, "Got [in] %d.\n", in
);
2105 ok(out
== 654, "Got [out] %d.\n", out
);
2106 ok(in_out
== 321, "Got [in, out] %d.\n", in_out
);
2109 hr
= IWidget_int_ptr(widget
, NULL
, &out
, &in_out
);
2110 ok(hr
== HRESULT_FROM_WIN32(RPC_X_NULL_REF_POINTER
), "Got hr %#x.\n", hr
);
2111 ok(!out
, "[out] parameter should have been cleared.\n");
2112 ok(in_out
== -1, "[in, out] parameter should not have been cleared.\n");
2115 hr
= IWidget_int_ptr(widget
, &in
, NULL
, &in_out
);
2116 ok(hr
== HRESULT_FROM_WIN32(RPC_X_NULL_REF_POINTER
), "Got hr %#x.\n", hr
);
2117 ok(in
== -1, "[in] parameter should not have been cleared.\n");
2118 ok(in_out
== -1, "[in, out] parameter should not have been cleared.\n");
2121 hr
= IWidget_int_ptr(widget
, &in
, &out
, NULL
);
2122 ok(hr
== HRESULT_FROM_WIN32(RPC_X_NULL_REF_POINTER
), "Got hr %#x.\n", hr
);
2123 ok(in
== -1, "[in] parameter should not have been cleared.\n");
2124 ok(!out
, "[out] parameter should have been cleared.\n");
2126 /* We can't test Invoke() with double pointers, as it is not possible to fit
2127 * more than one level of indirection into a VARIANTARG. */
2130 in_ptr
= out_ptr
= in_out_ptr
= NULL
;
2131 hr
= IWidget_int_ptr_ptr(widget
, &in_ptr
, &out_ptr
, &in_out_ptr
);
2132 ok(hr
== S_OK
, "Got hr %#x\n", hr
);
2133 ok(!in_ptr
, "Got [in] %p.\n", in_ptr
);
2134 ok(!out_ptr
, "Got [out] %p.\n", out_ptr
);
2135 ok(!in_out_ptr
, "Got [in, out] %p.\n", in_out_ptr
);
2138 hr
= IWidget_int_ptr_ptr(widget
, &in_ptr
, &out_ptr
, &in_out_ptr
);
2139 ok(hr
== S_OK
, "Got hr %#x\n", hr
);
2140 ok(*out_ptr
== 654, "Got [out] %d.\n", *out_ptr
);
2141 ok(*in_out_ptr
== 321, "Got [in, out] %d.\n", *in_out_ptr
);
2142 CoTaskMemFree(out_ptr
);
2143 CoTaskMemFree(in_out_ptr
);
2151 in_out_ptr
= &in_out
;
2152 hr
= IWidget_int_ptr_ptr(widget
, &in_ptr
, &out_ptr
, &in_out_ptr
);
2153 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
2154 ok(out_ptr
!= &out
, "[out] ptr should have changed.\n");
2155 ok(in_out_ptr
== &in_out
, "[in, out] ptr should not have changed.\n");
2156 ok(*out_ptr
== 654, "Got [out] %d.\n", *out_ptr
);
2157 ok(*in_out_ptr
== 321, "Got [in, out] %d.\n", *in_out_ptr
);
2160 in_ptr
= out_ptr
= NULL
;
2162 in_out_ptr
= &in_out
;
2163 hr
= IWidget_int_ptr_ptr(widget
, &in_ptr
, &out_ptr
, &in_out_ptr
);
2164 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
2165 ok(!in_out_ptr
, "Got [in, out] %p.\n", in_out_ptr
);
2168 in_out_ptr
= &in_out
;
2169 hr
= IWidget_int_ptr_ptr(widget
, NULL
, &out_ptr
, &in_out_ptr
);
2170 ok(hr
== HRESULT_FROM_WIN32(RPC_X_NULL_REF_POINTER
), "Got hr %#x.\n", hr
);
2171 ok(!out_ptr
, "[out] parameter should have been cleared.\n");
2172 ok(in_out_ptr
== &in_out
, "[in, out] parameter should not have been cleared.\n");
2175 in_out_ptr
= &in_out
;
2176 hr
= IWidget_int_ptr_ptr(widget
, &in_ptr
, NULL
, &in_out_ptr
);
2177 ok(hr
== HRESULT_FROM_WIN32(RPC_X_NULL_REF_POINTER
), "Got hr %#x.\n", hr
);
2178 ok(in_ptr
== &in
, "[in] parameter should not have been cleared.\n");
2179 ok(in_out_ptr
== &in_out
, "[in, out] parameter should not have been cleared.\n");
2183 hr
= IWidget_int_ptr_ptr(widget
, &in_ptr
, &out_ptr
, NULL
);
2184 ok(hr
== HRESULT_FROM_WIN32(RPC_X_NULL_REF_POINTER
), "Got hr %#x.\n", hr
);
2185 ok(in_ptr
== &in
, "[in] parameter should not have been cleared.\n");
2186 ok(!out_ptr
, "[out] parameter should have been cleared.\n");
2189 static void test_marshal_iface(IWidget
*widget
, IDispatch
*disp
)
2192 DISPPARAMS dispparams
= {arg
, NULL
, ARRAY_SIZE(arg
), 0};
2193 ISomethingFromDispatch
*sfd1
, *sfd2
, *sfd3
, *proxy_sfd
, *sfd_in
, *sfd_out
, *sfd_in_out
;
2194 IUnknown
*proxy_unk
, *proxy_unk2
, *unk_in
, *unk_out
, *unk_in_out
;
2195 IDispatch
*proxy_disp
;
2197 IDispatch disp_noptr
;
2198 ISomethingFromDispatch sfd_noptr
;
2202 sfd1
= create_disp_obj();
2203 sfd2
= create_disp_obj();
2204 sfd3
= create_disp_obj();
2205 hr
= IWidget_iface_in(widget
, (IUnknown
*)sfd1
,
2206 (IDispatch
*)sfd2
, sfd3
);
2207 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
2208 release_iface(sfd1
);
2209 release_iface(sfd2
);
2210 release_iface(sfd3
);
2213 hr
= IWidget_iface_in(widget
, NULL
, NULL
, NULL
);
2214 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
2217 proxy_unk
= (IUnknown
*)0xdeadbeef;
2218 proxy_disp
= (IDispatch
*)0xdeadbeef;
2219 proxy_sfd
= (ISomethingFromDispatch
*)0xdeadbeef;
2220 hr
= IWidget_iface_out(widget
, &proxy_unk
, &proxy_disp
, &proxy_sfd
);
2221 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
2222 check_iface_marshal(proxy_unk
, proxy_disp
, proxy_sfd
);
2223 release_iface(proxy_unk
);
2224 release_iface(proxy_disp
);
2225 release_iface(proxy_sfd
);
2228 hr
= IWidget_iface_out(widget
, &proxy_unk
, &proxy_disp
, &proxy_sfd
);
2229 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
2230 ok(!proxy_unk
, "Got unexpected proxy %p.\n", proxy_unk
);
2231 ok(!proxy_disp
, "Got unexpected proxy %p.\n", proxy_disp
);
2232 ok(!proxy_sfd
, "Got unexpected proxy %p.\n", proxy_sfd
);
2235 sfd_in
= sfd1
= create_disp_obj();
2236 sfd_out
= sfd2
= create_disp_obj();
2237 sfd_in_out
= sfd3
= create_disp_obj();
2238 hr
= IWidget_iface_ptr(widget
, &sfd_in
, &sfd_out
, &sfd_in_out
);
2239 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
2240 ok(sfd_in
== sfd1
, "[in] parameter should not have changed.\n");
2241 ok(!sfd_out
, "[out] parameter should have been cleared.\n");
2242 ok(sfd_in_out
== sfd3
, "[in, out] parameter should not have changed.\n");
2243 release_iface(sfd1
);
2244 release_iface(sfd2
);
2245 release_iface(sfd3
);
2248 sfd_in
= sfd1
= create_disp_obj();
2249 sfd_in_out
= sfd3
= create_disp_obj();
2250 ISomethingFromDispatch_AddRef(sfd_in_out
);
2251 hr
= IWidget_iface_ptr(widget
, &sfd_in
, &sfd_out
, &sfd_in_out
);
2252 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
2253 hr
= ISomethingFromDispatch_anotherfn(sfd_out
);
2254 ok(hr
== 0x01234567, "Got hr %#x.\n", hr
);
2255 ok(sfd_in_out
!= sfd3
, "[in, out] parameter should have changed.\n");
2256 hr
= ISomethingFromDispatch_anotherfn(sfd_in_out
);
2257 ok(hr
== 0x01234567, "Got hr %#x.\n", hr
);
2258 release_iface(sfd_out
);
2259 release_iface(sfd_in_out
);
2260 release_iface(sfd1
);
2261 release_iface(sfd3
);
2264 sfd_in
= sfd_out
= sfd_in_out
= NULL
;
2265 hr
= IWidget_iface_ptr(widget
, &sfd_in
, &sfd_out
, &sfd_in_out
);
2266 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
2267 ok(!sfd_out
, "[out] parameter should not have been set.\n");
2268 hr
= ISomethingFromDispatch_anotherfn(sfd_in_out
);
2269 ok(hr
== 0x01234567, "Got hr %#x.\n", hr
);
2270 release_iface(sfd_in_out
);
2273 sfd_in
= sfd_out
= NULL
;
2274 sfd_in_out
= sfd3
= create_disp_obj();
2275 ISomethingFromDispatch_AddRef(sfd_in_out
);
2276 hr
= IWidget_iface_ptr(widget
, &sfd_in
, &sfd_out
, &sfd_in_out
);
2277 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
2278 ok(!sfd_in_out
, "Got [in, out] %p.\n", sfd_in_out
);
2279 release_iface(sfd3
);
2281 sfd1
= create_disp_obj();
2282 sfd2
= create_disp_obj();
2283 sfd3
= create_disp_obj();
2284 unk_noptr
.lpVtbl
= (IUnknownVtbl
*)sfd1
;
2285 disp_noptr
.lpVtbl
= (IDispatchVtbl
*)sfd2
;
2286 sfd_noptr
.lpVtbl
= (ISomethingFromDispatchVtbl
*)sfd3
;
2287 hr
= IWidget_iface_noptr(widget
, unk_noptr
, disp_noptr
, sfd_noptr
);
2288 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
2289 release_iface(sfd1
);
2290 release_iface(sfd2
);
2291 release_iface(sfd3
);
2293 /* Test with Invoke(). Note that since we pass VT_UNKNOWN, we don't get our
2294 * interface back, but rather an IUnknown. */
2297 sfd1
= create_disp_obj();
2298 sfd2
= create_disp_obj();
2299 sfd3
= create_disp_obj();
2301 V_VT(&arg
[2]) = VT_UNKNOWN
; V_UNKNOWN(&arg
[2]) = (IUnknown
*)sfd1
;
2302 V_VT(&arg
[1]) = VT_UNKNOWN
; V_UNKNOWN(&arg
[1]) = (IUnknown
*)sfd2
;
2303 V_VT(&arg
[0]) = VT_UNKNOWN
; V_UNKNOWN(&arg
[0]) = (IUnknown
*)sfd3
;
2304 hr
= IDispatch_Invoke(disp
, DISPID_TM_IFACE_IN
, &IID_NULL
, LOCALE_NEUTRAL
,
2305 DISPATCH_METHOD
, &dispparams
, NULL
, NULL
, NULL
);
2306 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
2308 V_VT(&arg
[2]) = VT_DISPATCH
; V_DISPATCH(&arg
[2]) = (IDispatch
*)sfd1
;
2309 V_VT(&arg
[1]) = VT_DISPATCH
; V_DISPATCH(&arg
[1]) = (IDispatch
*)sfd2
;
2310 V_VT(&arg
[0]) = VT_DISPATCH
; V_DISPATCH(&arg
[0]) = (IDispatch
*)sfd3
;
2311 hr
= IDispatch_Invoke(disp
, DISPID_TM_IFACE_IN
, &IID_NULL
, LOCALE_NEUTRAL
,
2312 DISPATCH_METHOD
, &dispparams
, NULL
, NULL
, NULL
);
2313 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
2315 release_iface(sfd1
);
2316 release_iface(sfd2
);
2317 release_iface(sfd3
);
2320 V_VT(&arg
[2]) = VT_UNKNOWN
; V_UNKNOWN(&arg
[2]) = NULL
;
2321 V_VT(&arg
[1]) = VT_UNKNOWN
; V_UNKNOWN(&arg
[1]) = NULL
;
2322 V_VT(&arg
[0]) = VT_UNKNOWN
; V_UNKNOWN(&arg
[0]) = NULL
;
2323 hr
= IDispatch_Invoke(disp
, DISPID_TM_IFACE_IN
, &IID_NULL
, LOCALE_NEUTRAL
,
2324 DISPATCH_METHOD
, &dispparams
, NULL
, NULL
, NULL
);
2325 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
2328 proxy_unk
= proxy_unk2
= NULL
;
2330 V_VT(&arg
[2]) = VT_UNKNOWN
|VT_BYREF
; V_UNKNOWNREF(&arg
[2]) = &proxy_unk
;
2331 V_VT(&arg
[1]) = VT_DISPATCH
|VT_BYREF
; V_DISPATCHREF(&arg
[1]) = &proxy_disp
;
2332 V_VT(&arg
[0]) = VT_UNKNOWN
|VT_BYREF
; V_UNKNOWNREF(&arg
[0]) = &proxy_unk2
;
2333 hr
= IDispatch_Invoke(disp
, DISPID_TM_IFACE_OUT
, &IID_NULL
, LOCALE_NEUTRAL
,
2334 DISPATCH_METHOD
, &dispparams
, NULL
, NULL
, NULL
);
2336 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
2338 hr
= IUnknown_QueryInterface(proxy_unk2
, &IID_ISomethingFromDispatch
, (void **)&proxy_sfd
);
2339 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
2340 check_iface_marshal(proxy_unk
, proxy_disp
, proxy_sfd
);
2341 ISomethingFromDispatch_Release(proxy_sfd
);
2342 release_iface(proxy_unk
);
2343 release_iface(proxy_disp
);
2344 release_iface(proxy_unk2
);
2348 proxy_unk
= proxy_unk2
= NULL
;
2350 hr
= IDispatch_Invoke(disp
, DISPID_TM_IFACE_OUT
, &IID_NULL
, LOCALE_NEUTRAL
,
2351 DISPATCH_METHOD
, &dispparams
, NULL
, NULL
, NULL
);
2353 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
2354 ok(!proxy_unk
, "Got unexpected proxy %p.\n", proxy_unk
);
2355 ok(!proxy_disp
, "Got unexpected proxy %p.\n", proxy_disp
);
2356 ok(!proxy_unk2
, "Got unexpected proxy %p.\n", proxy_unk2
);
2359 sfd1
= create_disp_obj();
2360 sfd3
= create_disp_obj();
2361 unk_in
= (IUnknown
*)sfd1
;
2363 unk_in_out
= (IUnknown
*)sfd3
;
2364 V_VT(&arg
[2]) = VT_UNKNOWN
|VT_BYREF
; V_UNKNOWNREF(&arg
[2]) = &unk_in
;
2365 V_VT(&arg
[1]) = VT_UNKNOWN
|VT_BYREF
; V_UNKNOWNREF(&arg
[1]) = &unk_out
;
2366 V_VT(&arg
[0]) = VT_UNKNOWN
|VT_BYREF
; V_UNKNOWNREF(&arg
[0]) = &unk_in_out
;
2367 hr
= IDispatch_Invoke(disp
, DISPID_TM_IFACE_PTR
, &IID_NULL
, LOCALE_NEUTRAL
,
2368 DISPATCH_METHOD
, &dispparams
, NULL
, NULL
, NULL
);
2370 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
2371 ok(unk_in
== (IUnknown
*)sfd1
, "[in] parameter should not have changed.\n");
2372 ok(!unk_out
, "[out] parameter should have been cleared.\n");
2373 ok(unk_in_out
== (IUnknown
*)sfd3
, "[in, out] parameter should not have changed.\n");
2374 release_iface(sfd1
);
2375 release_iface(sfd3
);
2378 sfd1
= create_disp_obj();
2379 sfd3
= create_disp_obj();
2380 unk_in
= (IUnknown
*)sfd1
;
2382 unk_in_out
= (IUnknown
*)sfd3
;
2383 IUnknown_AddRef(unk_in_out
);
2384 hr
= IDispatch_Invoke(disp
, DISPID_TM_IFACE_PTR
, &IID_NULL
, LOCALE_NEUTRAL
,
2385 DISPATCH_METHOD
, &dispparams
, NULL
, NULL
, NULL
);
2387 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
2390 hr
= IUnknown_QueryInterface(unk_out
, &IID_ISomethingFromDispatch
, (void **)&sfd_out
);
2391 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
2392 hr
= ISomethingFromDispatch_anotherfn(sfd_out
);
2393 ok(hr
== 0x01234567, "Got hr %#x.\n", hr
);
2394 ISomethingFromDispatch_Release(sfd_out
);
2396 ok(unk_in_out
!= (IUnknown
*)sfd3
, "[in, out] parameter should have changed.\n");
2397 hr
= IUnknown_QueryInterface(unk_in_out
, &IID_ISomethingFromDispatch
, (void **)&sfd_in_out
);
2398 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
2399 hr
= ISomethingFromDispatch_anotherfn(sfd_in_out
);
2400 ok(hr
== 0x01234567, "Got hr %#x.\n", hr
);
2401 ISomethingFromDispatch_Release(sfd_in_out
);
2403 release_iface(unk_out
);
2404 release_iface(unk_in_out
);
2406 release_iface(sfd1
);
2408 release_iface(sfd3
);
2411 unk_in
= unk_out
= unk_in_out
= NULL
;
2412 hr
= IDispatch_Invoke(disp
, DISPID_TM_IFACE_PTR
, &IID_NULL
, LOCALE_NEUTRAL
,
2413 DISPATCH_METHOD
, &dispparams
, NULL
, NULL
, NULL
);
2415 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
2417 ok(!unk_out
, "[out] parameter should not have been set.\n");
2419 hr
= IUnknown_QueryInterface(unk_in_out
, &IID_ISomethingFromDispatch
, (void **)&sfd_in_out
);
2420 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
2421 hr
= ISomethingFromDispatch_anotherfn(sfd_in_out
);
2422 ok(hr
== 0x01234567, "Got hr %#x.\n", hr
);
2423 ISomethingFromDispatch_Release(sfd_in_out
);
2425 release_iface(unk_in_out
);
2429 unk_in
= unk_out
= NULL
;
2430 sfd3
= create_disp_obj();
2431 unk_in_out
= (IUnknown
*)sfd3
;
2432 IUnknown_AddRef(unk_in_out
);
2433 hr
= IDispatch_Invoke(disp
, DISPID_TM_IFACE_PTR
, &IID_NULL
, LOCALE_NEUTRAL
,
2434 DISPATCH_METHOD
, &dispparams
, NULL
, NULL
, NULL
);
2436 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
2437 ok(!unk_in_out
, "[in, out] parameter should have been cleared.\n");
2438 release_iface(sfd3
);
2442 static void test_marshal_bstr(IWidget
*widget
, IDispatch
*disp
)
2445 DISPPARAMS dispparams
= {arg
, NULL
, ARRAY_SIZE(arg
), 0};
2446 BSTR in
, out
, in_ptr
, in_out
;
2451 in
= SysAllocStringLen(test_bstr1
, ARRAY_SIZE(test_bstr1
));
2453 in_ptr
= SysAllocString(test_bstr2
);
2454 in_out
= SysAllocString(test_bstr3
);
2456 V_VT(&arg
[3]) = VT_BSTR
; V_BSTR(&arg
[3]) = in
;
2457 V_VT(&arg
[2]) = VT_BSTR
|VT_BYREF
; V_BSTRREF(&arg
[2]) = &out
;
2458 V_VT(&arg
[1]) = VT_BSTR
|VT_BYREF
; V_BSTRREF(&arg
[1]) = &in_ptr
;
2459 V_VT(&arg
[0]) = VT_BSTR
|VT_BYREF
; V_BSTRREF(&arg
[0]) = &in_out
;
2460 hr
= IDispatch_Invoke(disp
, DISPID_TM_BSTR
, &IID_NULL
, LOCALE_NEUTRAL
,
2461 DISPATCH_METHOD
, &dispparams
, NULL
, NULL
, NULL
);
2462 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
2463 ok(in
[1] == test_bstr1
[1], "[in] parameter should not be changed.\n");
2464 ok(in_ptr
[1] == 'X', "[in] pointer should be changed.\n");
2465 ok(in_out
[1] == 'X', "[in, out] parameter should be changed.\n");
2466 len
= SysStringLen(out
);
2467 ok(len
== lstrlenW(test_bstr4
), "Got wrong length %d.\n", len
);
2468 ok(!memcmp(out
, test_bstr4
, len
), "Got string %s.\n", wine_dbgstr_wn(out
, len
));
2470 in
[1] = test_bstr1
[1];
2471 in_ptr
[1] = test_bstr2
[1];
2472 in_out
[1] = test_bstr3
[1];
2474 out
= (BSTR
)0xdeadbeef;
2475 hr
= IWidget_bstr(widget
, in
, &out
, &in_ptr
, &in_out
);
2476 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
2477 ok(in
[1] == test_bstr1
[1], "[in] parameter should not be changed.\n");
2478 ok(in_ptr
[1] == test_bstr2
[1], "[in] pointer should not be changed.\n");
2479 ok(in_out
[1] == 'X', "[in, out] parameter should be changed.\n");
2480 len
= SysStringLen(out
);
2481 ok(len
== lstrlenW(test_bstr4
), "Got wrong length %d.\n", len
);
2482 ok(!memcmp(out
, test_bstr4
, len
), "Got string %s.\n", wine_dbgstr_wn(out
, len
));
2485 SysFreeString(in_ptr
);
2486 SysFreeString(in_out
);
2489 out
= in_ptr
= in_out
= NULL
;
2490 hr
= IWidget_bstr(widget
, NULL
, &out
, &in_ptr
, &in_out
);
2491 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
2493 in
= SysAllocString(L
"test");
2494 hr
= IWidget_no_in_out(widget
, in
, 5);
2495 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
2498 static void test_marshal_variant(IWidget
*widget
, IDispatch
*disp
)
2501 DISPPARAMS dispparams
= {arg
, NULL
, ARRAY_SIZE(arg
), 0};
2502 VARIANT out
, in_ptr
, in_out
;
2509 V_VT(&in_ptr
) = VT_I4
;
2511 V_VT(&in_out
) = VT_BSTR
;
2512 V_BSTR(&in_out
) = bstr
= SysAllocString(test_bstr2
);
2514 V_VT(&arg
[3]) = VT_CY
;
2515 V_CY(&arg
[3]).Hi
= 0xdababe;
2516 V_CY(&arg
[3]).Lo
= 0xdeadbeef;
2517 V_VT(&arg
[2]) = VT_VARIANT
|VT_BYREF
; V_VARIANTREF(&arg
[2]) = &out
;
2518 V_VT(&arg
[1]) = VT_VARIANT
|VT_BYREF
; V_VARIANTREF(&arg
[1]) = &in_ptr
;
2519 V_VT(&arg
[0]) = VT_VARIANT
|VT_BYREF
; V_VARIANTREF(&arg
[0]) = &in_out
;
2520 hr
= IDispatch_Invoke(disp
, DISPID_TM_VARIANT
, &IID_NULL
, LOCALE_NEUTRAL
,
2521 DISPATCH_METHOD
, &dispparams
, NULL
, NULL
, NULL
);
2522 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
2523 ok(V_VT(&arg
[3]) == VT_CY
, "Got wrong type %u.\n", V_VT(&arg
[3]));
2524 ok(V_VT(&out
) == VT_UI1
, "Got wrong type %u.\n", V_VT(&out
));
2525 ok(V_UI1(&out
) == 3, "Got wrong value %d.\n", V_UI1(&out
));
2527 ok(V_VT(&in_ptr
) == VT_I2
, "Got wrong type %u.\n", V_VT(&in_ptr
));
2528 ok(V_I2(&in_ptr
) == 4, "Got wrong value %d.\n", V_I1(&in_ptr
));
2529 ok(V_VT(&in_out
) == VT_I1
, "Got wrong type %u.\n", V_VT(&in_out
));
2530 ok(V_I1(&in_out
) == 5, "Got wrong value %d.\n", V_I1(&in_out
));
2535 V_VT(&in_ptr
) = VT_I4
;
2537 V_VT(&in_out
) = VT_BSTR
;
2538 V_BSTR(&in_out
) = bstr
= SysAllocString(test_bstr2
);
2539 hr
= IWidget_variant(widget
, arg
[3], &out
, &in_ptr
, &in_out
);
2540 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
2541 ok(V_VT(&arg
[3]) == VT_CY
, "Got wrong type %u.\n", V_VT(&arg
[3]));
2542 ok(V_VT(&out
) == VT_UI1
, "Got wrong type %u.\n", V_VT(&out
));
2543 ok(V_UI1(&out
) == 3, "Got wrong value %d.\n", V_UI1(&out
));
2544 ok(V_VT(&in_ptr
) == VT_I4
, "Got wrong type %u.\n", V_VT(&in_ptr
));
2545 ok(V_I2(&in_ptr
) == -1, "Got wrong value %d.\n", V_I1(&in_ptr
));
2546 ok(V_VT(&in_out
) == VT_I1
, "Got wrong type %u.\n", V_VT(&in_out
));
2547 ok(V_I1(&in_out
) == 5, "Got wrong value %d.\n", V_I1(&in_out
));
2550 static void test_marshal_safearray(IWidget
*widget
, IDispatch
*disp
)
2552 SAFEARRAY
*in
, *out
, *out2
, *in_ptr
, *in_out
;
2555 in
= make_safearray(3);
2556 out
= out2
= make_safearray(5);
2557 in_ptr
= make_safearray(7);
2558 in_out
= make_safearray(9);
2559 hr
= IWidget_safearray(widget
, in
, &out
, &in_ptr
, &in_out
);
2560 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
2561 check_safearray(in
, 3);
2562 check_safearray(out
, 4);
2563 check_safearray(out2
, 5);
2564 check_safearray(in_ptr
, 7);
2565 check_safearray(in_out
, 6);
2567 SafeArrayDestroy(in
);
2568 SafeArrayDestroy(out
);
2569 SafeArrayDestroy(out2
);
2570 SafeArrayDestroy(in_ptr
);
2571 SafeArrayDestroy(in_out
);
2574 static void test_marshal_struct(IWidget
*widget
, IDispatch
*disp
)
2576 MYSTRUCT out
, in_ptr
, in_out
, *in_ptr_ptr
;
2577 RECT rect_out
, rect_in_ptr
, rect_in_out
;
2578 ISomethingFromDispatch
*sfd
;
2579 struct complex complex;
2580 int i
, i2
, *pi
= &i2
;
2583 memcpy(&out
, &test_mystruct2
, sizeof(MYSTRUCT
));
2584 memcpy(&in_ptr
, &test_mystruct3
, sizeof(MYSTRUCT
));
2585 memcpy(&in_out
, &test_mystruct4
, sizeof(MYSTRUCT
));
2586 hr
= IWidget_mystruct(widget
, test_mystruct1
, &out
, &in_ptr
, &in_out
);
2587 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
2588 ok(!memcmp(&out
, &test_mystruct5
, sizeof(MYSTRUCT
)), "Structs didn't match.\n");
2589 ok(!memcmp(&in_ptr
, &test_mystruct3
, sizeof(MYSTRUCT
)), "Structs didn't match.\n");
2590 ok(!memcmp(&in_out
, &test_mystruct7
, sizeof(MYSTRUCT
)), "Structs didn't match.\n");
2592 memcpy(&in_ptr
, &test_mystruct1
, sizeof(MYSTRUCT
));
2593 in_ptr_ptr
= &in_ptr
;
2594 hr
= IWidget_mystruct_ptr_ptr(widget
, &in_ptr_ptr
);
2595 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
2597 /* Make sure that "thin" structs (<=8 bytes) are handled correctly in x86-64. */
2599 hr
= IWidget_thin_struct(widget
, test_thin_struct
);
2600 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
2602 /* Make sure we can handle an imported type. */
2604 rect_out
= test_rect2
;
2605 rect_in_ptr
= test_rect3
;
2606 rect_in_out
= test_rect4
;
2607 hr
= IWidget_rect(widget
, test_rect1
, &rect_out
, &rect_in_ptr
, &rect_in_out
);
2608 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
2609 ok(EqualRect(&rect_out
, &test_rect5
), "Rects didn't match.\n");
2610 ok(EqualRect(&rect_in_ptr
, &test_rect3
), "Rects didn't match.\n");
2611 ok(EqualRect(&rect_in_out
, &test_rect7
), "Rects didn't match.\n");
2613 /* Test complex structs. */
2620 complex.iface
= create_disp_obj();
2621 sfd
= create_disp_obj();
2622 complex.iface_ptr
= &sfd
;
2623 complex.bstr
= SysAllocString(test_bstr2
);
2624 V_VT(&complex.var
) = VT_I4
;
2625 V_I4(&complex.var
) = 123;
2626 memcpy(&complex.mystruct
, &test_mystruct1
, sizeof(MYSTRUCT
));
2627 memcpy(complex.arr
, test_array1
, sizeof(array_t
));
2628 complex.myint
= 456;
2629 hr
= IWidget_complex_struct(widget
, complex);
2630 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
2633 static void test_marshal_array(IWidget
*widget
, IDispatch
*disp
)
2635 VARIANT var_in
[2], var_out
[2], var_in_out
[2];
2636 ISomethingFromDispatch
*proxy_sfd
;
2637 array_t in
, out
, in_out
;
2638 MYSTRUCT struct_in
[2];
2642 memcpy(in
, test_array1
, sizeof(array_t
));
2643 memcpy(out
, test_array2
, sizeof(array_t
));
2644 memcpy(in_out
, test_array3
, sizeof(array_t
));
2645 hr
= IWidget_array(widget
, in
, out
, in_out
);
2646 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
2647 ok(!memcmp(&in
, &test_array1
, sizeof(array_t
)), "Arrays didn't match.\n");
2648 ok(!memcmp(&out
, &test_array5
, sizeof(array_t
)), "Arrays didn't match.\n");
2649 ok(!memcmp(&in_out
, &test_array6
, sizeof(array_t
)), "Arrays didn't match.\n");
2651 V_VT(&var_in
[0]) = VT_I4
; V_I4(&var_in
[0]) = 1;
2652 V_VT(&var_in
[1]) = VT_BYREF
|VT_I4
; V_I4REF(&var_in
[1]) = &i
;
2653 V_VT(&var_out
[0]) = VT_I4
; V_I4(&var_out
[0]) = 3;
2654 V_VT(&var_out
[1]) = VT_I4
; V_I4(&var_out
[1]) = 4;
2655 V_VT(&var_in_out
[0]) = VT_I4
; V_I4(&var_in_out
[0]) = 5;
2656 V_VT(&var_in_out
[1]) = VT_BSTR
; V_BSTR(&var_in_out
[1]) = SysAllocString(test_bstr1
);
2657 hr
= IWidget_variant_array(widget
, var_in
, var_out
, var_in_out
);
2658 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
2659 ok(V_VT(&var_in
[0]) == VT_I4
, "Got wrong type %u.\n", V_VT(&var_in
[0]));
2660 ok(V_I4(&var_in
[0]) == 1, "Got wrong value %d.\n", V_I4(&var_in
[0]));
2661 ok(V_VT(&var_in
[1]) == (VT_BYREF
|VT_I4
), "Got wrong type %u.\n", V_VT(&var_in
[1]));
2662 ok(V_I4REF(&var_in
[1]) == &i
, "Got wrong value %p.\n", V_I4REF(&var_in
[1]));
2663 ok(i
== 2, "Got wrong value %d.\n", i
);
2664 ok(V_VT(&var_out
[0]) == VT_I1
, "Got wrong type %u.\n", V_VT(&var_out
[0]));
2665 ok(V_I1(&var_out
[0]) == 9, "Got wrong value %u.\n", V_VT(&var_out
[0]));
2666 ok(V_VT(&var_out
[1]) == VT_BSTR
, "Got wrong type %u.\n", V_VT(&var_out
[1]));
2667 ok(!lstrcmpW(V_BSTR(&var_out
[1]), test_bstr2
), "Got wrong value %s.\n", wine_dbgstr_w(V_BSTR(&var_out
[1])));
2668 ok(V_VT(&var_in_out
[0]) == VT_I1
, "Got wrong type %u.\n", V_VT(&var_in_out
[0]));
2669 ok(V_I1(&var_in_out
[0]) == 11, "Got wrong value %u.\n", V_VT(&var_in_out
[0]));
2670 ok(V_VT(&var_in_out
[1]) == VT_UNKNOWN
, "Got wrong type %u.\n", V_VT(&var_in_out
[1]));
2671 hr
= IUnknown_QueryInterface(V_UNKNOWN(&var_in_out
[1]), &IID_ISomethingFromDispatch
, (void **)&proxy_sfd
);
2672 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
2673 hr
= ISomethingFromDispatch_anotherfn(proxy_sfd
);
2674 ok(hr
== 0x01234567, "Got hr %#x.\n", hr
);
2675 ISomethingFromDispatch_Release(proxy_sfd
);
2676 release_iface(V_UNKNOWN(&var_in_out
[1]));
2678 memcpy(&struct_in
[0], &test_mystruct1
, sizeof(MYSTRUCT
));
2679 memcpy(&struct_in
[1], &test_mystruct2
, sizeof(MYSTRUCT
));
2680 hr
= IWidget_mystruct_array(widget
, struct_in
);
2681 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
2684 static void test_marshal_coclass(IWidget
*widget
, IDispatch
*disp
)
2687 DISPPARAMS dispparams
= {arg
, NULL
, ARRAY_SIZE(arg
), 0};
2688 struct coclass_obj
*class1
, *class2
, *class3
;
2689 IUnknown
*unk_in
, *unk_out
, *unk_in_out
;
2690 ICoclass1
*in
, *out
, *in_out
;
2691 Coclass1 class1_noptr
;
2692 Coclass2 class2_noptr
;
2693 Coclass3 class3_noptr
;
2696 class1
= create_coclass_obj();
2697 class2
= create_coclass_obj();
2698 class3
= create_coclass_obj();
2700 hr
= IWidget_Coclass(widget
, (Coclass1
*)&class1
->ICoclass1_iface
,
2701 (Coclass2
*)&class2
->ICoclass1_iface
, (Coclass3
*)&class3
->ICoclass1_iface
);
2702 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
2704 hr
= IWidget_Coclass(widget
, (Coclass1
*)&class1
->ICoclass2_iface
,
2705 (Coclass2
*)&class2
->ICoclass2_iface
, (Coclass3
*)&class3
->ICoclass2_iface
);
2706 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
2708 release_iface(&class1
->ICoclass1_iface
);
2709 release_iface(&class2
->ICoclass1_iface
);
2710 release_iface(&class3
->ICoclass1_iface
);
2713 class1
= create_coclass_obj();
2714 class2
= create_coclass_obj();
2715 class3
= create_coclass_obj();
2716 in
= &class1
->ICoclass1_iface
;
2717 out
= &class2
->ICoclass1_iface
;
2718 in_out
= &class3
->ICoclass1_iface
;
2719 hr
= IWidget_Coclass_ptr(widget
, (Coclass1
**)&in
, (Coclass1
**)&out
, (Coclass1
**)&in_out
);
2720 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
2721 ok(in
== &class1
->ICoclass1_iface
, "[in] parameter should not have changed.\n");
2722 ok(!out
, "[out] parameter should have been cleared.\n");
2723 ok(in_out
== &class3
->ICoclass1_iface
, "[in, out] parameter should not have changed.\n");
2724 release_iface(&class1
->ICoclass1_iface
);
2725 release_iface(&class2
->ICoclass1_iface
);
2726 release_iface(&class3
->ICoclass1_iface
);
2729 class1
= create_coclass_obj();
2730 class3
= create_coclass_obj();
2731 in
= &class1
->ICoclass1_iface
;
2732 in_out
= &class3
->ICoclass1_iface
;
2733 ICoclass1_AddRef(in_out
);
2734 hr
= IWidget_Coclass_ptr(widget
, (Coclass1
**)&in
,
2735 (Coclass1
**)&out
, (Coclass1
**)&in_out
);
2736 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
2737 hr
= ICoclass1_test(out
);
2738 ok(hr
== 1, "Got hr %#x.\n", hr
);
2739 ok(in_out
!= &class3
->ICoclass1_iface
, "[in, out] parameter should have changed.\n");
2740 hr
= ICoclass1_test(in_out
);
2741 ok(hr
== 1, "Got hr %#x.\n", hr
);
2743 release_iface(in_out
);
2744 release_iface(&class1
->ICoclass1_iface
);
2745 release_iface(&class3
->ICoclass1_iface
);
2748 in
= out
= in_out
= NULL
;
2749 hr
= IWidget_Coclass_ptr(widget
, (Coclass1
**)&in
,
2750 (Coclass1
**)&out
, (Coclass1
**)&in_out
);
2751 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
2752 hr
= ICoclass1_test(in_out
);
2753 ok(hr
== 1, "Got hr %#x.\n", hr
);
2754 release_iface(in_out
);
2758 class3
= create_coclass_obj();
2759 in_out
= &class3
->ICoclass1_iface
;
2760 hr
= IWidget_Coclass_ptr(widget
, (Coclass1
**)&in
,
2761 (Coclass1
**)&out
, (Coclass1
**)&in_out
);
2762 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
2763 ok(!in_out
, "Got [in, out] %p.\n", in_out
);
2765 class1
= create_coclass_obj();
2766 class2
= create_coclass_obj();
2767 class3
= create_coclass_obj();
2768 class1_noptr
.iface
= &class1
->ICoclass1_iface
;
2769 class2_noptr
.iface
= &class2
->ICoclass2_iface
;
2770 class3_noptr
.iface
= &class3
->ICoclass1_iface
;
2771 hr
= IWidget_Coclass_noptr(widget
, class1_noptr
, class2_noptr
, class3_noptr
);
2772 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
2773 release_iface(&class1
->ICoclass1_iface
);
2774 release_iface(&class2
->ICoclass1_iface
);
2775 release_iface(&class3
->ICoclass1_iface
);
2777 /* Test with Invoke(). Note that since we pass VT_UNKNOWN, we don't get our
2778 * interface back, but rather an IUnknown. */
2780 class1
= create_coclass_obj();
2781 class2
= create_coclass_obj();
2782 class3
= create_coclass_obj();
2784 V_VT(&arg
[2]) = VT_UNKNOWN
; V_UNKNOWN(&arg
[2]) = (IUnknown
*)&class1
->ICoclass1_iface
;
2785 V_VT(&arg
[1]) = VT_UNKNOWN
; V_UNKNOWN(&arg
[1]) = (IUnknown
*)&class2
->ICoclass1_iface
;
2786 V_VT(&arg
[0]) = VT_UNKNOWN
; V_UNKNOWN(&arg
[0]) = (IUnknown
*)&class3
->ICoclass1_iface
;
2787 hr
= IDispatch_Invoke(disp
, DISPID_TM_COCLASS
, &IID_NULL
, LOCALE_NEUTRAL
,
2788 DISPATCH_METHOD
, &dispparams
, NULL
, NULL
, NULL
);
2789 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
2791 V_VT(&arg
[2]) = VT_UNKNOWN
; V_UNKNOWN(&arg
[2]) = (IUnknown
*)&class1
->ICoclass2_iface
;
2792 V_VT(&arg
[1]) = VT_UNKNOWN
; V_UNKNOWN(&arg
[1]) = (IUnknown
*)&class2
->ICoclass2_iface
;
2793 V_VT(&arg
[0]) = VT_UNKNOWN
; V_UNKNOWN(&arg
[0]) = (IUnknown
*)&class3
->ICoclass2_iface
;
2794 hr
= IDispatch_Invoke(disp
, DISPID_TM_COCLASS
, &IID_NULL
, LOCALE_NEUTRAL
,
2795 DISPATCH_METHOD
, &dispparams
, NULL
, NULL
, NULL
);
2796 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
2798 V_VT(&arg
[2]) = VT_DISPATCH
; V_DISPATCH(&arg
[2]) = (IDispatch
*)&class1
->ICoclass1_iface
;
2799 V_VT(&arg
[1]) = VT_DISPATCH
; V_DISPATCH(&arg
[1]) = (IDispatch
*)&class2
->ICoclass1_iface
;
2800 V_VT(&arg
[0]) = VT_DISPATCH
; V_DISPATCH(&arg
[0]) = (IDispatch
*)&class3
->ICoclass1_iface
;
2801 hr
= IDispatch_Invoke(disp
, DISPID_TM_COCLASS
, &IID_NULL
, LOCALE_NEUTRAL
,
2802 DISPATCH_METHOD
, &dispparams
, NULL
, NULL
, NULL
);
2803 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
2805 release_iface(&class1
->ICoclass1_iface
);
2806 release_iface(&class2
->ICoclass1_iface
);
2807 release_iface(&class3
->ICoclass1_iface
);
2810 class1
= create_coclass_obj();
2811 class3
= create_coclass_obj();
2812 unk_in
= (IUnknown
*)&class1
->ICoclass1_iface
;
2814 unk_in_out
= (IUnknown
*)&class3
->ICoclass1_iface
;
2815 V_VT(&arg
[2]) = VT_UNKNOWN
|VT_BYREF
; V_UNKNOWNREF(&arg
[2]) = &unk_in
;
2816 V_VT(&arg
[1]) = VT_UNKNOWN
|VT_BYREF
; V_UNKNOWNREF(&arg
[1]) = &unk_out
;
2817 V_VT(&arg
[0]) = VT_UNKNOWN
|VT_BYREF
; V_UNKNOWNREF(&arg
[0]) = &unk_in_out
;
2818 hr
= IDispatch_Invoke(disp
, DISPID_TM_COCLASS_PTR
, &IID_NULL
, LOCALE_NEUTRAL
,
2819 DISPATCH_METHOD
, &dispparams
, NULL
, NULL
, NULL
);
2821 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
2822 ok(unk_in
== (IUnknown
*)&class1
->ICoclass1_iface
, "[in] parameter should not have changed.\n");
2823 ok(!unk_out
, "[out] parameter should have been cleared.\n");
2824 ok(unk_in_out
== (IUnknown
*)&class3
->ICoclass1_iface
, "[in, out] parameter should not have changed.\n");
2825 release_iface(&class1
->ICoclass1_iface
);
2826 release_iface(&class3
->ICoclass1_iface
);
2829 class1
= create_coclass_obj();
2830 class3
= create_coclass_obj();
2831 unk_in
= (IUnknown
*)&class1
->ICoclass1_iface
;
2833 unk_in_out
= (IUnknown
*)&class3
->ICoclass1_iface
;
2834 IUnknown_AddRef(unk_in_out
);
2835 hr
= IDispatch_Invoke(disp
, DISPID_TM_COCLASS_PTR
, &IID_NULL
, LOCALE_NEUTRAL
,
2836 DISPATCH_METHOD
, &dispparams
, NULL
, NULL
, NULL
);
2838 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
2841 hr
= IUnknown_QueryInterface(unk_out
, &IID_ICoclass1
, (void **)&out
);
2842 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
2843 hr
= ICoclass1_test(out
);
2844 ok(hr
== 1, "Got hr %#x.\n", hr
);
2845 ICoclass1_Release(out
);
2847 ok(unk_in_out
!= (IUnknown
*)&class3
->ICoclass1_iface
, "[in, out] parameter should have changed.\n");
2848 hr
= IUnknown_QueryInterface(unk_in_out
, &IID_ICoclass1
, (void **)&in_out
);
2849 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
2850 hr
= ICoclass1_test(in_out
);
2851 ok(hr
== 1, "Got hr %#x.\n", hr
);
2852 ICoclass1_Release(in_out
);
2854 release_iface(unk_out
);
2855 release_iface(unk_in_out
);
2857 release_iface(&class1
->ICoclass1_iface
);
2859 release_iface(&class3
->ICoclass1_iface
);
2862 unk_in
= unk_out
= unk_in_out
= NULL
;
2863 hr
= IDispatch_Invoke(disp
, DISPID_TM_COCLASS_PTR
, &IID_NULL
, LOCALE_NEUTRAL
,
2864 DISPATCH_METHOD
, &dispparams
, NULL
, NULL
, NULL
);
2866 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
2868 ok(!unk_out
, "[out] parameter should not have been set.\n");
2870 hr
= IUnknown_QueryInterface(unk_in_out
, &IID_ICoclass1
, (void **)&in_out
);
2871 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
2872 hr
= ICoclass1_test(in_out
);
2873 ok(hr
== 1, "Got hr %#x.\n", hr
);
2874 ICoclass1_Release(in_out
);
2876 release_iface(unk_in_out
);
2880 unk_in
= unk_out
= NULL
;
2881 class3
= create_coclass_obj();
2882 unk_in_out
= (IUnknown
*)&class3
->ICoclass1_iface
;
2883 IUnknown_AddRef(unk_in_out
);
2884 hr
= IDispatch_Invoke(disp
, DISPID_TM_COCLASS_PTR
, &IID_NULL
, LOCALE_NEUTRAL
,
2885 DISPATCH_METHOD
, &dispparams
, NULL
, NULL
, NULL
);
2887 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
2889 ok(!unk_in_out
, "[in, out] parameter should have been cleared.\n");
2892 release_iface(&class3
->ICoclass1_iface
);
2895 static void test_typelibmarshal(void)
2897 static const WCHAR szCat
[] = { 'C','a','t',0 };
2898 static const WCHAR szTestTest
[] = { 'T','e','s','t','T','e','s','t',0 };
2899 static const WCHAR szSuperman
[] = { 'S','u','p','e','r','m','a','n',0 };
2901 IKindaEnumWidget
*pKEW
= KindaEnumWidget_Create();
2904 IDispatch
*pDispatch
;
2905 static const LARGE_INTEGER ullZero
;
2906 EXCEPINFO excepinfo
;
2908 DISPID dispidNamed
= DISPID_PROPERTYPUT
;
2909 DISPPARAMS dispparams
;
2910 VARIANTARG vararg
[4];
2915 ITypeInfo
*pTypeInfo
;
2918 ok(pKEW
!= NULL
, "Widget creation failed\n");
2920 hr
= CreateStreamOnHGlobal(NULL
, TRUE
, &pStream
);
2921 ok_ole_success(hr
, CreateStreamOnHGlobal
);
2922 tid
= start_host_object(pStream
, &IID_IKindaEnumWidget
, (IUnknown
*)pKEW
, MSHLFLAGS_NORMAL
, &thread
);
2923 IKindaEnumWidget_Release(pKEW
);
2925 IStream_Seek(pStream
, ullZero
, STREAM_SEEK_SET
, NULL
);
2926 hr
= CoUnmarshalInterface(pStream
, &IID_IKindaEnumWidget
, (void **)&pKEW
);
2927 ok_ole_success(hr
, CoUnmarshalInterface
);
2928 IStream_Release(pStream
);
2931 end_host_object(tid
, thread
);
2935 hr
= IKindaEnumWidget_Next(pKEW
, &pWidget
);
2936 ok_ole_success(hr
, IKindaEnumWidget_Next
);
2938 IKindaEnumWidget_Release(pKEW
);
2940 /* call GetTypeInfoCount (direct) */
2941 hr
= IWidget_GetTypeInfoCount(pWidget
, &uval
);
2942 ok_ole_success(hr
, IWidget_GetTypeInfoCount
);
2943 hr
= IWidget_GetTypeInfoCount(pWidget
, &uval
);
2944 ok_ole_success(hr
, IWidget_GetTypeInfoCount
);
2946 hr
= IWidget_QueryInterface(pWidget
, &IID_IDispatch
, (void **)&pDispatch
);
2947 ok_ole_success(hr
, IWidget_QueryInterface
);
2950 VariantInit(&vararg
[0]);
2951 dispparams
.cNamedArgs
= 1;
2952 dispparams
.rgdispidNamedArgs
= &dispidNamed
;
2953 dispparams
.cArgs
= 1;
2954 dispparams
.rgvarg
= vararg
;
2955 VariantInit(&varresult
);
2956 hr
= IDispatch_Invoke(pDispatch
, DISPID_TM_NAME
, &IID_NULL
, LOCALE_NEUTRAL
, DISPATCH_PROPERTYPUT
, &dispparams
, &varresult
, &excepinfo
, NULL
);
2957 ok_ole_success(hr
, IDispatch_Invoke
);
2958 ok(excepinfo
.wCode
== 0x0 && excepinfo
.scode
== S_OK
,
2959 "EXCEPINFO differs from expected: wCode = 0x%x, scode = 0x%08x\n",
2960 excepinfo
.wCode
, excepinfo
.scode
);
2961 VariantClear(&varresult
);
2963 /* call put_Name (direct) */
2964 bstr
= SysAllocString(szSuperman
);
2965 hr
= IWidget_put_Name(pWidget
, bstr
);
2966 ok_ole_success(hr
, IWidget_put_Name
);
2967 SysFreeString(bstr
);
2970 dispparams
.cNamedArgs
= 0;
2971 dispparams
.rgdispidNamedArgs
= NULL
;
2972 dispparams
.cArgs
= 0;
2973 dispparams
.rgvarg
= NULL
;
2974 VariantInit(&varresult
);
2975 hr
= IDispatch_Invoke(pDispatch
, DISPID_TM_NAME
, &IID_NULL
, LOCALE_NEUTRAL
, DISPATCH_PROPERTYGET
, &dispparams
, &varresult
, &excepinfo
, NULL
);
2976 ok_ole_success(hr
, IDispatch_Invoke
);
2977 ok(excepinfo
.wCode
== 0x0 && excepinfo
.scode
== S_OK
,
2978 "EXCEPINFO differs from expected: wCode = 0x%x, scode = 0x%08x\n",
2979 excepinfo
.wCode
, excepinfo
.scode
);
2980 trace("Name = %s\n", wine_dbgstr_w(V_BSTR(&varresult
)));
2981 VariantClear(&varresult
);
2983 /* call get_Name (direct) */
2984 bstr
= (void *)0xdeadbeef;
2985 hr
= IWidget_get_Name(pWidget
, &bstr
);
2986 ok_ole_success(hr
, IWidget_get_Name
);
2987 ok(!lstrcmpW(bstr
, szCat
), "IWidget_get_Name should have returned string \"Cat\" instead of %s\n", wine_dbgstr_w(bstr
));
2988 SysFreeString(bstr
);
2990 /* call DoSomething without optional arguments */
2991 VariantInit(&vararg
[0]);
2992 VariantInit(&vararg
[1]);
2993 V_VT(&vararg
[1]) = VT_R8
;
2994 V_R8(&vararg
[1]) = 3.141;
2995 dispparams
.cNamedArgs
= 0;
2996 dispparams
.cArgs
= 2;
2997 dispparams
.rgdispidNamedArgs
= NULL
;
2998 dispparams
.rgvarg
= vararg
;
2999 VariantInit(&varresult
);
3000 hr
= IDispatch_Invoke(pDispatch
, DISPID_TM_DOSOMETHING
, &IID_NULL
, LOCALE_NEUTRAL
, DISPATCH_METHOD
, &dispparams
, &varresult
, &excepinfo
, NULL
);
3001 ok_ole_success(hr
, IDispatch_Invoke
);
3002 ok(V_VT(&varresult
) == VT_EMPTY
, "varresult should be VT_EMPTY\n");
3003 VariantClear(&varresult
);
3005 /* call DoSomething with optional argument set to VT_EMPTY */
3006 VariantInit(&vararg
[0]);
3007 VariantInit(&vararg
[1]);
3008 VariantInit(&vararg
[2]);
3009 V_VT(&vararg
[2]) = VT_R8
;
3010 V_R8(&vararg
[2]) = 3.141;
3011 dispparams
.cNamedArgs
= 0;
3012 dispparams
.cArgs
= 3;
3013 dispparams
.rgdispidNamedArgs
= NULL
;
3014 dispparams
.rgvarg
= vararg
;
3015 VariantInit(&varresult
);
3016 hr
= IDispatch_Invoke(pDispatch
, DISPID_TM_DOSOMETHING
, &IID_NULL
, LOCALE_NEUTRAL
, DISPATCH_METHOD
, &dispparams
, &varresult
, &excepinfo
, NULL
);
3017 ok_ole_success(hr
, IDispatch_Invoke
);
3018 ok(V_VT(&varresult
) == VT_EMPTY
, "varresult should be VT_EMPTY\n");
3019 VariantClear(&varresult
);
3021 /* call DoSomething with optional arguments set to VT_ERROR/DISP_E_PARAMNOTFOUND */
3022 VariantInit(&vararg
[0]);
3023 VariantInit(&vararg
[1]);
3024 VariantInit(&vararg
[2]);
3025 VariantInit(&vararg
[3]);
3026 V_VT(&vararg
[3]) = VT_R8
;
3027 V_R8(&vararg
[3]) = 3.141;
3028 V_VT(&vararg
[1]) = VT_ERROR
;
3029 V_ERROR(&vararg
[1]) = DISP_E_PARAMNOTFOUND
;
3030 V_VT(&vararg
[0]) = VT_ERROR
;
3031 V_ERROR(&vararg
[0]) = DISP_E_PARAMNOTFOUND
;
3032 dispparams
.cNamedArgs
= 0;
3033 dispparams
.cArgs
= 4;
3034 dispparams
.rgdispidNamedArgs
= NULL
;
3035 dispparams
.rgvarg
= vararg
;
3036 VariantInit(&varresult
);
3037 hr
= IDispatch_Invoke(pDispatch
, DISPID_TM_DOSOMETHING
, &IID_NULL
, LOCALE_NEUTRAL
, DISPATCH_METHOD
, &dispparams
, &varresult
, &excepinfo
, NULL
);
3038 ok_ole_success(hr
, IDispatch_Invoke
);
3039 ok(V_VT(&varresult
) == VT_EMPTY
, "varresult should be VT_EMPTY\n");
3040 VariantClear(&varresult
);
3042 /* call get_State */
3043 dispparams
.cNamedArgs
= 0;
3044 dispparams
.cArgs
= 0;
3045 dispparams
.rgdispidNamedArgs
= NULL
;
3046 dispparams
.rgvarg
= NULL
;
3047 hr
= IDispatch_Invoke(pDispatch
, DISPID_TM_STATE
, &IID_NULL
, LOCALE_NEUTRAL
, DISPATCH_PROPERTYGET
, &dispparams
, &varresult
, &excepinfo
, NULL
);
3048 ok_ole_success(hr
, IDispatch_Invoke
);
3049 ok((V_VT(&varresult
) == VT_I4
) && (V_I4(&varresult
) == STATE_WIDGETIFIED
), "Return val mismatch\n");
3051 /* call get_State (direct) */
3052 hr
= IWidget_get_State(pWidget
, &the_state
);
3053 ok_ole_success(hr
, IWidget_get_state
);
3054 ok(the_state
== STATE_WIDGETIFIED
, "should have returned WIDGET_WIDGETIFIED instead of %d\n", the_state
);
3056 /* call put_State */
3057 the_state
= STATE_WIDGETIFIED
;
3058 VariantInit(&vararg
[0]);
3059 V_VT(&vararg
[0]) = VT_BYREF
|VT_I4
;
3060 V_I4REF(&vararg
[0]) = (int *)&the_state
;
3061 dispparams
.cNamedArgs
= 1;
3062 dispparams
.cArgs
= 1;
3063 dispparams
.rgdispidNamedArgs
= &dispidNamed
;
3064 dispparams
.rgvarg
= vararg
;
3065 hr
= IDispatch_Invoke(pDispatch
, DISPID_TM_STATE
, &IID_NULL
, LOCALE_NEUTRAL
, DISPATCH_PROPERTYPUT
, &dispparams
, &varresult
, &excepinfo
, NULL
);
3066 ok_ole_success(hr
, IDispatch_Invoke
);
3069 bstr
= SysAllocString(szTestTest
);
3070 VariantInit(&vararg
[0]);
3071 V_VT(&vararg
[0]) = VT_BYREF
|VT_BSTR
;
3072 V_BSTRREF(&vararg
[0]) = &bstr
;
3073 dispparams
.cNamedArgs
= 0;
3074 dispparams
.cArgs
= 1;
3075 dispparams
.rgdispidNamedArgs
= NULL
;
3076 dispparams
.rgvarg
= vararg
;
3077 VariantInit(&varresult
);
3078 hr
= IDispatch_Invoke(pDispatch
, DISPID_TM_MAP
, &IID_NULL
, LOCALE_NEUTRAL
, DISPATCH_METHOD
, &dispparams
, &varresult
, &excepinfo
, NULL
);
3079 ok_ole_success(hr
, IDispatch_Invoke
);
3080 ok(V_VT(&varresult
) == VT_BSTR
, "Return value should be of type BSTR instead of %d\n", V_VT(&varresult
));
3081 ok(!lstrcmpW(V_BSTR(&varresult
), szTestTest
), "Return value should have been \"TestTest\" instead of %s\n", wine_dbgstr_w(V_BSTR(&varresult
)));
3082 VariantClear(&varresult
);
3083 SysFreeString(bstr
);
3085 /* call SetOleColor with large negative VT_I4 param */
3086 VariantInit(&vararg
[0]);
3087 V_VT(&vararg
[0]) = VT_I4
;
3088 V_I4(&vararg
[0]) = 0x80000005;
3089 dispparams
.cNamedArgs
= 0;
3090 dispparams
.cArgs
= 1;
3091 dispparams
.rgdispidNamedArgs
= NULL
;
3092 dispparams
.rgvarg
= vararg
;
3093 hr
= IDispatch_Invoke(pDispatch
, DISPID_TM_SETOLECOLOR
, &IID_NULL
, LOCALE_NEUTRAL
, DISPATCH_METHOD
, &dispparams
, NULL
, &excepinfo
, NULL
);
3094 ok_ole_success(hr
, IDispatch_Invoke
);
3096 /* call GetOleColor */
3097 dispparams
.cNamedArgs
= 0;
3098 dispparams
.cArgs
= 0;
3099 dispparams
.rgdispidNamedArgs
= NULL
;
3100 dispparams
.rgvarg
= NULL
;
3101 VariantInit(&varresult
);
3102 hr
= IDispatch_Invoke(pDispatch
, DISPID_TM_GETOLECOLOR
, &IID_NULL
, LOCALE_NEUTRAL
, DISPATCH_METHOD
, &dispparams
, &varresult
, &excepinfo
, NULL
);
3103 ok_ole_success(hr
, IDispatch_Invoke
);
3104 VariantClear(&varresult
);
3107 dispparams
.cNamedArgs
= 0;
3108 dispparams
.cArgs
= 0;
3109 dispparams
.rgdispidNamedArgs
= NULL
;
3110 dispparams
.rgvarg
= NULL
;
3111 VariantInit(&varresult
);
3112 hr
= IDispatch_Invoke(pDispatch
, DISPID_TM_CLONE
, &IID_NULL
, LOCALE_NEUTRAL
, DISPATCH_PROPERTYGET
, &dispparams
, &varresult
, &excepinfo
, NULL
);
3113 ok_ole_success(hr
, IDispatch_Invoke
);
3114 ok(V_VT(&varresult
) == VT_DISPATCH
, "vt %x\n", V_VT(&varresult
));
3115 VariantClear(&varresult
);
3117 /* call CloneInterface */
3118 dispparams
.cNamedArgs
= 0;
3119 dispparams
.cArgs
= 0;
3120 dispparams
.rgdispidNamedArgs
= NULL
;
3121 dispparams
.rgvarg
= NULL
;
3122 VariantInit(&varresult
);
3123 hr
= IDispatch_Invoke(pDispatch
, DISPID_TM_CLONEINTERFACE
, &IID_NULL
, LOCALE_NEUTRAL
, DISPATCH_PROPERTYGET
, &dispparams
, &varresult
, &excepinfo
, NULL
);
3124 ok_ole_success(hr
, IDispatch_Invoke
);
3125 ok(V_VT(&varresult
) == VT_DISPATCH
, "vt %x\n", V_VT(&varresult
));
3126 VariantClear(&varresult
);
3128 /* call CloneDispatch with automatic value getting */
3129 V_VT(&vararg
[0]) = VT_I2
;
3130 V_I2(&vararg
[0]) = 1;
3131 dispparams
.cNamedArgs
= 0;
3132 dispparams
.rgdispidNamedArgs
= NULL
;
3133 dispparams
.cArgs
= 1;
3134 dispparams
.rgvarg
= vararg
;
3135 VariantInit(&varresult
);
3136 hr
= IDispatch_Invoke(pDispatch
, DISPID_TM_CLONEDISPATCH
, &IID_NULL
, LOCALE_NEUTRAL
, DISPATCH_PROPERTYGET
, &dispparams
, &varresult
, &excepinfo
, NULL
);
3137 ok_ole_success(hr
, IDispatch_Invoke
);
3139 ok(excepinfo
.wCode
== 0x0 && excepinfo
.scode
== S_OK
,
3140 "EXCEPINFO differs from expected: wCode = 0x%x, scode = 0x%08x\n",
3141 excepinfo
.wCode
, excepinfo
.scode
);
3143 ok(V_VT(&varresult
) == VT_I2
, "V_VT(&varresult) was %d instead of VT_I2\n", V_VT(&varresult
));
3144 ok(V_I2(&varresult
) == 1234, "V_I2(&varresult) was %d instead of 1234\n", V_I2(&varresult
));
3145 VariantClear(&varresult
);
3147 /* call CloneCoclass */
3148 dispparams
.cNamedArgs
= 0;
3149 dispparams
.cArgs
= 0;
3150 dispparams
.rgdispidNamedArgs
= NULL
;
3151 dispparams
.rgvarg
= NULL
;
3152 VariantInit(&varresult
);
3153 hr
= IDispatch_Invoke(pDispatch
, DISPID_TM_CLONECOCLASS
, &IID_NULL
, LOCALE_NEUTRAL
, DISPATCH_PROPERTYGET
, &dispparams
, &varresult
, &excepinfo
, NULL
);
3154 ok_ole_success(hr
, IDispatch_Invoke
);
3156 ok(excepinfo
.wCode
== 0x0 && excepinfo
.scode
== S_OK
,
3157 "EXCEPINFO differs from expected: wCode = 0x%x, scode = 0x%08x\n",
3158 excepinfo
.wCode
, excepinfo
.scode
);
3160 ok(V_VT(&varresult
) == VT_DISPATCH
, "V_VT(&varresult) was %d instead of VT_DISPATCH\n", V_VT(&varresult
));
3161 ok(V_DISPATCH(&varresult
) != NULL
, "expected V_DISPATCH(&varresult) != NULL\n");
3163 /* call Value with a VT_VARIANT|VT_BYREF type */
3164 V_VT(&vararg
[0]) = VT_VARIANT
|VT_BYREF
;
3165 V_VARIANTREF(&vararg
[0]) = &vararg
[1];
3166 V_VT(&vararg
[1]) = VT_I2
;
3167 V_I2(&vararg
[1]) = 1;
3168 dispparams
.cNamedArgs
= 0;
3169 dispparams
.rgdispidNamedArgs
= NULL
;
3170 dispparams
.cArgs
= 1;
3171 dispparams
.rgvarg
= vararg
;
3172 VariantInit(&varresult
);
3173 hr
= IDispatch_Invoke(pDispatch
, DISPID_VALUE
, &IID_NULL
, LOCALE_NEUTRAL
, DISPATCH_PROPERTYGET
, &dispparams
, &varresult
, &excepinfo
, NULL
);
3174 ok_ole_success(hr
, IDispatch_Invoke
);
3176 ok(excepinfo
.wCode
== 0x0 && excepinfo
.scode
== S_OK
,
3177 "EXCEPINFO differs from expected: wCode = 0x%x, scode = 0x%08x\n",
3178 excepinfo
.wCode
, excepinfo
.scode
);
3180 ok(V_VT(&varresult
) == VT_I2
, "V_VT(&varresult) was %d instead of VT_I2\n", V_VT(&varresult
));
3181 ok(V_I2(&varresult
) == 1234, "V_I2(&varresult) was %d instead of 1234\n", V_I2(&varresult
));
3182 VariantClear(&varresult
);
3184 /* call Array with BSTR argument - type mismatch */
3185 VariantInit(&vararg
[0]);
3186 V_VT(&vararg
[0]) = VT_BSTR
;
3187 V_BSTR(&vararg
[0]) = SysAllocString(szSuperman
);
3188 dispparams
.cNamedArgs
= 0;
3189 dispparams
.cArgs
= 1;
3190 dispparams
.rgdispidNamedArgs
= NULL
;
3191 dispparams
.rgvarg
= vararg
;
3192 hr
= IDispatch_Invoke(pDispatch
, DISPID_TM_ARRAY
, &IID_NULL
, LOCALE_NEUTRAL
, DISPATCH_METHOD
, &dispparams
, NULL
, NULL
, NULL
);
3193 ok(hr
== DISP_E_TYPEMISMATCH
|| hr
== DISP_E_BADVARTYPE
, "expected DISP_E_TYPEMISMATCH, got %#x\n", hr
);
3194 SysFreeString(V_BSTR(&vararg
[0]));
3196 /* call ArrayPtr with BSTR argument - type mismatch */
3197 VariantInit(&vararg
[0]);
3198 V_VT(&vararg
[0]) = VT_BSTR
;
3199 V_BSTR(&vararg
[0]) = SysAllocString(szSuperman
);
3200 dispparams
.cNamedArgs
= 0;
3201 dispparams
.cArgs
= 1;
3202 dispparams
.rgdispidNamedArgs
= NULL
;
3203 dispparams
.rgvarg
= vararg
;
3204 hr
= IDispatch_Invoke(pDispatch
, DISPID_TM_VARARRAYPTR
, &IID_NULL
, LOCALE_NEUTRAL
, DISPATCH_METHOD
, &dispparams
, NULL
, NULL
, NULL
);
3205 ok(hr
== DISP_E_TYPEMISMATCH
|| hr
== DISP_E_BADVARTYPE
, "expected DISP_E_TYPEMISMATCH, got %#x\n", hr
);
3206 SysFreeString(V_BSTR(&vararg
[0]));
3209 VariantInit(&vararg
[3]);
3210 V_VT(&vararg
[3]) = VT_I4
;
3211 V_I4(&vararg
[3]) = 3;
3212 VariantInit(&vararg
[2]);
3213 V_VT(&vararg
[2]) = VT_I4
;
3214 V_I4(&vararg
[2]) = 0;
3215 VariantInit(&vararg
[1]);
3216 V_VT(&vararg
[1]) = VT_I4
;
3217 V_I4(&vararg
[1]) = 1;
3218 VariantInit(&vararg
[0]);
3219 V_VT(&vararg
[0]) = VT_I4
;
3220 V_I4(&vararg
[0]) = 2;
3221 dispparams
.cNamedArgs
= 0;
3222 dispparams
.cArgs
= 4;
3223 dispparams
.rgdispidNamedArgs
= NULL
;
3224 dispparams
.rgvarg
= vararg
;
3225 hr
= IDispatch_Invoke(pDispatch
, DISPID_TM_VARARG
, &IID_NULL
, LOCALE_NEUTRAL
, DISPATCH_METHOD
, &dispparams
, NULL
, NULL
, NULL
);
3226 ok_ole_success(hr
, IDispatch_Invoke
);
3228 /* call VarArg, even one (non-optional, non-safearray) named argument is not allowed */
3230 dispparams
.cNamedArgs
= 1;
3231 dispparams
.rgdispidNamedArgs
= &dispidNamed
;
3232 hr
= IDispatch_Invoke(pDispatch
, DISPID_TM_VARARG
, &IID_NULL
, LOCALE_NEUTRAL
, DISPATCH_METHOD
, &dispparams
, NULL
, NULL
, NULL
);
3233 ok(hr
== DISP_E_NONAMEDARGS
, "IDispatch_Invoke should have returned DISP_E_NONAMEDARGS instead of 0x%08x\n", hr
);
3234 dispidNamed
= DISPID_PROPERTYPUT
;
3236 /* call VarArg_Run */
3237 VariantInit(&vararg
[1]);
3238 V_VT(&vararg
[1]) = VT_BSTR
;
3239 V_BSTR(&vararg
[1]) = SysAllocString(szCat
);
3240 VariantInit(&vararg
[0]);
3241 V_VT(&vararg
[0]) = VT_BSTR
;
3242 V_BSTR(&vararg
[0]) = SysAllocString(szSuperman
);
3243 dispparams
.cNamedArgs
= 0;
3244 dispparams
.cArgs
= 2;
3245 dispparams
.rgdispidNamedArgs
= NULL
;
3246 dispparams
.rgvarg
= vararg
;
3247 hr
= IDispatch_Invoke(pDispatch
, DISPID_TM_VARARG_RUN
, &IID_NULL
, LOCALE_NEUTRAL
, DISPATCH_METHOD
, &dispparams
, NULL
, NULL
, NULL
);
3248 ok_ole_success(hr
, IDispatch_Invoke
);
3249 SysFreeString(V_BSTR(&vararg
[1]));
3250 SysFreeString(V_BSTR(&vararg
[0]));
3252 /* call VarArg_Ref_Run */
3253 VariantInit(&vararg
[1]);
3254 V_VT(&vararg
[1]) = VT_BSTR
;
3255 V_BSTR(&vararg
[1]) = SysAllocString(szCat
);
3256 VariantInit(&vararg
[0]);
3257 V_VT(&vararg
[0]) = VT_BSTR
;
3258 V_BSTR(&vararg
[0]) = SysAllocString(szSuperman
);
3259 dispparams
.cNamedArgs
= 0;
3260 dispparams
.cArgs
= 2;
3261 dispparams
.rgdispidNamedArgs
= NULL
;
3262 dispparams
.rgvarg
= vararg
;
3263 hr
= IDispatch_Invoke(pDispatch
, DISPID_TM_VARARG_REF_RUN
, &IID_NULL
, LOCALE_NEUTRAL
, DISPATCH_METHOD
, &dispparams
, NULL
, NULL
, NULL
);
3264 ok_ole_success(hr
, IDispatch_Invoke
);
3265 SysFreeString(V_BSTR(&vararg
[1]));
3266 SysFreeString(V_BSTR(&vararg
[0]));
3269 dispparams
.cNamedArgs
= 0;
3270 dispparams
.cArgs
= 0;
3271 dispparams
.rgdispidNamedArgs
= NULL
;
3272 dispparams
.rgvarg
= NULL
;
3273 VariantInit(&varresult
);
3274 hr
= IDispatch_Invoke(pDispatch
, DISPID_TM_ERROR
, &IID_NULL
, LOCALE_NEUTRAL
, DISPATCH_METHOD
, &dispparams
, NULL
, &excepinfo
, NULL
);
3275 ok(hr
== DISP_E_EXCEPTION
, "IDispatch_Invoke should have returned DISP_E_EXCEPTION instead of 0x%08x\n", hr
);
3276 ok(excepinfo
.wCode
== 0x0 && excepinfo
.scode
== E_NOTIMPL
,
3277 "EXCEPINFO differs from expected: wCode = 0x%x, scode = 0x%08x\n",
3278 excepinfo
.wCode
, excepinfo
.scode
);
3279 VariantClear(&varresult
);
3282 pTypeInfo
= NonOleAutomation_GetTypeInfo();
3283 dispparams
.cNamedArgs
= 0;
3284 dispparams
.cArgs
= 0;
3285 dispparams
.rgdispidNamedArgs
= NULL
;
3286 dispparams
.rgvarg
= NULL
;
3287 VariantInit(&varresult
);
3288 hr
= ITypeInfo_Invoke(pTypeInfo
, &NonOleAutomation
, DISPID_NOA_BSTRRET
, DISPATCH_METHOD
, &dispparams
, &varresult
, &excepinfo
, NULL
);
3289 ok_ole_success(hr
, ITypeInfo_Invoke
);
3290 ok(V_VT(&varresult
) == VT_BSTR
, "V_VT(&varresult) should be VT_BSTR instead of %d\n", V_VT(&varresult
));
3291 ok(V_BSTR(&varresult
) != NULL
, "V_BSTR(&varresult) should not be NULL\n");
3293 VariantClear(&varresult
);
3295 dispparams
.cNamedArgs
= 0;
3296 dispparams
.cArgs
= 0;
3297 dispparams
.rgdispidNamedArgs
= NULL
;
3298 dispparams
.rgvarg
= NULL
;
3299 hr
= ITypeInfo_Invoke(pTypeInfo
, &NonOleAutomation
, DISPID_NOA_ERROR
, DISPATCH_METHOD
, &dispparams
, &varresult
, &excepinfo
, NULL
);
3300 ok(hr
== DISP_E_EXCEPTION
, "ITypeInfo_Invoke should have returned DISP_E_EXCEPTION instead of 0x%08x\n", hr
);
3301 ok(V_VT(&varresult
) == VT_EMPTY
, "V_VT(&varresult) should be VT_EMPTY instead of %d\n", V_VT(&varresult
));
3302 ok(excepinfo
.wCode
== 0x0 && excepinfo
.scode
== E_NOTIMPL
,
3303 "EXCEPINFO differs from expected: wCode = 0x%x, scode = 0x%08x\n",
3304 excepinfo
.wCode
, excepinfo
.scode
);
3305 VariantClear(&varresult
);
3307 ITypeInfo_Release(pTypeInfo
);
3309 /* tests call put_Name without named arg */
3310 VariantInit(&vararg
[0]);
3311 dispparams
.cNamedArgs
= 0;
3312 dispparams
.rgdispidNamedArgs
= NULL
;
3313 dispparams
.cArgs
= 1;
3314 dispparams
.rgvarg
= vararg
;
3315 VariantInit(&varresult
);
3316 hr
= IDispatch_Invoke(pDispatch
, DISPID_TM_NAME
, &IID_NULL
, LOCALE_NEUTRAL
, DISPATCH_PROPERTYPUT
, &dispparams
, &varresult
, &excepinfo
, NULL
);
3317 ok(hr
== DISP_E_PARAMNOTFOUND
, "IDispatch_Invoke should have returned DISP_E_PARAMNOTFOUND instead of 0x%08x\n", hr
);
3318 VariantClear(&varresult
);
3320 /* tests param type that cannot be coerced */
3321 VariantInit(&vararg
[0]);
3322 V_VT(&vararg
[0]) = VT_UNKNOWN
;
3323 V_UNKNOWN(&vararg
[0]) = NULL
;
3324 dispparams
.cNamedArgs
= 1;
3325 dispparams
.rgdispidNamedArgs
= &dispidNamed
;
3326 dispparams
.cArgs
= 1;
3327 dispparams
.rgvarg
= vararg
;
3328 VariantInit(&varresult
);
3329 hr
= IDispatch_Invoke(pDispatch
, DISPID_TM_NAME
, &IID_NULL
, LOCALE_NEUTRAL
, DISPATCH_PROPERTYPUT
, &dispparams
, &varresult
, &excepinfo
, NULL
);
3330 ok(hr
== DISP_E_TYPEMISMATCH
, "IDispatch_Invoke should have returned DISP_E_TYPEMISMATCH instead of 0x%08x\n", hr
);
3331 VariantClear(&varresult
);
3333 /* tests bad param type */
3334 VariantInit(&vararg
[0]);
3335 V_VT(&vararg
[0]) = VT_CLSID
;
3336 V_BYREF(&vararg
[0]) = NULL
;
3337 dispparams
.cNamedArgs
= 1;
3338 dispparams
.rgdispidNamedArgs
= &dispidNamed
;
3339 dispparams
.cArgs
= 1;
3340 dispparams
.rgvarg
= vararg
;
3341 VariantInit(&varresult
);
3342 hr
= IDispatch_Invoke(pDispatch
, DISPID_TM_NAME
, &IID_NULL
, LOCALE_NEUTRAL
, DISPATCH_PROPERTYPUT
, &dispparams
, &varresult
, &excepinfo
, NULL
);
3343 ok(hr
== DISP_E_BADVARTYPE
, "IDispatch_Invoke should have returned DISP_E_BADVARTYPE instead of 0x%08x\n", hr
);
3344 VariantClear(&varresult
);
3346 /* tests too small param count */
3347 dispparams
.cNamedArgs
= 0;
3348 dispparams
.rgdispidNamedArgs
= NULL
;
3349 dispparams
.cArgs
= 0;
3350 dispparams
.rgvarg
= NULL
;
3351 VariantInit(&varresult
);
3352 hr
= IDispatch_Invoke(pDispatch
, DISPID_TM_DOSOMETHING
, &IID_NULL
, LOCALE_NEUTRAL
, DISPATCH_METHOD
, &dispparams
, &varresult
, &excepinfo
, NULL
);
3353 ok(hr
== DISP_E_BADPARAMCOUNT
, "IDispatch_Invoke should have returned DISP_E_BADPARAMCOUNT instead of 0x%08x\n", hr
);
3354 VariantClear(&varresult
);
3356 /* tests propget function with large param count */
3357 VariantInit(&vararg
[0]);
3358 V_VT(&vararg
[0]) = VT_BSTR
;
3359 V_BSTR(&vararg
[0]) = NULL
;
3360 V_VT(&vararg
[1]) = VT_I4
;
3361 V_I4(&vararg
[1]) = 1;
3362 dispparams
.cNamedArgs
= 0;
3363 dispparams
.cArgs
= 2;
3364 dispparams
.rgdispidNamedArgs
= NULL
;
3365 dispparams
.rgvarg
= vararg
;
3366 hr
= IDispatch_Invoke(pDispatch
, DISPID_TM_STATE
, &IID_NULL
, LOCALE_NEUTRAL
, DISPATCH_PROPERTYGET
, &dispparams
, &varresult
, &excepinfo
, NULL
);
3367 ok(hr
== DISP_E_NOTACOLLECTION
, "IDispatch_Invoke should have returned DISP_E_NOTACOLLECTION instead of 0x%08x\n", hr
);
3369 /* test propput with lcid */
3371 /* the lcid passed to the function is the first lcid in the typelib header.
3372 Since we don't explicitly set an lcid in the idl, it'll default to US English. */
3373 VariantInit(&vararg
[0]);
3374 V_VT(&vararg
[0]) = VT_I4
;
3375 V_I4(&vararg
[0]) = 0xcafe;
3376 dispparams
.cNamedArgs
= 1;
3377 dispparams
.rgdispidNamedArgs
= &dispidNamed
;
3378 dispparams
.cArgs
= 1;
3379 dispparams
.rgvarg
= vararg
;
3380 VariantInit(&varresult
);
3381 hr
= IDispatch_Invoke(pDispatch
, DISPID_TM_PROP_WITH_LCID
, &IID_NULL
, 0x40c, DISPATCH_PROPERTYPUT
, &dispparams
, &varresult
, &excepinfo
, NULL
);
3382 ok_ole_success(hr
, ITypeInfo_Invoke
);
3383 VariantClear(&varresult
);
3385 /* test propget with lcid */
3386 dispparams
.cNamedArgs
= 0;
3387 dispparams
.cArgs
= 0;
3388 dispparams
.rgvarg
= NULL
;
3389 dispparams
.rgdispidNamedArgs
= NULL
;
3390 hr
= IDispatch_Invoke(pDispatch
, DISPID_TM_PROP_WITH_LCID
, &IID_NULL
, 0x40c, DISPATCH_PROPERTYGET
, &dispparams
, &varresult
, &excepinfo
, NULL
);
3391 ok_ole_success(hr
, ITypeInfo_Invoke
);
3392 ok(V_VT(&varresult
) == VT_I4
, "got %x\n", V_VT(&varresult
));
3393 ok(V_I4(&varresult
) == 0x409, "got %x\n", V_I4(&varresult
));
3394 VariantClear(&varresult
);
3396 /* test propget of INT value */
3397 dispparams
.cNamedArgs
= 0;
3398 dispparams
.cArgs
= 0;
3399 dispparams
.rgvarg
= NULL
;
3400 dispparams
.rgdispidNamedArgs
= NULL
;
3401 hr
= IDispatch_Invoke(pDispatch
, DISPID_TM_PROP_INT
, &IID_NULL
, 0x40c, DISPATCH_PROPERTYGET
, &dispparams
, &varresult
, &excepinfo
, NULL
);
3402 ok_ole_success(hr
, ITypeInfo_Invoke
);
3403 ok(V_VT(&varresult
) == VT_I4
, "got %x\n", V_VT(&varresult
));
3404 ok(V_I4(&varresult
) == -13, "got %x\n", V_I4(&varresult
));
3405 VariantClear(&varresult
);
3407 /* test propget of INT value */
3408 dispparams
.cNamedArgs
= 0;
3409 dispparams
.cArgs
= 0;
3410 dispparams
.rgvarg
= NULL
;
3411 dispparams
.rgdispidNamedArgs
= NULL
;
3412 hr
= IDispatch_Invoke(pDispatch
, DISPID_TM_PROP_UINT
, &IID_NULL
, 0x40c, DISPATCH_PROPERTYGET
, &dispparams
, &varresult
, &excepinfo
, NULL
);
3413 ok_ole_success(hr
, ITypeInfo_Invoke
);
3414 ok(V_VT(&varresult
) == VT_UI4
, "got %x\n", V_VT(&varresult
));
3415 ok(V_UI4(&varresult
) == 42, "got %x\n", V_UI4(&varresult
));
3416 VariantClear(&varresult
);
3418 /* test byref marshalling */
3420 VariantInit(&vararg
[0]);
3421 V_VT(&vararg
[0]) = VT_UI4
|VT_BYREF
;
3422 V_UI4REF(&vararg
[0]) = &uval
;
3423 dispparams
.cNamedArgs
= 0;
3424 dispparams
.cArgs
= 1;
3425 dispparams
.rgvarg
= vararg
;
3426 dispparams
.rgdispidNamedArgs
= NULL
;
3427 hr
= IDispatch_Invoke(pDispatch
, DISPID_TM_BYREF_UINT
, &IID_NULL
, LOCALE_NEUTRAL
, DISPATCH_METHOD
, &dispparams
, &varresult
, &excepinfo
, NULL
);
3428 ok_ole_success(hr
, ITypeInfo_Invoke
);
3429 ok(V_VT(&varresult
) == VT_EMPTY
, "varresult should be VT_EMPTY\n");
3430 ok(V_VT(&vararg
[0]) == (VT_UI4
|VT_BYREF
), "arg VT not unmarshalled correctly: %x\n", V_VT(&vararg
[0]));
3431 ok(V_UI4REF(&vararg
[0]) == &uval
, "Byref pointer not preserved: %p/%p\n", &uval
, V_UI4REF(&vararg
[0]));
3432 ok(*V_UI4REF(&vararg
[0]) == 42, "Expected 42 to be returned instead of %u\n", *V_UI4REF(&vararg
[0]));
3433 VariantClear(&varresult
);
3434 VariantClear(&vararg
[0]);
3436 /* test propput with optional argument. */
3437 VariantInit(&vararg
[0]);
3438 V_VT(&vararg
[0]) = VT_I4
;
3439 V_I4(&vararg
[0]) = 0xcafe;
3440 dispparams
.cNamedArgs
= 1;
3441 dispparams
.rgdispidNamedArgs
= &dispidNamed
;
3442 dispparams
.cArgs
= 1;
3443 dispparams
.rgvarg
= vararg
;
3444 VariantInit(&varresult
);
3445 hr
= IDispatch_Invoke(pDispatch
, DISPID_TM_PROP_OPT_ARG
, &IID_NULL
, 0x40c, DISPATCH_PROPERTYPUT
, &dispparams
, &varresult
, &excepinfo
, NULL
);
3446 ok_ole_success(hr
, ITypeInfo_Invoke
);
3447 VariantClear(&varresult
);
3449 /* test propput with required argument. */
3450 VariantInit(&vararg
[0]);
3451 VariantInit(&vararg
[1]);
3452 V_VT(&vararg
[0]) = VT_I4
;
3453 V_I4(&vararg
[0]) = 0x1234;
3454 V_VT(&vararg
[1]) = VT_I4
;
3455 V_I4(&vararg
[1]) = 0x5678;
3456 dispparams
.cNamedArgs
= 1;
3457 dispparams
.rgdispidNamedArgs
= &dispidNamed
;
3458 dispparams
.cArgs
= 2;
3459 dispparams
.rgvarg
= vararg
;
3460 VariantInit(&varresult
);
3461 hr
= IDispatch_Invoke(pDispatch
, DISPID_TM_PROP_REQ_ARG
, &IID_NULL
, 0x40c, DISPATCH_PROPERTYPUT
, &dispparams
, &varresult
, &excepinfo
, NULL
);
3462 ok_ole_success(hr
, ITypeInfo_Invoke
);
3463 VariantClear(&varresult
);
3465 /* restricted member */
3466 dispparams
.cNamedArgs
= 0;
3467 dispparams
.rgdispidNamedArgs
= NULL
;
3468 dispparams
.cArgs
= 0;
3469 dispparams
.rgvarg
= NULL
;
3470 VariantInit(&varresult
);
3471 hr
= IDispatch_Invoke(pDispatch
, DISPID_TM_RESTRICTED
, &IID_NULL
, 0x40c, DISPATCH_METHOD
, &dispparams
, &varresult
, &excepinfo
, NULL
);
3472 ok( hr
== DISP_E_MEMBERNOTFOUND
, "got %08x\n", hr
);
3473 VariantClear(&varresult
);
3475 /* restricted member with -ve memid (not restricted) */
3476 dispparams
.cNamedArgs
= 0;
3477 dispparams
.rgdispidNamedArgs
= NULL
;
3478 dispparams
.cArgs
= 0;
3479 dispparams
.rgvarg
= NULL
;
3480 VariantInit(&varresult
);
3481 hr
= IDispatch_Invoke(pDispatch
, DISPID_TM_NEG_RESTRICTED
, &IID_NULL
, 0x40c, DISPATCH_METHOD
, &dispparams
, &varresult
, &excepinfo
, NULL
);
3482 ok( hr
== S_OK
, "got %08x\n", hr
);
3483 ok(V_VT(&varresult
) == VT_I4
, "got %x\n", V_VT(&varresult
));
3484 ok(V_I4(&varresult
) == DISPID_TM_NEG_RESTRICTED
, "got %x\n", V_I4(&varresult
));
3485 VariantClear(&varresult
);
3487 test_marshal_basetypes(pWidget
, pDispatch
);
3488 test_marshal_pointer(pWidget
, pDispatch
);
3489 test_marshal_iface(pWidget
, pDispatch
);
3490 test_marshal_bstr(pWidget
, pDispatch
);
3491 test_marshal_variant(pWidget
, pDispatch
);
3492 test_marshal_safearray(pWidget
, pDispatch
);
3493 test_marshal_struct(pWidget
, pDispatch
);
3494 test_marshal_array(pWidget
, pDispatch
);
3495 test_marshal_coclass(pWidget
, pDispatch
);
3497 IDispatch_Release(pDispatch
);
3498 IWidget_Release(pWidget
);
3500 trace("calling end_host_object\n");
3501 end_host_object(tid
, thread
);
3504 static void test_DispCallFunc(void)
3506 static const WCHAR szEmpty
[] = { 0 };
3507 VARTYPE rgvt
[] = { VT_R8
, VT_BSTR
, VT_BSTR
, VT_VARIANT
|VT_BYREF
};
3508 VARIANTARG vararg
[4];
3510 VARIANTARG
*rgpvarg
[4] = { &vararg
[0], &vararg
[1], &vararg
[2], &vararg
[3] };
3511 VARIANTARG varresult
;
3513 IWidget
*pWidget
= Widget_Create();
3514 V_VT(&vararg
[0]) = VT_R8
;
3515 V_R8(&vararg
[0]) = 3.141;
3516 V_VT(&vararg
[1]) = VT_BSTR
;
3517 V_BSTRREF(&vararg
[1]) = CoTaskMemAlloc(sizeof(BSTR
));
3518 V_VT(&vararg
[2]) = VT_BSTR
;
3519 V_BSTR(&vararg
[2]) = SysAllocString(szEmpty
);
3520 V_VT(&vararg
[3]) = VT_VARIANT
|VT_BYREF
;
3521 V_VARIANTREF(&vararg
[3]) = &varref
;
3522 V_VT(&varref
) = VT_ERROR
;
3523 V_ERROR(&varref
) = DISP_E_PARAMNOTFOUND
;
3524 VariantInit(&varresult
);
3525 hr
= DispCallFunc(pWidget
, 9*sizeof(void*), CC_STDCALL
, VT_UI4
, 4, rgvt
, rgpvarg
, &varresult
);
3526 ok_ole_success(hr
, DispCallFunc
);
3527 VariantClear(&varresult
);
3528 SysFreeString(*V_BSTRREF(&vararg
[1]));
3529 CoTaskMemFree(V_BSTRREF(&vararg
[1]));
3530 VariantClear(&vararg
[2]);
3531 IWidget_Release(pWidget
);
3534 static void test_StaticWidget(void)
3536 ITypeInfo
*type_info
;
3537 DISPPARAMS dispparams
;
3538 VARIANTARG vararg
[4];
3539 EXCEPINFO excepinfo
;
3543 type_info
= get_type_info(&IID_IStaticWidget
);
3546 dispparams
.cNamedArgs
= 0;
3547 dispparams
.cArgs
= 1;
3548 dispparams
.rgdispidNamedArgs
= NULL
;
3549 dispparams
.rgvarg
= vararg
;
3550 V_VT(vararg
) = VT_DISPATCH
;
3551 V_DISPATCH(vararg
) = (IDispatch
*)&TestDualDisp
;
3552 VariantInit(&varresult
);
3553 hr
= ITypeInfo_Invoke(type_info
, &StaticWidget
, DISPID_TM_TESTDUAL
, DISPATCH_METHOD
,
3554 &dispparams
, &varresult
, &excepinfo
, NULL
);
3555 ok_ole_success(hr
, IDispatch_Invoke
);
3556 ok(V_VT(&varresult
) == VT_EMPTY
, "vt %x\n", V_VT(&varresult
));
3557 VariantClear(&varresult
);
3559 /* call TestSecondIface */
3560 dispparams
.cNamedArgs
= 0;
3561 dispparams
.cArgs
= 1;
3562 dispparams
.rgdispidNamedArgs
= NULL
;
3563 dispparams
.rgvarg
= vararg
;
3564 V_VT(vararg
) = VT_DISPATCH
;
3565 V_DISPATCH(vararg
) = (IDispatch
*)&TestDualDisp
;
3566 VariantInit(&varresult
);
3567 hr
= ITypeInfo_Invoke(type_info
, &StaticWidget
, DISPID_TM_TESTSECONDIFACE
, DISPATCH_METHOD
,
3568 &dispparams
, &varresult
, &excepinfo
, NULL
);
3569 ok_ole_success(hr
, IDispatch_Invoke
);
3570 ok(V_VT(&varresult
) == VT_EMPTY
, "vt %x\n", V_VT(&varresult
));
3571 VariantClear(&varresult
);
3573 ITypeInfo_Release(type_info
);
3576 static void test_libattr(void)
3582 hr
= LoadRegTypeLib(&LIBID_TestTypelib
, 2, 5, LOCALE_NEUTRAL
, &pTypeLib
);
3583 ok_ole_success(hr
, LoadRegTypeLib
);
3587 hr
= ITypeLib_GetLibAttr(pTypeLib
, &pattr
);
3588 ok_ole_success(hr
, GetLibAttr
);
3591 ok(pattr
->lcid
== MAKELANGID(LANG_NEUTRAL
, SUBLANG_NEUTRAL
), "lcid %x\n", pattr
->lcid
);
3593 ITypeLib_ReleaseTLibAttr(pTypeLib
, pattr
);
3596 ITypeLib_Release(pTypeLib
);
3599 static void test_external_connection(void)
3601 IStream
*stream
, *stream2
;
3602 ITestSecondDisp
*second
;
3608 static const LARGE_INTEGER zero
;
3610 trace("Testing IExternalConnection...\n");
3612 external_connections
= 0;
3614 /* Marshaling an interface increases external connection count. */
3615 expect_last_release_closes
= FALSE
;
3616 hres
= CreateStreamOnHGlobal(NULL
, TRUE
, &stream
);
3617 ok(hres
== S_OK
, "CreateStreamOnHGlobal failed: %08x\n", hres
);
3618 tid
= start_host_object(stream
, &IID_ItestDual
, (IUnknown
*)&TestDual
, MSHLFLAGS_NORMAL
, &thread
);
3619 ok(external_connections
== 1, "external_connections = %d\n", external_connections
);
3621 IStream_Seek(stream
, zero
, STREAM_SEEK_SET
, NULL
);
3622 hres
= CoUnmarshalInterface(stream
, &IID_ItestDual
, (void**)&iface
);
3623 ok(hres
== S_OK
, "CoUnmarshalInterface failed: %08x\n", hres
);
3626 end_host_object(tid
, thread
);
3627 IStream_Release(stream
);
3630 ok(external_connections
== 1, "external_connections = %d\n", external_connections
);
3632 IStream_Release(stream
);
3633 ok(external_connections
== 1, "external_connections = %d\n", external_connections
);
3635 /* Creating a stub for new iface causes new external connection. */
3636 hres
= ItestDual_QueryInterface(iface
, &IID_ITestSecondDisp
, (void**)&second
);
3637 ok(hres
== S_OK
, "Could not get ITestSecondDisp iface: %08x\n", hres
);
3639 ok(external_connections
== 2, "external_connections = %d\n", external_connections
);
3641 ITestSecondDisp_Release(second
);
3643 ok(external_connections
== 2, "external_connections = %d\n", external_connections
);
3645 expect_last_release_closes
= TRUE
;
3646 ItestDual_Release(iface
);
3647 ok(external_connections
== 0, "external_connections = %d\n", external_connections
);
3649 end_host_object(tid
, thread
);
3651 /* A test with direct CoMarshalInterface call. */
3652 hres
= CreateStreamOnHGlobal(NULL
, TRUE
, &stream
);
3653 ok(hres
== S_OK
, "CreateStreamOnHGlobal failed: %08x\n", hres
);
3655 expect_last_release_closes
= FALSE
;
3656 hres
= CoMarshalInterface(stream
, &IID_ItestDual
, (IUnknown
*)&TestDual
, MSHCTX_INPROC
, NULL
, MSHLFLAGS_NORMAL
);
3657 ok(hres
== S_OK
, "CoMarshalInterface failed: %08x\n", hres
);
3658 ok(external_connections
== 1, "external_connections = %d\n", external_connections
);
3660 expect_last_release_closes
= TRUE
;
3661 IStream_Seek(stream
, zero
, STREAM_SEEK_SET
, NULL
);
3662 hres
= CoReleaseMarshalData(stream
);
3663 ok(hres
== S_OK
, "CoReleaseMarshalData failed: %08x\n", hres
);
3664 ok(external_connections
== 0, "external_connections = %d\n", external_connections
);
3666 /* Two separated marshal data are still one external connection. */
3667 hres
= CreateStreamOnHGlobal(NULL
, TRUE
, &stream2
);
3668 ok(hres
== S_OK
, "CreateStreamOnHGlobal failed: %08x\n", hres
);
3670 expect_last_release_closes
= FALSE
;
3671 IStream_Seek(stream
, zero
, STREAM_SEEK_SET
, NULL
);
3672 hres
= CoMarshalInterface(stream
, &IID_ItestDual
, (IUnknown
*)&TestDual
, MSHCTX_INPROC
, NULL
, MSHLFLAGS_NORMAL
);
3673 ok(hres
== S_OK
, "CoMarshalInterface failed: %08x\n", hres
);
3674 ok(external_connections
== 1, "external_connections = %d\n", external_connections
);
3676 hres
= CoMarshalInterface(stream2
, &IID_ItestDual
, (IUnknown
*)&TestDual
, MSHCTX_INPROC
, NULL
, MSHLFLAGS_NORMAL
);
3677 ok(hres
== S_OK
, "CoMarshalInterface failed: %08x\n", hres
);
3678 ok(external_connections
== 1, "external_connections = %d\n", external_connections
);
3680 IStream_Seek(stream
, zero
, STREAM_SEEK_SET
, NULL
);
3681 hres
= CoReleaseMarshalData(stream
);
3682 ok(hres
== S_OK
, "CoReleaseMarshalData failed: %08x\n", hres
);
3683 ok(external_connections
== 1, "external_connections = %d\n", external_connections
);
3685 expect_last_release_closes
= TRUE
;
3686 IStream_Seek(stream2
, zero
, STREAM_SEEK_SET
, NULL
);
3687 hres
= CoReleaseMarshalData(stream2
);
3688 ok(hres
== S_OK
, "CoReleaseMarshalData failed: %08x\n", hres
);
3689 ok(external_connections
== 0, "external_connections = %d\n", external_connections
);
3691 IStream_Release(stream
);
3692 IStream_Release(stream2
);
3694 /* Weak table marshaling does not increment external connections */
3695 hres
= CreateStreamOnHGlobal(NULL
, TRUE
, &stream
);
3696 ok(hres
== S_OK
, "CreateStreamOnHGlobal failed: %08x\n", hres
);
3698 hres
= CoMarshalInterface(stream
, &IID_ItestDual
, (IUnknown
*)&TestDual
, MSHCTX_INPROC
, NULL
, MSHLFLAGS_TABLEWEAK
);
3699 ok(hres
== S_OK
, "CoMarshalInterface failed: %08x\n", hres
);
3700 ok(external_connections
== 0, "external_connections = %d\n", external_connections
);
3702 IStream_Seek(stream
, zero
, STREAM_SEEK_SET
, NULL
);
3703 hres
= CoUnmarshalInterface(stream
, &IID_ItestDual
, (void**)&iface
);
3704 ok(hres
== S_OK
, "CoUnmarshalInterface failed: %08x\n", hres
);
3705 ok(external_connections
== 0, "external_connections = %d\n", external_connections
);
3706 ItestDual_Release(iface
);
3708 IStream_Seek(stream
, zero
, STREAM_SEEK_SET
, NULL
);
3709 hres
= CoReleaseMarshalData(stream
);
3710 ok(hres
== S_OK
, "CoReleaseMarshalData failed: %08x\n", hres
);
3711 ok(external_connections
== 0, "external_connections = %d\n", external_connections
);
3713 IStream_Release(stream
);
3716 static void test_marshal_dispinterface(void)
3718 static const LARGE_INTEGER zero
;
3720 ISomethingFromDispatch
*disp_obj
= create_disp_obj();
3721 ITypeInfo
*typeinfo
= NULL
;
3722 IDispatch
*proxy_disp
;
3729 CreateStreamOnHGlobal(NULL
, TRUE
, &stream
);
3730 tid
= start_host_object(stream
, &DIID_ItestIF4
, (IUnknown
*)disp_obj
, MSHLFLAGS_NORMAL
, &thread
);
3731 IStream_Seek(stream
, zero
, STREAM_SEEK_SET
, NULL
);
3732 hr
= CoUnmarshalInterface(stream
, &DIID_ItestIF4
, (void **)&proxy_disp
);
3733 ok(hr
== S_OK
, "Got hr %#x.\n", hr
);
3735 hr
= IDispatch_GetTypeInfo(proxy_disp
, 0xdeadbeef, 0, &typeinfo
);
3736 ok(hr
== 0xbeefdead, "Got hr %#x.\n", hr
);
3738 ref
= IDispatch_Release(proxy_disp
);
3739 ok(!ref
, "Got outstanding refcount %d.\n", ref
);
3740 ref
= IStream_Release(stream
);
3741 ok(!ref
, "Got outstanding refcount %d.\n", ref
);
3742 end_host_object(tid
, thread
);
3743 ref
= ISomethingFromDispatch_Release(disp_obj
);
3744 ok(!ref
, "Got outstanding refcount %d.\n", ref
);
3747 START_TEST(tmarshal
)
3750 HANDLE hOleaut32
= GetModuleHandleA("oleaut32.dll");
3751 pVarAdd
= (void*)GetProcAddress(hOleaut32
, "VarAdd");
3753 CoInitializeEx(NULL
, COINIT_APARTMENTTHREADED
);
3755 hr
= register_current_module_typelib();
3759 win_skip("Registration of the test typelib failed, skipping tests\n");
3763 test_typelibmarshal();
3764 test_DispCallFunc();
3765 test_StaticWidget();
3767 test_external_connection();
3768 test_marshal_dispinterface();
3770 hr
= UnRegisterTypeLib(&LIBID_TestTypelib
, 2, 5, LOCALE_NEUTRAL
,
3771 sizeof(void*) == 8 ? SYS_WIN64
: SYS_WIN32
);
3772 ok_ole_success(hr
, UnRegisterTypeLib
);