ReactOS 0.4.15-dev-8612-g0707475
tmarshal.c
Go to the documentation of this file.
1/*
2 * Copyright (C) 2005-2006 Robert Shearman for CodeWeavers
3 *
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.
8 *
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.
13 *
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
17 *
18 */
19
20#include <math.h>
21
22#define COBJMACROS
23#define CONST_VTABLE
24
25#include <windows.h>
26#include <ocidl.h>
27#include <stdio.h>
28
29#include "wine/test.h"
30
31#include "tmarshal.h"
32
34
35
36#define ok_ole_success(hr, func) ok(hr == S_OK, #func " failed with error 0x%08x\n", hr)
37static inline void release_iface_(unsigned int line, void *iface)
38{
39 ULONG ref = IUnknown_Release((IUnknown *)iface);
40 ok_(__FILE__, line)(!ref, "Got outstanding refcount %d.\n", ref);
41 if (ref == 1) IUnknown_Release((IUnknown *)iface);
42}
43#define release_iface(a) release_iface_(__LINE__, a)
44
45/* ULL suffix is not portable */
46#define ULL_CONST(dw1, dw2) ((((ULONGLONG)dw1) << 32) | (ULONGLONG)dw2)
47
48static const WCHAR test_bstr1[] = {'f','o','o',0,'b','a','r'};
49static const WCHAR test_bstr2[] = {'t','e','s','t',0};
50static const WCHAR test_bstr3[] = {'q','u','x',0};
51static const WCHAR test_bstr4[] = {'a','b','c',0};
52
53static const MYSTRUCT test_mystruct1 = {0x12345678, ULL_CONST(0xdeadbeef, 0x98765432), {0,1,2,3,4,5,6,7}};
54static const MYSTRUCT test_mystruct2 = {0x91827364, ULL_CONST(0x88776655, 0x44332211), {3,6,1,4,0,1,3,0}};
55static const MYSTRUCT test_mystruct3 = {0x1a1b1c1d, ULL_CONST(0x1e1f1011, 0x12131415), {9,2,4,5,6,5,1,3}};
56static const MYSTRUCT test_mystruct4 = {0x2a2b2c2d, ULL_CONST(0x2e2f2021, 0x22232425), {0,4,6,7,3,6,7,4}};
57static const MYSTRUCT test_mystruct5 = {0x3a3b3c3d, ULL_CONST(0x3e3f3031, 0x32333435), {1,6,7,3,8,4,6,5}};
58static const MYSTRUCT test_mystruct6 = {0x4a4b4c4d, ULL_CONST(0x4e4f4041, 0x42434445), {3,6,5,3,4,8,0,9}};
59static const MYSTRUCT test_mystruct7 = {0x5a5b5c5d, ULL_CONST(0x5e5f5051, 0x52535455), {1,8,4,4,4,2,3,1}};
60
61static const struct thin test_thin_struct = {-456, 78};
62
63static const RECT test_rect1 = {1,2,3,4};
64static const RECT test_rect2 = {5,6,7,8};
65static const RECT test_rect3 = {9,10,11,12};
66static const RECT test_rect4 = {13,14,15,16};
67static const RECT test_rect5 = {17,18,19,20};
68static const RECT test_rect6 = {21,22,23,24};
69static const RECT test_rect7 = {25,26,27,28};
70
71static const array_t test_array1 = {1,2,3,4};
72static const array_t test_array2 = {5,6,7,8};
73static const array_t test_array3 = {9,10,11,12};
74static const array_t test_array4 = {13,14,15,16};
75static const array_t test_array5 = {17,18,19,20};
76static const array_t test_array6 = {21,22,23,24};
77
78#define RELEASEMARSHALDATA WM_USER
79
81{
83 IID iid;
85 MSHLFLAGS marshal_flags;
88};
89
91{
92 struct host_object_data *data = p;
93 HRESULT hr;
94 MSG msg;
95
97
98 if (data->filter)
99 {
100 IMessageFilter * prev_filter = NULL;
101 hr = CoRegisterMessageFilter(data->filter, &prev_filter);
102 if (prev_filter) IMessageFilter_Release(prev_filter);
104 }
105
106 hr = CoMarshalInterface(data->stream, &data->iid, data->object, MSHCTX_INPROC, NULL, data->marshal_flags);
108
109 /* force the message queue to be created before signaling parent thread */
111
112 SetEvent(data->marshal_event);
113
114 while (GetMessageA(&msg, NULL, 0, 0))
115 {
116 if (msg.hwnd == NULL && msg.message == RELEASEMARSHALDATA)
117 {
118 trace("releasing marshal data\n");
119 CoReleaseMarshalData(data->stream);
120 SetEvent((HANDLE)msg.lParam);
121 }
122 else
124 }
125
127
129
130 return hr;
131}
132
134{
135 DWORD tid = 0;
137 struct host_object_data *data = HeapAlloc(GetProcessHeap(), 0, sizeof(*data));
138
139 data->stream = stream;
140 data->iid = *riid;
141 data->object = object;
142 data->marshal_flags = marshal_flags;
143 data->marshal_event = marshal_event;
144 data->filter = filter;
145
147
148 /* wait for marshaling to complete before returning */
151
152 return tid;
153}
154
156{
158}
159
160#if 0 /* not used */
161/* asks thread to release the marshal data because it has to be done by the
162 * same thread that marshaled the interface in the first place. */
163static void release_host_object(DWORD tid)
164{
169}
170#endif
171
173{
175 ok(ret, "PostThreadMessage failed with error %d\n", GetLastError());
176 /* be careful of races - don't return until hosting thread has terminated */
179}
180
183
185{
186 ok(0, "unexpected call\n");
187 *ppv = NULL;
188 return E_NOINTERFACE;
189}
190
192{
193 return 2;
194}
195
197{
198 return 1;
199}
200
202{
203 trace("add connection\n");
204
205 ok(extconn == EXTCONN_STRONG, "extconn = %d\n", extconn);
206 ok(!reserved, "reserved = %x\n", reserved);
207 return ++external_connections;
208}
209
211 DWORD reserved, BOOL fLastReleaseCloses)
212{
213 trace("release connection\n");
214
215 ok(extconn == EXTCONN_STRONG, "extconn = %d\n", extconn);
216 ok(!reserved, "reserved = %x\n", reserved);
217
218 ok(fLastReleaseCloses == expect_last_release_closes, "fLastReleaseCloses = %x, expected %x\n",
219 fLastReleaseCloses, expect_last_release_closes);
220 return --external_connections;
221}
222
223static const IExternalConnectionVtbl ExternalConnectionVtbl = {
229};
230
232
233static ItestDual TestDual, TestDualDisp;
234
235static HRESULT WINAPI TestSecondIface_QueryInterface(ITestSecondIface *iface, REFIID riid, void **ppv)
236{
237 return ItestDual_QueryInterface(&TestDual, riid, ppv);
238}
239
240static ULONG WINAPI TestSecondIface_AddRef(ITestSecondIface *iface)
241{
242 return 2;
243}
244
245static ULONG WINAPI TestSecondIface_Release(ITestSecondIface *iface)
246{
247 return 1;
248}
249
250static HRESULT WINAPI TestSecondIface_test(ITestSecondIface *iface)
251{
252 return 1;
253}
254
255static const ITestSecondIfaceVtbl TestSecondIfaceVtbl = {
260};
261
262static ITestSecondIface TestSecondIface = { &TestSecondIfaceVtbl };
263
264static HRESULT WINAPI TestSecondDisp_QueryInterface(ITestSecondDisp *iface, REFIID riid, void **ppv)
265{
266 return ItestDual_QueryInterface(&TestDual, riid, ppv);
267}
268
269static ULONG WINAPI TestSecondDisp_AddRef(ITestSecondDisp *iface)
270{
271 return 2;
272}
273
274static ULONG WINAPI TestSecondDisp_Release(ITestSecondDisp *iface)
275{
276 return 1;
277}
278
279static HRESULT WINAPI TestSecondDisp_GetTypeInfoCount(ITestSecondDisp *iface, UINT *pctinfo)
280{
281 ok(0, "unexpected call\n");
282 return E_NOTIMPL;
283}
284
285static HRESULT WINAPI TestSecondDisp_GetTypeInfo(ITestSecondDisp *iface, UINT iTInfo, LCID lcid, ITypeInfo **ppTInfo)
286{
287 ok(0, "unexpected call\n");
288 return E_NOTIMPL;
289}
290
291static HRESULT WINAPI TestSecondDisp_GetIDsOfNames(ITestSecondDisp *iface, REFIID riid, LPOLESTR *rgszNames,
292 UINT cNames, LCID lcid, DISPID *rgDispId)
293{
294 ok(0, "unexpected call\n");
295 return E_NOTIMPL;
296}
297
298static HRESULT WINAPI TestSecondDisp_Invoke(ITestSecondDisp *iface, DISPID dispIdMember, REFIID riid, LCID lcid,
299 WORD wFlags, DISPPARAMS *pDispParams, VARIANT *pVarResult, EXCEPINFO *pExcepInfo,
300 UINT *puArgErr)
301{
302 ok(0, "unexpected call\n");
303 return E_NOTIMPL;
304}
305
306static HRESULT WINAPI TestSecondDisp_test(ITestSecondDisp *iface)
307{
308 ok(0, "unexpected call\n");
309 return E_NOTIMPL;
310}
311
312static ITestSecondDispVtbl TestSecondDispVtbl = {
321};
322
323static ITestSecondDisp TestSecondDisp = { &TestSecondDispVtbl };
324
326{
329 return S_OK;
330 }else if(IsEqualGUID(riid, &IID_ItestDual)) {
332 return S_OK;
333 }else if(IsEqualGUID(riid, &IID_ITestSecondIface)) {
335 return S_OK;
336 }else if(IsEqualGUID(riid, &IID_ITestSecondDisp)) {
338 return S_OK;
339 }else if (IsEqualGUID(riid, &IID_IExternalConnection)) {
340 trace("QI external connection\n");
342 return S_OK;
343 }
344
345 *ppvObject = NULL;
346 return E_NOINTERFACE;
347}
348
349static ULONG WINAPI TestDual_AddRef(ItestDual *iface)
350{
351 return 2;
352}
353
354static ULONG WINAPI TestDual_Release(ItestDual *iface)
355{
356 return 1;
357}
358
359static HRESULT WINAPI TestDual_GetTypeInfoCount(ItestDual *iface, UINT *pctinfo)
360{
361 ok(0, "unexpected call\n");
362 return E_NOTIMPL;
363}
364
365static HRESULT WINAPI TestDual_GetTypeInfo(ItestDual *iface, UINT iTInfo, LCID lcid, ITypeInfo **ppTInfo)
366{
367 ok(0, "unexpected call\n");
368 return E_NOTIMPL;
369}
370
371static HRESULT WINAPI TestDual_GetIDsOfNames(ItestDual *iface, REFIID riid, LPOLESTR *rgszNames,
372 UINT cNames, LCID lcid, DISPID *rgDispId)
373{
374 ok(0, "unexpected call\n");
375 return E_NOTIMPL;
376}
377
378static HRESULT WINAPI TestDual_Invoke(ItestDual *iface, DISPID dispIdMember, REFIID riid, LCID lcid,
379 WORD wFlags, DISPPARAMS *pDispParams, VARIANT *pVarResult, EXCEPINFO *pExcepInfo,
380 UINT *puArgErr)
381{
382 ok(0, "unexpected call\n");
383 return E_NOTIMPL;
384}
385
386static ItestDualVtbl TestDualVtbl = {
394};
395
396static ItestDual TestDual = { &TestDualVtbl };
397static ItestDual TestDualDisp = { &TestDualVtbl };
398
400{
401 ISomethingFromDispatch ISomethingFromDispatch_iface;
403};
404
405static inline struct disp_obj *impl_from_ISomethingFromDispatch(ISomethingFromDispatch *iface)
406{
408}
409
410static HRESULT WINAPI disp_obj_QueryInterface(ISomethingFromDispatch *iface, REFIID iid, void **out)
411{
413 || IsEqualGUID(iid, &IID_ISomethingFromDispatch)
414 || IsEqualGUID(iid, &DIID_ItestIF4))
415 {
416 *out = iface;
417 ISomethingFromDispatch_AddRef(iface);
418 return S_OK;
419 }
420
421 *out = NULL;
422 return E_NOINTERFACE;
423}
424
425static ULONG WINAPI disp_obj_AddRef(ISomethingFromDispatch *iface)
426{
428 return ++obj->ref;
429}
430
431static ULONG WINAPI disp_obj_Release(ISomethingFromDispatch *iface)
432{
434 LONG ref = --obj->ref;
435 if (!ref)
437 return ref;
438}
439
440static HRESULT WINAPI disp_obj_GetTypeInfoCount(ISomethingFromDispatch *iface, UINT *count)
441{
442 ok(0, "unexpected call\n");
443 return E_NOTIMPL;
444}
445
446static HRESULT WINAPI disp_obj_GetTypeInfo(ISomethingFromDispatch *iface,
448{
449 ok(index == 0xdeadbeef, "Got unexpected index %#x.\n", index);
450 return 0xbeefdead;
451}
452
453static HRESULT WINAPI disp_obj_GetIDsOfNames(ISomethingFromDispatch *iface,
454 REFIID iid, LPOLESTR *names, UINT count, LCID lcid, DISPID *ids)
455{
456 ok(0, "unexpected call\n");
457 return E_NOTIMPL;
458}
459
460static HRESULT WINAPI disp_obj_Invoke(ISomethingFromDispatch *iface, DISPID id, REFIID iid, LCID lcid,
461 WORD flags, DISPPARAMS *dispparams, VARIANT *result, EXCEPINFO *excepinfo, UINT *errarg)
462{
463 ok(0, "unexpected call\n");
464 return E_NOTIMPL;
465}
466
467static HRESULT WINAPI disp_obj_anotherfn(ISomethingFromDispatch *iface)
468{
469 return 0x01234567;
470}
471
472static const ISomethingFromDispatchVtbl disp_obj_vtbl =
473{
482};
483
484static ISomethingFromDispatch *create_disp_obj(void)
485{
486 struct disp_obj *obj = CoTaskMemAlloc(sizeof(*obj));
487 obj->ISomethingFromDispatch_iface.lpVtbl = &disp_obj_vtbl;
488 obj->ref = 1;
489 return &obj->ISomethingFromDispatch_iface;
490}
491
493{
497};
498
499static inline struct coclass_obj *impl_from_ICoclass1(ICoclass1 *iface)
500{
501 return CONTAINING_RECORD(iface, struct coclass_obj, ICoclass1_iface);
502}
503
504static inline struct coclass_obj *impl_from_ICoclass2(ICoclass2 *iface)
505{
506 return CONTAINING_RECORD(iface, struct coclass_obj, ICoclass2_iface);
507}
508
509static HRESULT WINAPI coclass1_QueryInterface(ICoclass1 *iface, REFIID iid, void **out)
510{
511 struct coclass_obj *obj = impl_from_ICoclass1(iface);
512
513 if (IsEqualGUID(iid, &IID_IUnknown)
514 || IsEqualGUID(iid, &IID_IDispatch)
515 || IsEqualGUID(iid, &IID_ICoclass1))
516 {
517 *out = iface;
518 ICoclass1_AddRef(iface);
519 return S_OK;
520 }
521 else if (IsEqualGUID(iid, &IID_ICoclass2))
522 {
523 *out = &obj->ICoclass2_iface;
524 ICoclass2_AddRef(*out);
525 return S_OK;
526 }
527
528 *out = NULL;
529 return E_NOINTERFACE;
530}
531
532static ULONG WINAPI coclass1_AddRef(ICoclass1 *iface)
533{
534 struct coclass_obj *obj = impl_from_ICoclass1(iface);
535 return ++obj->ref;
536}
537
538static ULONG WINAPI coclass1_Release(ICoclass1 *iface)
539{
540 struct coclass_obj *obj = impl_from_ICoclass1(iface);
541 LONG ref = --obj->ref;
542 if (!ref)
544 return ref;
545}
546
548{
549 ok(0, "unexpected call\n");
550 return E_NOTIMPL;
551}
552
554 LCID lcid, ITypeInfo **typeinfo)
555{
556 ok(index == 0xdeadbeef, "Got unexpected index %#x.\n", index);
557 return 0xbeefdead;
558}
559
560static HRESULT WINAPI coclass1_GetIDsOfNames(ICoclass1 *iface, REFIID iid,
562{
563 ok(0, "unexpected call\n");
564 return E_NOTIMPL;
565}
566
567static HRESULT WINAPI coclass1_Invoke(ICoclass1 *iface, DISPID id, REFIID iid, LCID lcid,
568 WORD flags, DISPPARAMS *dispparams, VARIANT *result, EXCEPINFO *excepinfo, UINT *errarg)
569{
570 ok(0, "unexpected call\n");
571 return E_NOTIMPL;
572}
573
574static HRESULT WINAPI coclass1_test(ICoclass1 *iface)
575{
576 return 1;
577}
578
579static HRESULT WINAPI coclass2_QueryInterface(ICoclass2 *iface, REFIID iid, void **out)
580{
581 struct coclass_obj *obj = impl_from_ICoclass2(iface);
582 return ICoclass1_QueryInterface(&obj->ICoclass1_iface, iid, out);
583}
584
585static ULONG WINAPI coclass2_AddRef(ICoclass2 *iface)
586{
587 struct coclass_obj *obj = impl_from_ICoclass2(iface);
588 return ICoclass1_AddRef(&obj->ICoclass1_iface);
589}
590
591static ULONG WINAPI coclass2_Release(ICoclass2 *iface)
592{
593 struct coclass_obj *obj = impl_from_ICoclass2(iface);
594 return ICoclass1_Release(&obj->ICoclass1_iface);
595}
596
598{
599 ok(0, "unexpected call\n");
600 return E_NOTIMPL;
601}
602
604 LCID lcid, ITypeInfo **typeinfo)
605{
606 ok(index == 0xdeadbeef, "Got unexpected index %#x.\n", index);
607 return 0xbeefdead;
608}
609
610static HRESULT WINAPI coclass2_GetIDsOfNames(ICoclass2 *iface, REFIID iid,
612{
613 ok(0, "unexpected call\n");
614 return E_NOTIMPL;
615}
616
617static HRESULT WINAPI coclass2_Invoke(ICoclass2 *iface, DISPID id, REFIID iid, LCID lcid,
618 WORD flags, DISPPARAMS *dispparams, VARIANT *result, EXCEPINFO *excepinfo, UINT *errarg)
619{
620 ok(0, "unexpected call\n");
621 return E_NOTIMPL;
622}
623
624static HRESULT WINAPI coclass2_test(ICoclass2 *iface)
625{
626 return 2;
627}
628
629static const ICoclass1Vtbl coclass1_vtbl =
630{
639};
640
641static const ICoclass2Vtbl coclass2_vtbl =
642{
651};
652
653static struct coclass_obj *create_coclass_obj(void)
654{
655 struct coclass_obj *obj = CoTaskMemAlloc(sizeof(*obj));
656 obj->ICoclass1_iface.lpVtbl = &coclass1_vtbl;
657 obj->ICoclass2_iface.lpVtbl = &coclass2_vtbl;
658 obj->ref = 1;
659 return obj;
660};
661
662static int testmode;
663
664typedef struct Widget
665{
670
671static inline Widget *impl_from_IWidget(IWidget *iface)
672{
673 return CONTAINING_RECORD(iface, Widget, IWidget_iface);
674}
675
677 IWidget *iface,
678 /* [in] */ REFIID riid,
679 /* [iid_is][out] */ void __RPC_FAR *__RPC_FAR *ppvObject)
680{
682 {
683 IWidget_AddRef(iface);
684 *ppvObject = iface;
685 return S_OK;
686 }
687 else
688 {
689 *ppvObject = NULL;
690 return E_NOINTERFACE;
691 }
692}
693
695 IWidget *iface)
696{
697 Widget *This = impl_from_IWidget(iface);
698
699 return InterlockedIncrement(&This->refs);
700}
701
703 IWidget *iface)
704{
705 Widget *This = impl_from_IWidget(iface);
706 ULONG refs = InterlockedDecrement(&This->refs);
707 if (!refs)
708 {
709 IUnknown_Release(This->pDispatchUnknown);
710 memset(This, 0xcc, sizeof(*This));
712 trace("Widget destroyed!\n");
713 }
714
715 return refs;
716}
717
719 IWidget *iface,
720 /* [out] */ UINT __RPC_FAR *pctinfo)
721{
722 Widget *This = impl_from_IWidget(iface);
723 IDispatch *pDispatch;
724 HRESULT hr = IUnknown_QueryInterface(This->pDispatchUnknown, &IID_IDispatch, (void **)&pDispatch);
725 if (SUCCEEDED(hr))
726 {
727 hr = IDispatch_GetTypeInfoCount(pDispatch, pctinfo);
728 IDispatch_Release(pDispatch);
729 }
730 return hr;
731}
732
734 IWidget __RPC_FAR * iface,
735 /* [in] */ UINT iTInfo,
736 /* [in] */ LCID lcid,
737 /* [out] */ ITypeInfo __RPC_FAR *__RPC_FAR *ppTInfo)
738{
739 Widget *This = impl_from_IWidget(iface);
740 IDispatch *pDispatch;
741 HRESULT hr = IUnknown_QueryInterface(This->pDispatchUnknown, &IID_IDispatch, (void **)&pDispatch);
742 if (SUCCEEDED(hr))
743 {
744 hr = IDispatch_GetTypeInfo(pDispatch, iTInfo, lcid, ppTInfo);
745 IDispatch_Release(pDispatch);
746 }
747 return hr;
748}
749
751 IWidget __RPC_FAR * iface,
752 /* [in] */ REFIID riid,
753 /* [size_is][in] */ LPOLESTR __RPC_FAR *rgszNames,
754 /* [in] */ UINT cNames,
755 /* [in] */ LCID lcid,
756 /* [size_is][out] */ DISPID __RPC_FAR *rgDispId)
757{
758 Widget *This = impl_from_IWidget(iface);
759 IDispatch *pDispatch;
760 HRESULT hr = IUnknown_QueryInterface(This->pDispatchUnknown, &IID_IDispatch, (void **)&pDispatch);
761 if (SUCCEEDED(hr))
762 {
763 hr = IDispatch_GetIDsOfNames(pDispatch, riid, rgszNames, cNames, lcid, rgDispId);
764 IDispatch_Release(pDispatch);
765 }
766 return hr;
767}
768
770 IWidget __RPC_FAR * iface,
771 /* [in] */ DISPID dispIdMember,
772 /* [in] */ REFIID riid,
773 /* [in] */ LCID lcid,
774 /* [in] */ WORD wFlags,
775 /* [out][in] */ DISPPARAMS __RPC_FAR *pDispParams,
776 /* [out] */ VARIANT __RPC_FAR *pVarResult,
777 /* [out] */ EXCEPINFO __RPC_FAR *pExcepInfo,
778 /* [out] */ UINT __RPC_FAR *puArgErr)
779{
780 Widget *This = impl_from_IWidget(iface);
781 IDispatch *pDispatch;
782 HRESULT hr = IUnknown_QueryInterface(This->pDispatchUnknown, &IID_IDispatch, (void **)&pDispatch);
783 if (SUCCEEDED(hr))
784 {
785 hr = IDispatch_Invoke(pDispatch, dispIdMember, riid, lcid, wFlags, pDispParams, pVarResult, pExcepInfo, puArgErr);
786 IDispatch_Release(pDispatch);
787 }
788 return hr;
789}
790
792 IWidget __RPC_FAR * iface,
793 /* [in] */ BSTR name)
794{
795 trace("put_Name(%s)\n", wine_dbgstr_w(name));
796 return S_OK;
797}
798
800 IWidget __RPC_FAR * iface,
801 /* [out] */ BSTR __RPC_FAR *name)
802{
803 static const WCHAR szCat[] = { 'C','a','t',0 };
804 trace("get_Name()\n");
805 *name = SysAllocString(szCat);
806 return S_OK;
807}
808
810 IWidget __RPC_FAR * iface,
811 /* [in] */ double number,
812 /* [out] */ BSTR *str1,
813 /* [defaultvalue][in] */ BSTR str2,
814 /* [optional][in] */ VARIANT __RPC_FAR *opt)
815{
816 static const WCHAR szString[] = { 'S','t','r','i','n','g',0 };
817 trace("DoSomething()\n");
818
819 ok(number == 3.141, "number(%f) != 3.141\n", number);
820 ok(*str2 == '\0', "str2(%s) != \"\"\n", wine_dbgstr_w(str2));
821 ok(V_VT(opt) == VT_ERROR, "V_VT(opt) should be VT_ERROR instead of 0x%x\n", V_VT(opt));
822 ok(V_ERROR(opt) == DISP_E_PARAMNOTFOUND, "V_ERROR(opt) should be DISP_E_PARAMNOTFOUND instead of 0x%08x\n", V_ERROR(opt));
823 *str1 = SysAllocString(szString);
824
825 return S_FALSE;
826}
827
829 IWidget __RPC_FAR * iface,
830 /* [retval][out] */ STATE __RPC_FAR *state)
831{
832 trace("get_State() = STATE_WIDGETIFIED\n");
833 *state = STATE_WIDGETIFIED;
834 return S_OK;
835}
836
838 IWidget __RPC_FAR * iface,
839 /* [in] */ STATE state)
840{
841 trace("put_State(%d)\n", state);
842 return S_OK;
843}
844
846 IWidget * iface,
847 BSTR bstrId,
848 BSTR *sValue)
849{
850 trace("Map(%s, %p)\n", wine_dbgstr_w(bstrId), sValue);
851 *sValue = SysAllocString(bstrId);
852 return S_OK;
853}
854
856 IWidget * iface,
857 OLE_COLOR val)
858{
859 trace("SetOleColor(0x%x)\n", val);
860 return S_OK;
861}
862
864 IWidget * iface,
865 OLE_COLOR *pVal)
866{
867 trace("GetOleColor() = 0x8000000f\n");
868 *pVal = 0x8000000f;
869 return S_FALSE;
870}
871
873 IWidget *iface,
874 IWidget **ppVal)
875{
876 trace("Clone()\n");
877 return Widget_QueryInterface(iface, &IID_IWidget, (void **)ppVal);
878}
879
881 IWidget *iface,
882 IDispatch **ppVal)
883{
884 trace("CloneDispatch()\n");
885 return Widget_QueryInterface(iface, &IID_IWidget, (void **)ppVal);
886}
887
889 IWidget *iface,
890 ApplicationObject2 **ppVal)
891{
892 trace("CloneCoclass()\n");
893 return Widget_QueryInterface(iface, &IID_IWidget, (void **)ppVal);
894}
895
897 IWidget __RPC_FAR * iface,
898 VARIANT *value,
899 VARIANT *retval)
900{
901 trace("Value(%p, %p)\n", value, retval);
902 ok(V_VT(value) == VT_I2, "V_VT(value) was %d instead of VT_I2\n", V_VT(value));
903 ok(V_I2(value) == 1, "V_I2(value) was %d instead of 1\n", V_I2(value));
904 V_VT(retval) = VT_I2;
905 V_I2(retval) = 1234;
906 return S_OK;
907}
908
910 IWidget * iface,
911 SAFEARRAY ** values)
912{
913 trace("VariantArrayPtr(%p)\n", values);
914 return S_OK;
915}
916
918 IWidget * iface,
919 int numexpect,
921{
922 LONG lbound, ubound, i;
923 VARIANT * data;
924 HRESULT hr;
925
926 trace("VarArg(%p)\n", values);
927
928 hr = SafeArrayGetLBound(values, 1, &lbound);
929 ok(hr == S_OK, "SafeArrayGetLBound failed with %x\n", hr);
930 ok(lbound == 0, "SafeArrayGetLBound returned %d\n", lbound);
931
932 hr = SafeArrayGetUBound(values, 1, &ubound);
933 ok(hr == S_OK, "SafeArrayGetUBound failed with %x\n", hr);
934 ok(ubound == numexpect-1, "SafeArrayGetUBound returned %d, but expected %d\n", ubound, numexpect-1);
935
937 ok(hr == S_OK, "SafeArrayAccessData failed with %x\n", hr);
938
939 for (i=0; i<=ubound-lbound; i++)
940 {
941 ok(V_VT(&data[i]) == VT_I4, "V_VT(&data[%d]) was %d\n", i, V_VT(&data[i]));
942 ok(V_I4(&data[i]) == i, "V_I4(&data[%d]) was %d\n", i, V_I4(&data[i]));
943 }
944
946 ok(hr == S_OK, "SafeArrayUnaccessData failed with %x\n", hr);
947
948 return S_OK;
949}
950
952 IWidget __RPC_FAR * iface)
953{
954 trace("Error()\n");
955 return E_NOTIMPL;
956}
957
959 IWidget __RPC_FAR * iface,
960 ISomethingFromDispatch **ppVal)
961{
962 trace("CloneInterface()\n");
963 *ppVal = 0;
964 return S_OK;
965}
966
968 IWidget* iface, LONG lcid, INT i)
969{
970 trace("put_prop_with_lcid(%08x, %x)\n", lcid, i);
971 ok(lcid == MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US), "got lcid %08x\n", lcid);
972 ok(i == 0xcafe, "got %08x\n", i);
973 return S_OK;
974}
975
977 IWidget* iface, LONG lcid, INT *i)
978{
979 trace("get_prop_with_lcid(%08x, %p)\n", lcid, i);
980 ok(lcid == MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US), "got lcid %08x\n", lcid);
981 *i = lcid;
982 return S_OK;
983}
984
986 IWidget* iface, INT *i)
987{
988 trace("get_prop_int(%p)\n", i);
989 *i = -13;
990 return S_OK;
991}
992
994 IWidget* iface, UINT *i)
995{
996 trace("get_prop_uint(%p)\n", i);
997 *i = 42;
998 return S_OK;
999}
1000
1002 IWidget* iface, UINT *i)
1003{
1004 *i = 42;
1005 return S_OK;
1006}
1007
1009 IWidget* iface, INT opt, INT i)
1010{
1011 trace("put_prop_opt_arg(%08x, %08x)\n", opt, i);
1012 todo_wine ok(opt == 0, "got opt=%08x\n", opt);
1013 ok(i == 0xcafe, "got i=%08x\n", i);
1014 return S_OK;
1015}
1016
1018 IWidget* iface, INT req, INT i)
1019{
1020 trace("put_prop_req_arg(%08x, %08x)\n", req, i);
1021 ok(req == 0x5678, "got req=%08x\n", req);
1022 ok(i == 0x1234, "got i=%08x\n", i);
1023 return S_OK;
1024}
1025
1026static HRESULT WINAPI Widget_pos_restrict(IWidget* iface, INT *i)
1027{
1028 trace("restrict\n");
1030 return S_OK;
1031}
1032
1033static HRESULT WINAPI Widget_neg_restrict(IWidget* iface, INT *i)
1034{
1035 trace("neg_restrict\n");
1037 return S_OK;
1038}
1039
1041 IWidget *iface, BSTR name, SAFEARRAY *params, VARIANT *result)
1042{
1043 static const WCHAR catW[] = { 'C','a','t',0 };
1044 static const WCHAR supermanW[] = { 'S','u','p','e','r','m','a','n',0 };
1045 LONG bound;
1046 VARIANT *var;
1047 BSTR bstr;
1048 HRESULT hr;
1049
1050 trace("VarArg_Run(%p,%p,%p)\n", name, params, result);
1051
1052 ok(!lstrcmpW(name, catW), "got %s\n", wine_dbgstr_w(name));
1053
1054 hr = SafeArrayGetLBound(params, 1, &bound);
1055 ok(hr == S_OK, "SafeArrayGetLBound error %#x\n", hr);
1056 ok(bound == 0, "expected 0, got %d\n", bound);
1057
1058 hr = SafeArrayGetUBound(params, 1, &bound);
1059 ok(hr == S_OK, "SafeArrayGetUBound error %#x\n", hr);
1060 ok(bound == 0, "expected 0, got %d\n", bound);
1061
1062 hr = SafeArrayAccessData(params, (void **)&var);
1063 ok(hr == S_OK, "SafeArrayAccessData failed with %x\n", hr);
1064
1065 ok(V_VT(&var[0]) == VT_BSTR, "expected VT_BSTR, got %d\n", V_VT(&var[0]));
1066 bstr = V_BSTR(&var[0]);
1067 ok(!lstrcmpW(bstr, supermanW), "got %s\n", wine_dbgstr_w(bstr));
1068
1070 ok(hr == S_OK, "SafeArrayUnaccessData error %#x\n", hr);
1071
1072 return S_OK;
1073}
1074
1076 IWidget *iface, BSTR name, SAFEARRAY **params, VARIANT *result)
1077{
1078 static const WCHAR catW[] = { 'C','a','t',0 };
1079 static const WCHAR supermanW[] = { 'S','u','p','e','r','m','a','n',0 };
1080 LONG bound;
1081 VARIANT *var;
1082 BSTR bstr;
1083 HRESULT hr;
1084
1085 trace("VarArg_Ref_Run(%p,%p,%p)\n", name, params, result);
1086
1087 ok(!lstrcmpW(name, catW), "got %s\n", wine_dbgstr_w(name));
1088
1089 hr = SafeArrayGetLBound(*params, 1, &bound);
1090 ok(hr == S_OK, "SafeArrayGetLBound error %#x\n", hr);
1091 ok(bound == 0, "expected 0, got %d\n", bound);
1092
1093 hr = SafeArrayGetUBound(*params, 1, &bound);
1094 ok(hr == S_OK, "SafeArrayGetUBound error %#x\n", hr);
1095 ok(bound == 0, "expected 0, got %d\n", bound);
1096
1097 hr = SafeArrayAccessData(*params, (void **)&var);
1098 ok(hr == S_OK, "SafeArrayAccessData error %#x\n", hr);
1099
1100 ok(V_VT(&var[0]) == VT_BSTR, "expected VT_BSTR, got %d\n", V_VT(&var[0]));
1101 bstr = V_BSTR(&var[0]);
1102 ok(!lstrcmpW(bstr, supermanW), "got %s\n", wine_dbgstr_w(bstr));
1103
1105 ok(hr == S_OK, "SafeArrayUnaccessData error %#x\n", hr);
1106
1107 return S_OK;
1108}
1109
1110static HRESULT WINAPI Widget_basetypes_in(IWidget *iface, signed char c, short s, int i, hyper h,
1111 unsigned char uc, unsigned short us, unsigned int ui, MIDL_uhyper uh,
1112 float f, double d, STATE st)
1113{
1114 ok(c == 5, "Got char %d.\n", c);
1115 ok(s == -123, "Got short %d.\n", s);
1116 ok(i == -100000, "Got int %d.\n", i);
1117 ok(h == (LONGLONG)-100000 * 1000000, "Got hyper %s.\n", wine_dbgstr_longlong(h));
1118 ok(uc == 0, "Got unsigned char %u.\n", uc);
1119 ok(us == 456, "Got unsigned short %u.\n", us);
1120 ok(ui == 0xdeadbeef, "Got unsigned int %i.\n", ui);
1121 ok(uh == (ULONGLONG)1234567890 * 9876543210, "Got unsigned hyper %s.\n", wine_dbgstr_longlong(uh));
1122 ok(f == (float)M_PI, "Got float %f.\n", f);
1123 ok(d == M_E, "Got double %f.\n", d);
1124 ok(st == STATE_WIDGETIFIED, "Got state %u.\n", st);
1125
1126 return S_OK;
1127}
1128
1129static HRESULT WINAPI Widget_basetypes_out(IWidget *iface, signed char *c, short *s, int *i, hyper *h,
1130 unsigned char *uc, unsigned short *us, unsigned int *ui, MIDL_uhyper *uh,
1131 float *f, double *d, STATE *st)
1132{
1133 *c = 10;
1134 *s = -321;
1135 *i = -200000;
1136 *h = (LONGLONG)-200000 * 1000000;
1137 *uc = 254;
1138 *us = 256;
1139 *ui = 0xf00dfade;
1140 *uh = (((ULONGLONG)0xabcdef01) << 32) | (ULONGLONG)0x23456789;
1141 *f = M_LN2;
1142 *d = M_LN10;
1143 *st = STATE_UNWIDGETIFIED;
1144
1145 return S_OK;
1146}
1147
1148static HRESULT WINAPI Widget_float_abi(IWidget *iface, float f, double d, int i, float f2, double d2)
1149{
1150 ok(f == 1.0f, "Got float %f.\n", f);
1151 ok(d == 2.0, "Got double %f.\n", d);
1152 ok(i == 3, "Got int %d.\n", i);
1153 ok(f2 == 4.0f, "Got float %f.\n", f2);
1154 ok(d2 == 5.0, "Got double %f.\n", d2);
1155
1156 return S_OK;
1157}
1158
1159static HRESULT WINAPI Widget_int_ptr(IWidget *iface, int *in, int *out, int *in_out)
1160{
1161 ok(*in == 123, "Got [in] %d.\n", *in);
1162 if (testmode == 0) /* Invoke() */
1163 ok(*out == 456, "Got [out] %d.\n", *out);
1164 else if (testmode == 1)
1165 ok(!*out, "Got [out] %d.\n", *out);
1166 ok(*in_out == 789, "Got [in, out] %d.\n", *in_out);
1167
1168 *in = 987;
1169 *out = 654;
1170 *in_out = 321;
1171
1172 return S_OK;
1173}
1174
1175static HRESULT WINAPI Widget_int_ptr_ptr(IWidget *iface, int **in, int **out, int **in_out)
1176{
1177 ok(!*out, "Got [out] %p.\n", *out);
1178 if (testmode == 0)
1179 {
1180 ok(!*in, "Got [in] %p.\n", *in);
1181 ok(!*in_out, "Got [in, out] %p.\n", *in_out);
1182 }
1183 else if (testmode == 1)
1184 {
1185 ok(!*in, "Got [in] %p.\n", *in);
1186 ok(!*in_out, "Got [in, out] %p.\n", *in_out);
1187
1188 *out = CoTaskMemAlloc(sizeof(int));
1189 **out = 654;
1190 *in_out = CoTaskMemAlloc(sizeof(int));
1191 **in_out = 321;
1192 }
1193 else if (testmode == 2)
1194 {
1195 ok(**in == 123, "Got [in] %d.\n", **in);
1196 ok(**in_out == 789, "Got [in, out] %d.\n", **in_out);
1197
1198 *out = CoTaskMemAlloc(sizeof(int));
1199 **out = 654;
1200 **in_out = 321;
1201 }
1202 else if (testmode == 3)
1203 {
1204 ok(**in_out == 789, "Got [in, out] %d.\n", **in_out);
1205 *in_out = NULL;
1206 }
1207
1208 return S_OK;
1209}
1210
1211/* Call methods to check that we have valid proxies to each interface. */
1212static void check_iface_marshal(IUnknown *unk, IDispatch *disp, ISomethingFromDispatch *sfd)
1213{
1214 ISomethingFromDispatch *sfd2;
1216 HRESULT hr;
1217
1218 hr = IUnknown_QueryInterface(unk, &IID_ISomethingFromDispatch, (void **)&sfd2);
1219 ok(hr == S_OK, "Got hr %#x.\n", hr);
1220 ISomethingFromDispatch_Release(sfd2);
1221
1222 hr = IDispatch_GetTypeInfo(disp, 0xdeadbeef, 0, &typeinfo);
1223 ok(hr == 0xbeefdead, "Got hr %#x.\n", hr);
1224
1225 hr = ISomethingFromDispatch_anotherfn(sfd);
1226 ok(hr == 0x01234567, "Got hr %#x.\n", hr);
1227}
1228
1229static HRESULT WINAPI Widget_iface_in(IWidget *iface, IUnknown *unk, IDispatch *disp, ISomethingFromDispatch *sfd)
1230{
1231 if (testmode == 0)
1232 check_iface_marshal(unk, disp, sfd);
1233 else if (testmode == 1)
1234 {
1235 ok(!unk, "Got iface %p.\n", unk);
1236 ok(!disp, "Got iface %p.\n", disp);
1237 ok(!sfd, "Got iface %p.\n", sfd);
1238 }
1239 return S_OK;
1240}
1241
1242static HRESULT WINAPI Widget_iface_out(IWidget *iface, IUnknown **unk, IDispatch **disp, ISomethingFromDispatch **sfd)
1243{
1244 ok(!*unk, "Got iface %p.\n", *unk);
1245 ok(!*disp, "Got iface %p.\n", *disp);
1246 ok(!*sfd, "Got iface %p.\n", *sfd);
1247
1248 if (testmode == 0)
1249 {
1250 *unk = (IUnknown *)create_disp_obj();
1251 *disp = (IDispatch *)create_disp_obj();
1252 *sfd = create_disp_obj();
1253 }
1254 return S_OK;
1255}
1256
1257static HRESULT WINAPI Widget_iface_ptr(IWidget *iface, ISomethingFromDispatch **in,
1258 ISomethingFromDispatch **out, ISomethingFromDispatch **in_out)
1259{
1260 HRESULT hr;
1261
1262 ok(!*out, "Got [out] %p.\n", *out);
1263 if (testmode == 0 || testmode == 1)
1264 {
1265 hr = ISomethingFromDispatch_anotherfn(*in);
1266 ok(hr == 0x01234567, "Got hr %#x.\n", hr);
1267 hr = ISomethingFromDispatch_anotherfn(*in_out);
1268 ok(hr == 0x01234567, "Got hr %#x.\n", hr);
1269 }
1270
1271 if (testmode == 1)
1272 {
1273 *out = create_disp_obj();
1274 ISomethingFromDispatch_Release(*in_out);
1275 *in_out = create_disp_obj();
1276 }
1277 else if (testmode == 2)
1278 {
1279 ok(!*in, "Got [in] %p.\n", *in);
1280 ok(!*in_out, "Got [in, out] %p.\n", *in_out);
1281 *in_out = create_disp_obj();
1282 }
1283 else if (testmode == 3)
1284 {
1285 hr = ISomethingFromDispatch_anotherfn(*in_out);
1286 ok(hr == 0x01234567, "Got hr %#x.\n", hr);
1287 ISomethingFromDispatch_Release(*in_out);
1288 *in_out = NULL;
1289 }
1290
1291 return S_OK;
1292}
1293
1294static HRESULT WINAPI Widget_bstr(IWidget *iface, BSTR in, BSTR *out, BSTR *in_ptr, BSTR *in_out)
1295{
1296 UINT len;
1297
1298 if (testmode == 0)
1299 {
1301 ok(len == sizeof(test_bstr1), "Got wrong length %u.\n", len);
1302 ok(!memcmp(in, test_bstr1, len), "Got string %s.\n", wine_dbgstr_wn(in, len / sizeof(WCHAR)));
1303 ok(!*out, "Got unexpected output %p.\n", *out);
1304 len = SysStringLen(*in_ptr);
1305 ok(len == lstrlenW(test_bstr2), "Got wrong length %u.\n", len);
1306 ok(!memcmp(*in_ptr, test_bstr2, len), "Got string %s.\n", wine_dbgstr_w(*in_ptr));
1307 len = SysStringLen(*in_out);
1308 ok(len == lstrlenW(test_bstr3), "Got wrong length %u.\n", len);
1309 ok(!memcmp(*in_out, test_bstr3, len), "Got string %s.\n", wine_dbgstr_w(*in_out));
1310
1312 in[1] = (*in_ptr)[1] = (*in_out)[1] = 'X';
1313 }
1314 else if (testmode == 1)
1315 {
1316 ok(!in, "Got string %s.\n", wine_dbgstr_w(in));
1317 ok(!*out, "Got string %s.\n", wine_dbgstr_w(*out));
1318 ok(!*in_ptr, "Got string %s.\n", wine_dbgstr_w(*in_ptr));
1319 ok(!*in_out, "Got string %s.\n", wine_dbgstr_w(*in_out));
1320 }
1321 return S_OK;
1322}
1323
1324static HRESULT WINAPI Widget_variant(IWidget *iface, VARIANT in, VARIANT *out, VARIANT *in_ptr, VARIANT *in_out)
1325{
1326 ok(V_VT(&in) == VT_CY, "Got wrong type %#x.\n", V_VT(&in));
1327 ok(V_CY(&in).Hi == 0xdababe && V_CY(&in).Lo == 0xdeadbeef,
1328 "Got wrong value %s.\n", wine_dbgstr_longlong(V_CY(&in).int64));
1329 if (testmode == 0)
1330 {
1331 ok(V_VT(out) == VT_I4, "Got wrong type %u.\n", V_VT(out));
1332 ok(V_I4(out) == 1, "Got wrong value %d.\n", V_I4(out));
1333 }
1334 else
1335 ok(V_VT(out) == VT_EMPTY, "Got wrong type %u.\n", V_VT(out));
1336 ok(V_VT(in_ptr) == VT_I4, "Got wrong type %u.\n", V_VT(in_ptr));
1337 ok(V_I4(in_ptr) == -1, "Got wrong value %d.\n", V_I4(in_ptr));
1338 ok(V_VT(in_out) == VT_BSTR, "Got wrong type %u.\n", V_VT(in_out));
1339 ok(!lstrcmpW(V_BSTR(in_out), test_bstr2), "Got wrong value %s.\n",
1340 wine_dbgstr_w(V_BSTR(in_out)));
1341
1342 V_VT(&in) = VT_I4;
1343 V_I4(&in) = 2;
1344 V_VT(out) = VT_UI1;
1345 V_UI1(out) = 3;
1346 V_VT(in_ptr) = VT_I2;
1347 V_I2(in_ptr) = 4;
1348 VariantClear(in_out);
1349 V_VT(in_out) = VT_I1;
1350 V_I1(in_out) = 5;
1351 return S_OK;
1352}
1353
1355{
1357 int i, *data;
1358
1359 SafeArrayAccessData(sa, (void **)&data);
1360 for (i = 0; i < len; ++i)
1361 data[i] = len + i;
1363
1364 return sa;
1365}
1366
1368{
1369 LONG len, i, *data;
1370 HRESULT hr;
1371
1372 hr = SafeArrayGetUBound(sa, 1, &len);
1373 len++;
1374 ok(hr == S_OK, "Got hr %#x.\n", hr);
1375 ok(len == expect, "Expected len %d, got %d.\n", expect, len);
1376
1377 hr = SafeArrayAccessData(sa, (void **)&data);
1378 ok(hr == S_OK, "Got hr %#x.\n", hr);
1379
1380 for (i = 0; i < len; ++i)
1381 ok(data[i] == len + i, "Expected data %d at %d, got %d.\n", len + i, i, data[i]);
1382
1384}
1385
1386static HRESULT WINAPI Widget_safearray(IWidget *iface, SAFEARRAY *in, SAFEARRAY **out, SAFEARRAY **in_ptr, SAFEARRAY **in_out)
1387{
1388 HRESULT hr;
1389
1390 check_safearray(in, 3);
1391 ok(!*out, "Got array %p.\n", *out);
1392 check_safearray(*in_ptr, 7);
1393 check_safearray(*in_out, 9);
1394
1395 hr = SafeArrayDestroy(*in_out);
1396 ok(hr == S_OK, "Got hr %#x.\n", hr);
1397
1398 *out = make_safearray(4);
1399 *in_out = make_safearray(6);
1400
1401 return S_OK;
1402}
1403
1404static HRESULT WINAPI Widget_mystruct(IWidget *iface, MYSTRUCT in, MYSTRUCT *out, MYSTRUCT *in_ptr, MYSTRUCT *in_out)
1405{
1406 static const MYSTRUCT empty = {0};
1407 ok(!memcmp(&in, &test_mystruct1, sizeof(in)), "Structs didn't match.\n");
1408 ok(!memcmp(out, &empty, sizeof(*out)), "Structs didn't match.\n");
1409 ok(!memcmp(in_ptr, &test_mystruct3, sizeof(*in_ptr)), "Structs didn't match.\n");
1410 ok(!memcmp(in_out, &test_mystruct4, sizeof(*in_out)), "Structs didn't match.\n");
1411
1412 memcpy(out, &test_mystruct5, sizeof(*out));
1413 memcpy(in_ptr, &test_mystruct6, sizeof(*in_ptr));
1414 memcpy(in_out, &test_mystruct7, sizeof(*in_out));
1415 return S_OK;
1416}
1417
1418static HRESULT WINAPI Widget_mystruct_ptr_ptr(IWidget *iface, MYSTRUCT **in)
1419{
1420 ok(!memcmp(*in, &test_mystruct1, sizeof(**in)), "Structs didn't match.\n");
1421 return S_OK;
1422}
1423
1424static HRESULT WINAPI Widget_thin_struct(IWidget *iface, struct thin in)
1425{
1426 ok(!memcmp(&in, &test_thin_struct, sizeof(in)), "Structs didn't match.\n");
1427 return S_OK;
1428}
1429
1430static HRESULT WINAPI Widget_rect(IWidget *iface, RECT in, RECT *out, RECT *in_ptr, RECT *in_out)
1431{
1432 static const RECT empty = {0};
1433 ok(EqualRect(&in, &test_rect1), "Rects didn't match.\n");
1434 ok(EqualRect(out, &empty), "Rects didn't match.\n");
1435 ok(EqualRect(in_ptr, &test_rect3), "Rects didn't match.\n");
1436 ok(EqualRect(in_out, &test_rect4), "Rects didn't match.\n");
1437
1438 *out = test_rect5;
1439 *in_ptr = test_rect6;
1440 *in_out = test_rect7;
1441 return S_OK;
1442}
1443
1444static HRESULT WINAPI Widget_complex_struct(IWidget *iface, struct complex in)
1445{
1446 HRESULT hr;
1447
1448 ok(in.c == 98, "Got char %d.\n", in.c);
1449 ok(in.i == 76543, "Got int %d.\n", in.i);
1450 ok(*in.pi == 2, "Got int pointer %d.\n", *in.pi);
1451 ok(**in.ppi == 10, "Got int double pointer %d.\n", **in.ppi);
1452 hr = ISomethingFromDispatch_anotherfn(in.iface);
1453 ok(hr == 0x01234567, "Got wrong hr %#x.\n", hr);
1454 hr = ISomethingFromDispatch_anotherfn(*in.iface_ptr);
1455 ok(hr == 0x01234567, "Got wrong hr %#x.\n", hr);
1456 ok(!lstrcmpW(in.bstr, test_bstr2), "Got string %s.\n", wine_dbgstr_w(in.bstr));
1457 ok(V_VT(&in.var) == VT_I4, "Got wrong type %u.\n", V_VT(&in.var));
1458 ok(V_I4(&in.var) == 123, "Got wrong value %d.\n", V_I4(&in.var));
1459 ok(!memcmp(&in.mystruct, &test_mystruct1, sizeof(MYSTRUCT)), "Structs didn't match.\n");
1460 ok(!memcmp(in.arr, test_array1, sizeof(array_t)), "Arrays didn't match.\n");
1461 ok(in.myint == 456, "Got int %d.\n", in.myint);
1462
1463 return S_OK;
1464}
1465
1466static HRESULT WINAPI Widget_array(IWidget *iface, array_t in, array_t out, array_t in_out)
1467{
1468 static const array_t empty = {0};
1469 ok(!memcmp(in, test_array1, sizeof(array_t)), "Arrays didn't match.\n");
1470 ok(!memcmp(out, empty, sizeof(array_t)), "Arrays didn't match.\n");
1471 ok(!memcmp(in_out, test_array3, sizeof(array_t)), "Arrays didn't match.\n");
1472
1473 memcpy(in, test_array4, sizeof(array_t));
1474 memcpy(out, test_array5, sizeof(array_t));
1475 memcpy(in_out, test_array6, sizeof(array_t));
1476
1477 return S_OK;
1478}
1479
1480static HRESULT WINAPI Widget_variant_array(IWidget *iface, VARIANT in[2], VARIANT out[2], VARIANT in_out[2])
1481{
1482 ok(V_VT(&in[0]) == VT_I4, "Got wrong type %u.\n", V_VT(&in[0]));
1483 ok(V_I4(&in[0]) == 1, "Got wrong value %d.\n", V_I4(&in[0]));
1484 ok(V_VT(&in[1]) == (VT_BYREF|VT_I4), "Got wrong type %u.\n", V_VT(&in[1]));
1485 ok(*V_I4REF(&in[1]) == 2, "Got wrong value %d.\n", *V_I4REF(&in[1]));
1486 ok(V_VT(&out[0]) == VT_EMPTY, "Got wrong type %u.\n", V_VT(&out[0]));
1487 ok(V_VT(&out[1]) == VT_EMPTY, "Got wrong type %u.\n", V_VT(&out[1]));
1488 ok(V_VT(&in_out[0]) == VT_I4, "Got wrong type %u.\n", V_VT(&in_out[0]));
1489 ok(V_I4(&in_out[0]) == 5, "Got wrong type %u.\n", V_VT(&in_out[0]));
1490 ok(V_VT(&in_out[1]) == VT_BSTR, "Got wrong type %u.\n", V_VT(&in_out[1]));
1491 ok(!lstrcmpW(V_BSTR(&in_out[1]), test_bstr1), "Got wrong value %s.\n", wine_dbgstr_w(V_BSTR(&in[1])));
1492
1493 V_VT(&in[0]) = VT_I1; V_I1(&in[0]) = 7;
1494 V_VT(&in[1]) = VT_I1; V_I1(&in[1]) = 8;
1495 V_VT(&out[0]) = VT_I1; V_I1(&out[0]) = 9;
1497 V_VT(&in_out[0]) = VT_I1; V_I1(&in_out[0]) = 11;
1498 V_VT(&in_out[1]) = VT_UNKNOWN; V_UNKNOWN(&in_out[1]) = (IUnknown *)create_disp_obj();
1499
1500 return S_OK;
1501}
1502
1503static HRESULT WINAPI Widget_mystruct_array(IWidget *iface, MYSTRUCT in[2])
1504{
1505 ok(!memcmp(&in[0], &test_mystruct1, sizeof(MYSTRUCT)), "Structs didn't match.\n");
1506 ok(!memcmp(&in[1], &test_mystruct2, sizeof(MYSTRUCT)), "Structs didn't match.\n");
1507 return S_OK;
1508}
1509
1510static HRESULT WINAPI Widget_myint(IWidget *iface, myint_t val, myint_t *ptr, myint_t **ptr_ptr)
1511{
1512 ok(val == 123, "Got value %d.\n", val);
1513 ok(*ptr == 456, "Got single ptr ref %d.\n", *ptr);
1514 ok(**ptr_ptr == 789, "Got double ptr ref %d.\n", **ptr_ptr);
1515 return S_OK;
1516}
1517
1518static HRESULT WINAPI Widget_Coclass(IWidget *iface, Coclass1 *class1, Coclass2 *class2, Coclass3 *class3)
1519{
1520 HRESULT hr;
1521
1522 hr = ICoclass1_test((ICoclass1 *)class1);
1523 ok(hr == 1, "Got hr %#x.\n", hr);
1524
1525 hr = ICoclass2_test((ICoclass2 *)class2);
1526 ok(hr == 2, "Got hr %#x.\n", hr);
1527
1528 hr = ICoclass1_test((ICoclass1 *)class3);
1529 ok(hr == 1, "Got hr %#x.\n", hr);
1530
1531 return S_OK;
1532}
1533
1534static HRESULT WINAPI Widget_Coclass_ptr(IWidget *iface, Coclass1 **in, Coclass1 **out, Coclass1 **in_out)
1535{
1536 struct coclass_obj *obj;
1537 HRESULT hr;
1538
1539 ok(!*out, "Got [out] %p.\n", *out);
1540 if (testmode == 0 || testmode == 1)
1541 {
1542 hr = ICoclass1_test((ICoclass1 *)*in);
1543 ok(hr == 1, "Got hr %#x.\n", hr);
1544 hr = ICoclass1_test((ICoclass1 *)*in_out);
1545 ok(hr == 1, "Got hr %#x.\n", hr);
1546 }
1547
1548 if (testmode == 1)
1549 {
1551 *out = (Coclass1 *)&obj->ICoclass1_iface;
1552
1553 ICoclass1_Release((ICoclass1 *)*in_out);
1555 *in_out = (Coclass1 *)&obj->ICoclass1_iface;
1556 }
1557 else if (testmode == 2)
1558 {
1559 ok(!*in_out, "Got [in, out] %p.\n", *in_out);
1561 *in_out = (Coclass1 *)&obj->ICoclass1_iface;
1562 }
1563 else if (testmode == 3)
1564 {
1565 hr = ICoclass1_test((ICoclass1 *)*in_out);
1566 ok(hr == 1, "Got hr %#x.\n", hr);
1567 ICoclass1_Release((ICoclass1 *)*in_out);
1568 *in_out = NULL;
1569 }
1570
1571 return S_OK;
1572}
1573
1574static const struct IWidgetVtbl Widget_VTable =
1575{
1588 Widget_Map,
1632};
1633
1634static HRESULT WINAPI StaticWidget_QueryInterface(IStaticWidget *iface, REFIID riid, void **ppvObject)
1635{
1636 if (IsEqualIID(riid, &IID_IStaticWidget) || IsEqualIID(riid, &IID_IUnknown) || IsEqualIID(riid, &IID_IDispatch))
1637 {
1638 IStaticWidget_AddRef(iface);
1639 *ppvObject = iface;
1640 return S_OK;
1641 }
1642
1643 *ppvObject = NULL;
1644 return E_NOINTERFACE;
1645}
1646
1647static ULONG WINAPI StaticWidget_AddRef(IStaticWidget *iface)
1648{
1649 return 2;
1650}
1651
1652static ULONG WINAPI StaticWidget_Release(IStaticWidget *iface)
1653{
1654 return 1;
1655}
1656
1657static HRESULT WINAPI StaticWidget_GetTypeInfoCount(IStaticWidget *iface, UINT *pctinfo)
1658{
1659 ok(0, "unexpected call\n");
1660 return E_NOTIMPL;
1661}
1662
1663static HRESULT WINAPI StaticWidget_GetTypeInfo(IStaticWidget *iface, UINT iTInfo, LCID lcid,
1664 ITypeInfo **ppTInfo)
1665{
1666 ok(0, "unexpected call\n");
1667 return E_NOTIMPL;
1668}
1669
1670static HRESULT WINAPI StaticWidget_GetIDsOfNames(IStaticWidget *iface, REFIID riid, LPOLESTR *rgszNames,
1671 UINT cNames, LCID lcid, DISPID *rgDispId)
1672{
1673 ok(0, "unexpected call\n");
1674 return E_NOTIMPL;
1675}
1676
1677static HRESULT WINAPI StaticWidget_Invoke(IStaticWidget *iface, DISPID dispIdMember, REFIID riid,
1678 LCID lcid, WORD wFlags, DISPPARAMS *pDispParams, VARIANT *pVarResult, EXCEPINFO *pExcepInfo,
1679 UINT *puArgErr)
1680{
1681 ok(0, "unexpected call\n");
1682 return E_NOTIMPL;
1683}
1684
1685static HRESULT WINAPI StaticWidget_TestDual(IStaticWidget *iface, ItestDual *p)
1686{
1687 trace("TestDual()\n");
1688 ok(p == &TestDual, "wrong ItestDual\n");
1689 return S_OK;
1690}
1691
1692static HRESULT WINAPI StaticWidget_TestSecondIface(IStaticWidget *iface, ITestSecondIface *p)
1693{
1694 trace("TestSecondIface()\n");
1695 ok(p == &TestSecondIface, "wrong ItestSecondIface\n");
1696 return S_OK;
1697}
1698
1699static const IStaticWidgetVtbl StaticWidgetVtbl = {
1709};
1710
1711static IStaticWidget StaticWidget = { &StaticWidgetVtbl };
1712
1713typedef struct KindaEnum
1714{
1715 IKindaEnumWidget IKindaEnumWidget_iface;
1718
1719static inline KindaEnum *impl_from_IKindaEnumWidget(IKindaEnumWidget *iface)
1720{
1721 return CONTAINING_RECORD(iface, KindaEnum, IKindaEnumWidget_iface);
1722}
1723
1725{
1728 HRESULT hr;
1730
1733
1735 if (SUCCEEDED(hr))
1736 {
1738 ITypeLib_Release(typelib);
1739 }
1740 return hr;
1741}
1742
1744{
1745 ITypeInfo *pTypeInfo;
1746 ITypeLib *pTypeLib;
1747 HRESULT hr;
1748
1749 hr = LoadRegTypeLib(&LIBID_TestTypelib, 2, 5, LOCALE_NEUTRAL, &pTypeLib);
1751 if (FAILED(hr))
1752 return NULL;
1753
1754 hr = ITypeLib_GetTypeInfoOfGuid(pTypeLib, riid, &pTypeInfo);
1755 ITypeLib_Release(pTypeLib);
1756 ok_ole_success(hr, ITypeLib_GetTypeInfoOfGuid);
1757 if (FAILED(hr))
1758 return NULL;
1759
1760 return pTypeInfo;
1761}
1762
1763static IWidget *Widget_Create(void)
1764{
1765 Widget *This;
1766 ITypeInfo *pTypeInfo;
1767 HRESULT hr = E_FAIL;
1768
1769 pTypeInfo = get_type_info(&IID_IWidget);
1770 if(!pTypeInfo)
1771 return NULL;
1772
1773 This = HeapAlloc(GetProcessHeap(), 0, sizeof(*This));
1774 This->IWidget_iface.lpVtbl = &Widget_VTable;
1775 This->refs = 1;
1776 This->pDispatchUnknown = NULL;
1777
1778 hr = CreateStdDispatch((IUnknown *)&This->IWidget_iface, This, pTypeInfo,
1779 &This->pDispatchUnknown);
1781 ITypeInfo_Release(pTypeInfo);
1782
1783 if (SUCCEEDED(hr))
1784 return &This->IWidget_iface;
1785 else
1786 {
1788 return NULL;
1789 }
1790}
1791
1793 IKindaEnumWidget *iface,
1794 /* [in] */ REFIID riid,
1795 /* [iid_is][out] */ void __RPC_FAR *__RPC_FAR *ppvObject)
1796{
1797 if (IsEqualIID(riid, &IID_IKindaEnumWidget) || IsEqualIID(riid, &IID_IUnknown))
1798 {
1799 IKindaEnumWidget_AddRef(iface);
1800 *ppvObject = iface;
1801 return S_OK;
1802 }
1803 else
1804 {
1805 *ppvObject = NULL;
1806 return E_NOINTERFACE;
1807 }
1808}
1809
1811 IKindaEnumWidget *iface)
1812{
1814
1815 return InterlockedIncrement(&This->refs);
1816}
1817
1819 IKindaEnumWidget *iface)
1820{
1822 ULONG refs = InterlockedDecrement(&This->refs);
1823 if (!refs)
1824 {
1825 memset(This, 0xcc, sizeof(*This));
1827 trace("KindaEnumWidget destroyed!\n");
1828 }
1829
1830 return refs;
1831}
1832
1834 IKindaEnumWidget *iface,
1835 /* [out] */ IWidget __RPC_FAR *__RPC_FAR *widget)
1836{
1837 *widget = Widget_Create();
1838 if (*widget)
1839 return S_OK;
1840 else
1841 return E_OUTOFMEMORY;
1842}
1843
1845 IKindaEnumWidget *iface,
1846 /* [out] */ ULONG __RPC_FAR *count)
1847{
1848 return E_NOTIMPL;
1849}
1850
1852 IKindaEnumWidget *iface)
1853{
1854 return E_NOTIMPL;
1855}
1856
1858 IKindaEnumWidget *iface,
1859 /* [out] */ IKindaEnumWidget __RPC_FAR *__RPC_FAR *ppenum)
1860{
1861 return E_NOTIMPL;
1862}
1863
1864static const IKindaEnumWidgetVtbl KindaEnumWidget_VTable =
1865{
1873};
1874
1875static IKindaEnumWidget *KindaEnumWidget_Create(void)
1876{
1877 KindaEnum *This;
1878
1879 This = HeapAlloc(GetProcessHeap(), 0, sizeof(*This));
1880 if (!This) return NULL;
1881 This->IKindaEnumWidget_iface.lpVtbl = &KindaEnumWidget_VTable;
1882 This->refs = 1;
1883 return &This->IKindaEnumWidget_iface;
1884}
1885
1886static HRESULT WINAPI NonOleAutomation_QueryInterface(INonOleAutomation *iface, REFIID riid, void **ppv)
1887{
1888 if (IsEqualIID(riid, &IID_IUnknown) || IsEqualIID(riid, &IID_INonOleAutomation))
1889 {
1890 *(INonOleAutomation **)ppv = iface;
1891 return S_OK;
1892 }
1893 *ppv = NULL;
1894 return E_NOINTERFACE;
1895}
1896
1897static ULONG WINAPI NonOleAutomation_AddRef(INonOleAutomation *iface)
1898{
1899 return 2;
1900}
1901
1902static ULONG WINAPI NonOleAutomation_Release(INonOleAutomation *iface)
1903{
1904 return 1;
1905}
1906
1907static BSTR WINAPI NonOleAutomation_BstrRet(INonOleAutomation *iface)
1908{
1909 static const WCHAR wszTestString[] = {'T','h','i','s',' ','i','s',' ','a',' ','t','e','s','t',' ','s','t','r','i','n','g',0};
1910 return SysAllocString(wszTestString);
1911}
1912
1913static HRESULT WINAPI NonOleAutomation_Error(INonOleAutomation *iface)
1914{
1915 return E_NOTIMPL;
1916}
1917
1918static INonOleAutomationVtbl NonOleAutomation_VTable =
1919{
1925};
1926
1927static INonOleAutomation NonOleAutomation = { &NonOleAutomation_VTable };
1928
1930{
1931 ITypeLib *pTypeLib;
1932 HRESULT hr = LoadRegTypeLib(&LIBID_TestTypelib, 2, 5, LOCALE_NEUTRAL, &pTypeLib);
1934 if (SUCCEEDED(hr))
1935 {
1936 ITypeInfo *pTypeInfo;
1937 hr = ITypeLib_GetTypeInfoOfGuid(pTypeLib, &IID_INonOleAutomation, &pTypeInfo);
1938 ok_ole_success(hr, ITypeLib_GetTypeInfoOfGuid);
1939 ITypeLib_Release(pTypeLib);
1940 return pTypeInfo;
1941 }
1942 return NULL;
1943}
1944
1945static void test_marshal_basetypes(IWidget *widget, IDispatch *disp)
1946{
1947 VARIANTARG arg[11];
1948 DISPPARAMS dispparams = {arg, NULL, ARRAY_SIZE(arg), 0};
1949 HRESULT hr;
1950
1951 signed char c;
1952 short s;
1953 int i, i2, *pi;
1954 hyper h;
1955 unsigned char uc;
1956 unsigned short us;
1957 unsigned int ui;
1958 MIDL_uhyper uh;
1959 float f;
1960 double d;
1961 STATE st;
1962
1963 V_VT(&arg[10]) = VT_I1; V_I1(&arg[10]) = 5;
1964 V_VT(&arg[9]) = VT_I2; V_I2(&arg[9]) = -123;
1965 V_VT(&arg[8]) = VT_I4; V_I4(&arg[8]) = -100000;
1966 V_VT(&arg[7]) = VT_I8; V_I8(&arg[7]) = (LONGLONG)-100000 * 1000000;
1967 V_VT(&arg[6]) = VT_UI1; V_UI1(&arg[6]) = 0;
1968 V_VT(&arg[5]) = VT_UI2; V_UI2(&arg[5]) = 456;
1969 V_VT(&arg[4]) = VT_UI4; V_UI4(&arg[4]) = 0xdeadbeef;
1970 V_VT(&arg[3]) = VT_UI8; V_UI8(&arg[3]) = (ULONGLONG)1234567890 * 9876543210;
1971 V_VT(&arg[2]) = VT_R4; V_R4(&arg[2]) = M_PI;
1972 V_VT(&arg[1]) = VT_R8; V_R8(&arg[1]) = M_E;
1973 V_VT(&arg[0]) = VT_I4; V_I4(&arg[0]) = STATE_WIDGETIFIED;
1974 hr = IDispatch_Invoke(disp, DISPID_TM_BASETYPES_IN, &IID_NULL, LOCALE_NEUTRAL,
1975 DISPATCH_METHOD, &dispparams, NULL, NULL, NULL);
1976 ok(hr == S_OK, "Got hr %#x.\n", hr);
1977
1978 hr = IWidget_basetypes_in(widget, 5, -123, -100000, (LONGLONG)-100000 * 1000000, 0, 456,
1979 0xdeadbeef, (ULONGLONG)1234567890 * 9876543210, M_PI, M_E, STATE_WIDGETIFIED);
1980 ok(hr == S_OK, "Got hr %#x.\n", hr);
1981
1982 c = s = i = h = uc = us = ui = uh = f = d = st = 0;
1983
1984 V_VT(&arg[10]) = VT_BYREF|VT_I1; V_I1REF(&arg[10]) = &c;
1985 V_VT(&arg[9]) = VT_BYREF|VT_I2; V_I2REF(&arg[9]) = &s;
1986 V_VT(&arg[8]) = VT_BYREF|VT_I4; V_I4REF(&arg[8]) = &i;
1987 V_VT(&arg[7]) = VT_BYREF|VT_I8; V_I8REF(&arg[7]) = &h;
1988 V_VT(&arg[6]) = VT_BYREF|VT_UI1; V_UI1REF(&arg[6]) = &uc;
1989 V_VT(&arg[5]) = VT_BYREF|VT_UI2; V_UI2REF(&arg[5]) = &us;
1990 V_VT(&arg[4]) = VT_BYREF|VT_UI4; V_UI4REF(&arg[4]) = &ui;
1991 V_VT(&arg[3]) = VT_BYREF|VT_UI8; V_UI8REF(&arg[3]) = &uh;
1992 V_VT(&arg[2]) = VT_BYREF|VT_R4; V_R4REF(&arg[2]) = &f;
1993 V_VT(&arg[1]) = VT_BYREF|VT_R8; V_R8REF(&arg[1]) = &d;
1994 V_VT(&arg[0]) = VT_BYREF|VT_I4; V_I4REF(&arg[0]) = (int *)&st;
1995 hr = IDispatch_Invoke(disp, DISPID_TM_BASETYPES_OUT, &IID_NULL, LOCALE_NEUTRAL,
1996 DISPATCH_METHOD, &dispparams, NULL, NULL, NULL);
1997 ok(hr == S_OK, "Got hr %#x.\n", hr);
1998 ok(c == 10, "Got char %d.\n", c);
1999 ok(s == -321, "Got short %d.\n", s);
2000 ok(i == -200000, "Got int %d.\n", i);
2001 ok(h == (LONGLONG)-200000 * 1000000L, "Got hyper %s.\n", wine_dbgstr_longlong(h));
2002 ok(uc == 254, "Got unsigned char %u.\n", uc);
2003 ok(us == 256, "Got unsigned short %u.\n", us);
2004 ok(ui == 0xf00dfade, "Got unsigned int %i.\n", ui);
2005 ok(uh == ((((ULONGLONG)0xabcdef01) << 32) | (ULONGLONG)0x23456789),
2006 "Got unsigned hyper %s.\n", wine_dbgstr_longlong(uh));
2007 ok(f == (float)M_LN2, "Got float %f.\n", f);
2008 ok(d == M_LN10, "Got double %f.\n", d);
2009 ok(st == STATE_UNWIDGETIFIED, "Got state %u.\n", st);
2010
2011 c = s = i = h = uc = us = ui = uh = f = d = st = 0;
2012
2013 hr = IWidget_basetypes_out(widget, &c, &s, &i, &h, &uc, &us, &ui, &uh, &f, &d, &st);
2014 ok(hr == S_OK, "Got hr %#x.\n", hr);
2015 ok(c == 10, "Got char %d.\n", c);
2016 ok(s == -321, "Got short %d.\n", s);
2017 ok(i == -200000, "Got int %d.\n", i);
2018 ok(h == (LONGLONG)-200000 * 1000000L, "Got hyper %s.\n", wine_dbgstr_longlong(h));
2019 ok(uc == 254, "Got unsigned char %u.\n", uc);
2020 ok(us == 256, "Got unsigned short %u.\n", us);
2021 ok(ui == 0xf00dfade, "Got unsigned int %i.\n", ui);
2022 ok(uh == ((((ULONGLONG)0xabcdef01) << 32) | (ULONGLONG)0x23456789),
2023 "Got unsigned hyper %s.\n", wine_dbgstr_longlong(uh));
2024 ok(f == (float)M_LN2, "Got float %f.\n", f);
2025 ok(d == M_LN10, "Got double %f.\n", d);
2026 ok(st == STATE_UNWIDGETIFIED, "Got state %u.\n", st);
2027
2028 /* Test marshalling of public typedefs. */
2029
2030 i = 456;
2031 i2 = 789;
2032 pi = &i2;
2033 hr = IWidget_myint(widget, 123, &i, &pi);
2034 ok(hr == S_OK, "Got hr %#x.\n", hr);
2035
2036 /* Test that different float ABIs are correctly handled. */
2037
2038 hr = IWidget_float_abi(widget, 1.0f, 2.0, 3, 4.0f, 5.0);
2039 ok(hr == S_OK, "Got hr %#x.\n", hr);
2040}
2041
2042static void test_marshal_pointer(IWidget *widget, IDispatch *disp)
2043{
2044 VARIANTARG arg[3];
2045 DISPPARAMS dispparams = {arg, NULL, ARRAY_SIZE(arg), 0};
2046 int in, out, in_out, *in_ptr, *out_ptr, *in_out_ptr;
2047 HRESULT hr;
2048
2049 testmode = 0;
2050
2051 in = 123;
2052 out = 456;
2053 in_out = 789;
2054 V_VT(&arg[2]) = VT_BYREF|VT_I4; V_I4REF(&arg[2]) = &in;
2055 V_VT(&arg[1]) = VT_BYREF|VT_I4; V_I4REF(&arg[1]) = &out;
2056 V_VT(&arg[0]) = VT_BYREF|VT_I4; V_I4REF(&arg[0]) = &in_out;
2057 hr = IDispatch_Invoke(disp, DISPID_TM_INT_PTR, &IID_NULL, LOCALE_NEUTRAL,
2058 DISPATCH_METHOD, &dispparams, NULL, NULL, NULL);
2059 ok(hr == S_OK, "Got hr %#x.\n", hr);
2060 ok(in == 987, "Got [in] %d.\n", in);
2061 ok(out == 654, "Got [out] %d.\n", out);
2062 ok(in_out == 321, "Got [in, out] %d.\n", in_out);
2063
2064 testmode = 1;
2065
2066 in = 123;
2067 out = 456;
2068 in_out = 789;
2069 hr = IWidget_int_ptr(widget, &in, &out, &in_out);
2070 ok(hr == S_OK, "Got hr %#x.\n", hr);
2071 ok(in == 123, "Got [in] %d.\n", in);
2072 ok(out == 654, "Got [out] %d.\n", out);
2073 ok(in_out == 321, "Got [in, out] %d.\n", in_out);
2074
2075 out = in_out = -1;
2076 hr = IWidget_int_ptr(widget, NULL, &out, &in_out);
2077 ok(hr == HRESULT_FROM_WIN32(RPC_X_NULL_REF_POINTER), "Got hr %#x.\n", hr);
2078 ok(!out, "[out] parameter should have been cleared.\n");
2079 ok(in_out == -1, "[in, out] parameter should not have been cleared.\n");
2080
2081 in = in_out = -1;
2082 hr = IWidget_int_ptr(widget, &in, NULL, &in_out);
2083 ok(hr == HRESULT_FROM_WIN32(RPC_X_NULL_REF_POINTER), "Got hr %#x.\n", hr);
2084 ok(in == -1, "[in] parameter should not have been cleared.\n");
2085 ok(in_out == -1, "[in, out] parameter should not have been cleared.\n");
2086
2087 in = out = -1;
2088 hr = IWidget_int_ptr(widget, &in, &out, NULL);
2089 ok(hr == HRESULT_FROM_WIN32(RPC_X_NULL_REF_POINTER), "Got hr %#x.\n", hr);
2090 ok(in == -1, "[in] parameter should not have been cleared.\n");
2091 ok(!out, "[out] parameter should have been cleared.\n");
2092
2093 /* We can't test Invoke() with double pointers, as it is not possible to fit
2094 * more than one level of indirection into a VARIANTARG. */
2095
2096 testmode = 0;
2097 in_ptr = out_ptr = in_out_ptr = NULL;
2098 hr = IWidget_int_ptr_ptr(widget, &in_ptr, &out_ptr, &in_out_ptr);
2099 ok(hr == S_OK, "Got hr %#x\n", hr);
2100 ok(!in_ptr, "Got [in] %p.\n", in_ptr);
2101 ok(!out_ptr, "Got [out] %p.\n", out_ptr);
2102 ok(!in_out_ptr, "Got [in, out] %p.\n", in_out_ptr);
2103
2104 testmode = 1;
2105 hr = IWidget_int_ptr_ptr(widget, &in_ptr, &out_ptr, &in_out_ptr);
2106 ok(hr == S_OK, "Got hr %#x\n", hr);
2107 ok(*out_ptr == 654, "Got [out] %d.\n", *out_ptr);
2108 ok(*in_out_ptr == 321, "Got [in, out] %d.\n", *in_out_ptr);
2109 CoTaskMemFree(out_ptr);
2110 CoTaskMemFree(in_out_ptr);
2111
2112 testmode = 2;
2113 in = 123;
2114 out = 456;
2115 in_out = 789;
2116 in_ptr = &in;
2117 out_ptr = &out;
2118 in_out_ptr = &in_out;
2119 hr = IWidget_int_ptr_ptr(widget, &in_ptr, &out_ptr, &in_out_ptr);
2120 ok(hr == S_OK, "Got hr %#x.\n", hr);
2121 ok(out_ptr != &out, "[out] ptr should have changed.\n");
2122 ok(in_out_ptr == &in_out, "[in, out] ptr should not have changed.\n");
2123 ok(*out_ptr == 654, "Got [out] %d.\n", *out_ptr);
2124 ok(*in_out_ptr == 321, "Got [in, out] %d.\n", *in_out_ptr);
2125
2126 testmode = 3;
2127 in_ptr = out_ptr = NULL;
2128 in_out = 789;
2129 in_out_ptr = &in_out;
2130 hr = IWidget_int_ptr_ptr(widget, &in_ptr, &out_ptr, &in_out_ptr);
2131 ok(hr == S_OK, "Got hr %#x.\n", hr);
2132 ok(!in_out_ptr, "Got [in, out] %p.\n", in_out_ptr);
2133
2134 out_ptr = &out;
2135 in_out_ptr = &in_out;
2136 hr = IWidget_int_ptr_ptr(widget, NULL, &out_ptr, &in_out_ptr);
2137 ok(hr == HRESULT_FROM_WIN32(RPC_X_NULL_REF_POINTER), "Got hr %#x.\n", hr);
2138 ok(!out_ptr, "[out] parameter should have been cleared.\n");
2139 ok(in_out_ptr == &in_out, "[in, out] parameter should not have been cleared.\n");
2140
2141 in_ptr = &in;
2142 in_out_ptr = &in_out;
2143 hr = IWidget_int_ptr_ptr(widget, &in_ptr, NULL, &in_out_ptr);
2144 ok(hr == HRESULT_FROM_WIN32(RPC_X_NULL_REF_POINTER), "Got hr %#x.\n", hr);
2145 ok(in_ptr == &in, "[in] parameter should not have been cleared.\n");
2146 ok(in_out_ptr == &in_out, "[in, out] parameter should not have been cleared.\n");
2147
2148 in_ptr = &in;
2149 out_ptr = &out;
2150 hr = IWidget_int_ptr_ptr(widget, &in_ptr, &out_ptr, NULL);
2151 ok(hr == HRESULT_FROM_WIN32(RPC_X_NULL_REF_POINTER), "Got hr %#x.\n", hr);
2152 ok(in_ptr == &in, "[in] parameter should not have been cleared.\n");
2153 ok(!out_ptr, "[out] parameter should have been cleared.\n");
2154}
2155
2156static void test_marshal_iface(IWidget *widget, IDispatch *disp)
2157{
2158 VARIANTARG arg[3];
2159 DISPPARAMS dispparams = {arg, NULL, ARRAY_SIZE(arg), 0};
2160 ISomethingFromDispatch *sfd1, *sfd2, *sfd3, *proxy_sfd, *sfd_in, *sfd_out, *sfd_in_out;
2161 IUnknown *proxy_unk, *proxy_unk2, *unk_in, *unk_out, *unk_in_out;
2162 IDispatch *proxy_disp;
2163 HRESULT hr;
2164
2165 testmode = 0;
2166 sfd1 = create_disp_obj();
2167 sfd2 = create_disp_obj();
2168 sfd3 = create_disp_obj();
2169 hr = IWidget_iface_in(widget, (IUnknown *)sfd1,
2170 (IDispatch *)sfd2, sfd3);
2171 ok(hr == S_OK, "Got hr %#x.\n", hr);
2172 release_iface(sfd1);
2173 release_iface(sfd2);
2174 release_iface(sfd3);
2175
2176 testmode = 1;
2177 hr = IWidget_iface_in(widget, NULL, NULL, NULL);
2178 ok(hr == S_OK, "Got hr %#x.\n", hr);
2179
2180 testmode = 0;
2181 proxy_unk = (IUnknown *)0xdeadbeef;
2182 proxy_disp = (IDispatch *)0xdeadbeef;
2183 proxy_sfd = (ISomethingFromDispatch *)0xdeadbeef;
2184 hr = IWidget_iface_out(widget, &proxy_unk, &proxy_disp, &proxy_sfd);
2185 ok(hr == S_OK, "Got hr %#x.\n", hr);
2186 check_iface_marshal(proxy_unk, proxy_disp, proxy_sfd);
2187 release_iface(proxy_unk);
2188 release_iface(proxy_disp);
2189 release_iface(proxy_sfd);
2190
2191 testmode = 1;
2192 hr = IWidget_iface_out(widget, &proxy_unk, &proxy_disp, &proxy_sfd);
2193 ok(hr == S_OK, "Got hr %#x.\n", hr);
2194 ok(!proxy_unk, "Got unexpected proxy %p.\n", proxy_unk);
2195 ok(!proxy_disp, "Got unexpected proxy %p.\n", proxy_disp);
2196 ok(!proxy_sfd, "Got unexpected proxy %p.\n", proxy_sfd);
2197
2198 testmode = 0;
2199 sfd_in = sfd1 = create_disp_obj();
2200 sfd_out = sfd2 = create_disp_obj();
2201 sfd_in_out = sfd3 = create_disp_obj();
2202 hr = IWidget_iface_ptr(widget, &sfd_in, &sfd_out, &sfd_in_out);
2203 ok(hr == S_OK, "Got hr %#x.\n", hr);
2204 ok(sfd_in == sfd1, "[in] parameter should not have changed.\n");
2205 ok(!sfd_out, "[out] parameter should have been cleared.\n");
2206 ok(sfd_in_out == sfd3, "[in, out] parameter should not have changed.\n");
2207 release_iface(sfd1);
2208 release_iface(sfd2);
2209 release_iface(sfd3);
2210
2211 testmode = 1;
2212 sfd_in = sfd1 = create_disp_obj();
2213 sfd_in_out = sfd3 = create_disp_obj();
2214 ISomethingFromDispatch_AddRef(sfd_in_out);
2215 hr = IWidget_iface_ptr(widget, &sfd_in, &sfd_out, &sfd_in_out);
2216 ok(hr == S_OK, "Got hr %#x.\n", hr);
2217 hr = ISomethingFromDispatch_anotherfn(sfd_out);
2218 ok(hr == 0x01234567, "Got hr %#x.\n", hr);
2219 ok(sfd_in_out != sfd3, "[in, out] parameter should have changed.\n");
2220 hr = ISomethingFromDispatch_anotherfn(sfd_in_out);
2221 ok(hr == 0x01234567, "Got hr %#x.\n", hr);
2222 release_iface(sfd_out);
2223 release_iface(sfd_in_out);
2224 release_iface(sfd1);
2225 release_iface(sfd3);
2226
2227 testmode = 2;
2228 sfd_in = sfd_out = sfd_in_out = NULL;
2229 hr = IWidget_iface_ptr(widget, &sfd_in, &sfd_out, &sfd_in_out);
2230 ok(hr == S_OK, "Got hr %#x.\n", hr);
2231 ok(!sfd_out, "[out] parameter should not have been set.\n");
2232 hr = ISomethingFromDispatch_anotherfn(sfd_in_out);
2233 ok(hr == 0x01234567, "Got hr %#x.\n", hr);
2234 release_iface(sfd_in_out);
2235
2236 testmode = 3;
2237 sfd_in = sfd_out = NULL;
2238 sfd_in_out = sfd3 = create_disp_obj();
2239 ISomethingFromDispatch_AddRef(sfd_in_out);
2240 hr = IWidget_iface_ptr(widget, &sfd_in, &sfd_out, &sfd_in_out);
2241 ok(hr == S_OK, "Got hr %#x.\n", hr);
2242 ok(!sfd_in_out, "Got [in, out] %p.\n", sfd_in_out);
2243 release_iface(sfd3);
2244
2245 /* Test with Invoke(). Note that since we pass VT_UNKNOWN, we don't get our
2246 * interface back, but rather an IUnknown. */
2247
2248 testmode = 0;
2249 sfd1 = create_disp_obj();
2250 sfd2 = create_disp_obj();
2251 sfd3 = create_disp_obj();
2252
2253 V_VT(&arg[2]) = VT_UNKNOWN; V_UNKNOWN(&arg[2]) = (IUnknown *)sfd1;
2254 V_VT(&arg[1]) = VT_UNKNOWN; V_UNKNOWN(&arg[1]) = (IUnknown *)sfd2;
2255 V_VT(&arg[0]) = VT_UNKNOWN; V_UNKNOWN(&arg[0]) = (IUnknown *)sfd3;
2256 hr = IDispatch_Invoke(disp, DISPID_TM_IFACE_IN, &IID_NULL, LOCALE_NEUTRAL,
2257 DISPATCH_METHOD, &dispparams, NULL, NULL, NULL);
2258 ok(hr == S_OK, "Got hr %#x.\n", hr);
2259
2260 V_VT(&arg[2]) = VT_DISPATCH; V_DISPATCH(&arg[2]) = (IDispatch *)sfd1;
2261 V_VT(&arg[1]) = VT_DISPATCH; V_DISPATCH(&arg[1]) = (IDispatch *)sfd2;
2262 V_VT(&arg[0]) = VT_DISPATCH; V_DISPATCH(&arg[0]) = (IDispatch *)sfd3;
2263 hr = IDispatch_Invoke(disp, DISPID_TM_IFACE_IN, &IID_NULL, LOCALE_NEUTRAL,
2264 DISPATCH_METHOD, &dispparams, NULL, NULL, NULL);
2265 ok(hr == S_OK, "Got hr %#x.\n", hr);
2266
2267 release_iface(sfd1);
2268 release_iface(sfd2);
2269 release_iface(sfd3);
2270
2271 testmode = 1;
2272 V_VT(&arg[2]) = VT_UNKNOWN; V_UNKNOWN(&arg[2]) = NULL;
2273 V_VT(&arg[1]) = VT_UNKNOWN; V_UNKNOWN(&arg[1]) = NULL;
2274 V_VT(&arg[0]) = VT_UNKNOWN; V_UNKNOWN(&arg[0]) = NULL;
2275 hr = IDispatch_Invoke(disp, DISPID_TM_IFACE_IN, &IID_NULL, LOCALE_NEUTRAL,
2276 DISPATCH_METHOD, &dispparams, NULL, NULL, NULL);
2277 ok(hr == S_OK, "Got hr %#x.\n", hr);
2278
2279 testmode = 0;
2280 proxy_unk = proxy_unk2 = NULL;
2281 proxy_disp = NULL;
2282 V_VT(&arg[2]) = VT_UNKNOWN|VT_BYREF; V_UNKNOWNREF(&arg[2]) = &proxy_unk;
2283 V_VT(&arg[1]) = VT_DISPATCH|VT_BYREF; V_DISPATCHREF(&arg[1]) = &proxy_disp;
2284 V_VT(&arg[0]) = VT_UNKNOWN|VT_BYREF; V_UNKNOWNREF(&arg[0]) = &proxy_unk2;
2285 hr = IDispatch_Invoke(disp, DISPID_TM_IFACE_OUT, &IID_NULL, LOCALE_NEUTRAL,
2286 DISPATCH_METHOD, &dispparams, NULL, NULL, NULL);
2288 ok(hr == S_OK, "Got hr %#x.\n", hr);
2289if (hr == S_OK) {
2290 hr = IUnknown_QueryInterface(proxy_unk2, &IID_ISomethingFromDispatch, (void **)&proxy_sfd);
2291 ok(hr == S_OK, "Got hr %#x.\n", hr);
2292 check_iface_marshal(proxy_unk, proxy_disp, proxy_sfd);
2293 ISomethingFromDispatch_Release(proxy_sfd);
2294 release_iface(proxy_unk);
2295 release_iface(proxy_disp);
2296 release_iface(proxy_unk2);
2297}
2298
2299 testmode = 1;
2300 proxy_unk = proxy_unk2 = NULL;
2301 proxy_disp = NULL;
2302 hr = IDispatch_Invoke(disp, DISPID_TM_IFACE_OUT, &IID_NULL, LOCALE_NEUTRAL,
2303 DISPATCH_METHOD, &dispparams, NULL, NULL, NULL);
2305 ok(hr == S_OK, "Got hr %#x.\n", hr);
2306 ok(!proxy_unk, "Got unexpected proxy %p.\n", proxy_unk);
2307 ok(!proxy_disp, "Got unexpected proxy %p.\n", proxy_disp);
2308 ok(!proxy_unk2, "Got unexpected proxy %p.\n", proxy_unk2);
2309
2310 testmode = 0;
2311 sfd1 = create_disp_obj();
2312 sfd3 = create_disp_obj();
2313 unk_in = (IUnknown *)sfd1;
2314 unk_out = NULL;
2315 unk_in_out = (IUnknown *)sfd3;
2318 V_VT(&arg[0]) = VT_UNKNOWN|VT_BYREF; V_UNKNOWNREF(&arg[0]) = &unk_in_out;
2319 hr = IDispatch_Invoke(disp, DISPID_TM_IFACE_PTR, &IID_NULL, LOCALE_NEUTRAL,
2320 DISPATCH_METHOD, &dispparams, NULL, NULL, NULL);
2322 ok(hr == S_OK, "Got hr %#x.\n", hr);
2323 ok(unk_in == (IUnknown *)sfd1, "[in] parameter should not have changed.\n");
2324 ok(!unk_out, "[out] parameter should have been cleared.\n");
2325 ok(unk_in_out == (IUnknown *)sfd3, "[in, out] parameter should not have changed.\n");
2326 release_iface(sfd1);
2327 release_iface(sfd3);
2328
2329 testmode = 1;
2330 sfd1 = create_disp_obj();
2331 sfd3 = create_disp_obj();
2332 unk_in = (IUnknown *)sfd1;
2333 unk_out = NULL;
2334 unk_in_out = (IUnknown *)sfd3;
2335 IUnknown_AddRef(unk_in_out);
2336 hr = IDispatch_Invoke(disp, DISPID_TM_IFACE_PTR, &IID_NULL, LOCALE_NEUTRAL,
2337 DISPATCH_METHOD, &dispparams, NULL, NULL, NULL);
2339 ok(hr == S_OK, "Got hr %#x.\n", hr);
2340
2341if (hr == S_OK) {
2342 hr = IUnknown_QueryInterface(unk_out, &IID_ISomethingFromDispatch, (void **)&sfd_out);
2343 ok(hr == S_OK, "Got hr %#x.\n", hr);
2344 hr = ISomethingFromDispatch_anotherfn(sfd_out);
2345 ok(hr == 0x01234567, "Got hr %#x.\n", hr);
2346 ISomethingFromDispatch_Release(sfd_out);
2347
2348 ok(unk_in_out != (IUnknown *)sfd3, "[in, out] parameter should have changed.\n");
2349 hr = IUnknown_QueryInterface(unk_in_out, &IID_ISomethingFromDispatch, (void **)&sfd_in_out);
2350 ok(hr == S_OK, "Got hr %#x.\n", hr);
2351 hr = ISomethingFromDispatch_anotherfn(sfd_in_out);
2352 ok(hr == 0x01234567, "Got hr %#x.\n", hr);
2353 ISomethingFromDispatch_Release(sfd_in_out);
2354
2356 release_iface(unk_in_out);
2357}
2358 release_iface(sfd1);
2360 release_iface(sfd3);
2361
2362 testmode = 2;
2363 unk_in = unk_out = unk_in_out = NULL;
2364 hr = IDispatch_Invoke(disp, DISPID_TM_IFACE_PTR, &IID_NULL, LOCALE_NEUTRAL,
2365 DISPATCH_METHOD, &dispparams, NULL, NULL, NULL);
2367 ok(hr == S_OK, "Got hr %#x.\n", hr);
2368
2369 ok(!unk_out, "[out] parameter should not have been set.\n");
2370if (hr == S_OK) {
2371 hr = IUnknown_QueryInterface(unk_in_out, &IID_ISomethingFromDispatch, (void **)&sfd_in_out);
2372 ok(hr == S_OK, "Got hr %#x.\n", hr);
2373 hr = ISomethingFromDispatch_anotherfn(sfd_in_out);
2374 ok(hr == 0x01234567, "Got hr %#x.\n", hr);
2375 ISomethingFromDispatch_Release(sfd_in_out);
2376
2377 release_iface(unk_in_out);
2378}
2379
2380 testmode = 3;
2381 unk_in = unk_out = NULL;
2382 sfd3 = create_disp_obj();
2383 unk_in_out = (IUnknown *)sfd3;
2384 IUnknown_AddRef(unk_in_out);
2385 hr = IDispatch_Invoke(disp, DISPID_TM_IFACE_PTR, &IID_NULL, LOCALE_NEUTRAL,
2386 DISPATCH_METHOD, &dispparams, NULL, NULL, NULL);
2387todo_wine {
2388 ok(hr == S_OK, "Got hr %#x.\n", hr);
2389 ok(!unk_in_out, "[in, out] parameter should have been cleared.\n");
2390 release_iface(sfd3);
2391}
2392}
2393
2394static void test_marshal_bstr(IWidget *widget, IDispatch *disp)
2395{
2396 VARIANTARG arg[4];
2397 DISPPARAMS dispparams = {arg, NULL, ARRAY_SIZE(arg), 0};
2398 BSTR in, out, in_ptr, in_out;
2399 HRESULT hr;
2400 UINT len;
2401
2402 testmode = 0;
2404 out = NULL;
2405 in_ptr = SysAllocString(test_bstr2);
2406 in_out = SysAllocString(test_bstr3);
2407
2408 V_VT(&arg[3]) = VT_BSTR; V_BSTR(&arg[3]) = in;
2409 V_VT(&arg[2]) = VT_BSTR|VT_BYREF; V_BSTRREF(&arg[2]) = &out;
2410 V_VT(&arg[1]) = VT_BSTR|VT_BYREF; V_BSTRREF(&arg[1]) = &in_ptr;
2411 V_VT(&arg[0]) = VT_BSTR|VT_BYREF; V_BSTRREF(&arg[0]) = &in_out;
2412 hr = IDispatch_Invoke(disp, DISPID_TM_BSTR, &IID_NULL, LOCALE_NEUTRAL,
2413 DISPATCH_METHOD, &dispparams, NULL, NULL, NULL);
2414 ok(hr == S_OK, "Got hr %#x.\n", hr);
2415 ok(in[1] == test_bstr1[1], "[in] parameter should not be changed.\n");
2416 ok(in_ptr[1] == 'X', "[in] pointer should be changed.\n");
2417 ok(in_out[1] == 'X', "[in, out] parameter should be changed.\n");
2418 len = SysStringLen(out);
2419 ok(len == lstrlenW(test_bstr4), "Got wrong length %d.\n", len);
2420 ok(!memcmp(out, test_bstr4, len), "Got string %s.\n", wine_dbgstr_wn(out, len));
2421
2422 in[1] = test_bstr1[1];
2423 in_ptr[1] = test_bstr2[1];
2424 in_out[1] = test_bstr3[1];
2426 out = (BSTR)0xdeadbeef;
2427 hr = IWidget_bstr(widget, in, &out, &in_ptr, &in_out);
2428 ok(hr == S_OK, "Got hr %#x.\n", hr);
2429 ok(in[1] == test_bstr1[1], "[in] parameter should not be changed.\n");
2430 ok(in_ptr[1] == test_bstr2[1], "[in] pointer should not be changed.\n");
2431 ok(in_out[1] == 'X', "[in, out] parameter should be changed.\n");
2432 len = SysStringLen(out);
2433 ok(len == lstrlenW(test_bstr4), "Got wrong length %d.\n", len);
2434 ok(!memcmp(out, test_bstr4, len), "Got string %s.\n", wine_dbgstr_wn(out, len));
2437 SysFreeString(in_ptr);
2438 SysFreeString(in_out);
2439
2440 testmode = 1;
2441 out = in_ptr = in_out = NULL;
2442 hr = IWidget_bstr(widget, NULL, &out, &in_ptr, &in_out);
2443 ok(hr == S_OK, "Got hr %#x.\n", hr);
2444}
2445
2446static void test_marshal_variant(IWidget *widget, IDispatch *disp)
2447{
2448 VARIANTARG arg[4];
2449 DISPPARAMS dispparams = {arg, NULL, ARRAY_SIZE(arg), 0};
2450 VARIANT out, in_ptr, in_out;
2451 HRESULT hr;
2452 BSTR bstr;
2453
2454 testmode = 0;
2455 V_VT(&out) = VT_I4;
2456 V_I4(&out) = 1;
2457 V_VT(&in_ptr) = VT_I4;
2458 V_I4(&in_ptr) = -1;
2459 V_VT(&in_out) = VT_BSTR;
2460 V_BSTR(&in_out) = bstr = SysAllocString(test_bstr2);
2461
2462 V_VT(&arg[3]) = VT_CY;
2463 V_CY(&arg[3]).Hi = 0xdababe;
2464 V_CY(&arg[3]).Lo = 0xdeadbeef;
2465 V_VT(&arg[2]) = VT_VARIANT|VT_BYREF; V_VARIANTREF(&arg[2]) = &out;
2466 V_VT(&arg[1]) = VT_VARIANT|VT_BYREF; V_VARIANTREF(&arg[1]) = &in_ptr;
2467 V_VT(&arg[0]) = VT_VARIANT|VT_BYREF; V_VARIANTREF(&arg[0]) = &in_out;
2468 hr = IDispatch_Invoke(disp, DISPID_TM_VARIANT, &IID_NULL, LOCALE_NEUTRAL,
2469 DISPATCH_METHOD, &dispparams, NULL, NULL, NULL);
2470 ok(hr == S_OK, "Got hr %#x.\n", hr);
2471 ok(V_VT(&arg[3]) == VT_CY, "Got wrong type %u.\n", V_VT(&arg[3]));
2472 ok(V_VT(&out) == VT_UI1, "Got wrong type %u.\n", V_VT(&out));
2473 ok(V_UI1(&out) == 3, "Got wrong value %d.\n", V_UI1(&out));
2474 VariantClear(&out);
2475 ok(V_VT(&in_ptr) == VT_I2, "Got wrong type %u.\n", V_VT(&in_ptr));
2476 ok(V_I2(&in_ptr) == 4, "Got wrong value %d.\n", V_I1(&in_ptr));
2477 ok(V_VT(&in_out) == VT_I1, "Got wrong type %u.\n", V_VT(&in_out));
2478 ok(V_I1(&in_out) == 5, "Got wrong value %d.\n", V_I1(&in_out));
2479
2480 testmode = 1;
2481 V_VT(&out) = VT_I4;
2482 V_I4(&out) = 1;
2483 V_VT(&in_ptr) = VT_I4;
2484 V_I4(&in_ptr) = -1;
2485 V_VT(&in_out) = VT_BSTR;
2486 V_BSTR(&in_out) = bstr = SysAllocString(test_bstr2);
2487 hr = IWidget_variant(widget, arg[3], &out, &in_ptr, &in_out);
2488 ok(hr == S_OK, "Got hr %#x.\n", hr);
2489 ok(V_VT(&arg[3]) == VT_CY, "Got wrong type %u.\n", V_VT(&arg[3]));
2490 ok(V_VT(&out) == VT_UI1, "Got wrong type %u.\n", V_VT(&out));
2491 ok(V_UI1(&out) == 3, "Got wrong value %d.\n", V_UI1(&out));
2492 ok(V_VT(&in_ptr) == VT_I4, "Got wrong type %u.\n", V_VT(&in_ptr));
2493 ok(V_I2(&in_ptr) == -1, "Got wrong value %d.\n", V_I1(&in_ptr));
2494 ok(V_VT(&in_out) == VT_I1, "Got wrong type %u.\n", V_VT(&in_out));
2495 ok(V_I1(&in_out) == 5, "Got wrong value %d.\n", V_I1(&in_out));
2496}
2497
2498static void test_marshal_safearray(IWidget *widget, IDispatch *disp)
2499{
2500 SAFEARRAY *in, *out, *out2, *in_ptr, *in_out;
2501 HRESULT hr;
2502
2503 in = make_safearray(3);
2504 out = out2 = make_safearray(5);
2505 in_ptr = make_safearray(7);
2506 in_out = make_safearray(9);
2507 hr = IWidget_safearray(widget, in, &out, &in_ptr, &in_out);
2508 ok(hr == S_OK, "Got hr %#x.\n", hr);
2509 check_safearray(in, 3);
2510 check_safearray(out, 4);
2511 check_safearray(out2, 5);
2512 check_safearray(in_ptr, 7);
2513 check_safearray(in_out, 6);
2514
2517 SafeArrayDestroy(out2);
2518 SafeArrayDestroy(in_ptr);
2519 SafeArrayDestroy(in_out);
2520}
2521
2522static void test_marshal_struct(IWidget *widget, IDispatch *disp)
2523{
2524 MYSTRUCT out, in_ptr, in_out, *in_ptr_ptr;
2525 RECT rect_out, rect_in_ptr, rect_in_out;
2526 ISomethingFromDispatch *sfd;
2527 struct complex complex;
2528 int i, i2, *pi = &i2;
2529 HRESULT hr;
2530
2531 memcpy(&out, &test_mystruct2, sizeof(MYSTRUCT));
2532 memcpy(&in_ptr, &test_mystruct3, sizeof(MYSTRUCT));
2533 memcpy(&in_out, &test_mystruct4, sizeof(MYSTRUCT));
2534 hr = IWidget_mystruct(widget, test_mystruct1, &out, &in_ptr, &in_out);
2535 ok(hr == S_OK, "Got hr %#x.\n", hr);
2536 ok(!memcmp(&out, &test_mystruct5, sizeof(MYSTRUCT)), "Structs didn't match.\n");
2537 ok(!memcmp(&in_ptr, &test_mystruct3, sizeof(MYSTRUCT)), "Structs didn't match.\n");
2538 ok(!memcmp(&in_out, &test_mystruct7, sizeof(MYSTRUCT)), "Structs didn't match.\n");
2539
2540 memcpy(&in_ptr, &test_mystruct1, sizeof(MYSTRUCT));
2541 in_ptr_ptr = &in_ptr;
2542 hr = IWidget_mystruct_ptr_ptr(widget, &in_ptr_ptr);
2543 ok(hr == S_OK, "Got hr %#x.\n", hr);
2544
2545 /* Make sure that "thin" structs (<=8 bytes) are handled correctly in x86-64. */
2546
2547 hr = IWidget_thin_struct(widget, test_thin_struct);
2548 ok(hr == S_OK, "Got hr %#x.\n", hr);
2549
2550 /* Make sure we can handle an imported type. */
2551
2552 rect_out = test_rect2;
2553 rect_in_ptr = test_rect3;
2554 rect_in_out = test_rect4;
2555 hr = IWidget_rect(widget, test_rect1, &rect_out, &rect_in_ptr, &rect_in_out);
2556 ok(hr == S_OK, "Got hr %#x.\n", hr);
2557 ok(EqualRect(&rect_out, &test_rect5), "Rects didn't match.\n");
2558 ok(EqualRect(&rect_in_ptr, &test_rect3), "Rects didn't match.\n");
2559 ok(EqualRect(&rect_in_out, &test_rect7), "Rects didn't match.\n");
2560
2561 /* Test complex structs. */
2562 complex.c = 98;
2563 complex.i = 76543;
2564 i = 2;
2565 complex.pi = &i;
2566 i2 = 10;
2567 complex.ppi = &pi;
2568 complex.iface = create_disp_obj();
2569 sfd = create_disp_obj();
2570 complex.iface_ptr = &sfd;
2572 V_VT(&complex.var) = VT_I4;
2573 V_I4(&complex.var) = 123;
2574 memcpy(&complex.mystruct, &test_mystruct1, sizeof(MYSTRUCT));
2575 memcpy(complex.arr, test_array1, sizeof(array_t));
2576 complex.myint = 456;
2577 hr = IWidget_complex_struct(widget, complex);
2578 ok(hr == S_OK, "Got hr %#x.\n", hr);
2579}
2580
2581static void test_marshal_array(IWidget *widget, IDispatch *disp)
2582{
2583 VARIANT var_in[2], var_out[2], var_in_out[2];
2584 ISomethingFromDispatch *proxy_sfd;
2585 array_t in, out, in_out;
2586 MYSTRUCT struct_in[2];
2587 HRESULT hr;
2588 int i = 2;
2589
2590 memcpy(in, test_array1, sizeof(array_t));
2591 memcpy(out, test_array2, sizeof(array_t));
2592 memcpy(in_out, test_array3, sizeof(array_t));
2593 hr = IWidget_array(widget, in, out, in_out);
2594 ok(hr == S_OK, "Got hr %#x.\n", hr);
2595 ok(!memcmp(&in, &test_array1, sizeof(array_t)), "Arrays didn't match.\n");
2596 ok(!memcmp(&out, &test_array5, sizeof(array_t)), "Arrays didn't match.\n");
2597 ok(!memcmp(&in_out, &test_array6, sizeof(array_t)), "Arrays didn't match.\n");
2598
2599 V_VT(&var_in[0]) = VT_I4; V_I4(&var_in[0]) = 1;
2600 V_VT(&var_in[1]) = VT_BYREF|VT_I4; V_I4REF(&var_in[1]) = &i;
2601 V_VT(&var_out[0]) = VT_I4; V_I4(&var_out[0]) = 3;
2602 V_VT(&var_out[1]) = VT_I4; V_I4(&var_out[1]) = 4;
2603 V_VT(&var_in_out[0]) = VT_I4; V_I4(&var_in_out[0]) = 5;
2604 V_VT(&var_in_out[1]) = VT_BSTR; V_BSTR(&var_in_out[1]) = SysAllocString(test_bstr1);
2605 hr = IWidget_variant_array(widget, var_in, var_out, var_in_out);
2606 ok(hr == S_OK, "Got hr %#x.\n", hr);
2607 ok(V_VT(&var_in[0]) == VT_I4, "Got wrong type %u.\n", V_VT(&var_in[0]));
2608 ok(V_I4(&var_in[0]) == 1, "Got wrong value %d.\n", V_I4(&var_in[0]));
2609 ok(V_VT(&var_in[1]) == (VT_BYREF|VT_I4), "Got wrong type %u.\n", V_VT(&var_in[1]));
2610 ok(V_I4REF(&var_in[1]) == &i, "Got wrong value %p.\n", V_I4REF(&var_in[1]));
2611 ok(i == 2, "Got wrong value %d.\n", i);
2612 ok(V_VT(&var_out[0]) == VT_I1, "Got wrong type %u.\n", V_VT(&var_out[0]));
2613 ok(V_I1(&var_out[0]) == 9, "Got wrong value %u.\n", V_VT(&var_out[0]));
2614 ok(V_VT(&var_out[1]) == VT_BSTR, "Got wrong type %u.\n", V_VT(&var_out[1]));
2615 ok(!lstrcmpW(V_BSTR(&var_out[1]), test_bstr2), "Got wrong value %s.\n", wine_dbgstr_w(V_BSTR(&var_out[1])));
2616 ok(V_VT(&var_in_out[0]) == VT_I1, "Got wrong type %u.\n", V_VT(&var_in_out[0]));
2617 ok(V_I1(&var_in_out[0]) == 11, "Got wrong value %u.\n", V_VT(&var_in_out[0]));
2618 ok(V_VT(&var_in_out[1]) == VT_UNKNOWN, "Got wrong type %u.\n", V_VT(&var_in_out[1]));
2619 hr = IUnknown_QueryInterface(V_UNKNOWN(&var_in_out[1]), &IID_ISomethingFromDispatch, (void **)&proxy_sfd);
2620 ok(hr == S_OK, "Got hr %#x.\n", hr);
2621 hr = ISomethingFromDispatch_anotherfn(proxy_sfd);
2622 ok(hr == 0x01234567, "Got hr %#x.\n", hr);
2623 ISomethingFromDispatch_Release(proxy_sfd);
2624 release_iface(V_UNKNOWN(&var_in_out[1]));
2625
2626 memcpy(&struct_in[0], &test_mystruct1, sizeof(MYSTRUCT));
2627 memcpy(&struct_in[1], &test_mystruct2, sizeof(MYSTRUCT));
2628 hr = IWidget_mystruct_array(widget, struct_in);
2629 ok(hr == S_OK, "Got hr %#x.\n", hr);
2630}
2631
2632static void test_marshal_coclass(IWidget *widget, IDispatch *disp)
2633{
2634 VARIANTARG arg[3];
2635 DISPPARAMS dispparams = {arg, NULL, ARRAY_SIZE(arg), 0};
2636 struct coclass_obj *class1, *class2, *class3;
2637 IUnknown *unk_in, *unk_out, *unk_in_out;
2638 ICoclass1 *in, *out, *in_out;
2639 HRESULT hr;
2640
2641 class1 = create_coclass_obj();
2642 class2 = create_coclass_obj();
2643 class3 = create_coclass_obj();
2644
2645 hr = IWidget_Coclass(widget, (Coclass1 *)&class1->ICoclass1_iface,
2646 (Coclass2 *)&class2->ICoclass1_iface, (Coclass3 *)&class3->ICoclass1_iface);
2647 ok(hr == S_OK, "Got hr %#x.\n", hr);
2648
2649 hr = IWidget_Coclass(widget, (Coclass1 *)&class1->ICoclass2_iface,
2650 (Coclass2 *)&class2->ICoclass2_iface, (Coclass3 *)&class3->ICoclass2_iface);
2651 ok(hr == S_OK, "Got hr %#x.\n", hr);
2652
2656
2657 testmode = 0;
2658 class1 = create_coclass_obj();
2659 class2 = create_coclass_obj();
2660 class3 = create_coclass_obj();
2661 in = &class1->ICoclass1_iface;
2662 out = &class2->ICoclass1_iface;
2663 in_out = &class3->ICoclass1_iface;
2664 hr = IWidget_Coclass_ptr(widget, (Coclass1 **)&in, (Coclass1 **)&out, (Coclass1 **)&in_out);
2665 ok(hr == S_OK, "Got hr %#x.\n", hr);
2666 ok(in == &class1->ICoclass1_iface, "[in] parameter should not have changed.\n");
2667 ok(!out, "[out] parameter should have been cleared.\n");
2668 ok(in_out == &class3->ICoclass1_iface, "[in, out] parameter should not have changed.\n");
2672
2673 testmode = 1;
2674 class1 = create_coclass_obj();
2675 class3 = create_coclass_obj();
2676 in = &class1->ICoclass1_iface;
2677 in_out = &class3->ICoclass1_iface;
2678 ICoclass1_AddRef(in_out);
2679 hr = IWidget_Coclass_ptr(widget, (Coclass1 **)&in,
2680 (Coclass1 **)&out, (Coclass1 **)&in_out);
2681 ok(hr == S_OK, "Got hr %#x.\n", hr);
2682 hr = ICoclass1_test(out);
2683 ok(hr == 1, "Got hr %#x.\n", hr);
2684 ok(in_out != &class3->ICoclass1_iface, "[in, out] parameter should have changed.\n");
2685 hr = ICoclass1_test(in_out);
2686 ok(hr == 1, "Got hr %#x.\n", hr);
2688 release_iface(in_out);
2691
2692 testmode = 2;
2693 in = out = in_out = NULL;
2694 hr = IWidget_Coclass_ptr(widget, (Coclass1 **)&in,
2695 (Coclass1 **)&out, (Coclass1 **)&in_out);
2696 ok(hr == S_OK, "Got hr %#x.\n", hr);
2697 hr = ICoclass1_test(in_out);
2698 ok(hr == 1, "Got hr %#x.\n", hr);
2699 release_iface(in_out);
2700
2701 testmode = 3;
2702 in = out = NULL;
2703 class3 = create_coclass_obj();
2704 in_out = &class3->ICoclass1_iface;
2705 hr = IWidget_Coclass_ptr(widget, (Coclass1 **)&in,
2706 (Coclass1 **)&out, (Coclass1 **)&in_out);
2707 ok(hr == S_OK, "Got hr %#x.\n", hr);
2708 ok(!in_out, "Got [in, out] %p.\n", in_out);
2709
2710 /* Test with Invoke(). Note that since we pass VT_UNKNOWN, we don't get our
2711 * interface back, but rather an IUnknown. */
2712
2713 class1 = create_coclass_obj();
2714 class2 = create_coclass_obj();
2715 class3 = create_coclass_obj();
2716
2717 V_VT(&arg[2]) = VT_UNKNOWN; V_UNKNOWN(&arg[2]) = (IUnknown *)&class1->ICoclass1_iface;
2718 V_VT(&arg[1]) = VT_UNKNOWN; V_UNKNOWN(&arg[1]) = (IUnknown *)&class2->ICoclass1_iface;
2719 V_VT(&arg[0]) = VT_UNKNOWN; V_UNKNOWN(&arg[0]) = (IUnknown *)&class3->ICoclass1_iface;
2720 hr = IDispatch_Invoke(disp, DISPID_TM_COCLASS, &IID_NULL, LOCALE_NEUTRAL,
2721 DISPATCH_METHOD, &dispparams, NULL, NULL, NULL);
2722 ok(hr == S_OK, "Got hr %#x.\n", hr);
2723
2724 V_VT(&arg[2]) = VT_UNKNOWN; V_UNKNOWN(&arg[2]) = (IUnknown *)&class1->ICoclass2_iface;
2725 V_VT(&arg[1]) = VT_UNKNOWN; V_UNKNOWN(&arg[1]) = (IUnknown *)&class2->ICoclass2_iface;
2726 V_VT(&arg[0]) = VT_UNKNOWN; V_UNKNOWN(&arg[0]) = (IUnknown *)&class3->ICoclass2_iface;
2727 hr = IDispatch_Invoke(disp, DISPID_TM_COCLASS, &IID_NULL, LOCALE_NEUTRAL,
2728 DISPATCH_METHOD, &dispparams, NULL, NULL, NULL);
2729 ok(hr == S_OK, "Got hr %#x.\n", hr);
2730
2731 V_VT(&arg[2]) = VT_DISPATCH; V_DISPATCH(&arg[2]) = (IDispatch *)&class1->ICoclass1_iface;
2732 V_VT(&arg[1]) = VT_DISPATCH; V_DISPATCH(&arg[1]) = (IDispatch *)&class2->ICoclass1_iface;
2733 V_VT(&arg[0]) = VT_DISPATCH; V_DISPATCH(&arg[0]) = (IDispatch *)&class3->ICoclass1_iface;
2734 hr = IDispatch_Invoke(disp, DISPID_TM_COCLASS, &IID_NULL, LOCALE_NEUTRAL,
2735 DISPATCH_METHOD, &dispparams, NULL, NULL, NULL);
2736 ok(hr == S_OK, "Got hr %#x.\n", hr);
2737
2741
2742 testmode = 0;
2743 class1 = create_coclass_obj();
2744 class3 = create_coclass_obj();
2745 unk_in = (IUnknown *)&class1->ICoclass1_iface;
2746 unk_out = NULL;
2747 unk_in_out = (IUnknown *)&class3->ICoclass1_iface;
2750 V_VT(&arg[0]) = VT_UNKNOWN|VT_BYREF; V_UNKNOWNREF(&arg[0]) = &unk_in_out;
2751 hr = IDispatch_Invoke(disp, DISPID_TM_COCLASS_PTR, &IID_NULL, LOCALE_NEUTRAL,
2752 DISPATCH_METHOD, &dispparams, NULL, NULL, NULL);
2754 ok(hr == S_OK, "Got hr %#x.\n", hr);
2755 ok(unk_in == (IUnknown *)&class1->ICoclass1_iface, "[in] parameter should not have changed.\n");
2756 ok(!unk_out, "[out] parameter should have been cleared.\n");
2757 ok(unk_in_out == (IUnknown *)&class3->ICoclass1_iface, "[in, out] parameter should not have changed.\n");
2760
2761 testmode = 1;
2762 class1 = create_coclass_obj();
2763 class3 = create_coclass_obj();
2764 unk_in = (IUnknown *)&class1->ICoclass1_iface;
2765 unk_out = NULL;
2766 unk_in_out = (IUnknown *)&class3->ICoclass1_iface;
2767 IUnknown_AddRef(unk_in_out);
2768 hr = IDispatch_Invoke(disp, DISPID_TM_COCLASS_PTR, &IID_NULL, LOCALE_NEUTRAL,
2769 DISPATCH_METHOD, &dispparams, NULL, NULL, NULL);
2771 ok(hr == S_OK, "Got hr %#x.\n", hr);
2772
2773if (hr == S_OK) {
2774 hr = IUnknown_QueryInterface(unk_out, &IID_ICoclass1, (void **)&out);
2775 ok(hr == S_OK, "Got hr %#x.\n", hr);
2776 hr = ICoclass1_test(out);
2777 ok(hr == 1, "Got hr %#x.\n", hr);
2778 ICoclass1_Release(out);
2779
2780 ok(unk_in_out != (IUnknown *)&class3->ICoclass1_iface, "[in, out] parameter should have changed.\n");
2781 hr = IUnknown_QueryInterface(unk_in_out, &IID_ICoclass1, (void **)&in_out);
2782 ok(hr == S_OK, "Got hr %#x.\n", hr);
2783 hr = ICoclass1_test(in_out);
2784 ok(hr == 1, "Got hr %#x.\n", hr);
2785 ICoclass1_Release(in_out);
2786
2788 release_iface(unk_in_out);
2789}
2793
2794 testmode = 2;
2795 unk_in = unk_out = unk_in_out = NULL;
2796 hr = IDispatch_Invoke(disp, DISPID_TM_COCLASS_PTR, &IID_NULL, LOCALE_NEUTRAL,
2797 DISPATCH_METHOD, &dispparams, NULL, NULL, NULL);
2799 ok(hr == S_OK, "Got hr %#x.\n", hr);
2800
2801 ok(!unk_out, "[out] parameter should not have been set.\n");
2802if (hr == S_OK) {
2803 hr = IUnknown_QueryInterface(unk_in_out, &IID_ICoclass1, (void **)&in_out);
2804 ok(hr == S_OK, "Got hr %#x.\n", hr);
2805 hr = ICoclass1_test(in_out);
2806 ok(hr == 1, "Got hr %#x.\n", hr);
2807 ICoclass1_Release(in_out);
2808
2809 release_iface(unk_in_out);
2810}
2811
2812 testmode = 3;
2813 unk_in = unk_out = NULL;
2814 class3 = create_coclass_obj();
2815 unk_in_out = (IUnknown *)&class3->ICoclass1_iface;
2816 IUnknown_AddRef(unk_in_out);
2817 hr = IDispatch_Invoke(disp, DISPID_TM_COCLASS_PTR, &IID_NULL, LOCALE_NEUTRAL,
2818 DISPATCH_METHOD, &dispparams, NULL, NULL, NULL);
2820 ok(hr == S_OK, "Got hr %#x.\n", hr);
2822 ok(!unk_in_out, "[in, out] parameter should have been cleared.\n");
2823
2826}
2827
2828static void test_typelibmarshal(void)
2829{
2830 static const WCHAR szCat[] = { 'C','a','t',0 };
2831 static const WCHAR szTestTest[] = { 'T','e','s','t','T','e','s','t',0 };
2832 static const WCHAR szSuperman[] = { 'S','u','p','e','r','m','a','n',0 };
2833 HRESULT hr;
2834 IKindaEnumWidget *pKEW = KindaEnumWidget_Create();
2835 IWidget *pWidget;
2836 IStream *pStream;
2837 IDispatch *pDispatch;
2838 static const LARGE_INTEGER ullZero;
2839 EXCEPINFO excepinfo;
2840 VARIANT varresult;
2841 DISPID dispidNamed = DISPID_PROPERTYPUT;
2842 DISPPARAMS dispparams;
2843 VARIANTARG vararg[4];
2844 STATE the_state;
2845 HANDLE thread;
2846 DWORD tid;
2847 BSTR bstr;
2848 ITypeInfo *pTypeInfo;
2849 UINT uval;
2850
2851 ok(pKEW != NULL, "Widget creation failed\n");
2852
2853 hr = CreateStreamOnHGlobal(NULL, TRUE, &pStream);
2855 tid = start_host_object(pStream, &IID_IKindaEnumWidget, (IUnknown *)pKEW, MSHLFLAGS_NORMAL, &thread);
2856 IKindaEnumWidget_Release(pKEW);
2857
2858 IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
2859 hr = CoUnmarshalInterface(pStream, &IID_IKindaEnumWidget, (void **)&pKEW);
2861 IStream_Release(pStream);
2862 if (FAILED(hr))
2863 {
2865 return;
2866 }
2867
2868 hr = IKindaEnumWidget_Next(pKEW, &pWidget);
2869 ok_ole_success(hr, IKindaEnumWidget_Next);
2870
2871 IKindaEnumWidget_Release(pKEW);
2872
2873 /* call GetTypeInfoCount (direct) */
2874 hr = IWidget_GetTypeInfoCount(pWidget, &uval);
2875 ok_ole_success(hr, IWidget_GetTypeInfoCount);
2876 hr = IWidget_GetTypeInfoCount(pWidget, &uval);
2877 ok_ole_success(hr, IWidget_GetTypeInfoCount);
2878
2879 hr = IWidget_QueryInterface(pWidget, &IID_IDispatch, (void **)&pDispatch);
2880 ok_ole_success(hr, IWidget_QueryInterface);
2881
2882 /* call put_Name */
2883 VariantInit(&vararg[0]);
2884 dispparams.cNamedArgs = 1;
2885 dispparams.rgdispidNamedArgs = &dispidNamed;
2886 dispparams.cArgs = 1;
2887 dispparams.rgvarg = vararg;
2888 VariantInit(&varresult);
2889 hr = IDispatch_Invoke(pDispatch, DISPID_TM_NAME, &IID_NULL, LOCALE_NEUTRAL, DISPATCH_PROPERTYPUT, &dispparams, &varresult, &excepinfo, NULL);
2890 ok_ole_success(hr, IDispatch_Invoke);
2891 ok(excepinfo.wCode == 0x0 && excepinfo.scode == S_OK,
2892 "EXCEPINFO differs from expected: wCode = 0x%x, scode = 0x%08x\n",
2893 excepinfo.wCode, excepinfo.scode);
2894 VariantClear(&varresult);
2895
2896 /* call put_Name (direct) */
2897 bstr = SysAllocString(szSuperman);
2898 hr = IWidget_put_Name(pWidget, bstr);
2899 ok_ole_success(hr, IWidget_put_Name);
2900 SysFreeString(bstr);
2901
2902 /* call get_Name */
2903 dispparams.cNamedArgs = 0;
2904 dispparams.rgdispidNamedArgs = NULL;
2905 dispparams.cArgs = 0;
2906 dispparams.rgvarg = NULL;
2907 VariantInit(&varresult);
2908 hr = IDispatch_Invoke(pDispatch, DISPID_TM_NAME, &IID_NULL, LOCALE_NEUTRAL, DISPATCH_PROPERTYGET, &dispparams, &varresult, &excepinfo, NULL);
2909 ok_ole_success(hr, IDispatch_Invoke);
2910 ok(excepinfo.wCode == 0x0 && excepinfo.scode == S_OK,
2911 "EXCEPINFO differs from expected: wCode = 0x%x, scode = 0x%08x\n",
2912 excepinfo.wCode, excepinfo.scode);
2913 trace("Name = %s\n", wine_dbgstr_w(V_BSTR(&varresult)));
2914 VariantClear(&varresult);
2915
2916 /* call get_Name (direct) */
2917 bstr = (void *)0xdeadbeef;
2918 hr = IWidget_get_Name(pWidget, &bstr);
2919 ok_ole_success(hr, IWidget_get_Name);
2920 ok(!lstrcmpW(bstr, szCat), "IWidget_get_Name should have returned string \"Cat\" instead of %s\n", wine_dbgstr_w(bstr));
2921 SysFreeString(bstr);
2922
2923 /* call DoSomething without optional arguments */
2924 VariantInit(&vararg[0]);
2925 VariantInit(&vararg[1]);
2926 V_VT(&vararg[1]) = VT_R8;
2927 V_R8(&vararg[1]) = 3.141;
2928 dispparams.cNamedArgs = 0;
2929 dispparams.cArgs = 2;
2930 dispparams.rgdispidNamedArgs = NULL;
2931 dispparams.rgvarg = vararg;
2932 VariantInit(&varresult);
2933 hr = IDispatch_Invoke(pDispatch, DISPID_TM_DOSOMETHING, &IID_NULL, LOCALE_NEUTRAL, DISPATCH_METHOD, &dispparams, &varresult, &excepinfo, NULL);
2934 ok_ole_success(hr, IDispatch_Invoke);
2935 ok(V_VT(&varresult) == VT_EMPTY, "varresult should be VT_EMPTY\n");
2936 VariantClear(&varresult);
2937
2938 /* call DoSomething with optional argument set to VT_EMPTY */
2939 VariantInit(&vararg[0]);
2940 VariantInit(&vararg[1]);
2941 VariantInit(&vararg[2]);
2942 V_VT(&vararg[2]) = VT_R8;
2943 V_R8(&vararg[2]) = 3.141;
2944 dispparams.cNamedArgs = 0;
2945 dispparams.cArgs = 3;
2946 dispparams.rgdispidNamedArgs = NULL;
2947 dispparams.rgvarg = vararg;
2948 VariantInit(&varresult);
2949 hr = IDispatch_Invoke(pDispatch, DISPID_TM_DOSOMETHING, &IID_NULL, LOCALE_NEUTRAL, DISPATCH_METHOD, &dispparams, &varresult, &excepinfo, NULL);
2950 ok_ole_success(hr, IDispatch_Invoke);
2951 ok(V_VT(&varresult) == VT_EMPTY, "varresult should be VT_EMPTY\n");
2952 VariantClear(&varresult);
2953
2954 /* call DoSomething with optional arguments set to VT_ERROR/DISP_E_PARAMNOTFOUND */
2955 VariantInit(&vararg[0]);
2956 VariantInit(&vararg[1]);
2957 VariantInit(&vararg[2]);
2958 VariantInit(&vararg[3]);
2959 V_VT(&vararg[3]) = VT_R8;
2960 V_R8(&vararg[3]) = 3.141;
2961 V_VT(&vararg[1]) = VT_ERROR;
2962 V_ERROR(&vararg[1]) = DISP_E_PARAMNOTFOUND;
2963 V_VT(&vararg[0]) = VT_ERROR;
2964 V_ERROR(&vararg[0]) = DISP_E_PARAMNOTFOUND;
2965 dispparams.cNamedArgs = 0;
2966 dispparams.cArgs = 4;
2967 dispparams.rgdispidNamedArgs = NULL;
2968 dispparams.rgvarg = vararg;
2969 VariantInit(&varresult);
2970 hr = IDispatch_Invoke(pDispatch, DISPID_TM_DOSOMETHING, &IID_NULL, LOCALE_NEUTRAL, DISPATCH_METHOD, &dispparams, &varresult, &excepinfo, NULL);
2971 ok_ole_success(hr, IDispatch_Invoke);
2972 ok(V_VT(&varresult) == VT_EMPTY, "varresult should be VT_EMPTY\n");
2973 VariantClear(&varresult);
2974
2975 /* call get_State */
2976 dispparams.cNamedArgs = 0;
2977 dispparams.cArgs = 0;
2978 dispparams.rgdispidNamedArgs = NULL;
2979 dispparams.rgvarg = NULL;
2980 hr = IDispatch_Invoke(pDispatch, DISPID_TM_STATE, &IID_NULL, LOCALE_NEUTRAL, DISPATCH_PROPERTYGET, &dispparams, &varresult, &excepinfo, NULL);
2981 ok_ole_success(hr, IDispatch_Invoke);
2982 ok((V_VT(&varresult) == VT_I4) && (V_I4(&varresult) == STATE_WIDGETIFIED), "Return val mismatch\n");
2983
2984 /* call get_State (direct) */
2985 hr = IWidget_get_State(pWidget, &the_state);
2986 ok_ole_success(hr, IWidget_get_state);
2987 ok(the_state == STATE_WIDGETIFIED, "should have returned WIDGET_WIDGETIFIED instead of %d\n", the_state);
2988
2989 /* call put_State */
2990 the_state = STATE_WIDGETIFIED;
2991 VariantInit(&vararg[0]);
2992 V_VT(&vararg[0]) = VT_BYREF|VT_I4;
2993 V_I4REF(&vararg[0]) = (int *)&the_state;
2994 dispparams.cNamedArgs = 1;
2995 dispparams.cArgs = 1;
2996 dispparams.rgdispidNamedArgs = &dispidNamed;
2997 dispparams.rgvarg = vararg;
2998 hr = IDispatch_Invoke(pDispatch, DISPID_TM_STATE, &IID_NULL, LOCALE_NEUTRAL, DISPATCH_PROPERTYPUT, &dispparams, &varresult, &excepinfo, NULL);
2999 ok_ole_success(hr, IDispatch_Invoke);
3000
3001 /* call Map */
3002 bstr = SysAllocString(szTestTest);
3003 VariantInit(&vararg[0]);
3004 V_VT(&vararg[0]) = VT_BYREF|VT_BSTR;
3005 V_BSTRREF(&vararg[0]) = &bstr;
3006 dispparams.cNamedArgs = 0;
3007 dispparams.cArgs = 1;
3008 dispparams.rgdispidNamedArgs = NULL;
3009 dispparams.rgvarg = vararg;
3010 VariantInit(&varresult);
3011 hr = IDispatch_Invoke(pDispatch, DISPID_TM_MAP, &IID_NULL, LOCALE_NEUTRAL, DISPATCH_METHOD, &dispparams, &varresult, &excepinfo, NULL);
3012 ok_ole_success(hr, IDispatch_Invoke);
3013 ok(V_VT(&varresult) == VT_BSTR, "Return value should be of type BSTR instead of %d\n", V_VT(&varresult));
3014 ok(!lstrcmpW(V_BSTR(&varresult), szTestTest), "Return value should have been \"TestTest\" instead of %s\n", wine_dbgstr_w(V_BSTR(&varresult)));
3015 VariantClear(&varresult);
3016 SysFreeString(bstr);
3017
3018 /* call SetOleColor with large negative VT_I4 param */
3019 VariantInit(&vararg[0]);
3020 V_VT(&vararg[0]) = VT_I4;
3021 V_I4(&vararg[0]) = 0x80000005;
3022 dispparams.cNamedArgs = 0;
3023 dispparams.cArgs = 1;
3024 dispparams.rgdispidNamedArgs = NULL;
3025 dispparams.rgvarg = vararg;
3026 hr = IDispatch_Invoke(pDispatch, DISPID_TM_SETOLECOLOR, &IID_NULL, LOCALE_NEUTRAL, DISPATCH_METHOD, &dispparams, NULL, &excepinfo, NULL);
3027 ok_ole_success(hr, IDispatch_Invoke);
3028
3029 /* call GetOleColor */
3030 dispparams.cNamedArgs = 0;
3031 dispparams.cArgs = 0;
3032 dispparams.rgdispidNamedArgs = NULL;
3033 dispparams.rgvarg = NULL;
3034 VariantInit(&varresult);
3035 hr = IDispatch_Invoke(pDispatch, DISPID_TM_GETOLECOLOR, &IID_NULL, LOCALE_NEUTRAL, DISPATCH_METHOD, &dispparams, &varresult, &excepinfo, NULL);
3036 ok_ole_success(hr, IDispatch_Invoke);
3037 VariantClear(&varresult);
3038
3039 /* call Clone */
3040 dispparams.cNamedArgs = 0;
3041 dispparams.cArgs = 0;
3042 dispparams.rgdispidNamedArgs = NULL;
3043 dispparams.rgvarg = NULL;
3044 VariantInit(&varresult);
3045 hr = IDispatch_Invoke(pDispatch, DISPID_TM_CLONE, &IID_NULL, LOCALE_NEUTRAL, DISPATCH_PROPERTYGET, &dispparams, &varresult, &excepinfo, NULL);
3046 ok_ole_success(hr, IDispatch_Invoke);
3047 ok(V_VT(&varresult) == VT_DISPATCH, "vt %x\n", V_VT(&varresult));
3048 VariantClear(&varresult);
3049
3050 /* call CloneInterface */
3051 dispparams.cNamedArgs = 0;
3052 dispparams.cArgs = 0;
3053 dispparams.rgdispidNamedArgs = NULL;
3054 dispparams.rgvarg = NULL;
3055 VariantInit(&varresult);
3056 hr = IDispatch_Invoke(pDispatch, DISPID_TM_CLONEINTERFACE, &IID_NULL, LOCALE_NEUTRAL, DISPATCH_PROPERTYGET, &dispparams, &varresult, &excepinfo, NULL);
3057 ok_ole_success(hr, IDispatch_Invoke);
3058 ok(V_VT(&varresult) == VT_DISPATCH, "vt %x\n", V_VT(&varresult));
3059 VariantClear(&varresult);
3060
3061 /* call CloneDispatch with automatic value getting */
3062 V_VT(&vararg[0]) = VT_I2;
3063 V_I2(&vararg[0]) = 1;
3064 dispparams.cNamedArgs = 0;
3065 dispparams.rgdispidNamedArgs = NULL;
3066 dispparams.cArgs = 1;
3067 dispparams.rgvarg = vararg;
3068 VariantInit(&varresult);
3069 hr = IDispatch_Invoke(pDispatch, DISPID_TM_CLONEDISPATCH, &IID_NULL, LOCALE_NEUTRAL, DISPATCH_PROPERTYGET, &dispparams, &varresult, &excepinfo, NULL);
3070 ok_ole_success(hr, IDispatch_Invoke);
3071
3072 ok(excepinfo.wCode == 0x0 && excepinfo.scode == S_OK,
3073 "EXCEPINFO differs from expected: wCode = 0x%x, scode = 0x%08x\n",
3074 excepinfo.wCode, excepinfo.scode);
3075
3076 ok(V_VT(&varresult) == VT_I2, "V_VT(&varresult) was %d instead of VT_I2\n", V_VT(&varresult));
3077 ok(V_I2(&varresult) == 1234, "V_I2(&varresult) was %d instead of 1234\n", V_I2(&varresult));
3078 VariantClear(&varresult);
3079
3080 /* call CloneCoclass */
3081 dispparams.cNamedArgs = 0;
3082 dispparams.cArgs = 0;
3083 dispparams.rgdispidNamedArgs = NULL;
3084 dispparams.rgvarg = NULL;
3085 VariantInit(&varresult);
3086 hr = IDispatch_Invoke(pDispatch, DISPID_TM_CLONECOCLASS, &IID_NULL, LOCALE_NEUTRAL, DISPATCH_PROPERTYGET, &dispparams, &varresult, &excepinfo, NULL);
3087 ok_ole_success(hr, IDispatch_Invoke);
3088
3089 ok(excepinfo.wCode == 0x0 && excepinfo.scode == S_OK,
3090 "EXCEPINFO differs from expected: wCode = 0x%x, scode = 0x%08x\n",
3091 excepinfo.wCode, excepinfo.scode);
3092
3093 ok(V_VT(&varresult) == VT_DISPATCH, "V_VT(&varresult) was %d instead of VT_DISPATCH\n", V_VT(&varresult));
3094 ok(V_DISPATCH(&varresult) != NULL, "expected V_DISPATCH(&varresult) != NULL\n");
3095
3096 /* call Value with a VT_VARIANT|VT_BYREF type */
3097 V_VT(&vararg[0]) = VT_VARIANT|VT_BYREF;
3098 V_VARIANTREF(&vararg[0]) = &vararg[1];
3099 V_VT(&vararg[1]) = VT_I2;
3100 V_I2(&vararg[1]) = 1;
3101 dispparams.cNamedArgs = 0;
3102 dispparams.rgdispidNamedArgs = NULL;
3103 dispparams.cArgs = 1;
3104 dispparams.rgvarg = vararg;
3105 VariantInit(&varresult);
3106 hr = IDispatch_Invoke(pDispatch, DISPID_VALUE, &IID_NULL, LOCALE_NEUTRAL, DISPATCH_PROPERTYGET, &dispparams, &varresult, &excepinfo, NULL);
3107 ok_ole_success(hr, IDispatch_Invoke);
3108
3109 ok(excepinfo.wCode == 0x0 && excepinfo.scode == S_OK,
3110 "EXCEPINFO differs from expected: wCode = 0x%x, scode = 0x%08x\n",
3111 excepinfo.wCode, excepinfo.scode);
3112
3113 ok(V_VT(&varresult) == VT_I2, "V_VT(&varresult) was %d instead of VT_I2\n", V_VT(&varresult));
3114 ok(V_I2(&varresult) == 1234, "V_I2(&varresult) was %d instead of 1234\n", V_I2(&varresult));
3115 VariantClear(&varresult);
3116
3117 /* call Array with BSTR argument - type mismatch */
3118 VariantInit(&vararg[0]);
3119 V_VT(&vararg[0]) = VT_BSTR;
3120 V_BSTR(&vararg[0]) = SysAllocString(szSuperman);
3121 dispparams.cNamedArgs = 0;
3122 dispparams.cArgs = 1;
3123 dispparams.rgdispidNamedArgs = NULL;
3124 dispparams.rgvarg = vararg;
3125 hr = IDispatch_Invoke(pDispatch, DISPID_TM_ARRAY, &IID_NULL, LOCALE_NEUTRAL, DISPATCH_METHOD, &dispparams, NULL, NULL, NULL);
3126 ok(hr == DISP_E_TYPEMISMATCH || hr == DISP_E_BADVARTYPE, "expected DISP_E_TYPEMISMATCH, got %#x\n", hr);
3127 SysFreeString(V_BSTR(&vararg[0]));
3128
3129 /* call ArrayPtr with BSTR argument - type mismatch */
3130 VariantInit(&vararg[0]);
3131 V_VT(&vararg[0]) = VT_BSTR;
3132 V_BSTR(&vararg[0]) = SysAllocString(szSuperman);
3133 dispparams.cNamedArgs = 0;
3134 dispparams.cArgs = 1;
3135 dispparams.rgdispidNamedArgs = NULL;
3136 dispparams.rgvarg = vararg;
3137 hr = IDispatch_Invoke(pDispatch, DISPID_TM_VARARRAYPTR, &IID_NULL, LOCALE_NEUTRAL, DISPATCH_METHOD, &dispparams, NULL, NULL, NULL);
3138 ok(hr == DISP_E_TYPEMISMATCH || hr == DISP_E_BADVARTYPE, "expected DISP_E_TYPEMISMATCH, got %#x\n", hr);
3139 SysFreeString(V_BSTR(&vararg[0]));
3140
3141 /* call VarArg */
3142 VariantInit(&vararg[3]);
3143 V_VT(&vararg[3]) = VT_I4;
3144 V_I4(&vararg[3]) = 3;
3145 VariantInit(&vararg[2]);
3146 V_VT(&vararg[2]) = VT_I4;
3147 V_I4(&vararg[2]) = 0;
3148 VariantInit(&vararg[1]);
3149 V_VT(&vararg[1]) = VT_I4;
3150 V_I4(&vararg[1]) = 1;
3151 VariantInit(&vararg[0]);
3152 V_VT(&vararg[0]) = VT_I4;
3153 V_I4(&vararg[0]) = 2;
3154 dispparams.cNamedArgs = 0;
3155 dispparams.cArgs = 4;
3156 dispparams.rgdispidNamedArgs = NULL;
3157 dispparams.rgvarg = vararg;
3158 hr = IDispatch_Invoke(pDispatch, DISPID_TM_VARARG, &IID_NULL, LOCALE_NEUTRAL, DISPATCH_METHOD, &dispparams, NULL, NULL, NULL);
3159 ok_ole_success(hr, IDispatch_Invoke);
3160
3161 /* call VarArg, even one (non-optional, non-safearray) named argument is not allowed */
3162 dispidNamed = 0;
3163 dispparams.cNamedArgs = 1;
3164 dispparams.rgdispidNamedArgs = &dispidNamed;
3165 hr = IDispatch_Invoke(pDispatch, DISPID_TM_VARARG, &IID_NULL, LOCALE_NEUTRAL, DISPATCH_METHOD, &dispparams, NULL, NULL, NULL);
3166 ok(hr == DISP_E_NONAMEDARGS, "IDispatch_Invoke should have returned DISP_E_NONAMEDARGS instead of 0x%08x\n", hr);
3167 dispidNamed = DISPID_PROPERTYPUT;
3168
3169 /* call VarArg_Run */
3170 VariantInit(&vararg[1]);
3171 V_VT(&vararg[1]) = VT_BSTR;
3172 V_BSTR(&vararg[1]) = SysAllocString(szCat);
3173 VariantInit(&vararg[0]);
3174 V_VT(&vararg[0]) = VT_BSTR;
3175 V_BSTR(&vararg[0]) = SysAllocString(szSuperman);
3176 dispparams.cNamedArgs = 0;
3177 dispparams.cArgs = 2;
3178 dispparams.rgdispidNamedArgs = NULL;
3179 dispparams.rgvarg = vararg;
3180 hr = IDispatch_Invoke(pDispatch, DISPID_TM_VARARG_RUN, &IID_NULL, LOCALE_NEUTRAL, DISPATCH_METHOD, &dispparams, NULL, NULL, NULL);
3181 ok_ole_success(hr, IDispatch_Invoke);
3182 SysFreeString(V_BSTR(&vararg[1]));
3183 SysFreeString(V_BSTR(&vararg[0]));
3184
3185 /* call VarArg_Ref_Run */
3186 VariantInit(&vararg[1]);
3187 V_VT(&vararg[1]) = VT_BSTR;
3188 V_BSTR(&vararg[1]) = SysAllocString(szCat);
3189 VariantInit(&vararg[0]);
3190 V_VT(&vararg[0]) = VT_BSTR;
3191 V_BSTR(&vararg[0]) = SysAllocString(szSuperman);
3192 dispparams.cNamedArgs = 0;
3193 dispparams.cArgs = 2;
3194 dispparams.rgdispidNamedArgs = NULL;
3195 dispparams.rgvarg = vararg;
3196 hr = IDispatch_Invoke(pDispatch, DISPID_TM_VARARG_REF_RUN, &IID_NULL, LOCALE_NEUTRAL, DISPATCH_METHOD, &dispparams, NULL, NULL, NULL);
3197 ok_ole_success(hr, IDispatch_Invoke);
3198 SysFreeString(V_BSTR(&vararg[1]));
3199 SysFreeString(V_BSTR(&vararg[0]));
3200
3201 /* call Error */
3202 dispparams.cNamedArgs = 0;
3203 dispparams.cArgs = 0;
3204 dispparams.rgdispidNamedArgs = NULL;
3205 dispparams.rgvarg = NULL;
3206 VariantInit(&varresult);
3207 hr = IDispatch_Invoke(pDispatch, DISPID_TM_ERROR, &IID_NULL, LOCALE_NEUTRAL, DISPATCH_METHOD, &dispparams, NULL, &excepinfo, NULL);
3208 ok(hr == DISP_E_EXCEPTION, "IDispatch_Invoke should have returned DISP_E_EXCEPTION instead of 0x%08x\n", hr);
3209 ok(excepinfo.wCode == 0x0 && excepinfo.scode == E_NOTIMPL,
3210 "EXCEPINFO differs from expected: wCode = 0x%x, scode = 0x%08x\n",
3211 excepinfo.wCode, excepinfo.scode);
3212 VariantClear(&varresult);
3213
3214 /* call BstrRet */
3215 pTypeInfo = NonOleAutomation_GetTypeInfo();
3216 dispparams.cNamedArgs = 0;
3217 dispparams.cArgs = 0;
3218 dispparams.rgdispidNamedArgs = NULL;
3219 dispparams.rgvarg = NULL;
3220 VariantInit(&varresult);
3221 hr = ITypeInfo_Invoke(pTypeInfo, &NonOleAutomation, DISPID_NOA_BSTRRET, DISPATCH_METHOD, &dispparams, &varresult, &excepinfo, NULL);
3222 ok_ole_success(hr, ITypeInfo_Invoke);
3223 ok(V_VT(&varresult) == VT_BSTR, "V_VT(&varresult) should be VT_BSTR instead of %d\n", V_VT(&varresult));
3224 ok(V_BSTR(&varresult) != NULL, "V_BSTR(&varresult) should not be NULL\n");
3225
3226 VariantClear(&varresult);
3227
3228 dispparams.cNamedArgs = 0;
3229 dispparams.cArgs = 0;
3230 dispparams.rgdispidNamedArgs = NULL;
3231 dispparams.rgvarg = NULL;
3232 hr = ITypeInfo_Invoke(pTypeInfo, &NonOleAutomation, DISPID_NOA_ERROR, DISPATCH_METHOD, &dispparams, &varresult, &excepinfo, NULL);
3233 ok(hr == DISP_E_EXCEPTION, "ITypeInfo_Invoke should have returned DISP_E_EXCEPTION instead of 0x%08x\n", hr);
3234 ok(V_VT(&varresult) == VT_EMPTY, "V_VT(&varresult) should be VT_EMPTY instead of %d\n", V_VT(&varresult));
3235 ok(excepinfo.wCode == 0x0 && excepinfo.scode == E_NOTIMPL,
3236 "EXCEPINFO differs from expected: wCode = 0x%x, scode = 0x%08x\n",
3237 excepinfo.wCode, excepinfo.scode);
3238 VariantClear(&varresult);
3239
3240 ITypeInfo_Release(pTypeInfo);
3241
3242 /* tests call put_Name without named arg */
3243 VariantInit(&vararg[0]);
3244 dispparams.cNamedArgs = 0;
3245 dispparams.rgdispidNamedArgs = NULL;
3246 dispparams.cArgs = 1;
3247 dispparams.rgvarg = vararg;
3248 VariantInit(&varresult);
3249 hr = IDispatch_Invoke(pDispatch, DISPID_TM_NAME, &IID_NULL, LOCALE_NEUTRAL, DISPATCH_PROPERTYPUT, &dispparams, &varresult, &excepinfo, NULL);
3250 ok(hr == DISP_E_PARAMNOTFOUND, "IDispatch_Invoke should have returned DISP_E_PARAMNOTFOUND instead of 0x%08x\n", hr);
3251 VariantClear(&varresult);
3252
3253 /* tests param type that cannot be coerced */
3254 VariantInit(&vararg[0]);
3255 V_VT(&vararg[0]) = VT_UNKNOWN;
3256 V_UNKNOWN(&vararg[0]) = NULL;
3257 dispparams.cNamedArgs = 1;
3258 dispparams.rgdispidNamedArgs = &dispidNamed;
3259 dispparams.cArgs = 1;
3260 dispparams.rgvarg = vararg;
3261 VariantInit(&varresult);
3262 hr = IDispatch_Invoke(pDispatch, DISPID_TM_NAME, &IID_NULL, LOCALE_NEUTRAL, DISPATCH_PROPERTYPUT, &dispparams, &varresult, &excepinfo, NULL);
3263 ok(hr == DISP_E_TYPEMISMATCH, "IDispatch_Invoke should have returned DISP_E_TYPEMISMATCH instead of 0x%08x\n", hr);
3264 VariantClear(&varresult);
3265
3266 /* tests bad param type */
3267 VariantInit(&vararg[0]);
3268 V_VT(&vararg[0]) = VT_CLSID;
3269 V_BYREF(&vararg[0]) = NULL;
3270 dispparams.cNamedArgs = 1;
3271 dispparams.rgdispidNamedArgs = &dispidNamed;
3272 dispparams.cArgs = 1;
3273 dispparams.rgvarg = vararg;
3274 VariantInit(&varresult);
3275 hr = IDispatch_Invoke(pDispatch, DISPID_TM_NAME, &IID_NULL, LOCALE_NEUTRAL, DISPATCH_PROPERTYPUT, &dispparams, &varresult, &excepinfo, NULL);
3276 ok(hr == DISP_E_BADVARTYPE, "IDispatch_Invoke should have returned DISP_E_BADVARTYPE instead of 0x%08x\n", hr);
3277 VariantClear(&varresult);
3278
3279 /* tests too small param count */
3280 dispparams.cNamedArgs = 0;
3281 dispparams.rgdispidNamedArgs = NULL;
3282 dispparams.cArgs = 0;
3283 dispparams.rgvarg = NULL;
3284 VariantInit(&varresult);
3285 hr = IDispatch_Invoke(pDispatch, DISPID_TM_DOSOMETHING, &IID_NULL, LOCALE_NEUTRAL, DISPATCH_METHOD, &dispparams, &varresult, &excepinfo, NULL);
3286 ok(hr == DISP_E_BADPARAMCOUNT, "IDispatch_Invoke should have returned DISP_E_BADPARAMCOUNT instead of 0x%08x\n", hr);
3287 VariantClear(&varresult);
3288
3289 /* tests propget function with large param count */
3290 VariantInit(&vararg[0]);
3291 V_VT(&vararg[0]) = VT_BSTR;
3292 V_BSTR(&vararg[0]) = NULL;
3293 V_VT(&vararg[1]) = VT_I4;
3294 V_I4(&vararg[1]) = 1;
3295 dispparams.cNamedArgs = 0;
3296 dispparams.cArgs = 2;
3297 dispparams.rgdispidNamedArgs = NULL;
3298 dispparams.rgvarg = vararg;
3299 hr = IDispatch_Invoke(pDispatch, DISPID_TM_STATE, &IID_NULL, LOCALE_NEUTRAL, DISPATCH_PROPERTYGET, &dispparams, &varresult, &excepinfo, NULL);
3300 ok(hr == DISP_E_NOTACOLLECTION, "IDispatch_Invoke should have returned DISP_E_NOTACOLLECTION instead of 0x%08x\n", hr);
3301
3302 /* test propput with lcid */
3303
3304 /* the lcid passed to the function is the first lcid in the typelib header.
3305 Since we don't explicitly set an lcid in the idl, it'll default to US English. */
3306 VariantInit(&vararg[0]);
3307 V_VT(&vararg[0]) = VT_I4;
3308 V_I4(&vararg[0]) = 0xcafe;
3309 dispparams.cNamedArgs = 1;
3310 dispparams.rgdispidNamedArgs = &dispidNamed;
3311 dispparams.cArgs = 1;
3312 dispparams.rgvarg = vararg;
3313 VariantInit(&varresult);
3314 hr = IDispatch_Invoke(pDispatch, DISPID_TM_PROP_WITH_LCID, &IID_NULL, 0x40c, DISPATCH_PROPERTYPUT, &dispparams, &varresult, &excepinfo, NULL);
3315 ok_ole_success(hr, ITypeInfo_Invoke);
3316 VariantClear(&varresult);
3317
3318 /* test propget with lcid */
3319 dispparams.cNamedArgs = 0;
3320 dispparams.cArgs = 0;
3321 dispparams.rgvarg = NULL;
3322 dispparams.rgdispidNamedArgs = NULL;
3323 hr = IDispatch_Invoke(pDispatch, DISPID_TM_PROP_WITH_LCID, &IID_NULL, 0x40c, DISPATCH_PROPERTYGET, &dispparams, &varresult, &excepinfo, NULL);
3324 ok_ole_success(hr, ITypeInfo_Invoke);
3325 ok(V_VT(&varresult) == VT_I4, "got %x\n", V_VT(&varresult));
3326 ok(V_I4(&varresult) == 0x409, "got %x\n", V_I4(&varresult));
3327 VariantClear(&varresult);
3328
3329 /* test propget of INT value */
3330 dispparams.cNamedArgs = 0;
3331 dispparams.cArgs = 0;
3332 dispparams.rgvarg = NULL;
3333 dispparams.rgdispidNamedArgs = NULL;
3334 hr = IDispatch_Invoke(pDispatch, DISPID_TM_PROP_INT, &IID_NULL, 0x40c, DISPATCH_PROPERTYGET, &dispparams, &varresult, &excepinfo, NULL);
3335 ok_ole_success(hr, ITypeInfo_Invoke);
3336 ok(V_VT(&varresult) == VT_I4, "got %x\n", V_VT(&varresult));
3337 ok(V_I4(&varresult) == -13, "got %x\n", V_I4(&varresult));
3338 VariantClear(&varresult);
3339
3340 /* test propget of INT value */
3341 dispparams.cNamedArgs = 0;
3342 dispparams.cArgs = 0;
3343 dispparams.rgvarg = NULL;
3344 dispparams.rgdispidNamedArgs = NULL;
3345 hr = IDispatch_Invoke(pDispatch, DISPID_TM_PROP_UINT, &IID_NULL, 0x40c, DISPATCH_PROPERTYGET, &dispparams, &varresult, &excepinfo, NULL);
3346 ok_ole_success(hr, ITypeInfo_Invoke);
3347 ok(V_VT(&varresult) == VT_UI4, "got %x\n", V_VT(&varresult));
3348 ok(V_UI4(&varresult) == 42, "got %x\n", V_UI4(&varresult));
3349 VariantClear(&varresult);
3350
3351 /* test byref marshalling */
3352 uval = 666;
3353 VariantInit(&vararg[0]);
3354 V_VT(&vararg[0]) = VT_UI4|VT_BYREF;
3355 V_UI4REF(&vararg[0]) = &uval;
3356 dispparams.cNamedArgs = 0;
3357 dispparams.cArgs = 1;
3358 dispparams.rgvarg = vararg;
3359 dispparams.rgdispidNamedArgs = NULL;
3360 hr = IDispatch_Invoke(pDispatch, DISPID_TM_BYREF_UINT, &IID_NULL, LOCALE_NEUTRAL, DISPATCH_METHOD, &dispparams, &