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
30 #include "wine/test.h"
34 #define ok_ole_success(hr, func) ok(hr == S_OK, #func " failed with error %#08lx\n", hr)
35 static inline void release_iface_(unsigned int line
, void *iface
)
37 ULONG ref
= IUnknown_Release((IUnknown
*)iface
);
38 ok_(__FILE__
, line
)(!ref
, "Got outstanding refcount %ld.\n", ref
);
39 if (ref
== 1) IUnknown_Release((IUnknown
*)iface
);
41 #define release_iface(a) release_iface_(__LINE__, a)
43 static const WCHAR test_bstr1
[] = {'f','o','o',0,'b','a','r'};
44 static const WCHAR test_bstr2
[] = {'t','e','s','t',0};
45 static const WCHAR test_bstr3
[] = {'q','u','x',0};
46 static const WCHAR test_bstr4
[] = {'a','b','c',0};
48 static const MYSTRUCT test_mystruct1
= {0x12345678, 0xdeadbeef98765432ull
, {0,1,2,3,4,5,6,7}};
49 static const MYSTRUCT test_mystruct2
= {0x91827364, 0x8877665544332211ull
, {3,6,1,4,0,1,3,0}};
50 static const MYSTRUCT test_mystruct3
= {0x1a1b1c1d, 0x1e1f101112131415ull
, {9,2,4,5,6,5,1,3}};
51 static const MYSTRUCT test_mystruct4
= {0x2a2b2c2d, 0x2e2f202122232425ull
, {0,4,6,7,3,6,7,4}};
52 static const MYSTRUCT test_mystruct5
= {0x3a3b3c3d, 0x3e3f303132333435ull
, {1,6,7,3,8,4,6,5}};
53 static const MYSTRUCT test_mystruct6
= {0x4a4b4c4d, 0x4e4f404142434445ull
, {3,6,5,3,4,8,0,9}};
54 static const MYSTRUCT test_mystruct7
= {0x5a5b5c5d, 0x5e5f505152535455ull
, {1,8,4,4,4,2,3,1}};
56 static const struct thin test_thin_struct
= {-456, 78};
58 static const RECT test_rect1
= {1,2,3,4};
59 static const RECT test_rect2
= {5,6,7,8};
60 static const RECT test_rect3
= {9,10,11,12};
61 static const RECT test_rect4
= {13,14,15,16};
62 static const RECT test_rect5
= {17,18,19,20};
63 static const RECT test_rect6
= {21,22,23,24};
64 static const RECT test_rect7
= {25,26,27,28};
66 static const array_t test_array1
= {1,2,3,4};
67 static const array_t test_array2
= {5,6,7,8};
68 static const array_t test_array3
= {9,10,11,12};
69 static const array_t test_array4
= {13,14,15,16};
70 static const array_t test_array5
= {17,18,19,20};
71 static const array_t test_array6
= {21,22,23,24};
73 #define RELEASEMARSHALDATA WM_USER
75 struct host_object_data
80 MSHLFLAGS marshal_flags
;
82 IMessageFilter
*filter
;
85 static DWORD CALLBACK
host_object_proc(LPVOID p
)
87 struct host_object_data
*data
= p
;
91 CoInitializeEx(NULL
, COINIT_APARTMENTTHREADED
);
95 IMessageFilter
* prev_filter
= NULL
;
96 hr
= CoRegisterMessageFilter(data
->filter
, &prev_filter
);
97 if (prev_filter
) IMessageFilter_Release(prev_filter
);
98 ok_ole_success(hr
, CoRegisterMessageFilter
);
101 hr
= CoMarshalInterface(data
->stream
, &data
->iid
, data
->object
, MSHCTX_INPROC
, NULL
, data
->marshal_flags
);
102 ok_ole_success(hr
, CoMarshalInterface
);
104 /* force the message queue to be created before signaling parent thread */
105 PeekMessageA(&msg
, NULL
, WM_USER
, WM_USER
, PM_NOREMOVE
);
107 SetEvent(data
->marshal_event
);
109 while (GetMessageA(&msg
, NULL
, 0, 0))
111 if (msg
.hwnd
== NULL
&& msg
.message
== RELEASEMARSHALDATA
)
113 trace("releasing marshal data\n");
114 CoReleaseMarshalData(data
->stream
);
115 SetEvent((HANDLE
)msg
.lParam
);
118 DispatchMessageA(&msg
);
121 HeapFree(GetProcessHeap(), 0, data
);
128 static DWORD
start_host_object2(IStream
*stream
, REFIID riid
, IUnknown
*object
, MSHLFLAGS marshal_flags
, IMessageFilter
*filter
, HANDLE
*thread
)
131 HANDLE marshal_event
= CreateEventA(NULL
, FALSE
, FALSE
, NULL
);
132 struct host_object_data
*data
= HeapAlloc(GetProcessHeap(), 0, sizeof(*data
));
134 data
->stream
= stream
;
136 data
->object
= object
;
137 data
->marshal_flags
= marshal_flags
;
138 data
->marshal_event
= marshal_event
;
139 data
->filter
= filter
;
141 *thread
= CreateThread(NULL
, 0, host_object_proc
, data
, 0, &tid
);
143 /* wait for marshaling to complete before returning */
144 WaitForSingleObject(marshal_event
, INFINITE
);
145 CloseHandle(marshal_event
);
150 static DWORD
start_host_object(IStream
*stream
, REFIID riid
, IUnknown
*object
, MSHLFLAGS marshal_flags
, HANDLE
*thread
)
152 return start_host_object2(stream
, riid
, object
, marshal_flags
, NULL
, thread
);
156 /* asks thread to release the marshal data because it has to be done by the
157 * same thread that marshaled the interface in the first place. */
158 static void release_host_object(DWORD tid
)
160 HANDLE event
= CreateEventA(NULL
, FALSE
, FALSE
, NULL
);
161 PostThreadMessageA(tid
, RELEASEMARSHALDATA
, 0, (LPARAM
)event
);
162 WaitForSingleObject(event
, INFINITE
);
167 static void end_host_object(DWORD tid
, HANDLE thread
)
169 BOOL ret
= PostThreadMessageA(tid
, WM_QUIT
, 0, 0);
170 ok(ret
, "PostThreadMessage failed with error %ld\n", GetLastError());
171 /* be careful of races - don't return until hosting thread has terminated */
172 WaitForSingleObject(thread
, INFINITE
);
176 static int external_connections
;
177 static BOOL expect_last_release_closes
;
179 static HRESULT WINAPI
ExternalConnection_QueryInterface(IExternalConnection
*iface
, REFIID riid
, void **ppv
)
181 ok(0, "unexpected call\n");
183 return E_NOINTERFACE
;
186 static ULONG WINAPI
ExternalConnection_AddRef(IExternalConnection
*iface
)
191 static ULONG WINAPI
ExternalConnection_Release(IExternalConnection
*iface
)
196 static DWORD WINAPI
ExternalConnection_AddConnection(IExternalConnection
*iface
, DWORD extconn
, DWORD reserved
)
198 trace("add connection\n");
200 ok(extconn
== EXTCONN_STRONG
, "extconn = %ld\n", extconn
);
201 ok(!reserved
, "reserved = %lx\n", reserved
);
202 return ++external_connections
;
205 static DWORD WINAPI
ExternalConnection_ReleaseConnection(IExternalConnection
*iface
, DWORD extconn
,
206 DWORD reserved
, BOOL fLastReleaseCloses
)
208 trace("release connection\n");
210 ok(extconn
== EXTCONN_STRONG
, "extconn = %ld\n", extconn
);
211 ok(!reserved
, "reserved = %lx\n", reserved
);
213 ok(fLastReleaseCloses
== expect_last_release_closes
, "fLastReleaseCloses = %x, expected %x\n",
214 fLastReleaseCloses
, expect_last_release_closes
);
215 return --external_connections
;
218 static const IExternalConnectionVtbl ExternalConnectionVtbl
= {
219 ExternalConnection_QueryInterface
,
220 ExternalConnection_AddRef
,
221 ExternalConnection_Release
,
222 ExternalConnection_AddConnection
,
223 ExternalConnection_ReleaseConnection
226 static IExternalConnection ExternalConnection
= { &ExternalConnectionVtbl
};
228 static ItestDual TestDual
, TestDualDisp
;
230 static HRESULT WINAPI
TestSecondIface_QueryInterface(ITestSecondIface
*iface
, REFIID riid
, void **ppv
)
232 return ItestDual_QueryInterface(&TestDual
, riid
, ppv
);
235 static ULONG WINAPI
TestSecondIface_AddRef(ITestSecondIface
*iface
)
240 static ULONG WINAPI
TestSecondIface_Release(ITestSecondIface
*iface
)
245 static HRESULT WINAPI
TestSecondIface_test(ITestSecondIface
*iface
)
250 static const ITestSecondIfaceVtbl TestSecondIfaceVtbl
= {
251 TestSecondIface_QueryInterface
,
252 TestSecondIface_AddRef
,
253 TestSecondIface_Release
,
257 static ITestSecondIface TestSecondIface
= { &TestSecondIfaceVtbl
};
259 static HRESULT WINAPI
TestSecondDisp_QueryInterface(ITestSecondDisp
*iface
, REFIID riid
, void **ppv
)
261 return ItestDual_QueryInterface(&TestDual
, riid
, ppv
);
264 static ULONG WINAPI
TestSecondDisp_AddRef(ITestSecondDisp
*iface
)
269 static ULONG WINAPI
TestSecondDisp_Release(ITestSecondDisp
*iface
)
274 static HRESULT WINAPI
TestSecondDisp_GetTypeInfoCount(ITestSecondDisp
*iface
, UINT
*pctinfo
)
276 ok(0, "unexpected call\n");
280 static HRESULT WINAPI
TestSecondDisp_GetTypeInfo(ITestSecondDisp
*iface
, UINT iTInfo
, LCID lcid
, ITypeInfo
**ppTInfo
)
282 ok(0, "unexpected call\n");
286 static HRESULT WINAPI
TestSecondDisp_GetIDsOfNames(ITestSecondDisp
*iface
, REFIID riid
, LPOLESTR
*rgszNames
,
287 UINT cNames
, LCID lcid
, DISPID
*rgDispId
)
289 ok(0, "unexpected call\n");
293 static HRESULT WINAPI
TestSecondDisp_Invoke(ITestSecondDisp
*iface
, DISPID dispIdMember
, REFIID riid
, LCID lcid
,
294 WORD wFlags
, DISPPARAMS
*pDispParams
, VARIANT
*pVarResult
, EXCEPINFO
*pExcepInfo
,
297 ok(0, "unexpected call\n");
301 static HRESULT WINAPI
TestSecondDisp_test(ITestSecondDisp
*iface
)
303 ok(0, "unexpected call\n");
307 static ITestSecondDispVtbl TestSecondDispVtbl
= {
308 TestSecondDisp_QueryInterface
,
309 TestSecondDisp_AddRef
,
310 TestSecondDisp_Release
,
311 TestSecondDisp_GetTypeInfoCount
,
312 TestSecondDisp_GetTypeInfo
,
313 TestSecondDisp_GetIDsOfNames
,
314 TestSecondDisp_Invoke
,
318 static ITestSecondDisp TestSecondDisp
= { &TestSecondDispVtbl
};
320 static HRESULT WINAPI
TestDual_QueryInterface(ItestDual
*iface
, REFIID riid
, void **ppvObject
)
322 if (IsEqualIID(riid
, &IID_IUnknown
) || IsEqualIID(riid
, &IID_IDispatch
)) {
323 *ppvObject
= &TestDualDisp
;
325 }else if(IsEqualGUID(riid
, &IID_ItestDual
)) {
326 *ppvObject
= &TestDual
;
328 }else if(IsEqualGUID(riid
, &IID_ITestSecondIface
)) {
329 *ppvObject
= &TestSecondIface
;
331 }else if(IsEqualGUID(riid
, &IID_ITestSecondDisp
)) {
332 *ppvObject
= &TestSecondDisp
;
334 }else if (IsEqualGUID(riid
, &IID_IExternalConnection
)) {
335 trace("QI external connection\n");
336 *ppvObject
= &ExternalConnection
;
341 return E_NOINTERFACE
;
344 static ULONG WINAPI
TestDual_AddRef(ItestDual
*iface
)
349 static ULONG WINAPI
TestDual_Release(ItestDual
*iface
)
354 static HRESULT WINAPI
TestDual_GetTypeInfoCount(ItestDual
*iface
, UINT
*pctinfo
)
356 ok(0, "unexpected call\n");
360 static HRESULT WINAPI
TestDual_GetTypeInfo(ItestDual
*iface
, UINT iTInfo
, LCID lcid
, ITypeInfo
**ppTInfo
)
362 ok(0, "unexpected call\n");
366 static HRESULT WINAPI
TestDual_GetIDsOfNames(ItestDual
*iface
, REFIID riid
, LPOLESTR
*rgszNames
,
367 UINT cNames
, LCID lcid
, DISPID
*rgDispId
)
369 ok(0, "unexpected call\n");
373 static HRESULT WINAPI
TestDual_Invoke(ItestDual
*iface
, DISPID dispIdMember
, REFIID riid
, LCID lcid
,
374 WORD wFlags
, DISPPARAMS
*pDispParams
, VARIANT
*pVarResult
, EXCEPINFO
*pExcepInfo
,
377 ok(0, "unexpected call\n");
381 static ItestDualVtbl TestDualVtbl
= {
382 TestDual_QueryInterface
,
385 TestDual_GetTypeInfoCount
,
386 TestDual_GetTypeInfo
,
387 TestDual_GetIDsOfNames
,
391 static ItestDual TestDual
= { &TestDualVtbl
};
392 static ItestDual TestDualDisp
= { &TestDualVtbl
};
396 ISomethingFromDispatch ISomethingFromDispatch_iface
;
398 bool support_idispatch
;
401 static inline struct disp_obj
*impl_from_ISomethingFromDispatch(ISomethingFromDispatch
*iface
)
403 return CONTAINING_RECORD(iface
, struct disp_obj
, ISomethingFromDispatch_iface
);
406 static HRESULT WINAPI
disp_obj_QueryInterface(ISomethingFromDispatch
*iface
, REFIID iid
, void **out
)
408 struct disp_obj
*obj
= impl_from_ISomethingFromDispatch(iface
);
410 if (!obj
->support_idispatch
)
411 ok(!IsEqualGUID(iid
, &IID_IDispatch
), "Expected no query for IDispatch.\n");
413 if (IsEqualGUID(iid
, &IID_IUnknown
) || IsEqualGUID(iid
, &IID_IDispatch
)
414 || IsEqualGUID(iid
, &IID_ISomethingFromDispatch
)
415 || IsEqualGUID(iid
, &DIID_ItestIF4
))
418 ISomethingFromDispatch_AddRef(iface
);
423 return E_NOINTERFACE
;
426 static ULONG WINAPI
disp_obj_AddRef(ISomethingFromDispatch
*iface
)
428 struct disp_obj
*obj
= impl_from_ISomethingFromDispatch(iface
);
432 static ULONG WINAPI
disp_obj_Release(ISomethingFromDispatch
*iface
)
434 struct disp_obj
*obj
= impl_from_ISomethingFromDispatch(iface
);
435 LONG ref
= --obj
->ref
;
441 static HRESULT WINAPI
disp_obj_GetTypeInfoCount(ISomethingFromDispatch
*iface
, UINT
*count
)
443 ok(0, "unexpected call\n");
447 static HRESULT WINAPI
disp_obj_GetTypeInfo(ISomethingFromDispatch
*iface
,
448 UINT index
, LCID lcid
, ITypeInfo
**typeinfo
)
450 ok(index
== 0xdeadbeef, "Got unexpected index %#x.\n", index
);
454 static HRESULT WINAPI
disp_obj_GetIDsOfNames(ISomethingFromDispatch
*iface
,
455 REFIID iid
, LPOLESTR
*names
, UINT count
, LCID lcid
, DISPID
*ids
)
457 ok(0, "unexpected call\n");
461 static HRESULT WINAPI
disp_obj_Invoke(ISomethingFromDispatch
*iface
, DISPID id
, REFIID iid
, LCID lcid
,
462 WORD flags
, DISPPARAMS
*dispparams
, VARIANT
*result
, EXCEPINFO
*excepinfo
, UINT
*errarg
)
464 ok(0, "unexpected call\n");
468 static HRESULT WINAPI
disp_obj_anotherfn(ISomethingFromDispatch
*iface
)
473 static const ISomethingFromDispatchVtbl disp_obj_vtbl
=
475 disp_obj_QueryInterface
,
478 disp_obj_GetTypeInfoCount
,
479 disp_obj_GetTypeInfo
,
480 disp_obj_GetIDsOfNames
,
485 static ISomethingFromDispatch
*create_disp_obj2(bool support_idispatch
)
487 struct disp_obj
*obj
= CoTaskMemAlloc(sizeof(*obj
));
488 obj
->ISomethingFromDispatch_iface
.lpVtbl
= &disp_obj_vtbl
;
490 obj
->support_idispatch
= support_idispatch
;
491 return &obj
->ISomethingFromDispatch_iface
;
494 static ISomethingFromDispatch
*create_disp_obj(void)
496 return create_disp_obj2(true);
501 ICoclass1 ICoclass1_iface
;
502 ICoclass2 ICoclass2_iface
;
506 static inline struct coclass_obj
*impl_from_ICoclass1(ICoclass1
*iface
)
508 return CONTAINING_RECORD(iface
, struct coclass_obj
, ICoclass1_iface
);
511 static inline struct coclass_obj
*impl_from_ICoclass2(ICoclass2
*iface
)
513 return CONTAINING_RECORD(iface
, struct coclass_obj
, ICoclass2_iface
);
516 static HRESULT WINAPI
coclass1_QueryInterface(ICoclass1
*iface
, REFIID iid
, void **out
)
518 struct coclass_obj
*obj
= impl_from_ICoclass1(iface
);
520 if (IsEqualGUID(iid
, &IID_IUnknown
)
521 || IsEqualGUID(iid
, &IID_IDispatch
)
522 || IsEqualGUID(iid
, &IID_ICoclass1
))
525 ICoclass1_AddRef(iface
);
528 else if (IsEqualGUID(iid
, &IID_ICoclass2
))
530 *out
= &obj
->ICoclass2_iface
;
531 ICoclass2_AddRef(*out
);
536 return E_NOINTERFACE
;
539 static ULONG WINAPI
coclass1_AddRef(ICoclass1
*iface
)
541 struct coclass_obj
*obj
= impl_from_ICoclass1(iface
);
545 static ULONG WINAPI
coclass1_Release(ICoclass1
*iface
)
547 struct coclass_obj
*obj
= impl_from_ICoclass1(iface
);
548 LONG ref
= --obj
->ref
;
554 static HRESULT WINAPI
coclass1_GetTypeInfoCount(ICoclass1
*iface
, UINT
*count
)
556 ok(0, "unexpected call\n");
560 static HRESULT WINAPI
coclass1_GetTypeInfo(ICoclass1
*iface
, UINT index
,
561 LCID lcid
, ITypeInfo
**typeinfo
)
563 ok(index
== 0xdeadbeef, "Got unexpected index %#x.\n", index
);
567 static HRESULT WINAPI
coclass1_GetIDsOfNames(ICoclass1
*iface
, REFIID iid
,
568 LPOLESTR
*names
, UINT count
, LCID lcid
, DISPID
*ids
)
570 ok(0, "unexpected call\n");
574 static HRESULT WINAPI
coclass1_Invoke(ICoclass1
*iface
, DISPID id
, REFIID iid
, LCID lcid
,
575 WORD flags
, DISPPARAMS
*dispparams
, VARIANT
*result
, EXCEPINFO
*excepinfo
, UINT
*errarg
)
577 ok(0, "unexpected call\n");
581 static HRESULT WINAPI
coclass1_test(ICoclass1
*iface
)
586 static HRESULT WINAPI
coclass2_QueryInterface(ICoclass2
*iface
, REFIID iid
, void **out
)
588 struct coclass_obj
*obj
= impl_from_ICoclass2(iface
);
589 return ICoclass1_QueryInterface(&obj
->ICoclass1_iface
, iid
, out
);
592 static ULONG WINAPI
coclass2_AddRef(ICoclass2
*iface
)
594 struct coclass_obj
*obj
= impl_from_ICoclass2(iface
);
595 return ICoclass1_AddRef(&obj
->ICoclass1_iface
);
598 static ULONG WINAPI
coclass2_Release(ICoclass2
*iface
)
600 struct coclass_obj
*obj
= impl_from_ICoclass2(iface
);
601 return ICoclass1_Release(&obj
->ICoclass1_iface
);
604 static HRESULT WINAPI
coclass2_GetTypeInfoCount(ICoclass2
*iface
, UINT
*count
)
606 ok(0, "unexpected call\n");
610 static HRESULT WINAPI
coclass2_GetTypeInfo(ICoclass2
*iface
, UINT index
,
611 LCID lcid
, ITypeInfo
**typeinfo
)
613 ok(index
== 0xdeadbeef, "Got unexpected index %#x.\n", index
);
617 static HRESULT WINAPI
coclass2_GetIDsOfNames(ICoclass2
*iface
, REFIID iid
,
618 LPOLESTR
*names
, UINT count
, LCID lcid
, DISPID
*ids
)
620 ok(0, "unexpected call\n");
624 static HRESULT WINAPI
coclass2_Invoke(ICoclass2
*iface
, DISPID id
, REFIID iid
, LCID lcid
,
625 WORD flags
, DISPPARAMS
*dispparams
, VARIANT
*result
, EXCEPINFO
*excepinfo
, UINT
*errarg
)
627 ok(0, "unexpected call\n");
631 static HRESULT WINAPI
coclass2_test(ICoclass2
*iface
)
636 static const ICoclass1Vtbl coclass1_vtbl
=
638 coclass1_QueryInterface
,
641 coclass1_GetTypeInfoCount
,
642 coclass1_GetTypeInfo
,
643 coclass1_GetIDsOfNames
,
648 static const ICoclass2Vtbl coclass2_vtbl
=
650 coclass2_QueryInterface
,
653 coclass2_GetTypeInfoCount
,
654 coclass2_GetTypeInfo
,
655 coclass2_GetIDsOfNames
,
660 static struct coclass_obj
*create_coclass_obj(void)
662 struct coclass_obj
*obj
= CoTaskMemAlloc(sizeof(*obj
));
663 obj
->ICoclass1_iface
.lpVtbl
= &coclass1_vtbl
;
664 obj
->ICoclass2_iface
.lpVtbl
= &coclass2_vtbl
;
671 typedef struct Widget
673 IWidget IWidget_iface
;
675 IUnknown
*pDispatchUnknown
;
678 static inline Widget
*impl_from_IWidget(IWidget
*iface
)
680 return CONTAINING_RECORD(iface
, Widget
, IWidget_iface
);
683 static HRESULT WINAPI
Widget_QueryInterface(
685 /* [in] */ REFIID riid
,
686 /* [iid_is][out] */ void __RPC_FAR
*__RPC_FAR
*ppvObject
)
688 if (IsEqualIID(riid
, &IID_IWidget
) || IsEqualIID(riid
, &IID_IUnknown
) || IsEqualIID(riid
, &IID_IDispatch
))
690 IWidget_AddRef(iface
);
697 return E_NOINTERFACE
;
701 static ULONG WINAPI
Widget_AddRef(
704 Widget
*This
= impl_from_IWidget(iface
);
706 return InterlockedIncrement(&This
->refs
);
709 static ULONG WINAPI
Widget_Release(
712 Widget
*This
= impl_from_IWidget(iface
);
713 ULONG refs
= InterlockedDecrement(&This
->refs
);
716 IUnknown_Release(This
->pDispatchUnknown
);
717 memset(This
, 0xcc, sizeof(*This
));
718 HeapFree(GetProcessHeap(), 0, This
);
719 trace("Widget destroyed!\n");
725 static HRESULT WINAPI
Widget_GetTypeInfoCount(
727 /* [out] */ UINT __RPC_FAR
*pctinfo
)
729 Widget
*This
= impl_from_IWidget(iface
);
730 IDispatch
*pDispatch
;
731 HRESULT hr
= IUnknown_QueryInterface(This
->pDispatchUnknown
, &IID_IDispatch
, (void **)&pDispatch
);
734 hr
= IDispatch_GetTypeInfoCount(pDispatch
, pctinfo
);
735 IDispatch_Release(pDispatch
);
740 static HRESULT WINAPI
Widget_GetTypeInfo(
741 IWidget __RPC_FAR
* iface
,
742 /* [in] */ UINT iTInfo
,
743 /* [in] */ LCID lcid
,
744 /* [out] */ ITypeInfo __RPC_FAR
*__RPC_FAR
*ppTInfo
)
746 Widget
*This
= impl_from_IWidget(iface
);
747 IDispatch
*pDispatch
;
748 HRESULT hr
= IUnknown_QueryInterface(This
->pDispatchUnknown
, &IID_IDispatch
, (void **)&pDispatch
);
751 hr
= IDispatch_GetTypeInfo(pDispatch
, iTInfo
, lcid
, ppTInfo
);
752 IDispatch_Release(pDispatch
);
757 static HRESULT WINAPI
Widget_GetIDsOfNames(
758 IWidget __RPC_FAR
* iface
,
759 /* [in] */ REFIID riid
,
760 /* [size_is][in] */ LPOLESTR __RPC_FAR
*rgszNames
,
761 /* [in] */ UINT cNames
,
762 /* [in] */ LCID lcid
,
763 /* [size_is][out] */ DISPID __RPC_FAR
*rgDispId
)
765 Widget
*This
= impl_from_IWidget(iface
);
766 IDispatch
*pDispatch
;
767 HRESULT hr
= IUnknown_QueryInterface(This
->pDispatchUnknown
, &IID_IDispatch
, (void **)&pDispatch
);
770 hr
= IDispatch_GetIDsOfNames(pDispatch
, riid
, rgszNames
, cNames
, lcid
, rgDispId
);
771 IDispatch_Release(pDispatch
);
776 static HRESULT WINAPI
Widget_Invoke(
777 IWidget __RPC_FAR
* iface
,
778 /* [in] */ DISPID dispIdMember
,
779 /* [in] */ REFIID riid
,
780 /* [in] */ LCID lcid
,
781 /* [in] */ WORD wFlags
,
782 /* [out][in] */ DISPPARAMS __RPC_FAR
*pDispParams
,
783 /* [out] */ VARIANT __RPC_FAR
*pVarResult
,
784 /* [out] */ EXCEPINFO __RPC_FAR
*pExcepInfo
,
785 /* [out] */ UINT __RPC_FAR
*puArgErr
)
787 Widget
*This
= impl_from_IWidget(iface
);
788 IDispatch
*pDispatch
;
789 HRESULT hr
= IUnknown_QueryInterface(This
->pDispatchUnknown
, &IID_IDispatch
, (void **)&pDispatch
);
792 hr
= IDispatch_Invoke(pDispatch
, dispIdMember
, riid
, lcid
, wFlags
, pDispParams
, pVarResult
, pExcepInfo
, puArgErr
);
793 IDispatch_Release(pDispatch
);
798 static HRESULT WINAPI
Widget_put_Name(
799 IWidget __RPC_FAR
* iface
,
800 /* [in] */ BSTR name
)
802 trace("put_Name(%s)\n", wine_dbgstr_w(name
));
806 static HRESULT WINAPI
Widget_get_Name(
807 IWidget __RPC_FAR
* iface
,
808 /* [out] */ BSTR __RPC_FAR
*name
)
810 static const WCHAR szCat
[] = { 'C','a','t',0 };
811 trace("get_Name()\n");
812 *name
= SysAllocString(szCat
);
816 static HRESULT WINAPI
Widget_DoSomething(
817 IWidget __RPC_FAR
* iface
,
818 /* [in] */ double number
,
819 /* [out] */ BSTR
*str1
,
820 /* [defaultvalue][in] */ BSTR str2
,
821 /* [optional][in] */ VARIANT __RPC_FAR
*opt
)
823 static const WCHAR szString
[] = { 'S','t','r','i','n','g',0 };
824 trace("DoSomething()\n");
826 ok(number
== 3.141, "number(%f) != 3.141\n", number
);
827 ok(*str2
== '\0', "str2(%s) != \"\"\n", wine_dbgstr_w(str2
));
828 ok(V_VT(opt
) == VT_ERROR
, "V_VT(opt) should be VT_ERROR instead of 0x%x\n", V_VT(opt
));
829 ok(V_ERROR(opt
) == DISP_E_PARAMNOTFOUND
, "V_ERROR(opt) should be DISP_E_PARAMNOTFOUND instead of 0x%08lx\n", V_ERROR(opt
));
830 *str1
= SysAllocString(szString
);
835 static HRESULT WINAPI
Widget_get_State(
836 IWidget __RPC_FAR
* iface
,
837 /* [retval][out] */ STATE __RPC_FAR
*state
)
839 trace("get_State() = STATE_WIDGETIFIED\n");
840 *state
= STATE_WIDGETIFIED
;
844 static HRESULT WINAPI
Widget_put_State(
845 IWidget __RPC_FAR
* iface
,
846 /* [in] */ STATE state
)
848 trace("put_State(%d)\n", state
);
852 static HRESULT WINAPI
Widget_Map(
857 trace("Map(%s, %p)\n", wine_dbgstr_w(bstrId
), sValue
);
858 *sValue
= SysAllocString(bstrId
);
862 static HRESULT WINAPI
Widget_SetOleColor(
866 trace("SetOleColor(0x%lx)\n", val
);
870 static HRESULT WINAPI
Widget_GetOleColor(
874 trace("GetOleColor() = 0x8000000f\n");
879 static HRESULT WINAPI
Widget_Clone(
884 return Widget_QueryInterface(iface
, &IID_IWidget
, (void **)ppVal
);
887 static HRESULT WINAPI
Widget_CloneDispatch(
891 trace("CloneDispatch()\n");
892 return Widget_QueryInterface(iface
, &IID_IWidget
, (void **)ppVal
);
895 static HRESULT WINAPI
Widget_CloneCoclass(
897 ApplicationObject2
**ppVal
)
899 trace("CloneCoclass()\n");
900 return Widget_QueryInterface(iface
, &IID_IWidget
, (void **)ppVal
);
903 static HRESULT WINAPI
Widget_Value(
904 IWidget __RPC_FAR
* iface
,
908 trace("Value(%p, %p)\n", value
, retval
);
909 ok(V_VT(value
) == VT_I2
, "V_VT(value) was %d instead of VT_I2\n", V_VT(value
));
910 ok(V_I2(value
) == 1, "V_I2(value) was %d instead of 1\n", V_I2(value
));
911 V_VT(retval
) = VT_I2
;
916 static HRESULT WINAPI
Widget_VariantArrayPtr(
920 trace("VariantArrayPtr(%p)\n", values
);
924 static HRESULT WINAPI
Widget_VarArg(
929 LONG lbound
, ubound
, i
;
933 trace("VarArg(%p)\n", values
);
935 ok( values
->cDims
== 1, "wrong cDims %u\n", values
->cDims
);
936 ok( values
->cbElements
== (numexpect
? sizeof(VARIANT
) : 0),
937 "wrong cbElements %lu\n", values
->cbElements
);
939 hr
= SafeArrayGetLBound(values
, 1, &lbound
);
940 ok(hr
== S_OK
, "SafeArrayGetLBound failed with %lx\n", hr
);
941 ok(lbound
== 0, "SafeArrayGetLBound returned %ld\n", lbound
);
943 hr
= SafeArrayGetUBound(values
, 1, &ubound
);
944 ok(hr
== S_OK
, "SafeArrayGetUBound failed with %lx\n", hr
);
945 ok(ubound
== numexpect
-1, "SafeArrayGetUBound returned %ld, but expected %d\n", ubound
, numexpect
-1);
947 hr
= SafeArrayAccessData(values
, (LPVOID
)&data
);
948 ok(hr
== S_OK
, "SafeArrayAccessData failed with %lx\n", hr
);
950 for (i
=0; i
<=ubound
-lbound
; i
++)
952 ok(V_VT(&data
[i
]) == VT_I4
, "V_VT(&data[%ld]) was %d\n", i
, V_VT(&data
[i
]));
953 ok(V_I4(&data
[i
]) == i
, "V_I4(&data[%ld]) was %ld\n", i
, V_I4(&data
[i
]));
956 hr
= SafeArrayUnaccessData(values
);
957 ok(hr
== S_OK
, "SafeArrayUnaccessData failed with %lx\n", hr
);
962 static HRESULT WINAPI
Widget_Error(
963 IWidget __RPC_FAR
* iface
)
969 static HRESULT WINAPI
Widget_CloneInterface(
970 IWidget __RPC_FAR
* iface
,
971 ISomethingFromDispatch
**ppVal
)
973 trace("CloneInterface()\n");
978 static HRESULT WINAPI
Widget_put_prop_with_lcid(
979 IWidget
* iface
, LONG lcid
, INT i
)
981 trace("put_prop_with_lcid(%08lx, %x)\n", lcid
, i
);
982 ok(lcid
== MAKELANGID(LANG_ENGLISH
, SUBLANG_ENGLISH_US
), "got lcid %08lx\n", lcid
);
983 ok(i
== 0xcafe, "got %08x\n", i
);
987 static HRESULT WINAPI
Widget_get_prop_with_lcid(
988 IWidget
* iface
, LONG lcid
, INT
*i
)
990 trace("get_prop_with_lcid(%08lx, %p)\n", lcid
, i
);
991 ok(lcid
== MAKELANGID(LANG_ENGLISH
, SUBLANG_ENGLISH_US
), "got lcid %08lx\n", lcid
);
996 static HRESULT WINAPI
Widget_get_prop_int(
997 IWidget
* iface
, INT
*i
)
999 trace("get_prop_int(%p)\n", i
);
1004 static HRESULT WINAPI
Widget_get_prop_uint(
1005 IWidget
* iface
, UINT
*i
)
1007 trace("get_prop_uint(%p)\n", i
);
1012 static HRESULT WINAPI
Widget_ByRefUInt(
1013 IWidget
* iface
, UINT
*i
)
1019 static HRESULT WINAPI
Widget_put_prop_opt_arg(
1020 IWidget
* iface
, INT opt
, INT i
)
1022 trace("put_prop_opt_arg(%08x, %08x)\n", opt
, i
);
1023 todo_wine
ok(opt
== 0, "got opt=%08x\n", opt
);
1024 ok(i
== 0xcafe, "got i=%08x\n", i
);
1028 static HRESULT WINAPI
Widget_put_prop_req_arg(
1029 IWidget
* iface
, INT req
, INT i
)
1031 trace("put_prop_req_arg(%08x, %08x)\n", req
, i
);
1032 ok(req
== 0x5678, "got req=%08x\n", req
);
1033 ok(i
== 0x1234, "got i=%08x\n", i
);
1037 static HRESULT WINAPI
Widget_pos_restrict(IWidget
* iface
, INT
*i
)
1039 trace("restrict\n");
1040 *i
= DISPID_TM_RESTRICTED
;
1044 static HRESULT WINAPI
Widget_neg_restrict(IWidget
* iface
, INT
*i
)
1046 trace("neg_restrict\n");
1047 *i
= DISPID_TM_NEG_RESTRICTED
;
1051 static HRESULT WINAPI
Widget_VarArg_Run(
1052 IWidget
*iface
, BSTR name
, SAFEARRAY
*params
, VARIANT
*result
)
1054 static const WCHAR catW
[] = { 'C','a','t',0 };
1055 static const WCHAR supermanW
[] = { 'S','u','p','e','r','m','a','n',0 };
1061 trace("VarArg_Run(%p,%p,%p)\n", name
, params
, result
);
1063 ok(!lstrcmpW(name
, catW
), "got %s\n", wine_dbgstr_w(name
));
1065 if (!params
->cbElements
) /* no varargs */
1067 hr
= SafeArrayGetUBound(params
, 1, &bound
);
1068 ok(hr
== S_OK
, "SafeArrayGetUBound error %#lx\n", hr
);
1069 ok(bound
== -1, "expected -1, got %ld\n", bound
);
1073 ok( params
->cbElements
== sizeof(VARIANT
), "wrong cbElements %lu\n", params
->cbElements
);
1075 hr
= SafeArrayGetLBound(params
, 1, &bound
);
1076 ok(hr
== S_OK
, "SafeArrayGetLBound error %#lx\n", hr
);
1077 ok(bound
== 0, "expected 0, got %ld\n", bound
);
1079 hr
= SafeArrayGetUBound(params
, 1, &bound
);
1080 ok(hr
== S_OK
, "SafeArrayGetUBound error %#lx\n", hr
);
1081 ok(bound
== 0, "expected 0, got %ld\n", bound
);
1083 hr
= SafeArrayAccessData(params
, (void **)&var
);
1084 ok(hr
== S_OK
, "SafeArrayAccessData failed with %lx\n", hr
);
1086 ok(V_VT(&var
[0]) == VT_BSTR
, "expected VT_BSTR, got %d\n", V_VT(&var
[0]));
1087 bstr
= V_BSTR(&var
[0]);
1088 ok(!lstrcmpW(bstr
, supermanW
), "got %s\n", wine_dbgstr_w(bstr
));
1090 hr
= SafeArrayUnaccessData(params
);
1091 ok(hr
== S_OK
, "SafeArrayUnaccessData error %#lx\n", hr
);
1096 static HRESULT WINAPI
Widget_VarArg_Ref_Run(
1097 IWidget
*iface
, BSTR name
, SAFEARRAY
**params
, VARIANT
*result
)
1099 static const WCHAR catW
[] = { 'C','a','t',0 };
1100 static const WCHAR supermanW
[] = { 'S','u','p','e','r','m','a','n',0 };
1106 trace("VarArg_Ref_Run(%p,%p,%p)\n", name
, params
, result
);
1108 ok(!lstrcmpW(name
, catW
), "got %s\n", wine_dbgstr_w(name
));
1110 if (!(*params
)->cbElements
) /* no varargs */
1112 hr
= SafeArrayGetUBound(*params
, 1, &bound
);
1113 ok(hr
== S_OK
, "SafeArrayGetUBound error %#lx\n", hr
);
1114 ok(bound
== -1, "expected -1, got %ld\n", bound
);
1118 ok( (*params
)->cbElements
== sizeof(VARIANT
), "wrong cbElements %lu\n", (*params
)->cbElements
);
1120 hr
= SafeArrayGetLBound(*params
, 1, &bound
);
1121 ok(hr
== S_OK
, "SafeArrayGetLBound error %#lx\n", hr
);
1122 ok(bound
== 0, "expected 0, got %ld\n", bound
);
1124 hr
= SafeArrayGetUBound(*params
, 1, &bound
);
1125 ok(hr
== S_OK
, "SafeArrayGetUBound error %#lx\n", hr
);
1126 ok(bound
== 0, "expected 0, got %ld\n", bound
);
1128 hr
= SafeArrayAccessData(*params
, (void **)&var
);
1129 ok(hr
== S_OK
, "SafeArrayAccessData error %#lx\n", hr
);
1131 ok(V_VT(&var
[0]) == VT_BSTR
, "expected VT_BSTR, got %d\n", V_VT(&var
[0]));
1132 bstr
= V_BSTR(&var
[0]);
1133 ok(!lstrcmpW(bstr
, supermanW
), "got %s\n", wine_dbgstr_w(bstr
));
1135 hr
= SafeArrayUnaccessData(*params
);
1136 ok(hr
== S_OK
, "SafeArrayUnaccessData error %#lx\n", hr
);
1141 static HRESULT WINAPI
Widget_basetypes_in(IWidget
*iface
, signed char c
, short s
, LONG l
, hyper h
,
1142 unsigned char uc
, unsigned short us
, ULONG ul
, MIDL_uhyper uh
,
1143 float f
, double d
, STATE st
)
1145 ok(c
== 5, "Got char %d.\n", c
);
1146 ok(s
== -123, "Got short %d.\n", s
);
1147 ok(l
== -100000, "Got int %ld.\n", l
);
1148 ok(h
== (LONGLONG
)-100000 * 1000000, "Got hyper %s.\n", wine_dbgstr_longlong(h
));
1149 ok(uc
== 0, "Got unsigned char %u.\n", uc
);
1150 ok(us
== 456, "Got unsigned short %u.\n", us
);
1151 ok(ul
== 0xdeadbeef, "Got unsigned int %lu.\n", ul
);
1152 ok(uh
== (ULONGLONG
)1234567890 * 9876543210, "Got unsigned hyper %s.\n", wine_dbgstr_longlong(uh
));
1153 ok(f
== (float)M_PI
, "Got float %f.\n", f
);
1154 ok(d
== M_E
, "Got double %f.\n", d
);
1155 ok(st
== STATE_WIDGETIFIED
, "Got state %u.\n", st
);
1160 static HRESULT WINAPI
Widget_basetypes_out(IWidget
*iface
, signed char *c
, short *s
, LONG
*l
, hyper
*h
,
1161 unsigned char *uc
, unsigned short *us
, ULONG
*ul
, MIDL_uhyper
*uh
,
1162 float *f
, double *d
, STATE
*st
)
1167 *h
= (LONGLONG
)-200000 * 1000000;
1171 *uh
= 0xabcdef0123456789ull
;
1174 *st
= STATE_UNWIDGETIFIED
;
1179 static HRESULT WINAPI
Widget_float_abi(IWidget
*iface
, float f
, double d
, int i
, float f2
, double d2
)
1181 ok(f
== 1.0f
, "Got float %f.\n", f
);
1182 ok(d
== 2.0, "Got double %f.\n", d
);
1183 ok(i
== 3, "Got int %d.\n", i
);
1184 ok(f2
== 4.0f
, "Got float %f.\n", f2
);
1185 ok(d2
== 5.0, "Got double %f.\n", d2
);
1190 static HRESULT WINAPI
Widget_long_ptr(IWidget
*iface
, LONG
*in
, LONG
*out
, LONG
*in_out
)
1192 ok(*in
== 123, "Got [in] %ld.\n", *in
);
1193 if (testmode
== 0) /* Invoke() */
1194 ok(*out
== 456, "Got [out] %ld.\n", *out
);
1195 else if (testmode
== 1)
1196 ok(!*out
, "Got [out] %ld.\n", *out
);
1197 ok(*in_out
== 789, "Got [in, out] %ld.\n", *in_out
);
1206 static HRESULT WINAPI
Widget_long_ptr_ptr(IWidget
*iface
, LONG
**in
, LONG
**out
, LONG
**in_out
)
1208 ok(!*out
, "Got [out] %p.\n", *out
);
1211 ok(!*in
, "Got [in] %p.\n", *in
);
1212 ok(!*in_out
, "Got [in, out] %p.\n", *in_out
);
1214 else if (testmode
== 1)
1216 ok(!*in
, "Got [in] %p.\n", *in
);
1217 ok(!*in_out
, "Got [in, out] %p.\n", *in_out
);
1219 *out
= CoTaskMemAlloc(sizeof(int));
1221 *in_out
= CoTaskMemAlloc(sizeof(int));
1224 else if (testmode
== 2)
1226 ok(**in
== 123, "Got [in] %ld.\n", **in
);
1227 ok(**in_out
== 789, "Got [in, out] %ld.\n", **in_out
);
1229 *out
= CoTaskMemAlloc(sizeof(int));
1233 else if (testmode
== 3)
1235 ok(**in_out
== 789, "Got [in, out] %ld.\n", **in_out
);
1242 /* Call methods to check that we have valid proxies to each interface. */
1243 static void check_iface_marshal(IUnknown
*unk
, IDispatch
*disp
, ISomethingFromDispatch
*sfd
)
1245 ISomethingFromDispatch
*sfd2
;
1246 ITypeInfo
*typeinfo
;
1249 hr
= IUnknown_QueryInterface(unk
, &IID_ISomethingFromDispatch
, (void **)&sfd2
);
1250 ok(hr
== S_OK
, "Got hr %#lx.\n", hr
);
1251 ISomethingFromDispatch_Release(sfd2
);
1253 hr
= IDispatch_GetTypeInfo(disp
, 0xdeadbeef, 0, &typeinfo
);
1254 ok(hr
== 0xbeefdead, "Got hr %#lx.\n", hr
);
1256 hr
= ISomethingFromDispatch_anotherfn(sfd
);
1257 ok(hr
== 0x01234567, "Got hr %#lx.\n", hr
);
1260 static HRESULT WINAPI
Widget_iface_in(IWidget
*iface
, IUnknown
*unk
, IDispatch
*disp
, ISomethingFromDispatch
*sfd
)
1263 check_iface_marshal(unk
, disp
, sfd
);
1264 else if (testmode
== 1)
1266 ok(!unk
, "Got iface %p.\n", unk
);
1267 ok(!disp
, "Got iface %p.\n", disp
);
1268 ok(!sfd
, "Got iface %p.\n", sfd
);
1273 static HRESULT WINAPI
Widget_iface_out(IWidget
*iface
, IUnknown
**unk
, IDispatch
**disp
, ISomethingFromDispatch
**sfd
)
1275 ok(!*unk
, "Got iface %p.\n", *unk
);
1276 ok(!*disp
, "Got iface %p.\n", *disp
);
1277 ok(!*sfd
, "Got iface %p.\n", *sfd
);
1281 *unk
= (IUnknown
*)create_disp_obj();
1282 *disp
= (IDispatch
*)create_disp_obj();
1283 *sfd
= create_disp_obj();
1288 static HRESULT WINAPI
Widget_iface_ptr(IWidget
*iface
, ISomethingFromDispatch
**in
,
1289 ISomethingFromDispatch
**out
, ISomethingFromDispatch
**in_out
)
1293 ok(!*out
, "Got [out] %p.\n", *out
);
1294 if (testmode
== 0 || testmode
== 1)
1296 hr
= ISomethingFromDispatch_anotherfn(*in
);
1297 ok(hr
== 0x01234567, "Got hr %#lx.\n", hr
);
1298 hr
= ISomethingFromDispatch_anotherfn(*in_out
);
1299 ok(hr
== 0x01234567, "Got hr %#lx.\n", hr
);
1304 *out
= create_disp_obj();
1305 ISomethingFromDispatch_Release(*in_out
);
1306 *in_out
= create_disp_obj();
1308 else if (testmode
== 2)
1310 ok(!*in
, "Got [in] %p.\n", *in
);
1311 ok(!*in_out
, "Got [in, out] %p.\n", *in_out
);
1312 *in_out
= create_disp_obj();
1314 else if (testmode
== 3)
1316 hr
= ISomethingFromDispatch_anotherfn(*in_out
);
1317 ok(hr
== 0x01234567, "Got hr %#lx.\n", hr
);
1318 ISomethingFromDispatch_Release(*in_out
);
1325 static HRESULT WINAPI
Widget_iface_noptr(IWidget
*iface
, IUnknown unk
, IDispatch disp
, ISomethingFromDispatch sfd
)
1327 check_iface_marshal((IUnknown
*)unk
.lpVtbl
, (IDispatch
*)disp
.lpVtbl
, (ISomethingFromDispatch
*)sfd
.lpVtbl
);
1331 static HRESULT WINAPI
Widget_bstr(IWidget
*iface
, BSTR in
, BSTR
*out
, BSTR
*in_ptr
, BSTR
*in_out
)
1337 len
= SysStringByteLen(in
);
1338 ok(len
== sizeof(test_bstr1
), "Got wrong length %u.\n", len
);
1339 ok(!memcmp(in
, test_bstr1
, len
), "Got string %s.\n", wine_dbgstr_wn(in
, len
/ sizeof(WCHAR
)));
1340 ok(!*out
, "Got unexpected output %p.\n", *out
);
1341 len
= SysStringLen(*in_ptr
);
1342 ok(len
== lstrlenW(test_bstr2
), "Got wrong length %u.\n", len
);
1343 ok(!memcmp(*in_ptr
, test_bstr2
, len
), "Got string %s.\n", wine_dbgstr_w(*in_ptr
));
1344 len
= SysStringLen(*in_out
);
1345 ok(len
== lstrlenW(test_bstr3
), "Got wrong length %u.\n", len
);
1346 ok(!memcmp(*in_out
, test_bstr3
, len
), "Got string %s.\n", wine_dbgstr_w(*in_out
));
1348 *out
= SysAllocString(test_bstr4
);
1349 in
[1] = (*in_ptr
)[1] = (*in_out
)[1] = 'X';
1351 else if (testmode
== 1)
1353 ok(!in
, "Got string %s.\n", wine_dbgstr_w(in
));
1354 ok(!*out
, "Got string %s.\n", wine_dbgstr_w(*out
));
1355 ok(!*in_ptr
, "Got string %s.\n", wine_dbgstr_w(*in_ptr
));
1356 ok(!*in_out
, "Got string %s.\n", wine_dbgstr_w(*in_out
));
1361 static HRESULT WINAPI
Widget_variant(IWidget
*iface
, VARIANT in
, VARIANT
*out
, VARIANT
*in_ptr
, VARIANT
*in_out
)
1363 ok(V_VT(&in
) == VT_CY
, "Got wrong type %#x.\n", V_VT(&in
));
1364 ok(V_CY(&in
).Hi
== 0xdababe && V_CY(&in
).Lo
== 0xdeadbeef,
1365 "Got wrong value %s.\n", wine_dbgstr_longlong(V_CY(&in
).int64
));
1368 ok(V_VT(out
) == VT_I4
, "Got wrong type %u.\n", V_VT(out
));
1369 ok(V_I4(out
) == 1, "Got wrong value %ld.\n", V_I4(out
));
1372 ok(V_VT(out
) == VT_EMPTY
, "Got wrong type %u.\n", V_VT(out
));
1373 ok(V_VT(in_ptr
) == VT_I4
, "Got wrong type %u.\n", V_VT(in_ptr
));
1374 ok(V_I4(in_ptr
) == -1, "Got wrong value %ld.\n", V_I4(in_ptr
));
1375 ok(V_VT(in_out
) == VT_BSTR
, "Got wrong type %u.\n", V_VT(in_out
));
1376 ok(!lstrcmpW(V_BSTR(in_out
), test_bstr2
), "Got wrong value %s.\n",
1377 wine_dbgstr_w(V_BSTR(in_out
)));
1383 V_VT(in_ptr
) = VT_I2
;
1385 VariantClear(in_out
);
1386 V_VT(in_out
) = VT_I1
;
1391 static SAFEARRAY
*make_safearray(ULONG len
)
1393 SAFEARRAY
*sa
= SafeArrayCreateVector(VT_I4
, 0, len
);
1396 SafeArrayAccessData(sa
, (void **)&data
);
1397 for (i
= 0; i
< len
; ++i
)
1399 SafeArrayUnaccessData(sa
);
1404 static void check_safearray(SAFEARRAY
*sa
, LONG expect
)
1409 hr
= SafeArrayGetUBound(sa
, 1, &len
);
1411 ok(hr
== S_OK
, "Got hr %#lx.\n", hr
);
1412 ok(len
== expect
, "Expected len %ld, got %ld.\n", expect
, len
);
1414 hr
= SafeArrayAccessData(sa
, (void **)&data
);
1415 ok(hr
== S_OK
, "Got hr %#lx.\n", hr
);
1417 for (i
= 0; i
< len
; ++i
)
1418 ok(data
[i
] == len
+ i
, "Expected data %ld at %ld, got %ld.\n", len
+ i
, i
, data
[i
]);
1420 SafeArrayUnaccessData(sa
);
1423 static HRESULT WINAPI
Widget_safearray(IWidget
*iface
, SAFEARRAY
*in
, SAFEARRAY
**out
, SAFEARRAY
**in_ptr
, SAFEARRAY
**in_out
)
1427 check_safearray(in
, 3);
1428 ok(!*out
, "Got array %p.\n", *out
);
1429 check_safearray(*in_ptr
, 7);
1430 check_safearray(*in_out
, 9);
1432 hr
= SafeArrayDestroy(*in_out
);
1433 ok(hr
== S_OK
, "Got hr %#lx.\n", hr
);
1435 *out
= make_safearray(4);
1436 *in_out
= make_safearray(6);
1441 static HRESULT WINAPI
Widget_mystruct(IWidget
*iface
, MYSTRUCT in
, MYSTRUCT
*out
, MYSTRUCT
*in_ptr
, MYSTRUCT
*in_out
)
1443 static const MYSTRUCT empty
= {0};
1444 ok(!memcmp(&in
, &test_mystruct1
, sizeof(in
)), "Structs didn't match.\n");
1445 ok(!memcmp(out
, &empty
, sizeof(*out
)), "Structs didn't match.\n");
1446 ok(!memcmp(in_ptr
, &test_mystruct3
, sizeof(*in_ptr
)), "Structs didn't match.\n");
1447 ok(!memcmp(in_out
, &test_mystruct4
, sizeof(*in_out
)), "Structs didn't match.\n");
1449 memcpy(out
, &test_mystruct5
, sizeof(*out
));
1450 memcpy(in_ptr
, &test_mystruct6
, sizeof(*in_ptr
));
1451 memcpy(in_out
, &test_mystruct7
, sizeof(*in_out
));
1455 static HRESULT WINAPI
Widget_mystruct_ptr_ptr(IWidget
*iface
, MYSTRUCT
**in
)
1457 ok(!memcmp(*in
, &test_mystruct1
, sizeof(**in
)), "Structs didn't match.\n");
1461 static HRESULT WINAPI
Widget_thin_struct(IWidget
*iface
, struct thin in
)
1463 ok(!memcmp(&in
, &test_thin_struct
, sizeof(in
)), "Structs didn't match.\n");
1467 static HRESULT WINAPI
Widget_rect(IWidget
*iface
, RECT in
, RECT
*out
, RECT
*in_ptr
, RECT
*in_out
)
1469 static const RECT empty
= {0};
1470 ok(EqualRect(&in
, &test_rect1
), "Rects didn't match.\n");
1471 ok(EqualRect(out
, &empty
), "Rects didn't match.\n");
1472 ok(EqualRect(in_ptr
, &test_rect3
), "Rects didn't match.\n");
1473 ok(EqualRect(in_out
, &test_rect4
), "Rects didn't match.\n");
1476 *in_ptr
= test_rect6
;
1477 *in_out
= test_rect7
;
1481 static HRESULT WINAPI
Widget_complex_struct(IWidget
*iface
, struct complex in
)
1485 ok(in
.c
== 98, "Got char %d.\n", in
.c
);
1486 ok(in
.i
== 76543, "Got int %d.\n", in
.i
);
1487 ok(*in
.pi
== 2, "Got int pointer %d.\n", *in
.pi
);
1488 ok(**in
.ppi
== 10, "Got int double pointer %d.\n", **in
.ppi
);
1489 hr
= ISomethingFromDispatch_anotherfn(in
.iface
);
1490 ok(hr
== 0x01234567, "Got wrong hr %#lx.\n", hr
);
1491 hr
= ISomethingFromDispatch_anotherfn(*in
.iface_ptr
);
1492 ok(hr
== 0x01234567, "Got wrong hr %#lx.\n", hr
);
1493 ok(!lstrcmpW(in
.bstr
, test_bstr2
), "Got string %s.\n", wine_dbgstr_w(in
.bstr
));
1494 ok(V_VT(&in
.var
) == VT_I4
, "Got wrong type %u.\n", V_VT(&in
.var
));
1495 ok(V_I4(&in
.var
) == 123, "Got wrong value %ld.\n", V_I4(&in
.var
));
1496 ok(!memcmp(&in
.mystruct
, &test_mystruct1
, sizeof(MYSTRUCT
)), "Structs didn't match.\n");
1497 ok(!memcmp(in
.arr
, test_array1
, sizeof(array_t
)), "Arrays didn't match.\n");
1498 ok(in
.myint
== 456, "Got int %d.\n", in
.myint
);
1503 static HRESULT WINAPI
Widget_array(IWidget
*iface
, array_t in
, array_t out
, array_t in_out
)
1505 static const array_t empty
= {0};
1506 ok(!memcmp(in
, test_array1
, sizeof(array_t
)), "Arrays didn't match.\n");
1507 ok(!memcmp(out
, empty
, sizeof(array_t
)), "Arrays didn't match.\n");
1508 ok(!memcmp(in_out
, test_array3
, sizeof(array_t
)), "Arrays didn't match.\n");
1510 memcpy(in
, test_array4
, sizeof(array_t
));
1511 memcpy(out
, test_array5
, sizeof(array_t
));
1512 memcpy(in_out
, test_array6
, sizeof(array_t
));
1517 static HRESULT WINAPI
Widget_variant_array(IWidget
*iface
, VARIANT in
[2], VARIANT out
[2], VARIANT in_out
[2])
1519 ok(V_VT(&in
[0]) == VT_I4
, "Got wrong type %u.\n", V_VT(&in
[0]));
1520 ok(V_I4(&in
[0]) == 1, "Got wrong value %ld.\n", V_I4(&in
[0]));
1521 ok(V_VT(&in
[1]) == (VT_BYREF
|VT_I4
), "Got wrong type %u.\n", V_VT(&in
[1]));
1522 ok(*V_I4REF(&in
[1]) == 2, "Got wrong value %ld.\n", *V_I4REF(&in
[1]));
1523 ok(V_VT(&out
[0]) == VT_EMPTY
, "Got wrong type %u.\n", V_VT(&out
[0]));
1524 ok(V_VT(&out
[1]) == VT_EMPTY
, "Got wrong type %u.\n", V_VT(&out
[1]));
1525 ok(V_VT(&in_out
[0]) == VT_I4
, "Got wrong type %u.\n", V_VT(&in_out
[0]));
1526 ok(V_I4(&in_out
[0]) == 5, "Got wrong type %u.\n", V_VT(&in_out
[0]));
1527 ok(V_VT(&in_out
[1]) == VT_BSTR
, "Got wrong type %u.\n", V_VT(&in_out
[1]));
1528 ok(!lstrcmpW(V_BSTR(&in_out
[1]), test_bstr1
), "Got wrong value %s.\n", wine_dbgstr_w(V_BSTR(&in
[1])));
1530 V_VT(&in
[0]) = VT_I1
; V_I1(&in
[0]) = 7;
1531 V_VT(&in
[1]) = VT_I1
; V_I1(&in
[1]) = 8;
1532 V_VT(&out
[0]) = VT_I1
; V_I1(&out
[0]) = 9;
1533 V_VT(&out
[1]) = VT_BSTR
; V_BSTR(&out
[1]) = SysAllocString(test_bstr2
);
1534 V_VT(&in_out
[0]) = VT_I1
; V_I1(&in_out
[0]) = 11;
1535 V_VT(&in_out
[1]) = VT_UNKNOWN
; V_UNKNOWN(&in_out
[1]) = (IUnknown
*)create_disp_obj();
1540 static HRESULT WINAPI
Widget_mystruct_array(IWidget
*iface
, MYSTRUCT in
[2])
1542 ok(!memcmp(&in
[0], &test_mystruct1
, sizeof(MYSTRUCT
)), "Structs didn't match.\n");
1543 ok(!memcmp(&in
[1], &test_mystruct2
, sizeof(MYSTRUCT
)), "Structs didn't match.\n");
1547 static HRESULT WINAPI
Widget_myint(IWidget
*iface
, myint_t val
, myint_t
*ptr
, myint_t
**ptr_ptr
)
1549 ok(val
== 123, "Got value %d.\n", val
);
1550 ok(*ptr
== 456, "Got single ptr ref %d.\n", *ptr
);
1551 ok(**ptr_ptr
== 789, "Got double ptr ref %d.\n", **ptr_ptr
);
1555 static HRESULT WINAPI
Widget_Coclass(IWidget
*iface
, Coclass1
*class1
, Coclass2
*class2
, Coclass3
*class3
)
1559 hr
= ICoclass1_test((ICoclass1
*)class1
);
1560 ok(hr
== 1, "Got hr %#lx.\n", hr
);
1562 hr
= ICoclass2_test((ICoclass2
*)class2
);
1563 ok(hr
== 2, "Got hr %#lx.\n", hr
);
1565 hr
= ICoclass1_test((ICoclass1
*)class3
);
1566 ok(hr
== 1, "Got hr %#lx.\n", hr
);
1571 static HRESULT WINAPI
Widget_Coclass_ptr(IWidget
*iface
, Coclass1
**in
, Coclass1
**out
, Coclass1
**in_out
)
1573 struct coclass_obj
*obj
;
1576 ok(!*out
, "Got [out] %p.\n", *out
);
1577 if (testmode
== 0 || testmode
== 1)
1579 hr
= ICoclass1_test((ICoclass1
*)*in
);
1580 ok(hr
== 1, "Got hr %#lx.\n", hr
);
1581 hr
= ICoclass1_test((ICoclass1
*)*in_out
);
1582 ok(hr
== 1, "Got hr %#lx.\n", hr
);
1587 obj
= create_coclass_obj();
1588 *out
= (Coclass1
*)&obj
->ICoclass1_iface
;
1590 ICoclass1_Release((ICoclass1
*)*in_out
);
1591 obj
= create_coclass_obj();
1592 *in_out
= (Coclass1
*)&obj
->ICoclass1_iface
;
1594 else if (testmode
== 2)
1596 ok(!*in_out
, "Got [in, out] %p.\n", *in_out
);
1597 obj
= create_coclass_obj();
1598 *in_out
= (Coclass1
*)&obj
->ICoclass1_iface
;
1600 else if (testmode
== 3)
1602 hr
= ICoclass1_test((ICoclass1
*)*in_out
);
1603 ok(hr
== 1, "Got hr %#lx.\n", hr
);
1604 ICoclass1_Release((ICoclass1
*)*in_out
);
1611 static HRESULT WINAPI
Widget_Coclass_noptr(IWidget
*iface
, Coclass1 class1
, Coclass2 class2
, Coclass3 class3
)
1615 hr
= ICoclass1_test(class1
.iface
);
1616 ok(hr
== 1, "Got hr %#lx.\n", hr
);
1618 hr
= ICoclass2_test(class2
.iface
);
1619 ok(hr
== 2, "Got hr %#lx.\n", hr
);
1621 hr
= ICoclass1_test(class3
.iface
);
1622 ok(hr
== 1, "Got hr %#lx.\n", hr
);
1627 static HRESULT WINAPI
Widget_no_in_out(IWidget
*iface
, BSTR str
, int i
)
1629 ok(SysStringLen(str
) == 4, "unexpected len\n");
1630 ok(!lstrcmpW(str
, L
"test"), "unexpected str %s\n", wine_dbgstr_w(str
));
1631 ok(i
== 5, "i = %d\n", i
);
1635 static const struct IWidgetVtbl Widget_VTable
=
1637 Widget_QueryInterface
,
1640 Widget_GetTypeInfoCount
,
1642 Widget_GetIDsOfNames
,
1653 Widget_CloneDispatch
,
1654 Widget_CloneCoclass
,
1656 Widget_VariantArrayPtr
,
1659 Widget_CloneInterface
,
1660 Widget_put_prop_with_lcid
,
1661 Widget_get_prop_with_lcid
,
1662 Widget_get_prop_int
,
1663 Widget_get_prop_uint
,
1665 Widget_put_prop_opt_arg
,
1666 Widget_put_prop_req_arg
,
1667 Widget_pos_restrict
,
1668 Widget_neg_restrict
,
1670 Widget_VarArg_Ref_Run
,
1671 Widget_basetypes_in
,
1672 Widget_basetypes_out
,
1675 Widget_long_ptr_ptr
,
1684 Widget_mystruct_ptr_ptr
,
1687 Widget_complex_struct
,
1689 Widget_variant_array
,
1690 Widget_mystruct_array
,
1694 Widget_Coclass_noptr
,
1698 static HRESULT WINAPI
StaticWidget_QueryInterface(IStaticWidget
*iface
, REFIID riid
, void **ppvObject
)
1700 if (IsEqualIID(riid
, &IID_IStaticWidget
) || IsEqualIID(riid
, &IID_IUnknown
) || IsEqualIID(riid
, &IID_IDispatch
))
1702 IStaticWidget_AddRef(iface
);
1708 return E_NOINTERFACE
;
1711 static ULONG WINAPI
StaticWidget_AddRef(IStaticWidget
*iface
)
1716 static ULONG WINAPI
StaticWidget_Release(IStaticWidget
*iface
)
1721 static HRESULT WINAPI
StaticWidget_GetTypeInfoCount(IStaticWidget
*iface
, UINT
*pctinfo
)
1723 ok(0, "unexpected call\n");
1727 static HRESULT WINAPI
StaticWidget_GetTypeInfo(IStaticWidget
*iface
, UINT iTInfo
, LCID lcid
,
1728 ITypeInfo
**ppTInfo
)
1730 ok(0, "unexpected call\n");
1734 static HRESULT WINAPI
StaticWidget_GetIDsOfNames(IStaticWidget
*iface
, REFIID riid
, LPOLESTR
*rgszNames
,
1735 UINT cNames
, LCID lcid
, DISPID
*rgDispId
)
1737 ok(0, "unexpected call\n");
1741 static HRESULT WINAPI
StaticWidget_Invoke(IStaticWidget
*iface
, DISPID dispIdMember
, REFIID riid
,
1742 LCID lcid
, WORD wFlags
, DISPPARAMS
*pDispParams
, VARIANT
*pVarResult
, EXCEPINFO
*pExcepInfo
,
1745 ok(0, "unexpected call\n");
1749 static HRESULT WINAPI
StaticWidget_TestDual(IStaticWidget
*iface
, ItestDual
*p
)
1751 trace("TestDual()\n");
1752 ok(p
== &TestDual
, "wrong ItestDual\n");
1756 static HRESULT WINAPI
StaticWidget_TestSecondIface(IStaticWidget
*iface
, ITestSecondIface
*p
)
1758 trace("TestSecondIface()\n");
1759 ok(p
== &TestSecondIface
, "wrong ItestSecondIface\n");
1763 static const IStaticWidgetVtbl StaticWidgetVtbl
= {
1764 StaticWidget_QueryInterface
,
1765 StaticWidget_AddRef
,
1766 StaticWidget_Release
,
1767 StaticWidget_GetTypeInfoCount
,
1768 StaticWidget_GetTypeInfo
,
1769 StaticWidget_GetIDsOfNames
,
1770 StaticWidget_Invoke
,
1771 StaticWidget_TestDual
,
1772 StaticWidget_TestSecondIface
1775 static IStaticWidget StaticWidget
= { &StaticWidgetVtbl
};
1777 typedef struct KindaEnum
1779 IKindaEnumWidget IKindaEnumWidget_iface
;
1783 static inline KindaEnum
*impl_from_IKindaEnumWidget(IKindaEnumWidget
*iface
)
1785 return CONTAINING_RECORD(iface
, KindaEnum
, IKindaEnumWidget_iface
);
1788 static HRESULT
register_current_module_typelib(void)
1790 WCHAR path
[MAX_PATH
];
1791 CHAR pathA
[MAX_PATH
];
1795 GetModuleFileNameA(NULL
, pathA
, MAX_PATH
);
1796 MultiByteToWideChar(CP_ACP
, 0, pathA
, -1, path
, MAX_PATH
);
1798 hr
= LoadTypeLib(path
, &typelib
);
1801 hr
= RegisterTypeLib(typelib
, path
, NULL
);
1802 ITypeLib_Release(typelib
);
1807 static ITypeInfo
*get_type_info(REFIID riid
)
1809 ITypeInfo
*pTypeInfo
;
1813 hr
= LoadRegTypeLib(&LIBID_TestTypelib
, 2, 5, LOCALE_NEUTRAL
, &pTypeLib
);
1814 ok_ole_success(hr
, LoadRegTypeLib
);
1818 hr
= ITypeLib_GetTypeInfoOfGuid(pTypeLib
, riid
, &pTypeInfo
);
1819 ITypeLib_Release(pTypeLib
);
1820 ok_ole_success(hr
, ITypeLib_GetTypeInfoOfGuid
);
1827 static IWidget
*Widget_Create(void)
1830 ITypeInfo
*pTypeInfo
;
1831 HRESULT hr
= E_FAIL
;
1833 pTypeInfo
= get_type_info(&IID_IWidget
);
1837 This
= HeapAlloc(GetProcessHeap(), 0, sizeof(*This
));
1838 This
->IWidget_iface
.lpVtbl
= &Widget_VTable
;
1840 This
->pDispatchUnknown
= NULL
;
1842 hr
= CreateStdDispatch((IUnknown
*)&This
->IWidget_iface
, This
, pTypeInfo
,
1843 &This
->pDispatchUnknown
);
1844 ok_ole_success(hr
, CreateStdDispatch
);
1845 ITypeInfo_Release(pTypeInfo
);
1848 return &This
->IWidget_iface
;
1851 HeapFree(GetProcessHeap(), 0, This
);
1856 static HRESULT WINAPI
KindaEnum_QueryInterface(
1857 IKindaEnumWidget
*iface
,
1858 /* [in] */ REFIID riid
,
1859 /* [iid_is][out] */ void __RPC_FAR
*__RPC_FAR
*ppvObject
)
1861 if (IsEqualIID(riid
, &IID_IKindaEnumWidget
) || IsEqualIID(riid
, &IID_IUnknown
))
1863 IKindaEnumWidget_AddRef(iface
);
1870 return E_NOINTERFACE
;
1874 static ULONG WINAPI
KindaEnum_AddRef(
1875 IKindaEnumWidget
*iface
)
1877 KindaEnum
*This
= impl_from_IKindaEnumWidget(iface
);
1879 return InterlockedIncrement(&This
->refs
);
1882 static ULONG WINAPI
KindaEnum_Release(
1883 IKindaEnumWidget
*iface
)
1885 KindaEnum
*This
= impl_from_IKindaEnumWidget(iface
);
1886 ULONG refs
= InterlockedDecrement(&This
->refs
);
1889 memset(This
, 0xcc, sizeof(*This
));
1890 HeapFree(GetProcessHeap(), 0, This
);
1891 trace("KindaEnumWidget destroyed!\n");
1897 static HRESULT WINAPI
KindaEnum_Next(
1898 IKindaEnumWidget
*iface
,
1899 /* [out] */ IWidget __RPC_FAR
*__RPC_FAR
*widget
)
1901 *widget
= Widget_Create();
1905 return E_OUTOFMEMORY
;
1908 static HRESULT WINAPI
KindaEnum_Count(
1909 IKindaEnumWidget
*iface
,
1910 /* [out] */ ULONG __RPC_FAR
*count
)
1915 static HRESULT WINAPI
KindaEnum_Reset(
1916 IKindaEnumWidget
*iface
)
1921 static HRESULT WINAPI
KindaEnum_Clone(
1922 IKindaEnumWidget
*iface
,
1923 /* [out] */ IKindaEnumWidget __RPC_FAR
*__RPC_FAR
*ppenum
)
1928 static const IKindaEnumWidgetVtbl KindaEnumWidget_VTable
=
1930 KindaEnum_QueryInterface
,
1939 static IKindaEnumWidget
*KindaEnumWidget_Create(void)
1943 This
= HeapAlloc(GetProcessHeap(), 0, sizeof(*This
));
1944 if (!This
) return NULL
;
1945 This
->IKindaEnumWidget_iface
.lpVtbl
= &KindaEnumWidget_VTable
;
1947 return &This
->IKindaEnumWidget_iface
;
1950 static HRESULT WINAPI
NonOleAutomation_QueryInterface(INonOleAutomation
*iface
, REFIID riid
, void **ppv
)
1952 if (IsEqualIID(riid
, &IID_IUnknown
) || IsEqualIID(riid
, &IID_INonOleAutomation
))
1954 *(INonOleAutomation
**)ppv
= iface
;
1958 return E_NOINTERFACE
;
1961 static ULONG WINAPI
NonOleAutomation_AddRef(INonOleAutomation
*iface
)
1966 static ULONG WINAPI
NonOleAutomation_Release(INonOleAutomation
*iface
)
1971 static BSTR WINAPI
NonOleAutomation_BstrRet(INonOleAutomation
*iface
)
1973 static const WCHAR wszTestString
[] = {'T','h','i','s',' ','i','s',' ','a',' ','t','e','s','t',' ','s','t','r','i','n','g',0};
1974 return SysAllocString(wszTestString
);
1977 static HRESULT WINAPI
NonOleAutomation_Error(INonOleAutomation
*iface
)
1982 static INonOleAutomationVtbl NonOleAutomation_VTable
=
1984 NonOleAutomation_QueryInterface
,
1985 NonOleAutomation_AddRef
,
1986 NonOleAutomation_Release
,
1987 NonOleAutomation_BstrRet
,
1988 NonOleAutomation_Error
1991 static INonOleAutomation NonOleAutomation
= { &NonOleAutomation_VTable
};
1993 static ITypeInfo
*NonOleAutomation_GetTypeInfo(void)
1996 HRESULT hr
= LoadRegTypeLib(&LIBID_TestTypelib
, 2, 5, LOCALE_NEUTRAL
, &pTypeLib
);
1997 ok_ole_success(hr
, LoadRegTypeLib
);
2000 ITypeInfo
*pTypeInfo
;
2001 hr
= ITypeLib_GetTypeInfoOfGuid(pTypeLib
, &IID_INonOleAutomation
, &pTypeInfo
);
2002 ok_ole_success(hr
, ITypeLib_GetTypeInfoOfGuid
);
2003 ITypeLib_Release(pTypeLib
);
2009 static void test_marshal_basetypes(IWidget
*widget
, IDispatch
*disp
)
2012 DISPPARAMS dispparams
= {arg
, NULL
, ARRAY_SIZE(arg
), 0};
2028 V_VT(&arg
[10]) = VT_I1
; V_I1(&arg
[10]) = 5;
2029 V_VT(&arg
[9]) = VT_I2
; V_I2(&arg
[9]) = -123;
2030 V_VT(&arg
[8]) = VT_I4
; V_I4(&arg
[8]) = -100000;
2031 V_VT(&arg
[7]) = VT_I8
; V_I8(&arg
[7]) = (LONGLONG
)-100000 * 1000000;
2032 V_VT(&arg
[6]) = VT_UI1
; V_UI1(&arg
[6]) = 0;
2033 V_VT(&arg
[5]) = VT_UI2
; V_UI2(&arg
[5]) = 456;
2034 V_VT(&arg
[4]) = VT_UI4
; V_UI4(&arg
[4]) = 0xdeadbeef;
2035 V_VT(&arg
[3]) = VT_UI8
; V_UI8(&arg
[3]) = (ULONGLONG
)1234567890 * 9876543210;
2036 V_VT(&arg
[2]) = VT_R4
; V_R4(&arg
[2]) = M_PI
;
2037 V_VT(&arg
[1]) = VT_R8
; V_R8(&arg
[1]) = M_E
;
2038 V_VT(&arg
[0]) = VT_I4
; V_I4(&arg
[0]) = STATE_WIDGETIFIED
;
2039 hr
= IDispatch_Invoke(disp
, DISPID_TM_BASETYPES_IN
, &IID_NULL
, LOCALE_NEUTRAL
,
2040 DISPATCH_METHOD
, &dispparams
, NULL
, NULL
, NULL
);
2041 ok(hr
== S_OK
, "Got hr %#lx.\n", hr
);
2043 hr
= IWidget_basetypes_in(widget
, 5, -123, -100000, (LONGLONG
)-100000 * 1000000, 0, 456,
2044 0xdeadbeef, (ULONGLONG
)1234567890 * 9876543210, M_PI
, M_E
, STATE_WIDGETIFIED
);
2045 ok(hr
== S_OK
, "Got hr %#lx.\n", hr
);
2047 c
= s
= l
= h
= uc
= us
= ul
= uh
= f
= d
= st
= 0;
2049 V_VT(&arg
[10]) = VT_BYREF
|VT_I1
; V_I1REF(&arg
[10]) = &c
;
2050 V_VT(&arg
[9]) = VT_BYREF
|VT_I2
; V_I2REF(&arg
[9]) = &s
;
2051 V_VT(&arg
[8]) = VT_BYREF
|VT_I4
; V_I4REF(&arg
[8]) = &l
;
2052 V_VT(&arg
[7]) = VT_BYREF
|VT_I8
; V_I8REF(&arg
[7]) = &h
;
2053 V_VT(&arg
[6]) = VT_BYREF
|VT_UI1
; V_UI1REF(&arg
[6]) = &uc
;
2054 V_VT(&arg
[5]) = VT_BYREF
|VT_UI2
; V_UI2REF(&arg
[5]) = &us
;
2055 V_VT(&arg
[4]) = VT_BYREF
|VT_UI4
; V_UI4REF(&arg
[4]) = &ul
;
2056 V_VT(&arg
[3]) = VT_BYREF
|VT_UI8
; V_UI8REF(&arg
[3]) = &uh
;
2057 V_VT(&arg
[2]) = VT_BYREF
|VT_R4
; V_R4REF(&arg
[2]) = &f
;
2058 V_VT(&arg
[1]) = VT_BYREF
|VT_R8
; V_R8REF(&arg
[1]) = &d
;
2059 V_VT(&arg
[0]) = VT_BYREF
|VT_I4
; V_I4REF(&arg
[0]) = (LONG
*)&st
;
2060 hr
= IDispatch_Invoke(disp
, DISPID_TM_BASETYPES_OUT
, &IID_NULL
, LOCALE_NEUTRAL
,
2061 DISPATCH_METHOD
, &dispparams
, NULL
, NULL
, NULL
);
2062 ok(hr
== S_OK
, "Got hr %#lx.\n", hr
);
2063 ok(c
== 10, "Got char %d.\n", c
);
2064 ok(s
== -321, "Got short %d.\n", s
);
2065 ok(l
== -200000, "Got int %ld.\n", l
);
2066 ok(h
== (LONGLONG
)-200000 * 1000000L, "Got hyper %s.\n", wine_dbgstr_longlong(h
));
2067 ok(uc
== 254, "Got unsigned char %u.\n", uc
);
2068 ok(us
== 256, "Got unsigned short %u.\n", us
);
2069 ok(ul
== 0xf00dfade, "Got unsigned int %li.\n", ul
);
2070 ok(uh
== 0xabcdef0123456789ull
, "Got unsigned hyper %s.\n", wine_dbgstr_longlong(uh
));
2071 ok(f
== (float)M_LN2
, "Got float %f.\n", f
);
2072 ok(d
== M_LN10
, "Got double %f.\n", d
);
2073 ok(st
== STATE_UNWIDGETIFIED
, "Got state %u.\n", st
);
2075 c
= s
= l
= h
= uc
= us
= ul
= uh
= f
= d
= st
= 0;
2077 hr
= IWidget_basetypes_out(widget
, &c
, &s
, &l
, &h
, &uc
, &us
, &ul
, &uh
, &f
, &d
, &st
);
2078 ok(hr
== S_OK
, "Got hr %#lx.\n", hr
);
2079 ok(c
== 10, "Got char %d.\n", c
);
2080 ok(s
== -321, "Got short %d.\n", s
);
2081 ok(l
== -200000, "Got int %ld.\n", l
);
2082 ok(h
== (LONGLONG
)-200000 * 1000000L, "Got hyper %s.\n", wine_dbgstr_longlong(h
));
2083 ok(uc
== 254, "Got unsigned char %u.\n", uc
);
2084 ok(us
== 256, "Got unsigned short %u.\n", us
);
2085 ok(ul
== 0xf00dfade, "Got unsigned int %li.\n", ul
);
2086 ok(uh
== 0xabcdef0123456789ull
, "Got unsigned hyper %s.\n", wine_dbgstr_longlong(uh
));
2087 ok(f
== (float)M_LN2
, "Got float %f.\n", f
);
2088 ok(d
== M_LN10
, "Got double %f.\n", d
);
2089 ok(st
== STATE_UNWIDGETIFIED
, "Got state %u.\n", st
);
2091 /* Test marshalling of public typedefs. */
2096 hr
= IWidget_myint(widget
, 123, &i
, &pi
);
2097 ok(hr
== S_OK
, "Got hr %#lx.\n", hr
);
2099 /* Test that different float ABIs are correctly handled. */
2101 hr
= IWidget_float_abi(widget
, 1.0f
, 2.0, 3, 4.0f
, 5.0);
2102 ok(hr
== S_OK
, "Got hr %#lx.\n", hr
);
2105 static void test_marshal_pointer(IWidget
*widget
, IDispatch
*disp
)
2108 DISPPARAMS dispparams
= {arg
, NULL
, ARRAY_SIZE(arg
), 0};
2109 LONG in
, out
, in_out
, *in_ptr
, *out_ptr
, *in_out_ptr
;
2117 V_VT(&arg
[2]) = VT_BYREF
|VT_I4
; V_I4REF(&arg
[2]) = &in
;
2118 V_VT(&arg
[1]) = VT_BYREF
|VT_I4
; V_I4REF(&arg
[1]) = &out
;
2119 V_VT(&arg
[0]) = VT_BYREF
|VT_I4
; V_I4REF(&arg
[0]) = &in_out
;
2120 hr
= IDispatch_Invoke(disp
, DISPID_TM_INT_PTR
, &IID_NULL
, LOCALE_NEUTRAL
,
2121 DISPATCH_METHOD
, &dispparams
, NULL
, NULL
, NULL
);
2122 ok(hr
== S_OK
, "Got hr %#lx.\n", hr
);
2123 ok(in
== 987, "Got [in] %ld.\n", in
);
2124 ok(out
== 654, "Got [out] %ld.\n", out
);
2125 ok(in_out
== 321, "Got [in, out] %ld.\n", in_out
);
2132 hr
= IWidget_long_ptr(widget
, &in
, &out
, &in_out
);
2133 ok(hr
== S_OK
, "Got hr %#lx.\n", hr
);
2134 ok(in
== 123, "Got [in] %ld.\n", in
);
2135 ok(out
== 654, "Got [out] %ld.\n", out
);
2136 ok(in_out
== 321, "Got [in, out] %ld.\n", in_out
);
2139 hr
= IWidget_long_ptr(widget
, NULL
, &out
, &in_out
);
2140 ok(hr
== HRESULT_FROM_WIN32(RPC_X_NULL_REF_POINTER
), "Got hr %#lx.\n", hr
);
2141 ok(!out
, "[out] parameter should have been cleared.\n");
2142 ok(in_out
== -1, "[in, out] parameter should not have been cleared.\n");
2145 hr
= IWidget_long_ptr(widget
, &in
, NULL
, &in_out
);
2146 ok(hr
== HRESULT_FROM_WIN32(RPC_X_NULL_REF_POINTER
), "Got hr %#lx.\n", hr
);
2147 ok(in
== -1, "[in] parameter should not have been cleared.\n");
2148 ok(in_out
== -1, "[in, out] parameter should not have been cleared.\n");
2151 hr
= IWidget_long_ptr(widget
, &in
, &out
, NULL
);
2152 ok(hr
== HRESULT_FROM_WIN32(RPC_X_NULL_REF_POINTER
), "Got hr %#lx.\n", hr
);
2153 ok(in
== -1, "[in] parameter should not have been cleared.\n");
2154 ok(!out
, "[out] parameter should have been cleared.\n");
2156 /* We can't test Invoke() with double pointers, as it is not possible to fit
2157 * more than one level of indirection into a VARIANTARG. */
2160 in_ptr
= out_ptr
= in_out_ptr
= NULL
;
2161 hr
= IWidget_long_ptr_ptr(widget
, &in_ptr
, &out_ptr
, &in_out_ptr
);
2162 ok(hr
== S_OK
, "Got hr %#lx\n", hr
);
2163 ok(!in_ptr
, "Got [in] %p.\n", in_ptr
);
2164 ok(!out_ptr
, "Got [out] %p.\n", out_ptr
);
2165 ok(!in_out_ptr
, "Got [in, out] %p.\n", in_out_ptr
);
2168 hr
= IWidget_long_ptr_ptr(widget
, &in_ptr
, &out_ptr
, &in_out_ptr
);
2169 ok(hr
== S_OK
, "Got hr %#lx\n", hr
);
2170 ok(*out_ptr
== 654, "Got [out] %ld.\n", *out_ptr
);
2171 ok(*in_out_ptr
== 321, "Got [in, out] %ld.\n", *in_out_ptr
);
2172 CoTaskMemFree(out_ptr
);
2173 CoTaskMemFree(in_out_ptr
);
2181 in_out_ptr
= &in_out
;
2182 hr
= IWidget_long_ptr_ptr(widget
, &in_ptr
, &out_ptr
, &in_out_ptr
);
2183 ok(hr
== S_OK
, "Got hr %#lx.\n", hr
);
2184 ok(out_ptr
!= &out
, "[out] ptr should have changed.\n");
2185 ok(in_out_ptr
== &in_out
, "[in, out] ptr should not have changed.\n");
2186 ok(*out_ptr
== 654, "Got [out] %ld.\n", *out_ptr
);
2187 ok(*in_out_ptr
== 321, "Got [in, out] %ld.\n", *in_out_ptr
);
2190 in_ptr
= out_ptr
= NULL
;
2192 in_out_ptr
= &in_out
;
2193 hr
= IWidget_long_ptr_ptr(widget
, &in_ptr
, &out_ptr
, &in_out_ptr
);
2194 ok(hr
== S_OK
, "Got hr %#lx.\n", hr
);
2195 ok(!in_out_ptr
, "Got [in, out] %p.\n", in_out_ptr
);
2198 in_out_ptr
= &in_out
;
2199 hr
= IWidget_long_ptr_ptr(widget
, NULL
, &out_ptr
, &in_out_ptr
);
2200 ok(hr
== HRESULT_FROM_WIN32(RPC_X_NULL_REF_POINTER
), "Got hr %#lx.\n", hr
);
2201 ok(!out_ptr
, "[out] parameter should have been cleared.\n");
2202 ok(in_out_ptr
== &in_out
, "[in, out] parameter should not have been cleared.\n");
2205 in_out_ptr
= &in_out
;
2206 hr
= IWidget_long_ptr_ptr(widget
, &in_ptr
, NULL
, &in_out_ptr
);
2207 ok(hr
== HRESULT_FROM_WIN32(RPC_X_NULL_REF_POINTER
), "Got hr %#lx.\n", hr
);
2208 ok(in_ptr
== &in
, "[in] parameter should not have been cleared.\n");
2209 ok(in_out_ptr
== &in_out
, "[in, out] parameter should not have been cleared.\n");
2213 hr
= IWidget_long_ptr_ptr(widget
, &in_ptr
, &out_ptr
, NULL
);
2214 ok(hr
== HRESULT_FROM_WIN32(RPC_X_NULL_REF_POINTER
), "Got hr %#lx.\n", hr
);
2215 ok(in_ptr
== &in
, "[in] parameter should not have been cleared.\n");
2216 ok(!out_ptr
, "[out] parameter should have been cleared.\n");
2219 static void test_marshal_iface(IWidget
*widget
, IDispatch
*disp
)
2222 DISPPARAMS dispparams
= {arg
, NULL
, ARRAY_SIZE(arg
), 0};
2223 ISomethingFromDispatch
*sfd1
, *sfd2
, *sfd3
, *proxy_sfd
, *sfd_in
, *sfd_out
, *sfd_in_out
;
2224 IUnknown
*proxy_unk
, *proxy_unk2
, *unk_in
, *unk_out
, *unk_in_out
;
2225 IDispatch
*proxy_disp
;
2227 IDispatch disp_noptr
;
2228 ISomethingFromDispatch sfd_noptr
;
2232 sfd1
= create_disp_obj();
2233 sfd2
= create_disp_obj();
2234 sfd3
= create_disp_obj();
2235 hr
= IWidget_iface_in(widget
, (IUnknown
*)sfd1
,
2236 (IDispatch
*)sfd2
, sfd3
);
2237 ok(hr
== S_OK
, "Got hr %#lx.\n", hr
);
2238 release_iface(sfd1
);
2239 release_iface(sfd2
);
2240 release_iface(sfd3
);
2243 hr
= IWidget_iface_in(widget
, NULL
, NULL
, NULL
);
2244 ok(hr
== S_OK
, "Got hr %#lx.\n", hr
);
2247 proxy_unk
= (IUnknown
*)0xdeadbeef;
2248 proxy_disp
= (IDispatch
*)0xdeadbeef;
2249 proxy_sfd
= (ISomethingFromDispatch
*)0xdeadbeef;
2250 hr
= IWidget_iface_out(widget
, &proxy_unk
, &proxy_disp
, &proxy_sfd
);
2251 ok(hr
== S_OK
, "Got hr %#lx.\n", hr
);
2252 check_iface_marshal(proxy_unk
, proxy_disp
, proxy_sfd
);
2253 release_iface(proxy_unk
);
2254 release_iface(proxy_disp
);
2255 release_iface(proxy_sfd
);
2258 hr
= IWidget_iface_out(widget
, &proxy_unk
, &proxy_disp
, &proxy_sfd
);
2259 ok(hr
== S_OK
, "Got hr %#lx.\n", hr
);
2260 ok(!proxy_unk
, "Got unexpected proxy %p.\n", proxy_unk
);
2261 ok(!proxy_disp
, "Got unexpected proxy %p.\n", proxy_disp
);
2262 ok(!proxy_sfd
, "Got unexpected proxy %p.\n", proxy_sfd
);
2265 sfd_in
= sfd1
= create_disp_obj();
2266 sfd_out
= sfd2
= create_disp_obj();
2267 sfd_in_out
= sfd3
= create_disp_obj();
2268 hr
= IWidget_iface_ptr(widget
, &sfd_in
, &sfd_out
, &sfd_in_out
);
2269 ok(hr
== S_OK
, "Got hr %#lx.\n", hr
);
2270 ok(sfd_in
== sfd1
, "[in] parameter should not have changed.\n");
2271 ok(!sfd_out
, "[out] parameter should have been cleared.\n");
2272 ok(sfd_in_out
== sfd3
, "[in, out] parameter should not have changed.\n");
2273 release_iface(sfd1
);
2274 release_iface(sfd2
);
2275 release_iface(sfd3
);
2278 sfd_in
= sfd1
= create_disp_obj();
2279 sfd_in_out
= sfd3
= create_disp_obj();
2280 ISomethingFromDispatch_AddRef(sfd_in_out
);
2281 hr
= IWidget_iface_ptr(widget
, &sfd_in
, &sfd_out
, &sfd_in_out
);
2282 ok(hr
== S_OK
, "Got hr %#lx.\n", hr
);
2283 hr
= ISomethingFromDispatch_anotherfn(sfd_out
);
2284 ok(hr
== 0x01234567, "Got hr %#lx.\n", hr
);
2285 ok(sfd_in_out
!= sfd3
, "[in, out] parameter should have changed.\n");
2286 hr
= ISomethingFromDispatch_anotherfn(sfd_in_out
);
2287 ok(hr
== 0x01234567, "Got hr %#lx.\n", hr
);
2288 release_iface(sfd_out
);
2289 release_iface(sfd_in_out
);
2290 release_iface(sfd1
);
2291 release_iface(sfd3
);
2294 sfd_in
= sfd_out
= sfd_in_out
= NULL
;
2295 hr
= IWidget_iface_ptr(widget
, &sfd_in
, &sfd_out
, &sfd_in_out
);
2296 ok(hr
== S_OK
, "Got hr %#lx.\n", hr
);
2297 ok(!sfd_out
, "[out] parameter should not have been set.\n");
2298 hr
= ISomethingFromDispatch_anotherfn(sfd_in_out
);
2299 ok(hr
== 0x01234567, "Got hr %#lx.\n", hr
);
2300 release_iface(sfd_in_out
);
2303 sfd_in
= sfd_out
= NULL
;
2304 sfd_in_out
= sfd3
= create_disp_obj();
2305 ISomethingFromDispatch_AddRef(sfd_in_out
);
2306 hr
= IWidget_iface_ptr(widget
, &sfd_in
, &sfd_out
, &sfd_in_out
);
2307 ok(hr
== S_OK
, "Got hr %#lx.\n", hr
);
2308 ok(!sfd_in_out
, "Got [in, out] %p.\n", sfd_in_out
);
2309 release_iface(sfd3
);
2311 sfd1
= create_disp_obj();
2312 sfd2
= create_disp_obj();
2313 sfd3
= create_disp_obj();
2314 unk_noptr
.lpVtbl
= (IUnknownVtbl
*)sfd1
;
2315 disp_noptr
.lpVtbl
= (IDispatchVtbl
*)sfd2
;
2316 sfd_noptr
.lpVtbl
= (ISomethingFromDispatchVtbl
*)sfd3
;
2317 hr
= IWidget_iface_noptr(widget
, unk_noptr
, disp_noptr
, sfd_noptr
);
2318 ok(hr
== S_OK
, "Got hr %#lx.\n", hr
);
2319 release_iface(sfd1
);
2320 release_iface(sfd2
);
2321 release_iface(sfd3
);
2323 /* Test with Invoke(). Note that since we pass VT_UNKNOWN, we don't get our
2324 * interface back, but rather an IUnknown. */
2327 sfd1
= create_disp_obj();
2328 sfd2
= create_disp_obj();
2329 sfd3
= create_disp_obj();
2331 V_VT(&arg
[2]) = VT_UNKNOWN
; V_UNKNOWN(&arg
[2]) = (IUnknown
*)sfd1
;
2332 V_VT(&arg
[1]) = VT_UNKNOWN
; V_UNKNOWN(&arg
[1]) = (IUnknown
*)sfd2
;
2333 V_VT(&arg
[0]) = VT_UNKNOWN
; V_UNKNOWN(&arg
[0]) = (IUnknown
*)sfd3
;
2334 hr
= IDispatch_Invoke(disp
, DISPID_TM_IFACE_IN
, &IID_NULL
, LOCALE_NEUTRAL
,
2335 DISPATCH_METHOD
, &dispparams
, NULL
, NULL
, NULL
);
2336 ok(hr
== S_OK
, "Got hr %#lx.\n", hr
);
2338 V_VT(&arg
[2]) = VT_DISPATCH
; V_DISPATCH(&arg
[2]) = (IDispatch
*)sfd1
;
2339 V_VT(&arg
[1]) = VT_DISPATCH
; V_DISPATCH(&arg
[1]) = (IDispatch
*)sfd2
;
2340 V_VT(&arg
[0]) = VT_DISPATCH
; V_DISPATCH(&arg
[0]) = (IDispatch
*)sfd3
;
2341 hr
= IDispatch_Invoke(disp
, DISPID_TM_IFACE_IN
, &IID_NULL
, LOCALE_NEUTRAL
,
2342 DISPATCH_METHOD
, &dispparams
, NULL
, NULL
, NULL
);
2343 ok(hr
== S_OK
, "Got hr %#lx.\n", hr
);
2345 release_iface(sfd1
);
2346 release_iface(sfd2
);
2347 release_iface(sfd3
);
2350 V_VT(&arg
[2]) = VT_UNKNOWN
; V_UNKNOWN(&arg
[2]) = NULL
;
2351 V_VT(&arg
[1]) = VT_UNKNOWN
; V_UNKNOWN(&arg
[1]) = NULL
;
2352 V_VT(&arg
[0]) = VT_UNKNOWN
; V_UNKNOWN(&arg
[0]) = NULL
;
2353 hr
= IDispatch_Invoke(disp
, DISPID_TM_IFACE_IN
, &IID_NULL
, LOCALE_NEUTRAL
,
2354 DISPATCH_METHOD
, &dispparams
, NULL
, NULL
, NULL
);
2355 ok(hr
== S_OK
, "Got hr %#lx.\n", hr
);
2358 proxy_unk
= proxy_unk2
= NULL
;
2360 V_VT(&arg
[2]) = VT_UNKNOWN
|VT_BYREF
; V_UNKNOWNREF(&arg
[2]) = &proxy_unk
;
2361 V_VT(&arg
[1]) = VT_DISPATCH
|VT_BYREF
; V_DISPATCHREF(&arg
[1]) = &proxy_disp
;
2362 V_VT(&arg
[0]) = VT_UNKNOWN
|VT_BYREF
; V_UNKNOWNREF(&arg
[0]) = &proxy_unk2
;
2363 hr
= IDispatch_Invoke(disp
, DISPID_TM_IFACE_OUT
, &IID_NULL
, LOCALE_NEUTRAL
,
2364 DISPATCH_METHOD
, &dispparams
, NULL
, NULL
, NULL
);
2366 ok(hr
== S_OK
, "Got hr %#lx.\n", hr
);
2368 hr
= IUnknown_QueryInterface(proxy_unk2
, &IID_ISomethingFromDispatch
, (void **)&proxy_sfd
);
2369 ok(hr
== S_OK
, "Got hr %#lx.\n", hr
);
2370 check_iface_marshal(proxy_unk
, proxy_disp
, proxy_sfd
);
2371 ISomethingFromDispatch_Release(proxy_sfd
);
2372 release_iface(proxy_unk
);
2373 release_iface(proxy_disp
);
2374 release_iface(proxy_unk2
);
2378 proxy_unk
= proxy_unk2
= NULL
;
2380 hr
= IDispatch_Invoke(disp
, DISPID_TM_IFACE_OUT
, &IID_NULL
, LOCALE_NEUTRAL
,
2381 DISPATCH_METHOD
, &dispparams
, NULL
, NULL
, NULL
);
2383 ok(hr
== S_OK
, "Got hr %#lx.\n", hr
);
2384 ok(!proxy_unk
, "Got unexpected proxy %p.\n", proxy_unk
);
2385 ok(!proxy_disp
, "Got unexpected proxy %p.\n", proxy_disp
);
2386 ok(!proxy_unk2
, "Got unexpected proxy %p.\n", proxy_unk2
);
2389 sfd1
= create_disp_obj();
2390 sfd3
= create_disp_obj();
2391 unk_in
= (IUnknown
*)sfd1
;
2393 unk_in_out
= (IUnknown
*)sfd3
;
2394 V_VT(&arg
[2]) = VT_UNKNOWN
|VT_BYREF
; V_UNKNOWNREF(&arg
[2]) = &unk_in
;
2395 V_VT(&arg
[1]) = VT_UNKNOWN
|VT_BYREF
; V_UNKNOWNREF(&arg
[1]) = &unk_out
;
2396 V_VT(&arg
[0]) = VT_UNKNOWN
|VT_BYREF
; V_UNKNOWNREF(&arg
[0]) = &unk_in_out
;
2397 hr
= IDispatch_Invoke(disp
, DISPID_TM_IFACE_PTR
, &IID_NULL
, LOCALE_NEUTRAL
,
2398 DISPATCH_METHOD
, &dispparams
, NULL
, NULL
, NULL
);
2400 ok(hr
== S_OK
, "Got hr %#lx.\n", hr
);
2401 ok(unk_in
== (IUnknown
*)sfd1
, "[in] parameter should not have changed.\n");
2402 ok(!unk_out
, "[out] parameter should have been cleared.\n");
2403 ok(unk_in_out
== (IUnknown
*)sfd3
, "[in, out] parameter should not have changed.\n");
2404 release_iface(sfd1
);
2405 release_iface(sfd3
);
2408 sfd1
= create_disp_obj();
2409 sfd3
= create_disp_obj();
2410 unk_in
= (IUnknown
*)sfd1
;
2412 unk_in_out
= (IUnknown
*)sfd3
;
2413 IUnknown_AddRef(unk_in_out
);
2414 hr
= IDispatch_Invoke(disp
, DISPID_TM_IFACE_PTR
, &IID_NULL
, LOCALE_NEUTRAL
,
2415 DISPATCH_METHOD
, &dispparams
, NULL
, NULL
, NULL
);
2417 ok(hr
== S_OK
, "Got hr %#lx.\n", hr
);
2420 hr
= IUnknown_QueryInterface(unk_out
, &IID_ISomethingFromDispatch
, (void **)&sfd_out
);
2421 ok(hr
== S_OK
, "Got hr %#lx.\n", hr
);
2422 hr
= ISomethingFromDispatch_anotherfn(sfd_out
);
2423 ok(hr
== 0x01234567, "Got hr %#lx.\n", hr
);
2424 ISomethingFromDispatch_Release(sfd_out
);
2426 ok(unk_in_out
!= (IUnknown
*)sfd3
, "[in, out] parameter should have changed.\n");
2427 hr
= IUnknown_QueryInterface(unk_in_out
, &IID_ISomethingFromDispatch
, (void **)&sfd_in_out
);
2428 ok(hr
== S_OK
, "Got hr %#lx.\n", hr
);
2429 hr
= ISomethingFromDispatch_anotherfn(sfd_in_out
);
2430 ok(hr
== 0x01234567, "Got hr %#lx.\n", hr
);
2431 ISomethingFromDispatch_Release(sfd_in_out
);
2433 release_iface(unk_out
);
2434 release_iface(unk_in_out
);
2436 release_iface(sfd1
);
2438 release_iface(sfd3
);
2441 unk_in
= unk_out
= unk_in_out
= NULL
;
2442 hr
= IDispatch_Invoke(disp
, DISPID_TM_IFACE_PTR
, &IID_NULL
, LOCALE_NEUTRAL
,
2443 DISPATCH_METHOD
, &dispparams
, NULL
, NULL
, NULL
);
2445 ok(hr
== S_OK
, "Got hr %#lx.\n", hr
);
2447 ok(!unk_out
, "[out] parameter should not have been set.\n");
2449 hr
= IUnknown_QueryInterface(unk_in_out
, &IID_ISomethingFromDispatch
, (void **)&sfd_in_out
);
2450 ok(hr
== S_OK
, "Got hr %#lx.\n", hr
);
2451 hr
= ISomethingFromDispatch_anotherfn(sfd_in_out
);
2452 ok(hr
== 0x01234567, "Got hr %#lx.\n", hr
);
2453 ISomethingFromDispatch_Release(sfd_in_out
);
2455 release_iface(unk_in_out
);
2459 unk_in
= unk_out
= NULL
;
2460 sfd3
= create_disp_obj();
2461 unk_in_out
= (IUnknown
*)sfd3
;
2462 IUnknown_AddRef(unk_in_out
);
2463 hr
= IDispatch_Invoke(disp
, DISPID_TM_IFACE_PTR
, &IID_NULL
, LOCALE_NEUTRAL
,
2464 DISPATCH_METHOD
, &dispparams
, NULL
, NULL
, NULL
);
2466 ok(hr
== S_OK
, "Got hr %#lx.\n", hr
);
2467 ok(!unk_in_out
, "[in, out] parameter should have been cleared.\n");
2468 release_iface(sfd3
);
2472 static void test_marshal_bstr(IWidget
*widget
, IDispatch
*disp
)
2475 DISPPARAMS dispparams
= {arg
, NULL
, ARRAY_SIZE(arg
), 0};
2476 BSTR in
, out
, in_ptr
, in_out
;
2481 in
= SysAllocStringLen(test_bstr1
, ARRAY_SIZE(test_bstr1
));
2483 in_ptr
= SysAllocString(test_bstr2
);
2484 in_out
= SysAllocString(test_bstr3
);
2486 V_VT(&arg
[3]) = VT_BSTR
; V_BSTR(&arg
[3]) = in
;
2487 V_VT(&arg
[2]) = VT_BSTR
|VT_BYREF
; V_BSTRREF(&arg
[2]) = &out
;
2488 V_VT(&arg
[1]) = VT_BSTR
|VT_BYREF
; V_BSTRREF(&arg
[1]) = &in_ptr
;
2489 V_VT(&arg
[0]) = VT_BSTR
|VT_BYREF
; V_BSTRREF(&arg
[0]) = &in_out
;
2490 hr
= IDispatch_Invoke(disp
, DISPID_TM_BSTR
, &IID_NULL
, LOCALE_NEUTRAL
,
2491 DISPATCH_METHOD
, &dispparams
, NULL
, NULL
, NULL
);
2492 ok(hr
== S_OK
, "Got hr %#lx.\n", hr
);
2493 ok(in
[1] == test_bstr1
[1], "[in] parameter should not be changed.\n");
2494 ok(in_ptr
[1] == 'X', "[in] pointer should be changed.\n");
2495 ok(in_out
[1] == 'X', "[in, out] parameter should be changed.\n");
2496 len
= SysStringLen(out
);
2497 ok(len
== lstrlenW(test_bstr4
), "Got wrong length %d.\n", len
);
2498 ok(!memcmp(out
, test_bstr4
, len
), "Got string %s.\n", wine_dbgstr_wn(out
, len
));
2500 in
[1] = test_bstr1
[1];
2501 in_ptr
[1] = test_bstr2
[1];
2502 in_out
[1] = test_bstr3
[1];
2504 out
= (BSTR
)0xdeadbeef;
2505 hr
= IWidget_bstr(widget
, in
, &out
, &in_ptr
, &in_out
);
2506 ok(hr
== S_OK
, "Got hr %#lx.\n", hr
);
2507 ok(in
[1] == test_bstr1
[1], "[in] parameter should not be changed.\n");
2508 ok(in_ptr
[1] == test_bstr2
[1], "[in] pointer should not be changed.\n");
2509 ok(in_out
[1] == 'X', "[in, out] parameter should be changed.\n");
2510 len
= SysStringLen(out
);
2511 ok(len
== lstrlenW(test_bstr4
), "Got wrong length %d.\n", len
);
2512 ok(!memcmp(out
, test_bstr4
, len
), "Got string %s.\n", wine_dbgstr_wn(out
, len
));
2515 SysFreeString(in_ptr
);
2516 SysFreeString(in_out
);
2519 out
= in_ptr
= in_out
= NULL
;
2520 hr
= IWidget_bstr(widget
, NULL
, &out
, &in_ptr
, &in_out
);
2521 ok(hr
== S_OK
, "Got hr %#lx.\n", hr
);
2523 in
= SysAllocString(L
"test");
2524 hr
= IWidget_no_in_out(widget
, in
, 5);
2525 ok(hr
== S_OK
, "Got hr %#lx.\n", hr
);
2528 static void test_marshal_variant(IWidget
*widget
, IDispatch
*disp
)
2531 DISPPARAMS dispparams
= {arg
, NULL
, ARRAY_SIZE(arg
), 0};
2532 VARIANT out
, in_ptr
, in_out
;
2539 V_VT(&in_ptr
) = VT_I4
;
2541 V_VT(&in_out
) = VT_BSTR
;
2542 V_BSTR(&in_out
) = bstr
= SysAllocString(test_bstr2
);
2544 V_VT(&arg
[3]) = VT_CY
;
2545 V_CY(&arg
[3]).Hi
= 0xdababe;
2546 V_CY(&arg
[3]).Lo
= 0xdeadbeef;
2547 V_VT(&arg
[2]) = VT_VARIANT
|VT_BYREF
; V_VARIANTREF(&arg
[2]) = &out
;
2548 V_VT(&arg
[1]) = VT_VARIANT
|VT_BYREF
; V_VARIANTREF(&arg
[1]) = &in_ptr
;
2549 V_VT(&arg
[0]) = VT_VARIANT
|VT_BYREF
; V_VARIANTREF(&arg
[0]) = &in_out
;
2550 hr
= IDispatch_Invoke(disp
, DISPID_TM_VARIANT
, &IID_NULL
, LOCALE_NEUTRAL
,
2551 DISPATCH_METHOD
, &dispparams
, NULL
, NULL
, NULL
);
2552 ok(hr
== S_OK
, "Got hr %#lx.\n", hr
);
2553 ok(V_VT(&arg
[3]) == VT_CY
, "Got wrong type %u.\n", V_VT(&arg
[3]));
2554 ok(V_VT(&out
) == VT_UI1
, "Got wrong type %u.\n", V_VT(&out
));
2555 ok(V_UI1(&out
) == 3, "Got wrong value %d.\n", V_UI1(&out
));
2557 ok(V_VT(&in_ptr
) == VT_I2
, "Got wrong type %u.\n", V_VT(&in_ptr
));
2558 ok(V_I2(&in_ptr
) == 4, "Got wrong value %d.\n", V_I1(&in_ptr
));
2559 ok(V_VT(&in_out
) == VT_I1
, "Got wrong type %u.\n", V_VT(&in_out
));
2560 ok(V_I1(&in_out
) == 5, "Got wrong value %d.\n", V_I1(&in_out
));
2565 V_VT(&in_ptr
) = VT_I4
;
2567 V_VT(&in_out
) = VT_BSTR
;
2568 V_BSTR(&in_out
) = bstr
= SysAllocString(test_bstr2
);
2569 hr
= IWidget_variant(widget
, arg
[3], &out
, &in_ptr
, &in_out
);
2570 ok(hr
== S_OK
, "Got hr %#lx.\n", hr
);
2571 ok(V_VT(&arg
[3]) == VT_CY
, "Got wrong type %u.\n", V_VT(&arg
[3]));
2572 ok(V_VT(&out
) == VT_UI1
, "Got wrong type %u.\n", V_VT(&out
));
2573 ok(V_UI1(&out
) == 3, "Got wrong value %d.\n", V_UI1(&out
));
2574 ok(V_VT(&in_ptr
) == VT_I4
, "Got wrong type %u.\n", V_VT(&in_ptr
));
2575 ok(V_I2(&in_ptr
) == -1, "Got wrong value %d.\n", V_I1(&in_ptr
));
2576 ok(V_VT(&in_out
) == VT_I1
, "Got wrong type %u.\n", V_VT(&in_out
));
2577 ok(V_I1(&in_out
) == 5, "Got wrong value %d.\n", V_I1(&in_out
));
2580 static void test_marshal_safearray(IWidget
*widget
, IDispatch
*disp
)
2582 SAFEARRAY
*in
, *out
, *out2
, *in_ptr
, *in_out
;
2585 in
= make_safearray(3);
2586 out
= out2
= make_safearray(5);
2587 in_ptr
= make_safearray(7);
2588 in_out
= make_safearray(9);
2589 hr
= IWidget_safearray(widget
, in
, &out
, &in_ptr
, &in_out
);
2590 ok(hr
== S_OK
, "Got hr %#lx.\n", hr
);
2591 check_safearray(in
, 3);
2592 check_safearray(out
, 4);
2593 check_safearray(out2
, 5);
2594 check_safearray(in_ptr
, 7);
2595 check_safearray(in_out
, 6);
2597 SafeArrayDestroy(in
);
2598 SafeArrayDestroy(out
);
2599 SafeArrayDestroy(out2
);
2600 SafeArrayDestroy(in_ptr
);
2601 SafeArrayDestroy(in_out
);
2604 static void test_marshal_struct(IWidget
*widget
, IDispatch
*disp
)
2606 MYSTRUCT out
, in_ptr
, in_out
, *in_ptr_ptr
;
2607 RECT rect_out
, rect_in_ptr
, rect_in_out
;
2608 ISomethingFromDispatch
*sfd
;
2609 struct complex complex;
2610 int i
, i2
, *pi
= &i2
;
2613 memcpy(&out
, &test_mystruct2
, sizeof(MYSTRUCT
));
2614 memcpy(&in_ptr
, &test_mystruct3
, sizeof(MYSTRUCT
));
2615 memcpy(&in_out
, &test_mystruct4
, sizeof(MYSTRUCT
));
2616 hr
= IWidget_mystruct(widget
, test_mystruct1
, &out
, &in_ptr
, &in_out
);
2617 ok(hr
== S_OK
, "Got hr %#lx.\n", hr
);
2618 ok(!memcmp(&out
, &test_mystruct5
, sizeof(MYSTRUCT
)), "Structs didn't match.\n");
2619 ok(!memcmp(&in_ptr
, &test_mystruct3
, sizeof(MYSTRUCT
)), "Structs didn't match.\n");
2620 ok(!memcmp(&in_out
, &test_mystruct7
, sizeof(MYSTRUCT
)), "Structs didn't match.\n");
2622 memcpy(&in_ptr
, &test_mystruct1
, sizeof(MYSTRUCT
));
2623 in_ptr_ptr
= &in_ptr
;
2624 hr
= IWidget_mystruct_ptr_ptr(widget
, &in_ptr_ptr
);
2625 ok(hr
== S_OK
, "Got hr %#lx.\n", hr
);
2627 /* Make sure that "thin" structs (<=8 bytes) are handled correctly in x86-64. */
2629 hr
= IWidget_thin_struct(widget
, test_thin_struct
);
2630 ok(hr
== S_OK
, "Got hr %#lx.\n", hr
);
2632 /* Make sure we can handle an imported type. */
2634 rect_out
= test_rect2
;
2635 rect_in_ptr
= test_rect3
;
2636 rect_in_out
= test_rect4
;
2637 hr
= IWidget_rect(widget
, test_rect1
, &rect_out
, &rect_in_ptr
, &rect_in_out
);
2638 ok(hr
== S_OK
, "Got hr %#lx.\n", hr
);
2639 ok(EqualRect(&rect_out
, &test_rect5
), "Rects didn't match.\n");
2640 ok(EqualRect(&rect_in_ptr
, &test_rect3
), "Rects didn't match.\n");
2641 ok(EqualRect(&rect_in_out
, &test_rect7
), "Rects didn't match.\n");
2643 /* Test complex structs. */
2650 complex.iface
= create_disp_obj();
2651 sfd
= create_disp_obj();
2652 complex.iface_ptr
= &sfd
;
2653 complex.bstr
= SysAllocString(test_bstr2
);
2654 V_VT(&complex.var
) = VT_I4
;
2655 V_I4(&complex.var
) = 123;
2656 memcpy(&complex.mystruct
, &test_mystruct1
, sizeof(MYSTRUCT
));
2657 memcpy(complex.arr
, test_array1
, sizeof(array_t
));
2658 complex.myint
= 456;
2659 hr
= IWidget_complex_struct(widget
, complex);
2660 ok(hr
== S_OK
, "Got hr %#lx.\n", hr
);
2663 static void test_marshal_array(IWidget
*widget
, IDispatch
*disp
)
2665 VARIANT var_in
[2], var_out
[2], var_in_out
[2];
2666 ISomethingFromDispatch
*proxy_sfd
;
2667 array_t in
, out
, in_out
;
2668 MYSTRUCT struct_in
[2];
2672 memcpy(in
, test_array1
, sizeof(array_t
));
2673 memcpy(out
, test_array2
, sizeof(array_t
));
2674 memcpy(in_out
, test_array3
, sizeof(array_t
));
2675 hr
= IWidget_array(widget
, in
, out
, in_out
);
2676 ok(hr
== S_OK
, "Got hr %#lx.\n", hr
);
2677 ok(!memcmp(&in
, &test_array1
, sizeof(array_t
)), "Arrays didn't match.\n");
2678 ok(!memcmp(&out
, &test_array5
, sizeof(array_t
)), "Arrays didn't match.\n");
2679 ok(!memcmp(&in_out
, &test_array6
, sizeof(array_t
)), "Arrays didn't match.\n");
2681 V_VT(&var_in
[0]) = VT_I4
; V_I4(&var_in
[0]) = 1;
2682 V_VT(&var_in
[1]) = VT_BYREF
|VT_I4
; V_I4REF(&var_in
[1]) = &l
;
2683 V_VT(&var_out
[0]) = VT_I4
; V_I4(&var_out
[0]) = 3;
2684 V_VT(&var_out
[1]) = VT_I4
; V_I4(&var_out
[1]) = 4;
2685 V_VT(&var_in_out
[0]) = VT_I4
; V_I4(&var_in_out
[0]) = 5;
2686 V_VT(&var_in_out
[1]) = VT_BSTR
; V_BSTR(&var_in_out
[1]) = SysAllocString(test_bstr1
);
2687 hr
= IWidget_variant_array(widget
, var_in
, var_out
, var_in_out
);
2688 ok(hr
== S_OK
, "Got hr %#lx.\n", hr
);
2689 ok(V_VT(&var_in
[0]) == VT_I4
, "Got wrong type %u.\n", V_VT(&var_in
[0]));
2690 ok(V_I4(&var_in
[0]) == 1, "Got wrong value %ld.\n", V_I4(&var_in
[0]));
2691 ok(V_VT(&var_in
[1]) == (VT_BYREF
|VT_I4
), "Got wrong type %u.\n", V_VT(&var_in
[1]));
2692 ok(V_I4REF(&var_in
[1]) == &l
, "Got wrong value %p.\n", V_I4REF(&var_in
[1]));
2693 ok(l
== 2, "Got wrong value %ld.\n", l
);
2694 ok(V_VT(&var_out
[0]) == VT_I1
, "Got wrong type %u.\n", V_VT(&var_out
[0]));
2695 ok(V_I1(&var_out
[0]) == 9, "Got wrong value %u.\n", V_VT(&var_out
[0]));
2696 ok(V_VT(&var_out
[1]) == VT_BSTR
, "Got wrong type %u.\n", V_VT(&var_out
[1]));
2697 ok(!lstrcmpW(V_BSTR(&var_out
[1]), test_bstr2
), "Got wrong value %s.\n", wine_dbgstr_w(V_BSTR(&var_out
[1])));
2698 ok(V_VT(&var_in_out
[0]) == VT_I1
, "Got wrong type %u.\n", V_VT(&var_in_out
[0]));
2699 ok(V_I1(&var_in_out
[0]) == 11, "Got wrong value %u.\n", V_VT(&var_in_out
[0]));
2700 ok(V_VT(&var_in_out
[1]) == VT_UNKNOWN
, "Got wrong type %u.\n", V_VT(&var_in_out
[1]));
2701 hr
= IUnknown_QueryInterface(V_UNKNOWN(&var_in_out
[1]), &IID_ISomethingFromDispatch
, (void **)&proxy_sfd
);
2702 ok(hr
== S_OK
, "Got hr %#lx.\n", hr
);
2703 hr
= ISomethingFromDispatch_anotherfn(proxy_sfd
);
2704 ok(hr
== 0x01234567, "Got hr %#lx.\n", hr
);
2705 ISomethingFromDispatch_Release(proxy_sfd
);
2706 release_iface(V_UNKNOWN(&var_in_out
[1]));
2708 memcpy(&struct_in
[0], &test_mystruct1
, sizeof(MYSTRUCT
));
2709 memcpy(&struct_in
[1], &test_mystruct2
, sizeof(MYSTRUCT
));
2710 hr
= IWidget_mystruct_array(widget
, struct_in
);
2711 ok(hr
== S_OK
, "Got hr %#lx.\n", hr
);
2714 static void test_marshal_coclass(IWidget
*widget
, IDispatch
*disp
)
2717 DISPPARAMS dispparams
= {arg
, NULL
, ARRAY_SIZE(arg
), 0};
2718 struct coclass_obj
*class1
, *class2
, *class3
;
2719 IUnknown
*unk_in
, *unk_out
, *unk_in_out
;
2720 ICoclass1
*in
, *out
, *in_out
;
2721 Coclass1 class1_noptr
;
2722 Coclass2 class2_noptr
;
2723 Coclass3 class3_noptr
;
2726 class1
= create_coclass_obj();
2727 class2
= create_coclass_obj();
2728 class3
= create_coclass_obj();
2730 hr
= IWidget_Coclass(widget
, (Coclass1
*)&class1
->ICoclass1_iface
,
2731 (Coclass2
*)&class2
->ICoclass1_iface
, (Coclass3
*)&class3
->ICoclass1_iface
);
2732 ok(hr
== S_OK
, "Got hr %#lx.\n", hr
);
2734 hr
= IWidget_Coclass(widget
, (Coclass1
*)&class1
->ICoclass2_iface
,
2735 (Coclass2
*)&class2
->ICoclass2_iface
, (Coclass3
*)&class3
->ICoclass2_iface
);
2736 ok(hr
== S_OK
, "Got hr %#lx.\n", hr
);
2738 release_iface(&class1
->ICoclass1_iface
);
2739 release_iface(&class2
->ICoclass1_iface
);
2740 release_iface(&class3
->ICoclass1_iface
);
2743 class1
= create_coclass_obj();
2744 class2
= create_coclass_obj();
2745 class3
= create_coclass_obj();
2746 in
= &class1
->ICoclass1_iface
;
2747 out
= &class2
->ICoclass1_iface
;
2748 in_out
= &class3
->ICoclass1_iface
;
2749 hr
= IWidget_Coclass_ptr(widget
, (Coclass1
**)&in
, (Coclass1
**)&out
, (Coclass1
**)&in_out
);
2750 ok(hr
== S_OK
, "Got hr %#lx.\n", hr
);
2751 ok(in
== &class1
->ICoclass1_iface
, "[in] parameter should not have changed.\n");
2752 ok(!out
, "[out] parameter should have been cleared.\n");
2753 ok(in_out
== &class3
->ICoclass1_iface
, "[in, out] parameter should not have changed.\n");
2754 release_iface(&class1
->ICoclass1_iface
);
2755 release_iface(&class2
->ICoclass1_iface
);
2756 release_iface(&class3
->ICoclass1_iface
);
2759 class1
= create_coclass_obj();
2760 class3
= create_coclass_obj();
2761 in
= &class1
->ICoclass1_iface
;
2762 in_out
= &class3
->ICoclass1_iface
;
2763 ICoclass1_AddRef(in_out
);
2764 hr
= IWidget_Coclass_ptr(widget
, (Coclass1
**)&in
,
2765 (Coclass1
**)&out
, (Coclass1
**)&in_out
);
2766 ok(hr
== S_OK
, "Got hr %#lx.\n", hr
);
2767 hr
= ICoclass1_test(out
);
2768 ok(hr
== 1, "Got hr %#lx.\n", hr
);
2769 ok(in_out
!= &class3
->ICoclass1_iface
, "[in, out] parameter should have changed.\n");
2770 hr
= ICoclass1_test(in_out
);
2771 ok(hr
== 1, "Got hr %#lx.\n", hr
);
2773 release_iface(in_out
);
2774 release_iface(&class1
->ICoclass1_iface
);
2775 release_iface(&class3
->ICoclass1_iface
);
2778 in
= out
= in_out
= NULL
;
2779 hr
= IWidget_Coclass_ptr(widget
, (Coclass1
**)&in
,
2780 (Coclass1
**)&out
, (Coclass1
**)&in_out
);
2781 ok(hr
== S_OK
, "Got hr %#lx.\n", hr
);
2782 hr
= ICoclass1_test(in_out
);
2783 ok(hr
== 1, "Got hr %#lx.\n", hr
);
2784 release_iface(in_out
);
2788 class3
= create_coclass_obj();
2789 in_out
= &class3
->ICoclass1_iface
;
2790 hr
= IWidget_Coclass_ptr(widget
, (Coclass1
**)&in
,
2791 (Coclass1
**)&out
, (Coclass1
**)&in_out
);
2792 ok(hr
== S_OK
, "Got hr %#lx.\n", hr
);
2793 ok(!in_out
, "Got [in, out] %p.\n", in_out
);
2795 class1
= create_coclass_obj();
2796 class2
= create_coclass_obj();
2797 class3
= create_coclass_obj();
2798 class1_noptr
.iface
= &class1
->ICoclass1_iface
;
2799 class2_noptr
.iface
= &class2
->ICoclass2_iface
;
2800 class3_noptr
.iface
= &class3
->ICoclass1_iface
;
2801 hr
= IWidget_Coclass_noptr(widget
, class1_noptr
, class2_noptr
, class3_noptr
);
2802 ok(hr
== S_OK
, "Got hr %#lx.\n", hr
);
2803 release_iface(&class1
->ICoclass1_iface
);
2804 release_iface(&class2
->ICoclass1_iface
);
2805 release_iface(&class3
->ICoclass1_iface
);
2807 /* Test with Invoke(). Note that since we pass VT_UNKNOWN, we don't get our
2808 * interface back, but rather an IUnknown. */
2810 class1
= create_coclass_obj();
2811 class2
= create_coclass_obj();
2812 class3
= create_coclass_obj();
2814 V_VT(&arg
[2]) = VT_UNKNOWN
; V_UNKNOWN(&arg
[2]) = (IUnknown
*)&class1
->ICoclass1_iface
;
2815 V_VT(&arg
[1]) = VT_UNKNOWN
; V_UNKNOWN(&arg
[1]) = (IUnknown
*)&class2
->ICoclass1_iface
;
2816 V_VT(&arg
[0]) = VT_UNKNOWN
; V_UNKNOWN(&arg
[0]) = (IUnknown
*)&class3
->ICoclass1_iface
;
2817 hr
= IDispatch_Invoke(disp
, DISPID_TM_COCLASS
, &IID_NULL
, LOCALE_NEUTRAL
,
2818 DISPATCH_METHOD
, &dispparams
, NULL
, NULL
, NULL
);
2819 ok(hr
== S_OK
, "Got hr %#lx.\n", hr
);
2821 V_VT(&arg
[2]) = VT_UNKNOWN
; V_UNKNOWN(&arg
[2]) = (IUnknown
*)&class1
->ICoclass2_iface
;
2822 V_VT(&arg
[1]) = VT_UNKNOWN
; V_UNKNOWN(&arg
[1]) = (IUnknown
*)&class2
->ICoclass2_iface
;
2823 V_VT(&arg
[0]) = VT_UNKNOWN
; V_UNKNOWN(&arg
[0]) = (IUnknown
*)&class3
->ICoclass2_iface
;
2824 hr
= IDispatch_Invoke(disp
, DISPID_TM_COCLASS
, &IID_NULL
, LOCALE_NEUTRAL
,
2825 DISPATCH_METHOD
, &dispparams
, NULL
, NULL
, NULL
);
2826 ok(hr
== S_OK
, "Got hr %#lx.\n", hr
);
2828 V_VT(&arg
[2]) = VT_DISPATCH
; V_DISPATCH(&arg
[2]) = (IDispatch
*)&class1
->ICoclass1_iface
;
2829 V_VT(&arg
[1]) = VT_DISPATCH
; V_DISPATCH(&arg
[1]) = (IDispatch
*)&class2
->ICoclass1_iface
;
2830 V_VT(&arg
[0]) = VT_DISPATCH
; V_DISPATCH(&arg
[0]) = (IDispatch
*)&class3
->ICoclass1_iface
;
2831 hr
= IDispatch_Invoke(disp
, DISPID_TM_COCLASS
, &IID_NULL
, LOCALE_NEUTRAL
,
2832 DISPATCH_METHOD
, &dispparams
, NULL
, NULL
, NULL
);
2833 ok(hr
== S_OK
, "Got hr %#lx.\n", hr
);
2835 release_iface(&class1
->ICoclass1_iface
);
2836 release_iface(&class2
->ICoclass1_iface
);
2837 release_iface(&class3
->ICoclass1_iface
);
2840 class1
= create_coclass_obj();
2841 class3
= create_coclass_obj();
2842 unk_in
= (IUnknown
*)&class1
->ICoclass1_iface
;
2844 unk_in_out
= (IUnknown
*)&class3
->ICoclass1_iface
;
2845 V_VT(&arg
[2]) = VT_UNKNOWN
|VT_BYREF
; V_UNKNOWNREF(&arg
[2]) = &unk_in
;
2846 V_VT(&arg
[1]) = VT_UNKNOWN
|VT_BYREF
; V_UNKNOWNREF(&arg
[1]) = &unk_out
;
2847 V_VT(&arg
[0]) = VT_UNKNOWN
|VT_BYREF
; V_UNKNOWNREF(&arg
[0]) = &unk_in_out
;
2848 hr
= IDispatch_Invoke(disp
, DISPID_TM_COCLASS_PTR
, &IID_NULL
, LOCALE_NEUTRAL
,
2849 DISPATCH_METHOD
, &dispparams
, NULL
, NULL
, NULL
);
2851 ok(hr
== S_OK
, "Got hr %#lx.\n", hr
);
2852 ok(unk_in
== (IUnknown
*)&class1
->ICoclass1_iface
, "[in] parameter should not have changed.\n");
2853 ok(!unk_out
, "[out] parameter should have been cleared.\n");
2854 ok(unk_in_out
== (IUnknown
*)&class3
->ICoclass1_iface
, "[in, out] parameter should not have changed.\n");
2855 release_iface(&class1
->ICoclass1_iface
);
2856 release_iface(&class3
->ICoclass1_iface
);
2859 class1
= create_coclass_obj();
2860 class3
= create_coclass_obj();
2861 unk_in
= (IUnknown
*)&class1
->ICoclass1_iface
;
2863 unk_in_out
= (IUnknown
*)&class3
->ICoclass1_iface
;
2864 IUnknown_AddRef(unk_in_out
);
2865 hr
= IDispatch_Invoke(disp
, DISPID_TM_COCLASS_PTR
, &IID_NULL
, LOCALE_NEUTRAL
,
2866 DISPATCH_METHOD
, &dispparams
, NULL
, NULL
, NULL
);
2868 ok(hr
== S_OK
, "Got hr %#lx.\n", hr
);
2871 hr
= IUnknown_QueryInterface(unk_out
, &IID_ICoclass1
, (void **)&out
);
2872 ok(hr
== S_OK
, "Got hr %#lx.\n", hr
);
2873 hr
= ICoclass1_test(out
);
2874 ok(hr
== 1, "Got hr %#lx.\n", hr
);
2875 ICoclass1_Release(out
);
2877 ok(unk_in_out
!= (IUnknown
*)&class3
->ICoclass1_iface
, "[in, out] parameter should have changed.\n");
2878 hr
= IUnknown_QueryInterface(unk_in_out
, &IID_ICoclass1
, (void **)&in_out
);
2879 ok(hr
== S_OK
, "Got hr %#lx.\n", hr
);
2880 hr
= ICoclass1_test(in_out
);
2881 ok(hr
== 1, "Got hr %#lx.\n", hr
);
2882 ICoclass1_Release(in_out
);
2884 release_iface(unk_out
);
2885 release_iface(unk_in_out
);
2887 release_iface(&class1
->ICoclass1_iface
);
2889 release_iface(&class3
->ICoclass1_iface
);
2892 unk_in
= unk_out
= unk_in_out
= NULL
;
2893 hr
= IDispatch_Invoke(disp
, DISPID_TM_COCLASS_PTR
, &IID_NULL
, LOCALE_NEUTRAL
,
2894 DISPATCH_METHOD
, &dispparams
, NULL
, NULL
, NULL
);
2896 ok(hr
== S_OK
, "Got hr %#lx.\n", hr
);
2898 ok(!unk_out
, "[out] parameter should not have been set.\n");
2900 hr
= IUnknown_QueryInterface(unk_in_out
, &IID_ICoclass1
, (void **)&in_out
);
2901 ok(hr
== S_OK
, "Got hr %#lx.\n", hr
);
2902 hr
= ICoclass1_test(in_out
);
2903 ok(hr
== 1, "Got hr %#lx.\n", hr
);
2904 ICoclass1_Release(in_out
);
2906 release_iface(unk_in_out
);
2910 unk_in
= unk_out
= NULL
;
2911 class3
= create_coclass_obj();
2912 unk_in_out
= (IUnknown
*)&class3
->ICoclass1_iface
;
2913 IUnknown_AddRef(unk_in_out
);
2914 hr
= IDispatch_Invoke(disp
, DISPID_TM_COCLASS_PTR
, &IID_NULL
, LOCALE_NEUTRAL
,
2915 DISPATCH_METHOD
, &dispparams
, NULL
, NULL
, NULL
);
2917 ok(hr
== S_OK
, "Got hr %#lx.\n", hr
);
2919 ok(!unk_in_out
, "[in, out] parameter should have been cleared.\n");
2922 release_iface(&class3
->ICoclass1_iface
);
2925 static void test_typelibmarshal(void)
2927 static const WCHAR szCat
[] = { 'C','a','t',0 };
2928 static const WCHAR szTestTest
[] = { 'T','e','s','t','T','e','s','t',0 };
2929 static const WCHAR szSuperman
[] = { 'S','u','p','e','r','m','a','n',0 };
2931 IKindaEnumWidget
*pKEW
= KindaEnumWidget_Create();
2934 IDispatch
*pDispatch
;
2935 static const LARGE_INTEGER ullZero
;
2936 EXCEPINFO excepinfo
;
2938 DISPID dispidNamed
= DISPID_PROPERTYPUT
;
2939 DISPPARAMS dispparams
;
2940 VARIANTARG vararg
[4];
2945 ITypeInfo
*pTypeInfo
;
2948 ok(pKEW
!= NULL
, "Widget creation failed\n");
2950 hr
= CreateStreamOnHGlobal(NULL
, TRUE
, &pStream
);
2951 ok_ole_success(hr
, CreateStreamOnHGlobal
);
2952 tid
= start_host_object(pStream
, &IID_IKindaEnumWidget
, (IUnknown
*)pKEW
, MSHLFLAGS_NORMAL
, &thread
);
2953 IKindaEnumWidget_Release(pKEW
);
2955 IStream_Seek(pStream
, ullZero
, STREAM_SEEK_SET
, NULL
);
2956 hr
= CoUnmarshalInterface(pStream
, &IID_IKindaEnumWidget
, (void **)&pKEW
);
2957 ok_ole_success(hr
, CoUnmarshalInterface
);
2958 IStream_Release(pStream
);
2961 end_host_object(tid
, thread
);
2965 hr
= IKindaEnumWidget_Next(pKEW
, &pWidget
);
2966 ok_ole_success(hr
, IKindaEnumWidget_Next
);
2968 IKindaEnumWidget_Release(pKEW
);
2970 /* call GetTypeInfoCount (direct) */
2971 hr
= IWidget_GetTypeInfoCount(pWidget
, &uval
);
2972 ok_ole_success(hr
, IWidget_GetTypeInfoCount
);
2973 hr
= IWidget_GetTypeInfoCount(pWidget
, &uval
);
2974 ok_ole_success(hr
, IWidget_GetTypeInfoCount
);
2976 hr
= IWidget_QueryInterface(pWidget
, &IID_IDispatch
, (void **)&pDispatch
);
2977 ok_ole_success(hr
, IWidget_QueryInterface
);
2980 VariantInit(&vararg
[0]);
2981 dispparams
.cNamedArgs
= 1;
2982 dispparams
.rgdispidNamedArgs
= &dispidNamed
;
2983 dispparams
.cArgs
= 1;
2984 dispparams
.rgvarg
= vararg
;
2985 VariantInit(&varresult
);
2986 hr
= IDispatch_Invoke(pDispatch
, DISPID_TM_NAME
, &IID_NULL
, LOCALE_NEUTRAL
, DISPATCH_PROPERTYPUT
, &dispparams
, &varresult
, &excepinfo
, NULL
);
2987 ok_ole_success(hr
, IDispatch_Invoke
);
2988 ok(excepinfo
.wCode
== 0x0 && excepinfo
.scode
== S_OK
,
2989 "EXCEPINFO differs from expected: wCode = 0x%x, scode = 0x%08lx\n",
2990 excepinfo
.wCode
, excepinfo
.scode
);
2991 VariantClear(&varresult
);
2993 /* call put_Name (direct) */
2994 bstr
= SysAllocString(szSuperman
);
2995 hr
= IWidget_put_Name(pWidget
, bstr
);
2996 ok_ole_success(hr
, IWidget_put_Name
);
2997 SysFreeString(bstr
);
3000 dispparams
.cNamedArgs
= 0;
3001 dispparams
.rgdispidNamedArgs
= NULL
;
3002 dispparams
.cArgs
= 0;
3003 dispparams
.rgvarg
= NULL
;
3004 VariantInit(&varresult
);
3005 hr
= IDispatch_Invoke(pDispatch
, DISPID_TM_NAME
, &IID_NULL
, LOCALE_NEUTRAL
, DISPATCH_PROPERTYGET
, &dispparams
, &varresult
, &excepinfo
, NULL
);
3006 ok_ole_success(hr
, IDispatch_Invoke
);
3007 ok(excepinfo
.wCode
== 0x0 && excepinfo
.scode
== S_OK
,
3008 "EXCEPINFO differs from expected: wCode = 0x%x, scode = 0x%08lx\n",
3009 excepinfo
.wCode
, excepinfo
.scode
);
3010 trace("Name = %s\n", wine_dbgstr_w(V_BSTR(&varresult
)));
3011 VariantClear(&varresult
);
3013 /* call get_Name (direct) */
3014 bstr
= (void *)0xdeadbeef;
3015 hr
= IWidget_get_Name(pWidget
, &bstr
);
3016 ok_ole_success(hr
, IWidget_get_Name
);
3017 ok(!lstrcmpW(bstr
, szCat
), "IWidget_get_Name should have returned string \"Cat\" instead of %s\n", wine_dbgstr_w(bstr
));
3018 SysFreeString(bstr
);
3020 /* call DoSomething without optional arguments */
3021 VariantInit(&vararg
[0]);
3022 VariantInit(&vararg
[1]);
3023 V_VT(&vararg
[1]) = VT_R8
;
3024 V_R8(&vararg
[1]) = 3.141;
3025 dispparams
.cNamedArgs
= 0;
3026 dispparams
.cArgs
= 2;
3027 dispparams
.rgdispidNamedArgs
= NULL
;
3028 dispparams
.rgvarg
= vararg
;
3029 VariantInit(&varresult
);
3030 hr
= IDispatch_Invoke(pDispatch
, DISPID_TM_DOSOMETHING
, &IID_NULL
, LOCALE_NEUTRAL
, DISPATCH_METHOD
, &dispparams
, &varresult
, &excepinfo
, NULL
);
3031 ok_ole_success(hr
, IDispatch_Invoke
);
3032 ok(V_VT(&varresult
) == VT_EMPTY
, "varresult should be VT_EMPTY\n");
3033 VariantClear(&varresult
);
3035 /* call DoSomething with optional argument set to VT_EMPTY */
3036 VariantInit(&vararg
[0]);
3037 VariantInit(&vararg
[1]);
3038 VariantInit(&vararg
[2]);
3039 V_VT(&vararg
[2]) = VT_R8
;
3040 V_R8(&vararg
[2]) = 3.141;
3041 dispparams
.cNamedArgs
= 0;
3042 dispparams
.cArgs
= 3;
3043 dispparams
.rgdispidNamedArgs
= NULL
;
3044 dispparams
.rgvarg
= vararg
;
3045 VariantInit(&varresult
);
3046 hr
= IDispatch_Invoke(pDispatch
, DISPID_TM_DOSOMETHING
, &IID_NULL
, LOCALE_NEUTRAL
, DISPATCH_METHOD
, &dispparams
, &varresult
, &excepinfo
, NULL
);
3047 ok_ole_success(hr
, IDispatch_Invoke
);
3048 ok(V_VT(&varresult
) == VT_EMPTY
, "varresult should be VT_EMPTY\n");
3049 VariantClear(&varresult
);
3051 /* call DoSomething with optional arguments set to VT_ERROR/DISP_E_PARAMNOTFOUND */
3052 VariantInit(&vararg
[0]);
3053 VariantInit(&vararg
[1]);
3054 VariantInit(&vararg
[2]);
3055 VariantInit(&vararg
[3]);
3056 V_VT(&vararg
[3]) = VT_R8
;
3057 V_R8(&vararg
[3]) = 3.141;
3058 V_VT(&vararg
[1]) = VT_ERROR
;
3059 V_ERROR(&vararg
[1]) = DISP_E_PARAMNOTFOUND
;
3060 V_VT(&vararg
[0]) = VT_ERROR
;
3061 V_ERROR(&vararg
[0]) = DISP_E_PARAMNOTFOUND
;
3062 dispparams
.cNamedArgs
= 0;
3063 dispparams
.cArgs
= 4;
3064 dispparams
.rgdispidNamedArgs
= NULL
;
3065 dispparams
.rgvarg
= vararg
;
3066 VariantInit(&varresult
);
3067 hr
= IDispatch_Invoke(pDispatch
, DISPID_TM_DOSOMETHING
, &IID_NULL
, LOCALE_NEUTRAL
, DISPATCH_METHOD
, &dispparams
, &varresult
, &excepinfo
, NULL
);
3068 ok_ole_success(hr
, IDispatch_Invoke
);
3069 ok(V_VT(&varresult
) == VT_EMPTY
, "varresult should be VT_EMPTY\n");
3070 VariantClear(&varresult
);
3072 /* call get_State */
3073 dispparams
.cNamedArgs
= 0;
3074 dispparams
.cArgs
= 0;
3075 dispparams
.rgdispidNamedArgs
= NULL
;
3076 dispparams
.rgvarg
= NULL
;
3077 hr
= IDispatch_Invoke(pDispatch
, DISPID_TM_STATE
, &IID_NULL
, LOCALE_NEUTRAL
, DISPATCH_PROPERTYGET
, &dispparams
, &varresult
, &excepinfo
, NULL
);
3078 ok_ole_success(hr
, IDispatch_Invoke
);
3079 ok((V_VT(&varresult
) == VT_I4
) && (V_I4(&varresult
) == STATE_WIDGETIFIED
), "Return val mismatch\n");
3081 /* call get_State (direct) */
3082 hr
= IWidget_get_State(pWidget
, &the_state
);
3083 ok_ole_success(hr
, IWidget_get_state
);
3084 ok(the_state
== STATE_WIDGETIFIED
, "should have returned WIDGET_WIDGETIFIED instead of %d\n", the_state
);
3086 /* call put_State */
3087 the_state
= STATE_WIDGETIFIED
;
3088 VariantInit(&vararg
[0]);
3089 V_VT(&vararg
[0]) = VT_BYREF
|VT_I4
;
3090 V_I4REF(&vararg
[0]) = (LONG
*)&the_state
;
3091 dispparams
.cNamedArgs
= 1;
3092 dispparams
.cArgs
= 1;
3093 dispparams
.rgdispidNamedArgs
= &dispidNamed
;
3094 dispparams
.rgvarg
= vararg
;
3095 hr
= IDispatch_Invoke(pDispatch
, DISPID_TM_STATE
, &IID_NULL
, LOCALE_NEUTRAL
, DISPATCH_PROPERTYPUT
, &dispparams
, &varresult
, &excepinfo
, NULL
);
3096 ok_ole_success(hr
, IDispatch_Invoke
);
3099 bstr
= SysAllocString(szTestTest
);
3100 VariantInit(&vararg
[0]);
3101 V_VT(&vararg
[0]) = VT_BYREF
|VT_BSTR
;
3102 V_BSTRREF(&vararg
[0]) = &bstr
;
3103 dispparams
.cNamedArgs
= 0;
3104 dispparams
.cArgs
= 1;
3105 dispparams
.rgdispidNamedArgs
= NULL
;
3106 dispparams
.rgvarg
= vararg
;
3107 VariantInit(&varresult
);
3108 hr
= IDispatch_Invoke(pDispatch
, DISPID_TM_MAP
, &IID_NULL
, LOCALE_NEUTRAL
, DISPATCH_METHOD
, &dispparams
, &varresult
, &excepinfo
, NULL
);
3109 ok_ole_success(hr
, IDispatch_Invoke
);
3110 ok(V_VT(&varresult
) == VT_BSTR
, "Return value should be of type BSTR instead of %d\n", V_VT(&varresult
));
3111 ok(!lstrcmpW(V_BSTR(&varresult
), szTestTest
), "Return value should have been \"TestTest\" instead of %s\n", wine_dbgstr_w(V_BSTR(&varresult
)));
3112 VariantClear(&varresult
);
3113 SysFreeString(bstr
);
3115 /* call SetOleColor with large negative VT_I4 param */
3116 VariantInit(&vararg
[0]);
3117 V_VT(&vararg
[0]) = VT_I4
;
3118 V_I4(&vararg
[0]) = 0x80000005;
3119 dispparams
.cNamedArgs
= 0;
3120 dispparams
.cArgs
= 1;
3121 dispparams
.rgdispidNamedArgs
= NULL
;
3122 dispparams
.rgvarg
= vararg
;
3123 hr
= IDispatch_Invoke(pDispatch
, DISPID_TM_SETOLECOLOR
, &IID_NULL
, LOCALE_NEUTRAL
, DISPATCH_METHOD
, &dispparams
, NULL
, &excepinfo
, NULL
);
3124 ok_ole_success(hr
, IDispatch_Invoke
);
3126 /* call GetOleColor */
3127 dispparams
.cNamedArgs
= 0;
3128 dispparams
.cArgs
= 0;
3129 dispparams
.rgdispidNamedArgs
= NULL
;
3130 dispparams
.rgvarg
= NULL
;
3131 VariantInit(&varresult
);
3132 hr
= IDispatch_Invoke(pDispatch
, DISPID_TM_GETOLECOLOR
, &IID_NULL
, LOCALE_NEUTRAL
, DISPATCH_METHOD
, &dispparams
, &varresult
, &excepinfo
, NULL
);
3133 ok_ole_success(hr
, IDispatch_Invoke
);
3134 VariantClear(&varresult
);
3137 dispparams
.cNamedArgs
= 0;
3138 dispparams
.cArgs
= 0;
3139 dispparams
.rgdispidNamedArgs
= NULL
;
3140 dispparams
.rgvarg
= NULL
;
3141 VariantInit(&varresult
);
3142 hr
= IDispatch_Invoke(pDispatch
, DISPID_TM_CLONE
, &IID_NULL
, LOCALE_NEUTRAL
, DISPATCH_PROPERTYGET
, &dispparams
, &varresult
, &excepinfo
, NULL
);
3143 ok_ole_success(hr
, IDispatch_Invoke
);
3144 ok(V_VT(&varresult
) == VT_DISPATCH
, "vt %x\n", V_VT(&varresult
));
3145 VariantClear(&varresult
);
3147 /* call CloneInterface */
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_CLONEINTERFACE
, &IID_NULL
, LOCALE_NEUTRAL
, DISPATCH_PROPERTYGET
, &dispparams
, &varresult
, &excepinfo
, NULL
);
3154 ok_ole_success(hr
, IDispatch_Invoke
);
3155 ok(V_VT(&varresult
) == VT_DISPATCH
, "vt %x\n", V_VT(&varresult
));
3156 VariantClear(&varresult
);
3158 /* call CloneDispatch with automatic value getting */
3159 V_VT(&vararg
[0]) = VT_I2
;
3160 V_I2(&vararg
[0]) = 1;
3161 dispparams
.cNamedArgs
= 0;
3162 dispparams
.rgdispidNamedArgs
= NULL
;
3163 dispparams
.cArgs
= 1;
3164 dispparams
.rgvarg
= vararg
;
3165 VariantInit(&varresult
);
3166 hr
= IDispatch_Invoke(pDispatch
, DISPID_TM_CLONEDISPATCH
, &IID_NULL
, LOCALE_NEUTRAL
, DISPATCH_PROPERTYGET
, &dispparams
, &varresult
, &excepinfo
, NULL
);
3167 ok_ole_success(hr
, IDispatch_Invoke
);
3169 ok(excepinfo
.wCode
== 0x0 && excepinfo
.scode
== S_OK
,
3170 "EXCEPINFO differs from expected: wCode = 0x%x, scode = 0x%08lx\n",
3171 excepinfo
.wCode
, excepinfo
.scode
);
3173 ok(V_VT(&varresult
) == VT_I2
, "V_VT(&varresult) was %d instead of VT_I2\n", V_VT(&varresult
));
3174 ok(V_I2(&varresult
) == 1234, "V_I2(&varresult) was %d instead of 1234\n", V_I2(&varresult
));
3175 VariantClear(&varresult
);
3177 /* call CloneCoclass */
3178 dispparams
.cNamedArgs
= 0;
3179 dispparams
.cArgs
= 0;
3180 dispparams
.rgdispidNamedArgs
= NULL
;
3181 dispparams
.rgvarg
= NULL
;
3182 VariantInit(&varresult
);
3183 hr
= IDispatch_Invoke(pDispatch
, DISPID_TM_CLONECOCLASS
, &IID_NULL
, LOCALE_NEUTRAL
, DISPATCH_PROPERTYGET
, &dispparams
, &varresult
, &excepinfo
, NULL
);
3184 ok_ole_success(hr
, IDispatch_Invoke
);
3186 ok(excepinfo
.wCode
== 0x0 && excepinfo
.scode
== S_OK
,
3187 "EXCEPINFO differs from expected: wCode = 0x%x, scode = 0x%08lx\n",
3188 excepinfo
.wCode
, excepinfo
.scode
);
3190 ok(V_VT(&varresult
) == VT_DISPATCH
, "V_VT(&varresult) was %d instead of VT_DISPATCH\n", V_VT(&varresult
));
3191 ok(V_DISPATCH(&varresult
) != NULL
, "expected V_DISPATCH(&varresult) != NULL\n");
3193 /* call Value with a VT_VARIANT|VT_BYREF type */
3194 V_VT(&vararg
[0]) = VT_VARIANT
|VT_BYREF
;
3195 V_VARIANTREF(&vararg
[0]) = &vararg
[1];
3196 V_VT(&vararg
[1]) = VT_I2
;
3197 V_I2(&vararg
[1]) = 1;
3198 dispparams
.cNamedArgs
= 0;
3199 dispparams
.rgdispidNamedArgs
= NULL
;
3200 dispparams
.cArgs
= 1;
3201 dispparams
.rgvarg
= vararg
;
3202 VariantInit(&varresult
);
3203 hr
= IDispatch_Invoke(pDispatch
, DISPID_VALUE
, &IID_NULL
, LOCALE_NEUTRAL
, DISPATCH_PROPERTYGET
, &dispparams
, &varresult
, &excepinfo
, NULL
);
3204 ok_ole_success(hr
, IDispatch_Invoke
);
3206 ok(excepinfo
.wCode
== 0x0 && excepinfo
.scode
== S_OK
,
3207 "EXCEPINFO differs from expected: wCode = 0x%x, scode = 0x%08lx\n",
3208 excepinfo
.wCode
, excepinfo
.scode
);
3210 ok(V_VT(&varresult
) == VT_I2
, "V_VT(&varresult) was %d instead of VT_I2\n", V_VT(&varresult
));
3211 ok(V_I2(&varresult
) == 1234, "V_I2(&varresult) was %d instead of 1234\n", V_I2(&varresult
));
3212 VariantClear(&varresult
);
3214 /* call Array with BSTR argument - type mismatch */
3215 VariantInit(&vararg
[0]);
3216 V_VT(&vararg
[0]) = VT_BSTR
;
3217 V_BSTR(&vararg
[0]) = SysAllocString(szSuperman
);
3218 dispparams
.cNamedArgs
= 0;
3219 dispparams
.cArgs
= 1;
3220 dispparams
.rgdispidNamedArgs
= NULL
;
3221 dispparams
.rgvarg
= vararg
;
3222 hr
= IDispatch_Invoke(pDispatch
, DISPID_TM_ARRAY
, &IID_NULL
, LOCALE_NEUTRAL
, DISPATCH_METHOD
, &dispparams
, NULL
, NULL
, NULL
);
3223 ok(hr
== DISP_E_TYPEMISMATCH
|| hr
== DISP_E_BADVARTYPE
, "expected DISP_E_TYPEMISMATCH, got %#lx\n", hr
);
3224 SysFreeString(V_BSTR(&vararg
[0]));
3226 /* call ArrayPtr with BSTR argument - type mismatch */
3227 VariantInit(&vararg
[0]);
3228 V_VT(&vararg
[0]) = VT_BSTR
;
3229 V_BSTR(&vararg
[0]) = SysAllocString(szSuperman
);
3230 dispparams
.cNamedArgs
= 0;
3231 dispparams
.cArgs
= 1;
3232 dispparams
.rgdispidNamedArgs
= NULL
;
3233 dispparams
.rgvarg
= vararg
;
3234 hr
= IDispatch_Invoke(pDispatch
, DISPID_TM_VARARRAYPTR
, &IID_NULL
, LOCALE_NEUTRAL
, DISPATCH_METHOD
, &dispparams
, NULL
, NULL
, NULL
);
3235 ok(hr
== DISP_E_TYPEMISMATCH
|| hr
== DISP_E_BADVARTYPE
, "expected DISP_E_TYPEMISMATCH, got %#lx\n", hr
);
3236 SysFreeString(V_BSTR(&vararg
[0]));
3239 VariantInit(&vararg
[3]);
3240 V_VT(&vararg
[3]) = VT_I4
;
3241 V_I4(&vararg
[3]) = 3;
3242 VariantInit(&vararg
[2]);
3243 V_VT(&vararg
[2]) = VT_I4
;
3244 V_I4(&vararg
[2]) = 0;
3245 VariantInit(&vararg
[1]);
3246 V_VT(&vararg
[1]) = VT_I4
;
3247 V_I4(&vararg
[1]) = 1;
3248 VariantInit(&vararg
[0]);
3249 V_VT(&vararg
[0]) = VT_I4
;
3250 V_I4(&vararg
[0]) = 2;
3251 dispparams
.cNamedArgs
= 0;
3252 dispparams
.cArgs
= 4;
3253 dispparams
.rgdispidNamedArgs
= NULL
;
3254 dispparams
.rgvarg
= vararg
;
3255 hr
= IDispatch_Invoke(pDispatch
, DISPID_TM_VARARG
, &IID_NULL
, LOCALE_NEUTRAL
, DISPATCH_METHOD
, &dispparams
, NULL
, NULL
, NULL
);
3256 ok_ole_success(hr
, IDispatch_Invoke
);
3258 /* without any varargs */
3259 dispparams
.cArgs
= 1;
3260 V_I4(&vararg
[0]) = 0;
3261 hr
= IDispatch_Invoke(pDispatch
, DISPID_TM_VARARG
, &IID_NULL
, LOCALE_NEUTRAL
, DISPATCH_METHOD
, &dispparams
, NULL
, NULL
, NULL
);
3262 ok_ole_success(hr
, IDispatch_Invoke
);
3264 /* call VarArg, even one (non-optional, non-safearray) named argument is not allowed */
3266 dispparams
.cNamedArgs
= 1;
3267 dispparams
.rgdispidNamedArgs
= &dispidNamed
;
3268 hr
= IDispatch_Invoke(pDispatch
, DISPID_TM_VARARG
, &IID_NULL
, LOCALE_NEUTRAL
, DISPATCH_METHOD
, &dispparams
, NULL
, NULL
, NULL
);
3269 ok(hr
== DISP_E_NONAMEDARGS
, "IDispatch_Invoke should have returned DISP_E_NONAMEDARGS instead of 0x%08lx\n", hr
);
3270 dispidNamed
= DISPID_PROPERTYPUT
;
3272 /* call VarArg_Run */
3273 VariantInit(&vararg
[1]);
3274 V_VT(&vararg
[1]) = VT_BSTR
;
3275 V_BSTR(&vararg
[1]) = SysAllocString(szCat
);
3276 VariantInit(&vararg
[0]);
3277 V_VT(&vararg
[0]) = VT_BSTR
;
3278 V_BSTR(&vararg
[0]) = SysAllocString(szSuperman
);
3279 dispparams
.cNamedArgs
= 0;
3280 dispparams
.cArgs
= 2;
3281 dispparams
.rgdispidNamedArgs
= NULL
;
3282 dispparams
.rgvarg
= vararg
;
3283 hr
= IDispatch_Invoke(pDispatch
, DISPID_TM_VARARG_RUN
, &IID_NULL
, LOCALE_NEUTRAL
, DISPATCH_METHOD
, &dispparams
, NULL
, NULL
, NULL
);
3284 ok_ole_success(hr
, IDispatch_Invoke
);
3285 /* without any varargs */
3286 dispparams
.cArgs
= 1;
3287 dispparams
.rgvarg
= vararg
+ 1;
3288 hr
= IDispatch_Invoke(pDispatch
, DISPID_TM_VARARG_RUN
, &IID_NULL
, LOCALE_NEUTRAL
, DISPATCH_METHOD
, &dispparams
, NULL
, NULL
, NULL
);
3289 ok_ole_success(hr
, IDispatch_Invoke
);
3290 SysFreeString(V_BSTR(&vararg
[1]));
3291 SysFreeString(V_BSTR(&vararg
[0]));
3293 /* call VarArg_Ref_Run */
3294 VariantInit(&vararg
[1]);
3295 V_VT(&vararg
[1]) = VT_BSTR
;
3296 V_BSTR(&vararg
[1]) = SysAllocString(szCat
);
3297 VariantInit(&vararg
[0]);
3298 V_VT(&vararg
[0]) = VT_BSTR
;
3299 V_BSTR(&vararg
[0]) = SysAllocString(szSuperman
);
3300 dispparams
.cNamedArgs
= 0;
3301 dispparams
.cArgs
= 2;
3302 dispparams
.rgdispidNamedArgs
= NULL
;
3303 dispparams
.rgvarg
= vararg
;
3304 hr
= IDispatch_Invoke(pDispatch
, DISPID_TM_VARARG_REF_RUN
, &IID_NULL
, LOCALE_NEUTRAL
, DISPATCH_METHOD
, &dispparams
, NULL
, NULL
, NULL
);
3305 ok_ole_success(hr
, IDispatch_Invoke
);
3306 /* without any varargs */
3307 dispparams
.cArgs
= 1;
3308 dispparams
.rgvarg
= vararg
+ 1;
3309 hr
= IDispatch_Invoke(pDispatch
, DISPID_TM_VARARG_REF_RUN
, &IID_NULL
, LOCALE_NEUTRAL
, DISPATCH_METHOD
, &dispparams
, NULL
, NULL
, NULL
);
3310 ok_ole_success(hr
, IDispatch_Invoke
);
3311 SysFreeString(V_BSTR(&vararg
[1]));
3312 SysFreeString(V_BSTR(&vararg
[0]));
3315 dispparams
.cNamedArgs
= 0;
3316 dispparams
.cArgs
= 0;
3317 dispparams
.rgdispidNamedArgs
= NULL
;
3318 dispparams
.rgvarg
= NULL
;
3319 VariantInit(&varresult
);
3320 hr
= IDispatch_Invoke(pDispatch
, DISPID_TM_ERROR
, &IID_NULL
, LOCALE_NEUTRAL
, DISPATCH_METHOD
, &dispparams
, NULL
, &excepinfo
, NULL
);
3321 ok(hr
== DISP_E_EXCEPTION
, "IDispatch_Invoke should have returned DISP_E_EXCEPTION instead of 0x%08lx\n", hr
);
3322 ok(excepinfo
.wCode
== 0x0 && excepinfo
.scode
== E_NOTIMPL
,
3323 "EXCEPINFO differs from expected: wCode = 0x%x, scode = 0x%08lx\n",
3324 excepinfo
.wCode
, excepinfo
.scode
);
3325 VariantClear(&varresult
);
3328 pTypeInfo
= NonOleAutomation_GetTypeInfo();
3329 dispparams
.cNamedArgs
= 0;
3330 dispparams
.cArgs
= 0;
3331 dispparams
.rgdispidNamedArgs
= NULL
;
3332 dispparams
.rgvarg
= NULL
;
3333 VariantInit(&varresult
);
3334 hr
= ITypeInfo_Invoke(pTypeInfo
, &NonOleAutomation
, DISPID_NOA_BSTRRET
, DISPATCH_METHOD
, &dispparams
, &varresult
, &excepinfo
, NULL
);
3335 ok_ole_success(hr
, ITypeInfo_Invoke
);
3336 ok(V_VT(&varresult
) == VT_BSTR
, "V_VT(&varresult) should be VT_BSTR instead of %d\n", V_VT(&varresult
));
3337 ok(V_BSTR(&varresult
) != NULL
, "V_BSTR(&varresult) should not be NULL\n");
3339 VariantClear(&varresult
);
3341 dispparams
.cNamedArgs
= 0;
3342 dispparams
.cArgs
= 0;
3343 dispparams
.rgdispidNamedArgs
= NULL
;
3344 dispparams
.rgvarg
= NULL
;
3345 hr
= ITypeInfo_Invoke(pTypeInfo
, &NonOleAutomation
, DISPID_NOA_ERROR
, DISPATCH_METHOD
, &dispparams
, &varresult
, &excepinfo
, NULL
);
3346 ok(hr
== DISP_E_EXCEPTION
, "ITypeInfo_Invoke should have returned DISP_E_EXCEPTION instead of 0x%08lx\n", hr
);
3347 ok(V_VT(&varresult
) == VT_EMPTY
, "V_VT(&varresult) should be VT_EMPTY instead of %d\n", V_VT(&varresult
));
3348 ok(excepinfo
.wCode
== 0x0 && excepinfo
.scode
== E_NOTIMPL
,
3349 "EXCEPINFO differs from expected: wCode = 0x%x, scode = 0x%08lx\n",
3350 excepinfo
.wCode
, excepinfo
.scode
);
3351 VariantClear(&varresult
);
3353 ITypeInfo_Release(pTypeInfo
);
3355 /* tests call put_Name without named arg */
3356 VariantInit(&vararg
[0]);
3357 dispparams
.cNamedArgs
= 0;
3358 dispparams
.rgdispidNamedArgs
= NULL
;
3359 dispparams
.cArgs
= 1;
3360 dispparams
.rgvarg
= vararg
;
3361 VariantInit(&varresult
);
3362 hr
= IDispatch_Invoke(pDispatch
, DISPID_TM_NAME
, &IID_NULL
, LOCALE_NEUTRAL
, DISPATCH_PROPERTYPUT
, &dispparams
, &varresult
, &excepinfo
, NULL
);
3363 ok(hr
== DISP_E_PARAMNOTFOUND
, "IDispatch_Invoke should have returned DISP_E_PARAMNOTFOUND instead of 0x%08lx\n", hr
);
3364 VariantClear(&varresult
);
3366 /* tests param type that cannot be coerced */
3367 VariantInit(&vararg
[0]);
3368 V_VT(&vararg
[0]) = VT_UNKNOWN
;
3369 V_UNKNOWN(&vararg
[0]) = NULL
;
3370 dispparams
.cNamedArgs
= 1;
3371 dispparams
.rgdispidNamedArgs
= &dispidNamed
;
3372 dispparams
.cArgs
= 1;
3373 dispparams
.rgvarg
= vararg
;
3374 VariantInit(&varresult
);
3375 hr
= IDispatch_Invoke(pDispatch
, DISPID_TM_NAME
, &IID_NULL
, LOCALE_NEUTRAL
, DISPATCH_PROPERTYPUT
, &dispparams
, &varresult
, &excepinfo
, NULL
);
3376 ok(hr
== DISP_E_TYPEMISMATCH
, "IDispatch_Invoke should have returned DISP_E_TYPEMISMATCH instead of 0x%08lx\n", hr
);
3377 VariantClear(&varresult
);
3379 /* tests bad param type */
3380 VariantInit(&vararg
[0]);
3381 V_VT(&vararg
[0]) = VT_CLSID
;
3382 V_BYREF(&vararg
[0]) = NULL
;
3383 dispparams
.cNamedArgs
= 1;
3384 dispparams
.rgdispidNamedArgs
= &dispidNamed
;
3385 dispparams
.cArgs
= 1;
3386 dispparams
.rgvarg
= vararg
;
3387 VariantInit(&varresult
);
3388 hr
= IDispatch_Invoke(pDispatch
, DISPID_TM_NAME
, &IID_NULL
, LOCALE_NEUTRAL
, DISPATCH_PROPERTYPUT
, &dispparams
, &varresult
, &excepinfo
, NULL
);
3389 ok(hr
== DISP_E_BADVARTYPE
, "IDispatch_Invoke should have returned DISP_E_BADVARTYPE instead of 0x%08lx\n", hr
);
3390 VariantClear(&varresult
);
3392 /* tests too small param count */
3393 dispparams
.cNamedArgs
= 0;
3394 dispparams
.rgdispidNamedArgs
= NULL
;
3395 dispparams
.cArgs
= 0;
3396 dispparams
.rgvarg
= NULL
;
3397 VariantInit(&varresult
);
3398 hr
= IDispatch_Invoke(pDispatch
, DISPID_TM_DOSOMETHING
, &IID_NULL
, LOCALE_NEUTRAL
, DISPATCH_METHOD
, &dispparams
, &varresult
, &excepinfo
, NULL
);
3399 ok(hr
== DISP_E_BADPARAMCOUNT
, "IDispatch_Invoke should have returned DISP_E_BADPARAMCOUNT instead of 0x%08lx\n", hr
);
3400 VariantClear(&varresult
);
3402 /* tests propget function with large param count */
3403 VariantInit(&vararg
[0]);
3404 V_VT(&vararg
[0]) = VT_BSTR
;
3405 V_BSTR(&vararg
[0]) = NULL
;
3406 V_VT(&vararg
[1]) = VT_I4
;
3407 V_I4(&vararg
[1]) = 1;
3408 dispparams
.cNamedArgs
= 0;
3409 dispparams
.cArgs
= 2;
3410 dispparams
.rgdispidNamedArgs
= NULL
;
3411 dispparams
.rgvarg
= vararg
;
3412 hr
= IDispatch_Invoke(pDispatch
, DISPID_TM_STATE
, &IID_NULL
, LOCALE_NEUTRAL
, DISPATCH_PROPERTYGET
, &dispparams
, &varresult
, &excepinfo
, NULL
);
3413 ok(hr
== DISP_E_NOTACOLLECTION
, "IDispatch_Invoke should have returned DISP_E_NOTACOLLECTION instead of 0x%08lx\n", hr
);
3415 /* test propput with lcid */
3417 /* the lcid passed to the function is the first lcid in the typelib header.
3418 Since we don't explicitly set an lcid in the idl, it'll default to US English. */
3419 VariantInit(&vararg
[0]);
3420 V_VT(&vararg
[0]) = VT_I4
;
3421 V_I4(&vararg
[0]) = 0xcafe;
3422 dispparams
.cNamedArgs
= 1;
3423 dispparams
.rgdispidNamedArgs
= &dispidNamed
;
3424 dispparams
.cArgs
= 1;
3425 dispparams
.rgvarg
= vararg
;
3426 VariantInit(&varresult
);
3427 hr
= IDispatch_Invoke(pDispatch
, DISPID_TM_PROP_WITH_LCID
, &IID_NULL
, 0x40c, DISPATCH_PROPERTYPUT
, &dispparams
, &varresult
, &excepinfo
, NULL
);
3428 ok_ole_success(hr
, ITypeInfo_Invoke
);
3429 VariantClear(&varresult
);
3431 /* test propget with lcid */
3432 dispparams
.cNamedArgs
= 0;
3433 dispparams
.cArgs
= 0;
3434 dispparams
.rgvarg
= NULL
;
3435 dispparams
.rgdispidNamedArgs
= NULL
;
3436 hr
= IDispatch_Invoke(pDispatch
, DISPID_TM_PROP_WITH_LCID
, &IID_NULL
, 0x40c, DISPATCH_PROPERTYGET
, &dispparams
, &varresult
, &excepinfo
, NULL
);
3437 ok_ole_success(hr
, ITypeInfo_Invoke
);
3438 ok(V_VT(&varresult
) == VT_I4
, "got %x\n", V_VT(&varresult
));
3439 ok(V_I4(&varresult
) == 0x409, "got %lx\n", V_I4(&varresult
));
3440 VariantClear(&varresult
);
3442 /* test propget of INT value */
3443 dispparams
.cNamedArgs
= 0;
3444 dispparams
.cArgs
= 0;
3445 dispparams
.rgvarg
= NULL
;
3446 dispparams
.rgdispidNamedArgs
= NULL
;
3447 hr
= IDispatch_Invoke(pDispatch
, DISPID_TM_PROP_INT
, &IID_NULL
, 0x40c, DISPATCH_PROPERTYGET
, &dispparams
, &varresult
, &excepinfo
, NULL
);
3448 ok_ole_success(hr
, ITypeInfo_Invoke
);
3449 ok(V_VT(&varresult
) == VT_I4
, "got %x\n", V_VT(&varresult
));
3450 ok(V_I4(&varresult
) == -13, "got %lx\n", V_I4(&varresult
));
3451 VariantClear(&varresult
);
3453 /* test propget of INT value */
3454 dispparams
.cNamedArgs
= 0;
3455 dispparams
.cArgs
= 0;
3456 dispparams
.rgvarg
= NULL
;
3457 dispparams
.rgdispidNamedArgs
= NULL
;
3458 hr
= IDispatch_Invoke(pDispatch
, DISPID_TM_PROP_UINT
, &IID_NULL
, 0x40c, DISPATCH_PROPERTYGET
, &dispparams
, &varresult
, &excepinfo
, NULL
);
3459 ok_ole_success(hr
, ITypeInfo_Invoke
);
3460 ok(V_VT(&varresult
) == VT_UI4
, "got %x\n", V_VT(&varresult
));
3461 ok(V_UI4(&varresult
) == 42, "got %lx\n", V_UI4(&varresult
));
3462 VariantClear(&varresult
);
3464 /* test byref marshalling */
3466 VariantInit(&vararg
[0]);
3467 V_VT(&vararg
[0]) = VT_UI4
|VT_BYREF
;
3468 V_UI4REF(&vararg
[0]) = (ULONG
*)&uval
;
3469 dispparams
.cNamedArgs
= 0;
3470 dispparams
.cArgs
= 1;
3471 dispparams
.rgvarg
= vararg
;
3472 dispparams
.rgdispidNamedArgs
= NULL
;
3473 hr
= IDispatch_Invoke(pDispatch
, DISPID_TM_BYREF_UINT
, &IID_NULL
, LOCALE_NEUTRAL
, DISPATCH_METHOD
, &dispparams
, &varresult
, &excepinfo
, NULL
);
3474 ok_ole_success(hr
, ITypeInfo_Invoke
);
3475 ok(V_VT(&varresult
) == VT_EMPTY
, "varresult should be VT_EMPTY\n");
3476 ok(V_VT(&vararg
[0]) == (VT_UI4
|VT_BYREF
), "arg VT not unmarshalled correctly: %x\n", V_VT(&vararg
[0]));
3477 ok(V_UI4REF(&vararg
[0]) == (ULONG
*)&uval
, "Byref pointer not preserved: %p/%p\n", &uval
, V_UI4REF(&vararg
[0]));
3478 ok(*V_UI4REF(&vararg
[0]) == 42, "Expected 42 to be returned instead of %lu\n", *V_UI4REF(&vararg
[0]));
3479 VariantClear(&varresult
);
3480 VariantClear(&vararg
[0]);
3482 /* test propput with optional argument. */
3483 VariantInit(&vararg
[0]);
3484 V_VT(&vararg
[0]) = VT_I4
;
3485 V_I4(&vararg
[0]) = 0xcafe;
3486 dispparams
.cNamedArgs
= 1;
3487 dispparams
.rgdispidNamedArgs
= &dispidNamed
;
3488 dispparams
.cArgs
= 1;
3489 dispparams
.rgvarg
= vararg
;
3490 VariantInit(&varresult
);
3491 hr
= IDispatch_Invoke(pDispatch
, DISPID_TM_PROP_OPT_ARG
, &IID_NULL
, 0x40c, DISPATCH_PROPERTYPUT
, &dispparams
, &varresult
, &excepinfo
, NULL
);
3492 ok_ole_success(hr
, ITypeInfo_Invoke
);
3493 VariantClear(&varresult
);
3495 /* test propput with required argument. */
3496 VariantInit(&vararg
[0]);
3497 VariantInit(&vararg
[1]);
3498 V_VT(&vararg
[0]) = VT_I4
;
3499 V_I4(&vararg
[0]) = 0x1234;
3500 V_VT(&vararg
[1]) = VT_I4
;
3501 V_I4(&vararg
[1]) = 0x5678;
3502 dispparams
.cNamedArgs
= 1;
3503 dispparams
.rgdispidNamedArgs
= &dispidNamed
;
3504 dispparams
.cArgs
= 2;
3505 dispparams
.rgvarg
= vararg
;
3506 VariantInit(&varresult
);
3507 hr
= IDispatch_Invoke(pDispatch
, DISPID_TM_PROP_REQ_ARG
, &IID_NULL
, 0x40c, DISPATCH_PROPERTYPUT
, &dispparams
, &varresult
, &excepinfo
, NULL
);
3508 ok_ole_success(hr
, ITypeInfo_Invoke
);
3509 VariantClear(&varresult
);
3511 /* restricted member */
3512 dispparams
.cNamedArgs
= 0;
3513 dispparams
.rgdispidNamedArgs
= NULL
;
3514 dispparams
.cArgs
= 0;
3515 dispparams
.rgvarg
= NULL
;
3516 VariantInit(&varresult
);
3517 hr
= IDispatch_Invoke(pDispatch
, DISPID_TM_RESTRICTED
, &IID_NULL
, 0x40c, DISPATCH_METHOD
, &dispparams
, &varresult
, &excepinfo
, NULL
);
3518 ok( hr
== DISP_E_MEMBERNOTFOUND
, "got %08lx\n", hr
);
3519 VariantClear(&varresult
);
3521 /* restricted member with -ve memid (not restricted) */
3522 dispparams
.cNamedArgs
= 0;
3523 dispparams
.rgdispidNamedArgs
= NULL
;
3524 dispparams
.cArgs
= 0;
3525 dispparams
.rgvarg
= NULL
;
3526 VariantInit(&varresult
);
3527 hr
= IDispatch_Invoke(pDispatch
, DISPID_TM_NEG_RESTRICTED
, &IID_NULL
, 0x40c, DISPATCH_METHOD
, &dispparams
, &varresult
, &excepinfo
, NULL
);
3528 ok( hr
== S_OK
, "got %08lx\n", hr
);
3529 ok(V_VT(&varresult
) == VT_I4
, "got %x\n", V_VT(&varresult
));
3530 ok(V_I4(&varresult
) == DISPID_TM_NEG_RESTRICTED
, "got %lx\n", V_I4(&varresult
));
3531 VariantClear(&varresult
);
3533 test_marshal_basetypes(pWidget
, pDispatch
);
3534 test_marshal_pointer(pWidget
, pDispatch
);
3535 test_marshal_iface(pWidget
, pDispatch
);
3536 test_marshal_bstr(pWidget
, pDispatch
);
3537 test_marshal_variant(pWidget
, pDispatch
);
3538 test_marshal_safearray(pWidget
, pDispatch
);
3539 test_marshal_struct(pWidget
, pDispatch
);
3540 test_marshal_array(pWidget
, pDispatch
);
3541 test_marshal_coclass(pWidget
, pDispatch
);
3543 IDispatch_Release(pDispatch
);
3544 IWidget_Release(pWidget
);
3546 trace("calling end_host_object\n");
3547 end_host_object(tid
, thread
);
3550 static void test_DispCallFunc(void)
3552 static const WCHAR szEmpty
[] = { 0 };
3553 VARTYPE rgvt
[] = { VT_R8
, VT_BSTR
, VT_BSTR
, VT_VARIANT
|VT_BYREF
};
3554 VARIANTARG vararg
[4];
3556 VARIANTARG
*rgpvarg
[4] = { &vararg
[0], &vararg
[1], &vararg
[2], &vararg
[3] };
3557 VARIANTARG varresult
;
3559 IWidget
*pWidget
= Widget_Create();
3560 V_VT(&vararg
[0]) = VT_R8
;
3561 V_R8(&vararg
[0]) = 3.141;
3562 V_VT(&vararg
[1]) = VT_BSTR
;
3563 V_BSTRREF(&vararg
[1]) = CoTaskMemAlloc(sizeof(BSTR
));
3564 V_VT(&vararg
[2]) = VT_BSTR
;
3565 V_BSTR(&vararg
[2]) = SysAllocString(szEmpty
);
3566 V_VT(&vararg
[3]) = VT_VARIANT
|VT_BYREF
;
3567 V_VARIANTREF(&vararg
[3]) = &varref
;
3568 V_VT(&varref
) = VT_ERROR
;
3569 V_ERROR(&varref
) = DISP_E_PARAMNOTFOUND
;
3570 VariantInit(&varresult
);
3571 hr
= DispCallFunc(pWidget
, 9*sizeof(void*), CC_STDCALL
, VT_UI4
, 4, rgvt
, rgpvarg
, &varresult
);
3572 ok_ole_success(hr
, DispCallFunc
);
3573 VariantClear(&varresult
);
3574 SysFreeString(*V_BSTRREF(&vararg
[1]));
3575 CoTaskMemFree(V_BSTRREF(&vararg
[1]));
3576 VariantClear(&vararg
[2]);
3577 IWidget_Release(pWidget
);
3580 static void test_StaticWidget(void)
3582 ITypeInfo
*type_info
;
3583 DISPPARAMS dispparams
;
3584 VARIANTARG vararg
[4];
3585 EXCEPINFO excepinfo
;
3589 type_info
= get_type_info(&IID_IStaticWidget
);
3592 dispparams
.cNamedArgs
= 0;
3593 dispparams
.cArgs
= 1;
3594 dispparams
.rgdispidNamedArgs
= NULL
;
3595 dispparams
.rgvarg
= vararg
;
3596 V_VT(vararg
) = VT_DISPATCH
;
3597 V_DISPATCH(vararg
) = (IDispatch
*)&TestDualDisp
;
3598 VariantInit(&varresult
);
3599 hr
= ITypeInfo_Invoke(type_info
, &StaticWidget
, DISPID_TM_TESTDUAL
, DISPATCH_METHOD
,
3600 &dispparams
, &varresult
, &excepinfo
, NULL
);
3601 ok_ole_success(hr
, IDispatch_Invoke
);
3602 ok(V_VT(&varresult
) == VT_EMPTY
, "vt %x\n", V_VT(&varresult
));
3603 VariantClear(&varresult
);
3605 /* call TestSecondIface */
3606 dispparams
.cNamedArgs
= 0;
3607 dispparams
.cArgs
= 1;
3608 dispparams
.rgdispidNamedArgs
= NULL
;
3609 dispparams
.rgvarg
= vararg
;
3610 V_VT(vararg
) = VT_DISPATCH
;
3611 V_DISPATCH(vararg
) = (IDispatch
*)&TestDualDisp
;
3612 VariantInit(&varresult
);
3613 hr
= ITypeInfo_Invoke(type_info
, &StaticWidget
, DISPID_TM_TESTSECONDIFACE
, DISPATCH_METHOD
,
3614 &dispparams
, &varresult
, &excepinfo
, NULL
);
3615 ok_ole_success(hr
, IDispatch_Invoke
);
3616 ok(V_VT(&varresult
) == VT_EMPTY
, "vt %x\n", V_VT(&varresult
));
3617 VariantClear(&varresult
);
3619 ITypeInfo_Release(type_info
);
3622 static void test_libattr(void)
3628 hr
= LoadRegTypeLib(&LIBID_TestTypelib
, 2, 5, LOCALE_NEUTRAL
, &pTypeLib
);
3629 ok_ole_success(hr
, LoadRegTypeLib
);
3633 hr
= ITypeLib_GetLibAttr(pTypeLib
, &pattr
);
3634 ok_ole_success(hr
, GetLibAttr
);
3637 ok(pattr
->lcid
== MAKELANGID(LANG_NEUTRAL
, SUBLANG_NEUTRAL
), "lcid %lx\n", pattr
->lcid
);
3639 ITypeLib_ReleaseTLibAttr(pTypeLib
, pattr
);
3642 ITypeLib_Release(pTypeLib
);
3645 static void test_external_connection(void)
3647 IStream
*stream
, *stream2
;
3648 ITestSecondDisp
*second
;
3654 static const LARGE_INTEGER zero
;
3656 trace("Testing IExternalConnection...\n");
3658 external_connections
= 0;
3660 /* Marshaling an interface increases external connection count. */
3661 expect_last_release_closes
= FALSE
;
3662 hres
= CreateStreamOnHGlobal(NULL
, TRUE
, &stream
);
3663 ok(hres
== S_OK
, "CreateStreamOnHGlobal failed: %08lx\n", hres
);
3664 tid
= start_host_object(stream
, &IID_ItestDual
, (IUnknown
*)&TestDual
, MSHLFLAGS_NORMAL
, &thread
);
3665 ok(external_connections
== 1, "external_connections = %d\n", external_connections
);
3667 IStream_Seek(stream
, zero
, STREAM_SEEK_SET
, NULL
);
3668 hres
= CoUnmarshalInterface(stream
, &IID_ItestDual
, (void**)&iface
);
3669 ok(hres
== S_OK
, "CoUnmarshalInterface failed: %08lx\n", hres
);
3672 end_host_object(tid
, thread
);
3673 IStream_Release(stream
);
3676 ok(external_connections
== 1, "external_connections = %d\n", external_connections
);
3678 IStream_Release(stream
);
3679 ok(external_connections
== 1, "external_connections = %d\n", external_connections
);
3681 /* Creating a stub for new iface causes new external connection. */
3682 hres
= ItestDual_QueryInterface(iface
, &IID_ITestSecondDisp
, (void**)&second
);
3683 ok(hres
== S_OK
, "Could not get ITestSecondDisp iface: %08lx\n", hres
);
3685 ok(external_connections
== 2, "external_connections = %d\n", external_connections
);
3687 ITestSecondDisp_Release(second
);
3689 ok(external_connections
== 2, "external_connections = %d\n", external_connections
);
3691 expect_last_release_closes
= TRUE
;
3692 ItestDual_Release(iface
);
3693 ok(external_connections
== 0, "external_connections = %d\n", external_connections
);
3695 end_host_object(tid
, thread
);
3697 /* A test with direct CoMarshalInterface call. */
3698 hres
= CreateStreamOnHGlobal(NULL
, TRUE
, &stream
);
3699 ok(hres
== S_OK
, "CreateStreamOnHGlobal failed: %08lx\n", hres
);
3701 expect_last_release_closes
= FALSE
;
3702 hres
= CoMarshalInterface(stream
, &IID_ItestDual
, (IUnknown
*)&TestDual
, MSHCTX_INPROC
, NULL
, MSHLFLAGS_NORMAL
);
3703 ok(hres
== S_OK
, "CoMarshalInterface failed: %08lx\n", hres
);
3704 ok(external_connections
== 1, "external_connections = %d\n", external_connections
);
3706 expect_last_release_closes
= TRUE
;
3707 IStream_Seek(stream
, zero
, STREAM_SEEK_SET
, NULL
);
3708 hres
= CoReleaseMarshalData(stream
);
3709 ok(hres
== S_OK
, "CoReleaseMarshalData failed: %08lx\n", hres
);
3710 ok(external_connections
== 0, "external_connections = %d\n", external_connections
);
3712 /* Two separated marshal data are still one external connection. */
3713 hres
= CreateStreamOnHGlobal(NULL
, TRUE
, &stream2
);
3714 ok(hres
== S_OK
, "CreateStreamOnHGlobal failed: %08lx\n", hres
);
3716 expect_last_release_closes
= FALSE
;
3717 IStream_Seek(stream
, zero
, STREAM_SEEK_SET
, NULL
);
3718 hres
= CoMarshalInterface(stream
, &IID_ItestDual
, (IUnknown
*)&TestDual
, MSHCTX_INPROC
, NULL
, MSHLFLAGS_NORMAL
);
3719 ok(hres
== S_OK
, "CoMarshalInterface failed: %08lx\n", hres
);
3720 ok(external_connections
== 1, "external_connections = %d\n", external_connections
);
3722 hres
= CoMarshalInterface(stream2
, &IID_ItestDual
, (IUnknown
*)&TestDual
, MSHCTX_INPROC
, NULL
, MSHLFLAGS_NORMAL
);
3723 ok(hres
== S_OK
, "CoMarshalInterface failed: %08lx\n", hres
);
3724 ok(external_connections
== 1, "external_connections = %d\n", external_connections
);
3726 IStream_Seek(stream
, zero
, STREAM_SEEK_SET
, NULL
);
3727 hres
= CoReleaseMarshalData(stream
);
3728 ok(hres
== S_OK
, "CoReleaseMarshalData failed: %08lx\n", hres
);
3729 ok(external_connections
== 1, "external_connections = %d\n", external_connections
);
3731 expect_last_release_closes
= TRUE
;
3732 IStream_Seek(stream2
, zero
, STREAM_SEEK_SET
, NULL
);
3733 hres
= CoReleaseMarshalData(stream2
);
3734 ok(hres
== S_OK
, "CoReleaseMarshalData failed: %08lx\n", hres
);
3735 ok(external_connections
== 0, "external_connections = %d\n", external_connections
);
3737 IStream_Release(stream
);
3738 IStream_Release(stream2
);
3740 /* Weak table marshaling does not increment external connections */
3741 hres
= CreateStreamOnHGlobal(NULL
, TRUE
, &stream
);
3742 ok(hres
== S_OK
, "CreateStreamOnHGlobal failed: %08lx\n", hres
);
3744 hres
= CoMarshalInterface(stream
, &IID_ItestDual
, (IUnknown
*)&TestDual
, MSHCTX_INPROC
, NULL
, MSHLFLAGS_TABLEWEAK
);
3745 ok(hres
== S_OK
, "CoMarshalInterface failed: %08lx\n", hres
);
3746 ok(external_connections
== 0, "external_connections = %d\n", external_connections
);
3748 IStream_Seek(stream
, zero
, STREAM_SEEK_SET
, NULL
);
3749 hres
= CoUnmarshalInterface(stream
, &IID_ItestDual
, (void**)&iface
);
3750 ok(hres
== S_OK
, "CoUnmarshalInterface failed: %08lx\n", hres
);
3751 ok(external_connections
== 0, "external_connections = %d\n", external_connections
);
3752 ItestDual_Release(iface
);
3754 IStream_Seek(stream
, zero
, STREAM_SEEK_SET
, NULL
);
3755 hres
= CoReleaseMarshalData(stream
);
3756 ok(hres
== S_OK
, "CoReleaseMarshalData failed: %08lx\n", hres
);
3757 ok(external_connections
== 0, "external_connections = %d\n", external_connections
);
3759 IStream_Release(stream
);
3762 static void test_marshal_dispinterface(void)
3764 static const LARGE_INTEGER zero
;
3766 ISomethingFromDispatch
*disp_obj
= create_disp_obj2(false);
3767 ITypeInfo
*typeinfo
= NULL
;
3768 IDispatch
*proxy_disp
;
3775 CreateStreamOnHGlobal(NULL
, TRUE
, &stream
);
3776 tid
= start_host_object(stream
, &DIID_ItestIF4
, (IUnknown
*)disp_obj
, MSHLFLAGS_NORMAL
, &thread
);
3777 IStream_Seek(stream
, zero
, STREAM_SEEK_SET
, NULL
);
3778 hr
= CoUnmarshalInterface(stream
, &DIID_ItestIF4
, (void **)&proxy_disp
);
3779 ok(hr
== S_OK
, "Got hr %#lx.\n", hr
);
3781 hr
= IDispatch_GetTypeInfo(proxy_disp
, 0xdeadbeef, 0, &typeinfo
);
3782 ok(hr
== 0xbeefdead, "Got hr %#lx.\n", hr
);
3784 ref
= IDispatch_Release(proxy_disp
);
3785 ok(!ref
, "Got outstanding refcount %ld.\n", ref
);
3786 ref
= IStream_Release(stream
);
3787 ok(!ref
, "Got outstanding refcount %ld.\n", ref
);
3788 end_host_object(tid
, thread
);
3789 ref
= ISomethingFromDispatch_Release(disp_obj
);
3790 ok(!ref
, "Got outstanding refcount %ld.\n", ref
);
3793 START_TEST(tmarshal
)
3797 CoInitializeEx(NULL
, COINIT_APARTMENTTHREADED
);
3799 hr
= register_current_module_typelib();
3803 win_skip("Registration of the test typelib failed, skipping tests\n");
3807 test_typelibmarshal();
3808 test_DispCallFunc();
3809 test_StaticWidget();
3811 test_external_connection();
3812 test_marshal_dispinterface();
3814 hr
= UnRegisterTypeLib(&LIBID_TestTypelib
, 2, 5, LOCALE_NEUTRAL
,
3815 sizeof(void*) == 8 ? SYS_WIN64
: SYS_WIN32
);
3816 ok_ole_success(hr
, UnRegisterTypeLib
);