wintrust: Use helper function for setting confidence in SoftpubCheckCert.
[wine] / dlls / oleaut32 / tests / tmarshal.c
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 #define COBJMACROS
21 #define CONST_VTABLE
22
23 #include <windows.h>
24 #include <ocidl.h>
25 #include <stdio.h>
26
27 #include "wine/test.h"
28
29 #include "tmarshal.h"
30 #include "tmarshal_dispids.h"
31
32 #define ok_ole_success(hr, func) ok(hr == S_OK, #func " failed with error 0x%08lx\n", (unsigned long int)hr)
33
34 /* ULL suffix is not portable */
35 #define ULL_CONST(dw1, dw2) ((((ULONGLONG)dw1) << 32) | (ULONGLONG)dw2)
36
37 const MYSTRUCT MYSTRUCT_BYVAL = {0x12345678, ULL_CONST(0xdeadbeef, 0x98765432)};
38 const MYSTRUCT MYSTRUCT_BYPTR = {0x91827364, ULL_CONST(0x88776655, 0x44332211)};
39 const MYSTRUCT MYSTRUCT_ARRAY[5] = {
40     {0x1a1b1c1d, ULL_CONST(0x1e1f1011, 0x12131415)},
41     {0x2a2b2c2d, ULL_CONST(0x2e2f2021, 0x22232425)},
42     {0x3a3b3c3d, ULL_CONST(0x3e3f3031, 0x32333435)},
43     {0x4a4b4c4d, ULL_CONST(0x4e4f4041, 0x42434445)},
44     {0x5a5b5c5d, ULL_CONST(0x5e5f5051, 0x52535455)},
45 };
46
47 /* Debugging functions from wine/libs/wine/debug.c */
48
49 /* allocate some tmp string space */
50 /* FIXME: this is not 100% thread-safe */
51 static char *get_tmp_space( int size )
52 {
53     static char *list[32];
54     static long pos;
55     char *ret;
56     int idx;
57
58     idx = ++pos % (sizeof(list)/sizeof(list[0]));
59     if ((ret = realloc( list[idx], size ))) list[idx] = ret;
60     return ret;
61 }
62
63 /* default implementation of wine_dbgstr_wn */
64 static const char *default_dbgstr_wn( const WCHAR *str, int n )
65 {
66     char *dst, *res;
67
68     if (!HIWORD(str))
69     {
70         if (!str) return "(null)";
71         res = get_tmp_space( 6 );
72         sprintf( res, "#%04x", LOWORD(str) );
73         return res;
74     }
75     if (n == -1) n = lstrlenW(str);
76     if (n < 0) n = 0;
77     else if (n > 200) n = 200;
78     dst = res = get_tmp_space( n * 5 + 7 );
79     *dst++ = 'L';
80     *dst++ = '"';
81     while (n-- > 0)
82     {
83         WCHAR c = *str++;
84         switch (c)
85         {
86         case '\n': *dst++ = '\\'; *dst++ = 'n'; break;
87         case '\r': *dst++ = '\\'; *dst++ = 'r'; break;
88         case '\t': *dst++ = '\\'; *dst++ = 't'; break;
89         case '"':  *dst++ = '\\'; *dst++ = '"'; break;
90         case '\\': *dst++ = '\\'; *dst++ = '\\'; break;
91         default:
92             if (c >= ' ' && c <= 126)
93                 *dst++ = (char)c;
94             else
95             {
96                 *dst++ = '\\';
97                 sprintf(dst,"%04x",c);
98                 dst+=4;
99             }
100         }
101     }
102     *dst++ = '"';
103     if (*str)
104     {
105         *dst++ = '.';
106         *dst++ = '.';
107         *dst++ = '.';
108     }
109     *dst = 0;
110     return res;
111 }
112
113 const char *wine_dbgstr_wn( const WCHAR *s, int n )
114 {
115     return default_dbgstr_wn(s, n);
116 }
117
118 const char *wine_dbgstr_w( const WCHAR *s )
119 {
120     return default_dbgstr_wn( s, -1 );
121 }
122
123
124 #define RELEASEMARSHALDATA WM_USER
125
126 struct host_object_data
127 {
128     IStream *stream;
129     IID iid;
130     IUnknown *object;
131     MSHLFLAGS marshal_flags;
132     HANDLE marshal_event;
133     IMessageFilter *filter;
134 };
135
136 static DWORD CALLBACK host_object_proc(LPVOID p)
137 {
138     struct host_object_data *data = (struct host_object_data *)p;
139     HRESULT hr;
140     MSG msg;
141
142     CoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
143
144     if (data->filter)
145     {
146         IMessageFilter * prev_filter = NULL;
147         hr = CoRegisterMessageFilter(data->filter, &prev_filter);
148         if (prev_filter) IMessageFilter_Release(prev_filter);
149         ok_ole_success(hr, CoRegisterMessageFilter);
150     }
151
152     hr = CoMarshalInterface(data->stream, &data->iid, data->object, MSHCTX_INPROC, NULL, data->marshal_flags);
153     ok_ole_success(hr, CoMarshalInterface);
154
155     /* force the message queue to be created before signaling parent thread */
156     PeekMessage(&msg, NULL, WM_USER, WM_USER, PM_NOREMOVE);
157
158     SetEvent(data->marshal_event);
159
160     while (GetMessage(&msg, NULL, 0, 0))
161     {
162         if (msg.hwnd == NULL && msg.message == RELEASEMARSHALDATA)
163         {
164             trace("releasing marshal data\n");
165             CoReleaseMarshalData(data->stream);
166             SetEvent((HANDLE)msg.lParam);
167         }
168         else
169             DispatchMessage(&msg);
170     }
171
172     HeapFree(GetProcessHeap(), 0, data);
173
174     CoUninitialize();
175
176     return hr;
177 }
178
179 static DWORD start_host_object2(IStream *stream, REFIID riid, IUnknown *object, MSHLFLAGS marshal_flags, IMessageFilter *filter, HANDLE *thread)
180 {
181     DWORD tid = 0;
182     HANDLE marshal_event = CreateEvent(NULL, FALSE, FALSE, NULL);
183     struct host_object_data *data = HeapAlloc(GetProcessHeap(), 0, sizeof(*data));
184
185     data->stream = stream;
186     data->iid = *riid;
187     data->object = object;
188     data->marshal_flags = marshal_flags;
189     data->marshal_event = marshal_event;
190     data->filter = filter;
191
192     *thread = CreateThread(NULL, 0, host_object_proc, data, 0, &tid);
193
194     /* wait for marshaling to complete before returning */
195     WaitForSingleObject(marshal_event, INFINITE);
196     CloseHandle(marshal_event);
197
198     return tid;
199 }
200
201 static DWORD start_host_object(IStream *stream, REFIID riid, IUnknown *object, MSHLFLAGS marshal_flags, HANDLE *thread)
202 {
203     return start_host_object2(stream, riid, object, marshal_flags, NULL, thread);
204 }
205
206 #if 0 /* not used */
207 /* asks thread to release the marshal data because it has to be done by the
208  * same thread that marshaled the interface in the first place. */
209 static void release_host_object(DWORD tid)
210 {
211     HANDLE event = CreateEvent(NULL, FALSE, FALSE, NULL);
212     PostThreadMessage(tid, RELEASEMARSHALDATA, 0, (LPARAM)event);
213     WaitForSingleObject(event, INFINITE);
214     CloseHandle(event);
215 }
216 #endif
217
218 static void end_host_object(DWORD tid, HANDLE thread)
219 {
220     BOOL ret = PostThreadMessage(tid, WM_QUIT, 0, 0);
221     ok(ret, "PostThreadMessage failed with error %d\n", GetLastError());
222     /* be careful of races - don't return until hosting thread has terminated */
223     WaitForSingleObject(thread, INFINITE);
224     CloseHandle(thread);
225 }
226
227 static ItestDual TestDual, TestDualDisp;
228
229 static HRESULT WINAPI TestDual_QueryInterface(ItestDual *iface, REFIID riid, void **ppvObject)
230 {
231     if (IsEqualIID(riid, &IID_IUnknown) || IsEqualIID(riid, &IID_IDispatch)) {
232         *ppvObject = &TestDualDisp;
233         return S_OK;
234     }else if(IsEqualGUID(riid, &IID_ItestDual)) {
235         *ppvObject = &TestDual;
236         return S_OK;
237     }
238
239     *ppvObject = NULL;
240     return E_NOINTERFACE;
241 }
242
243 static ULONG WINAPI TestDual_AddRef(ItestDual *iface)
244 {
245     return 2;
246 }
247
248 static ULONG WINAPI TestDual_Release(ItestDual *iface)
249 {
250     return 1;
251 }
252
253 static HRESULT WINAPI TestDual_GetTypeInfoCount(ItestDual *iface, UINT *pctinfo)
254 {
255     ok(0, "unexpected call\n");
256     return E_NOTIMPL;
257 }
258
259 static HRESULT WINAPI TestDual_GetTypeInfo(ItestDual *iface, UINT iTInfo, LCID lcid, ITypeInfo **ppTInfo)
260 {
261     ok(0, "unexpected call\n");
262     return E_NOTIMPL;
263 }
264
265 static HRESULT WINAPI TestDual_GetIDsOfNames(ItestDual *iface, REFIID riid, LPOLESTR *rgszNames,
266         UINT cNames, LCID lcid, DISPID *rgDispId)
267 {
268     ok(0, "unexpected call\n");
269     return E_NOTIMPL;
270 }
271
272 static HRESULT WINAPI TestDual_Invoke(ItestDual *iface, DISPID dispIdMember, REFIID riid, LCID lcid,
273         WORD wFlags, DISPPARAMS *pDispParams, VARIANT *pVarResult, EXCEPINFO *pExcepInfo,
274         UINT *puArgErr)
275 {
276     ok(0, "unexpected call\n");
277     return E_NOTIMPL;
278 }
279
280 static ItestDualVtbl TestDualVtbl = {
281     TestDual_QueryInterface,
282     TestDual_AddRef,
283     TestDual_Release,
284     TestDual_GetTypeInfoCount,
285     TestDual_GetTypeInfo,
286     TestDual_GetIDsOfNames,
287     TestDual_Invoke
288 };
289
290 static ItestDual TestDual = { &TestDualVtbl };
291 static ItestDual TestDualDisp = { &TestDualVtbl };
292
293 typedef struct Widget
294 {
295     const IWidgetVtbl *lpVtbl;
296     LONG refs;
297     IUnknown *pDispatchUnknown;
298 } Widget;
299
300 HRESULT WINAPI Widget_QueryInterface(
301     IWidget *iface,
302     /* [in] */ REFIID riid,
303     /* [iid_is][out] */ void __RPC_FAR *__RPC_FAR *ppvObject)
304 {
305     if (IsEqualIID(riid, &IID_IWidget) || IsEqualIID(riid, &IID_IUnknown) || IsEqualIID(riid, &IID_IDispatch))
306     {
307         IWidget_AddRef(iface);
308         *ppvObject = iface;
309         return S_OK;
310     }
311     else
312     {
313         *ppvObject = NULL;
314         return E_NOINTERFACE;
315     }
316 }
317
318 ULONG WINAPI Widget_AddRef(
319     IWidget *iface)
320 {
321     Widget *This = (Widget *)iface;
322
323     return InterlockedIncrement(&This->refs);
324 }
325
326 ULONG WINAPI Widget_Release(
327     IWidget *iface)
328 {
329     Widget *This = (Widget *)iface;
330     ULONG refs = InterlockedDecrement(&This->refs);
331     if (!refs)
332     {
333         IUnknown_Release(This->pDispatchUnknown);
334         memset(This, 0xcc, sizeof(*This));
335         HeapFree(GetProcessHeap(), 0, This);
336         trace("Widget destroyed!\n");
337     }
338
339     return refs;
340 }
341
342 HRESULT WINAPI Widget_GetTypeInfoCount(
343     IWidget *iface,
344     /* [out] */ UINT __RPC_FAR *pctinfo)
345 {
346     Widget *This = (Widget *)iface;
347     IDispatch *pDispatch;
348     HRESULT hr = IUnknown_QueryInterface(This->pDispatchUnknown, &IID_IDispatch, (void **)&pDispatch);
349     if (SUCCEEDED(hr))
350     {
351         hr = IDispatch_GetTypeInfoCount(pDispatch, pctinfo);
352         IDispatch_Release(pDispatch);
353     }
354     return hr;
355 }
356
357 HRESULT WINAPI Widget_GetTypeInfo(
358     IWidget __RPC_FAR * iface,
359     /* [in] */ UINT iTInfo,
360     /* [in] */ LCID lcid,
361     /* [out] */ ITypeInfo __RPC_FAR *__RPC_FAR *ppTInfo)
362 {
363     Widget *This = (Widget *)iface;
364     IDispatch *pDispatch;
365     HRESULT hr = IUnknown_QueryInterface(This->pDispatchUnknown, &IID_IDispatch, (void **)&pDispatch);
366     if (SUCCEEDED(hr))
367     {
368         hr = IDispatch_GetTypeInfo(pDispatch, iTInfo, lcid, ppTInfo);
369         IDispatch_Release(pDispatch);
370     }
371     return hr;
372 }
373
374 HRESULT WINAPI Widget_GetIDsOfNames(
375     IWidget __RPC_FAR * iface,
376     /* [in] */ REFIID riid,
377     /* [size_is][in] */ LPOLESTR __RPC_FAR *rgszNames,
378     /* [in] */ UINT cNames,
379     /* [in] */ LCID lcid,
380     /* [size_is][out] */ DISPID __RPC_FAR *rgDispId)
381 {
382     Widget *This = (Widget *)iface;
383     IDispatch *pDispatch;
384     HRESULT hr = IUnknown_QueryInterface(This->pDispatchUnknown, &IID_IDispatch, (void **)&pDispatch);
385     if (SUCCEEDED(hr))
386     {
387         hr = IDispatch_GetIDsOfNames(pDispatch, riid, rgszNames, cNames, lcid, rgDispId);
388         IDispatch_Release(pDispatch);
389     }
390     return hr;
391 }
392
393 HRESULT WINAPI Widget_Invoke(
394     IWidget __RPC_FAR * iface,
395     /* [in] */ DISPID dispIdMember,
396     /* [in] */ REFIID riid,
397     /* [in] */ LCID lcid,
398     /* [in] */ WORD wFlags,
399     /* [out][in] */ DISPPARAMS __RPC_FAR *pDispParams,
400     /* [out] */ VARIANT __RPC_FAR *pVarResult,
401     /* [out] */ EXCEPINFO __RPC_FAR *pExcepInfo,
402     /* [out] */ UINT __RPC_FAR *puArgErr)
403 {
404     Widget *This = (Widget *)iface;
405     IDispatch *pDispatch;
406     HRESULT hr = IUnknown_QueryInterface(This->pDispatchUnknown, &IID_IDispatch, (void **)&pDispatch);
407     if (SUCCEEDED(hr))
408     {
409         hr = IDispatch_Invoke(pDispatch, dispIdMember, riid, lcid, wFlags, pDispParams, pVarResult, pExcepInfo, puArgErr);
410         IDispatch_Release(pDispatch);
411     }
412     return hr;
413 }
414
415 HRESULT WINAPI Widget_put_Name(
416     IWidget __RPC_FAR * iface,
417     /* [in] */ BSTR name)
418 {
419     trace("put_Name(%s)\n", wine_dbgstr_w(name));
420     return S_OK;
421 }
422
423 HRESULT WINAPI Widget_get_Name(
424     IWidget __RPC_FAR * iface,
425     /* [out] */ BSTR __RPC_FAR *name)
426 {
427     static const WCHAR szCat[] = { 'C','a','t',0 };
428     trace("get_Name()\n");
429     *name = SysAllocString(szCat);
430     return S_OK;
431 }
432
433 HRESULT WINAPI Widget_DoSomething(
434     IWidget __RPC_FAR * iface,
435     /* [in] */ double number,
436     /* [out] */ BSTR *str1,
437     /* [defaultvalue][in] */ BSTR str2,
438     /* [optional][in] */ VARIANT __RPC_FAR *opt)
439 {
440     static const WCHAR szString[] = { 'S','t','r','i','n','g',0 };
441     trace("DoSomething()\n");
442
443     ok(number == 3.141, "number(%f) != 3.141\n", number);
444     ok(*str2 == '\0', "str2(%s) != \"\"\n", wine_dbgstr_w(str2));
445     ok(V_VT(opt) == VT_ERROR, "V_VT(opt) should be VT_ERROR instead of 0x%x\n", V_VT(opt));
446     ok(V_ERROR(opt) == DISP_E_PARAMNOTFOUND, "V_ERROR(opt) should be DISP_E_PARAMNOTFOUND instead of 0x%08x\n", V_ERROR(opt));
447     *str1 = SysAllocString(szString);
448
449     return S_FALSE;
450 }
451
452 HRESULT WINAPI Widget_get_State(
453     IWidget __RPC_FAR * iface,
454     /* [retval][out] */ STATE __RPC_FAR *state)
455 {
456     trace("get_State() = STATE_WIDGETIFIED\n");
457     *state = STATE_WIDGETIFIED;
458     return S_OK;
459 }
460
461 HRESULT WINAPI Widget_put_State(
462     IWidget __RPC_FAR * iface,
463     /* [in] */ STATE state)
464 {
465     trace("put_State(%d)\n", state);
466     return S_OK;
467 }
468
469 HRESULT WINAPI Widget_Map(
470     IWidget * iface,
471     BSTR bstrId,
472     BSTR *sValue)
473 {
474     trace("Map(%s, %p)\n", wine_dbgstr_w(bstrId), sValue);
475     *sValue = SysAllocString(bstrId);
476     return S_OK;
477 }
478
479 HRESULT WINAPI Widget_SetOleColor(
480     IWidget * iface,
481     OLE_COLOR val)
482 {
483     trace("SetOleColor(0x%x)\n", val);
484     return S_OK;
485 }
486
487 HRESULT WINAPI Widget_GetOleColor(
488     IWidget * iface,
489     OLE_COLOR *pVal)
490 {
491     trace("GetOleColor() = 0x8000000f\n");
492     *pVal = 0x8000000f;
493     return S_FALSE;
494 }
495
496 HRESULT WINAPI Widget_Clone(
497     IWidget *iface,
498     IWidget **ppVal)
499 {
500     trace("Clone()\n");
501     return Widget_QueryInterface(iface, &IID_IWidget, (void **)ppVal);
502 }
503
504 HRESULT WINAPI Widget_CloneDispatch(
505     IWidget *iface,
506     IDispatch **ppVal)
507 {
508     trace("CloneDispatch()\n");
509     return Widget_QueryInterface(iface, &IID_IWidget, (void **)ppVal);
510 }
511
512 HRESULT WINAPI Widget_CloneCoclass(
513     IWidget *iface,
514     ApplicationObject2 **ppVal)
515 {
516     trace("CloneCoclass()\n");
517     return S_OK;
518 }
519
520 HRESULT WINAPI Widget_Value(
521     IWidget __RPC_FAR * iface,
522     VARIANT *value,
523     VARIANT *retval)
524 {
525     trace("Value(%p, %p)\n", value, retval);
526     ok(V_VT(value) == VT_I2, "V_VT(value) was %d instead of VT_I2\n", V_VT(value));
527     ok(V_I2(value) == 1, "V_I2(value) was %d instead of 1\n", V_I2(value));
528     V_VT(retval) = VT_I2;
529     V_I2(retval) = 1234;
530     return S_OK;
531 }
532
533 HRESULT WINAPI Widget_Array(
534     IWidget * iface,
535     SAFEARRAY * values)
536 {
537     trace("Array(%p)\n", values);
538     return S_OK;
539 }
540
541 HRESULT WINAPI Widget_VariantArrayPtr(
542     IWidget * iface,
543     SAFEARRAY ** values)
544 {
545     trace("VariantArrayPtr(%p)\n", values);
546     return S_OK;
547 }
548
549 void WINAPI Widget_Variant(
550     IWidget __RPC_FAR * iface,
551     VARIANT var)
552 {
553     trace("Variant()\n");
554     ok(V_VT(&var) == VT_CY, "V_VT(&var) was %d\n", V_VT(&var));
555     ok(S(V_CY(&var)).Hi == 0xdababe, "V_CY(&var).Hi was 0x%x\n", S(V_CY(&var)).Hi);
556     ok(S(V_CY(&var)).Lo == 0xdeadbeef, "V_CY(&var).Lo was 0x%x\n", S(V_CY(&var)).Lo);
557 }
558
559 void WINAPI Widget_VarArg(
560     IWidget * iface,
561     int numexpect,
562     SAFEARRAY * values)
563 {
564     LONG lbound, ubound, i;
565     VARIANT * data;
566     HRESULT hr;
567
568     trace("VarArg(%p)\n", values);
569
570     hr = SafeArrayGetLBound(values, 1, &lbound);
571     ok(hr == S_OK, "SafeArrayGetLBound failed with %x\n", hr);
572     ok(lbound == 0, "SafeArrayGetLBound returned %d\n", lbound);
573
574     hr = SafeArrayGetUBound(values, 1, &ubound);
575     ok(hr == S_OK, "SafeArrayGetUBound failed with %x\n", hr);
576     ok(ubound == numexpect-1, "SafeArrayGetUBound returned %d, but expected %d\n", ubound, numexpect-1);
577
578     hr = SafeArrayAccessData(values, (LPVOID)&data);
579     ok(hr == S_OK, "SafeArrayAccessData failed with %x\n", hr);
580
581     for (i=0; i<=ubound-lbound; i++)
582     {
583         ok(V_VT(&data[i]) == VT_I4, "V_VT(&data[%d]) was %d\n", i, V_VT(&data[i]));
584         ok(V_I4(&data[i]) == i, "V_I4(&data[%d]) was %d\n", i, V_I4(&data[i]));
585     }
586
587     hr = SafeArrayUnaccessData(values);
588     ok(hr == S_OK, "SafeArrayUnaccessData failed with %x\n", hr);
589 }
590
591 void WINAPI Widget_StructArgs(
592     IWidget * iface,
593     MYSTRUCT byval,
594     MYSTRUCT *byptr,
595     MYSTRUCT arr[5])
596 {
597     ok(memcmp(&byval, &MYSTRUCT_BYVAL, sizeof(MYSTRUCT))==0, "Struct parameter passed by value corrupted\n");
598     ok(memcmp(byptr,  &MYSTRUCT_BYPTR, sizeof(MYSTRUCT))==0, "Struct parameter passed by pointer corrupted\n");
599     ok(memcmp(arr,    MYSTRUCT_ARRAY,  sizeof(MYSTRUCT_ARRAY))==0, "Array of structs corrupted\n");
600 }
601
602
603 HRESULT WINAPI Widget_Error(
604     IWidget __RPC_FAR * iface)
605 {
606     trace("Error()\n");
607     return E_NOTIMPL;
608 }
609
610 HRESULT WINAPI Widget_CloneInterface(
611     IWidget __RPC_FAR * iface,
612     ISomethingFromDispatch **ppVal)
613 {
614     trace("CloneInterface()\n");
615     *ppVal = 0;
616     return S_OK;
617 }
618
619 static const struct IWidgetVtbl Widget_VTable =
620 {
621     Widget_QueryInterface,
622     Widget_AddRef,
623     Widget_Release,
624     Widget_GetTypeInfoCount,
625     Widget_GetTypeInfo,
626     Widget_GetIDsOfNames,
627     Widget_Invoke,
628     Widget_put_Name,
629     Widget_get_Name,
630     Widget_DoSomething,
631     Widget_get_State,
632     Widget_put_State,
633     Widget_Map,
634     Widget_SetOleColor,
635     Widget_GetOleColor,
636     Widget_Clone,
637     Widget_CloneDispatch,
638     Widget_CloneCoclass,
639     Widget_Value,
640     Widget_Array,
641     Widget_VariantArrayPtr,
642     Widget_Variant,
643     Widget_VarArg,
644     Widget_StructArgs,
645     Widget_Error,
646     Widget_CloneInterface
647 };
648
649 static HRESULT WINAPI StaticWidget_QueryInterface(IStaticWidget *iface, REFIID riid, void **ppvObject)
650 {
651     if (IsEqualIID(riid, &IID_IStaticWidget) || IsEqualIID(riid, &IID_IUnknown) || IsEqualIID(riid, &IID_IDispatch))
652     {
653         IStaticWidget_AddRef(iface);
654         *ppvObject = iface;
655         return S_OK;
656     }
657
658     *ppvObject = NULL;
659     return E_NOINTERFACE;
660 }
661
662 static ULONG WINAPI StaticWidget_AddRef(IStaticWidget *iface)
663 {
664     return 2;
665 }
666
667 static ULONG WINAPI StaticWidget_Release(IStaticWidget *iface)
668 {
669     return 1;
670 }
671
672 static HRESULT WINAPI StaticWidget_GetTypeInfoCount(IStaticWidget *iface, UINT *pctinfo)
673 {
674     ok(0, "unexpected call\n");
675     return E_NOTIMPL;
676 }
677
678 static HRESULT WINAPI StaticWidget_GetTypeInfo(IStaticWidget *iface, UINT iTInfo, LCID lcid,
679         ITypeInfo **ppTInfo)
680 {
681     ok(0, "unexpected call\n");
682     return E_NOTIMPL;
683 }
684
685 static HRESULT WINAPI StaticWidget_GetIDsOfNames(IStaticWidget *iface, REFIID riid, LPOLESTR *rgszNames,
686         UINT cNames, LCID lcid, DISPID *rgDispId)
687 {
688     ok(0, "unexpected call\n");
689     return E_NOTIMPL;
690 }
691
692 static HRESULT WINAPI StaticWidget_Invoke(IStaticWidget *iface, DISPID dispIdMember, REFIID riid,
693         LCID lcid, WORD wFlags, DISPPARAMS *pDispParams, VARIANT *pVarResult, EXCEPINFO *pExcepInfo,
694          UINT *puArgErr)
695 {
696     ok(0, "unexpected call\n");
697     return E_NOTIMPL;
698 }
699
700 static HRESULT WINAPI StaticWidget_TestDual(IStaticWidget *iface, ItestDual *p)
701 {
702     trace("TestDual()\n");
703     todo_wine
704     ok(p == &TestDual, "wrong ItestDual\n");
705     return S_OK;
706 }
707
708 static const IStaticWidgetVtbl StaticWidgetVtbl = {
709     StaticWidget_QueryInterface,
710     StaticWidget_AddRef,
711     StaticWidget_Release,
712     StaticWidget_GetTypeInfoCount,
713     StaticWidget_GetTypeInfo,
714     StaticWidget_GetIDsOfNames,
715     StaticWidget_Invoke,
716     StaticWidget_TestDual
717 };
718
719 static IStaticWidget StaticWidget = { &StaticWidgetVtbl };
720
721 typedef struct KindaEnum
722 {
723     const IKindaEnumWidgetVtbl *lpVtbl;
724     LONG refs;
725 } KindaEnum;
726
727 static HRESULT register_current_module_typelib(void)
728 {
729     WCHAR path[MAX_PATH];
730     CHAR pathA[MAX_PATH];
731     HRESULT hr;
732     ITypeLib *typelib;
733
734     GetModuleFileNameA(NULL, pathA, MAX_PATH);
735     MultiByteToWideChar(CP_ACP, 0, pathA, -1, path, MAX_PATH);
736
737     hr = LoadTypeLib(path, &typelib);
738     if (SUCCEEDED(hr))
739     {
740         hr = RegisterTypeLib(typelib, path, NULL);
741         ITypeLib_Release(typelib);
742     }
743     return hr;
744 }
745
746 static ITypeInfo *get_type_info(REFIID riid)
747 {
748     ITypeInfo *pTypeInfo;
749     ITypeLib *pTypeLib;
750     HRESULT hr;
751
752     hr = LoadRegTypeLib(&LIBID_TestTypelib, 1, 0, LOCALE_NEUTRAL, &pTypeLib);
753     ok_ole_success(hr, LoadRegTypeLib);
754     if (FAILED(hr))
755         return NULL;
756
757     hr = ITypeLib_GetTypeInfoOfGuid(pTypeLib, riid, &pTypeInfo);
758     ITypeLib_Release(pTypeLib);
759     ok_ole_success(hr, ITypeLib_GetTypeInfoOfGuid);
760     if (FAILED(hr))
761         return NULL;
762
763     return pTypeInfo;
764 }
765
766 static IWidget *Widget_Create(void)
767 {
768     Widget *This;
769     ITypeInfo *pTypeInfo;
770     HRESULT hr = E_FAIL;
771
772     pTypeInfo = get_type_info(&IID_IWidget);
773     if(!pTypeInfo)
774         return NULL;
775
776     This = HeapAlloc(GetProcessHeap(), 0, sizeof(*This));
777     This->lpVtbl = &Widget_VTable;
778     This->refs = 1;
779     This->pDispatchUnknown = NULL;
780
781     hr = CreateStdDispatch((IUnknown *)&This->lpVtbl, This, pTypeInfo, &This->pDispatchUnknown);
782     ok_ole_success(hr, CreateStdDispatch);
783     ITypeInfo_Release(pTypeInfo);
784
785     if (SUCCEEDED(hr))
786         return (IWidget *)&This->lpVtbl;
787     else
788     {
789         HeapFree(GetProcessHeap(), 0, This);
790         return NULL;
791     }
792 }
793
794 HRESULT WINAPI KindaEnum_QueryInterface(
795     IKindaEnumWidget *iface,
796     /* [in] */ REFIID riid,
797     /* [iid_is][out] */ void __RPC_FAR *__RPC_FAR *ppvObject)
798 {
799     if (IsEqualIID(riid, &IID_IKindaEnumWidget) || IsEqualIID(riid, &IID_IUnknown))
800     {
801         IKindaEnumWidget_AddRef(iface);
802         *ppvObject = iface;
803         return S_OK;
804     }
805     else
806     {
807         *ppvObject = NULL;
808         return E_NOINTERFACE;
809     }
810 }
811
812 ULONG WINAPI KindaEnum_AddRef(
813     IKindaEnumWidget *iface)
814 {
815     KindaEnum *This = (KindaEnum *)iface;
816
817     return InterlockedIncrement(&This->refs);
818 }
819
820 ULONG WINAPI KindaEnum_Release(
821     IKindaEnumWidget *iface)
822 {
823     KindaEnum *This = (KindaEnum *)iface;
824     ULONG refs = InterlockedDecrement(&This->refs);
825     if (!refs)
826     {
827         memset(This, 0xcc, sizeof(*This));
828         HeapFree(GetProcessHeap(), 0, This);
829         trace("KindaEnumWidget destroyed!\n");
830     }
831
832     return refs;
833 }
834
835 HRESULT WINAPI KindaEnum_Next(
836     IKindaEnumWidget *iface,
837     /* [out] */ IWidget __RPC_FAR *__RPC_FAR *widget)
838 {
839     *widget = Widget_Create();
840     if (*widget)
841         return S_OK;
842     else
843         return E_OUTOFMEMORY;
844 }
845
846 HRESULT WINAPI KindaEnum_Count(
847     IKindaEnumWidget *iface,
848     /* [out] */ unsigned long __RPC_FAR *count)
849 {
850     return E_NOTIMPL;
851 }
852
853 HRESULT WINAPI KindaEnum_Reset(
854     IKindaEnumWidget *iface)
855 {
856     return E_NOTIMPL;
857 }
858
859 HRESULT WINAPI KindaEnum_Clone(
860     IKindaEnumWidget *iface,
861     /* [out] */ IKindaEnumWidget __RPC_FAR *__RPC_FAR *ppenum)
862 {
863     return E_NOTIMPL;
864 }
865
866 static const IKindaEnumWidgetVtbl KindaEnumWidget_VTable =
867 {
868     KindaEnum_QueryInterface,
869     KindaEnum_AddRef,
870     KindaEnum_Release,
871     KindaEnum_Next,
872     KindaEnum_Count,
873     KindaEnum_Reset,
874     KindaEnum_Clone
875 };
876
877 static IKindaEnumWidget *KindaEnumWidget_Create(void)
878 {
879     KindaEnum *This;
880
881     This = HeapAlloc(GetProcessHeap(), 0, sizeof(*This));
882     if (!This) return NULL;
883     This->lpVtbl = &KindaEnumWidget_VTable;
884     This->refs = 1;
885     return (IKindaEnumWidget *)This;
886 }
887
888 static HRESULT WINAPI NonOleAutomation_QueryInterface(INonOleAutomation *iface, REFIID riid, void **ppv)
889 {
890     if (IsEqualIID(riid, &IID_IUnknown) || IsEqualIID(riid, &IID_INonOleAutomation))
891     {
892         *(INonOleAutomation **)ppv = iface;
893         return S_OK;
894     }
895     *ppv = NULL;
896     return E_NOINTERFACE;
897 }
898
899 static ULONG WINAPI NonOleAutomation_AddRef(INonOleAutomation *iface)
900 {
901     return 2;
902 }
903
904 static ULONG WINAPI NonOleAutomation_Release(INonOleAutomation *iface)
905 {
906     return 1;
907 }
908
909 static BSTR WINAPI NonOleAutomation_BstrRet(INonOleAutomation *iface)
910 {
911     static const WCHAR wszTestString[] = {'T','h','i','s',' ','i','s',' ','a',' ','t','e','s','t',' ','s','t','r','i','n','g',0};
912     return SysAllocString(wszTestString);
913 }
914
915 static INonOleAutomationVtbl NonOleAutomation_VTable =
916 {
917     NonOleAutomation_QueryInterface,
918     NonOleAutomation_AddRef,
919     NonOleAutomation_Release,
920     NonOleAutomation_BstrRet,
921 };
922
923 static INonOleAutomation NonOleAutomation = { &NonOleAutomation_VTable };
924
925 static ITypeInfo *NonOleAutomation_GetTypeInfo(void)
926 {
927     ITypeLib *pTypeLib;
928     HRESULT hr = LoadRegTypeLib(&LIBID_TestTypelib, 1, 0, LOCALE_NEUTRAL, &pTypeLib);
929     ok_ole_success(hr, LoadRegTypeLib);
930     if (SUCCEEDED(hr))
931     {
932         ITypeInfo *pTypeInfo;
933         hr = ITypeLib_GetTypeInfoOfGuid(pTypeLib, &IID_INonOleAutomation, &pTypeInfo);
934         ok_ole_success(hr, ITypeLib_GetTypeInfoOfGuid);
935         return pTypeInfo;
936     }
937     return NULL;
938 }
939
940 static void test_typelibmarshal(void)
941 {
942     static const WCHAR szCat[] = { 'C','a','t',0 };
943     static const WCHAR szTestTest[] = { 'T','e','s','t','T','e','s','t',0 };
944     static WCHAR szSuperman[] = { 'S','u','p','e','r','m','a','n',0 };
945     HRESULT hr;
946     IKindaEnumWidget *pKEW = KindaEnumWidget_Create();
947     IWidget *pWidget;
948     IStream *pStream;
949     IDispatch *pDispatch;
950     static const LARGE_INTEGER ullZero;
951     EXCEPINFO excepinfo;
952     VARIANT varresult;
953     DISPID dispidNamed = DISPID_PROPERTYPUT;
954     DISPPARAMS dispparams;
955     VARIANTARG vararg[4];
956     STATE the_state;
957     HANDLE thread;
958     DWORD tid;
959     BSTR bstr;
960     ITypeInfo *pTypeInfo;
961     MYSTRUCT mystruct;
962     MYSTRUCT mystructArray[5];
963
964     ok(pKEW != NULL, "Widget creation failed\n");
965
966     hr = CreateStreamOnHGlobal(NULL, TRUE, &pStream);
967     ok_ole_success(hr, CreateStreamOnHGlobal);
968     tid = start_host_object(pStream, &IID_IKindaEnumWidget, (IUnknown *)pKEW, MSHLFLAGS_NORMAL, &thread);
969     IKindaEnumWidget_Release(pKEW);
970
971     IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
972     hr = CoUnmarshalInterface(pStream, &IID_IKindaEnumWidget, (void **)&pKEW);
973     ok_ole_success(hr, CoUnmarshalInterface);
974     IStream_Release(pStream);
975
976     hr = IKindaEnumWidget_Next(pKEW, &pWidget);
977     ok_ole_success(hr, IKindaEnumWidget_Next);
978
979     IKindaEnumWidget_Release(pKEW);
980
981     hr = IWidget_QueryInterface(pWidget, &IID_IDispatch, (void **)&pDispatch);
982
983     /* call put_Name */
984     VariantInit(&vararg[0]);
985     dispparams.cNamedArgs = 1;
986     dispparams.rgdispidNamedArgs = &dispidNamed;
987     dispparams.cArgs = 1;
988     dispparams.rgvarg = vararg;
989     VariantInit(&varresult);
990     hr = IDispatch_Invoke(pDispatch, DISPID_TM_NAME, &IID_NULL, LOCALE_NEUTRAL, DISPATCH_PROPERTYPUT, &dispparams, &varresult, &excepinfo, NULL);
991     ok_ole_success(hr, IDispatch_Invoke);
992     ok(excepinfo.wCode == 0x0 && excepinfo.scode == S_OK,
993         "EXCEPINFO differs from expected: wCode = 0x%x, scode = 0x%08x\n",
994         excepinfo.wCode, excepinfo.scode);
995     VariantClear(&varresult);
996
997     /* call put_Name (direct) */
998     bstr = SysAllocString(szSuperman);
999     hr = IWidget_put_Name(pWidget, bstr);
1000     ok_ole_success(hr, IWidget_put_Name);
1001     SysFreeString(bstr);
1002
1003     /* call get_Name */
1004     dispparams.cNamedArgs = 0;
1005     dispparams.rgdispidNamedArgs = NULL;
1006     dispparams.cArgs = 0;
1007     dispparams.rgvarg = NULL;
1008     VariantInit(&varresult);
1009     hr = IDispatch_Invoke(pDispatch, DISPID_TM_NAME, &IID_NULL, LOCALE_NEUTRAL, DISPATCH_PROPERTYGET, &dispparams, &varresult, &excepinfo, NULL);
1010     ok_ole_success(hr, IDispatch_Invoke);
1011     ok(excepinfo.wCode == 0x0 && excepinfo.scode == S_OK,
1012         "EXCEPINFO differs from expected: wCode = 0x%x, scode = 0x%08x\n",
1013         excepinfo.wCode, excepinfo.scode);
1014     trace("Name = %s\n", wine_dbgstr_w(V_BSTR(&varresult)));
1015     VariantClear(&varresult);
1016
1017     /* call get_Name (direct) */
1018     bstr = NULL;
1019     hr = IWidget_get_Name(pWidget, &bstr);
1020     ok_ole_success(hr, IWidget_get_Name);
1021     ok(!lstrcmpW(bstr, szCat), "IWidget_get_Name should have returned string \"Cat\" instead of %s\n", wine_dbgstr_w(bstr));
1022     SysFreeString(bstr);
1023
1024     /* call DoSomething */
1025     VariantInit(&vararg[0]);
1026     VariantInit(&vararg[1]);
1027     V_VT(&vararg[1]) = VT_R8;
1028     V_R8(&vararg[1]) = 3.141;
1029     dispparams.cNamedArgs = 0;
1030     dispparams.cArgs = 2;
1031     dispparams.rgdispidNamedArgs = NULL;
1032     dispparams.rgvarg = vararg;
1033     VariantInit(&varresult);
1034     hr = IDispatch_Invoke(pDispatch, DISPID_TM_DOSOMETHING, &IID_NULL, LOCALE_NEUTRAL, DISPATCH_METHOD, &dispparams, &varresult, &excepinfo, NULL);
1035     ok_ole_success(hr, IDispatch_Invoke);
1036     ok(V_VT(&varresult) == VT_EMPTY, "varresult should be VT_EMPTY\n");
1037     VariantClear(&varresult);
1038
1039     /* call get_State */
1040     dispparams.cNamedArgs = 0;
1041     dispparams.cArgs = 0;
1042     dispparams.rgdispidNamedArgs = NULL;
1043     dispparams.rgvarg = NULL;
1044     hr = IDispatch_Invoke(pDispatch, DISPID_TM_STATE, &IID_NULL, LOCALE_NEUTRAL, DISPATCH_PROPERTYGET, &dispparams, &varresult, &excepinfo, NULL);
1045     ok_ole_success(hr, IDispatch_Invoke);
1046     ok((V_VT(&varresult) == VT_I4) && (V_I4(&varresult) == STATE_WIDGETIFIED), "Return val mismatch\n");
1047
1048     /* call get_State (direct) */
1049     hr = IWidget_get_State(pWidget, &the_state);
1050     ok_ole_success(hr, IWidget_get_state);
1051     ok(the_state == STATE_WIDGETIFIED, "should have returned WIDGET_WIDGETIFIED instead of %d\n", the_state);
1052
1053     /* call put_State */
1054     the_state = STATE_WIDGETIFIED;
1055     VariantInit(&vararg[0]);
1056     V_VT(&vararg[0]) = VT_BYREF|VT_I4;
1057     V_I4REF(&vararg[0]) = (int *)&the_state;
1058     dispparams.cNamedArgs = 1;
1059     dispparams.cArgs = 1;
1060     dispparams.rgdispidNamedArgs = &dispidNamed;
1061     dispparams.rgvarg = vararg;
1062     hr = IDispatch_Invoke(pDispatch, DISPID_TM_STATE, &IID_NULL, LOCALE_NEUTRAL, DISPATCH_PROPERTYPUT, &dispparams, &varresult, &excepinfo, NULL);
1063     ok_ole_success(hr, IDispatch_Invoke);
1064
1065     /* call Map */
1066     bstr = SysAllocString(szTestTest);
1067     VariantInit(&vararg[0]);
1068     V_VT(&vararg[0]) = VT_BYREF|VT_BSTR;
1069     V_BSTRREF(&vararg[0]) = &bstr;
1070     dispparams.cNamedArgs = 0;
1071     dispparams.cArgs = 1;
1072     dispparams.rgdispidNamedArgs = NULL;
1073     dispparams.rgvarg = vararg;
1074     VariantInit(&varresult);
1075     hr = IDispatch_Invoke(pDispatch, DISPID_TM_MAP, &IID_NULL, LOCALE_NEUTRAL, DISPATCH_METHOD, &dispparams, &varresult, &excepinfo, NULL);
1076     ok_ole_success(hr, IDispatch_Invoke);
1077     ok(V_VT(&varresult) == VT_BSTR, "Return value should be of type BSTR instead of %d\n", V_VT(&varresult));
1078     ok(!lstrcmpW(V_BSTR(&varresult), szTestTest), "Return value should have been \"TestTest\" instead of %s\n", wine_dbgstr_w(V_BSTR(&varresult)));
1079     VariantClear(&varresult);
1080
1081     /* call SetOleColor with large negative VT_I4 param */
1082     VariantInit(&vararg[0]);
1083     V_VT(&vararg[0]) = VT_I4;
1084     V_I4(&vararg[0]) = 0x80000005;
1085     dispparams.cNamedArgs = 0;
1086     dispparams.cArgs = 1;
1087     dispparams.rgdispidNamedArgs = NULL;
1088     dispparams.rgvarg = vararg;
1089     hr = IDispatch_Invoke(pDispatch, DISPID_TM_SETOLECOLOR, &IID_NULL, LOCALE_NEUTRAL, DISPATCH_METHOD, &dispparams, NULL, &excepinfo, NULL);
1090     ok_ole_success(hr, IDispatch_Invoke);
1091
1092     /* call GetOleColor */
1093     dispparams.cNamedArgs = 0;
1094     dispparams.cArgs = 0;
1095     dispparams.rgdispidNamedArgs = NULL;
1096     dispparams.rgvarg = NULL;
1097     VariantInit(&varresult);
1098     hr = IDispatch_Invoke(pDispatch, DISPID_TM_GETOLECOLOR, &IID_NULL, LOCALE_NEUTRAL, DISPATCH_METHOD, &dispparams, &varresult, &excepinfo, NULL);
1099     ok_ole_success(hr, IDispatch_Invoke);
1100     VariantClear(&varresult);
1101
1102     /* call StructArgs (direct) */
1103     mystruct = MYSTRUCT_BYPTR;
1104     memcpy(mystructArray, MYSTRUCT_ARRAY, sizeof(mystructArray));
1105     IWidget_StructArgs(pWidget, MYSTRUCT_BYVAL, &mystruct, mystructArray);
1106
1107     /* call Clone */
1108     dispparams.cNamedArgs = 0;
1109     dispparams.cArgs = 0;
1110     dispparams.rgdispidNamedArgs = NULL;
1111     dispparams.rgvarg = NULL;
1112     VariantInit(&varresult);
1113     hr = IDispatch_Invoke(pDispatch, DISPID_TM_CLONE, &IID_NULL, LOCALE_NEUTRAL, DISPATCH_PROPERTYGET, &dispparams, &varresult, &excepinfo, NULL);
1114     ok_ole_success(hr, IDispatch_Invoke);
1115     ok(V_VT(&varresult) == VT_DISPATCH, "vt %x\n", V_VT(&varresult));
1116     VariantClear(&varresult);
1117
1118     /* call CloneInterface */
1119     dispparams.cNamedArgs = 0;
1120     dispparams.cArgs = 0;
1121     dispparams.rgdispidNamedArgs = NULL;
1122     dispparams.rgvarg = NULL;
1123     VariantInit(&varresult);
1124     hr = IDispatch_Invoke(pDispatch, DISPID_TM_CLONEINTERFACE, &IID_NULL, LOCALE_NEUTRAL, DISPATCH_PROPERTYGET, &dispparams, &varresult, &excepinfo, NULL);
1125     ok_ole_success(hr, IDispatch_Invoke);
1126     ok(V_VT(&varresult) == VT_DISPATCH, "vt %x\n", V_VT(&varresult));
1127     VariantClear(&varresult);
1128
1129     /* call CloneDispatch with automatic value getting */
1130     V_VT(&vararg[0]) = VT_I2;
1131     V_I2(&vararg[0]) = 1;
1132     dispparams.cNamedArgs = 0;
1133     dispparams.rgdispidNamedArgs = NULL;
1134     dispparams.cArgs = 1;
1135     dispparams.rgvarg = vararg;
1136     VariantInit(&varresult);
1137     hr = IDispatch_Invoke(pDispatch, DISPID_TM_CLONEDISPATCH, &IID_NULL, LOCALE_NEUTRAL, DISPATCH_PROPERTYGET, &dispparams, &varresult, &excepinfo, NULL);
1138     ok_ole_success(hr, IDispatch_Invoke);
1139
1140     ok(excepinfo.wCode == 0x0 && excepinfo.scode == S_OK,
1141         "EXCEPINFO differs from expected: wCode = 0x%x, scode = 0x%08x\n",
1142         excepinfo.wCode, excepinfo.scode);
1143
1144     ok(V_VT(&varresult) == VT_I2, "V_VT(&varresult) was %d instead of VT_I2\n", V_VT(&varresult));
1145     ok(V_I2(&varresult) == 1234, "V_I2(&varresult) was %d instead of 1234\n", V_I2(&varresult));
1146     VariantClear(&varresult);
1147
1148     /* call CloneCoclass */
1149     dispparams.cNamedArgs = 0;
1150     dispparams.cArgs = 0;
1151     dispparams.rgdispidNamedArgs = NULL;
1152     dispparams.rgvarg = NULL;
1153     VariantInit(&varresult);
1154     hr = IDispatch_Invoke(pDispatch, DISPID_TM_CLONECOCLASS, &IID_NULL, LOCALE_NEUTRAL, DISPATCH_PROPERTYGET, &dispparams, &varresult, &excepinfo, NULL);
1155     ok_ole_success(hr, IDispatch_Invoke);
1156
1157     ok(excepinfo.wCode == 0x0 && excepinfo.scode == S_OK,
1158        "EXCEPINFO differs from expected: wCode = 0x%x, scode = 0x%08x\n",
1159        excepinfo.wCode, excepinfo.scode);
1160
1161     ok(V_VT(&varresult) == VT_DISPATCH, "V_VT(&varresult) was %d instead of VT_DISPATCH\n", V_VT(&varresult));
1162     ok(!V_DISPATCH(&varresult), "V_DISPATCH(&varresult) should be NULL instead of %p\n", V_DISPATCH(&varresult));
1163     VariantClear(&varresult);
1164
1165     /* call Value with a VT_VARIANT|VT_BYREF type */
1166     V_VT(&vararg[0]) = VT_VARIANT|VT_BYREF;
1167     V_VARIANTREF(&vararg[0]) = &vararg[1];
1168     V_VT(&vararg[1]) = VT_I2;
1169     V_I2(&vararg[1]) = 1;
1170     dispparams.cNamedArgs = 0;
1171     dispparams.rgdispidNamedArgs = NULL;
1172     dispparams.cArgs = 1;
1173     dispparams.rgvarg = vararg;
1174     VariantInit(&varresult);
1175     hr = IDispatch_Invoke(pDispatch, DISPID_VALUE, &IID_NULL, LOCALE_NEUTRAL, DISPATCH_PROPERTYGET, &dispparams, &varresult, &excepinfo, NULL);
1176     ok_ole_success(hr, IDispatch_Invoke);
1177
1178     ok(excepinfo.wCode == 0x0 && excepinfo.scode == S_OK,
1179         "EXCEPINFO differs from expected: wCode = 0x%x, scode = 0x%08x\n",
1180         excepinfo.wCode, excepinfo.scode);
1181
1182     ok(V_VT(&varresult) == VT_I2, "V_VT(&varresult) was %d instead of VT_I2\n", V_VT(&varresult));
1183     ok(V_I2(&varresult) == 1234, "V_I2(&varresult) was %d instead of 1234\n", V_I2(&varresult));
1184     VariantClear(&varresult);
1185
1186     /* call Variant - exercises variant copying in ITypeInfo::Invoke and
1187      * handling of void return types */
1188     /* use a big type to ensure that the variant was properly copied into the
1189      * destination function's args */
1190     V_VT(&vararg[0]) = VT_CY;
1191     S(V_CY(&vararg[0])).Hi = 0xdababe;
1192     S(V_CY(&vararg[0])).Lo = 0xdeadbeef;
1193     dispparams.cNamedArgs = 0;
1194     dispparams.cArgs = 1;
1195     dispparams.rgdispidNamedArgs = NULL;
1196     dispparams.rgvarg = vararg;
1197     VariantInit(&varresult);
1198     hr = IDispatch_Invoke(pDispatch, DISPID_TM_VARIANT, &IID_NULL, LOCALE_NEUTRAL, DISPATCH_METHOD, &dispparams, NULL, NULL, NULL);
1199     ok_ole_success(hr, IDispatch_Invoke);
1200     VariantClear(&varresult);
1201
1202     /* call VarArg */
1203     VariantInit(&vararg[3]);
1204     V_VT(&vararg[3]) = VT_I4;
1205     V_I4(&vararg[3]) = 3;
1206     VariantInit(&vararg[2]);
1207     V_VT(&vararg[2]) = VT_I4;
1208     V_I4(&vararg[2]) = 0;
1209     VariantInit(&vararg[1]);
1210     V_VT(&vararg[1]) = VT_I4;
1211     V_I4(&vararg[1]) = 1;
1212     VariantInit(&vararg[0]);
1213     V_VT(&vararg[0]) = VT_I4;
1214     V_I4(&vararg[0]) = 2;
1215     dispparams.cNamedArgs = 0;
1216     dispparams.cArgs = 4;
1217     dispparams.rgdispidNamedArgs = NULL;
1218     dispparams.rgvarg = vararg;
1219     hr = IDispatch_Invoke(pDispatch, DISPID_TM_VARARG, &IID_NULL, LOCALE_NEUTRAL, DISPATCH_METHOD, &dispparams, NULL, NULL, NULL);
1220     ok_ole_success(hr, ITypeInfo_Invoke);
1221
1222     /* call VarArg, even one (non-optional, non-safearray) named argument is not allowed */
1223     dispidNamed = 0;
1224     dispparams.cNamedArgs = 1;
1225     dispparams.rgdispidNamedArgs = &dispidNamed;
1226     hr = IDispatch_Invoke(pDispatch, DISPID_TM_VARARG, &IID_NULL, LOCALE_NEUTRAL, DISPATCH_METHOD, &dispparams, NULL, NULL, NULL);
1227     ok(hr == DISP_E_NONAMEDARGS, "IDispatch_Invoke should have returned DISP_E_NONAMEDARGS instead of 0x%08x\n", hr);
1228     dispidNamed = DISPID_PROPERTYPUT;
1229
1230     /* call Error */
1231     dispparams.cNamedArgs = 0;
1232     dispparams.cArgs = 0;
1233     dispparams.rgdispidNamedArgs = NULL;
1234     dispparams.rgvarg = NULL;
1235     VariantInit(&varresult);
1236     hr = IDispatch_Invoke(pDispatch, DISPID_TM_ERROR, &IID_NULL, LOCALE_NEUTRAL, DISPATCH_METHOD, &dispparams, NULL, &excepinfo, NULL);
1237     ok(hr == DISP_E_EXCEPTION, "IDispatch_Invoke should have returned DISP_E_EXCEPTION instead of 0x%08x\n", hr);
1238     ok(excepinfo.wCode == 0x0 && excepinfo.scode == E_NOTIMPL,
1239         "EXCEPINFO differs from expected: wCode = 0x%x, scode = 0x%08x\n",
1240         excepinfo.wCode, excepinfo.scode);
1241     VariantClear(&varresult);
1242
1243     /* call BstrRet */
1244     pTypeInfo = NonOleAutomation_GetTypeInfo();
1245     dispparams.cNamedArgs = 0;
1246     dispparams.cArgs = 0;
1247     dispparams.rgdispidNamedArgs = NULL;
1248     dispparams.rgvarg = NULL;
1249     VariantInit(&varresult);
1250     hr = ITypeInfo_Invoke(pTypeInfo, &NonOleAutomation, DISPID_NOA_BSTRRET, DISPATCH_METHOD, &dispparams, &varresult, &excepinfo, NULL);
1251     ok_ole_success(hr, ITypeInfo_Invoke);
1252     ok(V_VT(&varresult) == VT_BSTR, "V_VT(&varresult) should be VT_BSTR instead of %d\n", V_VT(&varresult));
1253     ok(V_BSTR(&varresult) != NULL, "V_BSTR(&varresult) should not be NULL\n");
1254
1255     VariantClear(&varresult);
1256     ITypeInfo_Release(pTypeInfo);
1257
1258     /* tests call put_Name without named arg */
1259     VariantInit(&vararg[0]);
1260     dispparams.cNamedArgs = 0;
1261     dispparams.rgdispidNamedArgs = NULL;
1262     dispparams.cArgs = 1;
1263     dispparams.rgvarg = vararg;
1264     VariantInit(&varresult);
1265     hr = IDispatch_Invoke(pDispatch, DISPID_TM_NAME, &IID_NULL, LOCALE_NEUTRAL, DISPATCH_PROPERTYPUT, &dispparams, &varresult, &excepinfo, NULL);
1266     ok(hr == DISP_E_PARAMNOTFOUND, "IDispatch_Invoke should have returned DISP_E_PARAMNOTFOUND instead of 0x%08x\n", hr);
1267     VariantClear(&varresult);
1268
1269     /* tests param type that cannot be coerced */
1270     VariantInit(&vararg[0]);
1271     V_VT(&vararg[0]) = VT_UNKNOWN;
1272     V_UNKNOWN(&vararg[0]) = NULL;
1273     dispparams.cNamedArgs = 1;
1274     dispparams.rgdispidNamedArgs = &dispidNamed;
1275     dispparams.cArgs = 1;
1276     dispparams.rgvarg = vararg;
1277     VariantInit(&varresult);
1278 #if 0 /* NULL unknown not currently marshaled correctly */
1279     hr = IDispatch_Invoke(pDispatch, DISPID_TM_NAME, &IID_NULL, LOCALE_NEUTRAL, DISPATCH_PROPERTYPUT, &dispparams, &varresult, &excepinfo, NULL);
1280     ok(hr == DISP_E_TYPEMISMATCH, "IDispatch_Invoke should have returned DISP_E_TYPEMISMATCH instead of 0x%08x\n", hr);
1281 #endif
1282     VariantClear(&varresult);
1283
1284     /* tests bad param type */
1285     VariantInit(&vararg[0]);
1286     V_VT(&vararg[0]) = VT_CLSID;
1287     V_BYREF(&vararg[0]) = NULL;
1288     dispparams.cNamedArgs = 1;
1289     dispparams.rgdispidNamedArgs = &dispidNamed;
1290     dispparams.cArgs = 1;
1291     dispparams.rgvarg = vararg;
1292     VariantInit(&varresult);
1293     hr = IDispatch_Invoke(pDispatch, DISPID_TM_NAME, &IID_NULL, LOCALE_NEUTRAL, DISPATCH_PROPERTYPUT, &dispparams, &varresult, &excepinfo, NULL);
1294     ok(hr == DISP_E_BADVARTYPE, "IDispatch_Invoke should have returned DISP_E_BADVARTYPE instead of 0x%08x\n", hr);
1295     VariantClear(&varresult);
1296
1297     /* tests too small param count */
1298     dispparams.cNamedArgs = 0;
1299     dispparams.rgdispidNamedArgs = NULL;
1300     dispparams.cArgs = 0;
1301     dispparams.rgvarg = NULL;
1302     VariantInit(&varresult);
1303     hr = IDispatch_Invoke(pDispatch, DISPID_TM_DOSOMETHING, &IID_NULL, LOCALE_NEUTRAL, DISPATCH_METHOD, &dispparams, &varresult, &excepinfo, NULL);
1304     ok(hr == DISP_E_BADPARAMCOUNT, "IDispatch_Invoke should have returned DISP_E_BADPARAMCOUNT instead of 0x%08x\n", hr);
1305     VariantClear(&varresult);
1306
1307     /* tests propget function with large param count */
1308     VariantInit(&vararg[0]);
1309     V_VT(&vararg[0]) = VT_BSTR;
1310     V_BSTR(&vararg[0]) = NULL;
1311     V_VT(&vararg[1]) = VT_I4;
1312     V_I4(&vararg[1]) = 1;
1313     dispparams.cNamedArgs = 0;
1314     dispparams.cArgs = 2;
1315     dispparams.rgdispidNamedArgs = NULL;
1316     dispparams.rgvarg = vararg;
1317     hr = IDispatch_Invoke(pDispatch, DISPID_TM_STATE, &IID_NULL, LOCALE_NEUTRAL, DISPATCH_PROPERTYGET, &dispparams, &varresult, &excepinfo, NULL);
1318     ok(hr == DISP_E_NOTACOLLECTION, "IDispatch_Invoke should have returned DISP_E_NOTACOLLECTION instead of 0x%08x\n", hr);
1319
1320     IDispatch_Release(pDispatch);
1321     IWidget_Release(pWidget);
1322
1323     trace("calling end_host_object\n");
1324     end_host_object(tid, thread);
1325 }
1326
1327 static void test_DispCallFunc(void)
1328 {
1329     static const WCHAR szEmpty[] = { 0 };
1330     VARTYPE rgvt[] = { VT_R8, VT_BSTR, VT_BSTR, VT_VARIANT|VT_BYREF };
1331     VARIANTARG vararg[4];
1332     VARIANTARG varref;
1333     VARIANTARG *rgpvarg[4] = { &vararg[0], &vararg[1], &vararg[2], &vararg[3] };
1334     VARIANTARG varresult;
1335     HRESULT hr;
1336     IWidget *pWidget = Widget_Create();
1337     V_VT(&vararg[0]) = VT_R8;
1338     V_R8(&vararg[0]) = 3.141;
1339     V_VT(&vararg[1]) = VT_BSTR;
1340     V_BSTR(&vararg[1]) = SysAllocString(szEmpty);
1341     V_VT(&vararg[2]) = VT_BSTR;
1342     V_BSTR(&vararg[2]) = SysAllocString(szEmpty);
1343     V_VT(&vararg[3]) = VT_VARIANT|VT_BYREF;
1344     V_VARIANTREF(&vararg[3]) = &varref;
1345     V_VT(&varref) = VT_ERROR;
1346     V_ERROR(&varref) = DISP_E_PARAMNOTFOUND;
1347     VariantInit(&varresult);
1348     hr = DispCallFunc(pWidget, 36, CC_STDCALL, VT_UI4, 4, rgvt, rgpvarg, &varresult);
1349     ok_ole_success(hr, DispCallFunc);
1350     VariantClear(&varresult);
1351     VariantClear(&vararg[1]);
1352     VariantClear(&vararg[2]);
1353     IWidget_Release(pWidget);
1354 }
1355
1356 static void test_StaticWidget(void)
1357 {
1358     ITypeInfo *type_info;
1359     DISPPARAMS dispparams;
1360     VARIANTARG vararg[4];
1361     EXCEPINFO excepinfo;
1362     VARIANT varresult;
1363     HRESULT hr;
1364
1365     type_info = get_type_info(&IID_IStaticWidget);
1366
1367     /* call TestDual */
1368     dispparams.cNamedArgs = 0;
1369     dispparams.cArgs = 1;
1370     dispparams.rgdispidNamedArgs = NULL;
1371     dispparams.rgvarg = vararg;
1372     V_VT(vararg) = VT_DISPATCH;
1373     V_DISPATCH(vararg) = (IDispatch*)&TestDualDisp;
1374     VariantInit(&varresult);
1375     hr = ITypeInfo_Invoke(type_info, &StaticWidget, DISPID_TM_TESTDUAL, DISPATCH_METHOD,
1376             &dispparams, &varresult, &excepinfo, NULL);
1377     ok_ole_success(hr, IDispatch_Invoke);
1378     ok(V_VT(&varresult) == VT_EMPTY, "vt %x\n", V_VT(&varresult));
1379     VariantClear(&varresult);
1380
1381     ITypeInfo_Release(type_info);
1382 }
1383
1384 START_TEST(tmarshal)
1385 {
1386     HRESULT hr;
1387
1388     CoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
1389
1390     hr = register_current_module_typelib();
1391     ok_ole_success(hr, register_current_module_typelib);
1392
1393     test_typelibmarshal();
1394     test_DispCallFunc();
1395     test_StaticWidget();
1396
1397     hr = UnRegisterTypeLib(&LIBID_TestTypelib, 1, 0, LOCALE_NEUTRAL, 1);
1398     ok_ole_success(hr, UnRegisterTypeLib);
1399
1400     CoUninitialize();
1401 }