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