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