d3d10core: Make some device_parent_*() functions static.
[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 static 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 static ULONG WINAPI Widget_AddRef(
319     IWidget *iface)
320 {
321     Widget *This = (Widget *)iface;
322
323     return InterlockedIncrement(&This->refs);
324 }
325
326 static 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 static 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 static 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 static 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 static 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 static 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 static 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 static 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 static 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 static 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 static 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 static 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 static 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 static 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 static 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 static HRESULT WINAPI Widget_CloneCoclass(
513     IWidget *iface,
514     ApplicationObject2 **ppVal)
515 {
516     trace("CloneCoclass()\n");
517     return S_OK;
518 }
519
520 static 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 static HRESULT WINAPI Widget_Array(
534     IWidget * iface,
535     SAFEARRAY * values)
536 {
537     trace("Array(%p)\n", values);
538     return S_OK;
539 }
540
541 static HRESULT WINAPI Widget_VariantArrayPtr(
542     IWidget * iface,
543     SAFEARRAY ** values)
544 {
545     trace("VariantArrayPtr(%p)\n", values);
546     return S_OK;
547 }
548
549 static HRESULT 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     return S_OK;
558 }
559
560 static HRESULT WINAPI Widget_VarArg(
561     IWidget * iface,
562     int numexpect,
563     SAFEARRAY * values)
564 {
565     LONG lbound, ubound, i;
566     VARIANT * data;
567     HRESULT hr;
568
569     trace("VarArg(%p)\n", values);
570
571     hr = SafeArrayGetLBound(values, 1, &lbound);
572     ok(hr == S_OK, "SafeArrayGetLBound failed with %x\n", hr);
573     ok(lbound == 0, "SafeArrayGetLBound returned %d\n", lbound);
574
575     hr = SafeArrayGetUBound(values, 1, &ubound);
576     ok(hr == S_OK, "SafeArrayGetUBound failed with %x\n", hr);
577     ok(ubound == numexpect-1, "SafeArrayGetUBound returned %d, but expected %d\n", ubound, numexpect-1);
578
579     hr = SafeArrayAccessData(values, (LPVOID)&data);
580     ok(hr == S_OK, "SafeArrayAccessData failed with %x\n", hr);
581
582     for (i=0; i<=ubound-lbound; i++)
583     {
584         ok(V_VT(&data[i]) == VT_I4, "V_VT(&data[%d]) was %d\n", i, V_VT(&data[i]));
585         ok(V_I4(&data[i]) == i, "V_I4(&data[%d]) was %d\n", i, V_I4(&data[i]));
586     }
587
588     hr = SafeArrayUnaccessData(values);
589     ok(hr == S_OK, "SafeArrayUnaccessData failed with %x\n", hr);
590
591     return S_OK;
592 }
593
594 static HRESULT WINAPI Widget_StructArgs(
595     IWidget * iface,
596     MYSTRUCT byval,
597     MYSTRUCT *byptr,
598     MYSTRUCT arr[5])
599 {
600     ok(memcmp(&byval, &MYSTRUCT_BYVAL, sizeof(MYSTRUCT))==0, "Struct parameter passed by value corrupted\n");
601     ok(memcmp(byptr,  &MYSTRUCT_BYPTR, sizeof(MYSTRUCT))==0, "Struct parameter passed by pointer corrupted\n");
602     ok(memcmp(arr,    MYSTRUCT_ARRAY,  sizeof(MYSTRUCT_ARRAY))==0, "Array of structs corrupted\n");
603     return S_OK;
604 }
605
606
607 static HRESULT WINAPI Widget_Error(
608     IWidget __RPC_FAR * iface)
609 {
610     trace("Error()\n");
611     return E_NOTIMPL;
612 }
613
614 static HRESULT WINAPI Widget_CloneInterface(
615     IWidget __RPC_FAR * iface,
616     ISomethingFromDispatch **ppVal)
617 {
618     trace("CloneInterface()\n");
619     *ppVal = 0;
620     return S_OK;
621 }
622
623 static const struct IWidgetVtbl Widget_VTable =
624 {
625     Widget_QueryInterface,
626     Widget_AddRef,
627     Widget_Release,
628     Widget_GetTypeInfoCount,
629     Widget_GetTypeInfo,
630     Widget_GetIDsOfNames,
631     Widget_Invoke,
632     Widget_put_Name,
633     Widget_get_Name,
634     Widget_DoSomething,
635     Widget_get_State,
636     Widget_put_State,
637     Widget_Map,
638     Widget_SetOleColor,
639     Widget_GetOleColor,
640     Widget_Clone,
641     Widget_CloneDispatch,
642     Widget_CloneCoclass,
643     Widget_Value,
644     Widget_Array,
645     Widget_VariantArrayPtr,
646     Widget_Variant,
647     Widget_VarArg,
648     Widget_StructArgs,
649     Widget_Error,
650     Widget_CloneInterface
651 };
652
653 static HRESULT WINAPI StaticWidget_QueryInterface(IStaticWidget *iface, REFIID riid, void **ppvObject)
654 {
655     if (IsEqualIID(riid, &IID_IStaticWidget) || IsEqualIID(riid, &IID_IUnknown) || IsEqualIID(riid, &IID_IDispatch))
656     {
657         IStaticWidget_AddRef(iface);
658         *ppvObject = iface;
659         return S_OK;
660     }
661
662     *ppvObject = NULL;
663     return E_NOINTERFACE;
664 }
665
666 static ULONG WINAPI StaticWidget_AddRef(IStaticWidget *iface)
667 {
668     return 2;
669 }
670
671 static ULONG WINAPI StaticWidget_Release(IStaticWidget *iface)
672 {
673     return 1;
674 }
675
676 static HRESULT WINAPI StaticWidget_GetTypeInfoCount(IStaticWidget *iface, UINT *pctinfo)
677 {
678     ok(0, "unexpected call\n");
679     return E_NOTIMPL;
680 }
681
682 static HRESULT WINAPI StaticWidget_GetTypeInfo(IStaticWidget *iface, UINT iTInfo, LCID lcid,
683         ITypeInfo **ppTInfo)
684 {
685     ok(0, "unexpected call\n");
686     return E_NOTIMPL;
687 }
688
689 static HRESULT WINAPI StaticWidget_GetIDsOfNames(IStaticWidget *iface, REFIID riid, LPOLESTR *rgszNames,
690         UINT cNames, LCID lcid, DISPID *rgDispId)
691 {
692     ok(0, "unexpected call\n");
693     return E_NOTIMPL;
694 }
695
696 static HRESULT WINAPI StaticWidget_Invoke(IStaticWidget *iface, DISPID dispIdMember, REFIID riid,
697         LCID lcid, WORD wFlags, DISPPARAMS *pDispParams, VARIANT *pVarResult, EXCEPINFO *pExcepInfo,
698          UINT *puArgErr)
699 {
700     ok(0, "unexpected call\n");
701     return E_NOTIMPL;
702 }
703
704 static HRESULT WINAPI StaticWidget_TestDual(IStaticWidget *iface, ItestDual *p)
705 {
706     trace("TestDual()\n");
707     todo_wine
708     ok(p == &TestDual, "wrong ItestDual\n");
709     return S_OK;
710 }
711
712 static const IStaticWidgetVtbl StaticWidgetVtbl = {
713     StaticWidget_QueryInterface,
714     StaticWidget_AddRef,
715     StaticWidget_Release,
716     StaticWidget_GetTypeInfoCount,
717     StaticWidget_GetTypeInfo,
718     StaticWidget_GetIDsOfNames,
719     StaticWidget_Invoke,
720     StaticWidget_TestDual
721 };
722
723 static IStaticWidget StaticWidget = { &StaticWidgetVtbl };
724
725 typedef struct KindaEnum
726 {
727     const IKindaEnumWidgetVtbl *lpVtbl;
728     LONG refs;
729 } KindaEnum;
730
731 static HRESULT register_current_module_typelib(void)
732 {
733     WCHAR path[MAX_PATH];
734     CHAR pathA[MAX_PATH];
735     HRESULT hr;
736     ITypeLib *typelib;
737
738     GetModuleFileNameA(NULL, pathA, MAX_PATH);
739     MultiByteToWideChar(CP_ACP, 0, pathA, -1, path, MAX_PATH);
740
741     hr = LoadTypeLib(path, &typelib);
742     if (SUCCEEDED(hr))
743     {
744         hr = RegisterTypeLib(typelib, path, NULL);
745         ITypeLib_Release(typelib);
746     }
747     return hr;
748 }
749
750 static ITypeInfo *get_type_info(REFIID riid)
751 {
752     ITypeInfo *pTypeInfo;
753     ITypeLib *pTypeLib;
754     HRESULT hr;
755
756     hr = LoadRegTypeLib(&LIBID_TestTypelib, 1, 0, LOCALE_NEUTRAL, &pTypeLib);
757     ok_ole_success(hr, LoadRegTypeLib);
758     if (FAILED(hr))
759         return NULL;
760
761     hr = ITypeLib_GetTypeInfoOfGuid(pTypeLib, riid, &pTypeInfo);
762     ITypeLib_Release(pTypeLib);
763     ok_ole_success(hr, ITypeLib_GetTypeInfoOfGuid);
764     if (FAILED(hr))
765         return NULL;
766
767     return pTypeInfo;
768 }
769
770 static IWidget *Widget_Create(void)
771 {
772     Widget *This;
773     ITypeInfo *pTypeInfo;
774     HRESULT hr = E_FAIL;
775
776     pTypeInfo = get_type_info(&IID_IWidget);
777     if(!pTypeInfo)
778         return NULL;
779
780     This = HeapAlloc(GetProcessHeap(), 0, sizeof(*This));
781     This->lpVtbl = &Widget_VTable;
782     This->refs = 1;
783     This->pDispatchUnknown = NULL;
784
785     hr = CreateStdDispatch((IUnknown *)&This->lpVtbl, This, pTypeInfo, &This->pDispatchUnknown);
786     ok_ole_success(hr, CreateStdDispatch);
787     ITypeInfo_Release(pTypeInfo);
788
789     if (SUCCEEDED(hr))
790         return (IWidget *)&This->lpVtbl;
791     else
792     {
793         HeapFree(GetProcessHeap(), 0, This);
794         return NULL;
795     }
796 }
797
798 static HRESULT WINAPI KindaEnum_QueryInterface(
799     IKindaEnumWidget *iface,
800     /* [in] */ REFIID riid,
801     /* [iid_is][out] */ void __RPC_FAR *__RPC_FAR *ppvObject)
802 {
803     if (IsEqualIID(riid, &IID_IKindaEnumWidget) || IsEqualIID(riid, &IID_IUnknown))
804     {
805         IKindaEnumWidget_AddRef(iface);
806         *ppvObject = iface;
807         return S_OK;
808     }
809     else
810     {
811         *ppvObject = NULL;
812         return E_NOINTERFACE;
813     }
814 }
815
816 static ULONG WINAPI KindaEnum_AddRef(
817     IKindaEnumWidget *iface)
818 {
819     KindaEnum *This = (KindaEnum *)iface;
820
821     return InterlockedIncrement(&This->refs);
822 }
823
824 static ULONG WINAPI KindaEnum_Release(
825     IKindaEnumWidget *iface)
826 {
827     KindaEnum *This = (KindaEnum *)iface;
828     ULONG refs = InterlockedDecrement(&This->refs);
829     if (!refs)
830     {
831         memset(This, 0xcc, sizeof(*This));
832         HeapFree(GetProcessHeap(), 0, This);
833         trace("KindaEnumWidget destroyed!\n");
834     }
835
836     return refs;
837 }
838
839 static HRESULT WINAPI KindaEnum_Next(
840     IKindaEnumWidget *iface,
841     /* [out] */ IWidget __RPC_FAR *__RPC_FAR *widget)
842 {
843     *widget = Widget_Create();
844     if (*widget)
845         return S_OK;
846     else
847         return E_OUTOFMEMORY;
848 }
849
850 static HRESULT WINAPI KindaEnum_Count(
851     IKindaEnumWidget *iface,
852     /* [out] */ unsigned long __RPC_FAR *count)
853 {
854     return E_NOTIMPL;
855 }
856
857 static HRESULT WINAPI KindaEnum_Reset(
858     IKindaEnumWidget *iface)
859 {
860     return E_NOTIMPL;
861 }
862
863 static HRESULT WINAPI KindaEnum_Clone(
864     IKindaEnumWidget *iface,
865     /* [out] */ IKindaEnumWidget __RPC_FAR *__RPC_FAR *ppenum)
866 {
867     return E_NOTIMPL;
868 }
869
870 static const IKindaEnumWidgetVtbl KindaEnumWidget_VTable =
871 {
872     KindaEnum_QueryInterface,
873     KindaEnum_AddRef,
874     KindaEnum_Release,
875     KindaEnum_Next,
876     KindaEnum_Count,
877     KindaEnum_Reset,
878     KindaEnum_Clone
879 };
880
881 static IKindaEnumWidget *KindaEnumWidget_Create(void)
882 {
883     KindaEnum *This;
884
885     This = HeapAlloc(GetProcessHeap(), 0, sizeof(*This));
886     if (!This) return NULL;
887     This->lpVtbl = &KindaEnumWidget_VTable;
888     This->refs = 1;
889     return (IKindaEnumWidget *)This;
890 }
891
892 static HRESULT WINAPI NonOleAutomation_QueryInterface(INonOleAutomation *iface, REFIID riid, void **ppv)
893 {
894     if (IsEqualIID(riid, &IID_IUnknown) || IsEqualIID(riid, &IID_INonOleAutomation))
895     {
896         *(INonOleAutomation **)ppv = iface;
897         return S_OK;
898     }
899     *ppv = NULL;
900     return E_NOINTERFACE;
901 }
902
903 static ULONG WINAPI NonOleAutomation_AddRef(INonOleAutomation *iface)
904 {
905     return 2;
906 }
907
908 static ULONG WINAPI NonOleAutomation_Release(INonOleAutomation *iface)
909 {
910     return 1;
911 }
912
913 static BSTR WINAPI NonOleAutomation_BstrRet(INonOleAutomation *iface)
914 {
915     static const WCHAR wszTestString[] = {'T','h','i','s',' ','i','s',' ','a',' ','t','e','s','t',' ','s','t','r','i','n','g',0};
916     return SysAllocString(wszTestString);
917 }
918
919 static INonOleAutomationVtbl NonOleAutomation_VTable =
920 {
921     NonOleAutomation_QueryInterface,
922     NonOleAutomation_AddRef,
923     NonOleAutomation_Release,
924     NonOleAutomation_BstrRet,
925 };
926
927 static INonOleAutomation NonOleAutomation = { &NonOleAutomation_VTable };
928
929 static ITypeInfo *NonOleAutomation_GetTypeInfo(void)
930 {
931     ITypeLib *pTypeLib;
932     HRESULT hr = LoadRegTypeLib(&LIBID_TestTypelib, 1, 0, LOCALE_NEUTRAL, &pTypeLib);
933     ok_ole_success(hr, LoadRegTypeLib);
934     if (SUCCEEDED(hr))
935     {
936         ITypeInfo *pTypeInfo;
937         hr = ITypeLib_GetTypeInfoOfGuid(pTypeLib, &IID_INonOleAutomation, &pTypeInfo);
938         ok_ole_success(hr, ITypeLib_GetTypeInfoOfGuid);
939         return pTypeInfo;
940     }
941     return NULL;
942 }
943
944 static void test_typelibmarshal(void)
945 {
946     static const WCHAR szCat[] = { 'C','a','t',0 };
947     static const WCHAR szTestTest[] = { 'T','e','s','t','T','e','s','t',0 };
948     static WCHAR szSuperman[] = { 'S','u','p','e','r','m','a','n',0 };
949     HRESULT hr;
950     IKindaEnumWidget *pKEW = KindaEnumWidget_Create();
951     IWidget *pWidget;
952     IStream *pStream;
953     IDispatch *pDispatch;
954     static const LARGE_INTEGER ullZero;
955     EXCEPINFO excepinfo;
956     VARIANT varresult;
957     DISPID dispidNamed = DISPID_PROPERTYPUT;
958     DISPPARAMS dispparams;
959     VARIANTARG vararg[4];
960     STATE the_state;
961     HANDLE thread;
962     DWORD tid;
963     BSTR bstr;
964     ITypeInfo *pTypeInfo;
965     MYSTRUCT mystruct;
966     MYSTRUCT mystructArray[5];
967
968     ok(pKEW != NULL, "Widget creation failed\n");
969
970     hr = CreateStreamOnHGlobal(NULL, TRUE, &pStream);
971     ok_ole_success(hr, CreateStreamOnHGlobal);
972     tid = start_host_object(pStream, &IID_IKindaEnumWidget, (IUnknown *)pKEW, MSHLFLAGS_NORMAL, &thread);
973     IKindaEnumWidget_Release(pKEW);
974
975     IStream_Seek(pStream, ullZero, STREAM_SEEK_SET, NULL);
976     hr = CoUnmarshalInterface(pStream, &IID_IKindaEnumWidget, (void **)&pKEW);
977     ok_ole_success(hr, CoUnmarshalInterface);
978     IStream_Release(pStream);
979
980     hr = IKindaEnumWidget_Next(pKEW, &pWidget);
981     ok_ole_success(hr, IKindaEnumWidget_Next);
982
983     IKindaEnumWidget_Release(pKEW);
984
985     hr = IWidget_QueryInterface(pWidget, &IID_IDispatch, (void **)&pDispatch);
986
987     /* call put_Name */
988     VariantInit(&vararg[0]);
989     dispparams.cNamedArgs = 1;
990     dispparams.rgdispidNamedArgs = &dispidNamed;
991     dispparams.cArgs = 1;
992     dispparams.rgvarg = vararg;
993     VariantInit(&varresult);
994     hr = IDispatch_Invoke(pDispatch, DISPID_TM_NAME, &IID_NULL, LOCALE_NEUTRAL, DISPATCH_PROPERTYPUT, &dispparams, &varresult, &excepinfo, NULL);
995     ok_ole_success(hr, IDispatch_Invoke);
996     ok(excepinfo.wCode == 0x0 && excepinfo.scode == S_OK,
997         "EXCEPINFO differs from expected: wCode = 0x%x, scode = 0x%08x\n",
998         excepinfo.wCode, excepinfo.scode);
999     VariantClear(&varresult);
1000
1001     /* call put_Name (direct) */
1002     bstr = SysAllocString(szSuperman);
1003     hr = IWidget_put_Name(pWidget, bstr);
1004     ok_ole_success(hr, IWidget_put_Name);
1005     SysFreeString(bstr);
1006
1007     /* call get_Name */
1008     dispparams.cNamedArgs = 0;
1009     dispparams.rgdispidNamedArgs = NULL;
1010     dispparams.cArgs = 0;
1011     dispparams.rgvarg = NULL;
1012     VariantInit(&varresult);
1013     hr = IDispatch_Invoke(pDispatch, DISPID_TM_NAME, &IID_NULL, LOCALE_NEUTRAL, DISPATCH_PROPERTYGET, &dispparams, &varresult, &excepinfo, NULL);
1014     ok_ole_success(hr, IDispatch_Invoke);
1015     ok(excepinfo.wCode == 0x0 && excepinfo.scode == S_OK,
1016         "EXCEPINFO differs from expected: wCode = 0x%x, scode = 0x%08x\n",
1017         excepinfo.wCode, excepinfo.scode);
1018     trace("Name = %s\n", wine_dbgstr_w(V_BSTR(&varresult)));
1019     VariantClear(&varresult);
1020
1021     /* call get_Name (direct) */
1022     bstr = NULL;
1023     hr = IWidget_get_Name(pWidget, &bstr);
1024     ok_ole_success(hr, IWidget_get_Name);
1025     ok(!lstrcmpW(bstr, szCat), "IWidget_get_Name should have returned string \"Cat\" instead of %s\n", wine_dbgstr_w(bstr));
1026     SysFreeString(bstr);
1027
1028     /* call DoSomething */
1029     VariantInit(&vararg[0]);
1030     VariantInit(&vararg[1]);
1031     V_VT(&vararg[1]) = VT_R8;
1032     V_R8(&vararg[1]) = 3.141;
1033     dispparams.cNamedArgs = 0;
1034     dispparams.cArgs = 2;
1035     dispparams.rgdispidNamedArgs = NULL;
1036     dispparams.rgvarg = vararg;
1037     VariantInit(&varresult);
1038     hr = IDispatch_Invoke(pDispatch, DISPID_TM_DOSOMETHING, &IID_NULL, LOCALE_NEUTRAL, DISPATCH_METHOD, &dispparams, &varresult, &excepinfo, NULL);
1039     ok_ole_success(hr, IDispatch_Invoke);
1040     ok(V_VT(&varresult) == VT_EMPTY, "varresult should be VT_EMPTY\n");
1041     VariantClear(&varresult);
1042
1043     /* call get_State */
1044     dispparams.cNamedArgs = 0;
1045     dispparams.cArgs = 0;
1046     dispparams.rgdispidNamedArgs = NULL;
1047     dispparams.rgvarg = NULL;
1048     hr = IDispatch_Invoke(pDispatch, DISPID_TM_STATE, &IID_NULL, LOCALE_NEUTRAL, DISPATCH_PROPERTYGET, &dispparams, &varresult, &excepinfo, NULL);
1049     ok_ole_success(hr, IDispatch_Invoke);
1050     ok((V_VT(&varresult) == VT_I4) && (V_I4(&varresult) == STATE_WIDGETIFIED), "Return val mismatch\n");
1051
1052     /* call get_State (direct) */
1053     hr = IWidget_get_State(pWidget, &the_state);
1054     ok_ole_success(hr, IWidget_get_state);
1055     ok(the_state == STATE_WIDGETIFIED, "should have returned WIDGET_WIDGETIFIED instead of %d\n", the_state);
1056
1057     /* call put_State */
1058     the_state = STATE_WIDGETIFIED;
1059     VariantInit(&vararg[0]);
1060     V_VT(&vararg[0]) = VT_BYREF|VT_I4;
1061     V_I4REF(&vararg[0]) = (int *)&the_state;
1062     dispparams.cNamedArgs = 1;
1063     dispparams.cArgs = 1;
1064     dispparams.rgdispidNamedArgs = &dispidNamed;
1065     dispparams.rgvarg = vararg;
1066     hr = IDispatch_Invoke(pDispatch, DISPID_TM_STATE, &IID_NULL, LOCALE_NEUTRAL, DISPATCH_PROPERTYPUT, &dispparams, &varresult, &excepinfo, NULL);
1067     ok_ole_success(hr, IDispatch_Invoke);
1068
1069     /* call Map */
1070     bstr = SysAllocString(szTestTest);
1071     VariantInit(&vararg[0]);
1072     V_VT(&vararg[0]) = VT_BYREF|VT_BSTR;
1073     V_BSTRREF(&vararg[0]) = &bstr;
1074     dispparams.cNamedArgs = 0;
1075     dispparams.cArgs = 1;
1076     dispparams.rgdispidNamedArgs = NULL;
1077     dispparams.rgvarg = vararg;
1078     VariantInit(&varresult);
1079     hr = IDispatch_Invoke(pDispatch, DISPID_TM_MAP, &IID_NULL, LOCALE_NEUTRAL, DISPATCH_METHOD, &dispparams, &varresult, &excepinfo, NULL);
1080     ok_ole_success(hr, IDispatch_Invoke);
1081     ok(V_VT(&varresult) == VT_BSTR, "Return value should be of type BSTR instead of %d\n", V_VT(&varresult));
1082     ok(!lstrcmpW(V_BSTR(&varresult), szTestTest), "Return value should have been \"TestTest\" instead of %s\n", wine_dbgstr_w(V_BSTR(&varresult)));
1083     VariantClear(&varresult);
1084
1085     /* call SetOleColor with large negative VT_I4 param */
1086     VariantInit(&vararg[0]);
1087     V_VT(&vararg[0]) = VT_I4;
1088     V_I4(&vararg[0]) = 0x80000005;
1089     dispparams.cNamedArgs = 0;
1090     dispparams.cArgs = 1;
1091     dispparams.rgdispidNamedArgs = NULL;
1092     dispparams.rgvarg = vararg;
1093     hr = IDispatch_Invoke(pDispatch, DISPID_TM_SETOLECOLOR, &IID_NULL, LOCALE_NEUTRAL, DISPATCH_METHOD, &dispparams, NULL, &excepinfo, NULL);
1094     ok_ole_success(hr, IDispatch_Invoke);
1095
1096     /* call GetOleColor */
1097     dispparams.cNamedArgs = 0;
1098     dispparams.cArgs = 0;
1099     dispparams.rgdispidNamedArgs = NULL;
1100     dispparams.rgvarg = NULL;
1101     VariantInit(&varresult);
1102     hr = IDispatch_Invoke(pDispatch, DISPID_TM_GETOLECOLOR, &IID_NULL, LOCALE_NEUTRAL, DISPATCH_METHOD, &dispparams, &varresult, &excepinfo, NULL);
1103     ok_ole_success(hr, IDispatch_Invoke);
1104     VariantClear(&varresult);
1105
1106     /* call StructArgs (direct) */
1107     mystruct = MYSTRUCT_BYPTR;
1108     memcpy(mystructArray, MYSTRUCT_ARRAY, sizeof(mystructArray));
1109     hr = IWidget_StructArgs(pWidget, MYSTRUCT_BYVAL, &mystruct, mystructArray);
1110     todo_wine {
1111     ok_ole_success(hr, IWidget_StructArgs);
1112     }
1113
1114     /* call Clone */
1115     dispparams.cNamedArgs = 0;
1116     dispparams.cArgs = 0;
1117     dispparams.rgdispidNamedArgs = NULL;
1118     dispparams.rgvarg = NULL;
1119     VariantInit(&varresult);
1120     hr = IDispatch_Invoke(pDispatch, DISPID_TM_CLONE, &IID_NULL, LOCALE_NEUTRAL, DISPATCH_PROPERTYGET, &dispparams, &varresult, &excepinfo, NULL);
1121     ok_ole_success(hr, IDispatch_Invoke);
1122     ok(V_VT(&varresult) == VT_DISPATCH, "vt %x\n", V_VT(&varresult));
1123     VariantClear(&varresult);
1124
1125     /* call CloneInterface */
1126     dispparams.cNamedArgs = 0;
1127     dispparams.cArgs = 0;
1128     dispparams.rgdispidNamedArgs = NULL;
1129     dispparams.rgvarg = NULL;
1130     VariantInit(&varresult);
1131     hr = IDispatch_Invoke(pDispatch, DISPID_TM_CLONEINTERFACE, &IID_NULL, LOCALE_NEUTRAL, DISPATCH_PROPERTYGET, &dispparams, &varresult, &excepinfo, NULL);
1132     ok_ole_success(hr, IDispatch_Invoke);
1133     ok(V_VT(&varresult) == VT_DISPATCH, "vt %x\n", V_VT(&varresult));
1134     VariantClear(&varresult);
1135
1136     /* call CloneDispatch with automatic value getting */
1137     V_VT(&vararg[0]) = VT_I2;
1138     V_I2(&vararg[0]) = 1;
1139     dispparams.cNamedArgs = 0;
1140     dispparams.rgdispidNamedArgs = NULL;
1141     dispparams.cArgs = 1;
1142     dispparams.rgvarg = vararg;
1143     VariantInit(&varresult);
1144     hr = IDispatch_Invoke(pDispatch, DISPID_TM_CLONEDISPATCH, &IID_NULL, LOCALE_NEUTRAL, DISPATCH_PROPERTYGET, &dispparams, &varresult, &excepinfo, NULL);
1145     ok_ole_success(hr, IDispatch_Invoke);
1146
1147     ok(excepinfo.wCode == 0x0 && excepinfo.scode == S_OK,
1148         "EXCEPINFO differs from expected: wCode = 0x%x, scode = 0x%08x\n",
1149         excepinfo.wCode, excepinfo.scode);
1150
1151     ok(V_VT(&varresult) == VT_I2, "V_VT(&varresult) was %d instead of VT_I2\n", V_VT(&varresult));
1152     ok(V_I2(&varresult) == 1234, "V_I2(&varresult) was %d instead of 1234\n", V_I2(&varresult));
1153     VariantClear(&varresult);
1154
1155     /* call CloneCoclass */
1156     dispparams.cNamedArgs = 0;
1157     dispparams.cArgs = 0;
1158     dispparams.rgdispidNamedArgs = NULL;
1159     dispparams.rgvarg = NULL;
1160     VariantInit(&varresult);
1161     hr = IDispatch_Invoke(pDispatch, DISPID_TM_CLONECOCLASS, &IID_NULL, LOCALE_NEUTRAL, DISPATCH_PROPERTYGET, &dispparams, &varresult, &excepinfo, NULL);
1162     ok_ole_success(hr, IDispatch_Invoke);
1163
1164     ok(excepinfo.wCode == 0x0 && excepinfo.scode == S_OK,
1165        "EXCEPINFO differs from expected: wCode = 0x%x, scode = 0x%08x\n",
1166        excepinfo.wCode, excepinfo.scode);
1167
1168     ok(V_VT(&varresult) == VT_DISPATCH, "V_VT(&varresult) was %d instead of VT_DISPATCH\n", V_VT(&varresult));
1169     ok(!V_DISPATCH(&varresult), "V_DISPATCH(&varresult) should be NULL instead of %p\n", V_DISPATCH(&varresult));
1170     VariantClear(&varresult);
1171
1172     /* call Value with a VT_VARIANT|VT_BYREF type */
1173     V_VT(&vararg[0]) = VT_VARIANT|VT_BYREF;
1174     V_VARIANTREF(&vararg[0]) = &vararg[1];
1175     V_VT(&vararg[1]) = VT_I2;
1176     V_I2(&vararg[1]) = 1;
1177     dispparams.cNamedArgs = 0;
1178     dispparams.rgdispidNamedArgs = NULL;
1179     dispparams.cArgs = 1;
1180     dispparams.rgvarg = vararg;
1181     VariantInit(&varresult);
1182     hr = IDispatch_Invoke(pDispatch, DISPID_VALUE, &IID_NULL, LOCALE_NEUTRAL, DISPATCH_PROPERTYGET, &dispparams, &varresult, &excepinfo, NULL);
1183     ok_ole_success(hr, IDispatch_Invoke);
1184
1185     ok(excepinfo.wCode == 0x0 && excepinfo.scode == S_OK,
1186         "EXCEPINFO differs from expected: wCode = 0x%x, scode = 0x%08x\n",
1187         excepinfo.wCode, excepinfo.scode);
1188
1189     ok(V_VT(&varresult) == VT_I2, "V_VT(&varresult) was %d instead of VT_I2\n", V_VT(&varresult));
1190     ok(V_I2(&varresult) == 1234, "V_I2(&varresult) was %d instead of 1234\n", V_I2(&varresult));
1191     VariantClear(&varresult);
1192
1193     /* call Variant - exercises variant copying in ITypeInfo::Invoke and
1194      * handling of void return types */
1195     /* use a big type to ensure that the variant was properly copied into the
1196      * destination function's args */
1197     V_VT(&vararg[0]) = VT_CY;
1198     S(V_CY(&vararg[0])).Hi = 0xdababe;
1199     S(V_CY(&vararg[0])).Lo = 0xdeadbeef;
1200     dispparams.cNamedArgs = 0;
1201     dispparams.cArgs = 1;
1202     dispparams.rgdispidNamedArgs = NULL;
1203     dispparams.rgvarg = vararg;
1204     VariantInit(&varresult);
1205     hr = IDispatch_Invoke(pDispatch, DISPID_TM_VARIANT, &IID_NULL, LOCALE_NEUTRAL, DISPATCH_METHOD, &dispparams, NULL, NULL, NULL);
1206     ok_ole_success(hr, IDispatch_Invoke);
1207     VariantClear(&varresult);
1208
1209     /* call VarArg */
1210     VariantInit(&vararg[3]);
1211     V_VT(&vararg[3]) = VT_I4;
1212     V_I4(&vararg[3]) = 3;
1213     VariantInit(&vararg[2]);
1214     V_VT(&vararg[2]) = VT_I4;
1215     V_I4(&vararg[2]) = 0;
1216     VariantInit(&vararg[1]);
1217     V_VT(&vararg[1]) = VT_I4;
1218     V_I4(&vararg[1]) = 1;
1219     VariantInit(&vararg[0]);
1220     V_VT(&vararg[0]) = VT_I4;
1221     V_I4(&vararg[0]) = 2;
1222     dispparams.cNamedArgs = 0;
1223     dispparams.cArgs = 4;
1224     dispparams.rgdispidNamedArgs = NULL;
1225     dispparams.rgvarg = vararg;
1226     hr = IDispatch_Invoke(pDispatch, DISPID_TM_VARARG, &IID_NULL, LOCALE_NEUTRAL, DISPATCH_METHOD, &dispparams, NULL, NULL, NULL);
1227     ok_ole_success(hr, ITypeInfo_Invoke);
1228
1229     /* call VarArg, even one (non-optional, non-safearray) named argument is not allowed */
1230     dispidNamed = 0;
1231     dispparams.cNamedArgs = 1;
1232     dispparams.rgdispidNamedArgs = &dispidNamed;
1233     hr = IDispatch_Invoke(pDispatch, DISPID_TM_VARARG, &IID_NULL, LOCALE_NEUTRAL, DISPATCH_METHOD, &dispparams, NULL, NULL, NULL);
1234     ok(hr == DISP_E_NONAMEDARGS, "IDispatch_Invoke should have returned DISP_E_NONAMEDARGS instead of 0x%08x\n", hr);
1235     dispidNamed = DISPID_PROPERTYPUT;
1236
1237     /* call Error */
1238     dispparams.cNamedArgs = 0;
1239     dispparams.cArgs = 0;
1240     dispparams.rgdispidNamedArgs = NULL;
1241     dispparams.rgvarg = NULL;
1242     VariantInit(&varresult);
1243     hr = IDispatch_Invoke(pDispatch, DISPID_TM_ERROR, &IID_NULL, LOCALE_NEUTRAL, DISPATCH_METHOD, &dispparams, NULL, &excepinfo, NULL);
1244     ok(hr == DISP_E_EXCEPTION, "IDispatch_Invoke should have returned DISP_E_EXCEPTION instead of 0x%08x\n", hr);
1245     ok(excepinfo.wCode == 0x0 && excepinfo.scode == E_NOTIMPL,
1246         "EXCEPINFO differs from expected: wCode = 0x%x, scode = 0x%08x\n",
1247         excepinfo.wCode, excepinfo.scode);
1248     VariantClear(&varresult);
1249
1250     /* call BstrRet */
1251     pTypeInfo = NonOleAutomation_GetTypeInfo();
1252     dispparams.cNamedArgs = 0;
1253     dispparams.cArgs = 0;
1254     dispparams.rgdispidNamedArgs = NULL;
1255     dispparams.rgvarg = NULL;
1256     VariantInit(&varresult);
1257     hr = ITypeInfo_Invoke(pTypeInfo, &NonOleAutomation, DISPID_NOA_BSTRRET, DISPATCH_METHOD, &dispparams, &varresult, &excepinfo, NULL);
1258     ok_ole_success(hr, ITypeInfo_Invoke);
1259     ok(V_VT(&varresult) == VT_BSTR, "V_VT(&varresult) should be VT_BSTR instead of %d\n", V_VT(&varresult));
1260     ok(V_BSTR(&varresult) != NULL, "V_BSTR(&varresult) should not be NULL\n");
1261
1262     VariantClear(&varresult);
1263     ITypeInfo_Release(pTypeInfo);
1264
1265     /* tests call put_Name without named arg */
1266     VariantInit(&vararg[0]);
1267     dispparams.cNamedArgs = 0;
1268     dispparams.rgdispidNamedArgs = NULL;
1269     dispparams.cArgs = 1;
1270     dispparams.rgvarg = vararg;
1271     VariantInit(&varresult);
1272     hr = IDispatch_Invoke(pDispatch, DISPID_TM_NAME, &IID_NULL, LOCALE_NEUTRAL, DISPATCH_PROPERTYPUT, &dispparams, &varresult, &excepinfo, NULL);
1273     ok(hr == DISP_E_PARAMNOTFOUND, "IDispatch_Invoke should have returned DISP_E_PARAMNOTFOUND instead of 0x%08x\n", hr);
1274     VariantClear(&varresult);
1275
1276     /* tests param type that cannot be coerced */
1277     VariantInit(&vararg[0]);
1278     V_VT(&vararg[0]) = VT_UNKNOWN;
1279     V_UNKNOWN(&vararg[0]) = NULL;
1280     dispparams.cNamedArgs = 1;
1281     dispparams.rgdispidNamedArgs = &dispidNamed;
1282     dispparams.cArgs = 1;
1283     dispparams.rgvarg = vararg;
1284     VariantInit(&varresult);
1285 #if 0 /* NULL unknown not currently marshaled correctly */
1286     hr = IDispatch_Invoke(pDispatch, DISPID_TM_NAME, &IID_NULL, LOCALE_NEUTRAL, DISPATCH_PROPERTYPUT, &dispparams, &varresult, &excepinfo, NULL);
1287     ok(hr == DISP_E_TYPEMISMATCH, "IDispatch_Invoke should have returned DISP_E_TYPEMISMATCH instead of 0x%08x\n", hr);
1288 #endif
1289     VariantClear(&varresult);
1290
1291     /* tests bad param type */
1292     VariantInit(&vararg[0]);
1293     V_VT(&vararg[0]) = VT_CLSID;
1294     V_BYREF(&vararg[0]) = NULL;
1295     dispparams.cNamedArgs = 1;
1296     dispparams.rgdispidNamedArgs = &dispidNamed;
1297     dispparams.cArgs = 1;
1298     dispparams.rgvarg = vararg;
1299     VariantInit(&varresult);
1300     hr = IDispatch_Invoke(pDispatch, DISPID_TM_NAME, &IID_NULL, LOCALE_NEUTRAL, DISPATCH_PROPERTYPUT, &dispparams, &varresult, &excepinfo, NULL);
1301     ok(hr == DISP_E_BADVARTYPE, "IDispatch_Invoke should have returned DISP_E_BADVARTYPE instead of 0x%08x\n", hr);
1302     VariantClear(&varresult);
1303
1304     /* tests too small param count */
1305     dispparams.cNamedArgs = 0;
1306     dispparams.rgdispidNamedArgs = NULL;
1307     dispparams.cArgs = 0;
1308     dispparams.rgvarg = NULL;
1309     VariantInit(&varresult);
1310     hr = IDispatch_Invoke(pDispatch, DISPID_TM_DOSOMETHING, &IID_NULL, LOCALE_NEUTRAL, DISPATCH_METHOD, &dispparams, &varresult, &excepinfo, NULL);
1311     ok(hr == DISP_E_BADPARAMCOUNT, "IDispatch_Invoke should have returned DISP_E_BADPARAMCOUNT instead of 0x%08x\n", hr);
1312     VariantClear(&varresult);
1313
1314     /* tests propget function with large param count */
1315     VariantInit(&vararg[0]);
1316     V_VT(&vararg[0]) = VT_BSTR;
1317     V_BSTR(&vararg[0]) = NULL;
1318     V_VT(&vararg[1]) = VT_I4;
1319     V_I4(&vararg[1]) = 1;
1320     dispparams.cNamedArgs = 0;
1321     dispparams.cArgs = 2;
1322     dispparams.rgdispidNamedArgs = NULL;
1323     dispparams.rgvarg = vararg;
1324     hr = IDispatch_Invoke(pDispatch, DISPID_TM_STATE, &IID_NULL, LOCALE_NEUTRAL, DISPATCH_PROPERTYGET, &dispparams, &varresult, &excepinfo, NULL);
1325     ok(hr == DISP_E_NOTACOLLECTION, "IDispatch_Invoke should have returned DISP_E_NOTACOLLECTION instead of 0x%08x\n", hr);
1326
1327     IDispatch_Release(pDispatch);
1328     IWidget_Release(pWidget);
1329
1330     trace("calling end_host_object\n");
1331     end_host_object(tid, thread);
1332 }
1333
1334 static void test_DispCallFunc(void)
1335 {
1336     static const WCHAR szEmpty[] = { 0 };
1337     VARTYPE rgvt[] = { VT_R8, VT_BSTR, VT_BSTR, VT_VARIANT|VT_BYREF };
1338     VARIANTARG vararg[4];
1339     VARIANTARG varref;
1340     VARIANTARG *rgpvarg[4] = { &vararg[0], &vararg[1], &vararg[2], &vararg[3] };
1341     VARIANTARG varresult;
1342     HRESULT hr;
1343     IWidget *pWidget = Widget_Create();
1344     V_VT(&vararg[0]) = VT_R8;
1345     V_R8(&vararg[0]) = 3.141;
1346     V_VT(&vararg[1]) = VT_BSTR;
1347     V_BSTR(&vararg[1]) = SysAllocString(szEmpty);
1348     V_VT(&vararg[2]) = VT_BSTR;
1349     V_BSTR(&vararg[2]) = SysAllocString(szEmpty);
1350     V_VT(&vararg[3]) = VT_VARIANT|VT_BYREF;
1351     V_VARIANTREF(&vararg[3]) = &varref;
1352     V_VT(&varref) = VT_ERROR;
1353     V_ERROR(&varref) = DISP_E_PARAMNOTFOUND;
1354     VariantInit(&varresult);
1355     hr = DispCallFunc(pWidget, 36, CC_STDCALL, VT_UI4, 4, rgvt, rgpvarg, &varresult);
1356     ok_ole_success(hr, DispCallFunc);
1357     VariantClear(&varresult);
1358     VariantClear(&vararg[1]);
1359     VariantClear(&vararg[2]);
1360     IWidget_Release(pWidget);
1361 }
1362
1363 static void test_StaticWidget(void)
1364 {
1365     ITypeInfo *type_info;
1366     DISPPARAMS dispparams;
1367     VARIANTARG vararg[4];
1368     EXCEPINFO excepinfo;
1369     VARIANT varresult;
1370     HRESULT hr;
1371
1372     type_info = get_type_info(&IID_IStaticWidget);
1373
1374     /* call TestDual */
1375     dispparams.cNamedArgs = 0;
1376     dispparams.cArgs = 1;
1377     dispparams.rgdispidNamedArgs = NULL;
1378     dispparams.rgvarg = vararg;
1379     V_VT(vararg) = VT_DISPATCH;
1380     V_DISPATCH(vararg) = (IDispatch*)&TestDualDisp;
1381     VariantInit(&varresult);
1382     hr = ITypeInfo_Invoke(type_info, &StaticWidget, DISPID_TM_TESTDUAL, DISPATCH_METHOD,
1383             &dispparams, &varresult, &excepinfo, NULL);
1384     ok_ole_success(hr, IDispatch_Invoke);
1385     ok(V_VT(&varresult) == VT_EMPTY, "vt %x\n", V_VT(&varresult));
1386     VariantClear(&varresult);
1387
1388     ITypeInfo_Release(type_info);
1389 }
1390
1391 START_TEST(tmarshal)
1392 {
1393     HRESULT hr;
1394
1395     CoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
1396
1397     hr = register_current_module_typelib();
1398     ok_ole_success(hr, register_current_module_typelib);
1399
1400     test_typelibmarshal();
1401     test_DispCallFunc();
1402     test_StaticWidget();
1403
1404     hr = UnRegisterTypeLib(&LIBID_TestTypelib, 1, 0, LOCALE_NEUTRAL, 1);
1405     ok_ole_success(hr, UnRegisterTypeLib);
1406
1407     CoUninitialize();
1408 }